2.0.0 • Published 3 years ago

@terminus/fe-testing v2.0.0

Weekly downloads
28
License
MIT
Repository
github
Last release
3 years ago

CI/CD Status MIT License
NPM version Library size

A collection of helpers to facilitate testing UI components.

Import from: @terminus/fe-testing

Table of Contents

Installation

yarn add @terminus/fe-testing -D
yarn add @terminus/fe-utilities rxjs date-fns @angular/{forms,platform-browser}

Mocks

ChangeDetectorRefMock

A mock of the Angular ChangeDetectorRefMock class.

// my.component.ts
import { ChangeDetectorRef } from '@angular/core';

@Component({...})
export class MyComponent {
  constructor(private changeDetectorRef: ChangeDetectorRef) {}
}
// my.component.spec.ts
import { ChangeDetectorRefMock } from '@terminus/fe-testing';
import { MyComponent } from './my.component';

let component: MyComponent;

beforeEach(() => {
  component = new MyComponent(
    new ChangeDetectorRefMock(),
  );
});

ElementRefMock

A mock of the Angular ElementRef class.

// my.component.ts
import { ElementRef } from '@angular/core';

@Component({...})
export class MyComponent {
  constructor(private elementRef: ElementRef) {}
}
// my.component.spec.ts
import { ElementRefMock } from '@terminus/fe-testing';
import { MyComponent } from './my.component';

let component: MyComponent;

beforeEach(() => {
  component = new MyComponent(
    new ElementRefMock(),
  );
});

rendererMock

A mock of the Angular Renderer with properties initialized with noop function.

// my.component.ts
import { Renderer } from '@angular/core';

@Component({...})
export class MyComponent {
  constructor(private renderer: Renderer) {}
}
// my.component.spec.ts
import { rendererMock } from '@terminus/fe-testing';

beforeEach(async(() => {
  TestBed.configureTestingModule({
    imports: [MyNeededModule],
    providers: [
      // rendererMock is a value:
      {
        provide: Renderer,
        useValue: rendererMock,
      },
    ],
    declarations: [MyComponent],
  }).compileComponents();
}));

renderer2Mock

A mock of the Angular Renderer2 with all properties stubbed.

// my.component.ts
import { Renderer2 } from '@angular/core';

@Component({...})
export class MyComponent {
  constructor(private renderer2: Renderer2) {}
}
// my.component.spec.ts
import { Renderer2Mock } from '@terminus/fe-testing';

beforeEach(async(() => {
  TestBed.configureTestingModule({
    ...
    providers: [
      // Renderer2Mock is a class:
      {
        provide: Renderer,
        useClass: Renderer2Mock,
      },
    ],
    declarations: [MyComponent],
  }).compileComponents();
}));

Or for newed classes:

import { Renderer2Mock } from '@terminus/fe-testing';

let component: MyComponent;

beforeEach(() => {
  component = new MyComponent(
    new Renderer2Mock(),
  );
});

TokenEscalatorMock

TODO

TokenExtractorMock

TODO

TsDocumentServiceMock

// my.component.ts
import { TsDocumentService } from '@terminus/fe-utilities';

@Component({...})
export class MyComponent {
  constructor(
    private documentService: TsDocumentService,
  ) {}
}
// my.component.spec.ts
import { TsDocumentServiceMock } from '@terminus/fe-testing';
import { MyComponent } from './my.component';

let component: MyComponent;

beforeEach(() => {
  component = new MyComponent(
    new TsDocumentServiceMock(),
  );
});

TsWindowServiceMock

// my.component.ts
import { TsWindowService } from '@terminus/fe-utilities';

@Component({...})
export class MyComponent {
  constructor(
    private windowService: TsWindowService,
  ) {}
}
// my.component.spec.ts
import { TsWindowServiceMock } from '@terminus/fe-testing';
import { MyComponent } from './my.component';

let component: MyComponent;

beforeEach(() => {
  component = new MyComponent(
    new TsWindowServiceMock(),
  );
});

Events

Creating Events

createFakeEvent

Creates a fake event object with any desired event type.

import { createFakeEvent } from '@terminus/fe-testing';

const focusEvent = createFakeEvent('focus');
ParamTypeDefault
typestring
canBubblebooleantrue
cancelablebooleantrue

createKeyboardEvent

Creates a browser KeyboardEvent from an element.

import { KEYCODES } from '@terminus/fe-utilities';
import { createKeyboardEvent } from '@terminus/fe-testing';

const keyboardEvent = createKeyboardEvent('keydown', KEYCODES.ENTER.keyCode, myInputNativeElement);
ParamTypeDefault
typestring
keyCodenumber
target?Element
key?string

createMouseEvent

Creates a browser MouseEvent with the specified options.

import { createMouseEvent } from '@terminus/fe-testing';

const mouseEvent = createMouseEvent('click');
const mouseEventAtLocation = createMouseEvent('click', 212, 433);
ParamTypeDefault
typestring
xnumber0
ynumber0

createTouchEvent

Creates a browser TouchEvent with the specified pointer coordinates.

import { createTouchEvent } from '@terminus/fe-testing';

const touchEvent = createTouchEvent('touchstart');
const touchEventAtLocation = createTouchEvent('touchstart', 212, 433);
ParamTypeDefault
typestring
pageXnumber0
pageYnumber0

Dispatching Events

dispatchEvent

Utility to dispatch any event on a Node.

import { dispatchEvent } from '@terminus/fe-testing';

dispatchEvent(myNativeElement, 'blur');
ParamTypeDefault
nodeNode|Window
eventEvent

dispatchFakeEvent

Shorthand to dispatch a fake event on a specified node.

import { dispatchFakeEvent } from '@terminus/fe-testing';

dispatchFakeEvent(myNativeElement, 'mousedown');
ParamTypeDefault
nodeNode|Window
typestring
canBubble?boolean

dispatchKeyboardEvent

Shorthand to dispatch a keyboard event with a specified key code.

import { dispatchKeyboardEvent } from '@terminus/fe-testing';

dispatchKeyboardEvent(myNativeElement, 'keyup', ENTER);
ParamTypeDefault
nodeNode
typestring
keyCodenumber
target?Element

dispatchMouseEvent

Shorthand to dispatch a mouse event on the specified coordinates.

import { dispatchMouseEvent } from '@terminus/fe-testing';

dispatchMouseEvent(myNativeElement, 'mousedown');
ParamTypeDefault
nodeNode
typestring
xnumber0
ynumber0
eventMouseEventcreateMouseEvent(type, x, y)

dispatchTouchEvent

Shorthand to dispatch a touch event on the specified coordinates.

import { dispatchTouchEvent } from '@terminus/fe-testing';

dispatchTouchEvent(myNativeElement, 'touchstart');
ParamTypeDefault
nodeNode
typestring
xnumber0
ynumber0

Angular Test Helpers

configureTestBedWhitespace

By default, Angular does not strip out any white space when compiling templates for the TestBed. This can make snapshot testing more difficult to visually parse. This helper will configure the TestBed and compile the components with extra white space stripped.

import {
  ConfigureTestBedFn,
  configureTestBed,
} from '@terminus/fe-testing';

describe(`MyComponentSnapshot`, () => {
  let fixture: ComponentFixture<MyComponent>;
  let component: MyComponent;

  beforeEach(async(() => {
    // Define your configuration just as you would using the standard TestBed,
    // except now it's inside a `ConfigureTestBedFn` function:
    const configure: ConfigureTestBedFn = (testBed) => {
      testBed.configureTestingModule({
        ...
        declarations: [
          MyComponent,
        ],
        ...
      });
    };

    // Pass the configuration in and receive a TestBed instance:
    configureTestBedWhitespace(configure).then((testBed) => {
      fixture = testBed.createComponent(MyComponent);
      component = fixture.componentInstance;
      fixture.detectChanges();
    });

  }));

  test(`should match the snapshot`, () => {
    expect(fixture).toMatchSnapshot();
  });
});

configureTestBedWithoutReset

By default, Angular resets the TestBed between each test. While this can be useful if components or services have shared state or create side-effects, it can slow down tests quite a bit. When the TestBed doesn't need to be reset, we can improve testing time by disabling this reset functionality.

NOTE: This function makes use of beforeAll and afterAll so it must be called inside your outermost describe block.

import { TestModuleMetadata } from '@angular/core/testing';
import { configureTestBedWithoutReset } from '@terminus/fe-testing';

describe(`MyComponent`, () => {
  let fixture: ComponentFixture<MyComponent>;
  let component: MyComponent;
  const moduleDefinition: TestModuleMetadata = {
    imports: [
      ...
    ],
    declarations: [
      ...
    ],
  };

  setUpTestBed(moduleDefinition);

  test(`should...`, () => {
    ...
  });
});

createComponent

Helper function to quickly generate a TestBed fixture with a single component.

import { createComponent } from '@terminus/fe-testing';

@Component({template: ``})
export class TestComponent {
  foo = 'bar';
}

test(`should do something`, () => {
  const fixture = createComponent<TestComponent>(TestComponent);

  expect(fixture.componentInstance.foo).toEqual('bar');
});

expectNativeEl

Reusable expect statement to check for the nativeElement.

import { expectNativeEl } from '@terminus/fe-testing';

let fixture: ComponentFixture<TestHostComponent>;
let testHost: TestHostComponent;

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

  fixture = TestBed.createComponent(TestHostComponent);
  testHost = fixture.componentInstance;
  fixture.detectChanges();
}));

test(`should have a native element`, () => {
  expectNativeEl(fixture).toBeTruthy();
})

getChildComponentInstanceFromFixture

Returns a component instance from a TestBed fixture:

import { getChildComponentInstanceFromFixture } from '@terminus/fe-testing';
import { Component } from '@angular/core';
import {
  async,
  ComponentFixture,
  TestBed,
} from '@angular/core/testing';

// The component we will want a reference too:
@Component({
  selector: `my-test`,
  template: `<h1>foo</h1>`,
})
class TestComponent {
  myString = 'foo';
}

// The parent component (fixture):
@Component({
  template: `<my-test></my-test>`,
})
class TestHostComponent {}

describe(`my test`, () => {
  let fixture: ComponentFixture<TestHostComponent>;

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [
        TestComponent,
        TestHostComponent,
      ],
    });

    // Create the fixture:
    fixture = TestBed.createComponent(TestHostComponent);
  });

  test(`should ...`, () => {
    // Get the instance:
    const instance: TestComponent = getChildComponentInstanceFromFixture(fixture, TestComponent);
    console.log(instance.myString); // logs out: `foo`
  });
});

getDomAttribute

A helper to return the value of a DOM attribute.

import { getDomAttribute } from '@terminus/fe-testing';

getDomAttribute(myElement, 'aria-label');

queryFor

Helper to query a fixture for a selector.

import { queryFor } from '@terminus/fe-testing';

let fixture: ComponentFixture<TestHostComponent>;
let testHost: TestHostComponent;
let nestedElement;

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

  fixture = TestBed.createComponent(TestHostComponent);
  testHost = fixture.componentInstance;
  fixture.detectChanges();

  nestedElement = queryFor(fixture, '.my-class');
}));

wrappedErrorMessage

Gets a RegExp used to detect an Angular wrapped error message. This allows testing for specific thrown errors in tests.

import { wrappedErrorMessage } from '@terminus/fe-testing';

expect(myFunc).toThrowError(wrappedErrorMessage(mySpecificError()));

See https://github.com/angular/angular/issues/8348 for more information.

typeInElement

Focuses an input, sets it's value and dispatches the input event, simulating user typing.

import { typeInElement } from '@terminus/fe-testing';

typeInElement('test@test.com', myEmailInputElement);
2.0.0

3 years ago

1.2.0

4 years ago

1.1.1

4 years ago

1.1.0

4 years ago

0.3.0

4 years ago

0.2.0

4 years ago

0.1.1

4 years ago

0.1.0

4 years ago

0.0.1

4 years ago