Skip to content
Draft
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
8 changes: 8 additions & 0 deletions .chronus/changes/fix_vscode_e2e_test-2025-8-15-10-18-14.md
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions packages/typespec-vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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).
24 changes: 23 additions & 1 deletion packages/typespec-vscode/test/extension/common/common-steps.ts
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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;
}
}
13 changes: 13 additions & 0 deletions packages/typespec-vscode/test/extension/common/emit-steps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
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 @@ -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");
Expand Down
14 changes: 7 additions & 7 deletions packages/typespec-vscode/test/extension/emit-typespec.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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);
Expand Down
20 changes: 12 additions & 8 deletions packages/typespec-vscode/test/extension/import-typespec.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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);
Expand Down
Loading