Skip to content

Commit 93e5620

Browse files
committed
test: strengthen assertions and remove redundant tests
1 parent 2b0394d commit 93e5620

File tree

11 files changed

+773
-1011
lines changed

11 files changed

+773
-1011
lines changed

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@
5454
"devDependencies": {
5555
"@types/node": "^24.9.2",
5656
"@types/react": "^18.0.27",
57+
"ansi-escapes": "^7.1.1",
58+
"ansi-regex": "^6.2.2",
5759
"clean-pkg-json": "^1.3.0",
5860
"expect-type": "^1.2.2",
5961
"fs-fixture": "^2.10.1",
@@ -67,6 +69,7 @@
6769
"react": "^17.0.2",
6870
"tsx": "^4.20.6",
6971
"typescript": "^5.9.3",
70-
"valtio": "^1.2.11"
72+
"valtio": "^1.2.11",
73+
"yoctocolors": "^2.1.2"
7174
}
7275
}

pnpm-lock.yaml

Lines changed: 35 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/specs/ansi.spec.ts

Lines changed: 43 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,40 @@
1-
import { stripVTControlCharacters } from 'node:util';
21
import { testSuite, expect } from 'manten';
32
import { createFixture } from 'fs-fixture';
3+
import ansiEscapes from 'ansi-escapes';
4+
import yoctocolors from 'yoctocolors';
45
import { node } from '../utils/node.js';
56
import { tempDir } from '../utils/temp-dir.js';
67

78
export default testSuite(({ describe }) => {
89
describe('ANSI control codes', ({ test }) => {
9-
test('uses ANSI clear and cursor movement codes', async () => {
10+
test('uses ANSI clear and cursor movement codes during spinner animation', async ({ onTestFail }) => {
1011
await using fixture = await createFixture({
1112
'test.mjs': `
1213
import task from '#tasuku';
1314
import { setTimeout } from 'node:timers/promises';
1415
1516
await task('Task', async () => {
16-
await setTimeout(200);
17+
await setTimeout(100);
1718
});
1819
`,
1920
}, { tempDir });
2021

2122
const result = await node(fixture.getPath('test.mjs'));
23+
onTestFail(() => { console.log(result); });
24+
expect(result.stderr).toBe('');
2225

23-
// Task completes successfully
24-
expect(stripVTControlCharacters(result.output).includes('Task')).toBe(true);
26+
// Loading state: yellow spinner
27+
expect(result.stdout).toContain(yoctocolors.yellow('⠋'));
2528

26-
// ANSI codes for line clearing and cursor movement
27-
// \x1B[2K = clear line
28-
// \x1B[1A = move cursor up one line
29-
expect(result.output).toContain('\u001B[2K');
30-
expect(result.output).toContain('\u001B[1A');
31-
});
32-
33-
test('ANSI clear codes present during spinner animation', async () => {
34-
await using fixture = await createFixture({
35-
'test.mjs': `
36-
import task from '#tasuku';
37-
import { setTimeout } from 'node:timers/promises';
38-
39-
await task('Task', async () => {
40-
await setTimeout(200);
41-
});
42-
`,
43-
}, { tempDir });
44-
45-
const result = await node(fixture.getPath('test.mjs'));
46-
47-
// Verify task completed
48-
expect(stripVTControlCharacters(result.output).includes('Task')).toBe(true);
29+
// ANSI codes used for animation
30+
const eraseLineCount = result.stdout.split(ansiEscapes.eraseLine).length - 1;
31+
const cursorUpCount = result.stdout.split(ansiEscapes.cursorUp()).length - 1;
32+
expect(eraseLineCount).toBeGreaterThanOrEqual(1); // At least one clear
33+
expect(cursorUpCount).toBeGreaterThanOrEqual(1); // At least one cursor move
4934

50-
// ANSI codes for cursor movement and line clearing during spinner updates
51-
expect(result.output).toContain('\u001B[2K'); // clear line
52-
expect(result.output).toContain('\u001B[1A'); // move up
35+
// Final state: green checkmark
36+
expect(result.stdout).toContain(yoctocolors.green('✔'));
37+
expect(result.stdout).toContain('Task');
5338
});
5439

5540
test('multiple line clears for multiple tasks', async () => {
@@ -67,16 +52,19 @@ export default testSuite(({ describe }) => {
6752
}, { tempDir });
6853

6954
const result = await node(fixture.getPath('test.mjs'));
70-
const textOutput = stripVTControlCharacters(result.output);
71-
72-
// All task names appear
73-
expect(textOutput.includes('one')).toBe(true);
74-
expect(textOutput.includes('two')).toBe(true);
75-
expect(textOutput.includes('three')).toBe(true);
76-
77-
// Multiple ANSI clear codes for updating multiple tasks
78-
expect(result.output).toContain('\u001B[2K');
79-
expect(result.output).toContain('\u001B[1A');
55+
expect(result.stderr).toBe('');
56+
57+
// All task names appear with checkmarks
58+
expect(result.stdout).toContain('one');
59+
expect(result.stdout).toContain('two');
60+
expect(result.stdout).toContain('three');
61+
expect(result.stdout).toContain(yoctocolors.green('✔'));
62+
63+
// Count ANSI codes - should appear multiple times for multiple task updates
64+
const eraseLineCount = result.stdout.split(ansiEscapes.eraseLine).length - 1;
65+
const cursorUpCount = result.stdout.split(ansiEscapes.cursorUp()).length - 1;
66+
expect(eraseLineCount).toBeGreaterThan(1); // Multiple line clears
67+
expect(cursorUpCount).toBeGreaterThan(1); // Multiple cursor moves
8068
});
8169

8270
test('clearing task triggers ANSI clear codes', async () => {
@@ -94,18 +82,24 @@ export default testSuite(({ describe }) => {
9482
});
9583
9684
task1.clear();
97-
98-
// Give renderer time to update
99-
await setTimeout(50);
10085
`,
10186
}, { tempDir });
10287

10388
const result = await node(fixture.getPath('test.mjs'));
104-
105-
// Should contain ANSI clear codes (line clear and cursor up)
106-
// These codes are used to clear Task 1 from the screen
107-
expect(result.output).toContain('\u001B[2K'); // clear line
108-
expect(result.output).toContain('\u001B[1A'); // move cursor up
89+
expect(result.stderr).toBe('');
90+
91+
// Both tasks appear with checkmarks initially
92+
expect(result.stdout).toContain('Task 1');
93+
expect(result.stdout).toContain('Task 2');
94+
expect(result.stdout).toContain(yoctocolors.green('✔'));
95+
96+
// Clearing triggers additional ANSI codes for re-rendering
97+
const eraseLineCount = result.stdout.split(ansiEscapes.eraseLine).length - 1;
98+
const cursorUpCount = result.stdout.split(ansiEscapes.cursorUp()).length - 1;
99+
// Multiple clears for task updates + clear operation
100+
expect(eraseLineCount).toBeGreaterThan(1);
101+
// Multiple cursor moves
102+
expect(cursorUpCount).toBeGreaterThan(1);
109103
});
110104
});
111105
});

0 commit comments

Comments
 (0)