Skip to content

Commit e586d17

Browse files
authored
test: speed up staged CLI tests (#35)
1 parent ad63bb0 commit e586d17

2 files changed

Lines changed: 74 additions & 122 deletions

File tree

packages/rstack/rstack.config.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import { define } from 'rstack';
22

3-
define.test(() => {
3+
define.test(async () => {
4+
const { withRslibConfig } = await import('@rstest/adapter-rslib');
5+
46
// Disable color in test
57
process.env.NO_COLOR = '1';
68

79
return {
10+
extends: withRslibConfig(),
811
source: {
912
tsconfigPath: './test/tsconfig.json',
1013
},
Lines changed: 70 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,31 @@
1-
import { execFileSync } from 'node:child_process';
2-
import { mkdtemp, rm, writeFile } from 'node:fs/promises';
3-
import path from 'node:path';
1+
import lintStaged from 'lint-staged';
2+
import { beforeEach, rs } from 'rstack/test';
43
import { test } from '#test-helpers';
4+
import { loadRstackConfig } from '../../../src/config.ts';
5+
import { runStagedCLI, type StagedConfig } from '../../../src/staged.ts';
56

6-
const git = (cwd: string, args: string[]): void => {
7-
execFileSync('git', args, { cwd, stdio: 'ignore' });
8-
};
9-
10-
const createGitFixture = async (): Promise<string> => {
11-
const cwd = await mkdtemp(path.join(import.meta.dirname, 'fixture-'));
12-
13-
await Promise.all([
14-
writeFile(
15-
path.join(cwd, 'rstack.config.ts'),
16-
`import { define } from 'rstack';
17-
18-
define.staged({ '*.txt': 'node revert.mjs' });
19-
`,
20-
),
21-
writeFile(
22-
path.join(cwd, 'revert.mjs'),
23-
`import { writeFileSync } from 'node:fs';
7+
rs.mock('lint-staged');
8+
rs.mock('../../../src/config.ts');
249

25-
for (const file of process.argv.slice(2)) {
26-
writeFileSync(file, 'initial\\n');
27-
}
28-
29-
console.log('staged task output');
30-
console.log('staged file:', process.argv[2]);
31-
`,
32-
),
33-
writeFile(path.join(cwd, 'file.txt'), 'initial\n'),
34-
]);
35-
36-
git(cwd, ['init', '--quiet']);
37-
git(cwd, ['add', '.']);
38-
git(cwd, [
39-
'-c',
40-
'user.name=Rstack Test',
41-
'-c',
42-
'user.email=rstack@example.com',
43-
'commit',
44-
'--quiet',
45-
'-m',
46-
'initial',
47-
]);
48-
49-
await writeFile(path.join(cwd, 'file.txt'), 'changed\n');
50-
git(cwd, ['add', 'file.txt']);
51-
52-
return cwd;
10+
const mocks = {
11+
lintStaged: rs.mocked(lintStaged),
12+
loadRstackConfig: rs.mocked(loadRstackConfig),
5313
};
5414

55-
const withGitFixture = async (callback: (cwd: string) => Promise<void> | void): Promise<void> => {
56-
const cwd = await createGitFixture();
57-
58-
try {
59-
await callback(cwd);
60-
} finally {
61-
await rm(cwd, { recursive: true, force: true });
62-
}
15+
const stagedConfig: StagedConfig = {
16+
'*.txt': 'echo test',
6317
};
6418

19+
beforeEach(() => {
20+
rs.resetAllMocks();
21+
mocks.lintStaged.mockResolvedValue(true);
22+
mocks.loadRstackConfig.mockResolvedValue({
23+
configs: { staged: stagedConfig },
24+
filePath: null,
25+
dependencies: [],
26+
});
27+
});
28+
6529
test('should display the staged help message', ({ execCli, expect }) => {
6630
const output = execCli('staged --help');
6731

@@ -82,76 +46,61 @@ test('should reject unknown staged options', ({ execCli, expect }) => {
8246
expect(() => execCli('staged --unknown')).toThrow();
8347
});
8448

85-
test('should prevent an empty commit by default', async ({ execCli, expect }) => {
86-
await withGitFixture((cwd) => {
87-
expect(() => execCli('staged', { cwd })).toThrow();
49+
test('should pass default options to lint-staged', async ({ expect }) => {
50+
await runStagedCLI([]);
51+
52+
expect(mocks.lintStaged).toHaveBeenCalledWith({
53+
allowEmpty: undefined,
54+
concurrent: undefined,
55+
config: stagedConfig,
56+
cwd: undefined,
57+
debug: undefined,
58+
quiet: undefined,
59+
relative: undefined,
60+
stash: undefined,
61+
verbose: undefined,
8862
});
8963
});
9064

91-
test('should allow an empty commit with --allow-empty', async ({ execCli }) => {
92-
await withGitFixture((cwd) => {
93-
execCli(`staged --allow-empty`, { cwd });
94-
});
95-
});
96-
97-
for (const option of ['--concurrent false', '-p 1']) {
98-
test(`should run staged tasks with ${option}`, async ({ execCli }) => {
99-
await withGitFixture((cwd) => {
100-
execCli(`staged --allow-empty ${option}`, { cwd });
101-
});
102-
});
103-
}
104-
105-
for (const option of ['--debug', '-d']) {
106-
test(`should print debug output with ${option}`, async ({ execCli, expect }) => {
107-
await withGitFixture((cwd) => {
108-
const output = execCli(`staged --allow-empty ${option} 2>&1`, { cwd });
109-
expect(output).toContain('lint-staged:');
110-
});
111-
});
112-
}
113-
114-
for (const option of ['--verbose', '-v']) {
115-
test(`should show successful task output with ${option}`, async ({ execCli, expect }) => {
116-
await withGitFixture((cwd) => {
117-
const output = execCli(`staged --allow-empty ${option}`, { cwd });
118-
expect(output).toContain('staged task output');
119-
});
120-
});
121-
}
65+
test('should pass long options to lint-staged', async ({ expect }) => {
66+
await runStagedCLI([
67+
'--allow-empty',
68+
'--concurrent',
69+
'false',
70+
'--cwd',
71+
'fixture',
72+
'--debug',
73+
'--no-stash',
74+
'--quiet',
75+
'--relative',
76+
'--verbose',
77+
]);
12278

123-
test('should run staged tasks without a backup stash', async ({ execCli, expect }) => {
124-
await withGitFixture((cwd) => {
125-
const output = execCli('staged --allow-empty --no-stash 2>&1', { cwd });
126-
expect(output).toContain('Skipping backup because `--no-stash` was used');
79+
expect(mocks.lintStaged).toHaveBeenCalledWith({
80+
allowEmpty: true,
81+
concurrent: false,
82+
config: stagedConfig,
83+
cwd: 'fixture',
84+
debug: true,
85+
quiet: true,
86+
relative: true,
87+
stash: false,
88+
verbose: true,
12789
});
12890
});
12991

130-
for (const option of ['--quiet', '-q']) {
131-
test(`should suppress lint-staged output with ${option}`, async ({ execCli, expect }) => {
132-
await withGitFixture((cwd) => {
133-
const output = execCli(`staged --allow-empty ${option}`, { cwd });
134-
expect(output).toBe('');
135-
});
136-
});
137-
}
138-
139-
for (const option of ['--relative', '-r']) {
140-
test(`should pass relative filepaths with ${option}`, async ({ execCli, expect }) => {
141-
await withGitFixture((cwd) => {
142-
const output = execCli(`staged --allow-empty --verbose ${option}`, { cwd });
143-
expect(output).toContain('staged file: file.txt');
144-
});
145-
});
146-
}
147-
148-
test('should run staged tasks in the specified cwd', async ({ execCli, expect }) => {
149-
await withGitFixture((cwd) => {
150-
const configPath = path.join(cwd, 'rstack.config.ts');
151-
const output = execCli(
152-
`--config ${JSON.stringify(configPath)} staged --allow-empty --cwd ${JSON.stringify(cwd)} --relative --verbose`,
153-
{ cwd: path.dirname(cwd) },
154-
);
155-
expect(output).toContain('staged file: file.txt');
92+
test('should pass short options and aliases to lint-staged', async ({ expect }) => {
93+
await runStagedCLI(['--allowEmpty', '-p', '1', '-d', '-q', '-r', '-v']);
94+
95+
expect(mocks.lintStaged).toHaveBeenCalledWith({
96+
allowEmpty: true,
97+
concurrent: 1,
98+
config: stagedConfig,
99+
cwd: undefined,
100+
debug: true,
101+
quiet: true,
102+
relative: true,
103+
stash: undefined,
104+
verbose: true,
156105
});
157106
});

0 commit comments

Comments
 (0)