mirror of
https://github.com/n8n-io/n8n.git
synced 2026-05-27 23:07:12 +02:00
207 lines
5.7 KiB
TypeScript
207 lines
5.7 KiB
TypeScript
import { execSync } from 'node:child_process';
|
|
import * as fs from 'node:fs';
|
|
import * as os from 'node:os';
|
|
import * as path from 'node:path';
|
|
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
|
|
|
const CLI_PATH = path.join(__dirname, '..', 'dist', 'cli.js');
|
|
|
|
describe('CLI', () => {
|
|
describe('--help', () => {
|
|
it('shows help text', () => {
|
|
const output = execSync(`node ${CLI_PATH} --help`, { encoding: 'utf-8' });
|
|
|
|
expect(output).toContain('Playwright Janitor');
|
|
expect(output).toContain('Commands:');
|
|
expect(output).toContain('baseline');
|
|
expect(output).toContain('inventory');
|
|
expect(output).toContain('impact');
|
|
expect(output).toContain('tcr');
|
|
expect(output).toContain('--ignore-baseline');
|
|
});
|
|
});
|
|
|
|
describe('--list', () => {
|
|
it('lists available rules', () => {
|
|
const output = execSync(`node ${CLI_PATH} --list`, { encoding: 'utf-8' });
|
|
|
|
expect(output).toContain('Available rules:');
|
|
expect(output).toContain('boundary-protection');
|
|
expect(output).toContain('selector-purity');
|
|
expect(output).toContain('dead-code');
|
|
expect(output).toContain('scope-lockdown');
|
|
});
|
|
});
|
|
|
|
describe('baseline --help', () => {
|
|
it('shows baseline help', () => {
|
|
const output = execSync(`node ${CLI_PATH} baseline --help`, { encoding: 'utf-8' });
|
|
|
|
expect(output).toContain('Baseline');
|
|
expect(output).toContain('.janitor-baseline.json');
|
|
expect(output).toContain('incremental cleanup');
|
|
});
|
|
});
|
|
|
|
describe('inventory --help', () => {
|
|
it('shows inventory help', () => {
|
|
const output = execSync(`node ${CLI_PATH} inventory --help`, { encoding: 'utf-8' });
|
|
|
|
expect(output).toContain('Inventory');
|
|
expect(output).toContain('JSON');
|
|
});
|
|
});
|
|
|
|
describe('impact --help', () => {
|
|
it('shows impact help', () => {
|
|
const output = execSync(`node ${CLI_PATH} impact --help`, { encoding: 'utf-8' });
|
|
|
|
expect(output).toContain('Impact');
|
|
expect(output).toContain('--file');
|
|
});
|
|
});
|
|
|
|
describe('method-impact --help', () => {
|
|
it('shows method-impact help', () => {
|
|
const output = execSync(`node ${CLI_PATH} method-impact --help`, { encoding: 'utf-8' });
|
|
|
|
expect(output).toContain('Method Impact');
|
|
expect(output).toContain('--method');
|
|
});
|
|
});
|
|
|
|
describe('tcr --help', () => {
|
|
it('shows tcr help', () => {
|
|
const output = execSync(`node ${CLI_PATH} tcr --help`, { encoding: 'utf-8' });
|
|
|
|
expect(output).toContain('TCR');
|
|
expect(output).toContain('--execute');
|
|
expect(output).toContain('--message');
|
|
expect(output).toContain('--max-diff-lines');
|
|
});
|
|
});
|
|
|
|
describe('argument parsing', () => {
|
|
let tempDir: string;
|
|
|
|
beforeAll(() => {
|
|
// Use realpathSync to avoid macOS /var -> /private/var symlink issues
|
|
tempDir = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'cli-test-')));
|
|
|
|
// Create tsconfig.json (required by ts-morph)
|
|
fs.writeFileSync(
|
|
path.join(tempDir, 'tsconfig.json'),
|
|
JSON.stringify({
|
|
compilerOptions: {
|
|
target: 'ES2020',
|
|
module: 'ESNext',
|
|
moduleResolution: 'node',
|
|
strict: true,
|
|
},
|
|
include: ['**/*.ts'],
|
|
}),
|
|
);
|
|
|
|
// Create minimal config as .js (Node.js can't dynamically import .ts files)
|
|
fs.writeFileSync(
|
|
path.join(tempDir, 'janitor.config.js'),
|
|
`module.exports = {
|
|
rootDir: '${tempDir}',
|
|
patterns: {
|
|
pages: ['pages/**/*.ts'],
|
|
components: [],
|
|
flows: [],
|
|
tests: ['tests/**/*.spec.ts'],
|
|
services: [],
|
|
fixtures: [],
|
|
helpers: [],
|
|
factories: [],
|
|
testData: [],
|
|
},
|
|
excludeFromPages: [],
|
|
facade: { file: 'pages/AppPage.ts', className: 'AppPage', excludeTypes: [] },
|
|
fixtureObjectName: 'app',
|
|
apiFixtureName: 'api',
|
|
rawApiPatterns: [],
|
|
flowLayerName: 'Composable',
|
|
architectureLayers: [],
|
|
rules: {},
|
|
};`,
|
|
);
|
|
|
|
fs.mkdirSync(path.join(tempDir, 'pages'), { recursive: true });
|
|
fs.mkdirSync(path.join(tempDir, 'tests'), { recursive: true });
|
|
});
|
|
|
|
afterAll(() => {
|
|
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
});
|
|
|
|
it('accepts --json flag', () => {
|
|
// Create a clean page file
|
|
fs.writeFileSync(path.join(tempDir, 'pages', 'CleanPage.ts'), 'export class CleanPage {}');
|
|
|
|
try {
|
|
const output = execSync(
|
|
`node ${CLI_PATH} --json --config=${path.join(tempDir, 'janitor.config.js')}`,
|
|
{
|
|
encoding: 'utf-8',
|
|
cwd: tempDir,
|
|
},
|
|
);
|
|
|
|
// Should be valid JSON
|
|
expect(() => JSON.parse(output) as unknown).not.toThrow();
|
|
} catch (error) {
|
|
// Even if there are violations, output should be JSON
|
|
const stderr = (error as { stdout?: string }).stdout ?? '';
|
|
if (stderr) {
|
|
expect(() => JSON.parse(stderr) as unknown).not.toThrow();
|
|
}
|
|
}
|
|
});
|
|
|
|
it('accepts --verbose flag', () => {
|
|
fs.writeFileSync(
|
|
path.join(tempDir, 'pages', 'VerbosePage.ts'),
|
|
'export class VerbosePage {}',
|
|
);
|
|
|
|
try {
|
|
const output = execSync(
|
|
`node ${CLI_PATH} --verbose --config=${path.join(tempDir, 'janitor.config.js')}`,
|
|
{
|
|
encoding: 'utf-8',
|
|
cwd: tempDir,
|
|
},
|
|
);
|
|
// Verbose output should include more detail
|
|
expect(output).toBeDefined();
|
|
} catch {
|
|
// May fail with violations, that's OK for this test
|
|
}
|
|
});
|
|
|
|
it('accepts --ignore-baseline flag', () => {
|
|
fs.writeFileSync(
|
|
path.join(tempDir, 'pages', 'BaselinePage.ts'),
|
|
'export class BaselinePage {}',
|
|
);
|
|
|
|
try {
|
|
const output = execSync(
|
|
`node ${CLI_PATH} --ignore-baseline --config=${path.join(tempDir, 'janitor.config.js')}`,
|
|
{
|
|
encoding: 'utf-8',
|
|
cwd: tempDir,
|
|
},
|
|
);
|
|
// Should not show "Using baseline" message when ignoring
|
|
expect(output).not.toContain('Using baseline');
|
|
} catch {
|
|
// May fail with violations, that's OK for this test
|
|
}
|
|
});
|
|
});
|
|
});
|