🎭
Playwright の Chrome 拡張でハマったこと
環境
- Playwright 1.45.1
参考資料
ハマったこと
localStorage
global.setup で localStorage に言語設定を行っていますが、テストに言語設定が反映されません。
tests/global.setup.ts
import { test as setup, expect } from "@playwright/test";
import dotenv from "dotenv";
import { STORAGE_STATE } from "../playwright.config";
// Read from default ".env" file.
dotenv.config();
setup.use({
baseURL: process.env.BASE_URL,
});
setup.beforeEach(async ({ page }, testInfo) => {
console.log(`Running ${testInfo.title}`);
});
setup("set localStorage", async ({ page }) => {
await page.context().addInitScript(() => {
window.localStorage.setItem("com.example.lang", "ja");
});
await page.goto("/");
await expect(page).toHaveTitle(/Example/);
await page.context().storageState({ path: STORAGE_STATE });
});
fixtures/chrome-extension.fixtures.ts
import {
test as base,
chromium,
Page,
type BrowserContext,
} from "@playwright/test";
import path from "path";
export const test = base.extend<{
page: Page;
context: BrowserContext;
extensionId: string;
}>({
context: async ({}, use) => {
const pathToExtension = path.join(
__dirname,
"../chrome-extension"
);
const context = await chromium.launchPersistentContext("", {
headless: false,
args: [
`--disable-extensions-except=${pathToExtension}`,
`--load-extension=${pathToExtension}`,
],
});
await use(context);
await context.close();
},
extensionId: async ({ context }, use) => {
let [background] = context.serviceWorkers();
if (!background) background = await context.waitForEvent("serviceworker");
const extensionId = background.url().split("/")[2];
await use(extensionId);
},
});
export const expect = test.expect;
解決策
fixture では global.setup で設定した localStorage が反映されないため、fixture 内で同様の処理を行う必要があります。
fixtures/chrome-extension.fixtures.ts
import {
test as base,
chromium,
Page,
type BrowserContext,
} from "@playwright/test";
import path from "path";
import { STORAGE_STATE } from "../playwright.config";
export const test = base.extend<{
page: Page;
context: BrowserContext;
extensionId: string;
}>({
context: async ({}, use) => {
const pathToExtension = path.join(
__dirname,
"../chrome-extension"
);
const context = await chromium.launchPersistentContext("", {
headless: false,
args: [
`--disable-extensions-except=${pathToExtension}`,
`--load-extension=${pathToExtension}`,
],
});
// global.setup で行っている localStorage の処理を追記する
// https://github.com/microsoft/playwright/issues/27161
context.addInitScript(() => {
window.localStorage.setItem("com.example.lang", "ja");
});
context.storageState({ path: STORAGE_STATE });
await use(context);
await context.close();
},
extensionId: async ({ context }, use) => {
let [background] = context.serviceWorkers();
if (!background) background = await context.waitForEvent("serviceworker");
const extensionId = background.url().split("/")[2];
await use(extensionId);
},
});
export const expect = test.expect;
Headless mode
公式ドキュメントの Headless mode を参考に実装すると次のエラーが発生しました。
fixtures/chrome-extension.fixtures.ts
import {
test as base,
chromium,
Page,
type BrowserContext,
} from "@playwright/test";
import path from "path";
export const test = base.extend<{
page: Page;
context: BrowserContext;
extensionId: string;
}>({
context: async ({}, use) => {
const pathToExtension = path.join(
__dirname,
"../chrome-extension"
);
const context = await chromium.launchPersistentContext("", {
// headless: false,
channel: "chromium", // Headless mode
args: [
`--disable-extensions-except=${pathToExtension}`,
`--load-extension=${pathToExtension}`,
],
});
await use(context);
await context.close();
},
extensionId: async ({ context }, use) => {
let [background] = context.serviceWorkers();
if (!background) background = await context.waitForEvent("serviceworker");
const extensionId = background.url().split("/")[2];
await use(extensionId);
},
});
export const expect = test.expect;
Test timeout of 30000ms exceeded while setting up "extensionId".
@chrome-extension.fixtures.ts:33
Error: browserContext.waitForEvent: Target page, context or browser has been closed
解決策
--headless=new
を追記することでエラーが解決しました。
fixtures/chrome-extension.fixtures.ts
const context = await chromium.launchPersistentContext("", {
// headless: false,
channel: "chromium", // Headless mode
args: [
`--headless=new`, // Headless mode
`--disable-extensions-except=${pathToExtension}`,
`--load-extension=${pathToExtension}`,
],
});
Discussion