이 가이드에서는 테스트 서비스를 통해 더 강력한 확장 프로그램을 빌드하는 방법을 설명합니다. Puppeteer를 사용하여 작업자 종료를 실행합니다. 종료는 경고 없이 발생할 수 있으며, 이로 인해 서비스 워커의 비지속성 상태가 손실될 수 있으므로 언제든지 종료를 처리할 준비가 되어 있어야 합니다. 따라서 확장 프로그램은 중요한 상태를 저장하고 다시 시작되는 즉시 요청을 처리할 수 있어야 이벤트를 처리합니다.
시작하기 전에
chrome-extensions-samples 저장소를 클론하거나 다운로드합니다.
/functional-samples/tutorial.terminate-sw/test-extension
에서 테스트 확장 프로그램을 사용합니다. 이 확장 프로그램은 버튼을 클릭할 때마다 서비스 워커에 메시지를 전송하고 응답을 수신하면 페이지에 텍스트를 추가합니다.
Puppeteer가 빌드되는 런타임인 Node.JS도 설치해야 합니다.
1단계: Node.js 프로젝트 시작
새 디렉터리에 다음 파일을 만듭니다. 이들이 함께 어우러져 새로운 Node.js 프로젝트를 설명하고 Puppeteer 테스트 모음의 기본 구조를 제공합니다. Jest를 테스트 실행기로 사용 이 설정에 관해 자세히 알아보려면 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);
});
2단계: 종속 항목 설치
npm install
을 실행하여 필수 종속 항목을 설치합니다.
3단계: 기본 테스트 작성
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
로 테스트를 실행하면 테스트가 성공적으로 완료되는 것을 확인할 수 있습니다.
4단계: 서비스 워커 종료
서비스 워커를 종료하는 다음 도우미 함수를 추가합니다.
/**
* 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');
});
5단계: 테스트 실행
npm start
을 실행합니다. 테스트가 실패하여 서비스 워커가
응답이 없습니다.
6단계: 서비스 워커 수정
그런 다음 임시 상태에 대한 의존성을 삭제하여 서비스 워커를 수정합니다. 저장소의 service-worker-fixed.js
에 저장된 다음 코드를 사용하도록 test-extension을 업데이트합니다.
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
리스너에서 true도 반환합니다.
7단계: 테스트 다시 실행
npm start
를 사용하여 테스트를 다시 실행합니다. 이제 통과합니다.
다음 단계
이제 자체 확장 프로그램에 동일한 접근 방식을 적용할 수 있습니다. 다음 사항을 고려하세요.
- 예상치 못한 서비스 작업자 종료 여부와 관계없이 실행을 지원하도록 테스트 모음을 빌드합니다. 그런 다음 두 모드를 개별적으로 실행하여 보다 명확하게 확인할 수 있습니다. 확인할 수 있습니다
- 테스트 내 임의의 지점에서 서비스 워커를 종료하는 코드를 작성합니다. 이는 예측하기 어려운 문제를 발견하는 데 좋은 방법입니다.
- 테스트 실패에서 교훈을 얻고 향후 방어적으로 코딩해 보세요. 대상 예를 들어 전역 변수 사용을 권장하지 않는 린트 규칙을 추가하고 데이터를 보다 영구적인 상태로 이동