Tester le Bluetooth Web avec Puppeteer

François Beaufort
François Beaufort

Le Bluetooth Web est compatible depuis Chrome 56 et permet aux développeurs de créer des applications Web qui communiquent directement avec les utilisateurs Appareils Bluetooth C'est le cas, par exemple, de la capacité de l'éditeur Web Espruino à importer du code sur des appareils Bluetooth compatibles. Il est désormais possible de tester ces applications avec Puppeteer.

Cet article de blog explique comment utiliser Puppeteer pour faire fonctionner et tester une application Web compatible Bluetooth. L'élément clé de cette approche est la capacité de Puppeteer à utiliser le sélecteur d'appareil Bluetooth de Chrome.

Si vous ne savez pas comment utiliser Web Bluetooth dans Chrome, la vidéo suivante présente l'invite Bluetooth dans l'éditeur Web Espruino:

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
L'utilisateur sélectionne un appareil Bluetooth Puck.js dans l'éditeur Web Espruino.

Pour suivre cet article de blog, vous aurez besoin d'une application Web sur laquelle le Bluetooth est activé, d'un appareil Bluetooth avec lequel elle peut communiquer, et de l'utilisation de Puppeteer v21.4.0 ou d'une version ultérieure.

Lancer le navigateur

Comme pour la plupart des scripts Puppeteer, commencez par lancer le navigateur avec Puppeteer.launch(). Pour accéder aux fonctionnalités Bluetooth, vous devez fournir quelques arguments supplémentaires:

  • Désactivez le mode headless: Puppeteer ouvre une fenêtre visible dans le navigateur Chrome pour exécuter le test. Utilisez le nouveau mode headless si vous préférez l'exécuter sans UI. L'ancien mode headless n'est pas compatible avec l'affichage d'invites Bluetooth.
  • Arguments supplémentaires pour Chromium: transmettre l'option "enable Web Bluetooth" l'argument pour les environnements Linux.
import puppeteer from 'puppeteer';

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

Lorsque vous ouvrez la première page, il est généralement recommandé d'utiliser un contexte de navigation privée. Cela permet d'éviter les fuites d'autorisations entre les tests exécutés avec votre script (bien que certains états partagés au niveau de l'OS ne puissent pas être empêchés par Puppeteer). Le code suivant illustre ce processus:

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

Vous pouvez ensuite accéder à l'URL de l'application Web que vous testez avec Page.goto().

Ouvrir l'invite de commande de l'appareil Bluetooth

Une fois que vous avez utilisé Puppeteer pour ouvrir la page de l'application Web avec Puppeteer, vous pouvez vous connecter à l'appareil Bluetooth pour lire les données. Pour cette étape, nous partons du principe que votre application Web comporte un bouton qui exécute du code JavaScript, y compris un appel à navigator.bluetooth.requestDevice().

Utilisez Page.locator().click() pour appuyer sur ce bouton, et Page.waitForDevicePrompt() pour reconnaître quand le sélecteur d'appareil Bluetooth s'affiche. Vous devez appeler waitForDevicePrompt() avant de cliquer sur le bouton, sinon l'invite sera déjà ouverte et ne pourra pas la détecter.

Étant donné que ces deux méthodes de Puppeteer renvoient des promesses, Promise.all() est un moyen pratique de les appeler dans le bon ordre:

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

La promesse renvoyée par waitForDevicePrompt() résout un objet DeviceRequestPrompt que vous utiliserez ensuite pour sélectionner l'appareil Bluetooth auquel vous souhaitez vous connecter.

Sélectionner un appareil

Utilisez DeviceRequestPrompt.waitForDevice() et DeviceRequestPrompt.select() pour trouver le bon appareil Bluetooth et vous y connecter.

DeviceRequestPrompt.waitForDevice() appelle le rappel fourni chaque fois que Chrome trouve un appareil Bluetooth avec des informations de base sur l'appareil. La première fois que le rappel renvoie la valeur "true", waitForDevice() renvoie l'élément DeviceRequestPromptDevice correspondant. Transmettez cet appareil à DeviceRequestPrompt.select() pour le sélectionner et vous y connecter.

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

Une fois DeviceRequestPrompt.select() résolu, Chrome se connecte à l'appareil, et la page Web peut y accéder.

Lire depuis l'appareil

À ce stade, votre application Web sera connectée à l'appareil Bluetooth choisi et pourra lire les informations qu'il contient. Voici un exemple:

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();

Pour une présentation plus détaillée de cette séquence d'appels d'API, consultez Communication avec des appareils Bluetooth via JavaScript.

À ce stade, vous savez comment utiliser Puppeteer pour automatiser l'utilisation d'une application Web compatible Bluetooth en remplaçant l'étape humaine consistant à sélectionner un appareil dans le menu de sélection des appareils Bluetooth. Bien que cela puisse être généralement utile, cela s'applique directement à l'écriture d'un test de bout en bout pour une telle application Web.

Créer un test

La partie manquante entre le code et l'écriture d'un test complet est d'extraire les informations de l'application Web et de les intégrer à votre script Puppeteer. Une fois que vous disposez de cette information, il est assez simple d'utiliser une bibliothèque de test (comme TAP ou mocha) pour vérifier que les bonnes données ont été lues et signalées.

Pour ce faire, l'une des méthodes les plus simples consiste à écrire des données dans le DOM. JavaScript propose de nombreuses méthodes pour effectuer cette opération sans bibliothèque supplémentaire. Pour en revenir à votre application Web fictive, il est possible qu'elle modifie la couleur d'un indicateur d'état lorsqu'elle lit des données à partir de l'appareil Bluetooth ou imprime les données littérales dans un champ. Exemple :

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

Dans Puppeteer, Page.$eval() vous permet d'extraire ces données du DOM de la page pour les intégrer à un script de test. $eval() utilise la même logique que document.querySelector() pour rechercher un élément, puis exécute la fonction de rappel fournie avec cet élément comme argument. Une fois que vous disposez de cette variable, utilisez votre bibliothèque d'assertions pour vérifier si les données sont celles que vous attendiez.

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

Ressources supplémentaires

Pour voir des exemples plus complexes d'écriture de tests pour les applications Web compatibles Bluetooth avec Puppeteer, consultez le dépôt suivant: https://github.com/WebBluetoothCG/manual-tests/. Le groupe de la communauté Web Bluetooth gère cette suite de tests, qui peuvent tous être exécutés depuis un navigateur ou localement. La caractéristique "Lecture seule" test est très semblable à l'exemple utilisé dans cet article de blog.

Remerciements

Merci à Vincent Scheib d'avoir lancé ce projet et de nous avoir fait part de ses précieux commentaires sur ce post.