Testa il Bluetooth web con Puppeteer

François Beaufort
François Beaufort

Web Bluetooth è supportato da Chrome 56 e consente agli sviluppatori di scrivere app web che comunicano direttamente con i dispositivi Bluetooth degli utenti. La capacità dell'editor web Esruino di caricare codice su dispositivi Bluetooth compatibili è un esempio di questo esempio. Ora è possibile testare queste applicazioni con Puppeteer.

Questo post del blog spiega come utilizzare Puppeteer per gestire e testare un'app web con Bluetooth. Il vantaggio principale è la capacità di Puppeteer di utilizzare il Selettore dispositivi Bluetooth di Chrome.

Se non hai dimestichezza con l'utilizzo di Web Bluetooth in Chrome, il seguente video mostra il prompt Bluetooth nell'editor web di Espruino:

L'utente seleziona un dispositivo Bluetooth Puck.js nell'editor web di Espruino.

Per seguire questo post del blog, ti serviranno un'app web abilitata per il Bluetooth, un dispositivo Bluetooth con cui possa comunicare e l'utilizzo di Puppeteer v21.4.0 o di una versione successiva.

Avvia il browser.

Come per la maggior parte degli script Puppeteer, inizia avviando il browser con Puppeteer.launch(). Per accedere alle funzionalità Bluetooth, devi fornire alcuni argomenti aggiuntivi:

import puppeteer from 'puppeteer';

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

Quando apri la prima pagina, in genere consigliamo di utilizzare un contesto del browser in incognito. In questo modo è possibile evitare fughe di autorizzazioni tra i test eseguiti con lo script (anche se alcuni stati condivisi a livello di sistema operativo non possono essere evitati da Puppeteer). Il seguente codice dimostra ciò:

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

Successivamente, potrai accedere all'URL dell'app web che stai testando con Page.goto().

Apri la richiesta del dispositivo Bluetooth

Dopo aver utilizzato Puppeteer per aprire la pagina dell'app web con Puppeteer, puoi connetterti al dispositivo Bluetooth per leggere i dati. Questo passaggio successivo presuppone che tu abbia un pulsante nell'app web che esegue codice JavaScript, inclusa una chiamata a navigator.bluetooth.requestDevice().

Usa Page.locator().click() per premere il pulsante e Page.waitForDevicePrompt() per riconoscere il momento in cui viene visualizzato il selettore dispositivo Bluetooth. Devi chiamare waitForDevicePrompt() prima di fare clic sul pulsante, altrimenti la richiesta si sarà già aperta e non sarà in grado di rilevarla.

Poiché entrambi i metodi di Puppeteer restituiscono promesse, Promise.all() è un modo pratico per chiamare insieme nell'ordine corretto:

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

La promessa restituita da waitForDevicePrompt() si risolve in un oggetto DeviceRequestPrompt che userai accanto al dispositivo Bluetooth a cui vuoi connetterti.

Seleziona un dispositivo

Usa DeviceRequestPrompt.waitForDevice() e DeviceRequestPrompt.select() per trovare e connettersi al dispositivo Bluetooth corretto.

DeviceRequestPrompt.waitForDevice() chiama il callback fornito ogni volta che Chrome trova un dispositivo Bluetooth con alcune informazioni di base sul dispositivo. La prima volta che il callback restituisce true, waitForDevice() risolve il problema DeviceRequestPromptDevice corrispondente. Passa il dispositivo a DeviceRequestPrompt.select() per selezionarlo e connetterlo al dispositivo Bluetooth.

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

Una volta risolto il problema di DeviceRequestPrompt.select(), Chrome viene connesso al dispositivo e la pagina web può accedervi.

Lettura dal dispositivo

A questo punto, la tua app web sarà connessa al dispositivo Bluetooth scelto e sarà in grado di leggerne le informazioni. Potrebbe avere il seguente aspetto:

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

Per una procedura dettagliata più approfondita di questa sequenza di chiamate API, consulta Comunicazione con dispositivi Bluetooth tramite JavaScript.

A questo punto, sai come utilizzare Puppeteer per automatizzare l'uso di un'app web abilitata per Bluetooth sostituendo il passaggio umano per la selezione di un dispositivo dal menu del selettore di dispositivi Bluetooth. Sebbene questo approccio possa essere utile in generale, è direttamente applicabile alla scrittura di un test end-to-end per tale app web.

Creare un test

La parte mancante dell'ultima fase della scrittura del codice per la scrittura di un test completo è ottenere informazioni dall'app web e inserendole nello script Puppeteer. Una volta ottenuto questo codice, è abbastanza semplice utilizzare una libreria di test (come TAP o mocha) per verificare che i dati letti e registrati siano corretti.

Uno dei modi più semplici per farlo è scrivere dati nel DOM. JavaScript offre molti modi per farlo senza librerie aggiuntive. Se torni all'ipotetica app web, il colore potrebbe cambiare il colore di un indicatore di stato quando legge i dati dal dispositivo Bluetooth o stampa i dati letterali in un campo. Ad esempio:

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

Da Puppeteer, Page.$eval() consente di estrarre questi dati dal DOM della pagina e inserirli in uno script di test. $eval() utilizza la stessa logica di document.querySelector() per trovare un elemento, quindi esegue la funzione di callback fornita con questo elemento come argomento. Dopo aver impostato questa variabile come variabile, utilizza la libreria di asserzioni per verificare se i dati sono quelli previsti.

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

Altre risorse

Per esempi più complessi di test di scrittura per app web abilitate per Bluetooth con Puppeteer, consulta questo repository: https://github.com/WebBluetoothCG/manual-tests/. Il Web Bluetooth Community Group gestisce questa suite di test, che possono essere eseguiti da un browser o localmente. Il test delle caratteristiche di sola lettura è più simile all'esempio utilizzato in questo post del blog.

Riconoscimenti

Ringraziamo Vincent Scheib per aver dato il via al progetto e per averci fornito un prezioso feedback su questo post.