import { ChangeDetectionStrategy , ChangeDetectorRef , Component , Injectable , ViewContainerRef , ElementRef } from "@angular/core" ; import { TestBed } from "@angular/core/testing" ; import { Observable , of } from "rxjs" ; import { DefaultLangChangeEvent , LangChangeEvent , TranslateLoader , RequestState , TranslateModule , TranslateService , TranslatePipe } from '@rxweb/ngx-translate-extension' ; import { RxTranslateModule , RxTranslation , TranslationResolver } from '@rxweb/translate' ; import { RouterModule , ActivatedRoute } from '@angular/router' ; class MockElementRef extends ElementRef { constructor ( nodeName ) { super ( nodeName ) ; } } class FakeActivatedRoute { } class FakeChangeDetectorRef extends ChangeDetectorRef { markForCheck ( ) { } detach ( ) { } detectChanges ( ) { } checkNoChanges ( ) { } reattach ( ) { } } @ Injectable ( ) @ Component ( { selector : 'hmx-app' , changeDetection : ChangeDetectionStrategy . OnPush , template : `{{'TEST' | translate}}` } ) class App { viewContainerRef : ViewContainerRef ; constructor ( viewContainerRef ) { this . viewContainerRef = viewContainerRef ; } } let translations = { "TEST" : "This is a test" } ; class FakeLoader implements TranslateLoader { getTranslation ( lang ) { return of ( translations ) ; } } describe ( 'TranslatePipe' , ( ) => { let translate ; let translatePipe ; let ref ; beforeEach ( ( ) => { TestBed . configureTestingModule ( { imports : [ RouterModule , TranslateModule . forRoot ( { loader : { provide : TranslateLoader , useClass : FakeLoader } } ) , RxTranslateModule . forRoot ( { isTest : true , forNgxTranslate : true , cacheLanguageWiseObject : true , } ) ] , providers : [ { provide : ActivatedRoute , useClass : FakeActivatedRoute } ] , declarations : [ App ] } ) ; translate = TestBed . get ( TranslateService ) ; ref = new FakeChangeDetectorRef ( ) ; translatePipe = new TranslatePipe ( translate , ref , new MockElementRef ( "app-root" ) , TestBed . get ( RxTranslation ) , < any > { component : App } , TestBed . get ( RequestState ) , TestBed . get ( TranslationResolver ) ) ; } ) ; afterEach ( ( ) => { translate = undefined ; translations = { "TEST" : "This is a test" } ; translatePipe = undefined ; ref = undefined ; } ) ; it ( 'is defined' , ( ) => { expect ( TranslatePipe ) . toBeDefined ( ) ; expect ( translatePipe ) . toBeDefined ( ) ; expect ( translatePipe instanceof TranslatePipe ) . toBeTruthy ( ) ; } ) ; it ( 'should translate a string' , ( ) => { translate . setTranslation ( 'en' , { "TEST" : "This is a test" } ) ; translate . use ( 'en' ) ; expect ( translatePipe . transform ( 'TEST' ) ) . toEqual ( "This is a test" ) ; } ) ; it ( 'should call markForChanges when it translates a string' , ( ) => { translate . setTranslation ( 'en' , { "TEST" : "This is a test" } ) ; translate . use ( 'en' ) ; spyOn ( ref , 'markForCheck' ) . and . callThrough ( ) ; translatePipe . transform ( 'TEST' ) ; expect ( ref . markForCheck ) . toHaveBeenCalled ( ) ; } ) ; it ( 'should translate a string with object parameters' , ( ) => { translate . setTranslation ( 'en' , { "TEST" : "This is a test {{param}}" } ) ; translate . use ( 'en' ) ; expect ( translatePipe . transform ( 'TEST' , { param : "with param" } ) ) . toEqual ( "This is a test with param" ) ; } ) ; it ( 'should translate a string with object as string parameters' , ( ) => { translate . setTranslation ( 'en' , { "TEST" : "This is a test {{param}}" } ) ; translate . use ( 'en' ) ; expect ( translatePipe . transform ( 'TEST' , '{param: "with param"}' ) ) . toEqual ( "This is a test with param" ) ; expect ( translatePipe . transform ( 'TEST' , '{"param": "with param"}' ) ) . toEqual ( "This is a test with param" ) ; expect ( translatePipe . transform ( 'TEST' , "{param: 'with param'}" ) ) . toEqual ( "This is a test with param" ) ; expect ( translatePipe . transform ( 'TEST' , "{'param' : 'with param'}" ) ) . toEqual ( "This is a test with param" ) ; } ) ; it ( 'should translate a string with object as multiple string parameters' , ( ) => { translate . setTranslation ( 'en' , { "TEST" : "This is a test {{param1}} {{param2}}" } ) ; translate . use ( 'en' ) ; expect ( translatePipe . transform ( 'TEST' , '{param1: "with param-1", param2: "and param-2"}' ) ) . toEqual ( "This is a test with param-1 and param-2" ) ; expect ( translatePipe . transform ( 'TEST' , '{"param1": "with param-1", "param2": "and param-2"}' ) ) . toEqual ( "This is a test with param-1 and param-2" ) ; expect ( translatePipe . transform ( 'TEST' , "{param1: 'with param-1', param2: 'and param-2'}" ) ) . toEqual ( "This is a test with param-1 and param-2" ) ; expect ( translatePipe . transform ( 'TEST' , "{'param1' : 'with param-1', 'param2': 'and param-2'}" ) ) . toEqual ( "This is a test with param-1 and param-2" ) ; } ) ; it ( 'should translate a string with object as nested string parameters' , ( ) => { translate . setTranslation ( 'en' , { "TEST" : "This is a test {{param.one}} {{param.two}}" } ) ; translate . use ( 'en' ) ; expect ( translatePipe . transform ( 'TEST' , '{param: {one: "with param-1", two: "and param-2"}}' ) ) . toEqual ( "This is a test with param-1 and param-2" ) ; expect ( translatePipe . transform ( 'TEST' , '{"param": {"one": "with param-1", "two": "and param-2"}}' ) ) . toEqual ( "This is a test with param-1 and param-2" ) ; expect ( translatePipe . transform ( 'TEST' , "{param: {one: 'with param-1', two: 'and param-2'}}" ) ) . toEqual ( "This is a test with param-1 and param-2" ) ; expect ( translatePipe . transform ( 'TEST' , "{'param' : {'one': 'with param-1', 'two': 'and param-2'}}" ) ) . toEqual ( "This is a test with param-1 and param-2" ) ; } ) ; it ( 'should update the value when the parameters change' , ( ) => { translate . setTranslation ( 'en' , { "TEST" : "This is a test {{param}}" } ) ; translate . use ( 'en' ) ; spyOn ( translatePipe , 'updateValue' ) . and . callThrough ( ) ; spyOn ( ref , 'markForCheck' ) . and . callThrough ( ) ; expect ( translatePipe . transform ( 'TEST' , { param : "with param" } ) ) . toEqual ( "This is a test with param" ) ; expect ( translatePipe . transform ( 'TEST' , { param : "with param" } ) ) . toEqual ( "This is a test with param" ) ; expect ( translatePipe . transform ( 'TEST' , { param : "with param2" } ) ) . toEqual ( "This is a test with param2" ) ; expect ( translatePipe . updateValue ) . toHaveBeenCalledTimes ( 2 ) ; expect ( ref . markForCheck ) . toHaveBeenCalledTimes ( 2 ) ; } ) ; it ( "should throw if you don't give an object parameter" , ( ) => { translate . setTranslation ( 'en' , { "TEST" : "This is a test {{param}}" } ) ; translate . use ( 'en' ) ; let param = 'param: "with param"' ; expect ( ( ) => { translatePipe . transform ( 'TEST' , param ) ; } ) . toThrowError ( `Wrong parameter in TranslatePipe. Expected a valid Object, received: ${ param }` ) ; } ) ; it ( "should return given falsey or non length query" , ( ) => { translate . setTranslation ( 'en' , { "TEST" : "This is a test" } ) ; translate . use ( 'en' ) ; expect ( translatePipe . transform ( null ) ) . toBeNull ( ) ; expect ( translatePipe . transform ( undefined ) ) . toBeUndefined ( ) ; expect ( translatePipe . transform ( 1234 as any ) ) . toBe ( 1234 ) ; } ) ; describe ( 'should update translations on lang change' , ( ) => { it ( 'with fake loader' , ( done ) => { translate . setTranslation ( 'en' , { "TEST" : "This is a test" } ) ; translate . setTranslation ( 'fr' , { "TEST" : "C'est un test" } ) ; translate . use ( 'en' ) ; expect ( translatePipe . transform ( 'TEST' ) ) . toEqual ( "This is a test" ) ; let subscription = translate . onLangChange . subscribe ( ( res ) => { expect ( res . lang ) . toEqual ( 'fr' ) ; expect ( translatePipe . transform ( 'TEST' ) ) . toEqual ( "C'est un test" ) ; subscription . unsubscribe ( ) ; done ( ) ; } ) ; translate . use ( 'fr' ) ; } ) ; it ( 'with file loader' , ( done ) => { translate . use ( 'en' ) ; expect ( translatePipe . transform ( 'TEST' ) ) . toEqual ( "This is a test" ) ; let subscription = translate . onLangChange . subscribe ( ( res ) => { setTimeout ( ( ) => { expect ( res . lang ) . toEqual ( 'fr' ) ; expect ( translatePipe . transform ( 'TEST' ) ) . toEqual ( "C'est un test" ) ; subscription . unsubscribe ( ) ; done ( ) ; } ) ; } ) ; translations = { "TEST" : "C'est un test" } ; translate . use ( 'fr' ) ; } ) ; it ( 'should detect changes with OnPush' , ( ) => { let fixture = ( < any > TestBed ) . createComponent ( App ) ; fixture . detectChanges ( ) ; expect ( fixture . debugElement . nativeElement . innerHTML ) . toEqual ( "TEST" ) ; translate . use ( 'en' ) ; fixture . detectChanges ( ) ; expect ( fixture . debugElement . nativeElement . innerHTML ) . toEqual ( "This is a test" ) ; } ) ; } ) ; describe ( 'should update translations on default lang change' , ( ) => { it ( 'with fake loader' , ( done ) => { translate . setTranslation ( 'en' , { "TEST" : "This is a test" } ) ; translate . setTranslation ( 'fr' , { "TEST" : "C'est un test" } ) ; translate . setDefaultLang ( 'en' ) ; expect ( translatePipe . transform ( 'TEST' ) ) . toEqual ( "This is a test" ) ; let subscription = translate . onDefaultLangChange . subscribe ( ( res ) => { expect ( res . lang ) . toEqual ( 'fr' ) ; expect ( translatePipe . transform ( 'TEST' ) ) . toEqual ( "C'est un test" ) ; subscription . unsubscribe ( ) ; done ( ) ; } ) ; translate . setDefaultLang ( 'fr' ) ; } ) ; it ( 'with file loader' , ( done ) => { translate . setDefaultLang ( 'en' ) ; expect ( translatePipe . transform ( 'TEST' ) ) . toEqual ( "This is a test" ) ; let subscription = translate . onDefaultLangChange . subscribe ( ( res ) => { setTimeout ( ( ) => { expect ( res . lang ) . toEqual ( 'fr' ) ; expect ( translatePipe . transform ( 'TEST' ) ) . toEqual ( "C'est un test" ) ; subscription . unsubscribe ( ) ; done ( ) ; } ) ; } ) ; translations = { "TEST" : "C'est un test" } ; translate . setDefaultLang ( 'fr' ) ; } ) ; it ( 'should detect changes with OnPush' , ( ) => { let fixture = ( < any > TestBed ) . createComponent ( App ) ; fixture . detectChanges ( ) ; expect ( fixture . debugElement . nativeElement . innerHTML ) . toEqual ( "TEST" ) ; translate . setDefaultLang ( 'en' ) ; fixture . detectChanges ( ) ; expect ( fixture . debugElement . nativeElement . innerHTML ) . toEqual ( "This is a test" ) ; } ) ; } ) ; } ) ;