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

François Beaufort
François Beaufort

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

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

אם אתם לא יודעים איך משתמשים ב-Web 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. האפשרות הזו שימושית באופן כללי, אבל היא רלוונטית ישירות לכתיבת בדיקה מקצה לקצה לאפליקציית אינטרנט כזו.

יצירת בדיקה

החלק החסר כדי לעבור מהקוד עד לכתיבת בדיקה מלאה הוא אחזור מידע מאפליקציית האינטרנט והעברתו לסקריפט של 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 על ההתחלה של הפרויקט הזה ועל המשוב החשוב שסיפק לגבי הפוסט הזה.