11import { renderHook , act } from "@testing-library/react" ;
22import { describe , it , expect , vi } from "vitest" ;
3- import type { CollectionSnapshot , CollectionStateSynchronizer } from "@/types/collection" ;
3+ import type { CollectionSnapshot , CollectionStatePersistence } from "@/types/collection" ;
44import { useCollectionVariables } from "./use-collection-variables" ;
55
6- describe ( "useCollectionVariables with synchronizer" , ( ) => {
7- function createMockSynchronizer ( initial ?: CollectionSnapshot ) {
8- const subscribers : Array < ( snapshot : CollectionSnapshot | undefined ) => void > = [ ] ;
6+ describe ( "useCollectionVariables with persistence" , ( ) => {
7+ function createMockPersistence ( initial ?: CollectionSnapshot ) {
98 return {
10- subscribe : vi . fn ( ( onChange ) => {
11- subscribers . push ( onChange ) ;
12- // BehaviorSubject: emit immediately
13- onChange ( initial ) ;
14- return ( ) => {
15- const idx = subscribers . indexOf ( onChange ) ;
16- if ( idx >= 0 ) subscribers . splice ( idx , 1 ) ;
17- } ;
18- } ) ,
9+ read : vi . fn ( ( ) => initial ) ,
1910 write : vi . fn ( ) ,
20- // Test helper to simulate external change
21- emit ( snapshot : CollectionSnapshot | undefined ) {
22- for ( const cb of subscribers ) cb ( snapshot ) ;
23- } ,
24- } satisfies CollectionStateSynchronizer & {
25- emit : ( s : CollectionSnapshot | undefined ) => void ;
26- } ;
11+ } satisfies CollectionStatePersistence ;
2712 }
2813
29- describe ( "subscribe (initial hydration)" , ( ) => {
30- it ( "uses synchronizer initial state over params defaults" , ( ) => {
31- const synchronizer = createMockSynchronizer ( {
14+ describe ( "read (initial hydration)" , ( ) => {
15+ it ( "uses persistence initial state over params defaults" , ( ) => {
16+ const persistence = createMockPersistence ( {
3217 filters : [ { field : "status" , operator : "eq" , value : "ACTIVE" } ] ,
3318 sort : [ { field : "name" , direction : "Asc" } ] ,
3419 pageSize : 50 ,
@@ -37,28 +22,28 @@ describe("useCollectionVariables with synchronizer", () => {
3722 const { result } = renderHook ( ( ) =>
3823 useCollectionVariables ( {
3924 params : { pageSize : 20 } ,
40- synchronizer ,
25+ persistence ,
4126 } ) ,
4227 ) ;
4328
44- expect ( synchronizer . subscribe ) . toHaveBeenCalledOnce ( ) ;
29+ expect ( persistence . read ) . toHaveBeenCalledOnce ( ) ;
4530 expect ( result . current . control . filters ) . toEqual ( [
4631 { field : "status" , operator : "eq" , value : "ACTIVE" } ,
4732 ] ) ;
4833 expect ( result . current . control . sortStates ) . toEqual ( [ { field : "name" , direction : "Asc" } ] ) ;
4934 expect ( result . current . control . pageSize ) . toBe ( 50 ) ;
5035 } ) ;
5136
52- it ( "falls back to params when synchronizer emits undefined" , ( ) => {
53- const synchronizer = createMockSynchronizer ( undefined ) ;
37+ it ( "falls back to params when persistence returns undefined" , ( ) => {
38+ const persistence = createMockPersistence ( undefined ) ;
5439
5540 const { result } = renderHook ( ( ) =>
5641 useCollectionVariables ( {
5742 params : {
5843 pageSize : 30 ,
5944 initialSort : [ { field : "createdAt" , direction : "Desc" } ] ,
6045 } ,
61- synchronizer ,
46+ persistence ,
6247 } ) ,
6348 ) ;
6449
@@ -69,8 +54,8 @@ describe("useCollectionVariables with synchronizer", () => {
6954 expect ( result . current . control . filters ) . toEqual ( [ ] ) ;
7055 } ) ;
7156
72- it ( "partially overrides params (only pageSize from synchronizer )" , ( ) => {
73- const synchronizer = createMockSynchronizer ( {
57+ it ( "partially overrides params (only pageSize from persistence )" , ( ) => {
58+ const persistence = createMockPersistence ( {
7459 pageSize : 100 ,
7560 } ) ;
7661
@@ -80,73 +65,48 @@ describe("useCollectionVariables with synchronizer", () => {
8065 pageSize : 20 ,
8166 initialSort : [ { field : "name" , direction : "Asc" } ] ,
8267 } ,
83- synchronizer ,
68+ persistence ,
8469 } ) ,
8570 ) ;
8671
8772 expect ( result . current . control . pageSize ) . toBe ( 100 ) ;
88- // Sort remains from params since synchronizer didn't provide it
73+ // Sort remains from params since persistence didn't provide it
8974 expect ( result . current . control . sortStates ) . toEqual ( [ { field : "name" , direction : "Asc" } ] ) ;
9075 } ) ;
9176 } ) ;
9277
93- describe ( "subscribe (external changes)" , ( ) => {
94- it ( "updates state when synchronizer emits external change" , ( ) => {
95- const synchronizer = createMockSynchronizer ( undefined ) ;
96-
97- const { result } = renderHook ( ( ) =>
98- useCollectionVariables ( {
99- params : { pageSize : 20 } ,
100- synchronizer,
101- } ) ,
102- ) ;
103-
104- act ( ( ) => {
105- synchronizer . emit ( {
106- filters : [ { field : "name" , operator : "contains" , value : "test" } ] ,
107- pageSize : 50 ,
108- } ) ;
109- } ) ;
110-
111- expect ( result . current . control . filters ) . toEqual ( [
112- { field : "name" , operator : "contains" , value : "test" } ,
113- ] ) ;
114- expect ( result . current . control . pageSize ) . toBe ( 50 ) ;
115- } ) ;
116- } ) ;
117-
11878 describe ( "write (state persistence)" , ( ) => {
11979 it ( "does not call write on initial mount (skip first write)" , ( ) => {
120- const synchronizer = createMockSynchronizer ( {
80+ const persistence = createMockPersistence ( {
12181 filters : [ { field : "status" , operator : "eq" , value : "ACTIVE" } ] ,
12282 pageSize : 50 ,
12383 } ) ;
12484
12585 renderHook ( ( ) =>
12686 useCollectionVariables ( {
12787 params : { pageSize : 20 } ,
128- synchronizer ,
88+ persistence ,
12989 } ) ,
13090 ) ;
13191
132- expect ( synchronizer . write ) . not . toHaveBeenCalled ( ) ;
92+ expect ( persistence . write ) . not . toHaveBeenCalled ( ) ;
13393 } ) ;
13494
13595 it ( "calls write on filter change" , ( ) => {
136- const synchronizer = createMockSynchronizer ( undefined ) ;
96+ const persistence = createMockPersistence ( undefined ) ;
13797
13898 const { result } = renderHook ( ( ) =>
13999 useCollectionVariables ( {
140100 params : { pageSize : 20 } ,
141- synchronizer ,
101+ persistence ,
142102 } ) ,
143103 ) ;
144104
145105 act ( ( ) => {
146106 result . current . control . addFilter ( "status" , "eq" , "ACTIVE" ) ;
147107 } ) ;
148108
149- expect ( synchronizer . write ) . toHaveBeenCalledWith (
109+ expect ( persistence . write ) . toHaveBeenCalledWith (
150110 expect . objectContaining ( {
151111 filters : [ { field : "status" , operator : "eq" , value : "ACTIVE" } ] ,
152112 pageSize : 20 ,
@@ -155,20 +115,20 @@ describe("useCollectionVariables with synchronizer", () => {
155115 } ) ;
156116
157117 it ( "calls write on sort change" , ( ) => {
158- const synchronizer = createMockSynchronizer ( undefined ) ;
118+ const persistence = createMockPersistence ( undefined ) ;
159119
160120 const { result } = renderHook ( ( ) =>
161121 useCollectionVariables ( {
162122 params : { pageSize : 20 } ,
163- synchronizer ,
123+ persistence ,
164124 } ) ,
165125 ) ;
166126
167127 act ( ( ) => {
168128 result . current . control . setSort ( "name" , "Desc" ) ;
169129 } ) ;
170130
171- expect ( synchronizer . write ) . toHaveBeenCalledWith (
131+ expect ( persistence . write ) . toHaveBeenCalledWith (
172132 expect . objectContaining ( {
173133 sort : [ { field : "name" , direction : "Desc" } ] ,
174134 pageSize : 20 ,
@@ -177,27 +137,27 @@ describe("useCollectionVariables with synchronizer", () => {
177137 } ) ;
178138
179139 it ( "calls write on pageSize change" , ( ) => {
180- const synchronizer = createMockSynchronizer ( undefined ) ;
140+ const persistence = createMockPersistence ( undefined ) ;
181141
182142 const { result } = renderHook ( ( ) =>
183143 useCollectionVariables ( {
184144 params : { pageSize : 20 } ,
185- synchronizer ,
145+ persistence ,
186146 } ) ,
187147 ) ;
188148
189149 act ( ( ) => {
190150 result . current . control . setPageSize ( 50 ) ;
191151 } ) ;
192152
193- expect ( synchronizer . write ) . toHaveBeenCalledWith (
153+ expect ( persistence . write ) . toHaveBeenCalledWith (
194154 expect . objectContaining ( {
195155 pageSize : 50 ,
196156 } ) ,
197157 ) ;
198158 } ) ;
199159
200- it ( "does not crash when no synchronizer is provided" , ( ) => {
160+ it ( "does not crash when no persistence is provided" , ( ) => {
201161 const { result } = renderHook ( ( ) => useCollectionVariables ( { params : { pageSize : 20 } } ) ) ;
202162
203163 act ( ( ) => {
0 commit comments