ngx-translate how to test components
Asked Answered
Q

4

21

I've got an application which uses this library. How do I test components with it? I DO NOT WANT TO TEST THE LIBRARY. I just need to start tests of my component without multiple errors about TranslateModule then TranslateService then TranslateStore ... until I get an error when compiling.

Is there an easy way to just run my tests with this dependency?

Once more, I don't want to test this library (check whether the string is being translated) I need to run tests on components which rely on this library.

Qualify answered 19/11, 2018 at 8:10 Comment(0)
T
33

If you don't necessarily need the keys to be translated you can import the TranslateModule in your test like this:

beforeEach(async(() => {
  TestBed.configureTestingModule({
    declarations: [
      ...
    ],
    imports: [
      TranslateModule.forRoot(),
    ],
    providers: [
      ...
    ]
  })
  .compileComponents();
}));

It will only show the translation keys

Turaco answered 20/11, 2018 at 11:11 Comment(3)
Works fine in angular 8 + ngx-translate/core": "^11.0.1, thanksDrandell
Works fine with angular 11Disenable
Works also fine with angular 15Aspirator
M
24

For me the ngx-translate-testing worked well https://www.npmjs.com/package/ngx-translate-testing

first

import { TranslateTestingModule } from 'ngx-translate-testing';

then

  imports: [
    ...
    TranslateTestingModule.withTranslations({ en: require('src/assets/i18n/en.json'), de: require('src/assets/i18n/de.json') })
  ], 

then test

  it('should render german title', inject([TranslateService], (translateService: TranslateService) => {
    translateService.setDefaultLang('de');
    const fixture = TestBed.createComponent(AppComponent);
    fixture.detectChanges();
    const compiled = fixture.debugElement.nativeElement;
    expect(compiled.querySelector('.title').textContent).toContain('GERMANTITLE');
  }));
Matterhorn answered 17/12, 2019 at 14:29 Comment(1)
TS2307: Cannot find module 'ngx-translate-testing' or its corresponding type declarations.Anaplastic
M
19

(Tested with Angular 8.1.0 and ngx-translate 11.0.1)

A) If you use the translate pipe in your component, create a TranslateMockPipe and add it to the declarations array of your spec (as proposed in this issue).

translate-mock.pipe.ts

import {Pipe, PipeTransform} from '@angular/core';


@Pipe({
  name: "translate"
})
export class TranslateMockPipe implements PipeTransform {
  public name: string = "translate";

  public transform(query: string, ...args: any[]): any {
    return query;
  }
}

your-component.spec.ts

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ YourComponent, TranslateMockPipe ],
      imports: [
        ...
      ]
    })
    .compileComponents();
  }));

In one case for some reason I also had to do step B).

B) If you use the translate service directly in your component, e.g. this.translate.get('foo.bar'), you'll need to import the TranslateModule and use the ngx-translate TranslateFakeLoader as a loader for it.

your-component.spec.ts

import {TranslateFakeLoader, TranslateLoader, TranslateModule} from '@ngx-translate/core';
...
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ YourComponent ], // you may add TranslateMockPipe from step 1 here, too
      imports: [
        ...
        TranslateModule.forRoot({
          loader: {
            provide: TranslateLoader,
            useClass: TranslateFakeLoader
          }
        })
      ]
    })
    .compileComponents();
  }));

This way, you can use the ngx-translate built-in Stub instead of creating your own as proposed in issue (it didn't work for me either).

Myrna answered 22/8, 2019 at 7:44 Comment(1)
I did the above, but I get an error when testing the value of translate.instant(). The test is getting the id string passed to translate.instant(), not the value. Using ngx-translate version 15 on Angular 16.Emmie
Z
0

What I've done is to setup all my translation related configuration in a separate TranslationModule that I import to a SharedModule.

import { TranslateModule, TranslateLoader } from '@ngx-translate/core';

@NgModule({
  declarations: [],
  imports: [CommonModule,
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: IfYouHaveACustomFactory,
        deps: [HttpClient]
      }
    })],
  exports: [TranslateModule],
  providers: [],
})
export class TranslationModule {

}

This can then be exported to all components that import the SharedModule,

@NgModule({
  imports: [],
  exports: [TranslationModule, SomeOtherModule],
})
export class SharedModule { }

And in your spec-file you simply import the SharedModule in your TestBed.configureTestingModule() like

 beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        RouterTestingModule,
        SharedModule,
...

And tests for components that use the translation service or pipe should run fine!

Zoltai answered 19/11, 2018 at 8:29 Comment(2)
I like this idea, but it doesn't work for me. The translate-pipe does no longer translate anything when I remove the TranslateModule.forRoot({...}) stuff from my app.module.ts where I had it before. Just importing my shared-module does not see to be enough to make it work.Knowhow
And in the tests I get errors like NullInjectorError: StaticInjectorError(DynamicTestModule)[TranslatePipe -> ChangeDetectorRef]: StaticInjectorError(Platform: core)[TranslatePipe -> ChangeDetectorRef]: NullInjectorError: No provider for ChangeDetectorRef!Knowhow

© 2022 - 2024 — McMap. All rights reserved.