Skip to content

Commit 4a76cf4

Browse files
committed
feat: expose fireEvent functions via createComponent in order to run detectChanges
drop detectChanges function in favor of the exposed events
1 parent cb1593f commit 4a76cf4

File tree

10 files changed

+107
-66
lines changed

10 files changed

+107
-66
lines changed

README.md

+4-16
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,9 @@ The second parameter in `createComponent` is the `options` parameter, which look
8686

8787
`schemas`: passed to the `TestBed`
8888

89-
The `createComponent` function returns an object consisting all of the query functions from [dom-testing-library][dom-testing-library] and adds the following properties:
89+
The `createComponent` function returns an object consisting all of the query functions from [dom-testing-library][dom-testing-library], all the event functions exposed from `fireEvent`, and adds the following properties:
90+
91+
> Every event runs `detectChanges` on the fixture.
9092
9193
#### `container: HTMLElement`
9294

@@ -98,10 +100,6 @@ All of the [dom-testing-library][dom-testing-library] query functions are binded
98100

99101
Prints out the container.
100102

101-
#### `detectChanges(checkNoChanges?: boolean) => void`
102-
103-
Runs `detectChanges` on the fixture.
104-
105103
#### `fixture: any`
106104

107105
The Angular fixture.
@@ -110,16 +108,6 @@ The Angular fixture.
110108

111109
Calls the the Angular `TestBed.get` function.
112110

113-
### `fireEvent`
114-
115-
Exposes the `fireEvent` from [dom-testing-library](dom-testing-library).
116-
117-
```ts
118-
import { fireEvent } from 'ngx-testing-library';
119-
120-
fireEvent.click(buttonNode);
121-
```
122-
123111
## Usage
124112

125113
You can find some examples in the [tests folder](https://github.com/tdeschryver/ngx-testing-library/tree/master/projects/ngx-testing-library/tests).
@@ -161,7 +149,7 @@ import { AppComponent } from './app.component';
161149
import { createComponent } from 'ngx-testing-library';
162150

163151
it(`should have as title 'my-awesome-app'`, async () => {
164-
const { detectChanges, getByText } = await createComponent('<app-root></app-root>', {
152+
const { getByText } = await createComponent('<app-root></app-root>', {
165153
declarations: [AppComponent],
166154
});
167155
expect(getByText('Welcome to my-awesome-app!')).toBeDefined();

projects/ngx-testing-library/src/lib/models.ts

+74-1
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ export interface Result<T> {
55
container: HTMLElement;
66
getFromTestBed: (token: any, notFoundValue?: any) => any;
77
debug: () => void;
8-
detectChanges: (checkNoChanges?: boolean) => void;
98
fixture: ComponentFixture<any>;
9+
10+
// Currently this isn't perfect because the typings from dom-testing-library are for TS 2.8
11+
// dom-testing-library queroes
1012
queryByPlaceholderText: any;
1113
queryAllByPlaceholderText: any;
1214
getByPlaceholderText: any;
@@ -35,6 +37,77 @@ export interface Result<T> {
3537
queryAllByValue: any;
3638
getByValue: any;
3739
getAllByValue: any;
40+
41+
// dom-testing-library fireEvents
42+
copy: (element: HTMLElement, options?: {}) => boolean;
43+
cut: (element: HTMLElement, options?: {}) => boolean;
44+
paste: (element: HTMLElement, options?: {}) => boolean;
45+
compositionEnd: (element: HTMLElement, options?: {}) => boolean;
46+
compositionStart: (element: HTMLElement, options?: {}) => boolean;
47+
compositionUpdate: (element: HTMLElement, options?: {}) => boolean;
48+
keyDown: (element: HTMLElement, options?: {}) => boolean;
49+
keyPress: (element: HTMLElement, options?: {}) => boolean;
50+
keyUp: (element: HTMLElement, options?: {}) => boolean;
51+
focus: (element: HTMLElement, options?: {}) => boolean;
52+
blur: (element: HTMLElement, options?: {}) => boolean;
53+
change: (element: HTMLElement, options?: {}) => boolean;
54+
input: (element: HTMLElement, options?: {}) => boolean;
55+
invalid: (element: HTMLElement, options?: {}) => boolean;
56+
submit: (element: HTMLElement, options?: {}) => boolean;
57+
click: (element: HTMLElement, options?: {}) => boolean;
58+
contextMenu: (element: HTMLElement, options?: {}) => boolean;
59+
dblClick: (element: HTMLElement, options?: {}) => boolean;
60+
drag: (element: HTMLElement, options?: {}) => boolean;
61+
dragEnd: (element: HTMLElement, options?: {}) => boolean;
62+
dragEnter: (element: HTMLElement, options?: {}) => boolean;
63+
dragExit: (element: HTMLElement, options?: {}) => boolean;
64+
dragLeave: (element: HTMLElement, options?: {}) => boolean;
65+
dragOver: (element: HTMLElement, options?: {}) => boolean;
66+
dragStart: (element: HTMLElement, options?: {}) => boolean;
67+
drop: (element: HTMLElement, options?: {}) => boolean;
68+
mouseDown: (element: HTMLElement, options?: {}) => boolean;
69+
mouseEnter: (element: HTMLElement, options?: {}) => boolean;
70+
mouseLeave: (element: HTMLElement, options?: {}) => boolean;
71+
mouseMove: (element: HTMLElement, options?: {}) => boolean;
72+
mouseOut: (element: HTMLElement, options?: {}) => boolean;
73+
mouseOver: (element: HTMLElement, options?: {}) => boolean;
74+
mouseUp: (element: HTMLElement, options?: {}) => boolean;
75+
select: (element: HTMLElement, options?: {}) => boolean;
76+
touchCancel: (element: HTMLElement, options?: {}) => boolean;
77+
touchEnd: (element: HTMLElement, options?: {}) => boolean;
78+
touchMove: (element: HTMLElement, options?: {}) => boolean;
79+
touchStart: (element: HTMLElement, options?: {}) => boolean;
80+
scroll: (element: HTMLElement, options?: {}) => boolean;
81+
wheel: (element: HTMLElement, options?: {}) => boolean;
82+
abort: (element: HTMLElement, options?: {}) => boolean;
83+
canPlay: (element: HTMLElement, options?: {}) => boolean;
84+
canPlayThrough: (element: HTMLElement, options?: {}) => boolean;
85+
durationChange: (element: HTMLElement, options?: {}) => boolean;
86+
emptied: (element: HTMLElement, options?: {}) => boolean;
87+
encrypted: (element: HTMLElement, options?: {}) => boolean;
88+
ended: (element: HTMLElement, options?: {}) => boolean;
89+
loadedData: (element: HTMLElement, options?: {}) => boolean;
90+
loadedMetadata: (element: HTMLElement, options?: {}) => boolean;
91+
loadStart: (element: HTMLElement, options?: {}) => boolean;
92+
pause: (element: HTMLElement, options?: {}) => boolean;
93+
play: (element: HTMLElement, options?: {}) => boolean;
94+
playing: (element: HTMLElement, options?: {}) => boolean;
95+
progress: (element: HTMLElement, options?: {}) => boolean;
96+
rateChange: (element: HTMLElement, options?: {}) => boolean;
97+
seeked: (element: HTMLElement, options?: {}) => boolean;
98+
seeking: (element: HTMLElement, options?: {}) => boolean;
99+
stalled: (element: HTMLElement, options?: {}) => boolean;
100+
suspend: (element: HTMLElement, options?: {}) => boolean;
101+
timeUpdate: (element: HTMLElement, options?: {}) => boolean;
102+
volumeChange: (element: HTMLElement, options?: {}) => boolean;
103+
waiting: (element: HTMLElement, options?: {}) => boolean;
104+
load: (element: HTMLElement, options?: {}) => boolean;
105+
error: (element: HTMLElement, options?: {}) => boolean;
106+
animationStart: (element: HTMLElement, options?: {}) => boolean;
107+
animationEnd: (element: HTMLElement, options?: {}) => boolean;
108+
animationIteration: (element: HTMLElement, options?: {}) => boolean;
109+
transitionEnd: (element: HTMLElement, options?: {}) => boolean;
110+
doubleClick: (element: HTMLElement, options?: {}) => boolean;
38111
}
39112

40113
export interface Options {

projects/ngx-testing-library/src/lib/ngx-testing-library.ts

+11-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Component, NgModule, Type } from '@angular/core';
22
import { TestBed, ComponentFixture } from '@angular/core/testing';
33
import { By } from '@angular/platform-browser';
4-
import { getQueriesForElement, prettyDOM } from 'dom-testing-library';
4+
import { getQueriesForElement, prettyDOM, fireEvent } from 'dom-testing-library';
55

66
import { Options, Result, ComponentInput } from './models';
77

@@ -34,13 +34,21 @@ export async function createComponent<T>(
3434
fixture.detectChanges();
3535
}
3636

37-
// Currently this isn't perfect because the typings from dom-testing-library are for TS 2.8
37+
const eventsWithChangeDetection = Object.keys(fireEvent).reduce((events, key) => {
38+
events[key] = (element: HTMLElement, options?: {}) => {
39+
const result = fireEvent[key](element, options);
40+
fixture.detectChanges();
41+
return result;
42+
};
43+
return events;
44+
}, {});
45+
3846
return {
3947
fixture,
4048
container: fixture.nativeElement,
4149
getFromTestBed: TestBed.get,
42-
detectChanges: (checkNoChanges?: boolean) => fixture.detectChanges(checkNoChanges),
4350
debug: () => console.log(prettyDOM(fixture.nativeElement)),
51+
...eventsWithChangeDetection,
4452
...getQueriesForElement(fixture.nativeElement),
4553
};
4654
}

projects/ngx-testing-library/src/public_api.ts

-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,3 @@
44

55
export * from './lib/models';
66
export * from './lib/ngx-testing-library';
7-
export { fireEvent } from 'dom-testing-library';

projects/ngx-testing-library/tests/counter/counter.spec.ts

+10-16
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Component, Input } from '@angular/core';
2-
import { createComponent, fireEvent } from '../../src/public_api';
2+
import { createComponent } from '../../src/public_api';
33

44
@Component({
55
selector: 'counter',
@@ -20,23 +20,21 @@ export class CounterComponent {
2020
}
2121

2222
test('Counter actions via template syntax', async () => {
23-
const { detectChanges, getByText, getByTestId } = await createComponent('<counter [counter]="10"></counter>', {
23+
const { getByText, getByTestId, click } = await createComponent('<counter [counter]="10"></counter>', {
2424
declarations: [CounterComponent],
2525
});
2626

27-
fireEvent.click(getByText('+'));
28-
detectChanges();
27+
click(getByText('+'));
2928
expect(getByText('Current Count: 11')).toBeTruthy();
3029
expect(getByTestId('count').textContent).toBe('Current Count: 11');
3130

32-
getByText('-').click();
33-
detectChanges();
31+
click(getByText('-'));
3432
expect(getByText('Current Count: 10')).toBeTruthy();
3533
expect(getByTestId('count').textContent).toBe('Current Count: 10');
3634
});
3735

3836
test('Counter actions via component syntax', async () => {
39-
const { getByText, detectChanges, getByTestId } = await createComponent(
37+
const { getByText, getByTestId, click } = await createComponent(
4038
{
4139
component: CounterComponent,
4240
parameters: {
@@ -48,19 +46,17 @@ test('Counter actions via component syntax', async () => {
4846
},
4947
);
5048

51-
getByText('+').click();
52-
detectChanges();
49+
click(getByText('+'));
5350
expect(getByText('Current Count: 11')).toBeTruthy();
5451
expect(getByTestId('count').textContent).toBe('Current Count: 11');
5552

56-
getByText('-').click();
57-
detectChanges();
53+
click(getByText('-'));
5854
expect(getByText('Current Count: 10')).toBeTruthy();
5955
expect(getByTestId('count').textContent).toBe('Current Count: 10');
6056
});
6157

6258
test('Counter actions via component syntax without parameters', async () => {
63-
const { getByText, detectChanges, getByTestId } = await createComponent(
59+
const { getByText, getByTestId, click } = await createComponent(
6460
{
6561
component: CounterComponent,
6662
},
@@ -69,13 +65,11 @@ test('Counter actions via component syntax without parameters', async () => {
6965
},
7066
);
7167

72-
getByText('+').click();
73-
detectChanges();
68+
click(getByText('+'));
7469
expect(getByText('Current Count: 1')).toBeTruthy();
7570
expect(getByTestId('count').textContent).toBe('Current Count: 1');
7671

77-
getByText('-').click();
78-
detectChanges();
72+
click(getByText('-'));
7973
expect(getByText('Current Count: 0')).toBeTruthy();
8074
expect(getByTestId('count').textContent).toBe('Current Count: 0');
8175
});

projects/ngx-testing-library/tests/debug.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Component, Input } from '@angular/core';
2-
import { createComponent, fireEvent } from '../src/public_api';
2+
import { createComponent } from '../src/public_api';
33

44
@Component({
55
selector: 'fixture',

projects/ngx-testing-library/tests/detectChanges.spec.ts

-21
This file was deleted.

projects/ngx-testing-library/tests/form/form.spec.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ReactiveFormsModule } from '@angular/forms';
2-
import { createComponent, fireEvent } from '../../src/public_api';
2+
import { createComponent } from '../../src/public_api';
33
import { LoginFormComponent } from './form.component';
44

55
test('login form submits using the component syntax', async () => {
@@ -8,7 +8,7 @@ test('login form submits using the component syntax', async () => {
88
emit: jest.fn(),
99
};
1010

11-
const { container, getByLabelText, getByText } = await createComponent(
11+
const { container, getByLabelText, getByText, input, submit } = await createComponent(
1212
{
1313
component: LoginFormComponent,
1414
parameters: {
@@ -27,12 +27,12 @@ test('login form submits using the component syntax', async () => {
2727
const formNode = container.querySelector('form');
2828

2929
usernameNode.value = fakeUser.username;
30-
fireEvent.input(usernameNode);
30+
input(usernameNode);
3131

3232
passwordNode.value = fakeUser.password;
33-
fireEvent.input(passwordNode);
33+
input(passwordNode);
3434

35-
fireEvent.submit(formNode);
35+
submit(formNode);
3636

3737
expect(handleLogin.emit).toHaveBeenCalledTimes(1);
3838
expect(handleLogin.emit).toHaveBeenCalledWith(fakeUser);

projects/ngx-testing-library/tests/getFromTestBed.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Component, Input, Injectable } from '@angular/core';
2-
import { createComponent, fireEvent } from '../src/public_api';
2+
import { createComponent } from '../src/public_api';
33

44
@Component({
55
selector: 'fixture',

src/app/app.component.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ test(`matches snapshot`, async () => {
99
});
1010

1111
test(`should have a title`, async () => {
12-
const { detectChanges, getByText } = await createComponent('<app-root></app-root>', {
12+
const { getByText } = await createComponent('<app-root></app-root>', {
1313
declarations: [AppComponent],
1414
});
1515
expect(getByText('Welcome to app!')).toBeDefined();

0 commit comments

Comments
 (0)