@ricsam/isolate-test-environment 0.1.3 → 0.1.6

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.
@@ -1,8 +1,21 @@
1
1
  // @bun @bun-cjs
2
- (function(exports, require, module, __filename, __dirname) {var __defProp = Object.defineProperty;
2
+ (function(exports, require, module, __filename, __dirname) {var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
3
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
4
6
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __toESM = (mod, isNodeMode, target) => {
9
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
10
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
11
+ for (let key of __getOwnPropNames(mod))
12
+ if (!__hasOwnProp.call(to, key))
13
+ __defProp(to, key, {
14
+ get: () => mod[key],
15
+ enumerable: true
16
+ });
17
+ return to;
18
+ };
6
19
  var __moduleCache = /* @__PURE__ */ new WeakMap;
7
20
  var __toCommonJS = (from) => {
8
21
  var entry = __moduleCache.get(from), desc;
@@ -31,9 +44,12 @@ var __export = (target, all) => {
31
44
  var exports_src = {};
32
45
  __export(exports_src, {
33
46
  setupTestEnvironment: () => setupTestEnvironment,
34
- runTests: () => runTests
47
+ runTests: () => runTests,
48
+ hasTests: () => hasTests,
49
+ getTestCount: () => getTestCount
35
50
  });
36
51
  module.exports = __toCommonJS(exports_src);
52
+ var import_isolated_vm = __toESM(require("isolated-vm"));
37
53
  var testEnvironmentCode = `
38
54
  (function() {
39
55
  // ============================================================
@@ -58,6 +74,33 @@ var testEnvironmentCode = `
58
74
  let currentSuite = rootSuite;
59
75
  const suiteStack = [rootSuite];
60
76
 
77
+ // Event callback (set from host)
78
+ let eventCallback = null;
79
+
80
+ function emitEvent(event) {
81
+ if (eventCallback) {
82
+ try {
83
+ eventCallback(JSON.stringify(event));
84
+ } catch (e) {
85
+ // Ignore callback errors
86
+ }
87
+ }
88
+ }
89
+
90
+ // ============================================================
91
+ // TestError class for rich error info
92
+ // ============================================================
93
+
94
+ class TestError extends Error {
95
+ constructor(message, matcherName, expected, actual) {
96
+ super(message);
97
+ this.name = 'TestError';
98
+ this.matcherName = matcherName;
99
+ this.expected = expected;
100
+ this.actual = actual;
101
+ }
102
+ }
103
+
61
104
  // ============================================================
62
105
  // Deep Equality Helper
63
106
  // ============================================================
@@ -157,10 +200,10 @@ var testEnvironmentCode = `
157
200
 
158
201
  function expect(actual) {
159
202
  function createMatchers(negated = false) {
160
- const assert = (condition, message) => {
203
+ const assert = (condition, message, matcherName, expected) => {
161
204
  const pass = negated ? !condition : condition;
162
205
  if (!pass) {
163
- throw new Error(message);
206
+ throw new TestError(message, matcherName, expected, actual);
164
207
  }
165
208
  };
166
209
 
@@ -170,7 +213,9 @@ var testEnvironmentCode = `
170
213
  actual === expected,
171
214
  negated
172
215
  ? \`Expected \${formatValue(actual)} not to be \${formatValue(expected)}\`
173
- : \`Expected \${formatValue(actual)} to be \${formatValue(expected)}\`
216
+ : \`Expected \${formatValue(actual)} to be \${formatValue(expected)}\`,
217
+ 'toBe',
218
+ expected
174
219
  );
175
220
  },
176
221
 
@@ -179,7 +224,9 @@ var testEnvironmentCode = `
179
224
  deepEqual(actual, expected),
180
225
  negated
181
226
  ? \`Expected \${formatValue(actual)} not to equal \${formatValue(expected)}\`
182
- : \`Expected \${formatValue(actual)} to equal \${formatValue(expected)}\`
227
+ : \`Expected \${formatValue(actual)} to equal \${formatValue(expected)}\`,
228
+ 'toEqual',
229
+ expected
183
230
  );
184
231
  },
185
232
 
@@ -188,7 +235,9 @@ var testEnvironmentCode = `
188
235
  strictDeepEqual(actual, expected),
189
236
  negated
190
237
  ? \`Expected \${formatValue(actual)} not to strictly equal \${formatValue(expected)}\`
191
- : \`Expected \${formatValue(actual)} to strictly equal \${formatValue(expected)}\`
238
+ : \`Expected \${formatValue(actual)} to strictly equal \${formatValue(expected)}\`,
239
+ 'toStrictEqual',
240
+ expected
192
241
  );
193
242
  },
194
243
 
@@ -197,7 +246,9 @@ var testEnvironmentCode = `
197
246
  !!actual,
198
247
  negated
199
248
  ? \`Expected \${formatValue(actual)} not to be truthy\`
200
- : \`Expected \${formatValue(actual)} to be truthy\`
249
+ : \`Expected \${formatValue(actual)} to be truthy\`,
250
+ 'toBeTruthy',
251
+ true
201
252
  );
202
253
  },
203
254
 
@@ -206,7 +257,9 @@ var testEnvironmentCode = `
206
257
  !actual,
207
258
  negated
208
259
  ? \`Expected \${formatValue(actual)} not to be falsy\`
209
- : \`Expected \${formatValue(actual)} to be falsy\`
260
+ : \`Expected \${formatValue(actual)} to be falsy\`,
261
+ 'toBeFalsy',
262
+ false
210
263
  );
211
264
  },
212
265
 
@@ -215,7 +268,9 @@ var testEnvironmentCode = `
215
268
  actual === null,
216
269
  negated
217
270
  ? \`Expected \${formatValue(actual)} not to be null\`
218
- : \`Expected \${formatValue(actual)} to be null\`
271
+ : \`Expected \${formatValue(actual)} to be null\`,
272
+ 'toBeNull',
273
+ null
219
274
  );
220
275
  },
221
276
 
@@ -224,7 +279,9 @@ var testEnvironmentCode = `
224
279
  actual === undefined,
225
280
  negated
226
281
  ? \`Expected \${formatValue(actual)} not to be undefined\`
227
- : \`Expected \${formatValue(actual)} to be undefined\`
282
+ : \`Expected \${formatValue(actual)} to be undefined\`,
283
+ 'toBeUndefined',
284
+ undefined
228
285
  );
229
286
  },
230
287
 
@@ -233,7 +290,9 @@ var testEnvironmentCode = `
233
290
  actual !== undefined,
234
291
  negated
235
292
  ? \`Expected \${formatValue(actual)} not to be defined\`
236
- : \`Expected \${formatValue(actual)} to be defined\`
293
+ : \`Expected \${formatValue(actual)} to be defined\`,
294
+ 'toBeDefined',
295
+ 'defined'
237
296
  );
238
297
  },
239
298
 
@@ -248,7 +307,9 @@ var testEnvironmentCode = `
248
307
  contains,
249
308
  negated
250
309
  ? \`Expected \${formatValue(actual)} not to contain \${formatValue(item)}\`
251
- : \`Expected \${formatValue(actual)} to contain \${formatValue(item)}\`
310
+ : \`Expected \${formatValue(actual)} to contain \${formatValue(item)}\`,
311
+ 'toContain',
312
+ item
252
313
  );
253
314
  },
254
315
 
@@ -276,14 +337,18 @@ var testEnvironmentCode = `
276
337
  matches,
277
338
  negated
278
339
  ? \`Expected function not to throw \${formatValue(expected)}\`
279
- : \`Expected function to throw \${formatValue(expected)}, but \${threw ? \`threw: \${error.message}\` : 'did not throw'}\`
340
+ : \`Expected function to throw \${formatValue(expected)}, but \${threw ? \`threw: \${error.message}\` : 'did not throw'}\`,
341
+ 'toThrow',
342
+ expected
280
343
  );
281
344
  } else {
282
345
  assert(
283
346
  threw,
284
347
  negated
285
348
  ? \`Expected function not to throw\`
286
- : \`Expected function to throw\`
349
+ : \`Expected function to throw\`,
350
+ 'toThrow',
351
+ 'any error'
287
352
  );
288
353
  }
289
354
  },
@@ -293,7 +358,9 @@ var testEnvironmentCode = `
293
358
  actual instanceof cls,
294
359
  negated
295
360
  ? \`Expected \${formatValue(actual)} not to be instance of \${cls.name || cls}\`
296
- : \`Expected \${formatValue(actual)} to be instance of \${cls.name || cls}\`
361
+ : \`Expected \${formatValue(actual)} to be instance of \${cls.name || cls}\`,
362
+ 'toBeInstanceOf',
363
+ cls.name || cls
297
364
  );
298
365
  },
299
366
 
@@ -303,7 +370,9 @@ var testEnvironmentCode = `
303
370
  actualLength === length,
304
371
  negated
305
372
  ? \`Expected length not to be \${length}, but got \${actualLength}\`
306
- : \`Expected length to be \${length}, but got \${actualLength}\`
373
+ : \`Expected length to be \${length}, but got \${actualLength}\`,
374
+ 'toHaveLength',
375
+ length
307
376
  );
308
377
  },
309
378
 
@@ -318,7 +387,9 @@ var testEnvironmentCode = `
318
387
  matches,
319
388
  negated
320
389
  ? \`Expected \${formatValue(actual)} not to match \${pattern}\`
321
- : \`Expected \${formatValue(actual)} to match \${pattern}\`
390
+ : \`Expected \${formatValue(actual)} to match \${pattern}\`,
391
+ 'toMatch',
392
+ pattern
322
393
  );
323
394
  },
324
395
 
@@ -331,7 +402,53 @@ var testEnvironmentCode = `
331
402
  hasProperty && valueMatches,
332
403
  negated
333
404
  ? \`Expected \${formatValue(actual)} not to have property \${path}\${arguments.length >= 2 ? \` with value \${formatValue(value)}\` : ''}\`
334
- : \`Expected \${formatValue(actual)} to have property \${path}\${arguments.length >= 2 ? \` with value \${formatValue(value)}\` : ''}\`
405
+ : \`Expected \${formatValue(actual)} to have property \${path}\${arguments.length >= 2 ? \` with value \${formatValue(value)}\` : ''}\`,
406
+ 'toHaveProperty',
407
+ arguments.length >= 2 ? { path, value } : { path }
408
+ );
409
+ },
410
+
411
+ toBeGreaterThan(expected) {
412
+ assert(
413
+ actual > expected,
414
+ negated
415
+ ? \`Expected \${formatValue(actual)} not to be greater than \${formatValue(expected)}\`
416
+ : \`Expected \${formatValue(actual)} to be greater than \${formatValue(expected)}\`,
417
+ 'toBeGreaterThan',
418
+ expected
419
+ );
420
+ },
421
+
422
+ toBeGreaterThanOrEqual(expected) {
423
+ assert(
424
+ actual >= expected,
425
+ negated
426
+ ? \`Expected \${formatValue(actual)} not to be greater than or equal to \${formatValue(expected)}\`
427
+ : \`Expected \${formatValue(actual)} to be greater than or equal to \${formatValue(expected)}\`,
428
+ 'toBeGreaterThanOrEqual',
429
+ expected
430
+ );
431
+ },
432
+
433
+ toBeLessThan(expected) {
434
+ assert(
435
+ actual < expected,
436
+ negated
437
+ ? \`Expected \${formatValue(actual)} not to be less than \${formatValue(expected)}\`
438
+ : \`Expected \${formatValue(actual)} to be less than \${formatValue(expected)}\`,
439
+ 'toBeLessThan',
440
+ expected
441
+ );
442
+ },
443
+
444
+ toBeLessThanOrEqual(expected) {
445
+ assert(
446
+ actual <= expected,
447
+ negated
448
+ ? \`Expected \${formatValue(actual)} not to be less than or equal to \${formatValue(expected)}\`
449
+ : \`Expected \${formatValue(actual)} to be less than or equal to \${formatValue(expected)}\`,
450
+ 'toBeLessThanOrEqual',
451
+ expected
335
452
  );
336
453
  },
337
454
  };
@@ -454,7 +571,7 @@ var testEnvironmentCode = `
454
571
  }
455
572
 
456
573
  // ============================================================
457
- // Test Runner
574
+ // Test Runner Helpers
458
575
  // ============================================================
459
576
 
460
577
  function checkForOnly(suite) {
@@ -479,120 +596,273 @@ var testEnvironmentCode = `
479
596
  return false;
480
597
  }
481
598
 
599
+ function countTests(suite, hasOnly) {
600
+ let count = 0;
601
+ if (hasOnly && !suiteHasOnly(suite)) return 0;
602
+ if (suite.skip) return suite.tests.length;
603
+
604
+ for (const t of suite.tests) {
605
+ if (hasOnly && !t.only && !suite.only) continue;
606
+ count++;
607
+ }
608
+ for (const child of suite.children) {
609
+ count += countTests(child, hasOnly);
610
+ }
611
+ return count;
612
+ }
613
+
614
+ function countSuites(suite, hasOnly) {
615
+ let count = 0;
616
+ if (hasOnly && !suiteHasOnly(suite)) return 0;
617
+
618
+ for (const child of suite.children) {
619
+ count++;
620
+ count += countSuites(child, hasOnly);
621
+ }
622
+ return count;
623
+ }
624
+
625
+ // ============================================================
626
+ // Test Runner
627
+ // ============================================================
628
+
482
629
  async function __runAllTests() {
483
- const results = [];
630
+ const testResults = [];
631
+ const suiteResults = [];
484
632
  const hasOnly = checkForOnly(rootSuite);
633
+ const runStart = Date.now();
634
+
635
+ // Emit runStart
636
+ const testCount = countTests(rootSuite, hasOnly);
637
+ const suiteCount = countSuites(rootSuite, hasOnly);
638
+ emitEvent({ type: 'runStart', testCount, suiteCount });
485
639
 
486
- async function runSuite(suite, parentHooks, namePath) {
640
+ async function runSuite(suite, parentHooks, pathArray, depth) {
487
641
  // Skip if this suite doesn't have any .only when .only exists elsewhere
488
642
  if (hasOnly && !suiteHasOnly(suite)) return;
489
643
 
644
+ const suitePath = [...pathArray];
645
+ const fullName = suitePath.join(' > ');
646
+ const suiteInfo = {
647
+ name: suite.name,
648
+ path: suitePath.slice(0, -1),
649
+ fullName,
650
+ depth,
651
+ };
652
+
653
+ // Emit suiteStart (only for non-root suites)
654
+ if (suite !== rootSuite) {
655
+ emitEvent({ type: 'suiteStart', suite: suiteInfo });
656
+ }
657
+
658
+ const suiteStart = Date.now();
659
+ let suitePassed = 0;
660
+ let suiteFailed = 0;
661
+ let suiteSkipped = 0;
662
+ let suiteTodo = 0;
663
+
490
664
  // Skip if suite is marked as skip
491
665
  if (suite.skip) {
492
666
  // Mark all tests in this suite as skipped
493
667
  for (const t of suite.tests) {
494
- results.push({
495
- name: namePath ? namePath + ' > ' + t.name : t.name,
496
- passed: true,
497
- skipped: true,
668
+ const testFullName = fullName ? fullName + ' > ' + t.name : t.name;
669
+ const testInfo = {
670
+ name: t.name,
671
+ suitePath: suitePath,
672
+ fullName: testFullName,
673
+ };
674
+ emitEvent({ type: 'testStart', test: testInfo });
675
+
676
+ const testResult = {
677
+ name: t.name,
678
+ suitePath: suitePath,
679
+ fullName: testFullName,
680
+ status: 'skip',
498
681
  duration: 0,
499
- });
500
- }
501
- return;
502
- }
503
-
504
- // Run beforeAll hooks
505
- for (const hook of suite.beforeAll) {
506
- await hook();
507
- }
508
-
509
- // Run tests
510
- for (const t of suite.tests) {
511
- const testName = namePath ? namePath + ' > ' + t.name : t.name;
682
+ };
683
+ testResults.push(testResult);
684
+ suiteSkipped++;
512
685
 
513
- // Skip if .only is used and this test isn't .only AND the suite doesn't have .only
514
- if (hasOnly && !t.only && !suite.only) continue;
515
-
516
- // Skip if test is marked as skip
517
- if (t.skip) {
518
- results.push({
519
- name: testName,
520
- passed: true,
521
- skipped: true,
522
- duration: 0,
523
- });
524
- continue;
686
+ emitEvent({ type: 'testEnd', test: testResult });
525
687
  }
526
-
527
- // Handle todo tests (no function provided)
528
- if (t.todo) {
529
- results.push({
530
- name: testName,
531
- passed: true,
532
- skipped: true,
533
- duration: 0,
534
- });
535
- continue;
688
+ } else {
689
+ // Run beforeAll hooks
690
+ for (const hook of suite.beforeAll) {
691
+ await hook();
536
692
  }
537
693
 
538
- const start = Date.now();
539
- try {
540
- // Run all beforeEach hooks (parent first, then current)
541
- for (const hook of [...parentHooks.beforeEach, ...suite.beforeEach]) {
542
- await hook();
694
+ // Run tests
695
+ for (const t of suite.tests) {
696
+ const testFullName = fullName ? fullName + ' > ' + t.name : t.name;
697
+ const testInfo = {
698
+ name: t.name,
699
+ suitePath: suitePath,
700
+ fullName: testFullName,
701
+ };
702
+
703
+ // Skip if .only is used and this test isn't .only AND the suite doesn't have .only
704
+ if (hasOnly && !t.only && !suite.only) continue;
705
+
706
+ emitEvent({ type: 'testStart', test: testInfo });
707
+
708
+ // Skip if test is marked as skip
709
+ if (t.skip) {
710
+ const testResult = {
711
+ name: t.name,
712
+ suitePath: suitePath,
713
+ fullName: testFullName,
714
+ status: 'skip',
715
+ duration: 0,
716
+ };
717
+ testResults.push(testResult);
718
+ suiteSkipped++;
719
+ emitEvent({ type: 'testEnd', test: testResult });
720
+ continue;
543
721
  }
544
722
 
545
- // Run test
546
- await t.fn();
723
+ // Handle todo tests (no function provided)
724
+ if (t.todo) {
725
+ const testResult = {
726
+ name: t.name,
727
+ suitePath: suitePath,
728
+ fullName: testFullName,
729
+ status: 'todo',
730
+ duration: 0,
731
+ };
732
+ testResults.push(testResult);
733
+ suiteTodo++;
734
+ emitEvent({ type: 'testEnd', test: testResult });
735
+ continue;
736
+ }
547
737
 
548
- // Run all afterEach hooks (current first, then parent)
549
- for (const hook of [...suite.afterEach, ...parentHooks.afterEach]) {
550
- await hook();
738
+ const testStart = Date.now();
739
+ try {
740
+ // Run all beforeEach hooks (parent first, then current)
741
+ for (const hook of [...parentHooks.beforeEach, ...suite.beforeEach]) {
742
+ await hook();
743
+ }
744
+
745
+ // Run test
746
+ await t.fn();
747
+
748
+ // Run all afterEach hooks (current first, then parent)
749
+ for (const hook of [...suite.afterEach, ...parentHooks.afterEach]) {
750
+ await hook();
751
+ }
752
+
753
+ const testResult = {
754
+ name: t.name,
755
+ suitePath: suitePath,
756
+ fullName: testFullName,
757
+ status: 'pass',
758
+ duration: Date.now() - testStart,
759
+ };
760
+ testResults.push(testResult);
761
+ suitePassed++;
762
+ emitEvent({ type: 'testEnd', test: testResult });
763
+ } catch (err) {
764
+ const testError = {
765
+ message: err.message || String(err),
766
+ stack: err.stack,
767
+ };
768
+ // If it's a TestError, include matcher info
769
+ if (err.matcherName !== undefined) {
770
+ testError.matcherName = err.matcherName;
771
+ testError.expected = err.expected;
772
+ testError.actual = err.actual;
773
+ }
774
+ const testResult = {
775
+ name: t.name,
776
+ suitePath: suitePath,
777
+ fullName: testFullName,
778
+ status: 'fail',
779
+ duration: Date.now() - testStart,
780
+ error: testError,
781
+ };
782
+ testResults.push(testResult);
783
+ suiteFailed++;
784
+ emitEvent({ type: 'testEnd', test: testResult });
551
785
  }
786
+ }
552
787
 
553
- results.push({
554
- name: testName,
555
- passed: true,
556
- duration: Date.now() - start,
557
- });
558
- } catch (err) {
559
- results.push({
560
- name: testName,
561
- passed: false,
562
- error: err.message || String(err),
563
- duration: Date.now() - start,
564
- });
788
+ // Run child suites
789
+ for (const child of suite.children) {
790
+ const childPath = [...suitePath, child.name];
791
+ await runSuite(child, {
792
+ beforeEach: [...parentHooks.beforeEach, ...suite.beforeEach],
793
+ afterEach: [...suite.afterEach, ...parentHooks.afterEach],
794
+ }, childPath, depth + 1);
565
795
  }
566
- }
567
796
 
568
- // Run child suites
569
- for (const child of suite.children) {
570
- const childPath = namePath ? namePath + ' > ' + child.name : child.name;
571
- await runSuite(child, {
572
- beforeEach: [...parentHooks.beforeEach, ...suite.beforeEach],
573
- afterEach: [...suite.afterEach, ...parentHooks.afterEach],
574
- }, childPath);
797
+ // Run afterAll hooks
798
+ for (const hook of suite.afterAll) {
799
+ await hook();
800
+ }
575
801
  }
576
802
 
577
- // Run afterAll hooks
578
- for (const hook of suite.afterAll) {
579
- await hook();
803
+ // Emit suiteEnd (only for non-root suites)
804
+ if (suite !== rootSuite) {
805
+ const suiteResult = {
806
+ ...suiteInfo,
807
+ passed: suitePassed,
808
+ failed: suiteFailed,
809
+ skipped: suiteSkipped,
810
+ todo: suiteTodo,
811
+ duration: Date.now() - suiteStart,
812
+ };
813
+ suiteResults.push(suiteResult);
814
+ emitEvent({ type: 'suiteEnd', suite: suiteResult });
580
815
  }
581
816
  }
582
817
 
583
- await runSuite(rootSuite, { beforeEach: [], afterEach: [] }, '');
818
+ await runSuite(rootSuite, { beforeEach: [], afterEach: [] }, [], -1);
584
819
 
585
- const passed = results.filter(r => r.passed && !r.skipped).length;
586
- const failed = results.filter(r => !r.passed).length;
587
- const skipped = results.filter(r => r.skipped).length;
820
+ const passed = testResults.filter(r => r.status === 'pass').length;
821
+ const failed = testResults.filter(r => r.status === 'fail').length;
822
+ const skipped = testResults.filter(r => r.status === 'skip').length;
823
+ const todo = testResults.filter(r => r.status === 'todo').length;
588
824
 
589
- return JSON.stringify({
825
+ const runResults = {
590
826
  passed,
591
827
  failed,
592
828
  skipped,
593
- total: results.length,
594
- results,
595
- });
829
+ todo,
830
+ total: testResults.length,
831
+ duration: Date.now() - runStart,
832
+ success: failed === 0,
833
+ suites: suiteResults,
834
+ tests: testResults,
835
+ };
836
+
837
+ emitEvent({ type: 'runEnd', results: runResults });
838
+
839
+ return JSON.stringify(runResults);
840
+ }
841
+
842
+ // ============================================================
843
+ // Helper Functions
844
+ // ============================================================
845
+
846
+ function __hasTests() {
847
+ function checkSuite(suite) {
848
+ if (suite.tests.length > 0) return true;
849
+ for (const child of suite.children) {
850
+ if (checkSuite(child)) return true;
851
+ }
852
+ return false;
853
+ }
854
+ return checkSuite(rootSuite);
855
+ }
856
+
857
+ function __getTestCount() {
858
+ function countInSuite(suite) {
859
+ let count = suite.tests.length;
860
+ for (const child of suite.children) {
861
+ count += countInSuite(child);
862
+ }
863
+ return count;
864
+ }
865
+ return countInSuite(rootSuite);
596
866
  }
597
867
 
598
868
  // Reset function to clear state between runs
@@ -608,6 +878,10 @@ var testEnvironmentCode = `
608
878
  suiteStack.push(rootSuite);
609
879
  }
610
880
 
881
+ function __setEventCallback(callback) {
882
+ eventCallback = callback;
883
+ }
884
+
611
885
  // ============================================================
612
886
  // Expose Globals
613
887
  // ============================================================
@@ -622,10 +896,28 @@ var testEnvironmentCode = `
622
896
  globalThis.afterAll = afterAll;
623
897
  globalThis.__runAllTests = __runAllTests;
624
898
  globalThis.__resetTestEnvironment = __resetTestEnvironment;
899
+ globalThis.__hasTests = __hasTests;
900
+ globalThis.__getTestCount = __getTestCount;
901
+ globalThis.__setEventCallback = __setEventCallback;
625
902
  })();
626
903
  `;
627
- async function setupTestEnvironment(context) {
904
+ async function setupTestEnvironment(context, options) {
628
905
  context.evalSync(testEnvironmentCode);
906
+ if (options?.onEvent) {
907
+ const eventCallbackRef = new import_isolated_vm.default.Reference((eventJson) => {
908
+ try {
909
+ const event = JSON.parse(eventJson);
910
+ options.onEvent(event);
911
+ } catch {}
912
+ });
913
+ const global = context.global;
914
+ global.setSync("__eventCallbackRef", eventCallbackRef);
915
+ context.evalSync(`
916
+ __setEventCallback((eventJson) => {
917
+ __eventCallbackRef.applySync(undefined, [eventJson]);
918
+ });
919
+ `);
920
+ }
629
921
  return {
630
922
  dispose() {
631
923
  try {
@@ -638,6 +930,12 @@ async function runTests(context) {
638
930
  const resultJson = await context.eval("__runAllTests()", { promise: true });
639
931
  return JSON.parse(resultJson);
640
932
  }
933
+ function hasTests(context) {
934
+ return context.evalSync("__hasTests()");
935
+ }
936
+ function getTestCount(context) {
937
+ return context.evalSync("__getTestCount()");
938
+ }
641
939
  })
642
940
 
643
- //# debugId=AE2FFE17A1C19B3664756E2164756E21
941
+ //# debugId=424CE17957C8217764756E2164756E21