Skip to content

Commit d9f292c

Browse files
committed
feat: allow creation of component via its type
1 parent b260887 commit d9f292c

File tree

5 files changed

+159
-53
lines changed

5 files changed

+159
-53
lines changed

projects/ngx-testing-library/package.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@
2323
"homepage": "https://github.com/tdeschryver/ngx-testing-library#readme",
2424
"peerDependencies": {
2525
"@angular/common": "^6.0.0-rc.0 || ^6.0.0",
26-
"@angular/core": "^6.0.0-rc.0 || ^6.0.0",
27-
"@angular/testing": "^6.0.0-rc.0 || ^6.0.0"
26+
"@angular/core": "^6.0.0-rc.0 || ^6.0.0"
2827
},
2928
"dependencies": {
3029
"dom-testing-library": "^2.5.0"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { Type } from '@angular/core';
2+
3+
export interface Result {
4+
container: any;
5+
get: (token: any, notFoundValue?: any) => any;
6+
getComponentInstance: <T>(selectorOrComponent: string | Type<T>) => T;
7+
debug: () => void;
8+
detectChanges: (checkNoChanges?: boolean) => void;
9+
fixture: any;
10+
queryByPlaceholderText: any;
11+
queryAllByPlaceholderText: any;
12+
getByPlaceholderText: any;
13+
getAllByPlaceholderText: any;
14+
queryByText: any;
15+
queryAllByText: any;
16+
getByText: any;
17+
getAllByText: any;
18+
queryByLabelText: any;
19+
queryAllByLabelText: any;
20+
getByLabelText: any;
21+
getAllByLabelText: any;
22+
queryByAltText: any;
23+
queryAllByAltText: any;
24+
getByAltText: any;
25+
getAllByAltText: any;
26+
queryByTestId: any;
27+
queryAllByTestId: any;
28+
getByTestId: any;
29+
getAllByTestId: any;
30+
queryByTitle: any;
31+
queryAllByTitle: any;
32+
getByTitle: any;
33+
getAllByTitle: any;
34+
queryByValue: any;
35+
queryAllByValue: any;
36+
getByValue: any;
37+
getAllByValue: any;
38+
}
39+
40+
export interface Options {
41+
detectChanges?: boolean;
42+
declarations: any[];
43+
providers?: any[];
44+
imports?: any[];
45+
schemas?: any[];
46+
}
47+
48+
export interface ComponentInput<T> {
49+
component: Type<T>;
50+
parameters?: Partial<T>;
51+
}

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

+36-50
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,62 @@
1-
import { Component, NgModule } from '@angular/core';
1+
import { Component, NgModule, Type } from '@angular/core';
22
import { TestBed, ComponentFixture } from '@angular/core/testing';
33
import { By } from '@angular/platform-browser';
44
import { getQueriesForElement, prettyDOM } from 'dom-testing-library';
55

6+
import { Options, Result, ComponentInput } from './models';
7+
68
@Component({ selector: 'test-component', template: '' })
79
class TestComponent {}
810

9-
export async function createComponent(
10-
template: string,
11-
{ detectChanges = true, declarations = [], providers = [], imports = [], schemas = [] } = {},
12-
): Promise<{
13-
container: any;
14-
get: (token: any, notFoundValue?: any) => any;
15-
getComponentInstance: <T>(selector: string) => T;
16-
debug: () => void;
17-
detectChanges: (checkNoChanges?: boolean) => void;
18-
fixture: any;
19-
queryByPlaceholderText: any;
20-
queryAllByPlaceholderText: any;
21-
getByPlaceholderText: any;
22-
getAllByPlaceholderText: any;
23-
queryByText: any;
24-
queryAllByText: any;
25-
getByText: any;
26-
getAllByText: any;
27-
queryByLabelText: any;
28-
queryAllByLabelText: any;
29-
getByLabelText: any;
30-
getAllByLabelText: any;
31-
queryByAltText: any;
32-
queryAllByAltText: any;
33-
getByAltText: any;
34-
getAllByAltText: any;
35-
queryByTestId: any;
36-
queryAllByTestId: any;
37-
getByTestId: any;
38-
getAllByTestId: any;
39-
queryByTitle: any;
40-
queryAllByTitle: any;
41-
getByTitle: any;
42-
getAllByTitle: any;
43-
queryByValue: any;
44-
queryAllByValue: any;
45-
getByValue: any;
46-
getAllByValue: any;
47-
}> {
11+
export async function createComponent(template: string, options: Options): Promise<Result>;
12+
export async function createComponent<T>(component: ComponentInput<T>, options: Options): Promise<Result>;
13+
export async function createComponent<T>(
14+
templateOrComponent: string | ComponentInput<T>,
15+
{ detectChanges = true, declarations = [], providers = [], imports = [], schemas = [] }: Options,
16+
): Promise<Result> {
17+
const isTemplate = typeof templateOrComponent === 'string';
18+
const extraDeclarations = isTemplate ? [TestComponent] : [];
19+
4820
TestBed.configureTestingModule({
49-
declarations: [TestComponent, ...declarations],
21+
declarations: [...declarations, ...extraDeclarations],
5022
providers: [...providers],
5123
imports: [...imports],
5224
schemas: [...schemas],
5325
});
5426

55-
TestBed.overrideComponent(TestComponent, {
56-
set: {
57-
template,
58-
},
59-
});
27+
if (isTemplate) {
28+
TestBed.overrideComponent(TestComponent, {
29+
set: {
30+
template: <string>templateOrComponent,
31+
},
32+
});
33+
}
6034

6135
await TestBed.compileComponents();
6236

63-
const fixture = TestBed.createComponent(TestComponent);
64-
if (detectChanges) {
65-
fixture.detectChanges();
37+
let fixture;
38+
if (isTemplate) {
39+
fixture = TestBed.createComponent(TestComponent);
40+
if (detectChanges) {
41+
fixture.detectChanges();
42+
}
43+
} else {
44+
const { component, parameters = [] } = <ComponentInput<T>>templateOrComponent;
45+
fixture = TestBed.createComponent(component);
46+
for (const key of Object.keys(parameters)) {
47+
fixture.componentInstance[key] = parameters[key];
48+
}
6649
}
6750

6851
// Currently this isn't perfect because the typings from dom-testing-library are for TS 2.8
6952
return {
7053
fixture,
7154
container: fixture.nativeElement,
7255
get: TestBed.get,
73-
getComponentInstance: <T>(selector: string) => fixture.debugElement.query(By.css(selector)).componentInstance as T,
56+
getComponentInstance: <C>(selectorOrComponent: string | C) =>
57+
typeof selectorOrComponent === 'string'
58+
? fixture.debugElement.query(By.css(selectorOrComponent)).componentInstance
59+
: fixture.componentInstance,
7460
debug: () => console.log(prettyDOM(fixture.nativeElement)),
7561
detectChanges: (checkNoChanges?: boolean) => fixture.detectChanges(checkNoChanges),
7662
...getQueriesForElement(fixture.nativeElement),

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

+1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
* Public API Surface of ngx-testing-library
33
*/
44

5+
export * from './lib/models';
56
export * from './lib/ngx-testing-library';
67
export { fireEvent } from 'dom-testing-library';

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

+70-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export class CounterComponent {
2020
}
2121

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

@@ -54,3 +54,72 @@ test('Counter actions - fireEvent', async () => {
5454
expect(getByText('Current Count: 12')).toBeTruthy();
5555
expect(getByTestId('count').textContent).toBe('Current Count: 12');
5656
});
57+
58+
test('Counter actions via component', async () => {
59+
const { getComponentInstance } = await createComponent<CounterComponent>(
60+
{
61+
component: CounterComponent,
62+
parameters: {
63+
counter: 10,
64+
},
65+
},
66+
{
67+
declarations: [CounterComponent],
68+
},
69+
);
70+
71+
const counter = getComponentInstance(CounterComponent);
72+
counter.increment();
73+
counter.increment();
74+
counter.increment();
75+
expect(counter.counter).toBe(13);
76+
77+
counter.decrement();
78+
expect(counter.counter).toBe(12);
79+
});
80+
81+
test('Counter actions via component without parameters', async () => {
82+
const { getComponentInstance } = await createComponent<CounterComponent>(
83+
{
84+
component: CounterComponent,
85+
},
86+
{
87+
declarations: [CounterComponent],
88+
},
89+
);
90+
91+
const counter = getComponentInstance(CounterComponent);
92+
counter.increment();
93+
counter.increment();
94+
counter.increment();
95+
expect(counter.counter).toBe(3);
96+
97+
counter.decrement();
98+
expect(counter.counter).toBe(2);
99+
});
100+
101+
test('Counter via component - test template', async () => {
102+
const { getByText, detectChanges, getByTestId } = await createComponent<CounterComponent>(
103+
{
104+
component: CounterComponent,
105+
parameters: {
106+
counter: 10,
107+
},
108+
},
109+
{
110+
declarations: [CounterComponent],
111+
},
112+
);
113+
114+
getByText('+').click();
115+
getByText('+').click();
116+
getByText('+').click();
117+
detectChanges();
118+
expect(getByText('Current Count: 13')).toBeTruthy();
119+
expect(getByTestId('count').textContent).toBe('Current Count: 13');
120+
121+
getByText('-').click();
122+
detectChanges();
123+
expect(getByText('Current Count: 12')).toBeTruthy();
124+
expect(getByTestId('count').textContent).toBe('Current Count: 12');
125+
});

0 commit comments

Comments
 (0)