Puppeteer की मदद से सर्विस वर्कर को बंद किए जाने की जांच करना

इस गाइड में बताया गया है कि Puppeteer का इस्तेमाल करके, सर्विस वर्कर की सुविधा को खत्म करके ज़्यादा बेहतर एक्सटेंशन कैसे बनाए जा सकते हैं. किसी भी समय सेवा को बंद करने के लिए तैयार रहना ज़रूरी है, क्योंकि ऐसा बिना किसी चेतावनी के हो सकता है. इसकी वजह से, सेवा कर्मचारी की ऐसी स्थिति होती है जब वह हमेशा के लिए बंद हो जाता है. ऐसे में, एक्सटेंशन को ज़रूरी स्थिति को सेव करना चाहिए. साथ ही, यह किसी इवेंट के दोबारा शुरू होते ही अनुरोधों को हैंडल करने में सक्षम होना चाहिए.

शुरू करने से पहले

chrome-extensions-सैंपल डेटा स्टोर करने की जगह का क्लोन बनाएं या उसे डाउनलोड करें. हम /functional-samples/tutorial.terminate-sw/test-extension में टेस्ट एक्सटेंशन का इस्तेमाल करेंगे. यह हर बार किसी बटन पर क्लिक होने पर, सर्विस वर्कर को मैसेज भेजता है और रिस्पॉन्स मिलने पर पेज पर टेक्स्ट जोड़ता है.

आपको Node.JS भी इंस्टॉल करना होगा जो Puppeteer पर बनाया गया रनटाइम है.

पहला चरण: अपना Node.js प्रोजेक्ट शुरू करें

इन फ़ाइलों को नई डायरेक्ट्री में बनाएं. ये दोनों मिलकर एक नया node.js प्रोजेक्ट बनाते हैं. साथ ही, टेस्ट रनर के तौर पर Jest का इस्तेमाल करके, Puppeteer टेस्ट सुइट का बेसिक स्ट्रक्चर मुहैया कराते हैं. इस सेटअप के बारे में ज़्यादा जानने के लिए, Puppeteer की मदद से Chrome एक्सटेंशन टेस्ट करना लेख देखें.

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;
});

ध्यान दें कि हमारा टेस्ट, सैंपल डेटा स्टोर करने की जगह से test-extension लोड करता है. chrome.runtime.onMessage का हैंडलर, chrome.runtime.onInstalled इवेंट के लिए हैंडलर में सेट किए गए स्टेट पर निर्भर करता है. इस वजह से, सर्विस वर्कर को बंद किए जाने और आने वाले समय में भेजे जाने वाले किसी मैसेज का जवाब देने पर, data का कॉन्टेंट खो जाएगा. जांच लिखने के बाद, हम इसे ठीक कर देंगे.

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);
});

दूसरा चरण: डिपेंडेंसी इंस्टॉल करना

ज़रूरी डिपेंडेंसी इंस्टॉल करने के लिए, npm install चलाएं.

तीसरा चरण: बुनियादी जांच लिखना

नीचे दिए गए टेस्ट को index.test.js के नीचे जोड़ें. इससे हमारे टेस्ट एक्सटेंशन का टेस्ट पेज खुलेगा और बटन पर क्लिक किया जाएगा. इसके बाद, सर्विस वर्कर से रिस्पॉन्स मिलने का इंतज़ार किया जाता है.

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');
});

आपके पास npm start के साथ टेस्ट करने का विकल्प है. जांच पूरी होने पर, आपको यह दिखेगा.

चौथा चरण: सर्विस वर्कर को बंद करना

नीचे दिया गया हेल्पर फ़ंक्शन जोड़ें, जो आपके सर्विस वर्कर को खत्म कर देता है:

/**
 * 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();
}

आखिर में, नीचे दिए गए कोड से अपनी जांच अपडेट करें. अब सर्विस वर्कर को हटा दें और बटन पर फिर से क्लिक करके देखें कि आपको जवाब मिला है या नहीं.

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');
});

पांचवां चरण: जांच करना

npm start चलाएं. आपका टेस्ट फ़ेल हो जाना चाहिए, जिससे पता चलता है कि सर्विस वर्कर को खत्म करने के बाद उसने जवाब नहीं दिया.

छठा चरण: सर्विस वर्कर को ठीक करना

इसके बाद, अस्थायी स्थिति पर निर्भरता को हटाकर सर्विस वर्कर को ठीक करें. रिपॉज़िटरी में मौजूद service-worker-fixed.js में सेव किए गए इस कोड का इस्तेमाल करने के लिए, टेस्ट-एक्सटेंशन को अपडेट करें.

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;
});

यहां हम सर्विस वर्कर के लाइफ़टाइम के बीच स्थिति को बनाए रखने के लिए, वर्शन को ग्लोबल वैरिएबल के बजाय chrome.storage.local में सेव करते हैं. स्टोरेज को सिर्फ़ एसिंक्रोनस तरीके से ऐक्सेस किया जा सकता है. इसलिए, यह पक्का करने के लिए कि sendResponse कॉलबैक चालू रहे, हम onMessage लिसनर से भी 'सही' दिखाते हैं.

सातवां चरण: फिर से जांच करना

npm start की मदद से फिर से टेस्ट करें. यह अब पास हो जाना चाहिए.

अगले चरण

अब यही तरीका अपने एक्सटेंशन पर भी लागू किया जा सकता है. इन बातों पर ध्यान दें:

  • अपना टेस्ट सुइट बनाएं, ताकि सर्विस वर्कर बंद किए जाने या उसके बिना भी काम करने में मदद मिले. फिर दोनों मोड को अलग-अलग चलाकर, यह साफ़ तौर पर देखा जा सकता है कि गड़बड़ी किस वजह से हुई थी.
  • टेस्ट में किसी भी समय पॉइंट पर सर्विस वर्कर को खत्म करने के लिए कोड लिखें. यह उन समस्याओं का पता लगाने का एक अच्छा तरीका हो सकता है जिनका अनुमान लगाना मुश्किल हो सकता है.
  • जांच में नाकामयाब होने पर सब सीखें और आने वाले समय में, सुरक्षित तरीके से कोड करने की कोशिश करें. उदाहरण के लिए, ग्लोबल वैरिएबल के इस्तेमाल को रोकने के लिए लिंटिंग नियम जोड़ें. साथ ही, डेटा को स्थायी स्थिति में ले जाने की कोशिश करें.