import { HttpClientTestingModule, HttpTestingController, } from '@angular/common/http/testing'; import { DebugElement, NO_ERRORS_SCHEMA, } from '@angular/core'; import { ComponentFixture, TestBed, waitForAsync, } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { TranslateLoader, TranslateModule, TranslateService, } from '@ngx-translate/core'; import { Observable, of, } from 'rxjs'; import { LangConfig } from '../../../config/lang-config.interface'; import { LocaleService } from '../../core/locale/locale.service'; import { LangSwitchComponent } from './lang-switch.component'; // This test is completely independent from any message catalogs or keys in the codebase // The translation module is instantiated with these bogus messages that we aren't using anyway. // Double quotes are mandatory in JSON, so de-activating the tslint rule checking for single quotes here. /* eslint-disable @typescript-eslint/quotes */ // JSON for the language files has double quotes around all literals /* eslint-disable quote-props */ class CustomLoader implements TranslateLoader { getTranslation(lang: string): Observable<any> { return of({ 'footer': { 'copyright': 'copyright © 2002-{{ year }}', 'link.dspace': 'DSpace software', 'link.lyrasis': 'LYRASIS', }, }); } } /* eslint-enable @typescript-eslint/quotes */ /* eslint-enable quote-props */ let localService: any; describe('LangSwitchComponent', () => { function getMockLocaleService(): LocaleService { return jasmine.createSpyObj('LocaleService', { setCurrentLanguageCode: jasmine.createSpy('setCurrentLanguageCode'), refreshAfterChangeLanguage: jasmine.createSpy('refreshAfterChangeLanguage'), }); } describe('with English and Deutsch activated, English as default', () => { let component: LangSwitchComponent; let fixture: ComponentFixture<LangSwitchComponent>; let de: DebugElement; let langSwitchElement: HTMLElement; let translate: TranslateService; let http: HttpTestingController; beforeEach(waitForAsync(() => { const mockConfig = { languages: [{ code: 'en', label: 'English', active: true, }, { code: 'de', label: 'Deutsch', active: true, }], }; TestBed.configureTestingModule({ imports: [HttpClientTestingModule, TranslateModule.forRoot({ loader: { provide: TranslateLoader, useClass: CustomLoader }, }), LangSwitchComponent], schemas: [NO_ERRORS_SCHEMA], providers: [ TranslateService, { provide: LocaleService, useValue: getMockLocaleService() }, ], }).compileComponents() .then(() => { translate = TestBed.inject(TranslateService); translate.addLangs(mockConfig.languages.filter((langConfig: LangConfig) => langConfig.active === true).map((a) => a.code)); translate.setDefaultLang('en'); translate.use('en'); http = TestBed.inject(HttpTestingController); fixture = TestBed.createComponent(LangSwitchComponent); localService = TestBed.inject(LocaleService); component = fixture.componentInstance; de = fixture.debugElement; langSwitchElement = de.nativeElement; fixture.detectChanges(); }); })); it('should create', () => { expect(component).toBeDefined(); }); it('should identify English as the label for the current active language in the component', waitForAsync(() => { fixture.detectChanges(); expect(component.currentLangLabel()).toEqual('English'); })); it('should be initialized with more than one language active', waitForAsync(() => { fixture.detectChanges(); expect(component.moreThanOneLanguage).toBeTruthy(); })); it('should define the main A HREF in the UI', (() => { expect(langSwitchElement.querySelector('a')).not.toBeNull(); })); describe('when selecting a language', () => { beforeEach(() => { spyOn(translate, 'use'); const langItem = fixture.debugElement.query(By.css('.dropdown-item')).nativeElement; langItem.click(); fixture.detectChanges(); }); it('should translate the app and set the client\'s language cookie', () => { expect(localService.setCurrentLanguageCode).toHaveBeenCalled(); expect(localService.refreshAfterChangeLanguage).toHaveBeenCalled(); }); }); }); describe('with English as the only active and also default language', () => { let component: LangSwitchComponent; let fixture: ComponentFixture<LangSwitchComponent>; let de: DebugElement; let langSwitchElement: HTMLElement; let translate: TranslateService; let http: HttpTestingController; beforeEach(waitForAsync(() => { const mockConfig = { languages: [{ code: 'en', label: 'English', active: true, }, { code: 'de', label: 'Deutsch', active: false, }], }; TestBed.configureTestingModule({ imports: [HttpClientTestingModule, TranslateModule.forRoot({ loader: { provide: TranslateLoader, useClass: CustomLoader }, }), LangSwitchComponent], schemas: [NO_ERRORS_SCHEMA], providers: [ TranslateService, { provide: LocaleService, useValue: getMockLocaleService() }, ], }).compileComponents(); translate = TestBed.inject(TranslateService); translate.addLangs(mockConfig.languages.filter((MyLangConfig) => MyLangConfig.active === true).map((a) => a.code)); translate.setDefaultLang('en'); translate.use('en'); http = TestBed.inject(HttpTestingController); })); beforeEach(() => { fixture = TestBed.createComponent(LangSwitchComponent); component = fixture.componentInstance; de = fixture.debugElement; langSwitchElement = de.nativeElement; }); it('should create', () => { expect(component).toBeDefined(); }); it('should not define the main header for the language switch, as it should be invisible', (() => { expect(langSwitchElement.querySelector('a')).toBeNull(); })); }); });