Puppeteer की मदद से वेब ब्लूटूथ की जांच करना

François Beaufort
François Beaufort

वेब ब्लूटूथ, Chrome 56 के बाद से ही काम कर रहा है. इससे डेवलपर ऐसे वेब ऐप्लिकेशन बना सकते हैं जो सीधे उपयोगकर्ताओं के ब्लूटूथ डिवाइसों से बात करते हैं. Espruino वेब एडिटर की ऐसी ब्लूटूथ डिवाइसों पर कोड अपलोड करना इसका एक उदाहरण है जिन पर यह सुविधा काम करती है. Puppeteer की मदद से अब इन ऐप्लिकेशन की जांच की जा सकती है.

इस ब्लॉग पोस्ट में ब्लूटूथ की सुविधा वाले वेब ऐप्लिकेशन को चलाने और उसकी जांच करने के लिए Puppeteer का इस्तेमाल करने का तरीका बताया गया है. इस ब्लॉग पोस्ट में, Chrome के ब्लूटूथ डिवाइस चुनने वाले टूल को चलाने के लिए Puppeteer की सुविधा की अहम जानकारी को शामिल किया गया है.

अगर आपको Chrome में वेब ब्लूटूथ इस्तेमाल करने के बारे में नहीं पता है, तो नीचे दिया गया वीडियो देखें. इसमें Espruino वेब एडिटर में ब्लूटूथ का अनुरोध दिखाया गया है:

उपयोगकर्ता, Espruino वेब एडिटर में एक Puck.js ब्लूटूथ डिवाइस चुनता है.

इस ब्लॉग पोस्ट को फ़ॉलो करने के लिए, आपको ब्लूटूथ की सुविधा वाला वेब ऐप्लिकेशन और एक ऐसा ब्लूटूथ डिवाइस चाहिए जिससे वह कम्यूनिकेट कर सके. साथ ही, आपको Puppeteer v21.4.0 या इसके बाद के वर्शन का इस्तेमाल करना होगा.

ब्राउज़र लॉन्च करें

ज़्यादातर Puppeteer स्क्रिप्ट की तरह, Puppeteer.launch() की मदद से ब्राउज़र लॉन्च करके शुरुआत करें. ब्लूटूथ सुविधाओं को ऐक्सेस करने के लिए, आपको कुछ अतिरिक्त तर्क देने होंगे:

import puppeteer from 'puppeteer';

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

हमारा सुझाव है कि पहला पेज खोलते समय गुप्त ब्राउज़र कॉन्टेक्स्ट का इस्तेमाल करें. यह आपकी स्क्रिप्ट के साथ चल रहे टेस्ट के बीच अनुमतियों को लीक होने से रोकने में मदद करता है (हालांकि, ओएस लेवल की कुछ शेयर की गई स्थिति होती है जिसे Puppeteer से नहीं रोका जा सकता). नीचे दिया गया कोड यह दिखाता है:

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

इसके बाद, उस वेब ऐप्लिकेशन के यूआरएल पर जाएं जिसकी टेस्टिंग Page.goto() पर की जा रही है.

ब्लूटूथ डिवाइस पर मिलने वाली सूचना को खोलें

Puppeteer की मदद से वेब ऐप्लिकेशन का पेज खोलने के लिए, Puppeteer का इस्तेमाल करने के बाद, डेटा पढ़ने के लिए ब्लूटूथ डिवाइस से कनेक्ट किया जा सकता है. अगले चरण में यह मान लिया जाता है कि आपके वेब ऐप्लिकेशन पर एक बटन है, जो navigator.bluetooth.requestDevice() को कॉल करने के साथ-साथ कुछ JavaScript चलाता है.

उस बटन को दबाने के लिए Page.locator().click() का इस्तेमाल करें. साथ ही, ब्लूटूथ डिवाइस चुनने का बटन दिखने पर Page.waitForDevicePrompt() का इस्तेमाल करें. बटन पर क्लिक करने से पहले आपको waitForDevicePrompt() को कॉल करना होगा, नहीं तो, प्रॉम्प्ट पहले ही खुल चुका होगा और वह इसका पता नहीं लगा सकेगा.

ये दोनों पपीटीयर तरीके वादों को दिखाते हैं. इसलिए, Promise.all() को सही क्रम में एक साथ कॉल करने का यह एक आसान तरीका है:

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

waitForDevicePrompt() से मिला प्रॉमिस DeviceRequestPrompt ऑब्जेक्ट में बदल जाता है. इसका इस्तेमाल उस ब्लूटूथ डिवाइस को चुनने के लिए किया जाएगा जिससे आपको कनेक्ट करना है.

कोई डिवाइस चुनें

सही ब्लूटूथ डिवाइस को खोजने और उससे कनेक्ट करने के लिए, DeviceRequestPrompt.waitForDevice() और DeviceRequestPrompt.select() का इस्तेमाल करें.

जब भी Chrome को कोई ब्लूटूथ डिवाइस मिलता है, तो DeviceRequestPrompt.waitForDevice() दिए गए कॉलबैक को कॉल करता है. इस डिवाइस में डिवाइस के बारे में कुछ बुनियादी जानकारी मौजूद होती है. जब कॉलबैक पहली बार 'सही' दिखाता है, तो waitForDevice(), मेल खाने वाले DeviceRequestPromptDevice से रिज़ॉल्व होता है. उस ब्लूटूथ डिवाइस को चुनने और उससे कनेक्ट करने के लिए, उस डिवाइस को DeviceRequestPrompt.select() से पास करें.

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

DeviceRequestPrompt.select() के ठीक हो जाने पर, Chrome को डिवाइस से कनेक्ट कर दिया जाता है और वेब पेज उसे ऐक्सेस कर सकता है.

डिवाइस से पढ़ें

इस समय, आपका वेब ऐप्लिकेशन चुने गए ब्लूटूथ डिवाइस से कनेक्ट हो जाएगा और उसमें मौजूद जानकारी पढ़ पाएगा. यह ऐसा दिख सकता है:

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

एपीआई कॉल के इस क्रम के बारे में कदम-दर-कदम निर्देश पाने के लिए, JavaScript पर ब्लूटूथ डिवाइसों से संपर्क करना लेख पढ़ें.

यहां, आपको पता है कि ब्लूटूथ डिवाइस चुनने वाले मेन्यू से डिवाइस चुनने वाले मानवीय चरण को बदलकर, ब्लूटूथ की सुविधा वाले वेब ऐप्लिकेशन के इस्तेमाल को ऑटोमेट करने के लिए Puppeteer का इस्तेमाल कैसे किया जाता है. यह तरीका आम तौर पर काम का हो सकता है, लेकिन ऐसे वेब ऐप्लिकेशन के लिए पूरी तरह से जांच (E2EE) करने पर सीधे तौर पर इसका इस्तेमाल किया जा सकता है.

टेस्ट बनाना

अब तक कोड लेने से लेकर टेस्ट लिखने तक, वेब ऐप्लिकेशन से जानकारी लेकर आपकी Puppeteer स्क्रिप्ट में जो जानकारी डाली जा रही है वह नहीं है. इसके बाद, टेस्टिंग लाइब्रेरी (जैसे कि TAP या मोका) का इस्तेमाल करना काफ़ी आसान है, ताकि यह पुष्टि की जा सके कि सही डेटा पढ़ा और रिपोर्ट किया गया था.

ऐसा करने का सबसे आसान तरीका, DOM में डेटा लिखना है. अतिरिक्त लाइब्रेरी के बिना, JavaScript में यह काम करने के कई तरीके हैं. अपने काल्पनिक वेब ऐप्लिकेशन पर वापस जाएं. जब यह ब्लूटूथ डिवाइस से डेटा को पढ़ता है या किसी फ़ील्ड में मौजूद शाब्दिक डेटा को प्रिंट करता है, तो यह स्थिति दिखाने वाले संकेत का रंग बदल सकता है. उदाहरण के लिए:

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

Puppeteer से, Page.$eval() आपको इस डेटा को पेज के DOM से बाहर और टेस्ट स्क्रिप्ट में लाने का तरीका बताता है. $eval() उसी लॉजिक का इस्तेमाल करता है जो document.querySelector() ने किसी एलिमेंट को खोजने के लिए किया है. इसके बाद, यह आर्ग्युमेंट के तौर पर उस एलिमेंट के साथ दिया गया कॉलबैक फ़ंक्शन चलाता है. इसे वैरिएबल के तौर पर इस्तेमाल करने के बाद, अपनी दावा लाइब्रेरी का इस्तेमाल करके यह पता लगाएं कि हमें उम्मीद के मुताबिक डेटा मिला है या नहीं.

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

ज़्यादा रिसॉर्स

Puppeteer और ब्लूटूथ की सुविधा वाले वेब ऐप्लिकेशन पर लिखने के मुश्किल उदाहरण देखने के लिए, यह रिपॉज़िटरी देखें: https://github.com/WebBluetoothCG/manual-tests/. वेब ब्लूटूथ कम्यूनिटी ग्रुप में जांच का यह सुइट शामिल होता है. इन सभी को किसी ब्राउज़र से या स्थानीय तौर पर चलाया जा सकता है. "रीड-ओनली वर्णिस्टिक" टेस्ट, इस ब्लॉग पोस्ट में इस्तेमाल किए गए उदाहरण से काफ़ी मिलता-जुलता है.

लोगों का आभार

इस प्रोजेक्ट को शुरू करने और इस पोस्ट पर ज़रूरी सुझाव देने के लिए, विंसेंट शीब को धन्यवाद.