@ngx-translate/core
Version:
529 lines (422 loc) • 18 kB
text/typescript
import {fakeAsync, TestBed, tick} from "@angular/core/testing";
import {Observable, of, timer, zip, defer} from "rxjs";
import {mapTo, take, toArray, first} from 'rxjs/operators';
import {LangChangeEvent, TranslateLoader, TranslateModule, TranslateService, TranslationChangeEvent} from '../public-api';
let translations: any = {"TEST": "This is a test"};
class FakeLoader implements TranslateLoader {
getTranslation(lang: string): Observable<any> {
return of(translations);
}
}
describe('TranslateService', () => {
let translate: TranslateService;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot({
loader: {provide: TranslateLoader, useClass: FakeLoader}
})
]
});
translate = TestBed.inject(TranslateService);
});
afterEach(() => {
translations = {"TEST": "This is a test"};
});
it('is defined', () => {
expect(TranslateService).toBeDefined();
expect(translate).toBeDefined();
expect(translate instanceof TranslateService).toBeTruthy();
});
it('should be able to get translations', () => {
translations = {"TEST": "This is a test", "TEST2": "This is another test"};
translate.use('en');
// this will request the translation from the backend because we use a static files loader for TranslateService
translate.get('TEST').subscribe((res: string) => {
expect(res).toEqual('This is a test');
});
// this will request the translation from downloaded translations without making a request to the backend
translate.get('TEST2').subscribe((res: string) => {
expect(res).toEqual('This is another test');
});
});
it('should be able to get an array translations', () => {
translations = {"TEST": "This is a test", "TEST2": "This is another test2"};
translate.use('en');
// this will request the translation from the backend because we use a static files loader for TranslateService
translate.get(['TEST', 'TEST2']).subscribe((res: string) => {
expect(res).toEqual(translations);
});
});
it("should fallback to the default language", () => {
translations = {};
translate.use('fr');
translate.get('TEST').subscribe((res: string) => {
expect(res).toEqual('TEST');
translate.setDefaultLang('nl');
translate.setTranslation('nl', {"TEST": "Dit is een test"});
translate.get('TEST').subscribe((res2: string) => {
expect(res2).toEqual('Dit is een test');
expect(translate.getDefaultLang()).toEqual('nl');
});
});
});
it("should use the default language by default", () => {
translate.setDefaultLang('nl');
translate.setTranslation('nl', {"TEST": "Dit is een test"});
translate.get('TEST').subscribe((res: string) => {
expect(res).toEqual('Dit is een test');
});
});
it("should return the key when it doesn't find a translation", () => {
translate.use('en');
translate.get('TEST2').subscribe((res: string) => {
expect(res).toEqual('TEST2');
});
});
it("should return the key when you haven't defined any translation", () => {
translate.get('TEST').subscribe((res: string) => {
expect(res).toEqual('TEST');
});
});
it('should return an empty value', () => {
translate.setDefaultLang('en');
translate.setTranslation('en', {"TEST": ""});
translate.get('TEST').subscribe((res: string) => {
expect(res).toEqual('');
});
});
it('should be able to get translations with params', () => {
translations = {"TEST": "This is a test {{param}}"};
translate.use('en');
translate.get('TEST', {param: 'with param'}).subscribe((res: string) => {
expect(res).toEqual('This is a test with param');
});
});
it('should be able to get translations with nested params', () => {
translations = {"TEST": "This is a test {{param.value}}"};
translate.use('en');
translate.get('TEST', {param: {value: 'with param'}}).subscribe((res: string) => {
expect(res).toEqual('This is a test with param');
});
});
it('should throw if you forget the key', () => {
translate.use('en');
expect(() => {
translate.get(undefined as any);
}).toThrowError('Parameter "key" required');
expect(() => {
translate.get('');
}).toThrowError('Parameter "key" required');
expect(() => {
translate.get(null as any);
}).toThrowError('Parameter "key" required');
expect(() => {
translate.instant(undefined as any);
}).toThrowError('Parameter "key" required');
});
it('should be able to get translations with nested keys', () => {
translations = {"TEST": {"TEST": "This is a test"}, "TEST2": {"TEST2": {"TEST2": "This is another test"}}};
translate.use('en');
translate.get('TEST.TEST').subscribe((res: string) => {
expect(res).toEqual('This is a test');
});
translate.get('TEST2.TEST2.TEST2').subscribe((res: string) => {
expect(res).toEqual('This is another test');
});
});
it("should merge translations if option shouldMerge is true", (done: Function) => {
translations = {};
translate.setTranslation('en', {"TEST": {"sub1": "value1"}}, true);
translate.setTranslation('en', {"TEST": {"sub2": "value2"}}, true);
translate.use('en');
translate.get('TEST').subscribe((res: any) => {
expect(res).toEqual({"sub1": "value1", "sub2": "value2"});
expect(translations).toEqual({});
done();
});
});
it("should merge non-valid JSON translations if option shouldMerge is true", () => {
translations = {};
translate.setTranslation('en', {"TEST": {"sub1": () => "value1"}}, true);
translate.setTranslation('en', {"TEST": {"sub2": () => "value2"}}, true);
translate.use('en');
translate.get('TEST.sub1').subscribe((res: string) => {
expect(res).toEqual('value1');
});
translate.get('TEST.sub2').subscribe((res: string) => {
expect(res).toEqual('value2');
});
});
it("shouldn't call the current loader if you set the translation yourself", (done: Function) => {
translations = {};
translate.setTranslation('en', {"TEST": "This is a test"});
translate.use('en');
translate.get('TEST').subscribe((res: string) => {
expect(res).toEqual('This is a test');
expect(translations).toEqual({});
done();
});
});
it('should be able to get a stream array', (done: Function) => {
let tr = {"TEST": "This is a test", "TEST2": "This is a test2"};
translate.setTranslation('en', tr);
translate.use('en');
translate.getStreamOnTranslationChange(['TEST', 'TEST2']).subscribe((res: any) => {
expect(res).toEqual(tr);
done();
});
});
it('should initially return the same value for getStreamOnTranslationChange and non-streaming get', (done: Function) => {
translations = {"TEST": "This is a test"};
translate.use('en');
zip(translate.getStreamOnTranslationChange('TEST'), translate.get('TEST')).subscribe((value: [string, string]) => {
const [streamed, nonStreamed] = value;
expect(streamed).toEqual('This is a test');
expect(streamed).toEqual(nonStreamed);
done();
});
});
it('should be able to stream a translation on translation change', (done: Function) => {
translations = {"TEST": "This is a test"};
translate.use('en');
translate.getStreamOnTranslationChange('TEST').pipe(take(3), toArray()).subscribe((res: string[]) => {
const expected = ['This is a test', 'I changed the test value!', 'I changed it again!'];
expect(res).toEqual(expected);
done();
});
translate.setTranslation('en', {"TEST": "I changed the test value!"});
translate.setTranslation('en', {"TEST": "I changed it again!"});
});
it('should interpolate the same param into each streamed value when get strean on translation change', (done: Function) => {
translations = {"TEST": "This is a test {{param}}"};
translate.use('en');
translate.getStreamOnTranslationChange('TEST', {param: 'with param'}).subscribe((res: string[]) => {
const expected = 'This is a test with param';
expect(res).toEqual(expected);
done();
});
});
it('should be able to stream a translation for the current language', (done: Function) => {
translations = {"TEST": "This is a test"};
translate.use('en');
translate.stream('TEST').subscribe((res: string) => {
expect(res).toEqual('This is a test');
done();
});
});
it('should be able to stream a translation of an array for the current language', (done: Function) => {
let tr = {"TEST": "This is a test", "TEST2": "This is a test2"};
translate.setTranslation('en', tr);
translate.use('en');
translate.stream(['TEST', 'TEST2']).subscribe((res: any) => {
expect(res).toEqual(tr);
done();
});
});
it('should initially return the same value for streaming and non-streaming get', (done: Function) => {
translations = {"TEST": "This is a test"};
translate.use('en');
zip(translate.stream('TEST'), translate.get('TEST')).subscribe((value: [string, string]) => {
const [streamed, nonStreamed] = value;
expect(streamed).toEqual('This is a test');
expect(streamed).toEqual(nonStreamed);
done();
});
});
it('should update streaming translations on language change', (done: Function) => {
translations = {"TEST": "This is a test"};
translate.use('en');
translate.stream('TEST').pipe(take(3), toArray()).subscribe((res: string[]) => {
const expected = ['This is a test', 'Dit is een test', 'This is a test'];
expect(res).toEqual(expected);
done();
});
translate.setTranslation('nl', {"TEST": "Dit is een test"});
translate.use('nl');
translate.use('en');
});
it('should update lazy streaming translations on translation change', (done: Function) => {
translations = {"TEST": "This is a test"};
translate.use('en');
const translation$ = translate.getStreamOnTranslationChange('TEST');
translate.setTranslation('en', {"TEST": "This is a test2"});
translation$.pipe(first()).subscribe((res: string[]) => {
const expected = "This is a test2";
expect(res).toEqual(expected);
done();
});
});
it('should update lazy streaming translations on language change', (done: Function) => {
translations = {"TEST": "This is a test"};
translate.use('en');
const translation$ = translate.stream('TEST');
translate.setTranslation('nl', {"TEST": "Dit is een test"});
translate.use('nl');
translation$.pipe(first()).subscribe((res: string[]) => {
const expected = 'Dit is een test';
expect(res).toEqual(expected);
done();
});
});
it('should update streaming translations of an array on language change', (done: Function) => {
const en = {"TEST": "This is a test", "TEST2": "This is a test2"};
const nl = {"TEST": "Dit is een test", "TEST2": "Dit is een test2"};
translate.setTranslation('en', en);
translate.use('en');
translate.stream(['TEST', 'TEST2']).pipe(take(3), toArray()).subscribe((res: any[]) => {
const expected = [en, nl, en];
expect(res).toEqual(expected);
done();
});
translate.setTranslation('nl', nl);
translate.use('nl');
translate.use('en');
});
it('should interpolate the same param into each streamed value', (done: Function) => {
translations = {"TEST": "This is a test {{param}}"};
translate.use('en');
translate.stream('TEST', {param: 'with param'}).pipe(take(3), toArray()).subscribe((res: string[]) => {
const expected = [
'This is a test with param',
'Dit is een test with param',
'This is a test with param'
];
expect(res).toEqual(expected);
done();
});
translate.setTranslation('nl', {"TEST": "Dit is een test {{param}}"});
translate.use('nl');
translate.use('en');
});
it('should be able to get instant translations', () => {
translate.setTranslation('en', {"TEST": "This is a test"});
translate.use('en');
expect(translate.instant('TEST')).toEqual('This is a test');
});
it('should be able to get instant translations of an array', () => {
let tr = {"TEST": "This is a test", "TEST2": "This is a test2"};
translate.setTranslation('en', tr);
translate.use('en');
expect(translate.instant(['TEST', 'TEST2'])).toEqual(tr);
});
it('should return the key if instant translations are not available', () => {
translate.setTranslation('en', {"TEST": "This is a test"});
translate.use('en');
expect(translate.instant('TEST2')).toEqual('TEST2');
});
it('should trigger an event when the translation value changes', () => {
translate.setTranslation('en', {});
translate.onTranslationChange.subscribe((event: TranslationChangeEvent) => {
expect(event.translations).toBeDefined();
expect(event.translations["TEST"]).toEqual("This is a test");
expect(event.lang).toBe('en');
});
translate.set("TEST", "This is a test", 'en');
});
it('should trigger an event when the lang changes', () => {
let tr = {"TEST": "This is a test"};
translate.setTranslation('en', tr);
translate.onLangChange.subscribe((event: LangChangeEvent) => {
expect(event.lang).toBe('en');
expect(event.translations).toEqual(tr);
});
translate.use('en');
});
it('should be able to reset a lang', (done: Function) => {
translate.use('en');
// this will request the translation from the backend because we use a static files loader for TranslateService
translate.get('TEST').subscribe((res: string) => {
expect(res).toEqual(translations['TEST']);
// reset the lang as if it was never initiated
translate.resetLang('en');
expect(translate.instant('TEST')).toEqual('TEST');
translate.get('TEST').subscribe((res2: string) => {
expect(res2).toEqual('TEST'); // because the loader is "pristine" as if it was never called
done();
});
});
});
it('should be able to reload a lang', () => {
translations = {};
translate.use('en');
// this will request the translation from the loader
translate.get('TEST').subscribe((res: string) => {
expect(res).toEqual('TEST');
translations = {"TEST": "This is a test 2"};
// reset the lang as if it was never initiated
translate.reloadLang('en').subscribe((res2: string) => {
expect(translate.instant('TEST')).toEqual(translations['TEST']);
});
});
});
it('should be able to add new langs', () => {
translate.addLangs(['pl', 'es']);
expect(translate.getLangs()).toEqual(['pl', 'es']);
translate.addLangs(['fr']);
translate.addLangs(['pl', 'fr']);
expect(translate.getLangs()).toEqual(['pl', 'es', 'fr']);
// this will request the translation from the backend because we use a static files loader for TranslateService
translate.use('en').subscribe((res: string) => {
expect(translate.getLangs()).toEqual(['pl', 'es', 'fr', 'en']);
translate.addLangs(['de']);
expect(translate.getLangs()).toEqual(['pl', 'es', 'fr', 'en', 'de']);
});
});
it('should be able to get the browserLang', () => {
let browserLang = translate.getBrowserLang();
expect(browserLang).toBeDefined();
expect(typeof browserLang === 'string').toBeTruthy();
});
it('should be able to get the browserCultureLang', () => {
let browserCultureLand = translate.getBrowserCultureLang();
expect(browserCultureLand).toBeDefined();
expect(typeof browserCultureLand === 'string').toBeTruthy();
});
it('should not make duplicate getTranslation calls', fakeAsync(() => {
let getTranslationCalls = 0;
jest.spyOn(translate.currentLoader, 'getTranslation').mockImplementation(() => {
getTranslationCalls += 1;
return timer(1000).pipe(mapTo(of(translations)));
});
translate.use('en');
translate.use('en');
tick(1001);
expect(getTranslationCalls).toEqual(1);
}));
it('should subscribe to the loader just once', () => {
let subscriptions = 0;
jest.spyOn(translate.currentLoader, 'getTranslation').mockImplementation(() => {
return defer(() => {
subscriptions++;
return of(translations);
});
});
translate.use('en');
translate.use('en');
translate.use('en').subscribe();
translate.use('en').subscribe();
expect(subscriptions).toEqual(1);
});
it('should compile translations only once, even when subscribing to translations while translations are loading', fakeAsync(() => {
jest.spyOn(translate.currentLoader, 'getTranslation').mockImplementation(() => {
return timer(1000).pipe(mapTo(of(translations)));
});
let translateCompilerCallCount = 0;
jest.spyOn(translate.compiler, 'compile').mockImplementation((value) => {
++translateCompilerCallCount;
return value;
});
jest.spyOn(translate.compiler, 'compileTranslations').mockImplementation((value) => {
++translateCompilerCallCount;
return value;
});
translate.setDefaultLang('en-US');
translate.get('TEST1').subscribe();
translate.get('TEST2').subscribe();
translate.get('TEST3').subscribe();
translate.get('TEST4').subscribe();
tick(1001);
expect(translateCompilerCallCount).toBe(1);
}));
});