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

François Beaufort
François Beaufort

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

בפוסט הזה בבלוג אנחנו מסבירים איך להשתמש ב-Puppeteer כדי לתפעל ולבדוק אפליקציית אינטרנט שתומכת ב-Bluetooth. החלק העיקרי הזה הוא היכולת של Puppeteer להפעיל את ה-Bluetooth Device Chooser של 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 מחזירות הבטחות, 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() כדי למצוא רכיב, ולאחר מכן מפעילה את פונקציית הקריאה החוזרת שסופקה עם הרכיב הזה בתור הארגומנט. אחרי שמגדירים את המשתנה, משתמשים בספריית טענת נכוֹנוּת (assertion) כדי לבדוק אם הנתונים מתאימים לציפיות שלנו.

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

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

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

אימות חתימות

תודה לווינסנט שייב שהתחיל את הפרויקט וסיפק משוב מועיל בפוסט הזה.