Skip to content

Commit

Permalink
fix: searching for things in default fixture
Browse files Browse the repository at this point in the history
  • Loading branch information
satanTime committed Nov 12, 2020
1 parent 127ab06 commit 17b5208
Show file tree
Hide file tree
Showing 10 changed files with 390 additions and 40 deletions.
57 changes: 37 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1492,10 +1492,7 @@ describe('MAIN', () => {
// By.directive(AppHeaderComponent)
// );
// but typesafe and fails if nothing has been found.
const header = ngMocks.find(
fixture.debugElement,
AppHeaderComponent
);
const header = ngMocks.find(AppHeaderComponent);

// Asserting how AppComponent uses AppHeaderComponent.
expect(header.componentInstance.showLogo).toBe(true);
Expand Down Expand Up @@ -2317,61 +2314,81 @@ const directive = ngMocks.get(fixture.debugElement, Directive);
#### ngMocks.findInstance

Returns the first found attribute or structural directive which belongs to the current element or its any child.
If the element isn't specified then the current fixture is used.

- `ngMocks.findInstance( debugElement, directive, notFoundValue? )`
- `ngMocks.findInstance( fixture?, directive, notFoundValue? )`
- `ngMocks.findInstance( debugElement?, directive, notFoundValue? )`

```typescript
const directive = ngMocks.findInstance(
const directive1 = ngMocks.findInstance(Directive1);
const directive2 = ngMocks.findInstance(fixture, Directive2);
const directive3 = ngMocks.findInstance(
fixture.debugElement,
Directive
Directive3
);
```

#### ngMocks.findInstances

Returns an array of all found attribute or structural directives which belong to the current element and all its children.
If the element isn't specified then the current fixture is used.

- `ngMocks.findInstances( debugElement, directive )`
- `ngMocks.findInstances( fixture?, directive )`
- `ngMocks.findInstances( debugElement?, directive )`

```typescript
const directives = ngMocks.findInstances(
const directives1 = ngMocks.findInstances(Directive1);
const directives2 = ngMocks.findInstances(fixture, Directive2);
const directives3 = ngMocks.findInstances(
fixture.debugElement,
Directive
Directive3
);
```

#### ngMocks.find

Returns a found DebugElement which belongs to a component with the correctly typed componentInstance,
or matches a css selector.
If a root element or a fixture aren't specified then the current fixture is used.

- `ngMocks.find( fixture, component, notFoundValue? )`
- `ngMocks.find( debugElement, component, notFoundValue? )`
- `ngMocks.find( debugElement, selector, notFoundValue? )`
- `ngMocks.find( fixture?, component, notFoundValue? )`
- `ngMocks.find( fixture?, cssSelector, notFoundValue? )`
- `ngMocks.find( debugElement?, component, notFoundValue? )`
- `ngMocks.find( debugElement?, cssSelector, notFoundValue? )`

```typescript
const element = ngMocks.find(fixture.debugElement, Component);
const element1 = ngMocks.find(Component1);
const element2 = ngMocks.find(fixture, Component2);
const element3 = ngMocks.find(fixture.debugElement, Component3);
```

```typescript
const element = ngMocks.find(fixture.debugElement, 'div.container');
const element1 = ngMocks.find('div.con1');
const element2 = ngMocks.find(fixture, 'div.con2');
const element3 = ngMocks.find(fixture.debugElement, 'div.con3');
```

#### ngMocks.findAll

Returns an array of found DebugElements which belong to a component with the correctly typed componentInstance,
or match a css selector.
If a root element or a fixture aren't specified then the current fixture is used.

- `ngMocks.findAll( fixture, component )`
- `ngMocks.findAll( debugElement, component )`
- `ngMocks.findAll( debugElement, selector )`
- `ngMocks.findAll( fixture?, component )`
- `ngMocks.findAll( fixture?, cssSelector )`
- `ngMocks.findAll( debugElement?, component )`
- `ngMocks.findAll( debugElement?, cssSelector )`

```typescript
const elements = ngMocks.findAll(fixture.debugElement, Component);
const elements1 = ngMocks.findAll(Component1);
const elements2 = ngMocks.findAll(fixture, Component2);
const elements3 = ngMocks.findAll(fixture.debugElement, Component3);
```

```typescript
const elements = ngMocks.findAll(fixture.debugElement, 'div.item');
const elements1 = ngMocks.findAll('div.item1');
const elements2 = ngMocks.findAll(fixture, 'div.item2');
const elements3 = ngMocks.findAll(fixture.debugElement, 'div.item3');
```

#### ngMocks.input
Expand Down
2 changes: 1 addition & 1 deletion examples/MAIN/test.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ describe('MAIN', () => {
// By.directive(AppHeaderComponent)
// );
// but typesafe and fails if nothing has been found.
const header = ngMocks.find(fixture.debugElement, AppHeaderComponent);
const header = ngMocks.find(AppHeaderComponent);

// Asserting how AppComponent uses AppHeaderComponent.
expect(header.componentInstance.showLogo).toBe(true);
Expand Down
6 changes: 6 additions & 0 deletions lib/mock-helper/func.get-last-fixture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { ComponentFixture, getTestBed } from '@angular/core/testing';

export default () => {
const fixtures: Array<ComponentFixture<any>> = (getTestBed() as any)._activeFixtures;
return fixtures[fixtures.length - 1];
};
14 changes: 10 additions & 4 deletions lib/mock-helper/mock-helper.find.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@ import { Type } from '../common/core.types';
import { getSourceOfMock } from '../common/func.get-source-of-mock';
import { MockedDebugElement } from '../mock-render/types';

import getLastFixture from './func.get-last-fixture';

const defaultNotFoundValue = {}; // simulating Symbol

export default (...args: any[]) => {
const el: MockedDebugElement = args[0].debugElement ? args[0].debugElement : args[0];
const sel: string | Type<any> = args[1];
const notFoundValue: any = args.length === 3 ? args[2] : defaultNotFoundValue;
const el: undefined | MockedDebugElement =
typeof args[0] !== 'object' ? undefined : args[0].debugElement ? args[0].debugElement : args[0];
const sel: string | Type<any> = el ? args[1] : args[0];
const notFoundValue: any =
el && args.length === 3 ? args[2] : !el && args.length === 2 ? args[1] : defaultNotFoundValue;

const debugElement = el || getLastFixture()?.debugElement;

const term = typeof sel === 'string' ? By.css(sel) : By.directive(getSourceOfMock(sel));
const result = el.query(term);
const result = debugElement?.query(term);
if (result) {
return result;
}
Expand Down
13 changes: 11 additions & 2 deletions lib/mock-helper/mock-helper.findAll.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
import { By } from '@angular/platform-browser';
import { MockedDebugElement, Type } from 'ng-mocks';

import { getSourceOfMock } from '../common/func.get-source-of-mock';

export default (el: any, sel: any) => {
import getLastFixture from './func.get-last-fixture';

export default (...args: any[]) => {
const el: undefined | MockedDebugElement =
typeof args[0] !== 'object' ? undefined : args[0].debugElement ? args[0].debugElement : args[0];
const sel: string | Type<any> = el ? args[1] : args[0];

const debugElement = el || getLastFixture()?.debugElement;

const term = typeof sel === 'string' ? By.css(sel) : By.directive(getSourceOfMock(sel));
return (el.debugElement ? el.debugElement : el).queryAll(term);
return debugElement?.queryAll(term) || [];
};
15 changes: 10 additions & 5 deletions lib/mock-helper/mock-helper.findInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,26 @@ import { Type } from '../common/core.types';
import { getSourceOfMock } from '../common/func.get-source-of-mock';
import { MockedDebugElement } from '../mock-render/types';

import getLastFixture from './func.get-last-fixture';
import findInstances from './mock-helper.findInstances';

const defaultNotFoundValue = {}; // simulating Symbol

export default <T>(...args: any[]) => {
const el: MockedDebugElement = args[0];
const sel: Type<T> = args[1];
const notFoundValue: any = args.length === 3 ? args[2] : defaultNotFoundValue;
const el: undefined | MockedDebugElement =
typeof args[0] !== 'object' ? undefined : args[0].debugElement ? args[0].debugElement : args[0];
const sel: Type<any> = el ? args[1] : args[0];
const notFoundValue: any =
el && args.length === 3 ? args[2] : !el && args.length === 2 ? args[1] : defaultNotFoundValue;

const result = findInstances(el, getSourceOfMock(sel));
const debugElement = el || getLastFixture()?.debugElement;

const result = findInstances(debugElement, getSourceOfMock(sel));
if (result.length) {
return result[0];
}
if (notFoundValue !== defaultNotFoundValue) {
return notFoundValue;
}
throw new Error(`Cannot find ${sel.name} directive via ngMocks.findInstance`);
throw new Error(`Cannot find an instance via ngMocks.findInstance(${sel.name})`);
};
16 changes: 12 additions & 4 deletions lib/mock-helper/mock-helper.findInstances.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Type } from '../common/core.types';
import { getSourceOfMock } from '../common/func.get-source-of-mock';
import { MockedDebugNode } from '../mock-render/types';
import { MockedDebugElement, MockedDebugNode } from '../mock-render/types';

import getLastFixture from './func.get-last-fixture';

function nestedCheck<T>(
result: T[],
Expand All @@ -11,15 +13,21 @@ function nestedCheck<T>(
if (element) {
result.push(element);
}
const childNodes = node.childNodes ? node.childNodes : [];
const childNodes = node?.childNodes || [];
childNodes.forEach(childNode => {
nestedCheck(result, childNode, callback);
});
}

export default <T>(el: MockedDebugNode, sel: Type<T>): T[] => {
export default <T>(...args: any[]): T[] => {
const el: undefined | MockedDebugElement =
typeof args[0] !== 'object' ? undefined : args[0].debugElement ? args[0].debugElement : args[0];
const sel: Type<any> = el ? args[1] : args[0];

const debugElement = el || getLastFixture()?.debugElement;

const result: T[] = [];
nestedCheck<T>(result, el, node => {
nestedCheck<T>(result, debugElement, node => {
try {
return node.injector.get(getSourceOfMock(sel));
} catch (error) {
Expand Down
4 changes: 3 additions & 1 deletion lib/mock-helper/mock-helper.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,9 @@ describe('MockHelper:getDirective', () => {

it('findInstance throws an error', () => {
const fixture = MockRender(`<component-a></component-a>`);
expect(() => ngMocks.findInstance(fixture.debugElement, BComponent)).toThrowError(/Cannot find BComponent/);
expect(() => ngMocks.findInstance(fixture.debugElement, BComponent)).toThrowError(
/Cannot find an instance via ngMocks.findInstance\(BComponent\)/
);
});

it('findInstance returns default value', () => {
Expand Down
55 changes: 52 additions & 3 deletions lib/mock-helper/mock-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,21 @@ export const ngMocks: {
*/
faster(): void;

/**
* @see https://github.com/ike18t/ng-mocks#ngmocksfind
*/
find<T>(component: Type<T>): MockedDebugElement<T>;

/**
* @see https://github.com/ike18t/ng-mocks#ngmocksfind
*/
find<T>(debugElement: MockedDebugElement | ComponentFixture<any>, component: Type<T>): MockedDebugElement<T>;

/**
* @see https://github.com/ike18t/ng-mocks#ngmocksfind
*/
find<T, D>(component: Type<T>, notFoundValue: D): D | MockedDebugElement<T>;

/**
* @see https://github.com/ike18t/ng-mocks#ngmocksfind
*/
Expand All @@ -113,11 +123,21 @@ export const ngMocks: {
notFoundValue: D
): D | MockedDebugElement<T>;

/**
* @see https://github.com/ike18t/ng-mocks#ngmocksfind
*/
find<T = any>(cssSelector: string): MockedDebugElement<T>;

/**
* @see https://github.com/ike18t/ng-mocks#ngmocksfind
*/
find<T = any>(debugElement: MockedDebugElement | ComponentFixture<any>, cssSelector: string): MockedDebugElement<T>;

/**
* @see https://github.com/ike18t/ng-mocks#ngmocksfind
*/
find<T = any, D = undefined>(cssSelector: string, notFoundValue: D): D | MockedDebugElement<T>;

/**
* @see https://github.com/ike18t/ng-mocks#ngmocksfind
*/
Expand All @@ -127,6 +147,11 @@ export const ngMocks: {
notFoundValue: D
): D | MockedDebugElement<T>;

/**
* @see https://github.com/ike18t/ng-mocks#ngmocksfindall
*/
findAll<T>(component: Type<T>): Array<MockedDebugElement<T>>;

/**
* @see https://github.com/ike18t/ng-mocks#ngmocksfindall
*/
Expand All @@ -135,6 +160,11 @@ export const ngMocks: {
component: Type<T>
): Array<MockedDebugElement<T>>;

/**
* @see https://github.com/ike18t/ng-mocks#ngmocksfindall
*/
findAll<T = any>(cssSelector: string): Array<MockedDebugElement<T>>;

/**
* @see https://github.com/ike18t/ng-mocks#ngmocksfindall
*/
Expand All @@ -146,17 +176,36 @@ export const ngMocks: {
/**
* @see https://github.com/ike18t/ng-mocks#ngmocksfindinstance
*/
findInstance<T>(debugNode: MockedDebugNode, instanceClass: Type<T>): T;
findInstance<T>(instanceClass: Type<T>): T;

/**
* @see https://github.com/ike18t/ng-mocks#ngmocksfindinstance
*/
findInstance<T, D>(debugNode: MockedDebugNode, instanceClass: Type<T>, notFoundValue: D): D | T;
findInstance<T>(debugNode: MockedDebugNode | ComponentFixture<any>, instanceClass: Type<T>): T;

/**
* @see https://github.com/ike18t/ng-mocks#ngmocksfindinstance
*/
findInstances<T>(debugNode: MockedDebugNode, instanceClass: Type<T>): T[];
findInstance<T, D>(instanceClass: Type<T>, notFoundValue: D): D | T;

/**
* @see https://github.com/ike18t/ng-mocks#ngmocksfindinstance
*/
findInstance<T, D>(
debugNode: MockedDebugNode | ComponentFixture<any>,
instanceClass: Type<T>,
notFoundValue: D
): D | T;

/**
* @see https://github.com/ike18t/ng-mocks#ngmocksfindinstances
*/
findInstances<T>(instanceClass: Type<T>): T[];

/**
* @see https://github.com/ike18t/ng-mocks#ngmocksfindinstances
*/
findInstances<T>(debugNode: MockedDebugNode | ComponentFixture<any>, instanceClass: Type<T>): T[];

/**
* @see https://github.com/ike18t/ng-mocks#ngmocksflushtestbed
Expand Down
Loading

0 comments on commit 17b5208

Please sign in to comment.