bun-sticky 1.0.3 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -120
- package/index.js +8 -0
- package/package.json +7 -27
- package/.claude/commands/score.md +0 -12
- package/.claude/commands/test.md +0 -15
- package/.github/FUNDING.yml +0 -5
- package/.github/workflows/ci.yml +0 -26
- package/.github/workflows/release.yml +0 -36
- package/CLAUDE.md +0 -98
- package/LICENSE +0 -21
- package/PUBLISH-PROTOCOL.md +0 -63
- package/index.ts +0 -349
- package/lib/parser.ts +0 -75
- package/lib/scorer.ts +0 -237
- package/lib/tier.ts +0 -46
- package/project.faf +0 -23
- package/tests/__snapshots__/sticky.test.ts.snap +0 -114
- package/tests/sticky.test.ts +0 -1321
- package/tests/wjttc.test.ts +0 -966
package/tests/sticky.test.ts
DELETED
|
@@ -1,1321 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 🥐 BUN STICKY - WJTTC CHAMPIONSHIP TEST SUITE
|
|
3
|
-
*
|
|
4
|
-
* THE BEST BUN TEST SUITE IN THE AI ERA
|
|
5
|
-
*
|
|
6
|
-
* Philosophy:
|
|
7
|
-
* - FULL Bun test API - Every feature, no shortcuts
|
|
8
|
-
* - WJTTC Standards - F1-grade, championship quality
|
|
9
|
-
* - META TESTING - Tests that test the tests
|
|
10
|
-
* - BREAK IT - So they never know it was ever broken
|
|
11
|
-
*
|
|
12
|
-
* Bun Test Features:
|
|
13
|
-
* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
14
|
-
* ✓ test() / describe()
|
|
15
|
-
* ✓ test.each() / describe.each()
|
|
16
|
-
* ✓ test.concurrent()
|
|
17
|
-
* ✓ test.todo() / test.skip() / test.only()
|
|
18
|
-
* ✓ test.if() / test.skipIf()
|
|
19
|
-
* ✓ test.failing() - Expected failures
|
|
20
|
-
* ✓ beforeAll() / afterAll() / beforeEach() / afterEach()
|
|
21
|
-
* ✓ mock() / spyOn() / mockImplementation()
|
|
22
|
-
* ✓ toMatchSnapshot() / toMatchInlineSnapshot()
|
|
23
|
-
* ✓ setSystemTime() - Time mocking
|
|
24
|
-
* ✓ expect.assertions() / expect.hasAssertions()
|
|
25
|
-
* ✓ expect.extend() - Custom matchers
|
|
26
|
-
* ✓ Async/Promise testing
|
|
27
|
-
* ✓ Error/Throw testing
|
|
28
|
-
* ✓ Timeout testing
|
|
29
|
-
* ✓ All 40+ matchers
|
|
30
|
-
* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
31
|
-
*
|
|
32
|
-
* Run: bun test
|
|
33
|
-
* Run with todos: bun test --todo
|
|
34
|
-
* Update snapshots: bun test -u
|
|
35
|
-
*/
|
|
36
|
-
|
|
37
|
-
import {
|
|
38
|
-
describe,
|
|
39
|
-
test,
|
|
40
|
-
expect,
|
|
41
|
-
beforeAll,
|
|
42
|
-
afterAll,
|
|
43
|
-
beforeEach,
|
|
44
|
-
afterEach,
|
|
45
|
-
mock,
|
|
46
|
-
spyOn,
|
|
47
|
-
setSystemTime,
|
|
48
|
-
} from "bun:test";
|
|
49
|
-
import { $ } from "bun";
|
|
50
|
-
|
|
51
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
52
|
-
// CUSTOM MATCHERS - Extend expect()
|
|
53
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
54
|
-
|
|
55
|
-
expect.extend({
|
|
56
|
-
toBeValidScore(received: number) {
|
|
57
|
-
const pass = received >= 0 && received <= 105;
|
|
58
|
-
return {
|
|
59
|
-
pass,
|
|
60
|
-
message: () =>
|
|
61
|
-
pass
|
|
62
|
-
? `Expected ${received} not to be a valid score (0-105)`
|
|
63
|
-
: `Expected ${received} to be a valid score (0-105)`,
|
|
64
|
-
};
|
|
65
|
-
},
|
|
66
|
-
toBeValidTier(received: { emoji: string; name: string; color: string }) {
|
|
67
|
-
const validEmojis = ["🍊", "🏆", "🥇", "🥈", "🥉", "🟢", "🟡", "🔴", "⚪"];
|
|
68
|
-
const pass = validEmojis.includes(received.emoji);
|
|
69
|
-
return {
|
|
70
|
-
pass,
|
|
71
|
-
message: () =>
|
|
72
|
-
pass
|
|
73
|
-
? `Expected tier not to be valid`
|
|
74
|
-
: `Expected tier to be valid, got ${received.emoji}`,
|
|
75
|
-
};
|
|
76
|
-
},
|
|
77
|
-
toHaveSlotCount(received: Record<string, unknown>, expected: number) {
|
|
78
|
-
const count = Object.keys(received).length;
|
|
79
|
-
const pass = count === expected;
|
|
80
|
-
return {
|
|
81
|
-
pass,
|
|
82
|
-
message: () =>
|
|
83
|
-
pass
|
|
84
|
-
? `Expected not to have ${expected} slots`
|
|
85
|
-
: `Expected ${expected} slots, got ${count}`,
|
|
86
|
-
};
|
|
87
|
-
},
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
// Type declarations for custom matchers
|
|
91
|
-
declare module "bun:test" {
|
|
92
|
-
interface Matchers<T> {
|
|
93
|
-
toBeValidScore(): void;
|
|
94
|
-
toBeValidTier(): void;
|
|
95
|
-
toHaveSlotCount(expected: number): void;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
100
|
-
// TIER 0: META TESTING - Tests that test the tests
|
|
101
|
-
// "We break it so they never know it was ever broken"
|
|
102
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
103
|
-
|
|
104
|
-
describe("Tier 0: META TESTING", () => {
|
|
105
|
-
test("T0.01 - This test file exists", async () => {
|
|
106
|
-
const file = Bun.file("./tests/sticky.test.ts");
|
|
107
|
-
expect(await file.exists()).toBe(true);
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
test("T0.02 - Test file is TypeScript", async () => {
|
|
111
|
-
const path = "./tests/sticky.test.ts";
|
|
112
|
-
expect(path.endsWith(".ts")).toBe(true);
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
test("T0.03 - Test file imports bun:test", async () => {
|
|
116
|
-
const content = await Bun.file("./tests/sticky.test.ts").text();
|
|
117
|
-
expect(content).toContain('from "bun:test"');
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
test("T0.04 - Test file has describe blocks", async () => {
|
|
121
|
-
const content = await Bun.file("./tests/sticky.test.ts").text();
|
|
122
|
-
const describeCount = (content.match(/describe\(/g) || []).length;
|
|
123
|
-
expect(describeCount).toBeGreaterThan(10);
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
test("T0.05 - Test file has test blocks", async () => {
|
|
127
|
-
const content = await Bun.file("./tests/sticky.test.ts").text();
|
|
128
|
-
const testCount = (content.match(/\btest\(/g) || []).length;
|
|
129
|
-
expect(testCount).toBeGreaterThan(50);
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
test("T0.06 - Test file uses mock()", async () => {
|
|
133
|
-
const content = await Bun.file("./tests/sticky.test.ts").text();
|
|
134
|
-
expect(content).toContain("mock(");
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
test("T0.07 - Test file uses spyOn()", async () => {
|
|
138
|
-
const content = await Bun.file("./tests/sticky.test.ts").text();
|
|
139
|
-
expect(content).toContain("spyOn(");
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
test("T0.08 - Test file uses toMatchSnapshot()", async () => {
|
|
143
|
-
const content = await Bun.file("./tests/sticky.test.ts").text();
|
|
144
|
-
expect(content).toContain("toMatchSnapshot()");
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
test("T0.09 - Test file uses test.each()", async () => {
|
|
148
|
-
const content = await Bun.file("./tests/sticky.test.ts").text();
|
|
149
|
-
expect(content).toContain("test.each(");
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
test("T0.10 - Test file uses beforeAll/afterAll", async () => {
|
|
153
|
-
const content = await Bun.file("./tests/sticky.test.ts").text();
|
|
154
|
-
expect(content).toContain("beforeAll(");
|
|
155
|
-
expect(content).toContain("afterAll(");
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
test("T0.11 - Snapshot directory exists after tests", async () => {
|
|
159
|
-
// Snapshots are created in __snapshots__
|
|
160
|
-
const snapshotDir = Bun.file("./tests/__snapshots__");
|
|
161
|
-
// This will pass after first run
|
|
162
|
-
expect(true).toBe(true);
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
test("T0.12 - expect.extend() is used for custom matchers", async () => {
|
|
166
|
-
const content = await Bun.file("./tests/sticky.test.ts").text();
|
|
167
|
-
expect(content).toContain("expect.extend(");
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
172
|
-
// TIER 1: CORE PARSING (20%)
|
|
173
|
-
// The foundation - if this breaks, everything breaks
|
|
174
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
175
|
-
|
|
176
|
-
describe("Tier 1: Core Parsing", () => {
|
|
177
|
-
test("T1.01 - Parse simple YAML key-value", async () => {
|
|
178
|
-
const { parseYaml } = await import("../lib/parser.ts");
|
|
179
|
-
const result = parseYaml("name: test");
|
|
180
|
-
expect(result.name).toBe("test");
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
test("T1.02 - Parse nested YAML structure", async () => {
|
|
184
|
-
const { parseYaml } = await import("../lib/parser.ts");
|
|
185
|
-
const yaml = `
|
|
186
|
-
project:
|
|
187
|
-
name: test
|
|
188
|
-
goal: testing
|
|
189
|
-
`;
|
|
190
|
-
const result = parseYaml(yaml);
|
|
191
|
-
expect(result.project).toBeDefined();
|
|
192
|
-
expect((result.project as any).name).toBe("test");
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
test("T1.03 - Skip comments", async () => {
|
|
196
|
-
const { parseYaml } = await import("../lib/parser.ts");
|
|
197
|
-
const yaml = `
|
|
198
|
-
# This is a comment
|
|
199
|
-
name: test
|
|
200
|
-
# Another comment
|
|
201
|
-
`;
|
|
202
|
-
const result = parseYaml(yaml);
|
|
203
|
-
expect(result.name).toBe("test");
|
|
204
|
-
expect(Object.keys(result).length).toBe(1);
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
test("T1.04 - Handle empty lines", async () => {
|
|
208
|
-
const { parseYaml } = await import("../lib/parser.ts");
|
|
209
|
-
const yaml = `
|
|
210
|
-
name: test
|
|
211
|
-
|
|
212
|
-
goal: testing
|
|
213
|
-
|
|
214
|
-
`;
|
|
215
|
-
const result = parseYaml(yaml);
|
|
216
|
-
expect(result.name).toBe("test");
|
|
217
|
-
expect(result.goal).toBe("testing");
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
test("T1.05 - Strip quotes from values", async () => {
|
|
221
|
-
const { parseYaml } = await import("../lib/parser.ts");
|
|
222
|
-
const yaml = `
|
|
223
|
-
single: 'quoted'
|
|
224
|
-
double: "quoted"
|
|
225
|
-
`;
|
|
226
|
-
const result = parseYaml(yaml);
|
|
227
|
-
expect(result.single).toBe("quoted");
|
|
228
|
-
expect(result.double).toBe("quoted");
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
test("T1.06 - Handle inline arrays", async () => {
|
|
232
|
-
const { parseYaml } = await import("../lib/parser.ts");
|
|
233
|
-
const yaml = `stack: [Bun, TypeScript, FAF]`;
|
|
234
|
-
const result = parseYaml(yaml);
|
|
235
|
-
expect(Array.isArray(result.stack)).toBe(true);
|
|
236
|
-
expect((result.stack as string[]).length).toBe(3);
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
// ★ test.each() - Parameterized tests
|
|
240
|
-
test.each([
|
|
241
|
-
["name: hello", "name", "hello"],
|
|
242
|
-
["version: 1.0.0", "version", "1.0.0"],
|
|
243
|
-
["type: cli", "type", "cli"],
|
|
244
|
-
["score: 100", "score", "100"],
|
|
245
|
-
])("T1.07 - Parse '%s' → %s=%s", async (yaml, key, value) => {
|
|
246
|
-
const { parseYaml } = await import("../lib/parser.ts");
|
|
247
|
-
const result = parseYaml(yaml);
|
|
248
|
-
expect(result[key]).toBe(value);
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
// Edge case: empty value creates nested object (YAML spec behavior)
|
|
252
|
-
test("T1.08 - Empty value creates nested object", async () => {
|
|
253
|
-
const { parseYaml } = await import("../lib/parser.ts");
|
|
254
|
-
const result = parseYaml("empty:");
|
|
255
|
-
expect(typeof result.empty).toBe("object");
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
test("T1.09 - getNestedValue deep path", async () => {
|
|
259
|
-
const { getNestedValue } = await import("../lib/parser.ts");
|
|
260
|
-
const obj = { a: { b: { c: { d: "deep" } } } };
|
|
261
|
-
expect(getNestedValue(obj, "a.b.c.d")).toBe("deep");
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
test("T1.10 - getNestedValue missing path returns undefined", async () => {
|
|
265
|
-
const { getNestedValue } = await import("../lib/parser.ts");
|
|
266
|
-
const obj = { a: { b: 1 } };
|
|
267
|
-
expect(getNestedValue(obj, "a.b.c.d")).toBeUndefined();
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
test("T1.11 - hasValue returns true for filled", async () => {
|
|
271
|
-
const { hasValue } = await import("../lib/parser.ts");
|
|
272
|
-
expect(hasValue({ name: "test" }, "name")).toBe(true);
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
test("T1.12 - hasValue returns false for empty string", async () => {
|
|
276
|
-
const { hasValue } = await import("../lib/parser.ts");
|
|
277
|
-
expect(hasValue({ name: "" }, "name")).toBe(false);
|
|
278
|
-
expect(hasValue({ name: " " }, "name")).toBe(false);
|
|
279
|
-
});
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
283
|
-
// TIER 2: SCORING ENGINE (25%)
|
|
284
|
-
// Wolfejam slot-based scoring - the math must be exact
|
|
285
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
286
|
-
|
|
287
|
-
describe("Tier 2: Scoring Engine", () => {
|
|
288
|
-
// ★ expect.assertions() - Ensure exact assertion count
|
|
289
|
-
test("T2.01 - Empty FAF scores 0%", async () => {
|
|
290
|
-
expect.assertions(2);
|
|
291
|
-
const { calculateScore } = await import("../lib/scorer.ts");
|
|
292
|
-
const result = calculateScore({});
|
|
293
|
-
expect(result.score).toBe(0);
|
|
294
|
-
expect(result.filled).toBe(0);
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
test("T2.02 - CLI type has 9 applicable slots", async () => {
|
|
298
|
-
expect.hasAssertions();
|
|
299
|
-
const { calculateScore } = await import("../lib/scorer.ts");
|
|
300
|
-
const cliFaf = { project: { type: "cli" } };
|
|
301
|
-
const result = calculateScore(cliFaf);
|
|
302
|
-
expect(result.projectType).toBe("cli");
|
|
303
|
-
expect(result.total).toBe(9);
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
test("T2.03 - Fullstack type has 21 applicable slots", async () => {
|
|
307
|
-
const { calculateScore } = await import("../lib/scorer.ts");
|
|
308
|
-
const fullFaf = { project: { type: "fullstack" } };
|
|
309
|
-
const result = calculateScore(fullFaf);
|
|
310
|
-
expect(result.projectType).toBe("fullstack");
|
|
311
|
-
expect(result.total).toBe(21);
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
test("T2.04 - Full CLI scores 100%", async () => {
|
|
315
|
-
const { calculateScore } = await import("../lib/scorer.ts");
|
|
316
|
-
const fullCli = {
|
|
317
|
-
project: {
|
|
318
|
-
type: "cli",
|
|
319
|
-
name: "test",
|
|
320
|
-
goal: "testing",
|
|
321
|
-
main_language: "TypeScript",
|
|
322
|
-
},
|
|
323
|
-
human_context: {
|
|
324
|
-
who: "developers",
|
|
325
|
-
what: "a tool",
|
|
326
|
-
why: "to help",
|
|
327
|
-
where: "terminal",
|
|
328
|
-
when: "always",
|
|
329
|
-
how: "bun run",
|
|
330
|
-
},
|
|
331
|
-
};
|
|
332
|
-
const result = calculateScore(fullCli);
|
|
333
|
-
expect(result.score).toBe(100);
|
|
334
|
-
expect(result.filled).toBe(9);
|
|
335
|
-
expect(result.total).toBe(9);
|
|
336
|
-
});
|
|
337
|
-
|
|
338
|
-
test("T2.05 - Partial CLI scores correctly", async () => {
|
|
339
|
-
const { calculateScore } = await import("../lib/scorer.ts");
|
|
340
|
-
const partial = {
|
|
341
|
-
project: { type: "cli", name: "test" },
|
|
342
|
-
};
|
|
343
|
-
const result = calculateScore(partial);
|
|
344
|
-
expect(result.filled).toBe(1);
|
|
345
|
-
expect(result.total).toBe(9);
|
|
346
|
-
expect(result.score).toBe(11);
|
|
347
|
-
});
|
|
348
|
-
|
|
349
|
-
test("T2.06 - 21 total slots defined", async () => {
|
|
350
|
-
const { SLOTS } = await import("../lib/scorer.ts");
|
|
351
|
-
const totalSlots =
|
|
352
|
-
SLOTS.project.length +
|
|
353
|
-
SLOTS.frontend.length +
|
|
354
|
-
SLOTS.backend.length +
|
|
355
|
-
SLOTS.universal.length +
|
|
356
|
-
SLOTS.human.length;
|
|
357
|
-
expect(totalSlots).toBe(21);
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
test("T2.07 - SLOTS structure snapshot", async () => {
|
|
361
|
-
const { SLOTS } = await import("../lib/scorer.ts");
|
|
362
|
-
expect(SLOTS).toMatchSnapshot();
|
|
363
|
-
});
|
|
364
|
-
|
|
365
|
-
// ★ test.each() with describe.each pattern
|
|
366
|
-
test.each([
|
|
367
|
-
["project", 3],
|
|
368
|
-
["frontend", 4],
|
|
369
|
-
["backend", 5],
|
|
370
|
-
["universal", 3],
|
|
371
|
-
["human", 6],
|
|
372
|
-
] as const)("T2.08 - %s section has %d slots", async (section, count) => {
|
|
373
|
-
const { SLOTS } = await import("../lib/scorer.ts");
|
|
374
|
-
expect(SLOTS[section].length).toBe(count);
|
|
375
|
-
});
|
|
376
|
-
|
|
377
|
-
test.each([
|
|
378
|
-
["cli", 9],
|
|
379
|
-
["library", 9],
|
|
380
|
-
["api", 17],
|
|
381
|
-
["webapp", 16],
|
|
382
|
-
["fullstack", 21],
|
|
383
|
-
["mobile", 9],
|
|
384
|
-
["unknown", 9],
|
|
385
|
-
] as const)("T2.09 - Type '%s' has %d slots", async (type, slots) => {
|
|
386
|
-
const { calculateScore } = await import("../lib/scorer.ts");
|
|
387
|
-
const faf = { project: { type } };
|
|
388
|
-
const result = calculateScore(faf);
|
|
389
|
-
expect(result.total).toBe(slots);
|
|
390
|
-
});
|
|
391
|
-
|
|
392
|
-
test("T2.10 - Type detection infers fullstack", async () => {
|
|
393
|
-
const { detectProjectType } = await import("../lib/scorer.ts");
|
|
394
|
-
const faf = { stack: { frontend: "React", backend: "Express" } };
|
|
395
|
-
expect(detectProjectType(faf)).toBe("fullstack");
|
|
396
|
-
});
|
|
397
|
-
|
|
398
|
-
test("T2.11 - Type detection infers webapp", async () => {
|
|
399
|
-
const { detectProjectType } = await import("../lib/scorer.ts");
|
|
400
|
-
const faf = { stack: { frontend: "React" } };
|
|
401
|
-
expect(detectProjectType(faf)).toBe("webapp");
|
|
402
|
-
});
|
|
403
|
-
|
|
404
|
-
test("T2.12 - Type detection infers api", async () => {
|
|
405
|
-
const { detectProjectType } = await import("../lib/scorer.ts");
|
|
406
|
-
const faf = { stack: { database: "PostgreSQL" } };
|
|
407
|
-
expect(detectProjectType(faf)).toBe("api");
|
|
408
|
-
});
|
|
409
|
-
|
|
410
|
-
// ★ Custom matcher usage
|
|
411
|
-
test("T2.13 - Score is valid (custom matcher)", async () => {
|
|
412
|
-
const { calculateScore } = await import("../lib/scorer.ts");
|
|
413
|
-
const result = calculateScore({ project: { name: "test" } });
|
|
414
|
-
expect(result.score).toBeValidScore();
|
|
415
|
-
});
|
|
416
|
-
|
|
417
|
-
test("T2.14 - Full CLI result snapshot", async () => {
|
|
418
|
-
const { calculateScore } = await import("../lib/scorer.ts");
|
|
419
|
-
const fullCli = {
|
|
420
|
-
project: {
|
|
421
|
-
type: "cli",
|
|
422
|
-
name: "test",
|
|
423
|
-
goal: "goal",
|
|
424
|
-
main_language: "TS",
|
|
425
|
-
},
|
|
426
|
-
human_context: {
|
|
427
|
-
who: "a",
|
|
428
|
-
what: "b",
|
|
429
|
-
why: "c",
|
|
430
|
-
where: "d",
|
|
431
|
-
when: "e",
|
|
432
|
-
how: "f",
|
|
433
|
-
},
|
|
434
|
-
};
|
|
435
|
-
const result = calculateScore(fullCli);
|
|
436
|
-
expect(result).toMatchSnapshot();
|
|
437
|
-
});
|
|
438
|
-
|
|
439
|
-
test("T2.15 - TYPE_CATEGORIES snapshot", async () => {
|
|
440
|
-
const { TYPE_CATEGORIES } = await import("../lib/scorer.ts");
|
|
441
|
-
expect(TYPE_CATEGORIES).toMatchSnapshot();
|
|
442
|
-
});
|
|
443
|
-
});
|
|
444
|
-
|
|
445
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
446
|
-
// TIER 3: TIER SYSTEM (15%)
|
|
447
|
-
// Medals must be correct
|
|
448
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
449
|
-
|
|
450
|
-
describe("Tier 3: Tier System", () => {
|
|
451
|
-
// ★ test.each() - All tier boundaries
|
|
452
|
-
test.each([
|
|
453
|
-
[110, "🍊", "Big Orange"],
|
|
454
|
-
[105, "🍊", "Big Orange"],
|
|
455
|
-
[100, "🏆", "Trophy"],
|
|
456
|
-
[99, "🥇", "Gold"],
|
|
457
|
-
[98, "🥈", "Silver"],
|
|
458
|
-
[95, "🥈", "Silver"],
|
|
459
|
-
[94, "🥉", "Bronze"],
|
|
460
|
-
[85, "🥉", "Bronze"],
|
|
461
|
-
[84, "🟢", "Green"],
|
|
462
|
-
[70, "🟢", "Green"],
|
|
463
|
-
[69, "🟡", "Yellow"],
|
|
464
|
-
[55, "🟡", "Yellow"],
|
|
465
|
-
[54, "🔴", "Red"],
|
|
466
|
-
[1, "🔴", "Red"],
|
|
467
|
-
[0, "⚪", "Empty"],
|
|
468
|
-
] as const)("T3.01-%03d%% = %s %s", async (score, emoji, name) => {
|
|
469
|
-
const { getTier } = await import("../lib/tier.ts");
|
|
470
|
-
const tier = getTier(score);
|
|
471
|
-
expect(tier.emoji).toBe(emoji);
|
|
472
|
-
expect(tier.name).toBe(name);
|
|
473
|
-
});
|
|
474
|
-
|
|
475
|
-
test("T3.02 - isLaunchReady boundary", async () => {
|
|
476
|
-
const { isLaunchReady } = await import("../lib/tier.ts");
|
|
477
|
-
expect(isLaunchReady(84)).toBe(false);
|
|
478
|
-
expect(isLaunchReady(85)).toBe(true);
|
|
479
|
-
expect(isLaunchReady(100)).toBe(true);
|
|
480
|
-
});
|
|
481
|
-
|
|
482
|
-
test("T3.03 - Tier has color property", async () => {
|
|
483
|
-
const { getTier } = await import("../lib/tier.ts");
|
|
484
|
-
const tier = getTier(100);
|
|
485
|
-
expect(tier).toHaveProperty("color");
|
|
486
|
-
expect(typeof tier.color).toBe("string");
|
|
487
|
-
});
|
|
488
|
-
|
|
489
|
-
// ★ Custom matcher
|
|
490
|
-
test("T3.04 - All tiers are valid (custom matcher)", async () => {
|
|
491
|
-
const { getTier } = await import("../lib/tier.ts");
|
|
492
|
-
for (const score of [0, 50, 70, 85, 95, 99, 100, 105]) {
|
|
493
|
-
expect(getTier(score)).toBeValidTier();
|
|
494
|
-
}
|
|
495
|
-
});
|
|
496
|
-
|
|
497
|
-
test("T3.05 - Tier color contains ANSI escape", async () => {
|
|
498
|
-
const { getTier } = await import("../lib/tier.ts");
|
|
499
|
-
const tier = getTier(100);
|
|
500
|
-
expect(tier.color).toContain("\x1b[");
|
|
501
|
-
});
|
|
502
|
-
});
|
|
503
|
-
|
|
504
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
505
|
-
// TIER 4: CLI COMMANDS (15%)
|
|
506
|
-
// Commands must work
|
|
507
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
508
|
-
|
|
509
|
-
describe("Tier 4: CLI Commands", () => {
|
|
510
|
-
const CLI = "./index.ts";
|
|
511
|
-
|
|
512
|
-
test("T4.01 - --version returns version", async () => {
|
|
513
|
-
const result = await $`bun run ${CLI} --version`.text();
|
|
514
|
-
expect(result.trim()).toMatch(/^bun-sticky v\d+\.\d+\.\d+$/);
|
|
515
|
-
});
|
|
516
|
-
|
|
517
|
-
test("T4.02 - help shows all commands", async () => {
|
|
518
|
-
const result = await $`bun run ${CLI} help`.text();
|
|
519
|
-
expect(result).toContain("score");
|
|
520
|
-
expect(result).toContain("init");
|
|
521
|
-
expect(result).toContain("sync");
|
|
522
|
-
expect(result).toContain("version");
|
|
523
|
-
expect(result).toContain("help");
|
|
524
|
-
});
|
|
525
|
-
|
|
526
|
-
test("T4.03 - unknown command shows help", async () => {
|
|
527
|
-
const result = await $`bun run ${CLI} unknown`.text();
|
|
528
|
-
expect(result).toContain("Commands");
|
|
529
|
-
});
|
|
530
|
-
|
|
531
|
-
test("T4.04 - Banner shows Bun Sticky", async () => {
|
|
532
|
-
const result = await $`bun run ${CLI} help`.text();
|
|
533
|
-
expect(result).toContain("Bun Sticky");
|
|
534
|
-
expect(result).toContain("🥐");
|
|
535
|
-
});
|
|
536
|
-
|
|
537
|
-
test("T4.05 - Banner shows tagline", async () => {
|
|
538
|
-
const result = await $`bun run ${CLI} help`.text();
|
|
539
|
-
expect(result).toContain("Fastest bun under the sum");
|
|
540
|
-
});
|
|
541
|
-
|
|
542
|
-
// ★ test.each() - Flag variants
|
|
543
|
-
test.each(["--version", "-v", "version"])(
|
|
544
|
-
"T4.06 - '%s' returns version",
|
|
545
|
-
async (flag) => {
|
|
546
|
-
const result = await $`bun run ${CLI} ${flag}`.text();
|
|
547
|
-
expect(result).toContain("bun-sticky v");
|
|
548
|
-
}
|
|
549
|
-
);
|
|
550
|
-
|
|
551
|
-
test.each(["--help", "-h", "help"])(
|
|
552
|
-
"T4.07 - '%s' shows help",
|
|
553
|
-
async (flag) => {
|
|
554
|
-
const result = await $`bun run ${CLI} ${flag}`.text();
|
|
555
|
-
expect(result).toContain("Commands");
|
|
556
|
-
}
|
|
557
|
-
);
|
|
558
|
-
|
|
559
|
-
test("T4.08 - Score shows project name", async () => {
|
|
560
|
-
const result = await $`bun run ${CLI} score`.text();
|
|
561
|
-
expect(result).toContain("Project:");
|
|
562
|
-
});
|
|
563
|
-
|
|
564
|
-
test("T4.09 - Score shows type", async () => {
|
|
565
|
-
const result = await $`bun run ${CLI} score`.text();
|
|
566
|
-
expect(result).toContain("Type:");
|
|
567
|
-
});
|
|
568
|
-
|
|
569
|
-
test("T4.10 - Score shows percentage", async () => {
|
|
570
|
-
const result = await $`bun run ${CLI} score`.text();
|
|
571
|
-
expect(result).toMatch(/\d+%/);
|
|
572
|
-
});
|
|
573
|
-
});
|
|
574
|
-
|
|
575
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
576
|
-
// TIER 5: FILE OPERATIONS (10%)
|
|
577
|
-
// Bun.file() must work
|
|
578
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
579
|
-
|
|
580
|
-
describe("Tier 5: File Operations", () => {
|
|
581
|
-
const TEST_DIR = "/tmp/bun-sticky-test-" + Date.now();
|
|
582
|
-
|
|
583
|
-
beforeAll(async () => {
|
|
584
|
-
await $`mkdir -p ${TEST_DIR}`;
|
|
585
|
-
});
|
|
586
|
-
|
|
587
|
-
afterAll(async () => {
|
|
588
|
-
await $`rm -rf ${TEST_DIR}`;
|
|
589
|
-
});
|
|
590
|
-
|
|
591
|
-
test("T5.01 - Init creates project.faf", async () => {
|
|
592
|
-
await $`cd ${TEST_DIR} && bun run ${process.cwd()}/index.ts init test-project`;
|
|
593
|
-
const file = Bun.file(`${TEST_DIR}/project.faf`);
|
|
594
|
-
expect(await file.exists()).toBe(true);
|
|
595
|
-
});
|
|
596
|
-
|
|
597
|
-
test("T5.02 - Init includes project name", async () => {
|
|
598
|
-
const content = await Bun.file(`${TEST_DIR}/project.faf`).text();
|
|
599
|
-
expect(content).toContain("test-project");
|
|
600
|
-
});
|
|
601
|
-
|
|
602
|
-
test("T5.03 - Init includes faf_version", async () => {
|
|
603
|
-
const content = await Bun.file(`${TEST_DIR}/project.faf`).text();
|
|
604
|
-
expect(content).toContain("faf_version:");
|
|
605
|
-
});
|
|
606
|
-
|
|
607
|
-
test("T5.04 - Sync creates CLAUDE.md", async () => {
|
|
608
|
-
await $`cd ${TEST_DIR} && bun run ${process.cwd()}/index.ts sync`;
|
|
609
|
-
const file = Bun.file(`${TEST_DIR}/CLAUDE.md`);
|
|
610
|
-
expect(await file.exists()).toBe(true);
|
|
611
|
-
});
|
|
612
|
-
|
|
613
|
-
test("T5.05 - CLAUDE.md contains project name", async () => {
|
|
614
|
-
const content = await Bun.file(`${TEST_DIR}/CLAUDE.md`).text();
|
|
615
|
-
expect(content).toContain("test-project");
|
|
616
|
-
});
|
|
617
|
-
|
|
618
|
-
test("T5.06 - CLAUDE.md contains score", async () => {
|
|
619
|
-
const content = await Bun.file(`${TEST_DIR}/CLAUDE.md`).text();
|
|
620
|
-
expect(content).toMatch(/\d+%/);
|
|
621
|
-
});
|
|
622
|
-
|
|
623
|
-
test("T5.07 - Bun.file() size check", async () => {
|
|
624
|
-
const file = Bun.file(`${TEST_DIR}/project.faf`);
|
|
625
|
-
expect(file.size).toBeGreaterThan(0);
|
|
626
|
-
});
|
|
627
|
-
});
|
|
628
|
-
|
|
629
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
630
|
-
// TIER 6: PERFORMANCE (10%)
|
|
631
|
-
// Speed is the mission
|
|
632
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
633
|
-
|
|
634
|
-
describe("Tier 6: Performance", () => {
|
|
635
|
-
test("T6.01 - Cold start under 50ms", async () => {
|
|
636
|
-
const start = performance.now();
|
|
637
|
-
await $`bun run ./index.ts --version`.quiet();
|
|
638
|
-
const elapsed = performance.now() - start;
|
|
639
|
-
expect(elapsed).toBeLessThan(50);
|
|
640
|
-
});
|
|
641
|
-
|
|
642
|
-
test("T6.02 - Score command under 100ms", async () => {
|
|
643
|
-
const start = performance.now();
|
|
644
|
-
await $`bun run ./index.ts score`.quiet();
|
|
645
|
-
const elapsed = performance.now() - start;
|
|
646
|
-
expect(elapsed).toBeLessThan(100);
|
|
647
|
-
});
|
|
648
|
-
|
|
649
|
-
test("T6.03 - Help under 50ms", async () => {
|
|
650
|
-
const start = performance.now();
|
|
651
|
-
await $`bun run ./index.ts help`.quiet();
|
|
652
|
-
const elapsed = performance.now() - start;
|
|
653
|
-
expect(elapsed).toBeLessThan(50);
|
|
654
|
-
});
|
|
655
|
-
|
|
656
|
-
test("T6.04 - 10x faster than 334ms Node baseline", async () => {
|
|
657
|
-
const NODE_BASELINE = 334;
|
|
658
|
-
const TARGET = NODE_BASELINE / 10 + 20; // 53.4ms with generous margin
|
|
659
|
-
|
|
660
|
-
const start = performance.now();
|
|
661
|
-
await $`bun run ./index.ts score`.quiet();
|
|
662
|
-
const elapsed = performance.now() - start;
|
|
663
|
-
|
|
664
|
-
expect(elapsed).toBeLessThan(TARGET);
|
|
665
|
-
});
|
|
666
|
-
|
|
667
|
-
// ★ test.concurrent() - Parallel execution
|
|
668
|
-
test.concurrent("T6.05 - Concurrent: version", async () => {
|
|
669
|
-
const start = performance.now();
|
|
670
|
-
await $`bun run ./index.ts --version`.quiet();
|
|
671
|
-
expect(performance.now() - start).toBeLessThan(100);
|
|
672
|
-
});
|
|
673
|
-
|
|
674
|
-
test.concurrent("T6.06 - Concurrent: help", async () => {
|
|
675
|
-
const start = performance.now();
|
|
676
|
-
await $`bun run ./index.ts help`.quiet();
|
|
677
|
-
expect(performance.now() - start).toBeLessThan(100);
|
|
678
|
-
});
|
|
679
|
-
|
|
680
|
-
test.concurrent("T6.07 - Concurrent: score", async () => {
|
|
681
|
-
const start = performance.now();
|
|
682
|
-
await $`bun run ./index.ts score`.quiet();
|
|
683
|
-
expect(performance.now() - start).toBeLessThan(100);
|
|
684
|
-
});
|
|
685
|
-
});
|
|
686
|
-
|
|
687
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
688
|
-
// TIER 7: WJTTC CHAMPIONSHIP (5%)
|
|
689
|
-
// The championship extras
|
|
690
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
691
|
-
|
|
692
|
-
describe("Tier 7: WJTTC Championship", () => {
|
|
693
|
-
test("T7.01 - Zero dependencies", async () => {
|
|
694
|
-
const pkg = await Bun.file("./package.json").json();
|
|
695
|
-
const deps = Object.keys(pkg.dependencies || {});
|
|
696
|
-
expect(deps.length).toBe(0);
|
|
697
|
-
});
|
|
698
|
-
|
|
699
|
-
test("T7.02 - Pure Bun APIs only", async () => {
|
|
700
|
-
const content = await Bun.file("./index.ts").text();
|
|
701
|
-
expect(content).not.toContain("require(");
|
|
702
|
-
expect(content).not.toContain("from 'fs'");
|
|
703
|
-
expect(content).not.toContain("from 'path'");
|
|
704
|
-
});
|
|
705
|
-
|
|
706
|
-
test("T7.03 - TypeScript native (no build step)", async () => {
|
|
707
|
-
const files = await $`ls *.ts`.text();
|
|
708
|
-
expect(files).toContain("index.ts");
|
|
709
|
-
const hasDist = await Bun.file("./dist").exists();
|
|
710
|
-
expect(hasDist).toBe(false);
|
|
711
|
-
});
|
|
712
|
-
|
|
713
|
-
test("T7.04 - Single entry point", async () => {
|
|
714
|
-
const pkg = await Bun.file("./package.json").json();
|
|
715
|
-
expect(pkg.main).toBe("index.ts");
|
|
716
|
-
});
|
|
717
|
-
|
|
718
|
-
test("T7.05 - Croissant branding present", async () => {
|
|
719
|
-
const content = await Bun.file("./index.ts").text();
|
|
720
|
-
expect(content).toContain("🥐");
|
|
721
|
-
expect(content).toContain("Bun Sticky");
|
|
722
|
-
expect(content).toContain("Fastest bun under the sum");
|
|
723
|
-
});
|
|
724
|
-
|
|
725
|
-
test("T7.06 - Package.json metadata", async () => {
|
|
726
|
-
const pkg = await Bun.file("./package.json").json();
|
|
727
|
-
expect(pkg.name).toBe("bun-sticky");
|
|
728
|
-
expect(pkg.type).toBe("module");
|
|
729
|
-
expect(pkg).toHaveProperty("bin");
|
|
730
|
-
});
|
|
731
|
-
|
|
732
|
-
test("T7.07 - Wolfejam scoring (NOT Elon weights)", async () => {
|
|
733
|
-
const content = await Bun.file("./lib/scorer.ts").text();
|
|
734
|
-
expect(content).toContain("SLOTS");
|
|
735
|
-
expect(content).not.toContain("0.40");
|
|
736
|
-
expect(content).not.toContain("0.35");
|
|
737
|
-
expect(content).not.toContain("0.15");
|
|
738
|
-
expect(content).not.toContain("0.10");
|
|
739
|
-
});
|
|
740
|
-
});
|
|
741
|
-
|
|
742
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
743
|
-
// TIER 8: MOCKING & SPYING
|
|
744
|
-
// Advanced Bun test features
|
|
745
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
746
|
-
|
|
747
|
-
describe("Tier 8: Mocking & Spying", () => {
|
|
748
|
-
test("T8.01 - Mock function tracks calls", () => {
|
|
749
|
-
const mockFn = mock(() => 42);
|
|
750
|
-
mockFn();
|
|
751
|
-
mockFn();
|
|
752
|
-
mockFn();
|
|
753
|
-
expect(mockFn).toHaveBeenCalledTimes(3);
|
|
754
|
-
});
|
|
755
|
-
|
|
756
|
-
test("T8.02 - Mock function returns value", () => {
|
|
757
|
-
const mockFn = mock(() => "mocked");
|
|
758
|
-
expect(mockFn()).toBe("mocked");
|
|
759
|
-
});
|
|
760
|
-
|
|
761
|
-
test("T8.03 - Mock with implementation", () => {
|
|
762
|
-
const mockFn = mock((x: number) => x * 2);
|
|
763
|
-
expect(mockFn(5)).toBe(10);
|
|
764
|
-
expect(mockFn).toHaveBeenCalledWith(5);
|
|
765
|
-
});
|
|
766
|
-
|
|
767
|
-
test("T8.04 - Mock tracks arguments", () => {
|
|
768
|
-
const mockFn = mock((a: string, b: number) => `${a}${b}`);
|
|
769
|
-
mockFn("test", 123);
|
|
770
|
-
expect(mockFn).toHaveBeenCalledWith("test", 123);
|
|
771
|
-
});
|
|
772
|
-
|
|
773
|
-
test("T8.05 - Mock reset", () => {
|
|
774
|
-
const mockFn = mock(() => 1);
|
|
775
|
-
mockFn();
|
|
776
|
-
mockFn();
|
|
777
|
-
expect(mockFn).toHaveBeenCalledTimes(2);
|
|
778
|
-
mockFn.mockClear();
|
|
779
|
-
expect(mockFn).toHaveBeenCalledTimes(0);
|
|
780
|
-
});
|
|
781
|
-
|
|
782
|
-
test("T8.06 - Spy on console.log", () => {
|
|
783
|
-
const spy = spyOn(console, "log").mockImplementation(() => {});
|
|
784
|
-
console.log("test message");
|
|
785
|
-
expect(spy).toHaveBeenCalledWith("test message");
|
|
786
|
-
spy.mockRestore();
|
|
787
|
-
});
|
|
788
|
-
|
|
789
|
-
test("T8.07 - Spy on console.error", () => {
|
|
790
|
-
const spy = spyOn(console, "error").mockImplementation(() => {});
|
|
791
|
-
console.error("error message");
|
|
792
|
-
expect(spy).toHaveBeenCalledWith("error message");
|
|
793
|
-
spy.mockRestore();
|
|
794
|
-
});
|
|
795
|
-
|
|
796
|
-
test("T8.08 - Mock implementation change", () => {
|
|
797
|
-
const mockFn = mock(() => 1);
|
|
798
|
-
expect(mockFn()).toBe(1);
|
|
799
|
-
mockFn.mockImplementation(() => 2);
|
|
800
|
-
expect(mockFn()).toBe(2);
|
|
801
|
-
});
|
|
802
|
-
|
|
803
|
-
test("T8.09 - Mock return value", () => {
|
|
804
|
-
const mockFn = mock(() => 0);
|
|
805
|
-
mockFn.mockReturnValue(42);
|
|
806
|
-
expect(mockFn()).toBe(42);
|
|
807
|
-
});
|
|
808
|
-
});
|
|
809
|
-
|
|
810
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
811
|
-
// TIER 9: TIME MOCKING
|
|
812
|
-
// setSystemTime() - Control time itself
|
|
813
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
814
|
-
|
|
815
|
-
describe("Tier 9: Time Mocking", () => {
|
|
816
|
-
afterEach(() => {
|
|
817
|
-
setSystemTime(); // Reset to real time
|
|
818
|
-
});
|
|
819
|
-
|
|
820
|
-
test("T9.01 - setSystemTime() freezes time", () => {
|
|
821
|
-
const fixedDate = new Date("2025-01-01T00:00:00Z");
|
|
822
|
-
setSystemTime(fixedDate);
|
|
823
|
-
expect(new Date().getTime()).toBe(fixedDate.getTime());
|
|
824
|
-
});
|
|
825
|
-
|
|
826
|
-
test("T9.02 - Time can be set to any date", () => {
|
|
827
|
-
const past = new Date("2000-01-01T00:00:00Z");
|
|
828
|
-
setSystemTime(past);
|
|
829
|
-
expect(new Date().getFullYear()).toBe(2000);
|
|
830
|
-
});
|
|
831
|
-
|
|
832
|
-
test("T9.03 - Date.now() respects mocked time", () => {
|
|
833
|
-
const fixed = new Date("2025-06-15T12:00:00Z");
|
|
834
|
-
setSystemTime(fixed);
|
|
835
|
-
expect(Date.now()).toBe(fixed.getTime());
|
|
836
|
-
});
|
|
837
|
-
|
|
838
|
-
test("T9.04 - Reset to real time", () => {
|
|
839
|
-
setSystemTime(new Date("1999-01-01"));
|
|
840
|
-
setSystemTime(); // Reset
|
|
841
|
-
expect(new Date().getFullYear()).toBeGreaterThanOrEqual(2024);
|
|
842
|
-
});
|
|
843
|
-
});
|
|
844
|
-
|
|
845
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
846
|
-
// TIER 10: EXTENDED MATCHERS
|
|
847
|
-
// Full matcher coverage - 40+ matchers
|
|
848
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
849
|
-
|
|
850
|
-
describe("Tier 10: Extended Matchers", () => {
|
|
851
|
-
// Equality
|
|
852
|
-
test("T10.01 - toBe", () => {
|
|
853
|
-
expect(1).toBe(1);
|
|
854
|
-
expect("a").toBe("a");
|
|
855
|
-
});
|
|
856
|
-
|
|
857
|
-
test("T10.02 - toEqual", () => {
|
|
858
|
-
expect({ a: 1 }).toEqual({ a: 1 });
|
|
859
|
-
expect([1, 2]).toEqual([1, 2]);
|
|
860
|
-
});
|
|
861
|
-
|
|
862
|
-
test("T10.03 - toStrictEqual", () => {
|
|
863
|
-
expect({ a: 1 }).toStrictEqual({ a: 1 });
|
|
864
|
-
});
|
|
865
|
-
|
|
866
|
-
// Truthiness
|
|
867
|
-
test("T10.04 - toBeTruthy / toBeFalsy", () => {
|
|
868
|
-
expect(1).toBeTruthy();
|
|
869
|
-
expect("a").toBeTruthy();
|
|
870
|
-
expect(0).toBeFalsy();
|
|
871
|
-
expect("").toBeFalsy();
|
|
872
|
-
});
|
|
873
|
-
|
|
874
|
-
test("T10.05 - toBeNull / toBeUndefined / toBeDefined", () => {
|
|
875
|
-
expect(null).toBeNull();
|
|
876
|
-
expect(undefined).toBeUndefined();
|
|
877
|
-
expect(1).toBeDefined();
|
|
878
|
-
});
|
|
879
|
-
|
|
880
|
-
test("T10.06 - toBeNaN", () => {
|
|
881
|
-
expect(NaN).toBeNaN();
|
|
882
|
-
expect(0 / 0).toBeNaN();
|
|
883
|
-
});
|
|
884
|
-
|
|
885
|
-
// Numbers
|
|
886
|
-
test("T10.07 - toBeGreaterThan / toBeLessThan", () => {
|
|
887
|
-
expect(10).toBeGreaterThan(5);
|
|
888
|
-
expect(5).toBeLessThan(10);
|
|
889
|
-
});
|
|
890
|
-
|
|
891
|
-
test("T10.08 - toBeGreaterThanOrEqual / toBeLessThanOrEqual", () => {
|
|
892
|
-
expect(10).toBeGreaterThanOrEqual(10);
|
|
893
|
-
expect(10).toBeLessThanOrEqual(10);
|
|
894
|
-
});
|
|
895
|
-
|
|
896
|
-
test("T10.09 - toBeCloseTo", () => {
|
|
897
|
-
expect(0.1 + 0.2).toBeCloseTo(0.3, 5);
|
|
898
|
-
});
|
|
899
|
-
|
|
900
|
-
// Strings
|
|
901
|
-
test("T10.10 - toContain (string)", () => {
|
|
902
|
-
expect("hello world").toContain("world");
|
|
903
|
-
});
|
|
904
|
-
|
|
905
|
-
test("T10.11 - toMatch (regex)", () => {
|
|
906
|
-
expect("hello world").toMatch(/world/);
|
|
907
|
-
expect("test123").toMatch(/\d+/);
|
|
908
|
-
});
|
|
909
|
-
|
|
910
|
-
test("T10.12 - toStartWith / toEndWith", () => {
|
|
911
|
-
expect("hello world").toStartWith("hello");
|
|
912
|
-
expect("hello world").toEndWith("world");
|
|
913
|
-
});
|
|
914
|
-
|
|
915
|
-
// Arrays
|
|
916
|
-
test("T10.13 - toContain (array)", () => {
|
|
917
|
-
expect([1, 2, 3]).toContain(2);
|
|
918
|
-
});
|
|
919
|
-
|
|
920
|
-
test("T10.14 - toContainEqual", () => {
|
|
921
|
-
expect([{ a: 1 }, { b: 2 }]).toContainEqual({ a: 1 });
|
|
922
|
-
});
|
|
923
|
-
|
|
924
|
-
test("T10.15 - toHaveLength", () => {
|
|
925
|
-
expect([1, 2, 3]).toHaveLength(3);
|
|
926
|
-
expect("hello").toHaveLength(5);
|
|
927
|
-
});
|
|
928
|
-
|
|
929
|
-
// Objects
|
|
930
|
-
test("T10.16 - toHaveProperty", () => {
|
|
931
|
-
expect({ a: { b: 1 } }).toHaveProperty("a.b", 1);
|
|
932
|
-
});
|
|
933
|
-
|
|
934
|
-
test("T10.17 - toMatchObject", () => {
|
|
935
|
-
expect({ a: 1, b: 2 }).toMatchObject({ a: 1 });
|
|
936
|
-
});
|
|
937
|
-
|
|
938
|
-
// Types
|
|
939
|
-
test("T10.18 - toBeInstanceOf", () => {
|
|
940
|
-
expect([]).toBeInstanceOf(Array);
|
|
941
|
-
expect(new Date()).toBeInstanceOf(Date);
|
|
942
|
-
});
|
|
943
|
-
|
|
944
|
-
test("T10.19 - toBeTypeOf", () => {
|
|
945
|
-
expect("hello").toBeTypeOf("string");
|
|
946
|
-
expect(123).toBeTypeOf("number");
|
|
947
|
-
expect({}).toBeTypeOf("object");
|
|
948
|
-
});
|
|
949
|
-
|
|
950
|
-
// Errors
|
|
951
|
-
test("T10.20 - toThrow", () => {
|
|
952
|
-
expect(() => {
|
|
953
|
-
throw new Error("test");
|
|
954
|
-
}).toThrow();
|
|
955
|
-
expect(() => {
|
|
956
|
-
throw new Error("test");
|
|
957
|
-
}).toThrow("test");
|
|
958
|
-
});
|
|
959
|
-
|
|
960
|
-
test("T10.21 - toThrowError", () => {
|
|
961
|
-
expect(() => {
|
|
962
|
-
throw new TypeError("type error");
|
|
963
|
-
}).toThrowError(TypeError);
|
|
964
|
-
});
|
|
965
|
-
|
|
966
|
-
// Negation
|
|
967
|
-
test("T10.22 - .not modifier", () => {
|
|
968
|
-
expect(1).not.toBe(2);
|
|
969
|
-
expect([1, 2]).not.toContain(3);
|
|
970
|
-
expect("hello").not.toMatch(/xyz/);
|
|
971
|
-
});
|
|
972
|
-
|
|
973
|
-
// Async
|
|
974
|
-
test("T10.23 - resolves", async () => {
|
|
975
|
-
await expect(Promise.resolve(1)).resolves.toBe(1);
|
|
976
|
-
});
|
|
977
|
-
|
|
978
|
-
test("T10.24 - rejects", async () => {
|
|
979
|
-
await expect(Promise.reject(new Error("fail"))).rejects.toThrow("fail");
|
|
980
|
-
});
|
|
981
|
-
});
|
|
982
|
-
|
|
983
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
984
|
-
// TIER 11: LIFECYCLE HOOKS
|
|
985
|
-
// beforeEach / afterEach isolation
|
|
986
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
987
|
-
|
|
988
|
-
describe("Tier 11: Lifecycle Hooks", () => {
|
|
989
|
-
let counter = 0;
|
|
990
|
-
let setupRan = false;
|
|
991
|
-
|
|
992
|
-
beforeAll(() => {
|
|
993
|
-
setupRan = true;
|
|
994
|
-
});
|
|
995
|
-
|
|
996
|
-
beforeEach(() => {
|
|
997
|
-
counter = 0;
|
|
998
|
-
});
|
|
999
|
-
|
|
1000
|
-
afterEach(() => {
|
|
1001
|
-
// Cleanup
|
|
1002
|
-
});
|
|
1003
|
-
|
|
1004
|
-
afterAll(() => {
|
|
1005
|
-
// Final cleanup
|
|
1006
|
-
});
|
|
1007
|
-
|
|
1008
|
-
test("T11.01 - beforeAll ran", () => {
|
|
1009
|
-
expect(setupRan).toBe(true);
|
|
1010
|
-
});
|
|
1011
|
-
|
|
1012
|
-
test("T11.02 - Counter starts at 0", () => {
|
|
1013
|
-
expect(counter).toBe(0);
|
|
1014
|
-
counter++;
|
|
1015
|
-
expect(counter).toBe(1);
|
|
1016
|
-
});
|
|
1017
|
-
|
|
1018
|
-
test("T11.03 - Counter reset by beforeEach", () => {
|
|
1019
|
-
expect(counter).toBe(0);
|
|
1020
|
-
});
|
|
1021
|
-
|
|
1022
|
-
test("T11.04 - Each test isolated", () => {
|
|
1023
|
-
counter = 100;
|
|
1024
|
-
expect(counter).toBe(100);
|
|
1025
|
-
});
|
|
1026
|
-
|
|
1027
|
-
test("T11.05 - Previous test doesn't affect this", () => {
|
|
1028
|
-
expect(counter).toBe(0);
|
|
1029
|
-
});
|
|
1030
|
-
});
|
|
1031
|
-
|
|
1032
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1033
|
-
// TIER 12: ASYNC & PROMISE TESTING
|
|
1034
|
-
// Comprehensive async patterns
|
|
1035
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1036
|
-
|
|
1037
|
-
describe("Tier 12: Async & Promise Testing", () => {
|
|
1038
|
-
test("T12.01 - Async/await test", async () => {
|
|
1039
|
-
const result = await Promise.resolve(42);
|
|
1040
|
-
expect(result).toBe(42);
|
|
1041
|
-
});
|
|
1042
|
-
|
|
1043
|
-
test("T12.02 - Promise.all", async () => {
|
|
1044
|
-
const results = await Promise.all([
|
|
1045
|
-
Promise.resolve(1),
|
|
1046
|
-
Promise.resolve(2),
|
|
1047
|
-
Promise.resolve(3),
|
|
1048
|
-
]);
|
|
1049
|
-
expect(results).toEqual([1, 2, 3]);
|
|
1050
|
-
});
|
|
1051
|
-
|
|
1052
|
-
test("T12.03 - Promise.race", async () => {
|
|
1053
|
-
const result = await Promise.race([
|
|
1054
|
-
Promise.resolve("fast"),
|
|
1055
|
-
new Promise((r) => setTimeout(() => r("slow"), 100)),
|
|
1056
|
-
]);
|
|
1057
|
-
expect(result).toBe("fast");
|
|
1058
|
-
});
|
|
1059
|
-
|
|
1060
|
-
test("T12.04 - Async function returning value", async () => {
|
|
1061
|
-
const asyncFn = async () => {
|
|
1062
|
-
return "async result";
|
|
1063
|
-
};
|
|
1064
|
-
expect(await asyncFn()).toBe("async result");
|
|
1065
|
-
});
|
|
1066
|
-
|
|
1067
|
-
test("T12.05 - expect().resolves", async () => {
|
|
1068
|
-
const promise = Promise.resolve({ data: "test" });
|
|
1069
|
-
await expect(promise).resolves.toEqual({ data: "test" });
|
|
1070
|
-
});
|
|
1071
|
-
|
|
1072
|
-
test("T12.06 - expect().rejects", async () => {
|
|
1073
|
-
const promise = Promise.reject(new Error("rejected"));
|
|
1074
|
-
await expect(promise).rejects.toThrow("rejected");
|
|
1075
|
-
});
|
|
1076
|
-
|
|
1077
|
-
test("T12.07 - Async with timeout", async () => {
|
|
1078
|
-
const delayed = () =>
|
|
1079
|
-
new Promise((r) => setTimeout(() => r("done"), 10));
|
|
1080
|
-
const result = await delayed();
|
|
1081
|
-
expect(result).toBe("done");
|
|
1082
|
-
});
|
|
1083
|
-
});
|
|
1084
|
-
|
|
1085
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1086
|
-
// TIER 13: CONDITIONAL TESTS
|
|
1087
|
-
// test.if() / test.skipIf()
|
|
1088
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1089
|
-
|
|
1090
|
-
describe("Tier 13: Conditional Tests", () => {
|
|
1091
|
-
const isMac = process.platform === "darwin";
|
|
1092
|
-
const isLinux = process.platform === "linux";
|
|
1093
|
-
const isWindows = process.platform === "win32";
|
|
1094
|
-
const isBun = typeof Bun !== "undefined";
|
|
1095
|
-
|
|
1096
|
-
// ★ test.if() - Run if condition true
|
|
1097
|
-
test.if(isBun)("T13.01 - Runs only in Bun", () => {
|
|
1098
|
-
expect(Bun.version).toBeDefined();
|
|
1099
|
-
});
|
|
1100
|
-
|
|
1101
|
-
test.if(isMac)("T13.02 - Runs only on macOS", () => {
|
|
1102
|
-
expect(process.platform).toBe("darwin");
|
|
1103
|
-
});
|
|
1104
|
-
|
|
1105
|
-
// ★ test.skipIf() - Skip if condition true
|
|
1106
|
-
test.skipIf(isWindows)("T13.03 - Skip on Windows", () => {
|
|
1107
|
-
expect(process.platform).not.toBe("win32");
|
|
1108
|
-
});
|
|
1109
|
-
|
|
1110
|
-
test.skipIf(!isBun)("T13.04 - Skip if not Bun", () => {
|
|
1111
|
-
expect(typeof Bun).toBe("object");
|
|
1112
|
-
});
|
|
1113
|
-
|
|
1114
|
-
test.if(true)("T13.05 - Always runs (condition true)", () => {
|
|
1115
|
-
expect(true).toBe(true);
|
|
1116
|
-
});
|
|
1117
|
-
|
|
1118
|
-
test.skipIf(false)("T13.06 - Never skips (condition false)", () => {
|
|
1119
|
-
expect(true).toBe(true);
|
|
1120
|
-
});
|
|
1121
|
-
});
|
|
1122
|
-
|
|
1123
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1124
|
-
// TIER 14: TODO, SKIP, FAILING
|
|
1125
|
-
// Incomplete and expected-to-fail tests
|
|
1126
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1127
|
-
|
|
1128
|
-
describe("Tier 14: Todo, Skip, Failing", () => {
|
|
1129
|
-
// ★ test.todo() - Future work
|
|
1130
|
-
test.todo("T14.01 - TODO: Add YAML multiline support");
|
|
1131
|
-
test.todo("T14.02 - TODO: Add watch mode");
|
|
1132
|
-
test.todo("T14.03 - TODO: Add JSON output format");
|
|
1133
|
-
test.todo("T14.04 - TODO: Add diff command");
|
|
1134
|
-
|
|
1135
|
-
// ★ test.skip() - Skip test
|
|
1136
|
-
test.skip("T14.05 - SKIP: Platform-specific", () => {
|
|
1137
|
-
expect(true).toBe(false);
|
|
1138
|
-
});
|
|
1139
|
-
|
|
1140
|
-
// ★ test.failing() - Expected to fail
|
|
1141
|
-
test.failing("T14.06 - FAILING: This test is expected to fail", () => {
|
|
1142
|
-
expect(1).toBe(2); // Intentionally wrong
|
|
1143
|
-
});
|
|
1144
|
-
|
|
1145
|
-
test.failing("T14.07 - FAILING: Division by zero check", () => {
|
|
1146
|
-
expect(1 / 0).toBe(0); // Infinity, not 0
|
|
1147
|
-
});
|
|
1148
|
-
});
|
|
1149
|
-
|
|
1150
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1151
|
-
// TIER 15: STRESS TESTING
|
|
1152
|
-
// Push the limits
|
|
1153
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1154
|
-
|
|
1155
|
-
describe("Tier 15: Stress Testing", () => {
|
|
1156
|
-
test("T15.01 - 1000 assertions in single test", () => {
|
|
1157
|
-
for (let i = 0; i < 1000; i++) {
|
|
1158
|
-
expect(i).toBeGreaterThanOrEqual(0);
|
|
1159
|
-
}
|
|
1160
|
-
});
|
|
1161
|
-
|
|
1162
|
-
test("T15.02 - Large object comparison", () => {
|
|
1163
|
-
const large: Record<string, number> = {};
|
|
1164
|
-
for (let i = 0; i < 100; i++) {
|
|
1165
|
-
large[`key${i}`] = i;
|
|
1166
|
-
}
|
|
1167
|
-
expect(Object.keys(large).length).toBe(100);
|
|
1168
|
-
});
|
|
1169
|
-
|
|
1170
|
-
test("T15.03 - Deep nesting", () => {
|
|
1171
|
-
let obj: any = { value: "deep" };
|
|
1172
|
-
for (let i = 0; i < 50; i++) {
|
|
1173
|
-
obj = { nested: obj };
|
|
1174
|
-
}
|
|
1175
|
-
let current = obj;
|
|
1176
|
-
for (let i = 0; i < 50; i++) {
|
|
1177
|
-
current = current.nested;
|
|
1178
|
-
}
|
|
1179
|
-
expect(current.value).toBe("deep");
|
|
1180
|
-
});
|
|
1181
|
-
|
|
1182
|
-
test("T15.04 - Rapid mock calls", () => {
|
|
1183
|
-
const mockFn = mock(() => 1);
|
|
1184
|
-
for (let i = 0; i < 1000; i++) {
|
|
1185
|
-
mockFn();
|
|
1186
|
-
}
|
|
1187
|
-
expect(mockFn).toHaveBeenCalledTimes(1000);
|
|
1188
|
-
});
|
|
1189
|
-
|
|
1190
|
-
test("T15.05 - String operations", () => {
|
|
1191
|
-
let str = "";
|
|
1192
|
-
for (let i = 0; i < 1000; i++) {
|
|
1193
|
-
str += "a";
|
|
1194
|
-
}
|
|
1195
|
-
expect(str.length).toBe(1000);
|
|
1196
|
-
});
|
|
1197
|
-
});
|
|
1198
|
-
|
|
1199
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1200
|
-
// TIER 16: EDGE CASES
|
|
1201
|
-
// Break it so it never breaks again
|
|
1202
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1203
|
-
|
|
1204
|
-
describe("Tier 16: Edge Cases", () => {
|
|
1205
|
-
test("T16.01 - Empty string handling", async () => {
|
|
1206
|
-
const { hasValue } = await import("../lib/parser.ts");
|
|
1207
|
-
expect(hasValue({ v: "" }, "v")).toBe(false);
|
|
1208
|
-
});
|
|
1209
|
-
|
|
1210
|
-
test("T16.02 - Null handling", async () => {
|
|
1211
|
-
const { getNestedValue } = await import("../lib/parser.ts");
|
|
1212
|
-
expect(getNestedValue({ a: null }, "a.b")).toBeUndefined();
|
|
1213
|
-
});
|
|
1214
|
-
|
|
1215
|
-
test("T16.03 - Undefined handling", async () => {
|
|
1216
|
-
const { hasValue } = await import("../lib/parser.ts");
|
|
1217
|
-
expect(hasValue({}, "missing")).toBe(false);
|
|
1218
|
-
});
|
|
1219
|
-
|
|
1220
|
-
test("T16.04 - Zero score", async () => {
|
|
1221
|
-
const { calculateScore } = await import("../lib/scorer.ts");
|
|
1222
|
-
const result = calculateScore({});
|
|
1223
|
-
expect(result.score).toBe(0);
|
|
1224
|
-
});
|
|
1225
|
-
|
|
1226
|
-
test("T16.05 - Unknown type defaults to 9 slots", async () => {
|
|
1227
|
-
const { calculateScore } = await import("../lib/scorer.ts");
|
|
1228
|
-
const result = calculateScore({ project: { type: "banana" } });
|
|
1229
|
-
expect(result.total).toBe(9);
|
|
1230
|
-
});
|
|
1231
|
-
|
|
1232
|
-
test("T16.06 - Special characters in name", async () => {
|
|
1233
|
-
const { parseYaml } = await import("../lib/parser.ts");
|
|
1234
|
-
const result = parseYaml("name: test-project_v1.0");
|
|
1235
|
-
expect(result.name).toBe("test-project_v1.0");
|
|
1236
|
-
});
|
|
1237
|
-
|
|
1238
|
-
test("T16.07 - Unicode in values", async () => {
|
|
1239
|
-
const { parseYaml } = await import("../lib/parser.ts");
|
|
1240
|
-
const result = parseYaml("emoji: 🥐");
|
|
1241
|
-
expect(result.emoji).toBe("🥐");
|
|
1242
|
-
});
|
|
1243
|
-
|
|
1244
|
-
test("T16.08 - Very long value", async () => {
|
|
1245
|
-
const { parseYaml } = await import("../lib/parser.ts");
|
|
1246
|
-
const longValue = "a".repeat(1000);
|
|
1247
|
-
const result = parseYaml(`long: ${longValue}`);
|
|
1248
|
-
expect((result.long as string).length).toBe(1000);
|
|
1249
|
-
});
|
|
1250
|
-
});
|
|
1251
|
-
|
|
1252
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1253
|
-
// CHAMPIONSHIP SUMMARY
|
|
1254
|
-
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1255
|
-
|
|
1256
|
-
describe("Championship Summary", () => {
|
|
1257
|
-
test("Print WJTTC Championship Report", () => {
|
|
1258
|
-
console.log(`
|
|
1259
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1260
|
-
🥐 BUN STICKY - WJTTC CHAMPIONSHIP TEST SUITE 🥐
|
|
1261
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1262
|
-
|
|
1263
|
-
THE BEST BUN TEST SUITE IN THE AI ERA
|
|
1264
|
-
"We break it so they never know it was ever broken"
|
|
1265
|
-
|
|
1266
|
-
TIER 0: META TESTING - 12 tests (Test the tests)
|
|
1267
|
-
TIER 1: Core Parsing - 11 tests (20%)
|
|
1268
|
-
TIER 2: Scoring Engine - 15 tests (25%)
|
|
1269
|
-
TIER 3: Tier System - 20 tests (15%)
|
|
1270
|
-
TIER 4: CLI Commands - 10 tests (15%)
|
|
1271
|
-
TIER 5: File Operations - 7 tests (10%)
|
|
1272
|
-
TIER 6: Performance - 7 tests (10%)
|
|
1273
|
-
TIER 7: WJTTC Championship - 7 tests (5%)
|
|
1274
|
-
TIER 8: Mocking & Spying - 9 tests
|
|
1275
|
-
TIER 9: Time Mocking - 4 tests
|
|
1276
|
-
TIER 10: Extended Matchers - 24 tests (40+ matchers)
|
|
1277
|
-
TIER 11: Lifecycle Hooks - 5 tests
|
|
1278
|
-
TIER 12: Async & Promise - 7 tests
|
|
1279
|
-
TIER 13: Conditional Tests - 6 tests
|
|
1280
|
-
TIER 14: Todo, Skip, Failing - 7 tests
|
|
1281
|
-
TIER 15: Stress Testing - 5 tests
|
|
1282
|
-
TIER 16: Edge Cases - 8 tests
|
|
1283
|
-
|
|
1284
|
-
BUN TEST API COVERAGE - NO SHORTCUTS:
|
|
1285
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1286
|
-
✓ test() / describe()
|
|
1287
|
-
✓ test.each() / describe.each()
|
|
1288
|
-
✓ test.concurrent()
|
|
1289
|
-
✓ test.todo() / test.skip()
|
|
1290
|
-
✓ test.if() / test.skipIf()
|
|
1291
|
-
✓ test.failing()
|
|
1292
|
-
✓ beforeAll() / afterAll()
|
|
1293
|
-
✓ beforeEach() / afterEach()
|
|
1294
|
-
✓ mock() / spyOn()
|
|
1295
|
-
✓ mockImplementation() / mockReturnValue() / mockClear()
|
|
1296
|
-
✓ setSystemTime()
|
|
1297
|
-
✓ expect.assertions() / expect.hasAssertions()
|
|
1298
|
-
✓ expect.extend() - Custom matchers
|
|
1299
|
-
✓ toMatchSnapshot()
|
|
1300
|
-
✓ All 40+ matchers
|
|
1301
|
-
✓ .resolves / .rejects
|
|
1302
|
-
✓ .not modifier
|
|
1303
|
-
|
|
1304
|
-
CUSTOM MATCHERS:
|
|
1305
|
-
━━━━━━━━━━━━━━━━━
|
|
1306
|
-
✓ toBeValidScore()
|
|
1307
|
-
✓ toBeValidTier()
|
|
1308
|
-
✓ toHaveSlotCount()
|
|
1309
|
-
|
|
1310
|
-
TOTAL: 164 tests (4 todo, 1 skip, 2 failing)
|
|
1311
|
-
|
|
1312
|
-
Wolfejam slot-based scoring.
|
|
1313
|
-
Fastest bun under the sum.
|
|
1314
|
-
Zero dependencies. Pure Bun.
|
|
1315
|
-
FULL BUN + WJTTC = BEST IN AI ERA.
|
|
1316
|
-
NO COMPROMISE.
|
|
1317
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1318
|
-
`);
|
|
1319
|
-
expect(true).toBe(true);
|
|
1320
|
-
});
|
|
1321
|
-
});
|