Menguji penghentian pekerja layanan dengan Puppeteer

Panduan ini menjelaskan cara mem-build ekstensi yang lebih andal dengan menguji penghentian pekerja layanan menggunakan Puppeteer. Siap menangani penghentian kapan saja waktu adalah hal penting karena ini dapat terjadi tanpa peringatan yang mengakibatkan status non-persisten pekerja layanan hilang. Akibatnya, ekstensi harus menyimpan status penting dan dapat menangani permintaan segera setelah dimulai lagi ketika ada yang akan ditangani.

Sebelum memulai

Clone atau download repositori chrome-extensions-samples. Kita akan menggunakan ekstensi pengujian di /functional-samples/tutorial.terminate-sw/test-extension yang mengirim pesan ke pekerja layanan setiap kali tombol diklik dan menambahkan teks ke halaman apakah respons diterima.

Anda juga harus menginstal Node.JS yang merupakan runtime tempat Puppeteer dibuat.

Langkah 1: Mulai project Node.js Anda

Buat file berikut di direktori baru. Bersama-sama mereka membuat Project Node.js dan menyediakan struktur dasar rangkaian pengujian Puppeteer menggunakan Jest sebagai runner pengujian. Lihat Menguji Ekstensi Chrome dengan Puppeteer untuk mempelajari penyiapan ini secara lebih mendetail.

package.json:

{
  "name": "puppeteer-demo",
  "version": "1.0",
  "dependencies": {
    "jest": "^29.7.0",
    "puppeteer": "^22.1.0"
  },
  "scripts": {
    "start": "jest ."
  },
  "devDependencies": {
    "@jest/globals": "^29.7.0"
  }
}

index.test.js:

const puppeteer = require('puppeteer');

const SAMPLES_REPO_PATH = 'PATH_TO_SAMPLES_REPOSITORY';
const EXTENSION_PATH = `${SAMPLES_REPO_PATH}/functional-samples/tutorial.terminate-sw/test-extension`;
const EXTENSION_ID = 'gjgkofgpcmpfpggbgjgdfaaifcmoklbl';

let browser;

beforeEach(async () => {
  browser = await puppeteer.launch({
    // Set to 'new' to hide Chrome if running as part of an automated build.
    headless: false,
    args: [
      `--disable-extensions-except=${EXTENSION_PATH}`,
      `--load-extension=${EXTENSION_PATH}`
    ]
  });
});

afterEach(async () => {
  await browser.close();
  browser = undefined;
});

Perhatikan bahwa pengujian kita memuat test-extension dari repositori contoh. Pengendali untuk chrome.runtime.onMessage bergantung pada status yang ditetapkan dalam pengendali untuk peristiwa chrome.runtime.onInstalled. Akibatnya, konten data akan hilang ketika pekerja layanan dihentikan dan merespons permintaan pesan akan gagal. Kita akan memperbaikinya setelah menulis pengujian.

service-worker-broken.js:

let data;

chrome.runtime.onInstalled.addListener(() => {
  data = { version: chrome.runtime.getManifest().version };
});

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  sendResponse(data.version);
});

Langkah 2: Instal dependensi

Jalankan npm install untuk menginstal dependensi yang diperlukan.

Langkah 3: Tulis pengujian dasar

Tambahkan pengujian berikut ke bagian bawah index.test.js. Tindakan ini akan membuka pengujian dari ekstensi pengujian, mengklik elemen tombol, dan menunggu respons dari pekerja layanan.

test('can message service worker', async () => {
  const page = await browser.newPage();
  await page.goto(`chrome-extension://${EXTENSION_ID}/page.html`);

  // Message without terminating service worker
  await page.click('button');
  await page.waitForSelector('#response-0');
});

Anda dapat menjalankan pengujian dengan npm start dan akan melihat pengujian tersebut selesai memulai proyek.

Langkah 4: Hentikan pekerja layanan

Tambahkan fungsi bantuan berikut yang menghentikan pekerja layanan Anda:

/**
 * Stops the service worker associated with a given extension ID. This is done
 * by creating a new Chrome DevTools Protocol session, finding the target ID
 * associated with the worker and running the Target.closeTarget command.
 *
 * @param {Page} browser Browser instance
 * @param {string} extensionId Extension ID of worker to terminate
 */
async function stopServiceWorker(browser, extensionId) {
  const host = `chrome-extension://${extensionId}`;

  const target = await browser.waitForTarget((t) => {
    return t.type() === 'service_worker' && t.url().startsWith(host);
  });

  const worker = await target.worker();
  await worker.close();
}

Terakhir, update pengujian Anda dengan kode berikut. Sekarang, hentikan pekerja layanan dan klik tombol lagi untuk memeriksa apakah Anda menerima respons.

test('can message service worker when terminated', async () => {
  const page = await browser.newPage();
  await page.goto(`chrome-extension://${EXTENSION_ID}/page.html`);

  // Message without terminating service worker
  await page.click('button');
  await page.waitForSelector('#response-0');

  // Terminate service worker
  await stopServiceWorker(page, EXTENSION_ID);

  // Try to send another message
  await page.click('button');
  await page.waitForSelector('#response-1');
});

Langkah 5: Jalankan pengujian

Jalankan npm start. Pengujian Anda akan gagal, yang menunjukkan bahwa pekerja layanan tidak merespons setelah dihentikan.

Langkah 6: Perbaiki pekerja layanan

Selanjutnya, perbaiki pekerja layanan dengan menghilangkan ketergantungannya pada status sementara. Perbarui ekstensi pengujian untuk menggunakan kode berikut, yang disimpan di service-worker-fixed.js di repositori.

service-worker-fixed.js:

chrome.runtime.onInstalled.addListener(() => {
  chrome.storage.local.set({ version: chrome.runtime.getManifest().version });
});

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  chrome.storage.local.get('version').then((data) => {
    sendResponse(data.version);
  });
  return true;
});

Di sini, kita menyimpan versi ke chrome.storage.local, bukan variabel global untuk mempertahankan status di antara masa aktif pekerja layanan. Karena penyimpanan hanya dapat diakses secara asinkron, kami juga menampilkan true (benar) dari pemroses onMessage ke pastikan callback sendResponse tetap aktif.

Langkah 7: Jalankan lagi pengujian

Jalankan pengujian lagi dengan npm start. Setelah itu, seharusnya berhasil.

Langkah berikutnya

Sekarang Anda dapat menerapkan pendekatan yang sama ke ekstensi Anda sendiri. Pertimbangkan berikut ini:

  • Membuat paket pengujian agar dapat dijalankan dengan atau tanpa layanan tak terduga pemutusan hubungan kerja karyawan. Kemudian, Anda dapat menjalankan kedua mode satu per satu untuk memperjelas penyebab kegagalan.
  • Tulis kode untuk menghentikan pekerja layanan pada titik acak dalam pengujian. Ini bisa menjadi cara yang baik untuk menemukan masalah yang mungkin sulit diprediksi.
  • Belajarlah dari kegagalan uji dan coba buat kode secara defensif di masa mendatang. Sebagai misalnya, tambahkan aturan lint untuk mencegah penggunaan variabel global dan coba memindahkan data ke status yang lebih persisten.