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
37 changes: 23 additions & 14 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
const jestPackageJson = require('jest/package.json');

module.exports = {
root: true,
env: {
es6: true,
node: true,
jest: true,
},
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
Expand All @@ -22,7 +19,9 @@ module.exports = {
'assets/**',
'scripts/**',
'coverage/**',
'e2e-tests/test-applications/**',
// Standalone jest-based package, linted/typechecked in its own context and
// outside the root tsconfig the parser uses (parserOptions.project).
'e2e-tests/**',
],
extends: [
'eslint:recommended',
Expand All @@ -33,16 +32,31 @@ module.exports = {
overrides: [
{
files: [
'**/e2e-tests/utils/**/*.ts',
'*.test.js',
'*.test.ts',
'**/__tests__/**/*.ts',
'**/__tests__/**/*.js',
'**/__mocks__/**/*.ts',
],
plugins: ['jest'],
extends: ['plugin:jest/recommended', 'plugin:jest/style'],
env: {
'jest/globals': true,
globals: {
// vitest test APIs (test.globals: true) ...
describe: 'readonly',
it: 'readonly',
test: 'readonly',
expect: 'readonly',
suite: 'readonly',
beforeEach: 'readonly',
afterEach: 'readonly',
beforeAll: 'readonly',
afterAll: 'readonly',
vi: 'readonly',
vitest: 'readonly',
// ... and the ambient mock helper types from types/vitest-global-types.d.ts
Mock: 'readonly',
Mocked: 'readonly',
MockInstance: 'readonly',
MockedFunction: 'readonly',
MockedClass: 'readonly',
},
rules: {
'@typescript-eslint/unbound-method': 'off',
Expand All @@ -55,11 +69,6 @@ module.exports = {
},
},
],
settings: {
jest: {
version: jestPackageJson.version,
},
},
globals: {
NodeJS: true,
},
Expand Down
12 changes: 6 additions & 6 deletions __mocks__/@posthog/warlock.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Mock for @posthog/warlock
//
// The real package is ESM-only and loads a YARA-X WASM binary at runtime, which
// jest cannot transform/execute. Unit tests exercise the wizard's own decision
// the unit test runner can't execute. Unit tests exercise the wizard's own decision
// logic (scan_context filtering, severity/action mapping, triage handling,
// fail-closed behavior) against these jest.fn()s — never the real engine. Rule
// fail-closed behavior) against these vi.fn()s — never the real engine. Rule
// matching itself is tested in the warlock repo.

import type * as RealWarlock from '@posthog/warlock';
Expand Down Expand Up @@ -62,13 +62,13 @@ export const CATEGORIES = [
] as const;

// Default: nothing matches. Tests override per-case with mockResolvedValueOnce.
export const scan = jest.fn(
export const scan = vi.fn(
(_content: string): Promise<ScanResult> =>
Promise.resolve({ matched: false }),
);

// Default: pass matches through as true positives (mirrors warlock's fail-safe).
export const triageMatches = jest.fn(
export const triageMatches = vi.fn(
(
_content: string,
matches: ScanMatch[],
Expand All @@ -86,8 +86,8 @@ export const triageMatches = jest.fn(
// ─── Compile-time drift guard ────────────────────────────────────
// If the real package's exports change shape, this assignment stops
// type-checking and `pnpm test` fails — so the mock can't silently diverge
// from the engine the wizard actually ships with. It works because jest's
// moduleNameMapper is runtime-only: the `import type` above resolves to the
// from the engine the wizard actually ships with. It works because vitest's
// resolve.alias is runtime-only: the `import type` above resolves to the
// REAL package under TypeScript and is fully erased at runtime.
// (This guard caught warlock 0.2.2 adding the required `matchedStrings`
// field to ScanMatch.)
Expand Down
9 changes: 9 additions & 0 deletions e2e-tests/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
{
// e2e-tests is a standalone, jest-based package (run via `jest -c
// jest.config.ts`). The root tsconfig moved the unit suite to vitest and
// dropped jest from its `types`/scope, so this config restores jest's ambient
// types and re-includes the e2e sources for ts-jest.
"extends": "../tsconfig.json",
"compilerOptions": {
"types": ["node", "jest"]
},
"include": ["**/*.ts"],
"exclude": ["node_modules", "test-applications/**/*"]
}
56 changes: 6 additions & 50 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
"@types/yargs": "^16.0.9",
"@typescript-eslint/eslint-plugin": "^5.13.0",
"@typescript-eslint/parser": "^5.13.0",
"@vitest/coverage-v8": "^3.2.4",
"babel-jest": "^29.7.0",
"dotenv": "^16.4.7",
"eslint": "^8.18.0",
Expand All @@ -91,7 +92,8 @@
"ts-node": "^10.9.1",
"tsdown": "^0.21.9",
"tsx": "^4.20.3",
"typescript": "^5.0.4"
"typescript": "^5.0.4",
"vitest": "^3.2.4"
},
"engines": {
"node": "^20.20.0 || >=22.22.0",
Expand All @@ -113,61 +115,15 @@
"fix": "pnpm fix:eslint && pnpm fix:prettier",
"fix:prettier": "prettier --write \"{lib,src,test}/**/*.ts\"",
"fix:eslint": "eslint . --cache --format stylish --fix",
"test": "pnpm build && jest",
"test": "pnpm build && vitest run",
"test:coverage": "pnpm build && vitest run --coverage",
"test:e2e": "pnpm build && ./e2e-tests/run.sh",
"test:e2e-record": "export RECORD_FIXTURES=true && pnpm build && ./e2e-tests/run.sh",
"try": "tsx bin.ts",
"dev": "pnpm build && pnpm link --global && pnpm build:watch",
"test:watch": "jest --watch",
"test:watch": "vitest",
"prepare": "husky"
},
"jest": {
"collectCoverage": true,
"coveragePathIgnorePatterns": [
"dist"
],
"transform": {
"^.+\\.tsx?$": "ts-jest",
"node_modules/.+\\.js$": "babel-jest"
},
"testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx",
"json"
],
"modulePathIgnorePatterns": [
"<rootDir>/dist/",
"<rootDir>/.claude/worktrees/"
],
"testPathIgnorePatterns": [
"/dist/",
"/node_modules/",
"\\.d\\.(jsx?|tsx?)$",
"\\.no-jest\\.(jsx?|tsx?)$",
"/e2e-tests/"
],
"testEnvironment": "node",
"transformIgnorePatterns": [
"node_modules/(?!(.pnpm/nanostores|nanostores))"
],
"moduleNameMapper": {
"^@anthropic-ai/claude-agent-sdk$": "<rootDir>/__mocks__/@anthropic-ai/claude-agent-sdk.ts",
"^@posthog/warlock$": "<rootDir>/__mocks__/@posthog/warlock.ts",
"^ink$": "<rootDir>/__mocks__/ink.ts",
"^@env$": "<rootDir>/src/env.ts",
"^@lib/(.*)$": "<rootDir>/src/lib/$1",
"^@utils/(.*)$": "<rootDir>/src/utils/$1",
"^@ui$": "<rootDir>/src/ui/index.ts",
"^@ui/(.*)$": "<rootDir>/src/ui/$1",
"^@steps$": "<rootDir>/src/steps/index.ts",
"^@steps/(.*)$": "<rootDir>/src/steps/$1",
"^@frameworks/(.*)$": "<rootDir>/src/frameworks/$1",
"^(\\.{1,2}/.*)\\.js$": "$1"
}
},
"lint-staged": {
".claude/settings.json": "sh -c 'printf \"\\n\\033[31mDo not commit .claude/settings.json — use .claude/settings.local.json (gitignored).\\nUnstage with: git restore --staged .claude/settings.json\\033[0m\\n\\n\" >&2 && exit 1'",
"*.{js,ts,tsx,jsx}": [
Expand Down
Loading
Loading