diff --git a/.chronus/changes/fix_vscode_e2e_test-2025-8-15-10-18-14.md b/.chronus/changes/fix_vscode_e2e_test-2025-8-15-10-18-14.md new file mode 100644 index 00000000000..6cc4f53f064 --- /dev/null +++ b/.chronus/changes/fix_vscode_e2e_test-2025-8-15-10-18-14.md @@ -0,0 +1,8 @@ +--- +# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking +changeKind: fix +packages: + - typespec-vscode +--- + +Fix vscode e2e test when making a release pr diff --git a/packages/typespec-vscode/package.json b/packages/typespec-vscode/package.json index 83e721286b9..1b6b0493d3c 100644 --- a/packages/typespec-vscode/package.json +++ b/packages/typespec-vscode/package.json @@ -277,6 +277,7 @@ "package-vsix": "vsce package", "deploy": "vsce publish", "open-in-browser": "vscode-test-web --extensionDevelopmentPath=. .", + "test:e2e": "pnpm test:web && pnpm test:extension", "test:web": "vscode-test-web --quality stable --extensionDevelopmentPath=. --headless --extensionTestsPath=dist/test/web/suite.js ./test/web/data", "test:extension": "vitest run --root test/extension" }, diff --git a/packages/typespec-vscode/temp/ImportTypespecProjectOpenApi3/openapi.3.0.yaml b/packages/typespec-vscode/temp/ImportTypespecProjectOpenApi3/openapi.3.0.yaml index 7f357d01845..ff5fc299340 100644 --- a/packages/typespec-vscode/temp/ImportTypespecProjectOpenApi3/openapi.3.0.yaml +++ b/packages/typespec-vscode/temp/ImportTypespecProjectOpenApi3/openapi.3.0.yaml @@ -1204,5 +1204,4 @@ servers: Endpoint: default: '' description: |- - Supported Text Translation endpoints (protocol and hostname, for example: - https://api.cognitive.microsofttranslator.com). + Supported Text Translation endpoints (protocol and hostname, for example:https://api.cognitive.microsofttranslator.com). diff --git a/packages/typespec-vscode/test/extension/common/common-steps.ts b/packages/typespec-vscode/test/extension/common/common-steps.ts index 90a88fce3ee..727ca6654c7 100644 --- a/packages/typespec-vscode/test/extension/common/common-steps.ts +++ b/packages/typespec-vscode/test/extension/common/common-steps.ts @@ -1,8 +1,9 @@ +import { execSync } from "child_process"; import { rm } from "fs/promises"; import fs from "node:fs"; import path from "node:path"; import { Locator, Page } from "playwright"; -import { CaseScreenshot, retry } from "./utils"; +import { CaseScreenshot, PNPM_NO_MATCHING_VERSION_ERROR, retry } from "./utils"; /** * Waits for the specified text to appear on the page before proceeding. @@ -136,3 +137,24 @@ export function restoreTspConfigFile(folderName: string, lines: string) { const filePath = path.join(folderName, "tspconfig.yaml"); fs.writeFileSync(filePath, lines, "utf-8"); } + +/** + * Attempt to install the specified npm package and handle the error of pnpm version mismatch. + * @param pkg package name + * @returns Return true to skip testing, otherwise return false. + */ +export function tryInstallAndHandle(pkg: string): boolean { + try { + execSync(`pnpm install ${pkg}`, { stdio: "pipe" }); + return false; + } catch (e: any) { + const errorOutput = (e.stdout && e.stdout.toString()) || ""; + if (PNPM_NO_MATCHING_VERSION_ERROR.test(errorOutput)) { + const filteredLines = errorOutput + .split("\n") + .filter((line: any) => !line.trim().startsWith("../..")); + process.stderr.write(["SKIP_REASON:", ...filteredLines].join("\n") + "\n"); + } + return true; + } +} diff --git a/packages/typespec-vscode/test/extension/common/emit-steps.ts b/packages/typespec-vscode/test/extension/common/emit-steps.ts index 90a2d93fd0b..40a86282fd9 100644 --- a/packages/typespec-vscode/test/extension/common/emit-steps.ts +++ b/packages/typespec-vscode/test/extension/common/emit-steps.ts @@ -20,6 +20,19 @@ export async function emitSelectType(page: Page, type: string, cs: CaseScreensho "Emitting Server Stub from TypeSpec files. Supported languages are .NET, JavaScript.", }, ]; + await retry( + page, + 3, + async () => { + const selectTypeBox = await page.getByRole("textbox", { + name: "Select an emitter type - Emit", + }); + return (await selectTypeBox.count()) > 0; + }, + `Failed to find the language for code emitting.`, + 2, + cs, + ); await retry( page, 3, diff --git a/packages/typespec-vscode/test/extension/common/utils.ts b/packages/typespec-vscode/test/extension/common/utils.ts index 638265fd0c7..a47a3b152fe 100644 --- a/packages/typespec-vscode/test/extension/common/utils.ts +++ b/packages/typespec-vscode/test/extension/common/utils.ts @@ -3,6 +3,9 @@ import path, { join } from "node:path"; import { ElectronApplication, Page, _electron } from "playwright"; import { test as baseTest, inject } from "vitest"; +export const PNPM_NO_MATCHING_VERSION_ERROR = + /ERR_PNPM_NO_MATCHING_VERSION.*No matching version found/; + const __dirname = import.meta.dirname; export const projectRoot = path.resolve(__dirname, "../../../"); export const tempDir = path.resolve(projectRoot, "./temp"); diff --git a/packages/typespec-vscode/test/extension/emit-typespec.test.ts b/packages/typespec-vscode/test/extension/emit-typespec.test.ts index 7fe6b3518c5..f433e7c61d0 100644 --- a/packages/typespec-vscode/test/extension/emit-typespec.test.ts +++ b/packages/typespec-vscode/test/extension/emit-typespec.test.ts @@ -8,16 +8,15 @@ import { readTspConfigFile, restoreTspConfigFile, startWithCommandPalette, + tryInstallAndHandle, } from "./common/common-steps"; import { emiChooseEmitter, emitSelectLanguage, emitSelectType } from "./common/emit-steps"; import { CaseScreenshot, tempDir, test } from "./common/utils"; -try { - execSync("pnpm install @typespec/http-client-csharp", { stdio: "inherit" }); - execSync("pnpm install @typespec/http", { stdio: "inherit" }); -} catch (e) { - process.exit(1); -} +let shouldSkip = false; + +shouldSkip = tryInstallAndHandle("@typespec/http") || shouldSkip; +shouldSkip = tryInstallAndHandle("@typespec/http-client-csharp") || shouldSkip; enum EmitProjectTriggerType { Command = "Command", @@ -64,7 +63,8 @@ beforeEach(() => { } }); -describe.each(EmitCasesConfigList)("EmitTypespecProject", async (item) => { +const describeFn = shouldSkip ? describe.skip : describe; +describeFn.each(EmitCasesConfigList)("EmitTypespecProject", async (item) => { const { caseName, selectType, selectTypeLanguage, TspConfigHasEmit, expectedResults } = item; test(caseName, async ({ launch }) => { const cs = new CaseScreenshot(caseName); diff --git a/packages/typespec-vscode/test/extension/import-typespec.test.ts b/packages/typespec-vscode/test/extension/import-typespec.test.ts index e5e01396f9d..10f6d63a77d 100644 --- a/packages/typespec-vscode/test/extension/import-typespec.test.ts +++ b/packages/typespec-vscode/test/extension/import-typespec.test.ts @@ -2,16 +2,19 @@ import { execSync } from "child_process"; import fs from "node:fs"; import path from "node:path"; import { beforeEach, describe } from "vitest"; -import { contrastResult, preContrastResult, startWithRightClick } from "./common/common-steps"; +import { + contrastResult, + preContrastResult, + startWithRightClick, + tryInstallAndHandle, +} from "./common/common-steps"; import { mockShowOpenDialog } from "./common/mock-dialogs"; import { CaseScreenshot, tempDir, test } from "./common/utils"; -try { - execSync("pnpm install @typespec/openapi3", { stdio: "inherit" }); - execSync("pnpm install @typespec/http", { stdio: "inherit" }); -} catch (e) { - process.exit(1); -} +let shouldSkip = false; + +shouldSkip = tryInstallAndHandle("@typespec/http") || shouldSkip; +shouldSkip = tryInstallAndHandle("@typespec/openapi3") || shouldSkip; enum ImportProjectTriggerType { CommandPalette = "CommandPalette", @@ -70,7 +73,8 @@ beforeEach(() => { } }); -describe.each(ImportCasesConfigList)("ImportTypespecFromOpenApi3", async (item) => { +const describeFn = shouldSkip ? describe.skip : describe; +describeFn.each(ImportCasesConfigList)("ImportTypespecFromOpenApi3", async (item) => { const { caseName, expectedResults } = item; test(caseName, async ({ launch }) => { const cs = new CaseScreenshot(caseName); diff --git a/packages/typespec-vscode/test/extension/preview-typespec.test.ts b/packages/typespec-vscode/test/extension/preview-typespec.test.ts index cd0370e38e2..89cd00e0c85 100644 --- a/packages/typespec-vscode/test/extension/preview-typespec.test.ts +++ b/packages/typespec-vscode/test/extension/preview-typespec.test.ts @@ -3,15 +3,13 @@ import { rm } from "fs/promises"; import fs from "node:fs"; import path from "node:path"; import { beforeEach, describe } from "vitest"; -import { startWithCommandPalette } from "./common/common-steps"; +import { startWithCommandPalette, tryInstallAndHandle } from "./common/common-steps"; import { CaseScreenshot, retry, tempDir, test } from "./common/utils"; -try { - execSync("pnpm install @typespec/http", { stdio: "inherit" }); - execSync("pnpm install @typespec/openapi3", { stdio: "inherit" }); -} catch (e) { - process.exit(1); -} +let shouldSkip = false; + +shouldSkip = tryInstallAndHandle("@typespec/http") || shouldSkip; +shouldSkip = tryInstallAndHandle("@typespec/openapi3") || shouldSkip; export enum PreviewProjectTriggerType { Command = "CommandPalette", @@ -53,7 +51,8 @@ beforeEach(() => { } }); -describe.each(PreviewCasesConfigList)("PreviewAPIDocument", async (item) => { +const describeFn = shouldSkip ? describe.skip : describe; +describeFn.each(PreviewCasesConfigList)("PreviewAPIDocument", async (item) => { const { caseName } = item; test(caseName, async ({ launch }) => { const cs = new CaseScreenshot(caseName);