Skip to content

Commit 962ec71

Browse files
authored
test: implement custom Vitest matchers for task order and status assertions (#243)
chore: remove other changelog libraries
1 parent 35636a0 commit 962ec71

File tree

18 files changed

+180
-940
lines changed

18 files changed

+180
-940
lines changed

.changeset/README.md

Lines changed: 0 additions & 8 deletions
This file was deleted.

.changeset/config.json

Lines changed: 0 additions & 10 deletions
This file was deleted.

.github/workflows/release-please.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
name: Release Please
2+
13
on:
24
push:
35
branches:
@@ -7,8 +9,6 @@ permissions:
79
contents: write
810
pull-requests: write
911

10-
name: release-please
11-
1212
jobs:
1313
release-please:
1414
runs-on: ubuntu-latest

.github/workflows/release.yml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,3 @@ jobs:
4444
run: |
4545
npm config set "//registry.npmjs.org/:_authToken" "${NPM_TOKEN}" # pnpm config set is broken
4646
pnpm publish -r --no-git-checks
47-
48-
- name: Generate Changelog
49-
run: npx changelogithub
50-
env:
51-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,11 @@
77
"start": "pnpm -r --parallel start"
88
},
99
"devDependencies": {
10-
"@changesets/cli": "^2.29.4",
1110
"@eslint/js": "^9.29.0",
1211
"@microsoft/api-extractor": "^7.52.8",
1312
"@stylistic/eslint-plugin": "^4.4.1",
1413
"@types/node": "^20.19.0",
1514
"@vitest/eslint-plugin": "^1.2.7",
16-
"changelogithub": "^13.15.0",
1715
"cspell": "^9.1.1",
1816
"eslint": "^9.29.0",
1917
"eslint-plugin-import": "^2.31.0",

packages/nadle/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"@types/node": "^20.19.0",
4242
"@types/object-hash": "^3.0.6",
4343
"@types/yargs": "^17.0.33",
44+
"@vitest/expect": "^3.2.4",
4445
"fixturify": "^3.0.0",
4546
"knip": "^5.61.0",
4647
"size-limit": "^11.2.0",
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import type { SyncExpectationResult } from "@vitest/expect";
2+
3+
export function toDoneInOrder(stdout: string, ...tasks: string[]): SyncExpectationResult {
4+
for (let firstTaskIndex = 0; firstTaskIndex < tasks.length - 1; firstTaskIndex++) {
5+
for (let secondTaskIndex = firstTaskIndex + 1; secondTaskIndex < tasks.length; secondTaskIndex++) {
6+
const firstTask = tasks[firstTaskIndex];
7+
const secondTask = tasks[secondTaskIndex];
8+
9+
const firstTaskDoneIndex = stdout.indexOf(`Task ${firstTask} DONE`);
10+
const secondTaskDoneIndex = stdout.indexOf(`Task ${secondTask} DONE`);
11+
12+
const pass = firstTaskDoneIndex < secondTaskDoneIndex;
13+
14+
if (!pass) {
15+
return {
16+
pass,
17+
message: () => `Expected task '${firstTask}' to be done before '${secondTask}', but it did not. Stdout:\n${stdout}`
18+
};
19+
}
20+
}
21+
}
22+
23+
return {
24+
pass: true,
25+
message: () => `All tasks done in the expected order.`
26+
};
27+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { type SyncExpectationResult } from "@vitest/expect";
2+
3+
export function toRunInOrder(stdout: string, ...groups: (string[] | string)[]): SyncExpectationResult {
4+
for (let firstGroupIndex = 0; firstGroupIndex < groups.length - 1; firstGroupIndex++) {
5+
for (let secondGroupIndex = firstGroupIndex + 1; secondGroupIndex < groups.length; secondGroupIndex++) {
6+
const firstGroup = (Array.isArray(groups[firstGroupIndex]) ? groups[firstGroupIndex] : [groups[firstGroupIndex]]) as string[];
7+
const secondGroup = (Array.isArray(groups[secondGroupIndex]) ? groups[secondGroupIndex] : [groups[secondGroupIndex]]) as string[];
8+
9+
for (const firstTask of firstGroup) {
10+
for (const secondTask of secondGroup) {
11+
const result = assertOrder(stdout, firstTask, secondTask);
12+
13+
if (!result.pass) {
14+
return result;
15+
}
16+
}
17+
}
18+
}
19+
}
20+
21+
return {
22+
pass: true,
23+
message: () => `All tasks ran in the expected order.`
24+
};
25+
}
26+
27+
function assertOrder(stdout: string, firstTask: string, secondTask: string) {
28+
const firstTaskDoneIndex = stdout.indexOf(`Task ${firstTask} DONE`);
29+
const secondTaskStartedIndex = stdout.indexOf(`Task ${secondTask} STARTED`);
30+
31+
if (firstTaskDoneIndex === -1) {
32+
return {
33+
pass: false,
34+
message: () => `Expected task '${firstTask}' to have run, but it did not. Stdout:\n${stdout}`
35+
};
36+
}
37+
38+
if (secondTaskStartedIndex === -1) {
39+
return {
40+
pass: false,
41+
message: () => `Expected task '${secondTask}' to have run, but it did not. Stdout:\n${stdout}`
42+
};
43+
}
44+
45+
const pass = firstTaskDoneIndex < secondTaskStartedIndex;
46+
47+
return {
48+
pass,
49+
message: () =>
50+
pass
51+
? `Expected task '${firstTask}' not to run before '${secondTask}', but it did. Stdout:\n${stdout}`
52+
: `Expected task '${firstTask}' to run before '${secondTask}', but the order was incorrect. Stdout:\n${stdout}`
53+
};
54+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { type ExpectationResult } from "@vitest/expect";
2+
3+
export function toSettle(stdout: string, taskName: string, status: "done" | "up-to-date" | "from-cache" | "failed"): ExpectationResult {
4+
const taskDoneIndex = stdout.indexOf(`Task ${taskName} ${status.toUpperCase()}`);
5+
6+
if (taskDoneIndex === -1) {
7+
return {
8+
pass: false,
9+
message: () => `Expected task '${taskName}' to have been marked as '${status}', but it did not. Stdout:\n${stdout}`
10+
};
11+
}
12+
13+
return {
14+
pass: true,
15+
message: () => `Task '${taskName}' was successfully marked as '${status}'.`
16+
};
17+
}
Lines changed: 4 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,10 @@
11
import { expect } from "vitest";
22

33
import { serialize } from "./serialize.js";
4+
import { toSettle } from "./matchers/to-settle.js";
5+
import { toRunInOrder } from "./matchers/to-run-in-order.js";
6+
import { toDoneInOrder } from "./matchers/to-done-in-order.js";
47

58
expect.addSnapshotSerializer({ serialize, test: (val) => typeof val === "string" });
69

7-
expect.extend({
8-
toDoneInOrder(stdout: string, ...tasks: string[]) {
9-
for (let firstTaskIndex = 0; firstTaskIndex < tasks.length - 1; firstTaskIndex++) {
10-
for (let secondTaskIndex = firstTaskIndex + 1; secondTaskIndex < tasks.length; secondTaskIndex++) {
11-
const firstTask = tasks[firstTaskIndex];
12-
const secondTask = tasks[secondTaskIndex];
13-
14-
const firstTaskDoneIndex = stdout.indexOf(`Task ${firstTask} DONE`);
15-
const secondTaskDoneIndex = stdout.indexOf(`Task ${secondTask} DONE`);
16-
17-
const pass = firstTaskDoneIndex < secondTaskDoneIndex;
18-
19-
if (!pass) {
20-
return {
21-
pass,
22-
message: () => `Expected task '${firstTask}' to be done before '${secondTask}', but it did not. Stdout:\n${stdout}`
23-
};
24-
}
25-
}
26-
}
27-
28-
return {
29-
pass: true,
30-
message: () => `All tasks done in the expected order.`
31-
};
32-
},
33-
toRunInOrder(stdout: string, ...groups: (string[] | string)[]) {
34-
for (let firstGroupIndex = 0; firstGroupIndex < groups.length - 1; firstGroupIndex++) {
35-
for (let secondGroupIndex = firstGroupIndex + 1; secondGroupIndex < groups.length; secondGroupIndex++) {
36-
const firstGroup = (Array.isArray(groups[firstGroupIndex]) ? groups[firstGroupIndex] : [groups[firstGroupIndex]]) as string[];
37-
const secondGroup = (Array.isArray(groups[secondGroupIndex]) ? groups[secondGroupIndex] : [groups[secondGroupIndex]]) as string[];
38-
39-
for (const firstTask of firstGroup) {
40-
for (const secondTask of secondGroup) {
41-
const result = assertOrder(stdout, firstTask, secondTask);
42-
43-
if (!result.pass) {
44-
return result;
45-
}
46-
}
47-
}
48-
}
49-
}
50-
51-
return {
52-
pass: true,
53-
message: () => `All tasks ran in the expected order.`
54-
};
55-
}
56-
});
57-
58-
function assertOrder(stdout: string, firstTask: string, secondTask: string) {
59-
const firstTaskDoneIndex = stdout.indexOf(`Task ${firstTask} DONE`);
60-
const secondTaskStartedIndex = stdout.indexOf(`Task ${secondTask} STARTED`);
61-
62-
if (firstTaskDoneIndex === -1) {
63-
return {
64-
pass: false,
65-
message: () => `Expected task '${firstTask}' to have run, but it did not. Stdout:\n${stdout}`
66-
};
67-
}
68-
69-
if (secondTaskStartedIndex === -1) {
70-
return {
71-
pass: false,
72-
message: () => `Expected task '${secondTask}' to have run, but it did not. Stdout:\n${stdout}`
73-
};
74-
}
75-
76-
const pass = firstTaskDoneIndex < secondTaskStartedIndex;
77-
78-
return {
79-
pass,
80-
message: () =>
81-
pass
82-
? `Expected task '${firstTask}' not to run before '${secondTask}', but it did. Stdout:\n${stdout}`
83-
: `Expected task '${firstTask}' to run before '${secondTask}', but the order was incorrect. Stdout:\n${stdout}`
84-
};
85-
}
10+
expect.extend({ toSettle, toRunInOrder, toDoneInOrder });

0 commit comments

Comments
 (0)