Skip to content

Commit e48801d

Browse files
committed
chore(repo): setup e2e tests for cli
1 parent be2a61a commit e48801d

File tree

13 files changed

+1105
-11
lines changed

13 files changed

+1105
-11
lines changed

justfile

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,18 @@ ready:
77
just build
88
just test
99

10-
build: build-core
11-
pnpm --filter @oxc-node/cli build
10+
build: build-core build-cli
1211
pnpm install
1312

13+
build-cli: build-core
14+
pnpm --filter @oxc-node/cli build
15+
1416
build-core:
1517
pnpm --filter @oxc-node/core build
1618
pnpm --filter @oxc-node/core export-oxc-runtime
1719

18-
test:
19-
pnpm test
20+
test: test-cli
21+
22+
23+
test-cli: build-cli
24+
pnpm --filter @oxc-node/cli-tests test
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Test that oxnode can execute TypeScript files directly
2+
const message: string = '!__E2E_OK__!'
3+
4+
interface TestResult {
5+
success: boolean
6+
value: number
7+
}
8+
9+
const result: TestResult = {
10+
success: true,
11+
value: 42,
12+
} as const
13+
14+
if (result.success) {
15+
console.log(message)
16+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"name": "basic-ts-fixture",
3+
"version": "0.0.0",
4+
"private": true,
5+
"type": "module"
6+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import path from 'node:path'
2+
import { fileURLToPath } from 'node:url'
3+
import { describe, expect, it } from 'vitest'
4+
import { OxnodeCLI } from '../src/invoke-cli.js'
5+
6+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
7+
const FIXTURE_PATH = path.resolve(__dirname, '../e2e-fixtures/basic-ts')
8+
9+
describe('basic-ts fixture', () => {
10+
it('should execute TypeScript file directly', () => {
11+
const [exitCode, logs] = OxnodeCLI()
12+
.setCwd(FIXTURE_PATH)
13+
.invoke(['index.ts'])
14+
15+
expect(exitCode).toBe(0)
16+
logs.should.contain('!__E2E_OK__!')
17+
})
18+
})
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { OxnodeCLI } from '../src/invoke-cli.js'
3+
4+
describe('oxnode CLI', () => {
5+
it('should show help when --help flag is passed', () => {
6+
const [exitCode, logs] = OxnodeCLI().invoke(['--help'])
7+
8+
expect(exitCode).toBe(0)
9+
logs.should.contain('oxnode')
10+
logs.should.contain('Run a script with oxc transformer and oxc-resolver')
11+
})
12+
13+
it('should show version when --version flag is passed', () => {
14+
const [exitCode, logs] = OxnodeCLI().invoke(['--version'])
15+
16+
expect(exitCode).toBe(0)
17+
logs.should.contain('0.0.')
18+
})
19+
})

packages/cli/tests/package.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "@oxc-node/cli-tests",
3+
"version": "0.0.0",
4+
"private": true,
5+
"type": "module",
6+
"scripts": {
7+
"test": "vitest run"
8+
},
9+
"devDependencies": {
10+
"@oxc-node/cli": "workspace:*",
11+
"@oxc-node/core": "workspace:*",
12+
"@types/node": "^24.1.0",
13+
"execa": "^9.6.0",
14+
"strip-ansi": "^7.1.0",
15+
"vitest": "^2.1.8"
16+
}
17+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { execaSync } from 'execa'
2+
import path from 'node:path'
3+
import { fileURLToPath } from 'node:url'
4+
import stripAnsi from 'strip-ansi'
5+
import { createLogsMatcher, type LogsMatcher } from './matchers.js'
6+
7+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
8+
9+
// Path to the built CLI binary
10+
const CLI_PATH = path.resolve(__dirname, '../../../cli/dist/index.js')
11+
12+
export interface OxnodeCLI {
13+
invoke: (args: string[]) => [number, LogsMatcher]
14+
setCwd: (cwd: string) => OxnodeCLI
15+
}
16+
17+
export function OxnodeCLI(): OxnodeCLI {
18+
let workingDirectory = process.cwd()
19+
20+
const setCwd = (cwd: string): OxnodeCLI => {
21+
workingDirectory = cwd
22+
return api
23+
}
24+
25+
const invoke = (args: string[]): [number, LogsMatcher] => {
26+
try {
27+
const result = execaSync('node', [CLI_PATH, ...args], {
28+
cwd: workingDirectory,
29+
env: {
30+
...process.env,
31+
NODE_ENV: 'production',
32+
},
33+
all: true,
34+
reject: false,
35+
})
36+
37+
const output = stripAnsi(result.all || '')
38+
const exitCode = result.exitCode
39+
40+
return [exitCode, createLogsMatcher(output)]
41+
} catch (error) {
42+
// If execa throws an error, capture it
43+
const err = error as { all?: string; exitCode?: number }
44+
const output = stripAnsi(err.all || '')
45+
const exitCode = err.exitCode || 1
46+
47+
return [exitCode, createLogsMatcher(output)]
48+
}
49+
}
50+
51+
const api: OxnodeCLI = {
52+
invoke,
53+
setCwd,
54+
}
55+
56+
return api
57+
}

packages/cli/tests/src/matchers.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { expect } from 'vitest'
2+
3+
export interface LogsMatcher {
4+
logOutput: () => void
5+
should: {
6+
contain: (expected: string) => void
7+
not: {
8+
contain: (expected: string) => void
9+
}
10+
}
11+
}
12+
13+
export function createLogsMatcher(output: string): LogsMatcher {
14+
return {
15+
logOutput: () => {
16+
console.log('=== CLI Output ===')
17+
console.log(output)
18+
console.log('=================')
19+
},
20+
should: {
21+
contain: (expected: string) => {
22+
expect(output).toContain(expected)
23+
},
24+
not: {
25+
contain: (expected: string) => {
26+
expect(output).not.toContain(expected)
27+
},
28+
},
29+
},
30+
}
31+
}

packages/cli/tests/tsconfig.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"extends": "../../../tsconfig.json",
3+
"compilerOptions": {
4+
"composite": true,
5+
"types": ["vitest/globals", "node"]
6+
},
7+
"include": ["./**/*.ts"],
8+
"exclude": ["node_modules"]
9+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { defineConfig } from 'vitest/config'
2+
3+
export default defineConfig({
4+
test: {
5+
globals: true,
6+
environment: 'node',
7+
include: ['**/*.test.ts', '**/*.spec.ts'],
8+
forceRerunTriggers: [
9+
'**/packages/cli/dist/**',
10+
'**/node_modules/@oxc-node/cli/dist/**',
11+
],
12+
},
13+
})

0 commit comments

Comments
 (0)