Panduan ini menjelaskan cara membuat ekstensi yang lebih andal dengan menguji penghentian service worker menggunakan Puppeteer. Penting untuk bersiap menangani penghentian kapan saja karena hal ini dapat terjadi tanpa peringatan sehingga menyebabkan hilangnya status non-persisten di service worker. Oleh karena itu, ekstensi harus menyimpan status penting dan dapat menangani permintaan segera setelah dimulai kembali saat ada peristiwa yang harus ditangani.
Sebelum memulai
Lakukan clone atau download repositori chrome-extensions-samples.
Kita akan menggunakan ekstensi pengujian di
/functional-samples/tutorial.terminate-sw/test-extension yang mengirim pesan
ke service worker setiap kali tombol diklik dan menambahkan teks ke halaman
jika respons diterima.
Anda juga perlu menginstal Node.JS yang merupakan runtime tempat Puppeteer dibangun.
Langkah 1: Mulai project Node.js Anda
Buat file berikut di direktori baru. Bersama-sama, keduanya akan membuat project Node.js baru 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": "^24.8.1"
},
"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,
pipe: true,
enableExtensions: [EXTENSION_PATH]
});
});
afterEach(async () => {
await browser.close();
browser = undefined;
});
Perhatikan bahwa pengujian kita memuat test-extension dari repositori contoh.
Handler untuk browser.runtime.onMessage bergantung pada status yang ditetapkan di handler
untuk peristiwa browser.runtime.onInstalled. Akibatnya, konten data akan hilang saat service worker dihentikan dan merespons pesan di masa mendatang akan gagal. Kita akan memperbaikinya setelah menulis pengujian.
service-worker-broken.js:
let data;
browser.runtime.onInstalled.addListener(() => {
data = { version: browser.runtime.getManifest().version };
});
browser.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 halaman pengujian dari ekstensi pengujian kami, mengklik elemen tombol, dan menunggu respons dari service worker.
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 bahwa pengujian tersebut selesai
dengan berhasil.
Langkah 4: Hentikan pekerja layanan
Tambahkan fungsi bantuan berikut yang menghentikan service worker 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, perbarui pengujian Anda dengan kode berikut. Sekarang, hentikan service worker 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 service worker tidak merespons setelah dihentikan.
Langkah 6: Perbaiki service worker
Selanjutnya, perbaiki pekerja layanan dengan menghapus ketergantungannya pada status sementara. Perbarui
test-extension untuk menggunakan kode berikut, yang disimpan di
service-worker-fixed.js di repositori.
service-worker-fixed.js:
browser.runtime.onInstalled.addListener(() => {
browser.storage.local.set({ version: browser.runtime.getManifest().version });
});
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
browser.storage.local.get('version').then((data) => {
sendResponse(data.version);
});
return true;
});
Di sini, kita menyimpan versi ke browser.storage.local, bukan variabel global
untuk mempertahankan status di antara masa aktif service worker. Karena penyimpanan hanya dapat
diakses secara asinkron, kita juga menampilkan nilai benar dari pemroses onMessage untuk
memastikan callback sendResponse tetap aktif.
Langkah 7: Jalankan pengujian lagi
Jalankan pengujian lagi dengan npm start. Sekarang seharusnya berhasil.
Langkah berikutnya
Sekarang Anda dapat menerapkan pendekatan yang sama ke ekstensi Anda sendiri. Pertimbangkan hal berikut:
- Bangun suite pengujian Anda untuk mendukung pengujian dengan atau tanpa penghentian service worker yang tidak terduga. Kemudian, Anda dapat menjalankan kedua mode secara terpisah untuk memperjelas penyebab kegagalan.
- Tulis kode untuk menghentikan service worker di titik acak dalam pengujian. Cara ini dapat menjadi cara yang baik untuk menemukan masalah yang mungkin sulit diprediksi.
- Belajarlah dari kegagalan pengujian dan cobalah untuk membuat kode secara defensif di masa mendatang. Misalnya, tambahkan aturan linting untuk mencegah penggunaan variabel global dan coba pindahkan data ke status yang lebih persisten.