on-zero 0.16.19 → 0.16.20

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 (120) hide show
  1. package/dist/cjs/createUseQuery.cjs +2 -1
  2. package/dist/cjs/createUseQuery.native.js +2 -1
  3. package/dist/cjs/createUseQuery.native.js.map +1 -1
  4. package/dist/cjs/createUseQueryDirect.cjs +2 -1
  5. package/dist/cjs/createUseQueryDirect.native.js +2 -1
  6. package/dist/cjs/createUseQueryDirect.native.js.map +1 -1
  7. package/dist/cjs/createZeroClient.cjs +75 -9
  8. package/dist/cjs/createZeroClient.native.js +151 -81
  9. package/dist/cjs/createZeroClient.native.js.map +1 -1
  10. package/dist/cjs/createZeroClient.recovery.test.cjs +351 -10
  11. package/dist/cjs/createZeroClient.recovery.test.native.js +412 -12
  12. package/dist/cjs/createZeroClient.recovery.test.native.js.map +1 -1
  13. package/dist/cjs/generate.cjs +16 -11
  14. package/dist/cjs/generate.native.js +16 -11
  15. package/dist/cjs/generate.native.js.map +1 -1
  16. package/dist/cjs/generate.test.cjs +22 -0
  17. package/dist/cjs/generate.test.native.js +22 -0
  18. package/dist/cjs/generate.test.native.js.map +1 -1
  19. package/dist/cjs/helpers/recoverZeroClient.cjs +542 -52
  20. package/dist/cjs/helpers/recoverZeroClient.native.js +721 -59
  21. package/dist/cjs/helpers/recoverZeroClient.native.js.map +1 -1
  22. package/dist/cjs/helpers/recoverZeroClient.test.cjs +318 -0
  23. package/dist/cjs/helpers/recoverZeroClient.test.native.js +361 -0
  24. package/dist/cjs/helpers/recoverZeroClient.test.native.js.map +1 -1
  25. package/dist/cjs/kvStore.cjs +30 -0
  26. package/dist/cjs/kvStore.native.js +34 -0
  27. package/dist/cjs/kvStore.native.js.map +1 -0
  28. package/dist/cjs/queryJson.cjs +58 -0
  29. package/dist/cjs/queryJson.native.js +86 -0
  30. package/dist/cjs/queryJson.native.js.map +1 -0
  31. package/dist/cjs/resolveQuery.cjs +2 -0
  32. package/dist/cjs/resolveQuery.native.js +2 -0
  33. package/dist/cjs/resolveQuery.native.js.map +1 -1
  34. package/dist/cjs/useQuery.empty.test.cjs +11 -1
  35. package/dist/cjs/useQuery.empty.test.native.js +23 -1
  36. package/dist/cjs/useQuery.empty.test.native.js.map +1 -1
  37. package/dist/cjs/useQuery.ssr.test.cjs +22 -1
  38. package/dist/cjs/useQuery.ssr.test.native.js +30 -1
  39. package/dist/cjs/useQuery.ssr.test.native.js.map +1 -1
  40. package/dist/esm/createUseQuery.mjs +2 -1
  41. package/dist/esm/createUseQuery.mjs.map +1 -1
  42. package/dist/esm/createUseQuery.native.js +2 -1
  43. package/dist/esm/createUseQuery.native.js.map +1 -1
  44. package/dist/esm/createUseQueryDirect.mjs +2 -1
  45. package/dist/esm/createUseQueryDirect.mjs.map +1 -1
  46. package/dist/esm/createUseQueryDirect.native.js +2 -1
  47. package/dist/esm/createUseQueryDirect.native.js.map +1 -1
  48. package/dist/esm/createZeroClient.mjs +76 -10
  49. package/dist/esm/createZeroClient.mjs.map +1 -1
  50. package/dist/esm/createZeroClient.native.js +152 -82
  51. package/dist/esm/createZeroClient.native.js.map +1 -1
  52. package/dist/esm/createZeroClient.recovery.test.mjs +352 -11
  53. package/dist/esm/createZeroClient.recovery.test.mjs.map +1 -1
  54. package/dist/esm/createZeroClient.recovery.test.native.js +413 -13
  55. package/dist/esm/createZeroClient.recovery.test.native.js.map +1 -1
  56. package/dist/esm/generate.mjs +16 -11
  57. package/dist/esm/generate.mjs.map +1 -1
  58. package/dist/esm/generate.native.js +16 -11
  59. package/dist/esm/generate.native.js.map +1 -1
  60. package/dist/esm/generate.test.mjs +22 -0
  61. package/dist/esm/generate.test.mjs.map +1 -1
  62. package/dist/esm/generate.test.native.js +22 -0
  63. package/dist/esm/generate.test.native.js.map +1 -1
  64. package/dist/esm/helpers/recoverZeroClient.mjs +542 -54
  65. package/dist/esm/helpers/recoverZeroClient.mjs.map +1 -1
  66. package/dist/esm/helpers/recoverZeroClient.native.js +721 -61
  67. package/dist/esm/helpers/recoverZeroClient.native.js.map +1 -1
  68. package/dist/esm/helpers/recoverZeroClient.test.mjs +319 -1
  69. package/dist/esm/helpers/recoverZeroClient.test.mjs.map +1 -1
  70. package/dist/esm/helpers/recoverZeroClient.test.native.js +362 -1
  71. package/dist/esm/helpers/recoverZeroClient.test.native.js.map +1 -1
  72. package/dist/esm/kvStore.mjs +5 -0
  73. package/dist/esm/kvStore.mjs.map +1 -0
  74. package/dist/esm/kvStore.native.js +6 -0
  75. package/dist/esm/kvStore.native.js.map +1 -0
  76. package/dist/esm/queryJson.mjs +32 -0
  77. package/dist/esm/queryJson.mjs.map +1 -0
  78. package/dist/esm/queryJson.native.js +57 -0
  79. package/dist/esm/queryJson.native.js.map +1 -0
  80. package/dist/esm/resolveQuery.mjs +2 -0
  81. package/dist/esm/resolveQuery.mjs.map +1 -1
  82. package/dist/esm/resolveQuery.native.js +2 -0
  83. package/dist/esm/resolveQuery.native.js.map +1 -1
  84. package/dist/esm/useQuery.empty.test.mjs +12 -2
  85. package/dist/esm/useQuery.empty.test.mjs.map +1 -1
  86. package/dist/esm/useQuery.empty.test.native.js +24 -2
  87. package/dist/esm/useQuery.empty.test.native.js.map +1 -1
  88. package/dist/esm/useQuery.ssr.test.mjs +23 -2
  89. package/dist/esm/useQuery.ssr.test.mjs.map +1 -1
  90. package/dist/esm/useQuery.ssr.test.native.js +31 -2
  91. package/dist/esm/useQuery.ssr.test.native.js.map +1 -1
  92. package/package.json +11 -3
  93. package/src/createUseQuery.tsx +2 -1
  94. package/src/createUseQueryDirect.tsx +2 -1
  95. package/src/createZeroClient.recovery.test.tsx +370 -7
  96. package/src/createZeroClient.tsx +100 -10
  97. package/src/generate.test.ts +31 -0
  98. package/src/generate.ts +22 -10
  99. package/src/helpers/recoverZeroClient.test.ts +323 -0
  100. package/src/helpers/recoverZeroClient.ts +896 -78
  101. package/src/kvStore.native.ts +7 -0
  102. package/src/kvStore.ts +7 -0
  103. package/src/queryJson.ts +46 -0
  104. package/src/resolveQuery.ts +2 -0
  105. package/src/useQuery.empty.test.tsx +16 -2
  106. package/src/useQuery.ssr.test.ts +23 -2
  107. package/types/createUseQuery.d.ts.map +1 -1
  108. package/types/createUseQueryDirect.d.ts.map +1 -1
  109. package/types/createZeroClient.d.ts.map +1 -1
  110. package/types/createZeroClient.recovery.test.d.ts.map +1 -1
  111. package/types/generate.d.ts.map +1 -1
  112. package/types/helpers/recoverZeroClient.d.ts +6 -0
  113. package/types/helpers/recoverZeroClient.d.ts.map +1 -1
  114. package/types/kvStore.d.ts +2 -0
  115. package/types/kvStore.d.ts.map +1 -0
  116. package/types/kvStore.native.d.ts +3 -0
  117. package/types/kvStore.native.d.ts.map +1 -0
  118. package/types/queryJson.d.ts +3 -0
  119. package/types/queryJson.d.ts.map +1 -0
  120. package/types/resolveQuery.d.ts.map +1 -1
@@ -6,35 +6,63 @@ var import_createZeroClient = require("./createZeroClient.cjs");
6
6
  var import_recoverZeroClient = require("./helpers/recoverZeroClient.cjs");
7
7
  var import_jsx_runtime = require("react/jsx-runtime");
8
8
  const fakeZero = import_vitest.vi.hoisted(() => {
9
+ const group = {
10
+ current: "g1"
11
+ };
9
12
  class FakeZero {
10
13
  constructor(options) {
11
14
  this.options = options;
12
15
  instances.push(this);
16
+ this.clientGroupID = Promise.resolve(group.current);
17
+ const listeners = /* @__PURE__ */new Set();
18
+ this.connection = {
19
+ state: {
20
+ current: {
21
+ name: "closed"
22
+ },
23
+ subscribe: listener => {
24
+ listeners.add(listener);
25
+ return () => {
26
+ listeners.delete(listener);
27
+ };
28
+ }
29
+ },
30
+ connect: import_vitest.vi.fn()
31
+ };
32
+ this.__connectionListeners = listeners;
13
33
  }
14
34
  context = {};
15
- connection = {
16
- state: {
17
- current: {
18
- name: "closed"
19
- },
20
- subscribe: () => () => {}
21
- },
22
- connect: import_vitest.vi.fn()
23
- };
35
+ connection;
24
36
  delete = import_vitest.vi.fn(async () => ({
25
37
  errors: []
26
38
  }));
27
39
  close = import_vitest.vi.fn();
28
40
  run = import_vitest.vi.fn(async () => []);
41
+ mutate = {
42
+ note: {
43
+ insert: import_vitest.vi.fn(() => ({
44
+ client: Promise.resolve({}),
45
+ server: Promise.resolve({})
46
+ }))
47
+ }
48
+ };
29
49
  preload = import_vitest.vi.fn(() => ({
30
50
  cleanup: () => {},
31
51
  complete: Promise.resolve()
32
52
  }));
53
+ clientGroupID;
33
54
  }
34
55
  const instances = [];
56
+ function setConnectionState(instance, name) {
57
+ instance.connection.state.current.name = name;
58
+ const listeners = instance.__connectionListeners;
59
+ for (const listener of [...listeners]) listener();
60
+ }
35
61
  return {
36
62
  FakeZero,
37
- instances
63
+ instances,
64
+ group,
65
+ setConnectionState
38
66
  };
39
67
  });
40
68
  import_vitest.vi.mock("@rocicorp/zero", async importOriginal => {
@@ -64,6 +92,7 @@ let root;
64
92
  window.sessionStorage.clear();
65
93
  (0, import_recoverZeroClient.resetRecoveryStateForTests)();
66
94
  fakeZero.instances.length = 0;
95
+ fakeZero.group.current = "g1";
67
96
  container = document.createElement("div");
68
97
  root = null;
69
98
  });
@@ -421,4 +450,316 @@ async function mount() {
421
450
  (0, import_vitest.expect)(await isolated.waitForZero()).toBe(connection.zero);
422
451
  (0, import_vitest.expect)(first.close).toHaveBeenCalledOnce();
423
452
  await connection.close();
453
+ });
454
+ function makeTransitionClient(instanceName) {
455
+ return (0, import_createZeroClient.createZeroClient)({
456
+ schema,
457
+ models: {},
458
+ groupedQueries: {},
459
+ instanceName
460
+ });
461
+ }
462
+ function collectClientEvents(client2) {
463
+ const events = [];
464
+ const off = client2.zeroEvents.listen(event => {
465
+ if (event) events.push(event);
466
+ });
467
+ return {
468
+ events,
469
+ off
470
+ };
471
+ }
472
+ async function mountTransitionClient(client2, userID) {
473
+ const el = document.createElement("div");
474
+ const mountedRoot = (0, import_client.createRoot)(el);
475
+ await (0, import_react.act)(async () => {
476
+ mountedRoot.render(/* @__PURE__ */(0, import_jsx_runtime.jsx)(client2.ProvideZero, {
477
+ cacheURL: "http://127.0.0.1:7777/zero",
478
+ userID,
479
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)("span", {
480
+ children: "ok"
481
+ })
482
+ }));
483
+ await Promise.resolve();
484
+ });
485
+ return {
486
+ el,
487
+ root: mountedRoot,
488
+ instance: fakeZero.instances.at(-1)
489
+ };
490
+ }
491
+ async function unmountTransitionClient(mounted) {
492
+ await (0, import_react.act)(async () => {
493
+ mounted.root.unmount();
494
+ });
495
+ }
496
+ function withoutPageReload() {
497
+ const originalLocation = globalThis.location;
498
+ Object.defineProperty(globalThis, "location", {
499
+ configurable: true,
500
+ value: void 0
501
+ });
502
+ return () => {
503
+ Object.defineProperty(globalThis, "location", {
504
+ configurable: true,
505
+ value: originalLocation
506
+ });
507
+ };
508
+ }
509
+ (0, import_vitest.test)("two providers ride one group transition and keep querying and mutating", async () => {
510
+ const restoreLocation = withoutPageReload();
511
+ const clientA = makeTransitionClient("transition-two-a");
512
+ const clientB = makeTransitionClient("transition-two-b");
513
+ const collectedA = collectClientEvents(clientA);
514
+ const collectedB = collectClientEvents(clientB);
515
+ const mountedA = await mountTransitionClient(clientA, "transition-user");
516
+ const mountedB = await mountTransitionClient(clientB, "transition-user");
517
+ const firstA = mountedA.instance;
518
+ const firstB = mountedB.instance;
519
+ const countBefore = fakeZero.instances.length;
520
+ try {
521
+ firstA.options.onUpdateNeeded({
522
+ type: "NewClientGroup"
523
+ });
524
+ firstB.options.onUpdateNeeded({
525
+ type: "NewClientGroup"
526
+ });
527
+ await (0, import_react.act)(async () => {
528
+ await new Promise(resolve => setTimeout(resolve, 0));
529
+ });
530
+ (0, import_vitest.expect)(fakeZero.instances).toHaveLength(countBefore + 2);
531
+ const secondA = fakeZero.instances[countBefore];
532
+ const secondB = fakeZero.instances[countBefore + 1];
533
+ (0, import_vitest.expect)(secondA).not.toBe(firstA);
534
+ (0, import_vitest.expect)(secondB).not.toBe(firstB);
535
+ (0, import_vitest.expect)(firstA.close).toHaveBeenCalledTimes(1);
536
+ (0, import_vitest.expect)(firstB.close).toHaveBeenCalledTimes(1);
537
+ (0, import_vitest.expect)((0, import_recoverZeroClient.isGroupTransitionOpen)()).toBe(true);
538
+ await (0, import_react.act)(async () => {
539
+ fakeZero.setConnectionState(secondA, "connected");
540
+ fakeZero.setConnectionState(secondB, "connected");
541
+ await Promise.resolve();
542
+ });
543
+ await import_vitest.vi.waitFor(() => (0, import_vitest.expect)((0, import_recoverZeroClient.isGroupTransitionOpen)()).toBe(false));
544
+ const allEvents = [...collectedA.events, ...collectedB.events];
545
+ (0, import_vitest.expect)(allEvents.filter(event => event.type === "recovering")).toHaveLength(1);
546
+ (0, import_vitest.expect)(allEvents.filter(event => event.type === "fatal")).toHaveLength(0);
547
+ (0, import_vitest.expect)(firstA.delete).not.toHaveBeenCalled();
548
+ (0, import_vitest.expect)(firstB.delete).not.toHaveBeenCalled();
549
+ await clientA.zero.run({});
550
+ await clientB.zero.run({});
551
+ (0, import_vitest.expect)(secondA.run).toHaveBeenCalled();
552
+ (0, import_vitest.expect)(secondB.run).toHaveBeenCalled();
553
+ clientA.zero.mutate.note.insert({
554
+ id: "a1"
555
+ });
556
+ clientB.zero.mutate.note.insert({
557
+ id: "b1"
558
+ });
559
+ (0, import_vitest.expect)(secondA.mutate.note.insert).toHaveBeenCalledTimes(1);
560
+ (0, import_vitest.expect)(secondB.mutate.note.insert).toHaveBeenCalledTimes(1);
561
+ } finally {
562
+ collectedA.off();
563
+ collectedB.off();
564
+ await unmountTransitionClient(mountedA);
565
+ await unmountTransitionClient(mountedB);
566
+ restoreLocation();
567
+ }
568
+ });
569
+ (0, import_vitest.test)("a second registry change after recovery remints again without fatal", async () => {
570
+ const restoreLocation = withoutPageReload();
571
+ const clientA = makeTransitionClient("transition-second-a");
572
+ const clientB = makeTransitionClient("transition-second-b");
573
+ const collectedA = collectClientEvents(clientA);
574
+ const collectedB = collectClientEvents(clientB);
575
+ const mountedA = await mountTransitionClient(clientA, "transition-second-user");
576
+ const mountedB = await mountTransitionClient(clientB, "transition-second-user");
577
+ try {
578
+ const fireBoth = instances => {
579
+ instances[0].options.onUpdateNeeded({
580
+ type: "NewClientGroup"
581
+ });
582
+ instances[1].options.onUpdateNeeded({
583
+ type: "NewClientGroup"
584
+ });
585
+ };
586
+ const settleRemints = async countBefore2 => {
587
+ await (0, import_react.act)(async () => {
588
+ await new Promise(resolve => setTimeout(resolve, 0));
589
+ });
590
+ (0, import_vitest.expect)(fakeZero.instances).toHaveLength(countBefore2 + 2);
591
+ const next = fakeZero.instances.slice(countBefore2);
592
+ await (0, import_react.act)(async () => {
593
+ for (const instance of next) fakeZero.setConnectionState(instance, "connected");
594
+ await Promise.resolve();
595
+ });
596
+ await import_vitest.vi.waitFor(() => (0, import_vitest.expect)((0, import_recoverZeroClient.isGroupTransitionOpen)()).toBe(false));
597
+ return next;
598
+ };
599
+ const countBeforeFirst = fakeZero.instances.length;
600
+ fireBoth(fakeZero.instances.slice(-2));
601
+ await settleRemints(countBeforeFirst);
602
+ fakeZero.group.current = "g2";
603
+ const countBefore = fakeZero.instances.length;
604
+ fireBoth(fakeZero.instances.slice(-2));
605
+ const third = await settleRemints(countBefore);
606
+ const allEvents = [...collectedA.events, ...collectedB.events];
607
+ (0, import_vitest.expect)(allEvents.filter(event => event.type === "recovering")).toHaveLength(2);
608
+ (0, import_vitest.expect)(allEvents.filter(event => event.type === "fatal")).toHaveLength(0);
609
+ await clientA.zero.run({});
610
+ await clientB.zero.run({});
611
+ (0, import_vitest.expect)(third[0].run).toHaveBeenCalled();
612
+ (0, import_vitest.expect)(third[1].run).toHaveBeenCalled();
613
+ } finally {
614
+ collectedA.off();
615
+ collectedB.off();
616
+ await unmountTransitionClient(mountedA);
617
+ await unmountTransitionClient(mountedB);
618
+ restoreLocation();
619
+ }
620
+ });
621
+ (0, import_vitest.test)("negative control: an incompatible schema emits exactly one terminal error, never a loop", async () => {
622
+ const restoreLocation = withoutPageReload();
623
+ const consoleError = import_vitest.vi.spyOn(console, "error").mockImplementation(() => {});
624
+ const clientA = makeTransitionClient("transition-negative-a");
625
+ const clientB = makeTransitionClient("transition-negative-b");
626
+ const collectedA = collectClientEvents(clientA);
627
+ const collectedB = collectClientEvents(clientB);
628
+ const mountedA = await mountTransitionClient(clientA, "transition-negative-user");
629
+ const mountedB = await mountTransitionClient(clientB, "transition-negative-user");
630
+ const firstA = mountedA.instance;
631
+ const firstB = mountedB.instance;
632
+ const countBefore = fakeZero.instances.length;
633
+ try {
634
+ firstA.options.onUpdateNeeded({
635
+ type: "SchemaVersionNotSupported"
636
+ });
637
+ firstB.options.onUpdateNeeded({
638
+ type: "SchemaVersionNotSupported"
639
+ });
640
+ await (0, import_react.act)(async () => {
641
+ await new Promise(resolve => setTimeout(resolve, 0));
642
+ });
643
+ (0, import_vitest.expect)(firstA.delete).toHaveBeenCalledTimes(1);
644
+ (0, import_vitest.expect)(firstB.delete).toHaveBeenCalledTimes(1);
645
+ (0, import_vitest.expect)(fakeZero.instances).toHaveLength(countBefore + 2);
646
+ const secondA = fakeZero.instances[countBefore];
647
+ const secondB = fakeZero.instances[countBefore + 1];
648
+ (0, import_vitest.expect)((0, import_recoverZeroClient.isGroupTransitionOpen)()).toBe(true);
649
+ secondA.options.onUpdateNeeded({
650
+ type: "SchemaVersionNotSupported"
651
+ });
652
+ await (0, import_react.act)(async () => {
653
+ await new Promise(resolve => setTimeout(resolve, 0));
654
+ });
655
+ const allEvents = () => [...collectedA.events, ...collectedB.events];
656
+ (0, import_vitest.expect)(allEvents().filter(event => event.type === "fatal")).toHaveLength(1);
657
+ const [fatal] = allEvents().filter(event => event.type === "fatal");
658
+ (0, import_vitest.expect)(fatal).toMatchObject({
659
+ reasonKey: "SchemaVersionNotSupported",
660
+ reason: import_vitest.expect.stringContaining("g1")
661
+ });
662
+ (0, import_vitest.expect)(consoleError).toHaveBeenCalledTimes(1);
663
+ (0, import_vitest.expect)(consoleError.mock.calls[0][0]).toContain("g1");
664
+ secondB.options.onUpdateNeeded({
665
+ type: "SchemaVersionNotSupported"
666
+ });
667
+ secondA.options.onUpdateNeeded({
668
+ type: "SchemaVersionNotSupported"
669
+ });
670
+ await (0, import_react.act)(async () => {
671
+ await new Promise(resolve => setTimeout(resolve, 0));
672
+ });
673
+ (0, import_vitest.expect)(allEvents().filter(event => event.type === "fatal")).toHaveLength(1);
674
+ (0, import_vitest.expect)(consoleError).toHaveBeenCalledTimes(1);
675
+ (0, import_vitest.expect)(fakeZero.instances).toHaveLength(countBefore + 2);
676
+ } finally {
677
+ collectedA.off();
678
+ collectedB.off();
679
+ await unmountTransitionClient(mountedA);
680
+ await unmountTransitionClient(mountedB);
681
+ restoreLocation();
682
+ consoleError.mockRestore();
683
+ }
684
+ });
685
+ (0, import_vitest.test)("concurrent update signals across providers schedule a single reload", async () => {
686
+ const reloadPage = import_vitest.vi.fn();
687
+ const originalLocation = globalThis.location;
688
+ Object.defineProperty(globalThis, "location", {
689
+ configurable: true,
690
+ value: {
691
+ href: "http://localhost/reload-test",
692
+ reload: reloadPage
693
+ }
694
+ });
695
+ const scheduleA = import_vitest.vi.fn();
696
+ const scheduleB = import_vitest.vi.fn();
697
+ const clientA = makeTransitionClient("transition-reload-a");
698
+ const clientB = makeTransitionClient("transition-reload-b");
699
+ const collectedA = collectClientEvents(clientA);
700
+ const collectedB = collectClientEvents(clientB);
701
+ const elA = document.createElement("div");
702
+ const elB = document.createElement("div");
703
+ const rootA = (0, import_client.createRoot)(elA);
704
+ const rootB = (0, import_client.createRoot)(elB);
705
+ try {
706
+ await (0, import_react.act)(async () => {
707
+ rootA.render(/* @__PURE__ */(0, import_jsx_runtime.jsx)(clientA.ProvideZero, {
708
+ cacheURL: "http://127.0.0.1:7777/zero",
709
+ userID: "transition-reload-user",
710
+ scheduleReload: scheduleA,
711
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)("span", {
712
+ children: "ok"
713
+ })
714
+ }));
715
+ await Promise.resolve();
716
+ });
717
+ await (0, import_react.act)(async () => {
718
+ rootB.render(/* @__PURE__ */(0, import_jsx_runtime.jsx)(clientB.ProvideZero, {
719
+ cacheURL: "http://127.0.0.1:7777/zero",
720
+ userID: "transition-reload-user",
721
+ scheduleReload: scheduleB,
722
+ children: /* @__PURE__ */(0, import_jsx_runtime.jsx)("span", {
723
+ children: "ok"
724
+ })
725
+ }));
726
+ await Promise.resolve();
727
+ });
728
+ const firstA = fakeZero.instances.at(-2);
729
+ const firstB = fakeZero.instances.at(-1);
730
+ firstA.options.onUpdateNeeded({
731
+ type: "NewClientGroup"
732
+ });
733
+ firstB.options.onUpdateNeeded({
734
+ type: "NewClientGroup"
735
+ });
736
+ await (0, import_react.act)(async () => {
737
+ await new Promise(resolve => setTimeout(resolve, 0));
738
+ });
739
+ (0, import_vitest.expect)(scheduleA.mock.calls.length + scheduleB.mock.calls.length).toBe(1);
740
+ (0, import_vitest.expect)(reloadPage).not.toHaveBeenCalled();
741
+ const allEvents = [...collectedA.events, ...collectedB.events];
742
+ (0, import_vitest.expect)(allEvents.filter(event => event.type === "fatal")).toHaveLength(0);
743
+ const ctx = (scheduleA.mock.calls[0] ?? scheduleB.mock.calls[0])[0];
744
+ await (0, import_react.act)(async () => {
745
+ await ctx.performReload();
746
+ });
747
+ (0, import_vitest.expect)(reloadPage).toHaveBeenCalledTimes(1);
748
+ (0, import_vitest.expect)((0, import_recoverZeroClient.isGroupTransitionOpen)()).toBe(false);
749
+ const marker = window.sessionStorage.getItem("on-zero-recover-http://localhost/reload-test-NewClientGroup");
750
+ (0, import_vitest.expect)(marker).toContain("g1");
751
+ } finally {
752
+ collectedA.off();
753
+ collectedB.off();
754
+ await (0, import_react.act)(async () => {
755
+ rootA.unmount();
756
+ });
757
+ await (0, import_react.act)(async () => {
758
+ rootB.unmount();
759
+ });
760
+ Object.defineProperty(globalThis, "location", {
761
+ configurable: true,
762
+ value: originalLocation
763
+ });
764
+ }
424
765
  });