בדיקת Bluetooth באינטרנט באמצעות Puppeteer

François Beaufort
François Beaufort

יש תמיכה ב-Bluetooth באינטרנט החל מגרסה 56 של Chrome, ומפתחים יכולים לכתוב אפליקציות אינטרנט שמדברים ישירות אל מכשירי ה-Bluetooth של המשתמשים. דוגמה לכך היא היכולת של עורך האינטרנט של Espruino להעלות קוד למכשירי Bluetooth תואמים. עכשיו אפשר לבדוק את האפליקציות האלה באמצעות Puppeteer.

בפוסט הזה נסביר איך משתמשים ב-Puppeteer כדי להפעיל ולבדוק אפליקציית אינטרנט שתומכת ב-Bluetooth. החלק העיקרי בכך הוא היכולת של Puppeteer להפעיל את הכלי לבחירת מכשירי Bluetooth ב-Chrome.

אם אתם לא יודעים איך להשתמש ב-Bluetooth באינטרנט ב-Chrome, בסרטון הבא מוצגת הנחיית ה-Bluetooth בעורך האינטרנט של Espruino:

המשתמש בוחר מכשיר Bluetooth מסוג Puck.js בעורך האינטרנט של Espruino.

כדי לבצע את ההוראות במאמר הזה, תצטרכו אפליקציית אינטרנט שתומכת ב-Bluetooth, מכשיר Bluetooth שאפשר לתקשר איתו ואת Puppeteer בגרסה v21.4.0 ואילך.

הפעלת הדפדפן

כמו ברוב הסקריפטים של Puppeteer, צריך להתחיל בהפעלת הדפדפן באמצעות Puppeteer.launch(). כדי לגשת לתכונות Bluetooth, צריך לספק כמה ארגומנטים נוספים:

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

לאחר מכן תוכלו לנווט לכתובת ה-URL של אפליקציית האינטרנט שאתם בודקים באמצעות Page.goto().

פתיחת ההנחיה לגבי מכשיר ה-Bluetooth

אחרי שמשתמשים ב-Puppeteer כדי לפתוח את הדף של אפליקציית האינטרנט באמצעות Puppeteer, אפשר להתחבר למכשיר ה-Bluetooth כדי לקרוא נתונים. השלב הבא מבוסס על ההנחה שיש באפליקציית האינטרנט לחצן שמריץ JavaScript, כולל קריאה ל-navigator.bluetooth.requestDevice().

משתמשים ב-Page.locator().click() כדי ללחוץ על הלחצן הזה, וב-Page.waitForDevicePrompt() כדי לזהות מתי חלונית הבחירה של מכשירי Bluetooth מופיעה. חובה לבצע את הקריאה ל-waitForDevicePrompt() לפני שלוחצים על הלחצן, אחרת ההנחיה כבר תופיע והיא לא תוכל לזהות אותה.

מכיוון ששתי השיטות האלה של Puppeteer מחזירות הבטחות (promises), אפשר להשתמש ב-Promise.all() כדי לקרוא להן יחד בסדר הנכון:

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

ההבטחה שמוחזרת על ידי waitForDevicePrompt() מתקבלת כאובייקט DeviceRequestPrompt, שבו תשתמשו בשלב הבא כדי לבחור את מכשיר ה-Bluetooth שאליו רוצים להתחבר.

בחירת מכשיר

משתמשים ב-DeviceRequestPrompt.waitForDevice() וב-DeviceRequestPrompt.select() כדי למצוא את מכשיר ה-Bluetooth הנכון ולהתחבר אליו.

DeviceRequestPrompt.waitForDevice() קורא ל-callback שסופק בכל פעם ש-Chrome מוצא מכשיר Bluetooth עם מידע בסיסי על המכשיר. בפעם הראשונה שהפונקציה הלא פוליגונמית מחזירה true, הערך של waitForDevice() מוגדר ל-DeviceRequestPromptDevice התואם. מעבירים את המכשיר הזה אל DeviceRequestPrompt.select() כדי לבחור בו ולהתחבר אל מכשיר ה-Bluetooth הזה.

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

אחרי שהבעיה ב-DeviceRequestPrompt.select() נפתרת, Chrome מחובר למכשיר ודף האינטרנט יכול לגשת אליו.

קריאה מהמכשיר

בשלב הזה, אפליקציית האינטרנט שלך תחובר למכשיר ה-Bluetooth שנבחר ותוכל לקרוא ממנו מידע. זה יכול להיראות כך:

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

הוראות מפורטות יותר לגבי רצף הקריאות ל-API מפורטות במאמר תקשורת עם מכשירי Bluetooth באמצעות JavaScript.

בשלב הזה, אתם יודעים איך להשתמש ב-Puppeteer כדי להפוך את השימוש ב-Bluetooth לאפליקציית אינטרנט שמופעלת ב-Bluetooth באופן אוטומטי, על ידי החלפת השלב האנושי של בחירת מכשיר מתפריט הבורר של מכשירי Bluetooth. האפשרות הזו שימושית באופן כללי, אבל היא רלוונטית ישירות לכתיבת בדיקה מקצה לקצה לאפליקציית אינטרנט כזו.

יצירת בדיקה

החלק החסר כדי לעבור מהקוד עד לכתיבת בדיקה מלאה הוא אחזור מידע מאפליקציית האינטרנט והעברתו לסקריפט של Puppeteer. אחרי שתעשו את זה, תוכלו להשתמש בספריית בדיקות (כמו TAP או mocha) כדי לוודא שהנתונים הנכונים נקראו ודווחו.

אחת הדרכים הקלות ביותר לעשות זאת היא לכתוב נתונים ב-DOM. ב-JavaScript יש הרבה דרכים לעשות זאת בלי ספריות נוספות. חזרה לאפליקציית האינטרנט ההיפותטית, היא עשויה לשנות את הצבע של מחוון סטטוס כשהיא קוראת נתונים ממכשיר ה-Bluetooth או להדפיס את הנתונים המילוליים בשדה. לדוגמה:

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

מ-Puppeteer, Page.$eval() מאפשר לשלוף את הנתונים האלה מה-DOM של הדף לתוך סקריפט בדיקה. $eval() משתמשת באותה לוגיקה כמו document.querySelector() כדי למצוא רכיב, ואז מפעילה את פונקציית הקריאה החוזרת שסופקה עם הרכיב הזה כארגומנט. אחרי שמגדירים את זה כמשתנה, משתמשים בספריית ההצהרות (assertions) כדי לבדוק אם הנתונים הם מה שציפיתם להם.

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

מקורות מידע נוספים

כדי לראות דוגמאות מורכבות יותר של בדיקות כתיבה לאפליקציות אינטרנט שתומכות ב-Bluetooth באמצעות Puppeteer, אפשר לעיין במאגר הזה: https://github.com/WebBluetoothCG/manual-tests/. קבוצת הקהילה של Web Bluetooth אחראית על חבילת הבדיקות הזו, שכל אחת מהן יכולה לפעול בדפדפן או באופן מקומי. הבדיקה 'מאפיין לקריאה בלבד' דומה ביותר לדוגמה שצוינה בפוסט הזה בבלוג.

אימות חתימות

תודה ל-Vincent Scheib על ההתחלה של הפרויקט הזה ועל המשוב החשוב שסיפק לגבי הפוסט הזה.