From 882b0e21325178ee4ff14750e16ce218c2c1d2f8 Mon Sep 17 00:00:00 2001 From: Gabriel De Los Rios Date: Tue, 23 Dec 2025 23:48:35 -0300 Subject: [PATCH] feat: add persistance to language selection --- src/app/app.config.ts | 16 +++++++++++++--- .../components/contact-form/contact-form.spec.ts | 8 +++++--- .../contact-list-table.spec.ts | 7 +++++-- .../components/contact-list/contact-list.spec.ts | 7 +++++-- .../contact-search-bar.spec.ts | 11 +++++++---- src/app/pages/edit/contact-resolver.spec.ts | 6 ++++-- src/app/pages/edit/edit.spec.ts | 6 ++++-- src/app/pages/main/main.spec.ts | 9 +++++++-- src/app/services/contact.service.spec.ts | 6 ++++-- src/app/services/language-manager.spec.ts | 13 +++++++++++-- src/app/services/language-manager.ts | 11 +++++++++-- 11 files changed, 74 insertions(+), 26 deletions(-) diff --git a/src/app/app.config.ts b/src/app/app.config.ts index d999763..2ae0d5d 100644 --- a/src/app/app.config.ts +++ b/src/app/app.config.ts @@ -1,19 +1,29 @@ -import { ApplicationConfig, InjectionToken, provideBrowserGlobalErrorListeners, provideZoneChangeDetection } from '@angular/core'; +import { + ApplicationConfig, + InjectionToken, + provideBrowserGlobalErrorListeners, + provideZoneChangeDetection, +} from '@angular/core'; import { provideRouter } from '@angular/router'; import { routes } from './app.routes'; import { strings } from './strings'; import { provideHttpClient } from '@angular/common/http'; +import { Language } from './types/Language.type'; const STRINGS_TOKEN = 'strings'; export const STRINGS_INJECTOR = new InjectionToken(STRINGS_TOKEN); +const LANGUAGE = 'LS_LANGUAGE'; +export const LS_LANGUAGE = new InjectionToken(LANGUAGE); + export const appConfig: ApplicationConfig = { providers: [ provideBrowserGlobalErrorListeners(), provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideHttpClient(), - {provide: STRINGS_INJECTOR, useValue: strings} - ] + { provide: STRINGS_INJECTOR, useValue: strings }, + { provide: LS_LANGUAGE, useValue: 'language' }, + ], }; diff --git a/src/app/components/contact-form/contact-form.spec.ts b/src/app/components/contact-form/contact-form.spec.ts index 0cc75c7..80dc695 100644 --- a/src/app/components/contact-form/contact-form.spec.ts +++ b/src/app/components/contact-form/contact-form.spec.ts @@ -1,22 +1,24 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ContactForm } from './contact-form'; -import { STRINGS_INJECTOR } from '../../app.config'; import { strings } from '../../strings'; import { By } from '@angular/platform-browser'; import { ContactDTO } from '../../models/ContactDTO'; +import { LanguageManager } from '../../services/language-manager'; describe('ContactForm', () => { let component: ContactForm; let fixture: ComponentFixture; + let languageManager: jasmine.SpyObj; beforeEach(async () => { + languageManager = jasmine.createSpyObj(LanguageManager.name, [], { strings: strings.en }); + await TestBed.configureTestingModule({ imports: [ContactForm], - providers: [{ provide: STRINGS_INJECTOR, useValue: strings }], + providers: [{ provide: LanguageManager, useValue: languageManager }], }).compileComponents(); - TestBed.inject(STRINGS_INJECTOR); fixture = TestBed.createComponent(ContactForm); component = fixture.componentInstance; fixture.detectChanges(); diff --git a/src/app/components/contact-list-table/contact-list-table.spec.ts b/src/app/components/contact-list-table/contact-list-table.spec.ts index 5a809ac..a4d368c 100644 --- a/src/app/components/contact-list-table/contact-list-table.spec.ts +++ b/src/app/components/contact-list-table/contact-list-table.spec.ts @@ -1,30 +1,33 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ContactListTable } from './contact-list-table'; -import { STRINGS_INJECTOR } from '../../app.config'; import { strings } from '../../strings'; import { ContactService } from '../../services/contact.service'; import { ContactDTO } from '../../models/ContactDTO'; import { By } from '@angular/platform-browser'; import { of } from 'rxjs'; import { Router } from '@angular/router'; +import { LanguageManager } from '../../services/language-manager'; describe('ContactListTable', () => { let component: ContactListTable; let fixture: ComponentFixture; + let contactService: jasmine.SpyObj; + let languageManager: jasmine.SpyObj; let router: jasmine.SpyObj; let CONTACT_LIST_MOCK: ContactDTO[]; beforeEach(async () => { contactService = jasmine.createSpyObj(ContactService.name, ['delete']); + languageManager = jasmine.createSpyObj(LanguageManager.name, [], { strings: strings.en }); router = jasmine.createSpyObj(Router.name, ['navigate']); CONTACT_LIST_MOCK = [new ContactDTO(1, 'MOCK', 'MOCK', '5491122222222')]; await TestBed.configureTestingModule({ imports: [ContactListTable], providers: [ - { provide: STRINGS_INJECTOR, useValue: strings }, { provide: ContactService, useValue: contactService }, + { provide: LanguageManager, useValue: languageManager }, { provide: Router, useValue: router }, ], }).compileComponents(); diff --git a/src/app/components/contact-list/contact-list.spec.ts b/src/app/components/contact-list/contact-list.spec.ts index 803e35b..4b14925 100644 --- a/src/app/components/contact-list/contact-list.spec.ts +++ b/src/app/components/contact-list/contact-list.spec.ts @@ -3,21 +3,24 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ContactList } from './contact-list'; import { ContactService } from '../../services/contact.service'; import { of } from 'rxjs'; -import { STRINGS_INJECTOR } from '../../app.config'; import { strings } from '../../strings'; +import { LanguageManager } from '../../services/language-manager'; describe('ContactList', () => { let component: ContactList; let fixture: ComponentFixture; let contactService: jasmine.SpyObj; + let languageManager: jasmine.SpyObj; beforeEach(async () => { contactService = jasmine.createSpyObj(ContactService.name, ['getAll']); + languageManager = jasmine.createSpyObj(LanguageManager.name, [], { strings: strings.en }); + await TestBed.configureTestingModule({ imports: [ContactList], providers: [ { provide: ContactService, useValue: contactService }, - { provide: STRINGS_INJECTOR, useValue: strings }, + { provide: LanguageManager, useValue: languageManager }, ], }).compileComponents(); contactService.getAll.and.returnValue(of([])); diff --git a/src/app/components/contact-search-bar/contact-search-bar.spec.ts b/src/app/components/contact-search-bar/contact-search-bar.spec.ts index 4a1cf56..93abf42 100644 --- a/src/app/components/contact-search-bar/contact-search-bar.spec.ts +++ b/src/app/components/contact-search-bar/contact-search-bar.spec.ts @@ -1,19 +1,22 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ContactSearchBar } from './contact-search-bar'; -import { STRINGS_INJECTOR } from '../../app.config'; import { strings } from '../../strings'; +import { LanguageManager } from '../../services/language-manager'; describe('ContactSearchBar', () => { let component: ContactSearchBar; let fixture: ComponentFixture; + let languageManager: jasmine.SpyObj; + beforeEach(async () => { + languageManager = jasmine.createSpyObj(LanguageManager.name, [], { strings: strings.en }); + await TestBed.configureTestingModule({ imports: [ContactSearchBar], - providers: [{provide: STRINGS_INJECTOR, useValue: strings}] - }) - .compileComponents(); + providers: [{ provide: LanguageManager, useValue: languageManager }], + }).compileComponents(); fixture = TestBed.createComponent(ContactSearchBar); component = fixture.componentInstance; diff --git a/src/app/pages/edit/contact-resolver.spec.ts b/src/app/pages/edit/contact-resolver.spec.ts index f3ab2cf..5d748e4 100644 --- a/src/app/pages/edit/contact-resolver.spec.ts +++ b/src/app/pages/edit/contact-resolver.spec.ts @@ -6,11 +6,12 @@ import { ContactDTO } from '../../models/ContactDTO'; import { provideHttpClient } from '@angular/common/http'; import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing'; import { environment } from '../../../environments/environment'; -import { STRINGS_INJECTOR } from '../../app.config'; import { strings } from '../../strings'; +import { LanguageManager } from '../../services/language-manager'; describe('contactResolver', () => { let httpTestingController: HttpTestingController; + let languageManager: jasmine.SpyObj; let router: jasmine.SpyObj; let ROUTE_MOCK: jasmine.SpyObj; @@ -19,6 +20,7 @@ describe('contactResolver', () => { TestBed.runInInjectionContext(() => contactResolver(...resolverParameters)); beforeEach(() => { + languageManager = jasmine.createSpyObj(LanguageManager.name, [], { strings: strings.en }); router = jasmine.createSpyObj(Router.name, ['navigate']); ROUTE_MOCK = jasmine.createSpyObj(ActivatedRouteSnapshot.name, [], { paramMap: { @@ -32,8 +34,8 @@ describe('contactResolver', () => { providers: [ provideHttpClient(), provideHttpClientTesting(), + { provide: LanguageManager, useValue: languageManager }, { provide: Router, useValue: router }, - { provide: STRINGS_INJECTOR, useValue: strings }, ], }); httpTestingController = TestBed.inject(HttpTestingController); diff --git a/src/app/pages/edit/edit.spec.ts b/src/app/pages/edit/edit.spec.ts index 5555bbc..198c0b2 100644 --- a/src/app/pages/edit/edit.spec.ts +++ b/src/app/pages/edit/edit.spec.ts @@ -1,13 +1,13 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { Edit } from './edit'; -import { STRINGS_INJECTOR } from '../../app.config'; import { strings } from '../../strings'; import { ActivatedRoute, Router } from '@angular/router'; import { ContactService } from '../../services/contact.service'; import { of } from 'rxjs'; import { ContactDTO } from '../../models/ContactDTO'; import { By } from '@angular/platform-browser'; +import { LanguageManager } from '../../services/language-manager'; describe('Edit', () => { let component: Edit; @@ -15,6 +15,7 @@ describe('Edit', () => { let activatedRoute: jasmine.SpyObj; let contactService: jasmine.SpyObj; + let languageManager: jasmine.SpyObj; let router: jasmine.SpyObj; let CONTACT_MOCK: ContactDTO; @@ -25,6 +26,7 @@ describe('Edit', () => { data: of({ contact: CONTACT_MOCK }), }); contactService = jasmine.createSpyObj(ContactService.name, ['update']); + languageManager = jasmine.createSpyObj(LanguageManager.name, [], { strings: strings.en }); router = jasmine.createSpyObj(Router.name, ['navigate']); await TestBed.configureTestingModule({ @@ -32,8 +34,8 @@ describe('Edit', () => { providers: [ { provide: ActivatedRoute, useValue: activatedRoute }, { provide: ContactService, useValue: contactService }, + { provide: LanguageManager, useValue: languageManager }, { provide: Router, useValue: router }, - { provide: STRINGS_INJECTOR, useValue: strings }, ], }).compileComponents(); diff --git a/src/app/pages/main/main.spec.ts b/src/app/pages/main/main.spec.ts index 13ea3c0..45b52ad 100644 --- a/src/app/pages/main/main.spec.ts +++ b/src/app/pages/main/main.spec.ts @@ -1,7 +1,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { Main } from './main'; -import { STRINGS_INJECTOR } from '../../app.config'; import { strings } from '../../strings'; import { ContactService } from '../../services/contact.service'; import { ContactList } from '../../components/contact-list/contact-list'; @@ -9,22 +8,28 @@ import { of } from 'rxjs'; import { ContactDTO } from '../../models/ContactDTO'; import { By } from '@angular/platform-browser'; import { ContactForm } from '../../components/contact-form/contact-form'; +import { LanguageManager } from '../../services/language-manager'; describe('Main', () => { let component: Main; let fixture: ComponentFixture
; let contactService: jasmine.SpyObj; + let languageManager: jasmine.SpyObj; beforeEach(async () => { contactService = jasmine.createSpyObj(ContactList.name, ['getAll', 'save']); contactService.getAll.and.returnValue(of([])); + languageManager = jasmine.createSpyObj(LanguageManager.name, ['selectedLanguage$'], { + strings: strings.en, + }); await TestBed.configureTestingModule({ imports: [Main], providers: [ - { provide: STRINGS_INJECTOR, useValue: strings }, { provide: ContactService, useValue: contactService }, + { provide: LanguageManager, useValue: languageManager }, ], }).compileComponents(); + languageManager.selectedLanguage$.and.returnValue('en'); fixture = TestBed.createComponent(Main); component = fixture.componentInstance; fixture.detectChanges(); diff --git a/src/app/services/contact.service.spec.ts b/src/app/services/contact.service.spec.ts index 8b9ba7a..befb9a9 100644 --- a/src/app/services/contact.service.spec.ts +++ b/src/app/services/contact.service.spec.ts @@ -5,23 +5,25 @@ import { provideHttpClient } from '@angular/common/http'; import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing'; import { environment } from '../../environments/environment'; import { ContactDTO } from '../models/ContactDTO'; -import { STRINGS_INJECTOR } from '../app.config'; import { strings } from '../strings'; +import { LanguageManager } from './language-manager'; describe('ContactService', () => { let service: ContactService; let httpTestingController: HttpTestingController; + let languageManager: jasmine.SpyObj; let RES_MOCK: Response; let endpointURL = environment.apiUrl + '/contacts'; beforeEach(() => { + languageManager = jasmine.createSpyObj(LanguageManager.name, [], { strings: strings.en }); TestBed.configureTestingModule({ imports: [], providers: [ provideHttpClient(), provideHttpClientTesting(), - { provide: STRINGS_INJECTOR, useValue: strings }, + { provide: LanguageManager, useValue: languageManager }, ], }); service = TestBed.inject(ContactService); diff --git a/src/app/services/language-manager.spec.ts b/src/app/services/language-manager.spec.ts index 13e6d8a..7647fd1 100644 --- a/src/app/services/language-manager.spec.ts +++ b/src/app/services/language-manager.spec.ts @@ -2,24 +2,33 @@ import { TestBed } from '@angular/core/testing'; import { LanguageManager } from './language-manager'; import { strings } from '../strings'; -import { STRINGS_INJECTOR } from '../app.config'; +import { LS_LANGUAGE, STRINGS_INJECTOR } from '../app.config'; import { Language } from '../types/Language.type'; +import { Localstorage } from './localstorage'; describe('LanguageManager', () => { let service: LanguageManager; + let localStorage: jasmine.SpyObj; beforeEach(() => { + localStorage = jasmine.createSpyObj(Localstorage.name, ['getItem', 'setItem']); TestBed.configureTestingModule({ - providers: [{ provide: STRINGS_INJECTOR, useValue: strings }], + providers: [ + { provide: STRINGS_INJECTOR, useValue: strings }, + { provide: LS_LANGUAGE, useValue: 'language' }, + { provide: Localstorage, useValue: localStorage }, + ], }); service = TestBed.inject(LanguageManager); }); it('should be created', () => { + localStorage.getItem.and.returnValue(null); expect(service).toBeTruthy(); }); it('should switch language', () => { + localStorage.getItem.and.returnValue(null); const SELECTED_LANGUAGE_MOCK: Language = 'es'; service.setLanguage(SELECTED_LANGUAGE_MOCK); expect(service.strings).toEqual(strings[SELECTED_LANGUAGE_MOCK]); diff --git a/src/app/services/language-manager.ts b/src/app/services/language-manager.ts index eb305f2..29f977e 100644 --- a/src/app/services/language-manager.ts +++ b/src/app/services/language-manager.ts @@ -1,19 +1,26 @@ import { inject, Injectable, signal } from '@angular/core'; -import { STRINGS_INJECTOR } from '../app.config'; +import { LS_LANGUAGE, STRINGS_INJECTOR } from '../app.config'; import { Language } from '../types/Language.type'; +import { Localstorage } from './localstorage'; @Injectable({ providedIn: 'root', }) export class LanguageManager { private readonly stringsDictionary = inject(STRINGS_INJECTOR); - + private readonly localStorage = inject(Localstorage); + private readonly lS_LANGUAGE = inject(LS_LANGUAGE); private readonly selectedLanguage = signal('en'); readonly selectedLanguage$ = this.selectedLanguage.asReadonly(); strings = this.stringsDictionary.en; + constructor() { + this.setLanguage(this.localStorage.getItem(this.lS_LANGUAGE) ?? 'en'); + } + setLanguage(language: Language) { this.selectedLanguage.set(language); + this.localStorage.setItem(this.lS_LANGUAGE, language); this.strings = this.stringsDictionary[language]; } }