'How can I test the rendering of an element using the date pipe in Angular 2?

I can't seem to test a component that uses a Date pipe in Angular 2 (using Karma through PhantomJS). When I try, I get ORIGINAL EXCEPTION: ReferenceError: Can't find variable: Intl

Here's my entire spec file:

import { provide, PLATFORM_PIPES } from '@angular/core';
import { DatePipe } from '@angular/common';
import { addProviders, async, inject } from '@angular/core/testing';

import { Post, PostComponent, PostHtmlComponent } from './';
import { usingComponentFixture } from '../../test-helpers';

describe('Component: Post', () => {
  beforeEach(() => {
    provide(PLATFORM_PIPES, {useValue: DatePipe, multi: true });
    addProviders([PostComponent, PostHtmlComponent, ]);
  });

  it('should render an h1 tag with text matching the post title', 
    usingComponentFixture(PostComponent, fixture => {
        let component = <PostComponent>fixture.componentInstance;
        let element = fixture.nativeElement;

        component.post = <Post>{ title: 'Hello', publishedOn: new Date('8/5/2016') };
        fixture.detectChanges();
        expect(element.querySelector('.blog-post-header h1').innerText).toBe('Hello');
    })
  );
});

And this is the component template:

 <div class="col-lg-8 col-md-7 col-sm-6">
   <h1>{{post.title}}</h1>
   <p class="lead">{{post.publishedOn | date:'fullDate'}}</p>
 </div>


Solution 1:[1]

I was able to resolve this issue. Here's what I had to do:

  1. npm install karma-intl-shim --save-dev
  2. Add 'intl-shim' to the frameworks collection in karma.conf.js
  3. Add the following to karma-test-shim.js (this is referenced in the files collection of karma.conf.js)

    require('karma-intl-shim');
    require('./en-us.js'); // copied from https://github.com/andyearnshaw/Intl.js/blob/master/locale-data/json/en-US.json
    Intl.__addLocaleData(enUsLocaleData);
    

Solution 2:[2]

Instead of mocking the DatePipe, you can use the transform method of DatePipe in typescript which is equivalent to the | operator in the HTML file

import {DatePipe} from '@angular/common';

let pipe = new DatePipe('en');

expect(page.myDate.nativeElement.innerHTML).toBe(pipe.transform(model.date, 'dd/MM/yyyy');

Solution 3:[3]

For tests I mock date pipe:

@Pipe({
    name: 'date',
    pure: false // required to update the value when the promise is resolved
})

export class MockedDatePipe implements PipeTransform {
    name: string = 'date';

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

Then when I configure testing module I inject it into declaration:

TestBed.configureTestingModule( {
    providers: [
        SelectionDispatcher,
        { provide: MyService, useClass: MockedMyServiceService }
    ],
    declarations: [ MyComponent, MockedTranslatePipe, MockedDatePipe ]
});

Solution 4:[4]

That worked for me:


import { DatePipe, registerLocaleData } from '@angular/common';
import localeDe from '@angular/common/locales/de';

registerLocaleData(localeDe);

//..
describe('My Test', () => {

let pipe = new DatePipe('de-DE');
    it('My Test-Case', () => {
        expect(page.myDate.nativeElement.innerHTML).toBe(pipe.transform(model.date);
    });
});

You must set the right locale.

That is a snippet from a Cypress-Test.

Solution 5:[5]

that's what worked for me:

import {DatePipe} from "@angular/common";
...
TestBed.configureTestingModule({
  ...
  providers: [DatePipe]
  ...
});

Solution 6:[6]

Expanding on other answers on here I was using the DatePipe in my component to produce a payload. I had the following setup.

Return the transform method on DatePipe in the mock, matching parameters used by the component i.e. ('YY'). Otherwise we will just get undefined as the value when testing.

.spec file

import { DatePipe } from '@angular/common';
.....
const mockDatePipe = {
  transform: jest.fn((val) => new DatePipe('en').transform(val, 'YY')),
};
.....
beforeEach(() => {
  component = new TestComponent(
    (mockDatePipe as unknown) as DatePipe,
    .....
  );
});

it('should return correct payload', () => {
  expect(component.getPayload(new Date('2022-02-02')).toEqual(
    {
      purchaseYear: '22',
    }
}

.ts file

public getPayload(date: new Date(), .....){
   return {
      purchaseYear: this.datePipe.transform(date, 'YY')
   };
);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Peter Pompeii
Solution 2 IAfanasov
Solution 3 Laxmikant Dange
Solution 4 Elio
Solution 5 Michel Dambros Figueiredo
Solution 6