Kiểm thử Bluetooth cho web bằng Puppeteer

François Beaufort
François Beaufort

Bluetooth trên web được hỗ trợ kể từ Chrome 56 và cho phép nhà phát triển viết các ứng dụng web giao tiếp trực tiếp với thiết bị Bluetooth của người dùng. Khả năng trình chỉnh sửa web Espruino tải mã lên các thiết bị Bluetooth tương thích là một ví dụ như vậy. Giờ đây, bạn có thể kiểm thử các ứng dụng này bằng Puppeteer.

Bài đăng trên blog này hướng dẫn cách sử dụng Puppeteer để vận hành và kiểm thử một ứng dụng web hỗ trợ Bluetooth. Phần quan trọng của việc này là khả năng của Puppeteer trong việc vận hành bộ chọn thiết bị Bluetooth của Chrome.

Nếu bạn chưa quen với việc sử dụng Web Bluetooth trong Chrome, video sau đây sẽ cho thấy lời nhắc Bluetooth trong trình chỉnh sửa web Espruino:

Người dùng chọn một thiết bị bluetooth Puck.js trong trình chỉnh sửa web Espruino.

Để làm theo bài đăng trên blog này, bạn cần có một ứng dụng web hỗ trợ Bluetooth, một thiết bị Bluetooth có thể giao tiếp với ứng dụng đó và đang sử dụng Puppeteer v21.4.0 trở lên.

Chạy trình duyệt

Giống như hầu hết các tập lệnh Puppeteer, hãy bắt đầu bằng cách chạy trình duyệt bằng Puppeteer.launch(). Để truy cập vào các tính năng Bluetooth, bạn cần cung cấp thêm một số đối số:

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch({
  headless: false,
  args: ["--enable-features=WebBluetooth"],
});

Khi mở trang đầu tiên, bạn nên sử dụng ngữ cảnh trình duyệt ẩn danh. Điều này giúp ngăn chặn việc rò rỉ quyền giữa các chương trình kiểm thử chạy bằng tập lệnh của bạn (mặc dù có một số trạng thái dùng chung cấp hệ điều hành mà Puppeteer không thể ngăn chặn). Mã sau đây minh hoạ việc này:

const browserContext = await browser.createIncognitoBrowserContext();
const page = await browserContext.newPage();

Sau đó, bạn có thể chuyển đến URL của ứng dụng web mà bạn đang kiểm thử bằng Page.goto().

Mở lời nhắc thiết bị Bluetooth

Sau khi sử dụng Puppeteer để mở trang của ứng dụng web bằng Puppeteer, bạn có thể kết nối với thiết bị Bluetooth để đọc dữ liệu. Bước tiếp theo này giả định rằng bạn có một nút trên ứng dụng web chạy một số JavaScript, bao gồm cả lệnh gọi đến navigator.bluetooth.requestDevice().

Sử dụng Page.locator().click() để nhấn nút đó và Page.waitForDevicePrompt() để nhận biết thời điểm trình chọn thiết bị Bluetooth xuất hiện. Bạn phải gọi waitForDevicePrompt() trước khi nhấp vào nút, nếu không, lời nhắc sẽ mở ra và không thể phát hiện được.

Vì cả hai phương thức Puppeteer này đều trả về các lời hứa, nên Promise.all() là một cách thuận tiện để gọi các phương thức đó theo đúng thứ tự:

const [devicePrompt] = await Promise.all([
  page.waitForDevicePrompt(),
  page.locator("#start-test-button").click(),
]);

Lời hứa do waitForDevicePrompt() trả về sẽ phân giải thành đối tượng DeviceRequestPrompt mà bạn sẽ sử dụng tiếp theo để chọn thiết bị Bluetooth mà bạn muốn kết nối.

Chọn thiết bị

Sử dụng DeviceRequestPrompt.waitForDevice()DeviceRequestPrompt.select() để tìm và kết nối với thiết bị Bluetooth phù hợp.

DeviceRequestPrompt.waitForDevice() gọi lệnh gọi lại đã cung cấp mỗi khi Chrome tìm thấy thiết bị Bluetooth có một số thông tin cơ bản về thiết bị. Trong lần đầu tiên lệnh gọi lại trả về true, waitForDevice() sẽ phân giải thành DeviceRequestPromptDevice đã so khớp. Truyền thiết bị đó cho DeviceRequestPrompt.select() để chọn và kết nối với thiết bị Bluetooth đó.

const bluetoothDevice = await devicePrompt.waitForDevice(
  (d) => d.name == wantedDeviceName,
);
await devicePrompt.select(bluetoothDevice);

Sau khi giải quyết xong DeviceRequestPrompt.select(), Chrome sẽ được kết nối với thiết bị và trang web sẽ có thể truy cập vào thiết bị đó.

Đọc từ thiết bị

Tại thời điểm này, ứng dụng web của bạn sẽ được kết nối với thiết bị Bluetooth đã chọn và có thể đọc thông tin từ thiết bị đó. Mã có thể như sau:

const serviceId = "6e400001-b5a3-f393-e0a9-e50e24dcca9e";

const device = await navigator.bluetooth.requestDevice({
  filters: [{ services: [serviceId] }],
});
const gattServer = await device.gatt.connect();
const service = await gattServer.getPrimaryService(serviceId);
const characteristic = await service.getCharacteristic(
  "0b30afd0-193e-11eb-adc1-0242ac120002",
);
const dataView = await characteristic.readValue();

Để biết hướng dẫn chi tiết hơn về trình tự các lệnh gọi API này, hãy xem phần Giao tiếp với thiết bị Bluetooth qua JavaScript.

Tại thời điểm này, bạn đã biết cách sử dụng Puppeteer để tự động hoá việc sử dụng ứng dụng web hỗ trợ Bluetooth bằng cách thay thế bước chọn thiết bị của con người trong trình đơn bộ chọn thiết bị Bluetooth. Mặc dù cách này thường hữu ích, nhưng bạn có thể áp dụng trực tiếp cách này để viết mã kiểm thử toàn diện cho một ứng dụng web như vậy.

Tạo kiểm thử

Phần còn thiếu từ việc lấy mã cho đến nay để viết một chương trình kiểm thử đầy đủ là lấy thông tin từ ứng dụng web và đưa vào tập lệnh Puppeteer. Sau khi có dữ liệu này, bạn có thể dễ dàng sử dụng thư viện kiểm thử (như TAP hoặc mocha) để xác minh rằng dữ liệu đã được đọc và báo cáo chính xác.

Một trong những cách dễ nhất để thực hiện việc này là ghi dữ liệu vào DOM. JavaScript có nhiều cách để thực hiện việc này mà không cần thêm thư viện. Quay lại ứng dụng web giả định của bạn, ứng dụng này có thể thay đổi màu của chỉ báo trạng thái khi đọc dữ liệu từ thiết bị Bluetooth hoặc in dữ liệu cố định trong một trường. Ví dụ:

const dataDisplayElement = document.querySelector('#data-display');
dataDisplayElement.innerText = dataView.getUint8();

Trong Puppeteer, Page.$eval() cung cấp cho bạn một cách để lấy dữ liệu này ra khỏi DOM của trang và đưa vào tập lệnh kiểm thử. $eval() sử dụng cùng một logic như document.querySelector() để tìm một phần tử, sau đó chạy hàm gọi lại được cung cấp với phần tử đó làm đối số. Sau khi bạn có biến này, hãy sử dụng thư viện xác nhận để kiểm tra xem dữ liệu có đúng như mong đợi hay không.

const dataText = await page.$eval('#data-display', (el) => el.innerText);
equal(17, dataText);

Tài nguyên khác

Để xem các ví dụ phức tạp hơn về cách viết mã kiểm thử cho ứng dụng web hỗ trợ Bluetooth bằng Puppeteer, hãy xem kho lưu trữ này: https://github.com/WebBluetoothCG/manual-tests/. Nhóm cộng đồng Web Bluetooth duy trì bộ kiểm thử này, tất cả các bộ kiểm thử này đều có thể chạy từ trình duyệt hoặc trên máy. Kiểm thử"Thuộc tính chỉ có thể đọc" tương tự nhất với ví dụ được dùng trong bài đăng trên blog này.

Thư cảm ơn

Cảm ơn Vincent Scheib đã khởi động dự án này và đưa ra ý kiến phản hồi có giá trị về bài đăng này.