Skip to content

Commit 4147616

Browse files
committed
✅ 修复 e2e 测试 service worker 超时并优化等待策略
- gm-api.spec.ts: Phase 2 重启 context 后等待 service worker 注册完成 再交给 fixtures,避免 extensionId fixture 用 10s 全局超时等待失败 - gm-api.spec.ts: 用事件驱动 Promise 替换 500ms 轮询循环, console 结果一出现立即继续 - utils.ts: installScriptByCode 用 DOM 事件等待替代固定延迟: click 后等光标出现,粘贴后等 .view-lines 内容变化
1 parent 0087af8 commit 4147616

File tree

2 files changed

+36
-28
lines changed

2 files changed

+36
-28
lines changed

e2e/gm-api.spec.ts

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,13 @@ const test = base.extend<{
2020
args: ["--headless=new", ...chromeArgs],
2121
});
2222
let [bg] = ctx1.serviceWorkers();
23-
if (!bg) bg = await ctx1.waitForEvent("serviceworker");
23+
if (!bg) bg = await ctx1.waitForEvent("serviceworker", { timeout: 30_000 });
2424
const extensionId = bg.url().split("/")[2];
2525
const extPage = await ctx1.newPage();
2626
await extPage.goto("chrome://extensions/");
2727
await extPage.waitForLoadState("domcontentloaded");
28-
await extPage.waitForTimeout(1_000);
28+
// Wait for developerPrivate API to be available instead of a fixed delay
29+
await extPage.waitForFunction(() => !!(chrome as any).developerPrivate, { timeout: 10_000 });
2930
await extPage.evaluate(async (id) => {
3031
await (chrome as any).developerPrivate.updateExtensionConfiguration({
3132
extensionId: id,
@@ -40,6 +41,10 @@ const test = base.extend<{
4041
headless: false,
4142
args: ["--headless=new", ...chromeArgs],
4243
});
44+
// Ensure service worker is registered before handing context to fixtures,
45+
// preventing extensionId fixture from timing out with the global 10s timeout.
46+
let [sw] = context.serviceWorkers();
47+
if (!sw) await context.waitForEvent("serviceworker", { timeout: 30_000 });
4348
await use(context);
4449
await context.close();
4550
fs.rmSync(userDataDir, { recursive: true, force: true });
@@ -117,24 +122,25 @@ async function runTestScript(
117122

118123
const page = await context.newPage();
119124
const logs: string[] = [];
120-
page.on("console", (msg) => logs.push(msg.text()));
121-
122-
await page.goto(targetUrl, { waitUntil: "domcontentloaded" });
123-
124-
// Wait for test results to appear in console
125-
const deadline = Date.now() + timeoutMs;
126125
let passed = -1;
127126
let failed = -1;
128-
while (Date.now() < deadline) {
129-
for (const log of logs) {
130-
const passMatch = log.match(/[:]\s*(\d+)/);
131-
const failMatch = log.match(/[:]\s*(\d+)/);
127+
128+
// Resolve as soon as both pass and fail counts appear in console output
129+
const resultReady = new Promise<void>((resolve) => {
130+
page.on("console", (msg) => {
131+
const text = msg.text();
132+
logs.push(text);
133+
const passMatch = text.match(/[:]\s*(\d+)/);
134+
const failMatch = text.match(/[:]\s*(\d+)/);
132135
if (passMatch) passed = parseInt(passMatch[1], 10);
133136
if (failMatch) failed = parseInt(failMatch[1], 10);
134-
}
135-
if (passed >= 0 && failed >= 0) break;
136-
await page.waitForTimeout(500);
137-
}
137+
if (passed >= 0 && failed >= 0) resolve();
138+
});
139+
});
140+
141+
await page.goto(targetUrl, { waitUntil: "domcontentloaded" });
142+
// Race: resolve immediately when results arrive, or fall through after timeout
143+
await Promise.race([resultReady, page.waitForTimeout(timeoutMs)]);
138144

139145
await page.close();
140146
return { passed, failed, logs };

e2e/utils.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,24 @@ export async function openEditorPage(context: BrowserContext, extensionId: strin
3636
/** Install a script by injecting code into the Monaco editor and saving */
3737
export async function installScriptByCode(context: BrowserContext, extensionId: string, code: string): Promise<void> {
3838
const page = await openEditorPage(context, extensionId);
39-
// Wait for Monaco editor to be ready
39+
// Wait for Monaco editor DOM and default template content to be ready
4040
await page.locator(".monaco-editor").waitFor({ timeout: 30_000 });
4141
await page.locator(".view-lines").waitFor({ timeout: 15_000 });
42-
// Click into editor to ensure focus
42+
// Click to focus and wait for the cursor to appear (confirms editor is interactive)
4343
await page.locator(".monaco-editor .view-lines").click();
44-
await page.waitForTimeout(500);
45-
// Select all existing content and replace via clipboard
44+
await page.locator(".cursors-layer .cursor").waitFor({ timeout: 5_000 });
45+
// Select all existing content
4646
await page.keyboard.press("ControlOrMeta+a");
47-
await page.waitForTimeout(500);
47+
// Capture current content fingerprint, then paste replacement
48+
const initialText = await page.locator(".view-lines").textContent();
4849
await page.evaluate((text) => navigator.clipboard.writeText(text), code);
4950
await page.keyboard.press("ControlOrMeta+v");
50-
await page.waitForTimeout(2000);
51+
// Wait for Monaco to finish rendering the pasted content (content will differ from template)
52+
await page.waitForFunction(
53+
(init) => document.querySelector(".view-lines")?.textContent !== init,
54+
initialText,
55+
{ timeout: 10_000 }
56+
);
5157
// Save
5258
await page.keyboard.press("ControlOrMeta+s");
5359
// Wait for save: try arco-message first, then verify via script list
@@ -61,13 +67,9 @@ export async function installScriptByCode(context: BrowserContext, extensionId:
6167
// For scripts with @require/@resource, the message may not appear.
6268
// Verify save by checking the script list on the options page.
6369
const listPage = await openOptionsPage(context, extensionId);
64-
await listPage.waitForTimeout(2_000);
6570
const emptyState = listPage.locator(".arco-empty");
66-
// Wait until at least one script appears (no empty state)
67-
for (let i = 0; i < 30; i++) {
68-
if ((await emptyState.count()) === 0) break;
69-
await listPage.waitForTimeout(1_000);
70-
}
71+
// Wait until at least one script appears (no empty state), up to 30s
72+
await emptyState.waitFor({ state: "detached", timeout: 30_000 }).catch(() => {});
7173
await listPage.close();
7274
}
7375
await page.close();

0 commit comments

Comments
 (0)