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
Comment thread
xirzec marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
changeKind: internal
packages:
- "@azure-tools/typespec-ts"
---

Include the fast `test-next` typespec-ts unit suite in the repo-wide vitest run as a cross-package smoke net, while keeping the heavier `unit-modular` suite and the Spector end-to-end integration project out of it. Those still run in the dedicated typespec-ts CI job, which now also triggers on the TypeSpec libraries typespec-ts emits from (`typespec-client-generator-core` and `typespec-azure-resource-manager`) so cross-package emit regressions are still caught. Scenario paths in the modular-unit suite now resolve against the package root so they no longer depend on the current working directory.
2 changes: 2 additions & 0 deletions .github/workflows/ci-typescript.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ on:
- release/*
paths:
- "packages/typespec-ts/**"
- "packages/typespec-client-generator-core/**"
- "packages/typespec-azure-resource-manager/**"
- ".github/workflows/ci-typescript.yml"
merge_group:

Expand Down
18 changes: 15 additions & 3 deletions packages/typespec-ts/test/modular-unit/scenario-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { afterAll, assert, describe, it } from "vitest";
import { readdirSync, readFileSync, statSync, writeFileSync } from "fs";
import path from "path";
import { format } from "prettier";
import { fileURLToPath } from "url";
import { parse as loadYaml } from "yaml";
import { prettierTypeScriptOptions } from "../../src/lib.js";
import {
Expand All @@ -16,7 +17,15 @@ import {
} from "../util/emit-util.js";
import { assertEqualContent, clearCompileCache, ExampleJson } from "../util/test-util.js";

export const SCENARIOS_LOCATION = "./test/modular-unit/scenarios";
// Anchor scenario paths to the package root (derived from this module's URL)
// rather than process.cwd(). This keeps the modular-unit suite working both when
// run from this package (cwd = packages/typespec-ts) and when it is picked up by
// the repo-wide vitest run (cwd = repo root). This file lives at
// `<package>/test/modular-unit/scenario-runner.ts`, so the package root is two
// directories up.
export const PACKAGE_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");

export const SCENARIOS_LOCATION = path.resolve(PACKAGE_ROOT, "test/modular-unit/scenarios");

const SCENARIOS_UPDATE = process.env["SCENARIOS_UPDATE"] === "true";

Expand Down Expand Up @@ -220,8 +229,11 @@ const OUTPUT_CODE_BLOCK_TYPES: Record<string, EmitterFunction> = {
* themselves leaf directories with their own generated test files.
*/
export function describeScenarioDir(location: string): void {
for (const child of readdirSync(location)) {
const fullPath = path.join(location, child);
// `location` is package-root-relative (as emitted by gen:scenario-suites);
// resolve it against the package root so it is independent of process.cwd().
const resolved = path.resolve(PACKAGE_ROOT, location);
for (const child of readdirSync(resolved)) {
const fullPath = path.join(resolved, child);
if (statSync(fullPath).isFile() && child.endsWith(".md")) {
describeScenarioFile(fullPath);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { readdirSync } from "fs";
import path from "path";
import { assert, it } from "vitest";
import { getLeafScenarioDirs } from "./scenario-runner.js";
import { getLeafScenarioDirs, PACKAGE_ROOT } from "./scenario-runner.js";

const SUITES_DIR = path.join("test", "modular-unit", "scenario-suites");
const SUITES_DIR = path.resolve(PACKAGE_ROOT, "test", "modular-unit", "scenario-suites");

function suiteFileName(relDir: string): string {
return relDir.split(/[\\/]/).join("__") + ".test.ts";
Expand Down
44 changes: 37 additions & 7 deletions packages/typespec-ts/vitest.config.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,55 @@
import { defineConfig } from "vitest/config";

// The repo-wide run (root `vitest.config.ts` / `vitest.config.fast.ts`) picks up
// this file as a single project and — in Vitest 4 — ignores the nested `projects`,
// using only these top-level `test` options. We deliberately include ONLY the fast
// `test-next` suite there: it is a quick cross-package smoke net (~14s). The heavy
// `unit-modular` suite (~150s of TypeSpec compiles) is intentionally excluded from
// the repo-wide run to keep it fast; it still runs in full via `pnpm unit-test`
// locally and in the dedicated `ci-typescript.yml` job — which also triggers on
// the TypeSpec libraries typespec-ts emits from (`typespec-client-generator-core`
// and `typespec-azure-resource-manager`), so cross-package emit regressions are
// still caught. The Spector end-to-end `integration-azure-modular`
// project needs generated clients and a running test server, so it too is excluded
// here and runs via its own script / the dedicated e2e CI job.
const repoWideInclude = ["test-next/**/*.test.ts"];

// The `test-next` suite includes ts-morph integration tests that invoke the
// TypeScript type checker (e.g. `binder.test.ts`). These are sub-second when run
// on their own, but in the repo-wide run every package's tests execute
// concurrently, and under that CPU/memory pressure they can exceed Vitest's 5s
// default. Double the default to give some headroom without masking a genuine
// hang. Applied both at the top level (used by the single-project repo-wide run)
// and on the `test-next` project (used by `pnpm test-next` / `--project
// test-next`) so the timeout holds either way.
const testNextTimeout = 10_000;

// Settings the `unit-modular` suites need (heavy TypeSpec compiles): no per-test
// timeout and a raised heap. In Vitest 4 `poolOptions` was removed — its
// sub-options (here `execArgv`) are now top-level `test.*` fields, set per-project.
const unitModularPool = {
testTimeout: 0,
pool: "forks" as const,
execArgv: ["--max-old-space-size=1024"],
};

export default defineConfig({
test: {
include: repoWideInclude,
testTimeout: testNextTimeout,
projects: [
{
test: {
name: "test-next",
include: ["test-next/**/*.test.ts"],
testTimeout: testNextTimeout,
},
},
{
test: {
name: "unit-modular",
include: ["test/modular-unit/**/*.test.ts"],
testTimeout: 0,
pool: "forks",
poolOptions: {
forks: {
execArgv: ["--max-old-space-size=1024"],
},
},
...unitModularPool,
},
},
{
Expand Down
5 changes: 1 addition & 4 deletions vitest.config.fast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@ export default mergeConfig(
defineConfig({
test: {
// Exclude core packages so we can only run test for this repo
projects: [
"packages/!(typespec-ts)/vitest.config.ts",
"packages/!(typespec-ts)/vitest.config.mts",
],
projects: ["packages/*/vitest.config.ts", "packages/*/vitest.config.mts"],
},
}),
);
4 changes: 2 additions & 2 deletions vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ export default mergeConfig(
defineConfig({
test: {
projects: [
"packages/!(typespec-ts)/vitest.config.ts",
"packages/*/vitest.config.ts",
"core/packages/*/vitest.config.ts",
"packages/!(typespec-ts)/vitest.config.mts",
"packages/*/vitest.config.mts",
"core/packages/*/vitest.config.mts",
],
},
Expand Down
Loading