22 * @jest -environment jsdom
33 */
44
5+ const {
6+ loadTranslations,
7+ getNestedProperty,
8+ getBrowserLanguage,
9+ getCurrentLanguage,
10+ updateDocumentMeta,
11+ updateTranslations,
12+ setLanguage
13+ } = require ( "./translations" ) ;
14+
515global . fetch = jest . fn ( ) ;
616console . error = jest . fn ( ) ;
717
818describe ( "Translations Module" , ( ) => {
919 beforeEach ( ( ) => {
1020 jest . clearAllMocks ( ) ;
1121 localStorage . clear ( ) ;
22+ document . body . innerHTML = "" ;
23+ document . head . innerHTML =
24+ '<title>Test</title><meta name="description" content="Test"><meta property="og:title" content="Test"><meta property="og:description" content="Test">' ;
1225 } ) ;
1326
1427 describe ( "Core Helper Functions" , ( ) => {
1528 test ( "getNestedProperty - should handle nested translation keys" , ( ) => {
16- const getNestedProperty = ( obj , path ) =>
17- path . split ( "." ) . reduce ( ( current , key ) => current ?. [ key ] , obj ) ;
18-
1929 const translations = { user : { profile : { name : "Jane" } } } ;
20-
2130 expect ( getNestedProperty ( translations , "user.profile.name" ) ) . toBe ( "Jane" ) ;
2231 expect ( getNestedProperty ( translations , "missing.key" ) ) . toBeUndefined ( ) ;
2332 } ) ;
2433
2534 test ( "getBrowserLanguage - should return supported language or default to English" , ( ) => {
26- const getBrowserLanguage = ( ) => {
27- const browserLang = navigator . language . split ( "-" ) [ 0 ] ;
28- const supportedLangs = [ "en" , "es" , "fr" , "pt" ] ;
29- return supportedLangs . includes ( browserLang ) ? browserLang : "en" ;
30- } ;
31-
3235 Object . defineProperty ( navigator , "language" , { value : "es-ES" , configurable : true } ) ;
3336 expect ( getBrowserLanguage ( ) ) . toBe ( "es" ) ;
3437
@@ -40,73 +43,86 @@ describe("Translations Module", () => {
4043 describe ( "Translation Loading" , ( ) => {
4144 test ( "should successfully fetch translations" , async ( ) => {
4245 const mockData = { title : "Test Title" , role : "Developer" } ;
43- global . fetch . mockResolvedValueOnce ( {
44- ok : true ,
45- json : async ( ) => mockData
46- } ) ;
46+ global . fetch . mockResolvedValueOnce ( { ok : true , json : async ( ) => mockData } ) ;
4747
48- const response = await fetch ( "./locales/en.json" ) ;
49- const data = await response . json ( ) ;
48+ const data = await loadTranslations ( "en" ) ;
5049
50+ expect ( fetch ) . toHaveBeenCalledWith ( "./locales/en.json" ) ;
5151 expect ( data ) . toEqual ( mockData ) ;
5252 } ) ;
5353
5454 test ( "should handle fetch errors gracefully" , async ( ) => {
5555 global . fetch . mockRejectedValueOnce ( new Error ( "Network error" ) ) ;
56+ global . fetch . mockResolvedValueOnce ( {
57+ ok : true ,
58+ json : async ( ) => ( { title : "English" } )
59+ } ) ;
60+
61+ const data = await loadTranslations ( "fr" ) ;
5662
57- try {
58- await fetch ( "./locales/es.json" ) ;
59- } catch ( error ) {
60- expect ( error . message ) . toBe ( "Network error" ) ;
61- }
63+ expect ( console . error ) . toHaveBeenCalled ( ) ;
64+ expect ( data ) . toEqual ( { title : "English" } ) ;
6265 } ) ;
6366 } ) ;
6467
6568 describe ( "localStorage Integration" , ( ) => {
6669 test ( "should store and retrieve selected language" , ( ) => {
6770 localStorage . setItem ( "language" , "es" ) ;
68- expect ( localStorage . getItem ( "language" ) ) . toBe ( "es" ) ;
71+ expect ( getCurrentLanguage ( ) ) . toBe ( "es" ) ;
72+ } ) ;
6973
70- localStorage . setItem ( "language" , "fr" ) ;
71- expect ( localStorage . getItem ( "language" ) ) . toBe ( "fr" ) ;
74+ test ( "should fall back to browser language if no stored language" , ( ) => {
75+ Object . defineProperty ( navigator , "language" , { value : "fr-FR" , configurable : true } ) ;
76+ expect ( getCurrentLanguage ( ) ) . toBe ( "fr" ) ;
7277 } ) ;
7378 } ) ;
7479
7580 describe ( "DOM Updates" , ( ) => {
76- beforeEach ( ( ) => {
77- document . documentElement . innerHTML = `
78- <head>
79- <title>Original Title</title>
80- <meta name="description" content="Original Description">
81- </head>
82- <body>
83- <h1 data-translate="role">Original Role</h1>
84- <img data-translate-alt="imageAlt" alt="Original Alt">
85- </body>
86- ` ;
87- } ) ;
88-
8981 test ( "should update document title and meta tags" , ( ) => {
90- document . title = "New Title" ;
91- const metaDesc = document . querySelector ( 'meta[name="description"]' ) ;
92- metaDesc . setAttribute ( "content" , "New Description" ) ;
82+ const translationsData = { title : "New Title" , metaDescription : "New Description" } ;
83+ updateDocumentMeta ( "es" , translationsData ) ;
9384
9485 expect ( document . title ) . toBe ( "New Title" ) ;
95- expect ( metaDesc . getAttribute ( "content" ) ) . toBe ( "New Description" ) ;
86+ expect ( document . querySelector ( 'meta[name="description"]' ) . getAttribute ( "content" ) ) . toBe (
87+ "New Description"
88+ ) ;
89+ expect ( document . documentElement . getAttribute ( "lang" ) ) . toBe ( "es" ) ;
9690 } ) ;
9791
9892 test ( "should update elements with data-translate attribute" , ( ) => {
99- const element = document . querySelector ( '[data-translate="role"]' ) ;
100- element . textContent = "Software Developer" ;
101-
102- expect ( element . textContent ) . toBe ( "Software Developer" ) ;
93+ document . body . innerHTML = '<p data-translate="role">Default</p>' ;
94+ updateTranslations ( { role : "Software Developer" } ) ;
95+ expect ( document . querySelector ( '[data-translate="role"]' ) . textContent ) . toBe (
96+ "Software Developer"
97+ ) ;
10398 } ) ;
10499
105100 test ( "should update alt attributes with data-translate-alt" , ( ) => {
106- const img = document . querySelector ( '[data-translate-alt="imageAlt"]' ) ;
107- img . setAttribute ( "alt" , "New Alt Text" ) ;
101+ document . body . innerHTML = '<img data-translate-alt="imageAlt" alt="Default">' ;
102+ updateTranslations ( { imageAlt : "Profile picture" } ) ;
103+ expect (
104+ document . querySelector ( '[data-translate-alt="imageAlt"]' ) . getAttribute ( "alt" )
105+ ) . toBe ( "Profile picture" ) ;
106+ } ) ;
107+ } ) ;
108+
109+ describe ( "setLanguage Integration" , ( ) => {
110+ test ( "should load translations and update DOM" , async ( ) => {
111+ const mockTranslations = {
112+ title : "Título" ,
113+ metaDescription : "Descripción" ,
114+ role : "Desarrollador"
115+ } ;
116+ global . fetch . mockResolvedValueOnce ( { ok : true , json : async ( ) => mockTranslations } ) ;
117+ document . body . innerHTML = '<p data-translate="role">Default</p>' ;
108118
109- expect ( img . getAttribute ( "alt" ) ) . toBe ( "New Alt Text" ) ;
119+ await setLanguage ( "es" ) ;
120+
121+ expect ( localStorage . getItem ( "language" ) ) . toBe ( "es" ) ;
122+ expect ( document . title ) . toBe ( "Título" ) ;
123+ expect ( document . querySelector ( '[data-translate="role"]' ) . textContent ) . toBe (
124+ "Desarrollador"
125+ ) ;
110126 } ) ;
111127 } ) ;
112128} ) ;
0 commit comments