Skip to content
Merged
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
6 changes: 3 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ This is a monorepo managed with `pnpm`. It produces a CLI tool for generating hi
- **Install**: `pnpm install`
- **Build**: `pnpm build` (generates validators, bundles packages, and runs `tsc -b`).
- **Lint/Format**: `pnpm lint` (uses Biome). For CI-style checks, use `pnpm ci-lint`.
- **Unit Tests**: `pnpm test` (uses Jest). For coverage, use `pnpm ci-test`.
- **Unit Tests**: `pnpm test` (uses Vitest). For coverage, use `pnpm ci-test`.
- **Integration Tests**:
- Generate: `pnpm integration:generate`
- Validate/Build: `pnpm integration:validate`
Expand All @@ -40,9 +40,9 @@ This is a monorepo managed with `pnpm`. It produces a CLI tool for generating hi
## Testing Standards

- **Unit Testing**: Tests are co-located with source code (`.spec.ts`).
- **Jest Globals**: You MUST explicitly import Jest globals in test files:
- **Vitest Globals**: You MUST explicitly import Vitest globals in test files:
```typescript
import {describe, expect, it} from "@jest/globals"
import {describe, expect, it} from "vitest"
```
- **Regression**: Always ensure `pnpm integration:validate` passes after changes to generation logic.

Expand Down
4 changes: 2 additions & 2 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ graph TD
### Invariants
- **No `npx`**: Always use `pnpm run` or `pnpm exec`.
- **Read-Only Generation**: Never manually edit files in `src/generated/` directories; they are overwritten during generation.
- **Jest Globals**: Always explicitly import Jest globals (`describe`, `it`, `expect`) from `@jest/globals`.
- **Vitest Globals**: Always explicitly import vitest globals (`describe`, `it`, `expect`) from `vitest`.

### Conventions
- **Co-location**: Unit tests (`*.spec.ts`) are co-located with the source code they test. Use explicit jest imports (`import {describe, it, expect} from "@jest/globals"`).
- **Co-location**: Unit tests (`*.spec.ts`) are co-located with the source code they test. Use explicit vitest imports (`import {describe, it, expect} from "vitest"`).
- **Import Extensions**: Use `.ts` extensions in imports (e.g., `import {foo} from "./foo.ts"`) to support ESM.
- **Dependency Migration**: Prefer `pnpm` workspace references (e.g., `"@nahkies/typescript-common-runtime": "workspace:*"`).

Expand Down
12 changes: 0 additions & 12 deletions e2e/jest.config.cjs

This file was deleted.

7 changes: 3 additions & 4 deletions e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"clean": "rm -rf ./dist && rm -rf ./src/generated",
"generate": "./scripts/generate.sh",
"build": "tsc -p ./tsconfig.json",
"test": "jest",
"test": "vitest run",
"start": "node ./dist/index.js"
},
"dependencies": {
Expand All @@ -25,12 +25,11 @@
"zod": "^4.3.6"
},
"devDependencies": {
"@jest/globals": "^30.4.1",
"@nahkies/openapi-code-generator": "workspace:*",
"@types/express": "^5.0.6",
"@types/koa": "^3.0.3",
"expect": "^30.4.1",
"jest": "^30.4.2",
"typescript": "^6.0.3"
"typescript": "^6.0.3",
"vitest": "^4.0.11"
}
}
2 changes: 1 addition & 1 deletion e2e/src/index.axios.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type {Server} from "node:http"
import {afterAll, beforeAll, describe, expect, it} from "@jest/globals"
import type {AxiosError} from "axios"
import {afterAll, beforeAll, describe, expect, it} from "vitest"
import {
ApiClient,
E2ETestClientServers,
Expand Down
9 changes: 5 additions & 4 deletions e2e/src/index.fetch.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import {
describe,
expect,
it,
jest,
} from "@jest/globals"
type MockedFunction,
vi,
} from "vitest"
import {
ApiClient,
E2ETestClientServers,
Expand Down Expand Up @@ -569,10 +570,10 @@ describe.each(
})

describe("route matching", () => {
let logSpy: jest.SpiedFunction<typeof console.log>
let logSpy: MockedFunction<typeof console.log>

beforeEach(() => {
logSpy = jest.spyOn(console, "log").mockImplementation(() => {})
logSpy = vi.spyOn(console, "log").mockImplementation(() => {})
})

afterEach(() => {
Expand Down
10 changes: 0 additions & 10 deletions e2e/src/jest.d.ts

This file was deleted.

2 changes: 1 addition & 1 deletion e2e/src/test-utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Blob} from "node:buffer"
import {expect} from "@jest/globals"
import {AsymmetricMatcher} from "expect"
import {expect} from "vitest"

class NumberInRange extends AsymmetricMatcher<number> {
constructor(
Expand Down
10 changes: 10 additions & 0 deletions e2e/src/vitest.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type {CustomMatcherResult} from "expect"

declare module "vitest" {
interface Assertion<T = any> {

Check warning on line 4 in e2e/src/vitest.d.ts

View workflow job for this annotation

GitHub Actions / build (24.x)

lint/suspicious/noExplicitAny

Unexpected any. Specify a different type.

Check warning on line 4 in e2e/src/vitest.d.ts

View workflow job for this annotation

GitHub Actions / build (22.x)

lint/suspicious/noExplicitAny

Unexpected any. Specify a different type.

Check warning on line 4 in e2e/src/vitest.d.ts

View workflow job for this annotation

GitHub Actions / build (26.x)

lint/suspicious/noExplicitAny

Unexpected any. Specify a different type.
toEqualBlob(expected: Blob): Promise<CustomMatcherResult>
}
interface AsymmetricMatchersContaining {
toEqualBlob(expected: Blob): Promise<CustomMatcherResult>
}
}
9 changes: 9 additions & 0 deletions e2e/vitest.config.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {defineConfig} from "vitest/config"
import {baseTestConfig} from "../vitest.base"

export default defineConfig({
test: {
...baseTestConfig.test,
name: "e2e",
},
})
15 changes: 0 additions & 15 deletions jest.base.js

This file was deleted.

12 changes: 0 additions & 12 deletions jest.config.js

This file was deleted.

14 changes: 0 additions & 14 deletions jest/reporter.js

This file was deleted.

12 changes: 5 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@
"build": "node ./scripts/generate-ajv-validator.js && pnpm -r --workspace-concurrency=4 run bundle && tsc -b tsconfig.json",
"build:docs": "pnpm --filter @nahkies/openapi-code-generator-documentation run build",
"build:watch": "tsc -b tsconfig.json -w",
"test": "jest",
"test": "vitest run",
"integration:clean": "pnpm --filter @integration/* run clean",
"integration:generate": "node ./scripts/generate.mjs",
"integration:validate": "pnpm -r --filter @integration/* --workspace-concurrency=2 run validate",
"e2e:generate": "pnpm --filter e2e run clean && pnpm --filter e2e run generate",
"e2e:validate": "pnpm --filter e2e run build && pnpm --filter e2e run test",
"ci-test": "jest --coverage",
"ci-test": "vitest run --coverage",
"ci-lint": "biome ci .",
"ci-pipeline": "./scripts/ci-pipeline.sh",
"ci-pipeline:fast": "FAST=1 ./scripts/ci-pipeline.sh",
Expand All @@ -44,26 +44,24 @@
"@biomejs/js-api": "4.0.0",
"@biomejs/wasm-nodejs": "2.4.15",
"@commander-js/extra-typings": "^14.0.0",
"@jest/reporters": "^30.4.1",
"@swc/core": "^1.15.40",
"@swc/jest": "^0.2.39",
"@tsconfig/node24": "^24.0.4",
"@tsconfig/strictest": "^2.0.8",
"@types/node": "^22.19.17",
"@vitest/coverage-v8": "4.1.7",
"ajv": "^8.20.0",
"ajv-draft-04": "^1.0.0",
"ajv-formats": "^3.0.1",
"commander": "^14.0.3",
"husky": "^9.1.7",
"jest": "^30.4.2",
"json5": "^2.2.3",
"lerna": "^9.0.7",
"lint-staged": "^17.0.5",
"prettier": "^3.8.3",
"publint": "^0.3.21",
"remark": "^15.0.1",
"remark-toc": "^9.0.0",
"typescript": "^6.0.3"
"typescript": "^6.0.3",
"vitest": "^4.0.11"
},
"workspaces": [
"packages/*",
Expand Down
12 changes: 0 additions & 12 deletions packages/openapi-code-generator/jest.config.cjs

This file was deleted.

6 changes: 3 additions & 3 deletions packages/openapi-code-generator/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,13 @@
"clean": "rm -rf ./dist && rm -f tsconfig.tsbuildinfo",
"build": "tsc -p ./tsconfig.json",
"bundle": "tsdown",
"test": "jest"
"test": "vitest run"
},
"devDependencies": {
"@azure-tools/typespec-autorest": "0.68.0",
"@azure-tools/typespec-azure-core": "0.68.0",
"@azure-tools/typespec-azure-resource-manager": "0.68.0",
"@azure-tools/typespec-client-generator-core": "0.68.0",
"@jest/globals": "^30.4.1",
"@nahkies/typescript-common-runtime": "workspace:^",
"@types/js-yaml": "^4.0.9",
"@types/lodash": "^4.17.24",
Expand All @@ -82,7 +81,8 @@
"@typespec/xml": "0.82.0",
"joi": "^18.2.1",
"tsdown": "^0.22.0",
"tsx": "^4.22.3"
"tsx": "^4.22.3",
"vitest": "^4.0.12"
},
"dependencies": {
"@biomejs/biome": "2.4.15",
Expand Down
2 changes: 1 addition & 1 deletion packages/openapi-code-generator/src/core/cli-utils.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {describe, expect, it} from "@jest/globals"
import {describe, expect, it} from "vitest"
import {
boolParser,
optionalBoolParser,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {describe, expect, it} from "@jest/globals"
import {describe, expect, it} from "vitest"
import {
createTestInputFromYamlString,
testVersions,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {describe, expect, it} from "@jest/globals"
import {describe, expect, it} from "vitest"
import {
type GenericLoaderRequestHeaders,
headersForRemoteUri,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {describe, expect, it} from "@jest/globals"
import {describe, expect, it} from "vitest"
import {normalizeRef, pathFromRef} from "./openapi-loader.ts"

describe("core/openapi-loader", () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import path from "node:path"
import {describe, expect, it} from "@jest/globals"
import {describe, expect, it} from "vitest"
import {NodeFsAdaptor} from "../file-system/node-fs-adaptor.ts"
import {loadPackageJson} from "./package.json.loader.ts"

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {describe, expect, it, jest} from "@jest/globals"
import {describe, expect, it, vi} from "vitest"
import {WebFsAdaptor} from "../file-system/web-fs-adaptor.ts"
import {loadTsConfigCompilerOptions} from "./tsconfig.loader.ts"

Expand Down Expand Up @@ -108,7 +108,7 @@ describe("core/loaders/tsconfig.loader", () => {
}),
})

const spy = jest
const spy = vi
.spyOn(fs, "readFile")
.mockRejectedValue(new Error("EACCES: permission denied"))

Expand Down
39 changes: 26 additions & 13 deletions packages/openapi-code-generator/src/core/logger.spec.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,49 @@
import {afterAll, beforeEach, describe, expect, it, jest} from "@jest/globals"
import {
afterAll,
afterEach,
beforeEach,
describe,
expect,
it,
type Mock,
vi,
} from "vitest"
import {Logger} from "./logger.ts"

describe("Logger", () => {
let sink: {info: jest.Mock; warn: jest.Mock; error: jest.Mock}
let sink: {info: Mock; warn: Mock; error: Mock}

beforeEach(() => {
sink = {
info: jest.fn(),
warn: jest.fn(),
error: jest.fn(),
info: vi.fn(),
warn: vi.fn(),
error: vi.fn(),
}
})

afterEach(() => {
vi.unstubAllEnvs()
})

afterAll(() => {
jest.restoreAllMocks()
vi.restoreAllMocks()
})

it("should include color escape sequences by default (assuming TTY)", () => {
vi.stubEnv("NO_COLOR", undefined)
vi.stubEnv("NODE_DISABLE_COLORS", undefined)
vi.stubEnv("TERM", "xterm")
const logger = new Logger(true, undefined, sink)

logger.warn("test message")

expect(sink.warn).toHaveBeenCalledWith(
expect.stringContaining("\x1b[33m[warn]\x1b[0m test message"),
expect.stringContaining("\x1b[33m[warn]\x1b[0m test message "),
)
})

it("should strip color escape sequences when NO_COLOR is set", () => {
jest.replaceProperty(process, "env", {...process.env, NO_COLOR: "1"})
vi.stubEnv("NO_COLOR", "1")
const logger = new Logger(true, undefined, sink)

logger.warn("test message")
Expand All @@ -36,10 +52,7 @@ describe("Logger", () => {
})

it("should strip color escape sequences when NODE_DISABLE_COLORS is set", () => {
jest.replaceProperty(process, "env", {
...process.env,
NODE_DISABLE_COLORS: "1",
})
vi.stubEnv("NODE_DISABLE_COLORS", "1")
const logger = new Logger(true, undefined, sink)

logger.warn("test message")
Expand All @@ -48,7 +61,7 @@ describe("Logger", () => {
})

it("should strip color escape sequences when TERM is dumb", () => {
jest.replaceProperty(process, "env", {...process.env, TERM: "dumb"})
vi.stubEnv("TERM", "dumb")
const logger = new Logger(true, undefined, sink)

logger.warn("test message")
Expand Down
Loading