From 041827dc5405e154a36b5e0ba8b46d21913344bf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 5 Feb 2026 16:25:33 +0000 Subject: [PATCH 1/7] Initial plan From cb97df58c929c562ab57d92fc0cd0ed4bf1086d1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 5 Feb 2026 16:40:10 +0000 Subject: [PATCH 2/7] Migrate init templates to new testing framework Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com> --- .../emitter-ts/test/hello.test.ts | 2 +- .../emitter-ts/test/test-host.ts | 43 +++++-------------- .../library-ts/test/decorators.test.ts | 33 ++++++-------- .../library-ts/test/test-host.ts | 24 ++++------- .../templates/emitter-ts/test/hello.test.ts | 2 +- .../templates/emitter-ts/test/test-host.ts.mu | 43 +++++-------------- .../library-ts/test/decorators.test.ts.mu | 33 ++++++-------- .../templates/library-ts/test/test-host.ts.mu | 24 ++++------- 8 files changed, 62 insertions(+), 142 deletions(-) diff --git a/packages/compiler/templates/__snapshots__/emitter-ts/test/hello.test.ts b/packages/compiler/templates/__snapshots__/emitter-ts/test/hello.test.ts index 9bf04d106c1..00d8f062a17 100644 --- a/packages/compiler/templates/__snapshots__/emitter-ts/test/hello.test.ts +++ b/packages/compiler/templates/__snapshots__/emitter-ts/test/hello.test.ts @@ -1,5 +1,5 @@ import { strictEqual } from "node:assert"; -import { describe, it } from "node:test"; +import { describe, it } from "vitest"; import { emit } from "./test-host.js"; describe("hello", () => { diff --git a/packages/compiler/templates/__snapshots__/emitter-ts/test/test-host.ts b/packages/compiler/templates/__snapshots__/emitter-ts/test/test-host.ts index 14b78cf71f5..2a0d323e463 100644 --- a/packages/compiler/templates/__snapshots__/emitter-ts/test/test-host.ts +++ b/packages/compiler/templates/__snapshots__/emitter-ts/test/test-host.ts @@ -1,43 +1,20 @@ import { Diagnostic, resolvePath } from "@typespec/compiler"; -import { - createTestHost, - createTestWrapper, - expectDiagnosticEmpty, -} from "@typespec/compiler/testing"; -import { EmitterTsTestLibrary } from "../src/testing/index.js"; +import { expectDiagnosticEmpty } from "@typespec/compiler/testing"; +import { createTester } from "@typespec/compiler/testing"; -export async function createEmitterTsTestHost() { - return createTestHost({ - libraries: [EmitterTsTestLibrary], - }); -} - -export async function createEmitterTsTestRunner() { - const host = await createEmitterTsTestHost(); - - return createTestWrapper(host, { - compilerOptions: { - noEmit: false, - emit: ["emitter-ts"], - }, - }); -} +export const Tester = createTester(resolvePath(import.meta.dirname, ".."), { + libraries: ["emitter-ts"], +}).emit("emitter-ts"); export async function emitWithDiagnostics( code: string ): Promise<[Record, readonly Diagnostic[]]> { - const runner = await createEmitterTsTestRunner(); - await runner.compileAndDiagnose(code, { - outputDir: "tsp-output", + const [{ outputs }, diagnostics] = await Tester.compileAndDiagnose(code, { + compilerOptions: { + emit: ["emitter-ts"], + }, }); - const emitterOutputDir = "./tsp-output/emitter-ts"; - const files = await runner.program.host.readDir(emitterOutputDir); - - const result: Record = {}; - for (const file of files) { - result[file] = (await runner.program.host.readFile(resolvePath(emitterOutputDir, file))).text; - } - return [result, runner.program.diagnostics]; + return [outputs, diagnostics]; } export async function emit(code: string): Promise> { diff --git a/packages/compiler/templates/__snapshots__/library-ts/test/decorators.test.ts b/packages/compiler/templates/__snapshots__/library-ts/test/decorators.test.ts index b089e56bcd8..ab7e95e2f43 100644 --- a/packages/compiler/templates/__snapshots__/library-ts/test/decorators.test.ts +++ b/packages/compiler/templates/__snapshots__/library-ts/test/decorators.test.ts @@ -1,29 +1,22 @@ import { strictEqual } from "node:assert"; -import { describe, it, beforeEach } from "node:test"; -import type { Operation } from "@typespec/compiler"; -import { BasicTestRunner, expectDiagnostics, extractCursor } from "@typespec/compiler/testing"; +import { describe, it } from "vitest"; +import { expectDiagnostics, extractCursor, t } from "@typespec/compiler/testing"; import { getAlternateName } from "../src/decorators.js"; -import { createLibraryTsTestRunner } from "./test-host.js"; +import { Tester } from "./test-host.js"; describe("decorators", () => { - let runner: BasicTestRunner; - - beforeEach(async () => { - runner = await createLibraryTsTestRunner(); - }) - describe("@alternateName", () => { it("set alternate name on operation", async () => { - const { test } = (await runner.compile( - `@alternateName("bar") @test op test(): void;` - )) as { test: Operation }; - strictEqual(getAlternateName(runner.program, test), "bar"); + const { test, program } = await Tester.compile(t.code` + @alternateName("bar") ${t.op("test")}(): void; + `); + strictEqual(getAlternateName(program, test), "bar"); }); it("emit diagnostic if not used on an operation", async () => { - const diagnostics = await runner.diagnose( - `@alternateName("bar") model Test {}` - ); + const diagnostics = await Tester.diagnose(` + @alternateName("bar") model Test {} + `); expectDiagnostics(diagnostics, { severity: "error", code: "decorator-wrong-target", @@ -34,14 +27,12 @@ describe("decorators", () => { it("emit diagnostic if using banned name", async () => { const {pos, source} = extractCursor(`@alternateName(┆"banned") op test(): void;`) - const diagnostics = await runner.diagnose( - source - ); + const diagnostics = await Tester.diagnose(source); expectDiagnostics(diagnostics, { severity: "error", code: "library-ts/banned-alternate-name", message: `Banned alternate name "banned".`, - pos: pos + runner.autoCodeOffset + pos }) }); }); diff --git a/packages/compiler/templates/__snapshots__/library-ts/test/test-host.ts b/packages/compiler/templates/__snapshots__/library-ts/test/test-host.ts index e973984e84b..852a8afc8b9 100644 --- a/packages/compiler/templates/__snapshots__/library-ts/test/test-host.ts +++ b/packages/compiler/templates/__snapshots__/library-ts/test/test-host.ts @@ -1,17 +1,9 @@ -import { createTestHost, createTestWrapper } from "@typespec/compiler/testing"; -import { LibraryTsTestLibrary } from "../src/testing/index.js"; - -export async function createLibraryTsTestHost() { - return createTestHost({ - libraries: [LibraryTsTestLibrary], - }); -} - -export async function createLibraryTsTestRunner() { - const host = await createLibraryTsTestHost(); - - return createTestWrapper(host, { - autoUsings: ["LibraryTs"] - }); -} +import { resolvePath } from "@typespec/compiler"; +import { createTester } from "@typespec/compiler/testing"; + +export const Tester = createTester(resolvePath(import.meta.dirname, ".."), { + libraries: ["library-ts"], +}) + .import("library-ts") + .using("LibraryTs"); diff --git a/packages/compiler/templates/emitter-ts/test/hello.test.ts b/packages/compiler/templates/emitter-ts/test/hello.test.ts index 9bf04d106c1..00d8f062a17 100644 --- a/packages/compiler/templates/emitter-ts/test/hello.test.ts +++ b/packages/compiler/templates/emitter-ts/test/hello.test.ts @@ -1,5 +1,5 @@ import { strictEqual } from "node:assert"; -import { describe, it } from "node:test"; +import { describe, it } from "vitest"; import { emit } from "./test-host.js"; describe("hello", () => { diff --git a/packages/compiler/templates/emitter-ts/test/test-host.ts.mu b/packages/compiler/templates/emitter-ts/test/test-host.ts.mu index 5f1f869861a..70d6b7fb7a2 100644 --- a/packages/compiler/templates/emitter-ts/test/test-host.ts.mu +++ b/packages/compiler/templates/emitter-ts/test/test-host.ts.mu @@ -1,43 +1,20 @@ import { Diagnostic, resolvePath } from "@typespec/compiler"; -import { - createTestHost, - createTestWrapper, - expectDiagnosticEmpty, -} from "@typespec/compiler/testing"; -import { {{#casing.pascalCase}}{{name}}{{/casing.pascalCase}}TestLibrary } from "../src/testing/index.js"; +import { expectDiagnosticEmpty } from "@typespec/compiler/testing"; +import { createTester } from "@typespec/compiler/testing"; -export async function create{{#casing.pascalCase}}{{name}}{{/casing.pascalCase}}TestHost() { - return createTestHost({ - libraries: [{{#casing.pascalCase}}{{name}}{{/casing.pascalCase}}TestLibrary], - }); -} - -export async function create{{#casing.pascalCase}}{{name}}{{/casing.pascalCase}}TestRunner() { - const host = await create{{#casing.pascalCase}}{{name}}{{/casing.pascalCase}}TestHost(); - - return createTestWrapper(host, { - compilerOptions: { - noEmit: false, - emit: ["{{name}}"], - }, - }); -} +export const Tester = createTester(resolvePath(import.meta.dirname, ".."), { + libraries: ["{{name}}"], +}).emit("{{name}}"); export async function emitWithDiagnostics( code: string ): Promise<[Record, readonly Diagnostic[]]> { - const runner = await create{{#casing.pascalCase}}{{name}}{{/casing.pascalCase}}TestRunner(); - await runner.compileAndDiagnose(code, { - outputDir: "tsp-output", + const [{ outputs }, diagnostics] = await Tester.compileAndDiagnose(code, { + compilerOptions: { + emit: ["{{name}}"], + }, }); - const emitterOutputDir = "./tsp-output/{{name}}"; - const files = await runner.program.host.readDir(emitterOutputDir); - - const result: Record = {}; - for (const file of files) { - result[file] = (await runner.program.host.readFile(resolvePath(emitterOutputDir, file))).text; - } - return [result, runner.program.diagnostics]; + return [outputs, diagnostics]; } export async function emit(code: string): Promise> { diff --git a/packages/compiler/templates/library-ts/test/decorators.test.ts.mu b/packages/compiler/templates/library-ts/test/decorators.test.ts.mu index 18b154793df..5c87f21401a 100644 --- a/packages/compiler/templates/library-ts/test/decorators.test.ts.mu +++ b/packages/compiler/templates/library-ts/test/decorators.test.ts.mu @@ -1,29 +1,22 @@ import { strictEqual } from "node:assert"; -import { describe, it, beforeEach } from "node:test"; -import type { Operation } from "@typespec/compiler"; -import { BasicTestRunner, expectDiagnostics, extractCursor } from "@typespec/compiler/testing"; +import { describe, it } from "vitest"; +import { expectDiagnostics, extractCursor, t } from "@typespec/compiler/testing"; import { getAlternateName } from "../src/decorators.js"; -import { create{{#casing.pascalCase}}{{name}}{{/casing.pascalCase}}TestRunner } from "./test-host.js"; +import { Tester } from "./test-host.js"; describe("decorators", () => { - let runner: BasicTestRunner; - - beforeEach(async () => { - runner = await create{{#casing.pascalCase}}{{name}}{{/casing.pascalCase}}TestRunner(); - }) - describe("@alternateName", () => { it("set alternate name on operation", async () => { - const { test } = (await runner.compile( - `@alternateName("bar") @test op test(): void;` - )) as { test: Operation }; - strictEqual(getAlternateName(runner.program, test), "bar"); + const { test, program } = await Tester.compile(t.code` + @alternateName("bar") ${t.op("test")}(): void; + `); + strictEqual(getAlternateName(program, test), "bar"); }); it("emit diagnostic if not used on an operation", async () => { - const diagnostics = await runner.diagnose( - `@alternateName("bar") model Test {}` - ); + const diagnostics = await Tester.diagnose(` + @alternateName("bar") model Test {} + `); expectDiagnostics(diagnostics, { severity: "error", code: "decorator-wrong-target", @@ -34,14 +27,12 @@ describe("decorators", () => { it("emit diagnostic if using banned name", async () => { const {pos, source} = extractCursor(`@alternateName(┆"banned") op test(): void;`) - const diagnostics = await runner.diagnose( - source - ); + const diagnostics = await Tester.diagnose(source); expectDiagnostics(diagnostics, { severity: "error", code: "{{name}}/banned-alternate-name", message: `Banned alternate name "banned".`, - pos: pos + runner.autoCodeOffset + pos }) }); }); diff --git a/packages/compiler/templates/library-ts/test/test-host.ts.mu b/packages/compiler/templates/library-ts/test/test-host.ts.mu index b75e5c1045d..a4b5aed5e7a 100644 --- a/packages/compiler/templates/library-ts/test/test-host.ts.mu +++ b/packages/compiler/templates/library-ts/test/test-host.ts.mu @@ -1,17 +1,9 @@ -import { createTestHost, createTestWrapper } from "@typespec/compiler/testing"; -import { {{#casing.pascalCase}}{{name}}{{/casing.pascalCase}}TestLibrary } from "../src/testing/index.js"; - -export async function create{{#casing.pascalCase}}{{name}}{{/casing.pascalCase}}TestHost() { - return createTestHost({ - libraries: [{{#casing.pascalCase}}{{name}}{{/casing.pascalCase}}TestLibrary], - }); -} - -export async function create{{#casing.pascalCase}}{{name}}{{/casing.pascalCase}}TestRunner() { - const host = await create{{#casing.pascalCase}}{{name}}{{/casing.pascalCase}}TestHost(); - - return createTestWrapper(host, { - autoUsings: ["{{#casing.pascalCase}}{{name}}{{/casing.pascalCase}}"] - }); -} +import { resolvePath } from "@typespec/compiler"; +import { createTester } from "@typespec/compiler/testing"; + +export const Tester = createTester(resolvePath(import.meta.dirname, ".."), { + libraries: ["{{name}}"], +}) + .import("{{name}}") + .using("{{#casing.pascalCase}}{{name}}{{/casing.pascalCase}}"); From bc903f97def35a999f15ae1ba33539c863a2668b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 5 Feb 2026 19:31:27 +0000 Subject: [PATCH 3/7] Revert vitest imports to node:test and fix tester path resolution Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com> --- .../templates/__snapshots__/emitter-ts/test/hello.test.ts | 2 +- .../templates/__snapshots__/emitter-ts/test/test-host.ts | 8 ++------ .../__snapshots__/library-ts/test/decorators.test.ts | 2 +- .../templates/__snapshots__/library-ts/test/test-host.ts | 2 +- packages/compiler/templates/emitter-ts/test/hello.test.ts | 2 +- .../compiler/templates/emitter-ts/test/test-host.ts.mu | 8 ++------ .../templates/library-ts/test/decorators.test.ts.mu | 2 +- .../compiler/templates/library-ts/test/test-host.ts.mu | 2 +- 8 files changed, 10 insertions(+), 18 deletions(-) diff --git a/packages/compiler/templates/__snapshots__/emitter-ts/test/hello.test.ts b/packages/compiler/templates/__snapshots__/emitter-ts/test/hello.test.ts index 00d8f062a17..9bf04d106c1 100644 --- a/packages/compiler/templates/__snapshots__/emitter-ts/test/hello.test.ts +++ b/packages/compiler/templates/__snapshots__/emitter-ts/test/hello.test.ts @@ -1,5 +1,5 @@ import { strictEqual } from "node:assert"; -import { describe, it } from "vitest"; +import { describe, it } from "node:test"; import { emit } from "./test-host.js"; describe("hello", () => { diff --git a/packages/compiler/templates/__snapshots__/emitter-ts/test/test-host.ts b/packages/compiler/templates/__snapshots__/emitter-ts/test/test-host.ts index 2a0d323e463..8e62dac4d01 100644 --- a/packages/compiler/templates/__snapshots__/emitter-ts/test/test-host.ts +++ b/packages/compiler/templates/__snapshots__/emitter-ts/test/test-host.ts @@ -2,18 +2,14 @@ import { Diagnostic, resolvePath } from "@typespec/compiler"; import { expectDiagnosticEmpty } from "@typespec/compiler/testing"; import { createTester } from "@typespec/compiler/testing"; -export const Tester = createTester(resolvePath(import.meta.dirname, ".."), { +export const Tester = createTester(resolvePath(import.meta.dirname, "../.."), { libraries: ["emitter-ts"], }).emit("emitter-ts"); export async function emitWithDiagnostics( code: string ): Promise<[Record, readonly Diagnostic[]]> { - const [{ outputs }, diagnostics] = await Tester.compileAndDiagnose(code, { - compilerOptions: { - emit: ["emitter-ts"], - }, - }); + const [{ outputs }, diagnostics] = await Tester.compileAndDiagnose(code); return [outputs, diagnostics]; } diff --git a/packages/compiler/templates/__snapshots__/library-ts/test/decorators.test.ts b/packages/compiler/templates/__snapshots__/library-ts/test/decorators.test.ts index ab7e95e2f43..332167df685 100644 --- a/packages/compiler/templates/__snapshots__/library-ts/test/decorators.test.ts +++ b/packages/compiler/templates/__snapshots__/library-ts/test/decorators.test.ts @@ -1,5 +1,5 @@ import { strictEqual } from "node:assert"; -import { describe, it } from "vitest"; +import { describe, it } from "node:test"; import { expectDiagnostics, extractCursor, t } from "@typespec/compiler/testing"; import { getAlternateName } from "../src/decorators.js"; import { Tester } from "./test-host.js"; diff --git a/packages/compiler/templates/__snapshots__/library-ts/test/test-host.ts b/packages/compiler/templates/__snapshots__/library-ts/test/test-host.ts index 852a8afc8b9..75009f5369e 100644 --- a/packages/compiler/templates/__snapshots__/library-ts/test/test-host.ts +++ b/packages/compiler/templates/__snapshots__/library-ts/test/test-host.ts @@ -1,7 +1,7 @@ import { resolvePath } from "@typespec/compiler"; import { createTester } from "@typespec/compiler/testing"; -export const Tester = createTester(resolvePath(import.meta.dirname, ".."), { +export const Tester = createTester(resolvePath(import.meta.dirname, "../.."), { libraries: ["library-ts"], }) .import("library-ts") diff --git a/packages/compiler/templates/emitter-ts/test/hello.test.ts b/packages/compiler/templates/emitter-ts/test/hello.test.ts index 00d8f062a17..9bf04d106c1 100644 --- a/packages/compiler/templates/emitter-ts/test/hello.test.ts +++ b/packages/compiler/templates/emitter-ts/test/hello.test.ts @@ -1,5 +1,5 @@ import { strictEqual } from "node:assert"; -import { describe, it } from "vitest"; +import { describe, it } from "node:test"; import { emit } from "./test-host.js"; describe("hello", () => { diff --git a/packages/compiler/templates/emitter-ts/test/test-host.ts.mu b/packages/compiler/templates/emitter-ts/test/test-host.ts.mu index 70d6b7fb7a2..950a699f0fa 100644 --- a/packages/compiler/templates/emitter-ts/test/test-host.ts.mu +++ b/packages/compiler/templates/emitter-ts/test/test-host.ts.mu @@ -2,18 +2,14 @@ import { Diagnostic, resolvePath } from "@typespec/compiler"; import { expectDiagnosticEmpty } from "@typespec/compiler/testing"; import { createTester } from "@typespec/compiler/testing"; -export const Tester = createTester(resolvePath(import.meta.dirname, ".."), { +export const Tester = createTester(resolvePath(import.meta.dirname, "../.."), { libraries: ["{{name}}"], }).emit("{{name}}"); export async function emitWithDiagnostics( code: string ): Promise<[Record, readonly Diagnostic[]]> { - const [{ outputs }, diagnostics] = await Tester.compileAndDiagnose(code, { - compilerOptions: { - emit: ["{{name}}"], - }, - }); + const [{ outputs }, diagnostics] = await Tester.compileAndDiagnose(code); return [outputs, diagnostics]; } diff --git a/packages/compiler/templates/library-ts/test/decorators.test.ts.mu b/packages/compiler/templates/library-ts/test/decorators.test.ts.mu index 5c87f21401a..48129fd9917 100644 --- a/packages/compiler/templates/library-ts/test/decorators.test.ts.mu +++ b/packages/compiler/templates/library-ts/test/decorators.test.ts.mu @@ -1,5 +1,5 @@ import { strictEqual } from "node:assert"; -import { describe, it } from "vitest"; +import { describe, it } from "node:test"; import { expectDiagnostics, extractCursor, t } from "@typespec/compiler/testing"; import { getAlternateName } from "../src/decorators.js"; import { Tester } from "./test-host.js"; diff --git a/packages/compiler/templates/library-ts/test/test-host.ts.mu b/packages/compiler/templates/library-ts/test/test-host.ts.mu index a4b5aed5e7a..d9bb3fbf1b3 100644 --- a/packages/compiler/templates/library-ts/test/test-host.ts.mu +++ b/packages/compiler/templates/library-ts/test/test-host.ts.mu @@ -1,7 +1,7 @@ import { resolvePath } from "@typespec/compiler"; import { createTester } from "@typespec/compiler/testing"; -export const Tester = createTester(resolvePath(import.meta.dirname, ".."), { +export const Tester = createTester(resolvePath(import.meta.dirname, "../.."), { libraries: ["{{name}}"], }) .import("{{name}}") From be7154b8fe2c7628bb726083fa7c75487a6b309f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 5 Feb 2026 19:42:46 +0000 Subject: [PATCH 4/7] Update eslint config to latest standard with typescript-eslint package Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com> --- .../templates/__snapshots__/emitter-ts/eslint.config.js | 8 ++++++++ .../templates/__snapshots__/emitter-ts/package.json | 3 +-- .../templates/__snapshots__/library-ts/eslint.config.js | 8 ++++++++ .../templates/__snapshots__/library-ts/package.json | 3 +-- packages/compiler/templates/emitter-ts/eslint.config.js | 8 ++++++++ packages/compiler/templates/emitter-ts/package.json | 3 +-- packages/compiler/templates/library-ts/eslint.config.js | 8 ++++++++ packages/compiler/templates/library-ts/package.json | 3 +-- 8 files changed, 36 insertions(+), 8 deletions(-) diff --git a/packages/compiler/templates/__snapshots__/emitter-ts/eslint.config.js b/packages/compiler/templates/__snapshots__/emitter-ts/eslint.config.js index 75cb4f7ce3e..1bcb62d80de 100644 --- a/packages/compiler/templates/__snapshots__/emitter-ts/eslint.config.js +++ b/packages/compiler/templates/__snapshots__/emitter-ts/eslint.config.js @@ -8,4 +8,12 @@ export default tsEslint.config( }, eslint.configs.recommended, ...tsEslint.configs.recommended, + { + rules: { + "@typescript-eslint/no-unused-vars": [ + "warn", + { varsIgnorePattern: "^_", argsIgnorePattern: "^_" }, + ], + }, + }, ); diff --git a/packages/compiler/templates/__snapshots__/emitter-ts/package.json b/packages/compiler/templates/__snapshots__/emitter-ts/package.json index f9f12501c17..8231ab14f7b 100644 --- a/packages/compiler/templates/__snapshots__/emitter-ts/package.json +++ b/packages/compiler/templates/__snapshots__/emitter-ts/package.json @@ -18,8 +18,7 @@ }, "devDependencies": { "@types/node": "latest", - "@typescript-eslint/eslint-plugin": "^8.15.0", - "@typescript-eslint/parser": "^8.15.0", + "typescript-eslint": "^8.49.0", "eslint": "^9.15.0", "@typespec/compiler": "latest", "typescript": "^5.3.3", diff --git a/packages/compiler/templates/__snapshots__/library-ts/eslint.config.js b/packages/compiler/templates/__snapshots__/library-ts/eslint.config.js index 75cb4f7ce3e..1bcb62d80de 100644 --- a/packages/compiler/templates/__snapshots__/library-ts/eslint.config.js +++ b/packages/compiler/templates/__snapshots__/library-ts/eslint.config.js @@ -8,4 +8,12 @@ export default tsEslint.config( }, eslint.configs.recommended, ...tsEslint.configs.recommended, + { + rules: { + "@typescript-eslint/no-unused-vars": [ + "warn", + { varsIgnorePattern: "^_", argsIgnorePattern: "^_" }, + ], + }, + }, ); diff --git a/packages/compiler/templates/__snapshots__/library-ts/package.json b/packages/compiler/templates/__snapshots__/library-ts/package.json index 408d5aac9ae..5e2377b221b 100644 --- a/packages/compiler/templates/__snapshots__/library-ts/package.json +++ b/packages/compiler/templates/__snapshots__/library-ts/package.json @@ -19,8 +19,7 @@ }, "devDependencies": { "@types/node": "latest", - "@typescript-eslint/eslint-plugin": "^8.15.0", - "@typescript-eslint/parser": "^8.15.0", + "typescript-eslint": "^8.49.0", "@typespec/compiler": "latest", "@typespec/library-linter": "latest", "eslint": "^9.15.0", diff --git a/packages/compiler/templates/emitter-ts/eslint.config.js b/packages/compiler/templates/emitter-ts/eslint.config.js index 75cb4f7ce3e..1bcb62d80de 100644 --- a/packages/compiler/templates/emitter-ts/eslint.config.js +++ b/packages/compiler/templates/emitter-ts/eslint.config.js @@ -8,4 +8,12 @@ export default tsEslint.config( }, eslint.configs.recommended, ...tsEslint.configs.recommended, + { + rules: { + "@typescript-eslint/no-unused-vars": [ + "warn", + { varsIgnorePattern: "^_", argsIgnorePattern: "^_" }, + ], + }, + }, ); diff --git a/packages/compiler/templates/emitter-ts/package.json b/packages/compiler/templates/emitter-ts/package.json index 96ca29f0f73..1c9baaf7d2c 100644 --- a/packages/compiler/templates/emitter-ts/package.json +++ b/packages/compiler/templates/emitter-ts/package.json @@ -18,8 +18,7 @@ }, "devDependencies": { "@types/node": "latest", - "@typescript-eslint/eslint-plugin": "^8.15.0", - "@typescript-eslint/parser": "^8.15.0", + "typescript-eslint": "^8.49.0", "eslint": "^9.15.0", "@typespec/compiler": "latest", "typescript": "^5.3.3", diff --git a/packages/compiler/templates/library-ts/eslint.config.js b/packages/compiler/templates/library-ts/eslint.config.js index 75cb4f7ce3e..1bcb62d80de 100644 --- a/packages/compiler/templates/library-ts/eslint.config.js +++ b/packages/compiler/templates/library-ts/eslint.config.js @@ -8,4 +8,12 @@ export default tsEslint.config( }, eslint.configs.recommended, ...tsEslint.configs.recommended, + { + rules: { + "@typescript-eslint/no-unused-vars": [ + "warn", + { varsIgnorePattern: "^_", argsIgnorePattern: "^_" }, + ], + }, + }, ); diff --git a/packages/compiler/templates/library-ts/package.json b/packages/compiler/templates/library-ts/package.json index 2a104d5c60b..456e579ed0a 100644 --- a/packages/compiler/templates/library-ts/package.json +++ b/packages/compiler/templates/library-ts/package.json @@ -19,8 +19,7 @@ }, "devDependencies": { "@types/node": "latest", - "@typescript-eslint/eslint-plugin": "^8.15.0", - "@typescript-eslint/parser": "^8.15.0", + "typescript-eslint": "^8.49.0", "@typespec/compiler": "latest", "@typespec/library-linter": "latest", "eslint": "^9.15.0", From 6f97eac0172a11784ee318e826d432fc188d56bf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 5 Feb 2026 20:02:25 +0000 Subject: [PATCH 5/7] Replace tsEslint.config with defineConfig from eslint/config Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com> --- .../templates/__snapshots__/emitter-ts/eslint.config.js | 3 ++- .../templates/__snapshots__/library-ts/eslint.config.js | 3 ++- packages/compiler/templates/emitter-ts/eslint.config.js | 3 ++- packages/compiler/templates/library-ts/eslint.config.js | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/compiler/templates/__snapshots__/emitter-ts/eslint.config.js b/packages/compiler/templates/__snapshots__/emitter-ts/eslint.config.js index 1bcb62d80de..430df9c59ea 100644 --- a/packages/compiler/templates/__snapshots__/emitter-ts/eslint.config.js +++ b/packages/compiler/templates/__snapshots__/emitter-ts/eslint.config.js @@ -1,8 +1,9 @@ // @ts-check import eslint from "@eslint/js"; +import { defineConfig } from "eslint/config"; import tsEslint from "typescript-eslint"; -export default tsEslint.config( +export default defineConfig( { ignores: ["**/dist/**/*", "**/.temp/**/*"], }, diff --git a/packages/compiler/templates/__snapshots__/library-ts/eslint.config.js b/packages/compiler/templates/__snapshots__/library-ts/eslint.config.js index 1bcb62d80de..430df9c59ea 100644 --- a/packages/compiler/templates/__snapshots__/library-ts/eslint.config.js +++ b/packages/compiler/templates/__snapshots__/library-ts/eslint.config.js @@ -1,8 +1,9 @@ // @ts-check import eslint from "@eslint/js"; +import { defineConfig } from "eslint/config"; import tsEslint from "typescript-eslint"; -export default tsEslint.config( +export default defineConfig( { ignores: ["**/dist/**/*", "**/.temp/**/*"], }, diff --git a/packages/compiler/templates/emitter-ts/eslint.config.js b/packages/compiler/templates/emitter-ts/eslint.config.js index 1bcb62d80de..430df9c59ea 100644 --- a/packages/compiler/templates/emitter-ts/eslint.config.js +++ b/packages/compiler/templates/emitter-ts/eslint.config.js @@ -1,8 +1,9 @@ // @ts-check import eslint from "@eslint/js"; +import { defineConfig } from "eslint/config"; import tsEslint from "typescript-eslint"; -export default tsEslint.config( +export default defineConfig( { ignores: ["**/dist/**/*", "**/.temp/**/*"], }, diff --git a/packages/compiler/templates/library-ts/eslint.config.js b/packages/compiler/templates/library-ts/eslint.config.js index 1bcb62d80de..430df9c59ea 100644 --- a/packages/compiler/templates/library-ts/eslint.config.js +++ b/packages/compiler/templates/library-ts/eslint.config.js @@ -1,8 +1,9 @@ // @ts-check import eslint from "@eslint/js"; +import { defineConfig } from "eslint/config"; import tsEslint from "typescript-eslint"; -export default tsEslint.config( +export default defineConfig( { ignores: ["**/dist/**/*", "**/.temp/**/*"], }, From 46659d8baf7c829df7509bc506a2fd02f91db4d3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 5 Feb 2026 20:12:12 +0000 Subject: [PATCH 6/7] Add changelog for init templates migration Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com> --- ...e-init-templates-testing-framework-2026-1-5-20-11-37.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .chronus/changes/copilot-update-init-templates-testing-framework-2026-1-5-20-11-37.md diff --git a/.chronus/changes/copilot-update-init-templates-testing-framework-2026-1-5-20-11-37.md b/.chronus/changes/copilot-update-init-templates-testing-framework-2026-1-5-20-11-37.md new file mode 100644 index 00000000000..cf2f9c23e28 --- /dev/null +++ b/.chronus/changes/copilot-update-init-templates-testing-framework-2026-1-5-20-11-37.md @@ -0,0 +1,7 @@ +--- +changeKind: internal +packages: + - "@typespec/compiler" +--- + +Update init templates to use createTester API and modern ESLint configuration \ No newline at end of file From 7ccf337c902f62f6ce9d816a57b67edc2769796b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Feb 2026 14:53:36 +0000 Subject: [PATCH 7/7] Fix library-ts template tests to work with createTester Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com> --- .../library-ts/test/decorators.test.ts | 20 +++++++++++-------- .../library-ts/test/test-host.ts | 4 +--- .../library-ts/test/decorators.test.ts.mu | 20 +++++++++++-------- .../templates/library-ts/test/test-host.ts.mu | 4 +--- 4 files changed, 26 insertions(+), 22 deletions(-) diff --git a/packages/compiler/templates/__snapshots__/library-ts/test/decorators.test.ts b/packages/compiler/templates/__snapshots__/library-ts/test/decorators.test.ts index 332167df685..51ee4d92418 100644 --- a/packages/compiler/templates/__snapshots__/library-ts/test/decorators.test.ts +++ b/packages/compiler/templates/__snapshots__/library-ts/test/decorators.test.ts @@ -1,20 +1,23 @@ import { strictEqual } from "node:assert"; import { describe, it } from "node:test"; -import { expectDiagnostics, extractCursor, t } from "@typespec/compiler/testing"; +import type { Operation, Program } from "@typespec/compiler"; +import { expectDiagnostics } from "@typespec/compiler/testing"; import { getAlternateName } from "../src/decorators.js"; import { Tester } from "./test-host.js"; describe("decorators", () => { describe("@alternateName", () => { it("set alternate name on operation", async () => { - const { test, program } = await Tester.compile(t.code` - @alternateName("bar") ${t.op("test")}(): void; - `); + const { test, program } = (await Tester.compile(` + using LibraryTs; + @alternateName("bar") @test op test(): void; + `)) as unknown as { test: Operation; program: Program }; strictEqual(getAlternateName(program, test), "bar"); }); it("emit diagnostic if not used on an operation", async () => { const diagnostics = await Tester.diagnose(` + using LibraryTs; @alternateName("bar") model Test {} `); expectDiagnostics(diagnostics, { @@ -26,13 +29,14 @@ describe("decorators", () => { it("emit diagnostic if using banned name", async () => { - const {pos, source} = extractCursor(`@alternateName(┆"banned") op test(): void;`) - const diagnostics = await Tester.diagnose(source); + const diagnostics = await Tester.diagnose(` + using LibraryTs; + @alternateName("banned") op test(): void; + `); expectDiagnostics(diagnostics, { severity: "error", code: "library-ts/banned-alternate-name", - message: `Banned alternate name "banned".`, - pos + message: `Banned alternate name "banned".` }) }); }); diff --git a/packages/compiler/templates/__snapshots__/library-ts/test/test-host.ts b/packages/compiler/templates/__snapshots__/library-ts/test/test-host.ts index 75009f5369e..588a223c42b 100644 --- a/packages/compiler/templates/__snapshots__/library-ts/test/test-host.ts +++ b/packages/compiler/templates/__snapshots__/library-ts/test/test-host.ts @@ -3,7 +3,5 @@ import { createTester } from "@typespec/compiler/testing"; export const Tester = createTester(resolvePath(import.meta.dirname, "../.."), { libraries: ["library-ts"], -}) - .import("library-ts") - .using("LibraryTs"); +}).import("library-ts"); diff --git a/packages/compiler/templates/library-ts/test/decorators.test.ts.mu b/packages/compiler/templates/library-ts/test/decorators.test.ts.mu index 48129fd9917..f79480f86f2 100644 --- a/packages/compiler/templates/library-ts/test/decorators.test.ts.mu +++ b/packages/compiler/templates/library-ts/test/decorators.test.ts.mu @@ -1,20 +1,23 @@ import { strictEqual } from "node:assert"; import { describe, it } from "node:test"; -import { expectDiagnostics, extractCursor, t } from "@typespec/compiler/testing"; +import type { Operation, Program } from "@typespec/compiler"; +import { expectDiagnostics } from "@typespec/compiler/testing"; import { getAlternateName } from "../src/decorators.js"; import { Tester } from "./test-host.js"; describe("decorators", () => { describe("@alternateName", () => { it("set alternate name on operation", async () => { - const { test, program } = await Tester.compile(t.code` - @alternateName("bar") ${t.op("test")}(): void; - `); + const { test, program } = (await Tester.compile(` + using {{#casing.pascalCase}}{{name}}{{/casing.pascalCase}}; + @alternateName("bar") @test op test(): void; + `)) as unknown as { test: Operation; program: Program }; strictEqual(getAlternateName(program, test), "bar"); }); it("emit diagnostic if not used on an operation", async () => { const diagnostics = await Tester.diagnose(` + using {{#casing.pascalCase}}{{name}}{{/casing.pascalCase}}; @alternateName("bar") model Test {} `); expectDiagnostics(diagnostics, { @@ -26,13 +29,14 @@ describe("decorators", () => { it("emit diagnostic if using banned name", async () => { - const {pos, source} = extractCursor(`@alternateName(┆"banned") op test(): void;`) - const diagnostics = await Tester.diagnose(source); + const diagnostics = await Tester.diagnose(` + using {{#casing.pascalCase}}{{name}}{{/casing.pascalCase}}; + @alternateName("banned") op test(): void; + `); expectDiagnostics(diagnostics, { severity: "error", code: "{{name}}/banned-alternate-name", - message: `Banned alternate name "banned".`, - pos + message: `Banned alternate name "banned".` }) }); }); diff --git a/packages/compiler/templates/library-ts/test/test-host.ts.mu b/packages/compiler/templates/library-ts/test/test-host.ts.mu index d9bb3fbf1b3..e87ec478d83 100644 --- a/packages/compiler/templates/library-ts/test/test-host.ts.mu +++ b/packages/compiler/templates/library-ts/test/test-host.ts.mu @@ -3,7 +3,5 @@ import { createTester } from "@typespec/compiler/testing"; export const Tester = createTester(resolvePath(import.meta.dirname, "../.."), { libraries: ["{{name}}"], -}) - .import("{{name}}") - .using("{{#casing.pascalCase}}{{name}}{{/casing.pascalCase}}"); +}).import("{{name}}");