Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 34 additions & 17 deletions packages/typespec-vscode/test/extension/common/mock-dialogs.ts
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this will solve both issue if they are not the same thing underneth. The 2nd one crash before any of the code changes are

packages/typespec-vscode test:e2e:  FAIL  create-typespec.test.ts > CreateTypespecProject > CreateTypespecProject GenericRestAPI Trigger CommandPalette EmptyFolder
packages/typespec-vscode test:e2e: Error: electronApplication.firstWindow: Target page, context or browser has been closed

Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function stubDialog<T extends keyof Dialog>(
return stubMultipleDialogs(app, [{ method, value }]);
}

export function stubMultipleDialogs<T extends keyof Dialog>(
export async function stubMultipleDialogs<T extends keyof Dialog>(
app: ElectronApplication,
mocks: DialogMethodStubPartial<T>[],
) {
Expand All @@ -53,23 +53,40 @@ export function stubMultipleDialogs<T extends keyof Dialog>(
});

// https://github.com/microsoft/playwright/issues/8278#issuecomment-1009957411
return app.evaluate(({ dialog }, mocks) => {
mocks.forEach((mock) => {
const thisDialog = dialog[mock.method];
if (!thisDialog) {
throw new Error(`can't find ${mock.method} on dialog module.`);
}
if (mock.method.endsWith("Sync")) {
dialog[mock.method] = () => {
return mock.value;
};
} else {
dialog[mock.method] = async () => {
return mock.value;
};
// Retry to handle transient "Execution context was destroyed" errors
// that occur when VS Code reloads during startup.
const maxRetries = 3;
const retryDelayMs = 1000;

for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await app.evaluate(({ dialog }, mocks) => {
mocks.forEach((mock) => {
const thisDialog = dialog[mock.method];
if (!thisDialog) {
throw new Error(`can't find ${mock.method} on dialog module.`);
}
if (mock.method.endsWith("Sync")) {
dialog[mock.method] = () => {
return mock.value;
};
} else {
dialog[mock.method] = async () => {
return mock.value;
};
}
});
}, mocksRequired);
} catch (error: any) {
const isRetryable =
error.message?.includes("Execution context was destroyed") ||
error.message?.includes("Target page, context or browser has been closed");
if (!isRetryable || attempt === maxRetries) {
throw error;
}
});
}, mocksRequired);
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
}
}
}

/**
Expand Down
3 changes: 3 additions & 0 deletions packages/typespec-vscode/test/extension/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ export const test = baseTest.extend<{
].filter((v): v is string => !!v),
});
const page = await app.firstWindow();
// Wait for the page to fully load to reduce the chance of
// VS Code reloading the window and destroying the execution context.
await page.waitForLoadState("domcontentloaded");
const tracePath = join(projectRoot, "test-results", task.name, "trace.zip");
const artifactsDir = join(tempDir, "playwright-artifacts");
await fs.promises.mkdir(artifactsDir, { recursive: true }); // make sure the directory exists
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ describe.each(CreateCasesConfigList)("CreateTypespecProject", async (item) => {
workspacePath: workspacePath,
});
await cs.screenshot(page, "after_launch");
// Wait for VS Code UI to be ready before mocking dialogs to avoid
// "Execution context was destroyed" errors from window reloads.
await page.waitForSelector(".explorer-viewlet", { timeout: 30000 });
await mockShowOpenDialog(app, [workspacePath]);
await startWithCommandPalette(page, "Create Typespec Project", cs);
await cs.screenshot(page, "after_start_command");
Expand Down
Loading