|
1 | 1 | import { describe, test, expect } from "vitest"; |
2 | | -import { |
3 | | - createStore, |
4 | | - createEvent, |
5 | | - createEffect, |
6 | | - fork, |
7 | | - serialize, |
8 | | - allSettled, |
9 | | - combine, |
10 | | - sample, |
11 | | -} from "effector"; |
12 | 2 |
|
13 | | -import { internalGetClientScope } from "./get-scope"; |
| 3 | +import { getScope } from "./get-scope"; |
14 | 4 |
|
15 | | -const up = createEvent(); |
16 | | -const longUpFx = createEffect(async () => { |
17 | | - await new Promise((r) => setTimeout(r, 10)); |
18 | | -}); |
19 | | -const $count = createStore(0).on([up, longUpFx.done], (s) => s + 1); |
20 | | -const $derived = $count.map((s) => ({ ref: s })); |
21 | | -const $combined = combine({ ref: $count }); |
22 | | -const $nestedCombined = combine({ ref: $derived }); |
| 5 | +describe('getScope implementation details', () => { |
| 6 | + test('should return new scope on server every time', () => { |
| 7 | + /** |
| 8 | + * Implementation detail that may change in the future |
| 9 | + */ |
| 10 | + const scopeOne = getScope(); |
| 11 | + const scopeTwo = getScope(); |
23 | 12 |
|
24 | | -const $sampled = sample({ |
25 | | - source: { ref: $combined }, |
26 | | - fn: (ref) => ref.ref.ref, |
27 | | -}); |
28 | | - |
29 | | -const getFixedDate = () => new Date(0); |
30 | | -const updateDate = createEvent<Date>(); |
31 | | -const $specialData = createStore(getFixedDate(), { |
32 | | - serialize: { |
33 | | - write: (_date) => ({ lol: "jsonified view" }), |
34 | | - read: (_json) => getFixedDate(), |
35 | | - }, |
36 | | -}).on($count, () => getFixedDate()); |
37 | | - |
38 | | -describe("getClientScope", () => { |
39 | | - test("should handle server values injection on the fly", async () => { |
40 | | - const serverScope = fork(); |
41 | | - |
42 | | - await allSettled(up, { scope: serverScope }); |
43 | | - await allSettled(up, { scope: serverScope }); |
44 | | - await allSettled(up, { scope: serverScope }); |
45 | | - |
46 | | - const serverValues = serialize(serverScope); |
47 | | - |
48 | | - const clientScopeOne = internalGetClientScope(); |
49 | | - |
50 | | - expect(clientScopeOne.getState($count)).toEqual(0); |
51 | | - expect(clientScopeOne.getState($derived)).toEqual({ ref: 0 }); |
52 | | - expect(clientScopeOne.getState($combined)).toEqual({ ref: 0 }); |
53 | | - expect(clientScopeOne.getState($nestedCombined)).toEqual({ |
54 | | - ref: { ref: 0 }, |
55 | | - }); |
56 | | - expect(clientScopeOne.getState($sampled)).toEqual(0); |
57 | | - expect(clientScopeOne.getState(longUpFx.pending)).toEqual(false); |
58 | | - expect(clientScopeOne.getState(longUpFx.inFlight)).toEqual(0); |
59 | | - expect(clientScopeOne.getState($specialData)).toEqual(getFixedDate()); |
60 | | - |
61 | | - const promise = allSettled(longUpFx, { scope: clientScopeOne }); |
62 | | - |
63 | | - expect(clientScopeOne.getState(longUpFx.inFlight)).toEqual(1); |
64 | | - |
65 | | - const clientScopeTwo = internalGetClientScope(serverValues); |
66 | | - |
67 | | - expect(clientScopeTwo.getState($count)).toEqual(3); |
68 | | - expect(clientScopeOne.getState($derived)).toEqual({ ref: 3 }); |
69 | | - expect(clientScopeOne.getState($combined)).toEqual({ ref: 3 }); |
70 | | - expect(clientScopeOne.getState($nestedCombined)).toEqual({ |
71 | | - ref: { ref: 3 }, |
72 | | - }); |
73 | | - expect(clientScopeOne.getState($sampled)).toEqual(3); |
74 | | - expect(clientScopeOne.getState(longUpFx.pending)).toEqual(true); |
75 | | - expect(clientScopeOne.getState(longUpFx.inFlight)).toEqual(1); |
76 | | - expect(clientScopeOne.getState($specialData)).toEqual(getFixedDate()); |
77 | | - |
78 | | - await promise; |
79 | | - |
80 | | - expect(clientScopeTwo.getState($count)).toEqual(4); |
81 | | - expect(clientScopeOne.getState($derived)).toEqual({ ref: 4 }); |
82 | | - expect(clientScopeOne.getState($combined)).toEqual({ ref: 4 }); |
83 | | - expect(clientScopeOne.getState($nestedCombined)).toEqual({ |
84 | | - ref: { ref: 4 }, |
85 | | - }); |
86 | | - expect(clientScopeOne.getState($sampled)).toEqual(4); |
87 | | - expect(clientScopeOne.getState(longUpFx.pending)).toEqual(false); |
88 | | - expect(clientScopeOne.getState(longUpFx.inFlight)).toEqual(0); |
89 | | - expect(clientScopeOne.getState($specialData)).toEqual(getFixedDate()); |
90 | | - }); |
91 | | - test("shallow navigation to same page", async () => { |
92 | | - const serverScope = fork(); |
93 | | - |
94 | | - await allSettled(up, { scope: serverScope }); |
95 | | - await allSettled(up, { scope: serverScope }); |
96 | | - await allSettled(up, { scope: serverScope }); |
97 | | - |
98 | | - const values = serialize(serverScope); |
99 | | - |
100 | | - const clientScopeOne = internalGetClientScope(values); |
101 | | - |
102 | | - expect(clientScopeOne.getState($count)).toEqual(3); |
103 | | - |
104 | | - await allSettled(up, { scope: clientScopeOne }); |
105 | | - |
106 | | - expect(clientScopeOne.getState($count)).toEqual(4); |
107 | | - |
108 | | - // This imitates shallow navigation to same page, e.g. with different query params |
109 | | - // |
110 | | - // Next.js will reuse the same pageProps instance in this case |
111 | | - // which will basically override current page state with initial one |
112 | | - // |
113 | | - // So we need to basically just ignore it, because |
114 | | - // we already have the latest state in the client scope |
115 | | - const clientScopeTwo = internalGetClientScope(values); |
116 | | - |
117 | | - expect(clientScopeTwo.getState($count)).toEqual(4); |
118 | | - }); |
119 | | -}); |
| 13 | + expect(scopeOne !== scopeTwo).toBe(true); |
| 14 | + }) |
| 15 | +}) |
0 commit comments