تست وب بلوتوث با Puppeteer

فرانسوا بوفور
François Beaufort

بلوتوث وب از Chrome 56 پشتیبانی می‌شود و به توسعه‌دهندگان اجازه می‌دهد برنامه‌های وب بنویسند که مستقیماً با دستگاه‌های بلوتوث کاربران صحبت می‌کنند. توانایی ویرایشگر وب Espruino برای آپلود کد روی دستگاه های بلوتوث سازگار یکی از این نمونه ها است. آزمایش این برنامه ها اکنون با Puppeteer امکان پذیر است.

این پست وبلاگ نحوه استفاده از Puppeteer برای کار و آزمایش یک برنامه وب دارای بلوتوث را توضیح می دهد. بخش کلیدی این توانایی Puppeteer برای کار با انتخابگر دستگاه بلوتوث کروم است.

اگر با استفاده از بلوتوث وب در کروم آشنا نیستید، ویدیوی زیر فرمان بلوتوث را در ویرایشگر وب Espruino نشان می‌دهد:

کاربر یک دستگاه بلوتوث Puck.js را در ویرایشگر وب Espruino انتخاب می کند.

برای دنبال کردن این پست وبلاگ، به یک برنامه وب دارای بلوتوث، یک دستگاه بلوتوث که بتواند با آن ارتباط برقرار کند و از Puppeteer نسخه 21.4.0 یا جدیدتر استفاده کند، نیاز دارید.

مرورگر را راه اندازی کنید

مانند اکثر اسکریپت های Puppeteer، با راه اندازی مرورگر با Puppeteer.launch() شروع کنید. برای دسترسی به ویژگی های بلوتوث، باید چند آرگومان اضافی ارائه دهید:

  • غیرفعال کردن حالت بدون سر: این بدان معناست که Puppeteer یک پنجره قابل مشاهده مرورگر کروم را برای اجرای آزمایش باز می کند. اگر ترجیح می دهید آن را بدون رابط کاربری اجرا کنید، از حالت هدلس جدید استفاده کنید. حالت بدون سرنشین قدیمی از نمایش درخواست‌های بلوتوث پشتیبانی نمی‌کند.
  • آرگومان‌های اضافی به Chromium: یک آرگومان «فعال کردن بلوتوث وب» را برای محیط‌های لینوکس ارسال کنید.
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() هستید بروید.

اعلان دستگاه بلوتوث را باز کنید

هنگامی که از Puppeteer برای باز کردن صفحه برنامه وب با Puppeteer استفاده کردید، می توانید برای خواندن داده ها به دستگاه بلوتوث متصل شوید. این مرحله بعدی فرض می‌کند که دکمه‌ای در برنامه وب خود دارید که برخی از جاوا اسکریپت را اجرا می‌کند، از جمله تماس با navigator.bluetooth.requestDevice() .

از Page.locator().click() برای فشار دادن آن دکمه و Page.waitForDevicePrompt() برای تشخیص زمانی که انتخابگر دستگاه بلوتوث ظاهر می شود استفاده کنید. قبل از کلیک کردن روی دکمه، باید waitForDevicePrompt() را فراخوانی کنید، در غیر این صورت، درخواست قبلاً باز شده است و قادر به شناسایی آن نخواهد بود.

از آنجایی که هر دوی این متدهای Puppeteer وعده‌ها را برمی‌گردانند، Promise.all() یک راه راحت برای فراخوانی آنها به ترتیب درست با هم است:

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

وعده ای که توسط waitForDevicePrompt() برگردانده می شود به یک شی DeviceRequestPrompt که در کنار آن برای انتخاب دستگاه بلوتوثی که می خواهید به آن متصل شوید، استفاده می کنید.

یک دستگاه را انتخاب کنید

از DeviceRequestPrompt.waitForDevice() و DeviceRequestPrompt.select() برای پیدا کردن و اتصال به دستگاه بلوتوث صحیح استفاده کنید.

DeviceRequestPrompt.waitForDevice() هر بار که Chrome دستگاه بلوتوثی را با اطلاعات اولیه در مورد دستگاه پیدا می کند، پاسخ تماس ارائه شده را فراخوانی می کند. اولین باری که callback true برمی‌گردد، 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();

برای آشنایی بیشتر با این توالی تماس‌های API، به برقراری ارتباط با دستگاه‌های بلوتوث از طریق جاوا اسکریپت مراجعه کنید.

در این مرحله، می‌دانید که چگونه از Puppeteer برای خودکار کردن استفاده از یک برنامه وب دارای بلوتوث با جایگزین کردن مرحله انسانی انتخاب یک دستگاه از منوی انتخابگر دستگاه بلوتوث استفاده کنید. در حالی که این ممکن است به طور کلی مفید باشد، به طور مستقیم برای نوشتن یک تست سرتاسر برای چنین برنامه وب قابل استفاده است.

یک تست ایجاد کنید

بخش گم شده از گرفتن کد تا کنون تا نوشتن یک تست کامل، دریافت اطلاعات از برنامه وب و به اسکریپت Puppeteer شما است. هنگامی که این مورد را دارید، استفاده از یک کتابخانه آزمایشی (مانند TAP یا موکا ) برای تأیید خواندن و گزارش صحیح داده ها بسیار ساده است.

یکی از ساده ترین راه ها برای انجام این کار، نوشتن داده ها در DOM است. جاوا اسکریپت راه های زیادی برای انجام این کار بدون کتابخانه های اضافی دارد. اگر به برنامه وب فرضی خود برگردید، ممکن است وقتی داده‌ها را از دستگاه بلوتوث می‌خواند یا داده‌های واقعی را در یک فیلد چاپ می‌کند، رنگ نشانگر وضعیت را تغییر دهد. به عنوان مثال:

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

از Puppeteer، Page.$eval() راهی را در اختیار شما قرار می دهد تا این داده ها را از DOM صفحه خارج کنید و به یک اسکریپت تست کنید. $eval() از همان منطق document.querySelector() برای یافتن یک عنصر استفاده می کند و سپس تابع callback ارائه شده را با آن عنصر به عنوان آرگومان اجرا می کند. هنگامی که این را به عنوان یک متغیر دارید، از کتابخانه ادعای خود استفاده کنید تا آزمایش کنید که آیا داده ها همان چیزی است که ما انتظار داریم.

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

منابع اضافی

برای مشاهده نمونه‌های پیچیده‌تر تست نوشتن برای برنامه‌های وب دارای بلوتوث با Puppeteer، به این مخزن مراجعه کنید: https://github.com/WebBluetoothCG/manual-tests/ . گروه وب بلوتوث جامعه این مجموعه آزمایشی را انجام می دهد که همه آنها می توانند از یک مرورگر یا به صورت محلی اجرا شوند. تست "ویژگی فقط خواندنی" بیشتر شبیه به نمونه استفاده شده در این پست وبلاگ است.

قدردانی

با تشکر از وینسنت شیب برای شروع این پروژه و ارائه بازخورد ارزشمند در مورد این پست.