@@ -31,18 +31,32 @@ type NamespaceLocale = {
3131 languages : 'Languages'
3232}
3333
34+ const defaultSupportedLocales = [ 'en' , 'fr' , 'es' ]
35+
3436const wrapper =
3537 ( {
36- loadDateLocale = async ( locale : string ) =>
37- import ( `date-fns/locale/${ locale } /index` ) ,
38+ loadDateLocale = async ( locale : string ) => {
39+ if ( locale === 'en' ) {
40+ return ( await import ( 'date-fns/locale/en-GB' ) ) . enGB
41+ }
42+ if ( locale === 'fr' ) {
43+ return ( await import ( 'date-fns/locale/fr' ) ) . fr
44+ }
45+
46+ if ( locale === 'es' ) {
47+ return ( await import ( 'date-fns/locale/es' ) ) . es
48+ }
49+
50+ return ( await import ( `date-fns/locale/en-GB` ) ) . enGB
51+ } ,
3852 defaultLoad = async ( { locale } : { locale : string } ) =>
3953 import ( `./locales/${ locale } .json` ) ,
4054 defaultLocale = 'en' ,
4155 defaultTranslations = { } ,
4256 enableDebugKey = false ,
4357 enableDefaultLocale = false ,
4458 localeItemStorage = LOCALE_ITEM_STORAGE ,
45- supportedLocales = [ 'en' , 'fr' , 'es' ] ,
59+ supportedLocales = defaultSupportedLocales ,
4660 } = { } ) =>
4761 ( { children } : { children : ReactNode } ) => (
4862 < I18n
@@ -126,16 +140,16 @@ describe('i18n hook', () => {
126140 expect ( result . current . t ( 'title' ) ) . toEqual ( en . title )
127141 } )
128142
129- act ( ( ) => {
130- result . current . switchLocale ( 'fr' )
143+ await act ( async ( ) => {
144+ await result . current . switchLocale ( 'fr' )
131145 } )
132146
133147 await waitFor ( ( ) => {
134148 expect ( result . current . t ( 'title' ) ) . toEqual ( fr . title )
135149 } )
136150
137- act ( ( ) => {
138- result . current . switchLocale ( 'es' )
151+ await act ( async ( ) => {
152+ await result . current . switchLocale ( 'es' )
139153 } )
140154
141155 await waitFor ( ( ) => {
@@ -176,8 +190,8 @@ describe('i18n hook', () => {
176190 expect ( result . current . t ( 'lastName' ) ) . toEqual ( 'Last Name' )
177191 expect ( result . current . t ( 'languages' ) ) . toEqual ( 'Languages' )
178192
179- act ( ( ) => {
180- result . current . switchLocale ( 'fr' )
193+ await act ( async ( ) => {
194+ await result . current . switchLocale ( 'fr' )
181195 } )
182196
183197 await waitFor ( ( ) => {
@@ -221,8 +235,8 @@ describe('i18n hook', () => {
221235
222236 // current local will be 'en' based on navigator
223237 // await load of locales
224- act ( ( ) => {
225- result . current . switchLocale ( 'fr' )
238+ await act ( async ( ) => {
239+ await result . current . switchLocale ( 'fr' )
226240 } )
227241
228242 await waitFor ( ( ) => {
@@ -264,11 +278,13 @@ describe('i18n hook', () => {
264278 } as unknown as Navigator )
265279 const mockGetItem = jest . fn ( ) . mockImplementation ( ( ) => 'en' )
266280 const mockSetItem = jest . fn ( )
281+ const mockRemoveItem = jest . fn ( )
267282 const localStorageMock = jest
268283 . spyOn ( global , 'localStorage' , 'get' )
269284 . mockReturnValue ( {
270285 getItem : mockGetItem ,
271286 setItem : mockSetItem ,
287+ removeItem : mockRemoveItem ,
272288 clear : jest . fn ( ) ,
273289 } as unknown as Storage )
274290
@@ -281,7 +297,38 @@ describe('i18n hook', () => {
281297
282298 await waitFor ( ( ) => {
283299 expect ( result . current . currentLocale ) . toEqual ( 'en' )
284- expect ( mockGetItem ) . toHaveBeenCalledTimes ( 2 )
300+ expect ( mockGetItem ) . toHaveBeenCalledTimes ( 1 )
301+ expect ( mockGetItem ) . toHaveBeenCalledWith ( LOCALE_ITEM_STORAGE )
302+ } )
303+ localStorageMock . mockRestore ( )
304+ } )
305+
306+ it ( 'should not set current locale from localStorage when this value is not supported' , async ( ) => {
307+ jest . spyOn ( global , 'navigator' , 'get' ) . mockReturnValueOnce ( {
308+ languages : [ 'bz' ] ,
309+ } as unknown as Navigator )
310+ const mockGetItem = jest . fn ( ) . mockImplementation ( ( ) => 're' )
311+ const mockSetItem = jest . fn ( )
312+ const mockRemoveItem = jest . fn ( )
313+ const localStorageMock = jest
314+ . spyOn ( global , 'localStorage' , 'get' )
315+ . mockReturnValue ( {
316+ getItem : mockGetItem ,
317+ setItem : mockSetItem ,
318+ removeItem : mockRemoveItem ,
319+ clear : jest . fn ( ) ,
320+ } as unknown as Storage )
321+
322+ const { result } = renderHook ( ( ) => useI18n ( ) , {
323+ wrapper : wrapper ( {
324+ defaultLocale : 'en' ,
325+ supportedLocales : [ 'en' ] ,
326+ } ) ,
327+ } )
328+
329+ await waitFor ( ( ) => {
330+ expect ( result . current . currentLocale ) . toEqual ( 'en' )
331+ expect ( mockGetItem ) . toHaveBeenCalledTimes ( 1 )
285332 expect ( mockGetItem ) . toHaveBeenCalledWith ( LOCALE_ITEM_STORAGE )
286333 } )
287334 localStorageMock . mockRestore ( )
@@ -293,11 +340,13 @@ describe('i18n hook', () => {
293340 } as unknown as Navigator )
294341 const mockGetItem = jest . fn ( )
295342 const mockSetItem = jest . fn ( )
343+ const mockRemoveItem = jest . fn ( )
296344 const localStorageMock = jest
297345 . spyOn ( global , 'localStorage' , 'get' )
298346 . mockReturnValueOnce ( {
299347 getItem : mockGetItem ,
300348 setItem : mockSetItem ,
349+ removeItem : mockRemoveItem ,
301350 clear : jest . fn ( ) ,
302351 } as unknown as Storage )
303352
@@ -320,11 +369,13 @@ describe('i18n hook', () => {
320369 } as unknown as Navigator )
321370 const mockGetItem = jest . fn ( )
322371 const mockSetItem = jest . fn ( )
372+ const mockRemoveItem = jest . fn ( )
323373 const localStorageMock = jest
324374 . spyOn ( global , 'localStorage' , 'get' )
325375 . mockReturnValueOnce ( {
326376 getItem : mockGetItem ,
327377 setItem : mockSetItem ,
378+ removeItem : mockRemoveItem ,
328379 clear : jest . fn ( ) ,
329380 } as unknown as Storage )
330381
@@ -350,28 +401,28 @@ describe('i18n hook', () => {
350401 } ) ,
351402 } )
352403 expect ( result . current . currentLocale ) . toEqual ( 'en' )
353- expect ( localStorage . getItem ( LOCALE_ITEM_STORAGE ) ) . toBe ( null )
404+ expect ( localStorage . getItem ( LOCALE_ITEM_STORAGE ) ) . toBe ( 'en' )
354405
355- act ( ( ) => {
356- result . current . switchLocale ( 'fr' )
406+ await act ( async ( ) => {
407+ await result . current . switchLocale ( 'fr' )
357408 } )
358409
359410 await waitFor ( ( ) => {
360411 expect ( result . current . currentLocale ) . toEqual ( 'fr' )
361412 } )
362413 expect ( localStorage . getItem ( LOCALE_ITEM_STORAGE ) ) . toBe ( 'fr' )
363414
364- act ( ( ) => {
365- result . current . switchLocale ( 'es' )
415+ await act ( async ( ) => {
416+ await result . current . switchLocale ( 'es' )
366417 } )
367418
368419 await waitFor ( ( ) => {
369420 expect ( result . current . currentLocale ) . toEqual ( 'es' )
370421 } )
371422 expect ( localStorage . getItem ( LOCALE_ITEM_STORAGE ) ) . toBe ( 'es' )
372423
373- act ( ( ) => {
374- result . current . switchLocale ( 'test' )
424+ await act ( async ( ) => {
425+ await result . current . switchLocale ( 'test' )
375426 } )
376427
377428 await waitFor ( ( ) => {
@@ -441,8 +492,8 @@ describe('i18n hook', () => {
441492 } ) ,
442493 ) . toEqual ( '$2.00' )
443494
444- act ( ( ) => {
445- result . current . switchLocale ( 'fr' )
495+ await act ( async ( ) => {
496+ await result . current . switchLocale ( 'fr' )
446497 } )
447498
448499 // https://stackoverflow.com/questions/58769806/identical-strings-not-matching-in-jest
@@ -491,8 +542,8 @@ describe('i18n hook', () => {
491542 } ) ,
492543 ) . toEqual ( 'Motorcycle Bus Car' )
493544
494- act ( ( ) => {
495- result . current . switchLocale ( 'fr' )
545+ await act ( async ( ) => {
546+ await result . current . switchLocale ( 'fr' )
496547 } )
497548
498549 await waitFor ( ( ) => {
@@ -565,8 +616,8 @@ describe('i18n hook', () => {
565616 } ) ,
566617 ) . toEqual ( '12/17/1995' )
567618
568- act ( ( ) => {
569- result . current . switchLocale ( 'fr' )
619+ await act ( async ( ) => {
620+ await result . current . switchLocale ( 'fr' )
570621 } )
571622
572623 await waitFor ( ( ) => {
@@ -602,11 +653,12 @@ describe('i18n hook', () => {
602653
603654 expect ( result . current . relativeTime ( date ) ) . toEqual ( 'over 20 years ago' )
604655
605- act ( ( ) => {
606- result . current . switchLocale ( 'fr' )
656+ await act ( async ( ) => {
657+ await result . current . switchLocale ( 'fr' )
607658 } )
608659
609660 await waitFor ( ( ) => {
661+ expect ( result . current . dateFnsLocale ?. code ) . toBe ( 'fr' )
610662 expect ( result . current . relativeTime ( date ) ) . toEqual ( 'il y a plus de 20 ans' )
611663 } )
612664 } )
@@ -621,8 +673,8 @@ describe('i18n hook', () => {
621673 const date = new Date ( 'September 13, 2011 15:15:00' )
622674
623675 expect ( result . current . relativeTimeStrict ( date ) ) . toEqual ( '3499 days ago' )
624- act ( ( ) => {
625- result . current . switchLocale ( 'fr' )
676+ await act ( async ( ) => {
677+ await result . current . switchLocale ( 'fr' )
626678 } )
627679
628680 await waitFor ( ( ) => {
@@ -642,8 +694,8 @@ describe('i18n hook', () => {
642694 expect (
643695 result . current . formatUnit ( 12 , { short : false , unit : 'byte' } ) ,
644696 ) . toEqual ( '12 bytes' )
645- act ( ( ) => {
646- result . current . switchLocale ( 'fr' )
697+ await act ( async ( ) => {
698+ await result . current . switchLocale ( 'fr' )
647699 } )
648700
649701 await waitFor ( ( ) => {
@@ -663,8 +715,8 @@ describe('i18n hook', () => {
663715 expect (
664716 result . current . formatDate ( new Date ( 2020 , 1 , 13 , 16 , 28 ) , 'numericHour' ) ,
665717 ) . toEqual ( '2020-02-13 4:28 PM' )
666- act ( ( ) => {
667- result . current . switchLocale ( 'fr' )
718+ await act ( async ( ) => {
719+ await result . current . switchLocale ( 'fr' )
668720 } )
669721
670722 await waitFor ( ( ) => {
@@ -674,17 +726,55 @@ describe('i18n hook', () => {
674726 } )
675727 } )
676728
677- it ( 'should load default datefns locales' , async ( ) => {
678- const { result } = renderHook ( ( ) => useI18n ( ) , {
679- wrapper : wrapper ( {
680- defaultLocale : 'test' ,
681- supportedLocales : [ 'test' ] ,
682- } ) ,
729+ describe ( 'date-fns' , ( ) => {
730+ it ( 'should load default date-fns locales' , async ( ) => {
731+ const { result } = renderHook ( ( ) => useI18n ( ) , {
732+ wrapper : wrapper ( {
733+ defaultLocale : 'test' ,
734+ supportedLocales : [ 'test' ] ,
735+ } ) ,
736+ } )
737+
738+ await waitFor ( ( ) => {
739+ expect ( result . current . dateFnsLocale ?. code ) . toEqual ( 'en-GB' )
740+ } )
683741 } )
684- expect ( result . current . dateFnsLocale ) . toBe ( undefined )
685742
686- await waitFor ( ( ) => {
687- expect ( result . current . dateFnsLocale ?. code ) . toEqual ( 'en-GB' )
743+ it ( 'should load correct date-fns based on current local' , async ( ) => {
744+ jest . spyOn ( global , 'navigator' , 'get' ) . mockReturnValueOnce ( {
745+ languages : [ 'fr' ] ,
746+ } as unknown as Navigator )
747+ const mockGetItem = jest . fn ( ) . mockImplementation ( ( ) => 'fr' )
748+ const mockSetItem = jest . fn ( )
749+ const mockRemoveItem = jest . fn ( )
750+ const localStorageMock = jest
751+ . spyOn ( global , 'localStorage' , 'get' )
752+ . mockReturnValue ( {
753+ getItem : mockGetItem ,
754+ setItem : mockSetItem ,
755+ removeItem : mockRemoveItem ,
756+ clear : jest . fn ( ) ,
757+ } as unknown as Storage )
758+
759+ const { result } = renderHook ( ( ) => useI18n ( ) , {
760+ wrapper : wrapper ( {
761+ defaultLocale : 'es' ,
762+ supportedLocales : [ 'en' , 'fr' , 'es' ] ,
763+ } ) ,
764+ } )
765+
766+ await waitFor ( ( ) => {
767+ expect ( result . current . currentLocale ) . toEqual ( 'fr' )
768+ expect ( mockGetItem ) . toHaveBeenCalledTimes ( 2 )
769+ expect ( mockGetItem ) . toHaveBeenCalledWith ( LOCALE_ITEM_STORAGE )
770+ } )
771+
772+ await waitFor ( ( ) => {
773+ expect ( result . current . dateFnsLocale ?. code ) . toEqual ( 'fr' )
774+ expect ( result . current . dateFnsLocale ) . toMatchObject ( { code : 'fr' } )
775+ } )
776+
777+ localStorageMock . mockRestore ( )
688778 } )
689779 } )
690780
0 commit comments