How to unit test a component with TranslateService and the translate pipe?

See original GitHub issue

I’m submitting a … (check one with “x”)

[ ] bug report => check the FAQ and search github for a similar issue or PR before submitting
[x] support request => check the FAQ and search github for a similar issue before submitting
[ ] feature request

Question How to test a component that uses TranslateService and the translate pipe?

I have a root module with:

TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: HttpLoaderFactory,
        deps: [HttpClient]
      }
    })

// AoT requires an exported function for factories
export function HttpLoaderFactory(httpClient: HttpClient) {
  return new TranslateHttpLoader(httpClient, "assets/i18n/", ".json");
}

also, inside my main component (with router-outlet) I have:

export class AppComponent {
  constructor(private translate: TranslateService) {
    translate.addLangs(["en", "it"]);
    translate.setDefaultLang('en');

    let browserLang = translate.getBrowserLang();
    translate.use(browserLang.match(/en|it/) ? browserLang : 'en');
  }
}

and finally, in my Component that I want to test I have this:

export class AboutComponent implements OnInit, OnDestroy {
  pageHeader: any = { title:'', strapline: '' };
  private i18nSubscription: Subscription;
  constructor(private translate: TranslateService) {}
  ngOnInit() {
    this.i18nSubscription = this.translate.get('ABOUT')
      .subscribe((res: any) => {
        this.pageHeader = {
          title: res['TITLE'],
          strapline: res['STRAPLINE']
        };
      });
  }

  ngOnDestroy() {
    if (this.i18nSubscription) {
      this.i18nSubscription.unsubscribe();
    }
  }
}

Now I want to test ‘AboutComponent’. But how?

At the moment I have this:

beforeEach( async(() => {
    TestBed.configureTestingModule({
      imports: [ TranslateModule.forRoot() ],
      declarations: [ AboutComponent, PageHeaderComponent ]
    });
    fixture = TestBed.createComponent(AboutComponent);
    comp = fixture.componentInstance;
    fixture.detectChanges();
    return fixture.whenStable().then(() => fixture.detectChanges());
  }));

Obviously I have to say to my test that I’m using 2 languages (en and it), but I don’t know which is the right way to do that.

At the moment both TemplateService and pipes aren’t working.

For instance, I created this to test the result of a traslate pipe:

    it('should display the about page', () => {
      const element: DebugElement = fixture.debugElement;
      fixture.detectChanges();
      const message: DebugElement[] = element.queryAll(By.css('small'));
      expect(message.length).toBe(2);      
     expect(message[0].nativeElement.textContent.trim()).toBe('');
      expect(message[1].nativeElement.textContent.trim()).toBe('Not implemented yet');
    });

and the result is this error:

Expected 'ABOUT.NOT_IMPLEMENTED' to be 'Not implemented yet'.

Thank u.

Please tell us about your environment:

  • ngx-translate version: 7.2.0

  • Angular version: 4.3.4

  • Browser: [all]

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:27
  • Comments:34

github_iconTop GitHub Comments

135reactions
pherriscommented, Oct 6, 2017

I’m just coming up to speed on this stack and was trying to wrap some tests around an Ionic component. I ran across this same problem and solved it by looking at translate.service.spec.ts (https://github.com/ngx-translate/core/blob/master/tests/translate.service.spec.ts) and the comments in this thread.

Essentially I had to define TranslateModule in imports and provide it a TranslateLoader called FakeLoader which wrapped my manually defined translations (it’d be nice to use the actual file here). Next I had to get the TranslateService instance and set the language to use in my test.

import { ComponentFixture, TestBed, getTestBed } from '@angular/core/testing';
import {Injector} from "@angular/core";
import { IonicModule, Platform, NavController } from 'ionic-angular';
import { TranslateModule, TranslateLoader, TranslateService } from '@ngx-translate/core';
import { By }              from '@angular/platform-browser';
import { DebugElement }    from '@angular/core';
import {Observable} from 'rxjs/Observable';

import { CardsPage } from './cards';

import {
  PlatformMock,
  NavMock,
} from '../../../test-config/mocks-ionic';

let translations: any = {"CARDS_TITLE": "This is a test"};

class FakeLoader implements TranslateLoader {
  getTranslation(lang: string): Observable<any> {
    return Observable.of(translations);
  }
}

describe('CardsPage (inline template)', () => {
  let comp:      CardsPage;
  let fixture:   ComponentFixture<CardsPage>;
  let de:        DebugElement;
  let el:        HTMLElement;
  let translate: TranslateService;
  let injector:  Injector;

  it('true is true', () => expect(true).toBe(true));

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [CardsPage],
      imports: [
        IonicModule.forRoot(CardsPage),
        TranslateModule.forRoot({
          loader: {provide: TranslateLoader, useClass: FakeLoader},
        })
      ],
      providers: [
        { provide: Platform, useClass: PlatformMock },
        { provide: NavController, useClass: NavMock },
      ]
    });
    injector = getTestBed();
    translate = injector.get(TranslateService);

    fixture = TestBed.createComponent(CardsPage);

    comp = fixture.componentInstance;

    de = fixture.debugElement.query(By.css('ion-title'));
    el = de.nativeElement;
  });

  it('should include the title of the cards page', () => {
    translate.use('en');
    fixture.detectChanges();
    expect(el.textContent).toContain('This is a test')
  });
});

This seems like a crazy amount of configuration and mocking for every component but I’m new to the Angular stack…

92reactions
AndreiShostikcommented, Jan 3, 2019

agree with @kbirger @ocombe, please take a look


import { Injectable, NgModule, Pipe, PipeTransform } from '@angular/core';
import { TranslateLoader, TranslateModule, TranslatePipe, TranslateService } from '@ngx-translate/core';
import { Observable, of } from 'rxjs';


const translations: any = {};

class FakeLoader implements TranslateLoader {
  getTranslation(lang: string): Observable<any> {
    return of(translations);
  }
}

@Pipe({
  name: 'translate'
})
export class TranslatePipeMock implements PipeTransform {
  public name = 'translate';

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

@Injectable()
export class TranslateServiceStub {
  public get<T>(key: T): Observable<T> {
    return of(key);
  }
}

@NgModule({
  declarations: [
    TranslatePipeMock
  ],
  providers: [
    { provide: TranslateService, useClass: TranslateServiceStub },
    { provide: TranslatePipe, useClass: TranslatePipeMock },
  ],
  imports: [
    TranslateModule.forRoot({
      loader: { provide: TranslateLoader, useClass: FakeLoader },
    })
  ],
  exports: [
    TranslatePipeMock,
    TranslateModule
  ]
})
export class TranslateTestingModule {

}

Read more comments on GitHub >

github_iconTop Results From Across the Web

angular - ngx-translate how to test components - Stack Overflow
I just need to start tests of my component without multiple errors about TranslateModule then TranslateService then TranslateStore ... until I ...
Read more >
Angular Unit Testing Tricks - iFiona
Then you can use the instant method in the typescript to get the translated string. To mock TranslateService in the component.spec.ts.
Read more >
Test ngx-translate easily using ngx-translate-testing - Medium
If you have used only TranslatePipe in html file and do not have to test any translations in the component, above configuration for...
Read more >
Testing Pipes – Testing Angular
How to test simple and complex, pure and impure Angular Pipes. ... The current language is stored in the TranslateService .
Read more >
Ngx-translate - Example - StackBlitz
testing ';. import {TranslateLoader, TranslateModule,. TranslateService} from "@ngx-translate/core";. import {AppComponent} from './app.component';.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found