11import { act , renderHook } from '@testing-library/react' ;
22
3+ import { renderHookServer } from '@/tests' ;
4+
35import type { OrientationLockType } from './useOrientation' ;
46
57import { useOrientation } from './useOrientation' ;
68
7- // Create mocks for ScreenOrientation API
89interface MockScreenOrientation {
910 angle : number ;
1011 lock : ReturnType < typeof vi . fn > ;
@@ -22,32 +23,18 @@ const createMockScreenOrientation = (
2223 unlock : vi . fn ( )
2324} ) ;
2425
25- // Mock for window.screen.orientation
26- let mockOrientation : MockScreenOrientation ;
27-
2826beforeEach ( ( ) => {
29- // Reset mocks before each test
30- mockOrientation = createMockScreenOrientation ( ) ;
31-
32- // Create complete mock for window.screen object
3327 Object . defineProperty ( window , 'screen' , {
34- value : {
35- orientation : mockOrientation
36- } ,
28+ value : { orientation : createMockScreenOrientation ( ) } ,
3729 writable : true ,
3830 configurable : true
3931 } ) ;
40-
41- vi . clearAllMocks ( ) ;
4232} ) ;
4333
44- afterEach ( ( ) => {
45- // Clear all event listeners
46- window . removeEventListener ( 'orientationchange' , expect . any ( Function ) ) ;
47- } ) ;
34+ afterEach ( vi . clearAllMocks ) ;
4835
49- it ( 'Should return correct initial state when orientation API is supported ' , ( ) => {
50- const { result } = renderHook ( ( ) => useOrientation ( ) ) ;
36+ it ( 'Should use orientation' , ( ) => {
37+ const { result } = renderHook ( useOrientation ) ;
5138
5239 expect ( result . current . supported ) . toBe ( true ) ;
5340 expect ( result . current . value ) . toEqual ( {
@@ -58,15 +45,26 @@ it('Should return correct initial state when orientation API is supported', () =
5845 expect ( result . current . unlock ) . toBeTypeOf ( 'function' ) ;
5946} ) ;
6047
61- it ( 'Should return correct initial state when orientation API is not supported' , ( ) => {
62- // Remove orientation API support
48+ it ( 'Should use orientation on server side' , ( ) => {
49+ const { result } = renderHookServer ( useOrientation ) ;
50+
51+ expect ( result . current . supported ) . toBe ( false ) ;
52+ expect ( result . current . value ) . toEqual ( {
53+ angle : 0 ,
54+ orientationType : undefined
55+ } ) ;
56+ expect ( result . current . lock ) . toBeTypeOf ( 'function' ) ;
57+ expect ( result . current . unlock ) . toBeTypeOf ( 'function' ) ;
58+ } ) ;
59+
60+ it ( 'Should use orientation for unsupported' , ( ) => {
6361 Object . defineProperty ( window , 'screen' , {
6462 value : { } ,
6563 writable : true ,
6664 configurable : true
6765 } ) ;
6866
69- const { result } = renderHook ( ( ) => useOrientation ( ) ) ;
67+ const { result } = renderHook ( useOrientation ) ;
7068
7169 expect ( result . current . supported ) . toBe ( false ) ;
7270 expect ( result . current . value ) . toEqual ( {
@@ -78,10 +76,15 @@ it('Should return correct initial state when orientation API is not supported',
7876} ) ;
7977
8078it ( 'Should handle different initial orientation values' , ( ) => {
81- mockOrientation . angle = 90 ;
82- mockOrientation . type = 'landscape-primary' ;
79+ Object . defineProperty ( window , 'screen' , {
80+ value : {
81+ orientation : createMockScreenOrientation ( 90 , 'landscape-primary' )
82+ } ,
83+ writable : true ,
84+ configurable : true
85+ } ) ;
8386
84- const { result } = renderHook ( ( ) => useOrientation ( ) ) ;
87+ const { result } = renderHook ( useOrientation ) ;
8588
8689 expect ( result . current . value ) . toEqual ( {
8790 angle : 90 ,
@@ -90,188 +93,46 @@ it('Should handle different initial orientation values', () => {
9093} ) ;
9194
9295it ( 'Should update state when orientationchange event is fired' , ( ) => {
93- const { result } = renderHook ( ( ) => useOrientation ( ) ) ;
96+ const { result } = renderHook ( useOrientation ) ;
9497
95- // Initial state
9698 expect ( result . current . value ) . toEqual ( {
9799 angle : 0 ,
98100 orientationType : 'portrait-primary'
99101 } ) ;
100102
101- // Simulate orientation change
102- act ( ( ) => {
103- mockOrientation . angle = 90 ;
104- mockOrientation . type = 'landscape-primary' ;
105- window . dispatchEvent ( new Event ( 'orientationchange' ) ) ;
106- } ) ;
107-
108- expect ( result . current . value ) . toEqual ( {
109- angle : 90 ,
110- orientationType : 'landscape-primary'
111- } ) ;
112- } ) ;
113-
114- it ( 'Should handle multiple orientation changes' , ( ) => {
115- const { result } = renderHook ( ( ) => useOrientation ( ) ) ;
116-
117- // First change
118103 act ( ( ) => {
119- mockOrientation . angle = 90 ;
120- mockOrientation . type = 'landscape-primary' ;
104+ Object . defineProperty ( window . screen , 'orientation' , {
105+ value : createMockScreenOrientation ( 90 , 'landscape-primary' ) ,
106+ writable : true ,
107+ configurable : true
108+ } ) ;
121109 window . dispatchEvent ( new Event ( 'orientationchange' ) ) ;
122110 } ) ;
123111
124112 expect ( result . current . value ) . toEqual ( {
125113 angle : 90 ,
126114 orientationType : 'landscape-primary'
127115 } ) ;
128-
129- // Second change
130- act ( ( ) => {
131- mockOrientation . angle = 270 ;
132- mockOrientation . type = 'landscape-secondary' ;
133- window . dispatchEvent ( new Event ( 'orientationchange' ) ) ;
134- } ) ;
135-
136- expect ( result . current . value ) . toEqual ( {
137- angle : 270 ,
138- orientationType : 'landscape-secondary'
139- } ) ;
140- } ) ;
141-
142- it ( 'Should not add event listener when orientation API is not supported' , ( ) => {
143- const addEventListenerSpy = vi . spyOn ( window , 'addEventListener' ) ;
144-
145- // Remove orientation API support
146- Object . defineProperty ( window , 'screen' , {
147- value : { } ,
148- writable : true ,
149- configurable : true
150- } ) ;
151-
152- renderHook ( ( ) => useOrientation ( ) ) ;
153-
154- expect ( addEventListenerSpy ) . not . toHaveBeenCalledWith ( 'orientationchange' , expect . any ( Function ) ) ;
155116} ) ;
156117
157118it ( 'Should call lock function when lock method is called' , ( ) => {
158- const { result } = renderHook ( ( ) => useOrientation ( ) ) ;
119+ const { result } = renderHook ( useOrientation ) ;
159120
160- act ( ( ) => {
161- result . current . lock ( 'landscape-primary' ) ;
162- } ) ;
121+ act ( ( ) => result . current . lock ( 'landscape-primary' ) ) ;
163122
164- expect ( mockOrientation . lock ) . toHaveBeenCalledWith ( 'landscape-primary' ) ;
123+ expect ( window . screen . orientation . lock ) . toHaveBeenCalledWith ( 'landscape-primary' ) ;
165124} ) ;
166125
167126it ( 'Should call unlock function when unlock method is called' , ( ) => {
168- const { result } = renderHook ( ( ) => useOrientation ( ) ) ;
127+ const { result } = renderHook ( useOrientation ) ;
169128
170- act ( ( ) => {
171- result . current . unlock ( ) ;
172- } ) ;
129+ act ( result . current . unlock ) ;
173130
174- expect ( mockOrientation . unlock ) . toHaveBeenCalled ( ) ;
175- } ) ;
176-
177- it ( 'Should not call lock when orientation API is not supported' , ( ) => {
178- // Remove orientation API support
179- Object . defineProperty ( window , 'screen' , {
180- value : { } ,
181- writable : true ,
182- configurable : true
183- } ) ;
184-
185- const { result } = renderHook ( ( ) => useOrientation ( ) ) ;
186-
187- act ( ( ) => {
188- result . current . lock ( 'landscape-primary' ) ;
189- } ) ;
190-
191- // lock should not be called since API is not supported
192- expect ( mockOrientation . lock ) . not . toHaveBeenCalled ( ) ;
193- } ) ;
194-
195- it ( 'Should not call unlock when orientation API is not supported' , ( ) => {
196- // Remove orientation API support
197- Object . defineProperty ( window , 'screen' , {
198- value : { } ,
199- writable : true ,
200- configurable : true
201- } ) ;
202-
203- const { result } = renderHook ( ( ) => useOrientation ( ) ) ;
204-
205- act ( ( ) => {
206- result . current . unlock ( ) ;
207- } ) ;
208-
209- // unlock should not be called since API is not supported
210- expect ( mockOrientation . unlock ) . not . toHaveBeenCalled ( ) ;
211- } ) ;
212-
213- it ( 'Should not call lock when lock function is not available' , ( ) => {
214- // Create orientation without lock method
215- Object . defineProperty ( window , 'screen' , {
216- value : {
217- orientation : {
218- angle : 0 ,
219- type : 'portrait-primary'
220- // lock method is missing
221- }
222- } ,
223- writable : true ,
224- configurable : true
225- } ) ;
226-
227- const { result } = renderHook ( ( ) => useOrientation ( ) ) ;
228-
229- expect ( ( ) => {
230- act ( ( ) => {
231- result . current . lock ( 'landscape-primary' ) ;
232- } ) ;
233- } ) . not . toThrow ( ) ;
234-
235- expect ( result . current . supported ) . toBe ( true ) ;
236- } ) ;
237-
238- it ( 'Should not call unlock when unlock function is not available' , ( ) => {
239- // Create orientation without unlock method
240- Object . defineProperty ( window , 'screen' , {
241- value : {
242- orientation : {
243- angle : 0 ,
244- type : 'portrait-primary'
245- // unlock method is missing
246- }
247- } ,
248- writable : true ,
249- configurable : true
250- } ) ;
251-
252- const { result } = renderHook ( ( ) => useOrientation ( ) ) ;
253-
254- expect ( ( ) => {
255- act ( ( ) => {
256- result . current . unlock ( ) ;
257- } ) ;
258- } ) . not . toThrow ( ) ;
259-
260- expect ( result . current . supported ) . toBe ( true ) ;
261- } ) ;
262-
263- it ( 'Should clean up event listener on unmount' , ( ) => {
264- const removeEventListenerSpy = vi . spyOn ( window , 'removeEventListener' ) ;
265-
266- const { unmount } = renderHook ( ( ) => useOrientation ( ) ) ;
267-
268- unmount ( ) ;
269-
270- expect ( removeEventListenerSpy ) . toHaveBeenCalledWith ( 'orientationchange' , expect . any ( Function ) ) ;
131+ expect ( window . screen . orientation . unlock ) . toHaveBeenCalled ( ) ;
271132} ) ;
272133
273134it ( 'Should handle all orientation lock types' , ( ) => {
274- const { result } = renderHook ( ( ) => useOrientation ( ) ) ;
135+ const { result } = renderHook ( useOrientation ) ;
275136
276137 const orientationTypes : OrientationLockType [ ] = [
277138 'any' ,
@@ -285,12 +146,20 @@ it('Should handle all orientation lock types', () => {
285146 ] ;
286147
287148 orientationTypes . forEach ( ( orientation ) => {
288- act ( ( ) => {
289- result . current . lock ( orientation ) ;
290- } ) ;
149+ act ( ( ) => result . current . lock ( orientation ) ) ;
291150
292- expect ( mockOrientation . lock ) . toHaveBeenCalledWith ( orientation ) ;
151+ expect ( window . screen . orientation . lock ) . toHaveBeenCalledWith ( orientation ) ;
293152 } ) ;
294153
295- expect ( mockOrientation . lock ) . toHaveBeenCalledTimes ( orientationTypes . length ) ;
154+ expect ( window . screen . orientation . lock ) . toHaveBeenCalledTimes ( orientationTypes . length ) ;
155+ } ) ;
156+
157+ it ( 'Should cleanup on unmount' , ( ) => {
158+ const removeEventListenerSpy = vi . spyOn ( window , 'removeEventListener' ) ;
159+
160+ const { unmount } = renderHook ( useOrientation ) ;
161+
162+ unmount ( ) ;
163+
164+ expect ( removeEventListenerSpy ) . toHaveBeenCalledWith ( 'orientationchange' , expect . any ( Function ) ) ;
296165} ) ;
0 commit comments