@scenetest/scenes 0.1.0

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.
Files changed (90) hide show
  1. package/LICENSE +21 -0
  2. package/dist/__tests__/devices.test.d.ts +2 -0
  3. package/dist/__tests__/devices.test.d.ts.map +1 -0
  4. package/dist/__tests__/devices.test.js +117 -0
  5. package/dist/__tests__/devices.test.js.map +1 -0
  6. package/dist/__tests__/dsl.test.d.ts +2 -0
  7. package/dist/__tests__/dsl.test.d.ts.map +1 -0
  8. package/dist/__tests__/dsl.test.js +385 -0
  9. package/dist/__tests__/dsl.test.js.map +1 -0
  10. package/dist/__tests__/markdown-scene.test.d.ts +2 -0
  11. package/dist/__tests__/markdown-scene.test.d.ts.map +1 -0
  12. package/dist/__tests__/markdown-scene.test.js +508 -0
  13. package/dist/__tests__/markdown-scene.test.js.map +1 -0
  14. package/dist/__tests__/reactive.test.d.ts +2 -0
  15. package/dist/__tests__/reactive.test.d.ts.map +1 -0
  16. package/dist/__tests__/reactive.test.js +383 -0
  17. package/dist/__tests__/reactive.test.js.map +1 -0
  18. package/dist/__tests__/swarm.test.d.ts +2 -0
  19. package/dist/__tests__/swarm.test.d.ts.map +1 -0
  20. package/dist/__tests__/swarm.test.js +214 -0
  21. package/dist/__tests__/swarm.test.js.map +1 -0
  22. package/dist/actor.d.ts +104 -0
  23. package/dist/actor.d.ts.map +1 -0
  24. package/dist/actor.js +527 -0
  25. package/dist/actor.js.map +1 -0
  26. package/dist/cli.d.ts +3 -0
  27. package/dist/cli.d.ts.map +1 -0
  28. package/dist/cli.js +273 -0
  29. package/dist/cli.js.map +1 -0
  30. package/dist/config.d.ts +21 -0
  31. package/dist/config.d.ts.map +1 -0
  32. package/dist/config.js +120 -0
  33. package/dist/config.js.map +1 -0
  34. package/dist/devices.d.ts +55 -0
  35. package/dist/devices.d.ts.map +1 -0
  36. package/dist/devices.js +167 -0
  37. package/dist/devices.js.map +1 -0
  38. package/dist/dsl.d.ts +99 -0
  39. package/dist/dsl.d.ts.map +1 -0
  40. package/dist/dsl.js +247 -0
  41. package/dist/dsl.js.map +1 -0
  42. package/dist/index.d.ts +13 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +16 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/init.d.ts +9 -0
  47. package/dist/init.d.ts.map +1 -0
  48. package/dist/init.js +27 -0
  49. package/dist/init.js.map +1 -0
  50. package/dist/loader.d.ts +2 -0
  51. package/dist/loader.d.ts.map +1 -0
  52. package/dist/loader.js +10 -0
  53. package/dist/loader.js.map +1 -0
  54. package/dist/markdown-scene.d.ts +120 -0
  55. package/dist/markdown-scene.d.ts.map +1 -0
  56. package/dist/markdown-scene.js +452 -0
  57. package/dist/markdown-scene.js.map +1 -0
  58. package/dist/message-bus.d.ts +31 -0
  59. package/dist/message-bus.d.ts.map +1 -0
  60. package/dist/message-bus.js +74 -0
  61. package/dist/message-bus.js.map +1 -0
  62. package/dist/reactive.d.ts +267 -0
  63. package/dist/reactive.d.ts.map +1 -0
  64. package/dist/reactive.js +779 -0
  65. package/dist/reactive.js.map +1 -0
  66. package/dist/runner.d.ts +51 -0
  67. package/dist/runner.d.ts.map +1 -0
  68. package/dist/runner.js +306 -0
  69. package/dist/runner.js.map +1 -0
  70. package/dist/scene.d.ts +40 -0
  71. package/dist/scene.d.ts.map +1 -0
  72. package/dist/scene.js +110 -0
  73. package/dist/scene.js.map +1 -0
  74. package/dist/selectors.d.ts +57 -0
  75. package/dist/selectors.d.ts.map +1 -0
  76. package/dist/selectors.js +193 -0
  77. package/dist/selectors.js.map +1 -0
  78. package/dist/swarm.d.ts +64 -0
  79. package/dist/swarm.d.ts.map +1 -0
  80. package/dist/swarm.js +306 -0
  81. package/dist/swarm.js.map +1 -0
  82. package/dist/team-manager.d.ts +120 -0
  83. package/dist/team-manager.d.ts.map +1 -0
  84. package/dist/team-manager.js +267 -0
  85. package/dist/team-manager.js.map +1 -0
  86. package/dist/types.d.ts +653 -0
  87. package/dist/types.d.ts.map +1 -0
  88. package/dist/types.js +2 -0
  89. package/dist/types.js.map +1 -0
  90. package/package.json +61 -0
@@ -0,0 +1,383 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { ConcurrentActorHandleImpl, drainAll } from '../reactive.js';
3
+ import { MessageBus } from '../message-bus.js';
4
+ // ---------------------------------------------------------------------------
5
+ // Helpers — minimal Playwright mocks
6
+ // ---------------------------------------------------------------------------
7
+ function mockLocator(visible = true) {
8
+ return {
9
+ waitFor: vi.fn().mockResolvedValue(undefined),
10
+ isVisible: vi.fn().mockResolvedValue(visible),
11
+ click: vi.fn().mockResolvedValue(undefined),
12
+ fill: vi.fn().mockResolvedValue(undefined),
13
+ check: vi.fn().mockResolvedValue(undefined),
14
+ selectOption: vi.fn().mockResolvedValue(undefined),
15
+ evaluate: vi.fn().mockResolvedValue(undefined),
16
+ };
17
+ }
18
+ /** Create a mock Page that stubs the methods ConcurrentActorHandleImpl uses */
19
+ function mockPage() {
20
+ const locator = mockLocator();
21
+ return {
22
+ goto: vi.fn().mockResolvedValue(undefined),
23
+ getByText: vi.fn().mockReturnValue({ first: () => locator }),
24
+ locator: vi.fn().mockReturnValue(locator),
25
+ evaluate: vi.fn().mockResolvedValue(undefined),
26
+ // Used by resolveSelector — it calls page.locator(css)
27
+ // We need to handle the selector resolution chain
28
+ _locator: locator,
29
+ };
30
+ }
31
+ /**
32
+ * Build a ConcurrentActorHandleImpl with mocked dependencies.
33
+ * Returns the actor plus shared timeline/warnings arrays for inspection.
34
+ */
35
+ function createTestActor(role = 'user', overrides) {
36
+ const bus = overrides?.bus ?? new MessageBus();
37
+ const timeline = [];
38
+ const warnings = [];
39
+ const page = overrides?.page ?? mockPage();
40
+ const actor = new ConcurrentActorHandleImpl(role, { id: `${role}-1`, username: role, email: `${role}@test.com`, password: 'pass' }, page, bus, timeline, warnings,
41
+ /* actionTimeout */ 5000,
42
+ /* warnAfter */ 60000 // high so warnings don't fire during tests
43
+ );
44
+ return { actor, bus, timeline, warnings, page };
45
+ }
46
+ /**
47
+ * Create a ConcurrentActorHandleImpl with deferred page (null).
48
+ * Simulates how flow() creates actors before browser init.
49
+ */
50
+ function createDeferredActor(role = 'user') {
51
+ const bus = new MessageBus();
52
+ const timeline = [];
53
+ const warnings = [];
54
+ const page = mockPage();
55
+ const actor = new ConcurrentActorHandleImpl(role, { id: `${role}-1`, username: role, email: `${role}@test.com`, password: 'pass' }, null, // deferred — page set later via _setPage
56
+ bus, timeline, warnings, 5000, 60000);
57
+ return { actor, bus, timeline, warnings, page };
58
+ }
59
+ // ---------------------------------------------------------------------------
60
+ // Tests
61
+ // ---------------------------------------------------------------------------
62
+ describe('ConcurrentActorHandleImpl', () => {
63
+ describe('queueing (declaration phase)', () => {
64
+ it('queues actions without executing', () => {
65
+ const { actor, page } = createTestActor();
66
+ actor.openTo('/login');
67
+ actor.see('form').typeInto('email', 'a@b.com').click('submit');
68
+ expect(actor.pending).toBe(4);
69
+ // Nothing should have been called on the page yet
70
+ expect(page.goto).not.toHaveBeenCalled();
71
+ });
72
+ it('chains fluently — every method returns the same actor', () => {
73
+ const { actor } = createTestActor();
74
+ const returned = actor
75
+ .openTo('/')
76
+ .see('nav')
77
+ .click('login')
78
+ .typeInto('email', 'x')
79
+ .check('remember')
80
+ .select('role', 'admin')
81
+ .wait(100)
82
+ .emit('done')
83
+ .waitFor('other')
84
+ .notSee('spinner')
85
+ .seeText('Welcome')
86
+ .seeToast('saved')
87
+ .scrollToBottom()
88
+ .up('header')
89
+ .prev()
90
+ .do(async () => { });
91
+ expect(returned).toBe(actor);
92
+ expect(actor.pending).toBe(16);
93
+ });
94
+ it('starts with zero pending actions', () => {
95
+ const { actor } = createTestActor();
96
+ expect(actor.pending).toBe(0);
97
+ });
98
+ it('forwards config properties', () => {
99
+ const { actor } = createTestActor('alice');
100
+ expect(actor.role).toBe('alice');
101
+ expect(actor.id).toBe('alice-1');
102
+ expect(actor.username).toBe('alice');
103
+ expect(actor.email).toBe('alice@test.com');
104
+ });
105
+ });
106
+ describe('drain (execution phase)', () => {
107
+ it('executes queued actions in order', async () => {
108
+ const order = [];
109
+ const { actor } = createTestActor();
110
+ actor.do(async () => { order.push('first'); });
111
+ actor.do(async () => { order.push('second'); });
112
+ actor.do(async () => { order.push('third'); });
113
+ await actor.drain();
114
+ expect(order).toEqual(['first', 'second', 'third']);
115
+ });
116
+ it('clears the queue after draining', async () => {
117
+ const { actor } = createTestActor();
118
+ actor.do(async () => { });
119
+ actor.do(async () => { });
120
+ expect(actor.pending).toBe(2);
121
+ await actor.drain();
122
+ expect(actor.pending).toBe(0);
123
+ });
124
+ it('records timeline entries', async () => {
125
+ const { actor, timeline } = createTestActor();
126
+ actor.do(async () => { });
127
+ actor.do(async () => { });
128
+ await actor.drain();
129
+ expect(timeline).toHaveLength(2);
130
+ expect(timeline[0].action).toBe('do');
131
+ expect(timeline[0].actor).toBe('user');
132
+ expect(timeline[0].duration).toBeDefined();
133
+ });
134
+ it('records errors in timeline entries', async () => {
135
+ const { actor, timeline } = createTestActor();
136
+ actor.do(async () => {
137
+ throw new Error('boom');
138
+ });
139
+ await expect(actor.drain()).rejects.toThrow('boom');
140
+ expect(timeline).toHaveLength(1);
141
+ expect(timeline[0].error).toBe('boom');
142
+ });
143
+ it('throws if drain called while already draining', async () => {
144
+ const { actor } = createTestActor();
145
+ // Queue a slow action
146
+ actor.do(async () => {
147
+ await new Promise((r) => setTimeout(r, 50));
148
+ });
149
+ const p1 = actor.drain();
150
+ await expect(actor.drain()).rejects.toThrow('already draining');
151
+ await p1;
152
+ });
153
+ it('stops execution when aborted', async () => {
154
+ const order = [];
155
+ const { actor } = createTestActor();
156
+ actor.do(async () => {
157
+ order.push('first');
158
+ // Abort mid-drain
159
+ actor.abort('peer failed');
160
+ });
161
+ actor.do(async () => {
162
+ order.push('second'); // should NOT execute
163
+ });
164
+ await expect(actor.drain()).rejects.toThrow('aborted');
165
+ expect(order).toEqual(['first']);
166
+ });
167
+ });
168
+ describe('coordination', () => {
169
+ it('emit() pushes message to bus during drain', async () => {
170
+ const bus = new MessageBus();
171
+ const { actor } = createTestActor('alice', { bus });
172
+ actor.emit('hello');
173
+ expect(bus.hasEmitted('hello')).toBe(false);
174
+ await actor.drain();
175
+ expect(bus.hasEmitted('hello')).toBe(true);
176
+ });
177
+ it('waitFor() blocks until message arrives', async () => {
178
+ const bus = new MessageBus();
179
+ const { actor } = createTestActor('bob', { bus });
180
+ const order = [];
181
+ actor.do(async () => { order.push('before-wait'); });
182
+ actor.waitFor('ready');
183
+ actor.do(async () => { order.push('after-wait'); });
184
+ // Start draining — will block at waitFor
185
+ const drainPromise = actor.drain();
186
+ // Give drain a tick to reach the waitFor
187
+ await new Promise((r) => setTimeout(r, 10));
188
+ expect(order).toEqual(['before-wait']);
189
+ // Emit the message — unblocks waitFor
190
+ bus.emit('ready');
191
+ await drainPromise;
192
+ expect(order).toEqual(['before-wait', 'after-wait']);
193
+ });
194
+ it('waitFor() resolves immediately if message already emitted (sticky)', async () => {
195
+ const bus = new MessageBus();
196
+ bus.emit('already-sent');
197
+ const { actor } = createTestActor('bob', { bus });
198
+ const order = [];
199
+ actor.waitFor('already-sent');
200
+ actor.do(async () => { order.push('after'); });
201
+ await actor.drain();
202
+ expect(order).toEqual(['after']);
203
+ });
204
+ });
205
+ describe('if() — conditional monitors', () => {
206
+ it('captures sub-actions during declaration without affecting main queue', () => {
207
+ const { actor } = createTestActor();
208
+ actor.do(async () => { });
209
+ actor.if('modal', a => {
210
+ a.do(async () => { });
211
+ a.do(async () => { });
212
+ });
213
+ actor.do(async () => { });
214
+ // Main queue should have 2 actions (the two do() calls), not 4
215
+ expect(actor.pending).toBe(2);
216
+ });
217
+ it('fires sub-actions inline when selector is visible during an action', async () => {
218
+ const { actor } = createTestActor();
219
+ const order = [];
220
+ // Register a conditional monitor
221
+ actor.if('modal', a => {
222
+ a.do(async () => { order.push('dismiss-modal'); });
223
+ });
224
+ // Queue a slow action during which the monitor should fire
225
+ actor.do(async () => {
226
+ order.push('action-start');
227
+ // Simulate a slow action
228
+ await new Promise((r) => setTimeout(r, 100));
229
+ order.push('action-end');
230
+ });
231
+ actor.do(async () => { order.push('after'); });
232
+ // We need the monitor to actually detect "modal" as visible.
233
+ // Since we're using mocks, the resolveSelector won't find anything,
234
+ // so the monitor won't fire. This test verifies the flow completes
235
+ // without the monitor firing (no visible selector).
236
+ await actor.drain();
237
+ expect(order).toEqual(['action-start', 'action-end', 'after']);
238
+ });
239
+ it('does not affect drain when monitor never triggers', async () => {
240
+ const { actor } = createTestActor();
241
+ const order = [];
242
+ actor.if('nonexistent', a => {
243
+ a.do(async () => { order.push('should-not-run'); });
244
+ });
245
+ actor.do(async () => { order.push('normal'); });
246
+ await actor.drain();
247
+ // Sub-actions should NOT have run
248
+ expect(order).toEqual(['normal']);
249
+ });
250
+ it('queue-swap restores main queue even if callback throws', () => {
251
+ const { actor } = createTestActor();
252
+ actor.do(async () => { });
253
+ expect(() => {
254
+ actor.if('modal', () => {
255
+ throw new Error('callback error');
256
+ });
257
+ }).toThrow('callback error');
258
+ // Main queue should still be intact
259
+ expect(actor.pending).toBe(1);
260
+ });
261
+ it('supports chained sub-actions inside if()', () => {
262
+ const { actor } = createTestActor();
263
+ actor.if('modal', a => {
264
+ a.click('dismiss').wait(100).click('confirm');
265
+ });
266
+ // Main queue unaffected
267
+ expect(actor.pending).toBe(0);
268
+ });
269
+ });
270
+ });
271
+ describe('deferred page initialization', () => {
272
+ it('allows queueing actions before page is set', () => {
273
+ const { actor } = createDeferredActor();
274
+ actor.openTo('/login');
275
+ actor.see('form').typeInto('email', 'a@b.com').click('submit');
276
+ expect(actor.pending).toBe(4);
277
+ });
278
+ it('exposes config properties before page is set', () => {
279
+ const { actor } = createDeferredActor('alice');
280
+ expect(actor.role).toBe('alice');
281
+ expect(actor.id).toBe('alice-1');
282
+ expect(actor.email).toBe('alice@test.com');
283
+ });
284
+ it('throws when accessing page before initialization', () => {
285
+ const { actor } = createDeferredActor();
286
+ expect(() => actor.page).toThrow('page not initialized');
287
+ });
288
+ it('throws when draining without page', async () => {
289
+ const { actor } = createDeferredActor();
290
+ actor.do(async () => { });
291
+ await expect(actor.drain()).rejects.toThrow('page not initialized');
292
+ });
293
+ it('drains successfully after _setPage', async () => {
294
+ const { actor, page } = createDeferredActor();
295
+ const order = [];
296
+ actor.do(async () => { order.push('first'); });
297
+ actor.do(async () => { order.push('second'); });
298
+ // Set page — simulates flow runner phase 2
299
+ actor._setPage(page);
300
+ await actor.drain();
301
+ expect(order).toEqual(['first', 'second']);
302
+ });
303
+ it('page getter works after _setPage', () => {
304
+ const { actor, page } = createDeferredActor();
305
+ actor._setPage(page);
306
+ expect(() => actor.page).not.toThrow();
307
+ });
308
+ });
309
+ describe('drainAll', () => {
310
+ it('drains multiple actors concurrently', async () => {
311
+ const events = [];
312
+ const { actor: alice } = createTestActor('alice');
313
+ const { actor: bob } = createTestActor('bob');
314
+ alice.do(async () => {
315
+ events.push('alice-start');
316
+ await new Promise((r) => setTimeout(r, 30));
317
+ events.push('alice-end');
318
+ });
319
+ bob.do(async () => {
320
+ events.push('bob-start');
321
+ await new Promise((r) => setTimeout(r, 10));
322
+ events.push('bob-end');
323
+ });
324
+ await drainAll([alice, bob]);
325
+ // Both should have started before either finished
326
+ // (bob finishes first because it's shorter)
327
+ expect(events.indexOf('alice-start')).toBeLessThan(events.indexOf('alice-end'));
328
+ expect(events.indexOf('bob-start')).toBeLessThan(events.indexOf('bob-end'));
329
+ // Both started (we don't assert start ordering because it's nondeterministic,
330
+ // but both must have completed)
331
+ expect(events).toContain('alice-end');
332
+ expect(events).toContain('bob-end');
333
+ });
334
+ it('aborts other actors when one fails', async () => {
335
+ const { actor: alice } = createTestActor('alice');
336
+ const { actor: bob } = createTestActor('bob');
337
+ alice.do(async () => {
338
+ throw new Error('alice broke');
339
+ });
340
+ bob.do(async () => {
341
+ // Slow action — should get aborted
342
+ await new Promise((r) => setTimeout(r, 200));
343
+ });
344
+ bob.do(async () => {
345
+ // Should never execute
346
+ });
347
+ await expect(drainAll([alice, bob])).rejects.toThrow('alice broke');
348
+ // Bob should have been aborted
349
+ expect(bob.aborted).toBe(true);
350
+ });
351
+ it('handles empty actor list', async () => {
352
+ await drainAll([]);
353
+ // Should not throw
354
+ });
355
+ it('handles single actor', async () => {
356
+ const { actor } = createTestActor();
357
+ const order = [];
358
+ actor.do(async () => { order.push('only'); });
359
+ await drainAll([actor]);
360
+ expect(order).toEqual(['only']);
361
+ });
362
+ it('cross-actor coordination via message bus', async () => {
363
+ const bus = new MessageBus();
364
+ const { actor: alice } = createTestActor('alice', { bus });
365
+ const { actor: bob } = createTestActor('bob', { bus });
366
+ const events = [];
367
+ // Alice does work then signals
368
+ alice.do(async () => {
369
+ events.push('alice-work');
370
+ await new Promise((r) => setTimeout(r, 20));
371
+ });
372
+ alice.emit('alice-done');
373
+ // Bob waits for alice then proceeds
374
+ bob.waitFor('alice-done');
375
+ bob.do(async () => {
376
+ events.push('bob-after-alice');
377
+ });
378
+ await drainAll([alice, bob]);
379
+ // Bob must have waited for alice
380
+ expect(events.indexOf('alice-work')).toBeLessThan(events.indexOf('bob-after-alice'));
381
+ });
382
+ });
383
+ //# sourceMappingURL=reactive.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reactive.test.js","sourceRoot":"","sources":["../../src/__tests__/reactive.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=swarm.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swarm.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/swarm.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,214 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { SwarmTrigger, resolveSwarmConfig } from '../swarm.js';
3
+ // ── Helpers ──────────────────────────────────────────────────────────
4
+ function makeSceneReport(name, status = 'completed', assertions = [{ result: true }]) {
5
+ return {
6
+ name,
7
+ file: `scenes/${name}.spec.ts`,
8
+ status,
9
+ teamIndex: 0,
10
+ actors: {},
11
+ assertions: assertions.map((a) => ({
12
+ type: a.result ? 'pass' : 'fail',
13
+ description: 'test',
14
+ result: a.result,
15
+ timestamp: Date.now(),
16
+ })),
17
+ warnings: [],
18
+ timeline: [],
19
+ duration: 100,
20
+ };
21
+ }
22
+ function makeRunReport(scenes) {
23
+ return {
24
+ timestamp: new Date().toISOString(),
25
+ duration: 1000,
26
+ scenes,
27
+ summary: {
28
+ scenes: scenes.length,
29
+ completed: scenes.filter((s) => s.status === 'completed').length,
30
+ failed: scenes.filter((s) => s.status !== 'completed').length,
31
+ assertions: {
32
+ total: scenes.reduce((sum, s) => sum + s.assertions.length, 0),
33
+ passed: scenes.reduce((sum, s) => sum + s.assertions.filter((a) => a.result).length, 0),
34
+ failed: scenes.reduce((sum, s) => sum + s.assertions.filter((a) => !a.result).length, 0),
35
+ },
36
+ warnings: 0,
37
+ },
38
+ };
39
+ }
40
+ // ── Tests ────────────────────────────────────────────────────────────
41
+ describe('resolveSwarmConfig', () => {
42
+ it('provides defaults when no config given', () => {
43
+ const resolved = resolveSwarmConfig();
44
+ expect(resolved.failureThreshold).toBe(5);
45
+ expect(resolved.windowSize).toBe(3);
46
+ expect(resolved.concurrency).toBe(Infinity);
47
+ expect(resolved.repeats).toBe(3);
48
+ expect(resolved.auto).toBe(true);
49
+ });
50
+ it('merges partial config with defaults', () => {
51
+ const resolved = resolveSwarmConfig({ failureThreshold: 10, concurrency: 2 });
52
+ expect(resolved.failureThreshold).toBe(10);
53
+ expect(resolved.concurrency).toBe(2);
54
+ expect(resolved.windowSize).toBe(3); // default
55
+ expect(resolved.repeats).toBe(3); // default
56
+ expect(resolved.auto).toBe(true); // default
57
+ });
58
+ it('overrides all defaults when full config given', () => {
59
+ const config = {
60
+ failureThreshold: 2,
61
+ windowSize: 5,
62
+ concurrency: 4,
63
+ repeats: 10,
64
+ auto: false,
65
+ };
66
+ const resolved = resolveSwarmConfig(config);
67
+ expect(resolved).toEqual(config);
68
+ });
69
+ });
70
+ describe('SwarmTrigger', () => {
71
+ describe('recordRun', () => {
72
+ it('tracks scene outcomes across runs', () => {
73
+ const trigger = new SwarmTrigger({ failureThreshold: 3, windowSize: 5 });
74
+ // Run 1: scene passes
75
+ trigger.recordRun(makeRunReport([makeSceneReport('login')]));
76
+ const record = trigger.getRecord('login');
77
+ expect(record).toBeDefined();
78
+ expect(record.history).toEqual([true]);
79
+ expect(record.consecutiveFailures).toBe(0);
80
+ });
81
+ it('counts consecutive failures', () => {
82
+ const trigger = new SwarmTrigger({ failureThreshold: 3, windowSize: 5 });
83
+ // Passes
84
+ trigger.recordRun(makeRunReport([makeSceneReport('login')]));
85
+ expect(trigger.getRecord('login').consecutiveFailures).toBe(0);
86
+ // Fails
87
+ trigger.recordRun(makeRunReport([makeSceneReport('login', 'failed')]));
88
+ expect(trigger.getRecord('login').consecutiveFailures).toBe(1);
89
+ // Fails again
90
+ trigger.recordRun(makeRunReport([makeSceneReport('login', 'failed')]));
91
+ expect(trigger.getRecord('login').consecutiveFailures).toBe(2);
92
+ });
93
+ it('resets consecutive count on pass', () => {
94
+ const trigger = new SwarmTrigger({ failureThreshold: 5, windowSize: 5 });
95
+ // Two failures
96
+ trigger.recordRun(makeRunReport([makeSceneReport('login', 'failed')]));
97
+ trigger.recordRun(makeRunReport([makeSceneReport('login', 'failed')]));
98
+ expect(trigger.getRecord('login').consecutiveFailures).toBe(2);
99
+ // Pass breaks the streak
100
+ trigger.recordRun(makeRunReport([makeSceneReport('login')]));
101
+ expect(trigger.getRecord('login').consecutiveFailures).toBe(0);
102
+ });
103
+ it('treats completed scenes with failed assertions as failures', () => {
104
+ const trigger = new SwarmTrigger({ failureThreshold: 3, windowSize: 5 });
105
+ // Scene completes but has a failed assertion
106
+ const scene = makeSceneReport('login', 'completed', [{ result: false }]);
107
+ trigger.recordRun(makeRunReport([scene]));
108
+ expect(trigger.getRecord('login').consecutiveFailures).toBe(1);
109
+ });
110
+ it('trims history to window size', () => {
111
+ const trigger = new SwarmTrigger({ failureThreshold: 5, windowSize: 3 });
112
+ // Record 5 runs
113
+ for (let i = 0; i < 5; i++) {
114
+ trigger.recordRun(makeRunReport([makeSceneReport('login')]));
115
+ }
116
+ // History should be trimmed to 3
117
+ expect(trigger.getRecord('login').history).toHaveLength(3);
118
+ });
119
+ it('tracks multiple scenes independently', () => {
120
+ const trigger = new SwarmTrigger({ failureThreshold: 3, windowSize: 5 });
121
+ trigger.recordRun(makeRunReport([
122
+ makeSceneReport('login'),
123
+ makeSceneReport('profile', 'failed'),
124
+ ]));
125
+ expect(trigger.getRecord('login').consecutiveFailures).toBe(0);
126
+ expect(trigger.getRecord('profile').consecutiveFailures).toBe(1);
127
+ });
128
+ });
129
+ describe('shouldTrigger', () => {
130
+ it('does not trigger when failures are below threshold', () => {
131
+ const trigger = new SwarmTrigger({ failureThreshold: 3, windowSize: 5 });
132
+ trigger.recordRun(makeRunReport([makeSceneReport('login', 'failed')]));
133
+ trigger.recordRun(makeRunReport([makeSceneReport('login', 'failed')]));
134
+ expect(trigger.shouldTrigger()).toEqual([]);
135
+ });
136
+ it('triggers when consecutive failures reach threshold', () => {
137
+ const trigger = new SwarmTrigger({ failureThreshold: 3, windowSize: 5 });
138
+ trigger.recordRun(makeRunReport([makeSceneReport('login', 'failed')]));
139
+ trigger.recordRun(makeRunReport([makeSceneReport('login', 'failed')]));
140
+ trigger.recordRun(makeRunReport([makeSceneReport('login', 'failed')]));
141
+ expect(trigger.shouldTrigger()).toEqual(['login']);
142
+ });
143
+ it('returns multiple triggered scenes', () => {
144
+ const trigger = new SwarmTrigger({ failureThreshold: 2, windowSize: 5 });
145
+ trigger.recordRun(makeRunReport([
146
+ makeSceneReport('login', 'failed'),
147
+ makeSceneReport('profile', 'failed'),
148
+ ]));
149
+ trigger.recordRun(makeRunReport([
150
+ makeSceneReport('login', 'failed'),
151
+ makeSceneReport('profile', 'failed'),
152
+ ]));
153
+ const triggered = trigger.shouldTrigger();
154
+ expect(triggered).toContain('login');
155
+ expect(triggered).toContain('profile');
156
+ expect(triggered).toHaveLength(2);
157
+ });
158
+ it('does not trigger when auto is disabled', () => {
159
+ const trigger = new SwarmTrigger({ failureThreshold: 1, auto: false });
160
+ trigger.recordRun(makeRunReport([makeSceneReport('login', 'failed')]));
161
+ expect(trigger.shouldTrigger()).toEqual([]);
162
+ });
163
+ it('only triggers for scenes that exceed threshold, not all', () => {
164
+ const trigger = new SwarmTrigger({ failureThreshold: 2, windowSize: 5 });
165
+ // login fails twice, profile fails once
166
+ trigger.recordRun(makeRunReport([
167
+ makeSceneReport('login', 'failed'),
168
+ makeSceneReport('profile', 'failed'),
169
+ ]));
170
+ trigger.recordRun(makeRunReport([
171
+ makeSceneReport('login', 'failed'),
172
+ makeSceneReport('profile'), // passes this time
173
+ ]));
174
+ expect(trigger.shouldTrigger()).toEqual(['login']);
175
+ });
176
+ });
177
+ describe('clear', () => {
178
+ it('resets all tracking data', () => {
179
+ const trigger = new SwarmTrigger({ failureThreshold: 1 });
180
+ trigger.recordRun(makeRunReport([makeSceneReport('login', 'failed')]));
181
+ expect(trigger.shouldTrigger()).toEqual(['login']);
182
+ trigger.clear();
183
+ expect(trigger.shouldTrigger()).toEqual([]);
184
+ expect(trigger.getRecord('login')).toBeUndefined();
185
+ });
186
+ });
187
+ describe('threshold edge cases', () => {
188
+ it('threshold of 1 triggers on first failure', () => {
189
+ const trigger = new SwarmTrigger({ failureThreshold: 1, windowSize: 3 });
190
+ trigger.recordRun(makeRunReport([makeSceneReport('login', 'failed')]));
191
+ expect(trigger.shouldTrigger()).toEqual(['login']);
192
+ });
193
+ it('a pass after threshold no longer triggers', () => {
194
+ const trigger = new SwarmTrigger({ failureThreshold: 2, windowSize: 5 });
195
+ trigger.recordRun(makeRunReport([makeSceneReport('login', 'failed')]));
196
+ trigger.recordRun(makeRunReport([makeSceneReport('login', 'failed')]));
197
+ expect(trigger.shouldTrigger()).toEqual(['login']);
198
+ // Now it passes
199
+ trigger.recordRun(makeRunReport([makeSceneReport('login')]));
200
+ expect(trigger.shouldTrigger()).toEqual([]);
201
+ });
202
+ it('interleaved pass/fail does not trigger', () => {
203
+ const trigger = new SwarmTrigger({ failureThreshold: 3, windowSize: 10 });
204
+ // fail, pass, fail, pass, fail — never 3 consecutive
205
+ trigger.recordRun(makeRunReport([makeSceneReport('login', 'failed')]));
206
+ trigger.recordRun(makeRunReport([makeSceneReport('login')]));
207
+ trigger.recordRun(makeRunReport([makeSceneReport('login', 'failed')]));
208
+ trigger.recordRun(makeRunReport([makeSceneReport('login')]));
209
+ trigger.recordRun(makeRunReport([makeSceneReport('login', 'failed')]));
210
+ expect(trigger.shouldTrigger()).toEqual([]);
211
+ });
212
+ });
213
+ });
214
+ //# sourceMappingURL=swarm.test.js.map