Web Bluetooth wird seit Chrome 56 unterstützt und ermöglicht es Entwicklern, Webanwendungen zu erstellen, die direkt mit den Bluetooth-Geräten der Nutzer kommunizieren. Ein Beispiel dafür ist die Möglichkeit des Espruino-Webeditors, Code auf kompatible Bluetooth-Geräte hochzuladen. Mit Puppeteer ist es jetzt möglich, diese Anwendungen zu testen.
In diesem Blog-Beitrag erfahren Sie, wie Sie Puppeteer verwenden, um eine Bluetooth-fähige Webanwendung zu bedienen und zu testen. Der wichtigste Teil davon ist die Fähigkeit von Puppeteer, die Bluetooth-Geräteauswahl von Chrome zu bedienen.
Wenn Sie mit der Verwendung von Web Bluetooth in Chrome nicht vertraut sind, sehen Sie sich das folgende Video zur Bluetooth-Aufforderung im Espruino-Webeditor an:
Um diesem Blogpost zu folgen, benötigen Sie eine Bluetooth-fähige Web-App und ein Bluetooth-Gerät, mit dem die App kommunizieren kann. Außerdem benötigen Sie Puppeteer v21.4.0 oder höher.
Browser starten
Wie bei den meisten Puppeteer-Scripts starten Sie zuerst den Browser mit Puppeteer.launch()
. Wenn Sie auf Bluetooth-Funktionen zugreifen möchten, müssen Sie einige zusätzliche Argumente angeben:
- Monitorlosen Modus deaktivieren: Dies bedeutet, dass Puppeteer ein sichtbares Chrome-Browserfenster öffnet, um den Test auszuführen. Verwenden Sie den neuen headless-Modus, wenn Sie ihn ohne Benutzeroberfläche ausführen möchten. Im alten monitorlosen Modus werden keine Bluetooth-Aufforderungen unterstützt.
- Zusätzliche Argumente für Chromium: Geben Sie für Linux-Umgebungen das Argument „enable Web Bluetooth“ an.
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({
headless: false,
args: ["--enable-features=WebBluetooth"],
});
Beim Öffnen der ersten Seite wird in der Regel empfohlen, einen Inkognitobrowser-Kontext zu verwenden. So wird verhindert, dass Berechtigungen zwischen den mit Ihrem Script ausgeführten Tests weitergegeben werden. Es gibt jedoch einen gemeinsamen Zustand auf Betriebssystemebene, der von Puppeteer nicht verhindert werden kann. Das wird im folgenden Code veranschaulicht:
const browserContext = await browser.createIncognitoBrowserContext();
const page = await browserContext.newPage();
Sie können dann mit Page.goto()
die URL der Webanwendung aufrufen, die Sie testen.
Aufforderung für das Bluetooth-Gerät öffnen
Sobald Sie Puppeteer verwendet haben, um die Seite der Webanwendung mit Puppeteer zu öffnen, können Sie eine Verbindung zum Bluetooth-Gerät herstellen, um Daten zu lesen. Für den nächsten Schritt wird davon ausgegangen, dass Sie in Ihrer Webanwendung eine Schaltfläche haben, die JavaScript ausführt, einschließlich eines Aufrufs von navigator.bluetooth.requestDevice()
.
Verwenden Sie Page.locator().click()
, um diese Schaltfläche zu drücken, und Page.waitForDevicePrompt()
, um zu erkennen, wann die Auswahl der Bluetooth-Geräte angezeigt wird. Sie müssen waitForDevicePrompt()
anrufen, bevor Sie auf die Schaltfläche klicken. Andernfalls wird der Prompt bereits geöffnet und kann nicht erkannt werden.
Da beide Puppeteer-Methoden Versprechen zurückgeben, ist Promise.all()
eine praktische Möglichkeit, sie in der richtigen Reihenfolge zusammen aufzurufen:
const [devicePrompt] = await Promise.all([
page.waitForDevicePrompt(),
page.locator("#start-test-button").click(),
]);
Das von waitForDevicePrompt()
zurückgegebene Versprechen wird in ein DeviceRequestPrompt
-Objekt aufgelöst, mit dem du als Nächstes das Bluetooth-Gerät auswählst, mit dem du eine Verbindung herstellen möchtest.
Gerät auswählen
Verwenden Sie DeviceRequestPrompt.waitForDevice()
und DeviceRequestPrompt.select()
, um das richtige Bluetooth-Gerät zu finden und eine Verbindung herzustellen.
DeviceRequestPrompt.waitForDevice()
ruft den angegebenen Rückruf jedes Mal auf, wenn Chrome ein Bluetooth-Gerät mit einigen grundlegenden Informationen zum Gerät findet. Wenn der Callback zum ersten Mal „true“ zurückgibt, wird waitForDevice()
auf den übereinstimmenden DeviceRequestPromptDevice
-Wert festgelegt. Gib das Gerät an DeviceRequestPrompt.select()
weiter, um es auszuwählen und eine Verbindung zu diesem Bluetooth-Gerät herzustellen.
const bluetoothDevice = await devicePrompt.waitForDevice(
(d) => d.name == wantedDeviceName,
);
await devicePrompt.select(bluetoothDevice);
Sobald DeviceRequestPrompt.select()
aufgelöst ist, ist Chrome mit dem Gerät verbunden und die Webseite kann darauf zugreifen.
Vom Gerät lesen
Jetzt ist Ihre Web-App mit dem ausgewählten Bluetooth-Gerät verbunden und kann auf diesem Gerät Informationen lesen. Das könnte so aussehen:
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();
Eine ausführlichere Anleitung zu dieser Abfolge von API-Aufrufen finden Sie unter Mit Bluetooth-Geräten über JavaScript kommunizieren.
Jetzt wissen Sie, wie Sie Puppeteer verwenden können, um die Verwendung einer Bluetooth-fähigen Webanwendung zu automatisieren, indem der manuelle Schritt der Auswahl eines Geräts aus dem Bluetooth-Geräteauswahlmenü ersetzt wird. Das ist zwar allgemein nützlich, aber es kann direkt auf das Schreiben eines End-to-End-Tests für eine solche Webanwendung angewendet werden.
Test erstellen
Das fehlende Stück, um den Code zu einem vollständigen Test zu machen, ist die Übertragung von Informationen aus der Webanwendung in Ihr Puppeteer-Script. Sobald Sie das haben, können Sie mit einer Testbibliothek wie TAP oder mocha ganz einfach prüfen, ob die richtigen Daten gelesen und erfasst wurden.
Eine der einfachsten Möglichkeiten dazu besteht darin, Daten in das DOM zu schreiben. JavaScript bietet hierfür zahlreiche Möglichkeiten ohne zusätzliche Bibliotheken. Zurück zu Ihrer hypothetischen Webanwendung: Diese könnte die Farbe einer Statusanzeige ändern, wenn sie Daten vom Bluetooth-Gerät liest, oder die Daten in einem Feld ausdrucken. Beispiel:
const dataDisplayElement = document.querySelector('#data-display');
dataDisplayElement.innerText = dataView.getUint8();
Mit Page.$eval()
in Puppeteer können Sie diese Daten aus dem DOM der Seite in ein Testscript einfügen. $eval()
verwendet dieselbe Logik wie document.querySelector()
, um ein Element zu finden, und führt dann die angegebene Rückruffunktion mit diesem Element als Argument aus. Sobald Sie dies als Variable haben, verwenden Sie Ihre Assertion-Bibliothek, um zu testen, ob die Daten unseren Erwartungen entsprechen.
const dataText = await page.$eval('#data-display', (el) => el.innerText);
equal(17, dataText);
Zusätzliche Ressourcen
Komplexere Beispiele zum Schreiben von Tests für Bluetooth-kompatible Web-Apps mit Puppeteer finden Sie in diesem Repository: https://github.com/WebBluetoothCG/manual-tests/. Die Web Bluetooth Community Group verwaltet diese Testsuite, die alle über einen Browser oder lokal ausgeführt werden kann. Der Test "Read-only Characteristic" ist dem Beispiel in diesem Blogpost am ähnlichsten.
Danksagung
Vielen Dank an Vincent Scheib, der dieses Projekt ins Leben gerufen und wertvolles Feedback zu diesem Beitrag gegeben hat.