@@ -22,162 +22,116 @@ afterAll(() => {
2222 document . documentElement . removeAttribute ( 'data-theme' )
2323} )
2424
25- describe . each ( [
26- [ false , 'server' ] ,
27- [ true , 'browser' ] ,
28- ] ) ( 'themeStore %s' , ( _isBrowser , _title ) => {
29- const originalWindow = globalThis . window
25+ describe ( 'themeStore' , ( ) => {
26+ // Loader.registry.delete(require.resolve('../theme-store'))
3027 beforeEach ( ( ) => {
31- // Remove window to simulate SSR
32- if ( ! _isBrowser ) {
33- // @ts -expect-error - Temporarily remove window for SSR test
34- delete globalThis . window
35- } else {
36- document . documentElement . removeAttribute ( 'data-theme' )
37- }
28+ document . documentElement . removeAttribute ( 'data-theme' )
3829 } )
3930
4031 afterEach ( ( ) => {
41- if ( _isBrowser ) {
42- document . documentElement . removeAttribute ( 'data-theme' )
43- }
44- globalThis . window = originalWindow
32+ document . documentElement . removeAttribute ( 'data-theme' )
4533 } )
46- if ( _isBrowser ) {
47- it ( 'should return themeStore object for browser' , ( ) => {
48- // const modulePath = require.resolve('../theme-store')
49- // delete require.cache[modulePath]
50- const themeStore = createThemeStore ( )
51- expect ( themeStore ) . toBeDefined ( )
52- expect ( themeStore . get ) . toEqual ( expect . any ( Function ) )
53- expect ( themeStore . set ) . toEqual ( expect . any ( Function ) )
54- expect ( themeStore . subscribe ) . toEqual ( expect . any ( Function ) )
55- expect ( themeStore . get ( ) ) . toBeNull ( )
56- expect ( themeStore . set ( 'dark' as any ) ) . toBeUndefined ( )
57- // subscribe returns an unsubscribe function, which returns boolean when called
58- const unsubscribe = themeStore . subscribe ( ( ) => { } )
59- expect ( typeof unsubscribe ) . toBe ( 'function' )
60- themeStore . subscribe ( ( ) => { } )
61- expect ( themeStore . set ( 'dark' as any ) ) . toBeUndefined ( )
62- } )
63-
64- it ( 'should call subscriber when theme changes via set' , ( ) => {
65- // const modulePath = require.resolve('../theme-store')
66- // delete require.cache[modulePath]
67- const themeStore = createThemeStore ( )
68- const callback = mock ( )
69-
70- themeStore . subscribe ( callback )
71-
72- // First call is from subscribe itself (reads current data-theme)
73- expect ( callback ) . toHaveBeenCalledTimes ( 1 )
74-
75- themeStore . set ( 'light' as any )
76- expect ( callback ) . toHaveBeenCalledTimes ( 2 )
77- expect ( callback ) . toHaveBeenLastCalledWith ( 'light' )
78- expect ( themeStore . get ( ) ) . toBe ( 'light' as any )
79- } )
80-
81- it ( 'should unsubscribe correctly' , ( ) => {
82- // const modulePath = require.resolve('../theme-store')
83- // delete require.cache[modulePath]
84- const themeStore = createThemeStore ( )
85- const callback = mock ( )
86-
87- const unsubscribe = themeStore . subscribe ( callback )
88- expect ( callback ) . toHaveBeenCalledTimes ( 1 )
89-
90- // Unsubscribe
91- const result = unsubscribe ( )
92- expect ( result ) . toBe ( true as any )
93-
94- // Should not be called after unsubscribe
95- themeStore . set ( 'dark' as any )
96- expect ( callback ) . toHaveBeenCalledTimes ( 1 )
97- } )
98-
99- it ( 'should read initial theme from data-theme attribute' , ( ) => {
100- document . documentElement . setAttribute ( 'data-theme' , 'dark' )
101-
102- // const modulePath = require.resolve('../theme-store')
103- // delete require.cache[modulePath]
104- const themeStore = createThemeStore ( )
105- const callback = mock ( )
106-
107- themeStore . subscribe ( callback )
108-
109- // Should be called with 'dark' from the attribute
110- expect ( callback ) . toHaveBeenCalledWith ( 'dark' )
111- } )
112-
113- it ( 'should update theme when data-theme attribute changes via MutationObserver' , async ( ) => {
114- // const modulePath = require.resolve('../theme-store')
115- // delete require.cache[modulePath]
116- const themeStore = createThemeStore ( )
117- const callback = mock ( )
118-
119- themeStore . subscribe ( callback )
120- expect ( callback ) . toHaveBeenCalledTimes ( 1 )
121-
122- // Change the attribute - MutationObserver should trigger
123- document . documentElement . setAttribute ( 'data-theme' , 'dark' )
124-
125- // Wait for MutationObserver to fire (it's async)
126- await new Promise ( ( resolve ) => setTimeout ( resolve , 10 ) )
127-
128- expect ( callback ) . toHaveBeenCalledWith ( 'dark' )
129- expect ( themeStore . get ( ) ) . toBe ( 'dark' as any )
130- } )
131-
132- it ( 'should handle multiple subscribers' , async ( ) => {
133- // const modulePath = require.resolve('../theme-store')
134- // delete require.cache[modulePath]
135- const themeStore = createThemeStore ( )
136- const callback1 = mock ( )
137- const callback2 = mock ( )
138-
139- themeStore . subscribe ( callback1 )
140- themeStore . subscribe ( callback2 )
141-
142- themeStore . set ( 'light' as any )
143-
144- expect ( callback1 ) . toHaveBeenLastCalledWith ( 'light' )
145- expect ( callback2 ) . toHaveBeenLastCalledWith ( 'light' )
146- } )
147-
148- it ( 'should filter mutations by type and target' , async ( ) => {
149- // const modulePath = require.resolve('../theme-store')
150- // delete require.cache[modulePath]
151- const themeStore = createThemeStore ( )
152- const callback = mock ( )
153-
154- themeStore . subscribe ( callback )
155-
156- // Change data-theme attribute (should trigger)
157- document . documentElement . setAttribute ( 'data-theme' , 'system' )
158-
159- await new Promise ( ( resolve ) => setTimeout ( resolve , 10 ) )
160-
161- expect ( themeStore . get ( ) ) . toBe ( 'system' as any )
162- } )
163- } else {
164- it ( 'should return themeStore object for server' , async ( ) => {
165- const { createThemeStore : createThemeStoreFn } = require . cache [
166- require . resolve ( '../theme-store' )
167- ] ?. exports as unknown as { createThemeStore : typeof createThemeStore }
168- const themeStore = createThemeStoreFn ( )
16934
170- // Test SSR store behavior
171- expect ( themeStore ) . toBeDefined ( )
172- expect ( themeStore . get ( ) ) . toBeNull ( )
173- expect ( themeStore . set ( 'dark' as any ) ) . toBeUndefined ( )
174-
175- const unsubscribe = themeStore . subscribe ( ( ) => { } )
176- expect ( typeof unsubscribe ) . toBe ( 'function' )
177-
178- // The unsubscribe should return a no-op function
179- const innerUnsubscribe = unsubscribe ( )
180- expect ( innerUnsubscribe ) . toBeUndefined ( )
181- } )
182- }
35+ it ( 'should return themeStore object for browser' , ( ) => {
36+ const themeStore = createThemeStore ( )
37+ expect ( themeStore ) . toBeDefined ( )
38+ expect ( themeStore . get ) . toEqual ( expect . any ( Function ) )
39+ expect ( themeStore . set ) . toEqual ( expect . any ( Function ) )
40+ expect ( themeStore . subscribe ) . toEqual ( expect . any ( Function ) )
41+ expect ( themeStore . get ( ) ) . toBeNull ( )
42+ expect ( themeStore . set ( 'dark' as any ) ) . toBeUndefined ( )
43+ // subscribe returns an unsubscribe function, which returns boolean when called
44+ const unsubscribe = themeStore . subscribe ( ( ) => { } )
45+ expect ( typeof unsubscribe ) . toBe ( 'function' )
46+ themeStore . subscribe ( ( ) => { } )
47+ expect ( themeStore . set ( 'dark' as any ) ) . toBeUndefined ( )
48+ } )
49+
50+ it ( 'should call subscriber when theme changes via set' , ( ) => {
51+ const themeStore = createThemeStore ( )
52+ const callback = mock ( )
53+
54+ themeStore . subscribe ( callback )
55+
56+ // First call is from subscribe itself (reads current data-theme)
57+ expect ( callback ) . toHaveBeenCalledTimes ( 1 )
58+
59+ themeStore . set ( 'light' as any )
60+ expect ( callback ) . toHaveBeenCalledTimes ( 2 )
61+ expect ( callback ) . toHaveBeenLastCalledWith ( 'light' )
62+ expect ( themeStore . get ( ) ) . toBe ( 'light' as any )
63+ } )
64+
65+ it ( 'should unsubscribe correctly' , ( ) => {
66+ const themeStore = createThemeStore ( )
67+ const callback = mock ( )
68+
69+ const unsubscribe = themeStore . subscribe ( callback )
70+ expect ( callback ) . toHaveBeenCalledTimes ( 1 )
71+
72+ // Unsubscribe
73+ const result = unsubscribe ( )
74+ expect ( result ) . toBe ( true as any )
75+
76+ // Should not be called after unsubscribe
77+ themeStore . set ( 'dark' as any )
78+ expect ( callback ) . toHaveBeenCalledTimes ( 1 )
79+ } )
80+
81+ it ( 'should read initial theme from data-theme attribute' , ( ) => {
82+ document . documentElement . setAttribute ( 'data-theme' , 'dark' )
83+
84+ const themeStore = createThemeStore ( )
85+ const callback = mock ( )
86+
87+ themeStore . subscribe ( callback )
88+
89+ // Should be called with 'dark' from the attribute
90+ expect ( callback ) . toHaveBeenCalledWith ( 'dark' )
91+ } )
92+
93+ it ( 'should update theme when data-theme attribute changes via MutationObserver' , async ( ) => {
94+ const themeStore = createThemeStore ( )
95+ const callback = mock ( )
96+
97+ themeStore . subscribe ( callback )
98+ expect ( callback ) . toHaveBeenCalledTimes ( 1 )
99+
100+ // Change the attribute - MutationObserver should trigger
101+ document . documentElement . setAttribute ( 'data-theme' , 'dark' )
102+
103+ // Wait for MutationObserver to fire (it's async)
104+ await new Promise ( ( resolve ) => setTimeout ( resolve , 10 ) )
105+
106+ expect ( callback ) . toHaveBeenCalledWith ( 'dark' )
107+ expect ( themeStore . get ( ) ) . toBe ( 'dark' as any )
108+ } )
109+
110+ it ( 'should handle multiple subscribers' , ( ) => {
111+ const themeStore = createThemeStore ( )
112+ const callback1 = mock ( )
113+ const callback2 = mock ( )
114+
115+ themeStore . subscribe ( callback1 )
116+ themeStore . subscribe ( callback2 )
117+
118+ themeStore . set ( 'light' as any )
119+
120+ expect ( callback1 ) . toHaveBeenLastCalledWith ( 'light' )
121+ expect ( callback2 ) . toHaveBeenLastCalledWith ( 'light' )
122+ } )
123+
124+ it ( 'should filter mutations by type and target' , async ( ) => {
125+ const themeStore = createThemeStore ( )
126+ const callback = mock ( )
127+
128+ themeStore . subscribe ( callback )
129+
130+ // Change data-theme attribute (should trigger)
131+ document . documentElement . setAttribute ( 'data-theme' , 'system' )
132+
133+ await new Promise ( ( resolve ) => setTimeout ( resolve , 10 ) )
134+
135+ expect ( themeStore . get ( ) ) . toBe ( 'system' as any )
136+ } )
183137} )
0 commit comments