Skip to content

Commit c76209f

Browse files
committed
fix: better docs with current features
adding more dynamic interface for debug nodes
1 parent 3872591 commit c76209f

File tree

11 files changed

+150
-148
lines changed

11 files changed

+150
-148
lines changed

README.md

Lines changed: 67 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ Or you could use this to mock them out and have the ability to assert on their i
2727

2828
```typescript
2929
import { ComponentFixture, TestBed } from '@angular/core/testing';
30-
import { By } from '@angular/platform-browser';
31-
import { MockComponent, MockedComponent, MockRender } from 'ng-mocks';
30+
import { MockComponent, MockedComponent, MockHelper, MockRender } from 'ng-mocks';
31+
3232
import { DependencyComponent } from './dependency.component';
3333
import { TestedComponent } from './tested.component';
3434

@@ -47,8 +47,11 @@ describe('MockComponent', () => {
4747
});
4848

4949
it('should send the correct value to the dependency component input', () => {
50-
const mockedComponent = fixture.debugElement.query(By.css('dependency-component-selector'))
51-
.componentInstance as DependencyComponent; // casting to retain type safety
50+
// the same as fixture.debugElement.query(By.css('dependency-component-selector')).componentInstance
51+
const mockedComponent = MockHelper.findOrFail<DependencyComponent>(
52+
fixture.debugElement,
53+
'dependency-component-selector'
54+
).componentInstance;
5255

5356
// let's pretend Dependency Component (unmocked) has 'someInput' as an input
5457
// the input value will be passed into the mocked component so you can assert on it
@@ -61,8 +64,7 @@ describe('MockComponent', () => {
6164

6265
it('should do something when the dependency component emits on its output', () => {
6366
spyOn(component, 'trigger');
64-
const mockedComponent = fixture.debugElement.query(By.directive(DependencyComponent))
65-
.componentInstance as DependencyComponent; // casting to retain type safety
67+
const mockedComponent = MockHelper.findOrFail(fixture.debugElement, DependencyComponent).componentInstance;
6668

6769
// again, let's pretend DependencyComponent has an output called 'someOutput'
6870
// emit on the output that MockComponent setup when generating the mock of Dependency Component
@@ -78,36 +80,37 @@ describe('MockComponent', () => {
7880
});
7981

8082
it('should render something inside of the dependency component', () => {
81-
const localFixture = MockRender(`
83+
const localFixture = MockRender<DependencyComponent>(`
8284
<dependency-component-selector>
8385
<p>inside content</p>
8486
</dependency-component-selector>
8587
`);
88+
8689
// because component does not have any @ContentChild we can access html directly.
8790
// assert on some side effect
88-
const mockedNgContent = localFixture.debugElement.query(By.directive(DependencyComponent)).nativeElement.innerHTML;
91+
const mockedNgContent = localFixture.point.nativeElement.innerHTML;
8992
expect(mockedNgContent).toContain('<p>inside content</p>');
9093
});
9194

9295
it('should render something inside of the dependency component', () => {
93-
const localFixture = MockRender(`
96+
const localFixture = MockRender<MockedComponent<DependencyComponent>>(`
9497
<dependency-component-selector>
9598
<ng-template #something><p>inside template</p></ng-template>
9699
<p>inside content</p>
97100
</dependency-component-selector>
98101
`);
99102

100103
// injected ng-content says as it was.
101-
const mockedNgContent = localFixture.debugElement.query(By.directive(DependencyComponent)).nativeElement.innerHTML;
104+
const mockedNgContent = localFixture.point.nativeElement.innerHTML;
102105
expect(mockedNgContent).toContain('<p>inside content</p>');
103106

104107
// because component does have @ContentChild we need to render them first with proper context.
105-
const mockedElement = localFixture.debugElement.query(By.directive(DependencyComponent));
106-
const mockedComponent: MockedComponent<DependencyComponent> = mockedElement.componentInstance;
108+
const mockedComponent = localFixture.point.componentInstance;
107109
mockedComponent.__render('something');
108110
localFixture.detectChanges();
109111

110-
const mockedNgTemplate = mockedElement.query(By.css('[data-key="something"]')).nativeElement.innerHTML;
112+
const mockedNgTemplate = MockHelper.findOrFail(localFixture.debugElement, '[data-key="something"]').nativeElement
113+
.innerHTML;
111114
expect(mockedNgTemplate).toContain('<p>inside template</p>');
112115
});
113116
});
@@ -124,8 +127,8 @@ describe('MockComponent', () => {
124127

125128
```typescript
126129
import { ComponentFixture, TestBed } from '@angular/core/testing';
127-
import { By } from '@angular/platform-browser';
128130
import { MockDirective, MockHelper } from 'ng-mocks';
131+
129132
import { DependencyDirective } from './dependency.directive';
130133
import { TestedComponent } from './tested.component';
131134

@@ -149,14 +152,12 @@ describe('MockDirective', () => {
149152

150153
// let's pretend Dependency Directive (unmocked) has 'someInput' as an input
151154
// the input value will be passed into the mocked directive so you can assert on it
152-
const mockedDirectiveInstance = MockHelper.getDirective(
153-
fixture.debugElement.query(By.css('span')),
155+
const mockedDirectiveInstance = MockHelper.getDirectiveOrFail(
156+
MockHelper.findOrFail(fixture.debugElement, 'span'),
154157
DependencyDirective
155158
);
156-
expect(mockedDirectiveInstance).toBeTruthy();
157-
if (mockedDirectiveInstance) {
158-
expect(mockedDirectiveInstance.someInput).toEqual('foo');
159-
}
159+
160+
expect(mockedDirectiveInstance.someInput).toEqual('foo');
160161
// assert on some side effect
161162
});
162163

@@ -166,16 +167,13 @@ describe('MockDirective', () => {
166167

167168
// again, let's pretend DependencyDirective has an output called 'someOutput'
168169
// emit on the output that MockDirective setup when generating the mock of Dependency Directive
169-
const mockedDirectiveInstance = MockHelper.getDirective(
170-
fixture.debugElement.query(By.css('span')),
170+
const mockedDirectiveInstance = MockHelper.getDirectiveOrFail(
171+
MockHelper.findOrFail(fixture.debugElement, 'span'),
171172
DependencyDirective
172173
);
173-
expect(mockedDirectiveInstance).toBeTruthy();
174-
if (mockedDirectiveInstance) {
175-
mockedDirectiveInstance.someOutput.emit({
176-
payload: 'foo',
177-
}); // if you casted mockedDirective as the original component type then this is type safe
178-
}
174+
mockedDirectiveInstance.someOutput.emit({
175+
payload: 'foo',
176+
}); // if you casted mockedDirective as the original component type then this is type safe
179177
// assert on some side effect
180178
});
181179
});
@@ -189,6 +187,7 @@ when assertions should be done on its nested elements.
189187
```typescript
190188
import { ComponentFixture, TestBed } from '@angular/core/testing';
191189
import { MockDirective, MockedDirective, MockHelper } from 'ng-mocks';
190+
192191
import { DependencyDirective } from './dependency.directive';
193192
import { TestedComponent } from './tested.component';
194193

@@ -213,7 +212,7 @@ describe('MockDirective', () => {
213212
// IMPORTANT: by default structural directives aren't rendered.
214213
// Because we can't automatically detect when and with which context they should be rendered.
215214
// Usually developer knows context and can render it manually with proper setup.
216-
const mockedDirectiveInstance = MockHelper.findDirective(
215+
const mockedDirectiveInstance = MockHelper.findDirectiveOrFail(
217216
fixture.debugElement,
218217
DependencyDirective
219218
) as MockedDirective<DependencyDirective>;
@@ -227,10 +226,7 @@ describe('MockDirective', () => {
227226

228227
// let's pretend Dependency Directive (unmocked) has 'someInput' as an input
229228
// the input value will be passed into the mocked directive so you can assert on it
230-
expect(mockedDirectiveInstance).toBeTruthy();
231-
if (mockedDirectiveInstance) {
232-
expect(mockedDirectiveInstance.someInput).toEqual('foo');
233-
}
229+
expect(mockedDirectiveInstance.someInput).toEqual('foo');
234230
// assert on some side effect
235231
});
236232
});
@@ -248,8 +244,8 @@ Personally, I found the best thing to do for assertions is to override the trans
248244

249245
```typescript
250246
import { ComponentFixture, TestBed } from '@angular/core/testing';
251-
import { By } from '@angular/platform-browser';
252-
import { MockPipe } from 'ng-mocks';
247+
import { MockHelper, MockPipe } from 'ng-mocks';
248+
253249
import { DependencyPipe } from './dependency.pipe';
254250
import { TestedComponent } from './tested.component';
255251

@@ -262,7 +258,7 @@ describe('MockPipe', () => {
262258
TestedComponent,
263259

264260
// alternatively you can use MockPipes to mock multiple but you lose the ability to override
265-
MockPipe(DependencyPipe, (...args) => JSON.stringify(args)),
261+
MockPipe(DependencyPipe, (...args: string[]) => JSON.stringify(args)),
266262
],
267263
});
268264

@@ -272,7 +268,8 @@ describe('MockPipe', () => {
272268

273269
describe('with transform override', () => {
274270
it('should return the result of the provided transform function', () => {
275-
expect(fixture.debugElement.query(By.css('span')).nativeElement.innerHTML).toEqual('["foo"]');
271+
const pipeElement = MockHelper.findOrFail(fixture.debugElement, 'span');
272+
expect(pipeElement.nativeElement.innerHTML).toEqual('["foo"]');
276273
});
277274
});
278275
});
@@ -289,8 +286,8 @@ describe('MockPipe', () => {
289286
```typescript
290287
import { ComponentFixture, TestBed } from '@angular/core/testing';
291288
import { ReactiveFormsModule } from '@angular/forms';
292-
import { By } from '@angular/platform-browser';
293-
import { MockComponent, MockedComponent } from 'ng-mocks';
289+
import { MockComponent, MockedComponent, MockHelper } from 'ng-mocks';
290+
294291
import { DependencyComponent } from './dependency.component';
295292
import { TestedComponent } from './tested.component';
296293

@@ -310,8 +307,10 @@ describe('MockReactiveForms', () => {
310307
});
311308

312309
it('should send the correct value to the dependency component input', () => {
313-
const mockedReactiveFormComponent = fixture.debugElement.query(By.css('dependency-component-selector'))
314-
.componentInstance as MockedComponent<DependencyComponent>; // casting to retain type safety
310+
const mockedReactiveFormComponent = MockHelper.findOrFail<MockedComponent<DependencyComponent>>(
311+
fixture.debugElement,
312+
'dependency-component-selector'
313+
).componentInstance;
315314

316315
mockedReactiveFormComponent.__simulateChange('foo');
317316
expect(component.formControl.value).toBe('foo');
@@ -336,6 +335,7 @@ For providers I typically will use TestBed.get(SomeProvider) and extend it using
336335
```typescript
337336
import { ComponentFixture, TestBed } from '@angular/core/testing';
338337
import { MockModule } from 'ng-mocks';
338+
339339
import { DependencyModule } from './dependency.module';
340340
import { TestedComponent } from './tested.component';
341341

@@ -379,7 +379,6 @@ It is useful if you want to mock system tokens / services such as APP_INITIALIZE
379379

380380
```typescript
381381
import { TestBed } from '@angular/core/testing';
382-
import { By } from '@angular/platform-browser';
383382
import { MockModule, MockRender } from 'ng-mocks';
384383

385384
import { DependencyModule } from './dependency.module';
@@ -411,8 +410,7 @@ describe('MockRender', () => {
411410
);
412411

413412
// assert on some side effect
414-
const componentInstance = fixture.debugElement.query(By.directive(TestedComponent))
415-
.componentInstance as TestedComponent;
413+
const componentInstance = fixture.point.componentInstance as TestedComponent;
416414
componentInstance.trigger.emit('foo1');
417415
expect(componentInstance.value1).toEqual('something1');
418416
expect(componentInstance.value2).toEqual('check');
@@ -504,28 +502,31 @@ const spySet: Spy = MockHelper.mockService(instance, propertyName, 'set');
504502

505503
```typescript
506504
// The example below uses auto spy.
507-
it('mocks getters, setters and methods in a way that jasmine can mock them w/o an issue', () => {
508-
const mock: GetterSetterMethodHuetod = MockService(GetterSetterMethodHuetod);
509-
expect(mock).toBeDefined();
510-
511-
// Creating a mock on the getter.
512-
MockHelper.mockService<Spy>(mock, 'name', 'get').and.returnValue('mock');
513-
expect(mock.name).toEqual('mock');
514-
515-
// Creating a mock on the setter.
516-
MockHelper.mockService(mock, 'name', 'set');
517-
mock.name = 'mock';
518-
expect(MockHelper.mockService(mock, 'name', 'set')).toHaveBeenCalledWith('mock');
519-
520-
// Creating a mock on the method.
521-
MockHelper.mockService<Spy>(mock, 'nameMethod').and.returnValue('mock');
522-
expect(mock.nameMethod('mock')).toEqual('mock');
523-
expect(MockHelper.mockService(mock, 'nameMethod')).toHaveBeenCalledWith('mock');
524-
525-
// Creating a mock on the method that doesn't exist.
526-
MockHelper.mockService<Spy>(mock, 'fakeMethod').and.returnValue('mock');
527-
expect((mock as any).fakeMethod('mock')).toEqual('mock');
528-
expect(MockHelper.mockService(mock, 'fakeMethod')).toHaveBeenCalledWith('mock');
505+
describe('MockService', () => {
506+
it('mocks getters, setters and methods in a way that jasmine can mock them w/o an issue', () => {
507+
// please note that auto spy should be enabled for this test.
508+
const mock: GetterSetterMethodHuetod = MockService(GetterSetterMethodHuetod);
509+
expect(mock).toBeDefined();
510+
511+
// Creating a mock on the getter.
512+
MockHelper.mockService<jasmine.Spy>(mock, 'name', 'get').and.returnValue('mock');
513+
expect(mock.name).toEqual('mock');
514+
515+
// Creating a mock on the setter.
516+
MockHelper.mockService(mock, 'name', 'set');
517+
mock.name = 'mock';
518+
expect(MockHelper.mockService(mock, 'name', 'set')).toHaveBeenCalledWith('mock');
519+
520+
// Creating a mock on the method.
521+
MockHelper.mockService<jasmine.Spy>(mock, 'nameMethod').and.returnValue('mock');
522+
expect(mock.nameMethod('mock')).toEqual('mock');
523+
expect(MockHelper.mockService(mock, 'nameMethod')).toHaveBeenCalledWith('mock');
524+
525+
// Creating a mock on the method that doesn't exist.
526+
MockHelper.mockService<jasmine.Spy>(mock, 'fakeMethod').and.returnValue('mock');
527+
expect((mock as any).fakeMethod('mock')).toEqual('mock');
528+
expect(MockHelper.mockService(mock, 'fakeMethod')).toHaveBeenCalledWith('mock');
529+
});
529530
});
530531
```
531532

examples/MockComponent/MockComponent.spec.ts

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ComponentFixture, TestBed } from '@angular/core/testing';
2-
import { By } from '@angular/platform-browser';
3-
import { MockComponent, MockedComponent, MockRender } from 'ng-mocks';
2+
import { MockComponent, MockedComponent, MockHelper, MockRender } from 'ng-mocks';
3+
44
import { DependencyComponent } from './dependency.component';
55
import { TestedComponent } from './tested.component';
66

@@ -19,8 +19,11 @@ describe('MockComponent', () => {
1919
});
2020

2121
it('should send the correct value to the dependency component input', () => {
22-
const mockedComponent = fixture.debugElement.query(By.css('dependency-component-selector'))
23-
.componentInstance as DependencyComponent; // casting to retain type safety
22+
// the same as fixture.debugElement.query(By.css('dependency-component-selector')).componentInstance
23+
const mockedComponent = MockHelper.findOrFail<DependencyComponent>(
24+
fixture.debugElement,
25+
'dependency-component-selector'
26+
).componentInstance;
2427

2528
// let's pretend Dependency Component (unmocked) has 'someInput' as an input
2629
// the input value will be passed into the mocked component so you can assert on it
@@ -33,8 +36,7 @@ describe('MockComponent', () => {
3336

3437
it('should do something when the dependency component emits on its output', () => {
3538
spyOn(component, 'trigger');
36-
const mockedComponent = fixture.debugElement.query(By.directive(DependencyComponent))
37-
.componentInstance as DependencyComponent; // casting to retain type safety
39+
const mockedComponent = MockHelper.findOrFail(fixture.debugElement, DependencyComponent).componentInstance;
3840

3941
// again, let's pretend DependencyComponent has an output called 'someOutput'
4042
// emit on the output that MockComponent setup when generating the mock of Dependency Component
@@ -50,36 +52,37 @@ describe('MockComponent', () => {
5052
});
5153

5254
it('should render something inside of the dependency component', () => {
53-
const localFixture = MockRender(`
55+
const localFixture = MockRender<DependencyComponent>(`
5456
<dependency-component-selector>
5557
<p>inside content</p>
5658
</dependency-component-selector>
5759
`);
60+
5861
// because component does not have any @ContentChild we can access html directly.
5962
// assert on some side effect
60-
const mockedNgContent = localFixture.debugElement.query(By.directive(DependencyComponent)).nativeElement.innerHTML;
63+
const mockedNgContent = localFixture.point.nativeElement.innerHTML;
6164
expect(mockedNgContent).toContain('<p>inside content</p>');
6265
});
6366

6467
it('should render something inside of the dependency component', () => {
65-
const localFixture = MockRender(`
68+
const localFixture = MockRender<MockedComponent<DependencyComponent>>(`
6669
<dependency-component-selector>
6770
<ng-template #something><p>inside template</p></ng-template>
6871
<p>inside content</p>
6972
</dependency-component-selector>
7073
`);
7174

7275
// injected ng-content says as it was.
73-
const mockedNgContent = localFixture.debugElement.query(By.directive(DependencyComponent)).nativeElement.innerHTML;
76+
const mockedNgContent = localFixture.point.nativeElement.innerHTML;
7477
expect(mockedNgContent).toContain('<p>inside content</p>');
7578

7679
// because component does have @ContentChild we need to render them first with proper context.
77-
const mockedElement = localFixture.debugElement.query(By.directive(DependencyComponent));
78-
const mockedComponent: MockedComponent<DependencyComponent> = mockedElement.componentInstance;
80+
const mockedComponent = localFixture.point.componentInstance;
7981
mockedComponent.__render('something');
8082
localFixture.detectChanges();
8183

82-
const mockedNgTemplate = mockedElement.query(By.css('[data-key="something"]')).nativeElement.innerHTML;
84+
const mockedNgTemplate = MockHelper.findOrFail(localFixture.debugElement, '[data-key="something"]').nativeElement
85+
.innerHTML;
8386
expect(mockedNgTemplate).toContain('<p>inside template</p>');
8487
});
8588
});

0 commit comments

Comments
 (0)