O Web Bluetooth é compatível desde o Chrome 56 e permite que os desenvolvedores criem apps da Web que se comunicam diretamente com os dispositivos Bluetooth dos usuários. A capacidade do editor da Web Espruino de fazer upload de código para dispositivos Bluetooth compatíveis é um exemplo. Agora é possível testar esses aplicativos com o Puppeteer.
Esta postagem do blog mostra como usar o Puppeteer para operar e testar um aplicativo da Web habilitado para Bluetooth. A parte principal é a capacidade do Puppeteer de operar o seletor de dispositivos Bluetooth do Chrome.
Se você não sabe usar o Web Bluetooth no Chrome, o vídeo a seguir mostra a solicitação de Bluetooth no editor da Web Espruino:
Para acompanhar esta postagem do blog, você precisará de um app da Web com Bluetooth ativado, de um dispositivo Bluetooth com o qual possa se comunicar e usar o Puppeteer v21.4.0 ou posterior.
Inicie o navegador
Como na maioria dos scripts Puppeteer, comece iniciando o navegador com Puppeteer.launch()
. Para acessar os recursos do Bluetooth, é necessário fornecer alguns argumentos extras:
- Desativar o modo headless: isso significa que o Puppeteer abrirá uma janela visível do navegador Chrome para executar o teste. Use o novo modo headless se você preferir executá-lo sem interface. O modo headless legado não é compatível com a exibição de solicitações por Bluetooth.
- Argumentos adicionais para o Chromium: transmita um argumento"enable Web Bluetooth" para ambientes Linux.
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({
headless: false,
args: ["--enable-features=WebBluetooth"],
});
Ao abrir a primeira página, geralmente é recomendável usar um contexto de navegador anônimo. Isso ajuda a evitar o vazamento de permissões entre os testes executados com o script (embora haja algum estado compartilhado no nível do SO que não pode ser impedido pelo Puppeteer). O código a seguir demonstra isso:
const browserContext = await browser.createIncognitoBrowserContext();
const page = await browserContext.newPage();
Em seguida, navegue até o URL do app da Web que você está testando com Page.goto()
.
Abrir a solicitação do dispositivo Bluetooth
Depois de usar o Puppeteer para abrir a página do aplicativo da Web com ele, conecte-se ao dispositivo Bluetooth para ler dados. Esta próxima etapa pressupõe que você tenha um botão no seu app da Web que executa JavaScript, incluindo uma chamada para navigator.bluetooth.requestDevice()
.
Use Page.locator().click()
para pressionar esse botão e Page.waitForDevicePrompt()
para reconhecer quando o seletor de dispositivo Bluetooth aparece. É necessário chamar waitForDevicePrompt()
antes de clicar no botão. Caso contrário, a solicitação já terá sido aberta e não será possível detectá-la.
Como esses dois métodos do Puppeteer retornam promessas, Promise.all()
é uma maneira conveniente de chamá-los na ordem correta juntos:
const [devicePrompt] = await Promise.all([
page.waitForDevicePrompt(),
page.locator("#start-test-button").click(),
]);
A promessa retornada por waitForDevicePrompt()
é resolvida em um objeto DeviceRequestPrompt
, que você vai usar ao lado para selecionar o dispositivo Bluetooth a que você quer se conectar.
Selecionar um dispositivo
Use DeviceRequestPrompt.waitForDevice()
e DeviceRequestPrompt.select()
para encontrar e se conectar ao dispositivo Bluetooth correto.
DeviceRequestPrompt.waitForDevice()
chama o callback fornecido toda vez que o Chrome encontra um dispositivo Bluetooth com algumas informações básicas sobre o dispositivo. Na primeira vez que o callback retornar "true", waitForDevice()
será resolvido como DeviceRequestPromptDevice
correspondente. Transmita esse dispositivo para o DeviceRequestPrompt.select()
para selecionar e se conectar a ele.
const bluetoothDevice = await devicePrompt.waitForDevice(
(d) => d.name == wantedDeviceName,
);
await devicePrompt.select(bluetoothDevice);
Assim que DeviceRequestPrompt.select()
for resolvido, o Chrome será conectado ao dispositivo e a página da Web poderá acessá-lo.
Ler a partir do dispositivo
Nesse momento, seu aplicativo da Web estará conectado ao dispositivo Bluetooth escolhido e poderá ler informações a partir dele. O resultado será algo como o seguinte:
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();
Para mais detalhes sobre essa sequência de chamadas de API, consulte Como se comunicar com dispositivos Bluetooth em JavaScript.
Neste ponto, você sabe como usar o Puppeteer para automatizar o uso de um aplicativo da Web habilitado para Bluetooth, substituindo a etapa humana de selecionar um dispositivo no menu do seletor de dispositivo Bluetooth. Embora isso possa ser útil em geral, é diretamente aplicável à criação de um teste completo para esse aplicativo da Web.
Criar um teste
O que falta desde levar o código até aqui até escrever um teste completo é extrair informações do app da Web para o script do Puppeteer. Depois disso, é bastante simples usar uma biblioteca de testes (como TAP ou mocha) para verificar se os dados corretos foram lidos e informados.
Uma das maneiras mais fáceis de fazer isso é gravar dados no DOM. O JavaScript tem muitas maneiras de fazer isso sem bibliotecas adicionais. Voltando ao aplicativo da Web hipotético, ele pode mudar a cor de um indicador de status ao ler dados do dispositivo Bluetooth ou imprimir os dados literais em um campo. Exemplo:
const dataDisplayElement = document.querySelector('#data-display');
dataDisplayElement.innerText = dataView.getUint8();
No Puppeteer, o Page.$eval()
oferece uma maneira de extrair esses dados do DOM da página para um script de teste. $eval()
usa a mesma lógica de document.querySelector()
para encontrar um elemento e, em seguida, executa a função de callback fornecida com esse elemento como o argumento. Depois de definir isso como uma variável, use sua biblioteca de declarações para testar se os dados são o esperado.
const dataText = await page.$eval('#data-display', (el) => el.innerText);
equal(17, dataText);
Outros recursos
Para ver exemplos mais complexos de criação de testes para apps da Web ativados por Bluetooth com o Puppeteer, consulte este repositório: https://github.com/WebBluetoothCG/manual-tests/ (link em inglês). O Grupo da comunidade Web Bluetooth mantém esse conjunto de testes, que podem ser executados em um navegador ou localmente. O teste"Característica somente leitura" é mais parecido com o exemplo usado nesta postagem do blog.
Agradecimentos
Agradecemos a Vincent Scheib por iniciar este projeto e fornecer comentários valiosos sobre esta postagem.