Skip to content

Commit

Permalink
fix: all find functions can handle undefined debug element
Browse files Browse the repository at this point in the history
  • Loading branch information
satanTime committed Feb 13, 2021
1 parent a110f1d commit 397ecf8
Show file tree
Hide file tree
Showing 18 changed files with 523 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import { Type } from '../common/core.types';

import { Node } from './func.get-from-node';

export default <T>(result: T[], node: DebugNode & Node, proto: Type<T>): void => {
export default <T>(result: T[], node: (DebugNode & Node) | null | undefined, proto: Type<T>): void => {
if (!node) {
return;
}

try {
const instance = node.injector.get(proto);
if (result.indexOf(instance) === -1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const detectContext = (node: DebugNode): any => {

const contextToNodes = (context: any): any => (Array.isArray(context) ? context : context?.lView);

export default <T>(result: T[], node: DebugNode & Node, proto: Type<T>): void => {
export default <T>(result: T[], node: (DebugNode & Node) | null | undefined, proto: Type<T>): void => {
if (!node || node._debugContext) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const normalize = (item: any): any => {
return null;
};

export default <T>(result: T[], node: DebugNode & Node, proto: Type<T>): void => {
export default <T>(result: T[], node: (DebugNode & Node) | null | undefined, proto: Type<T>): void => {
if (!node || !node._debugContext) {
return;
}
Expand Down
2 changes: 1 addition & 1 deletion libs/ng-mocks/src/lib/mock-helper/func.get-from-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export interface Node {
parent?: (DebugNode & Node) | null;
}

export default <T>(result: T[], node: DebugNode & Node, proto: Type<T>): T[] => {
export default <T>(result: T[], node: (DebugNode & Node) | null | undefined, proto: Type<T>): T[] => {
funcGetFromNodeInjector(result, node, proto);
funcGetFromNodeStandard(result, node, proto);
funcGetFromNodeIvy(result, node, proto);
Expand Down
31 changes: 21 additions & 10 deletions libs/ng-mocks/src/lib/mock-helper/func.parse-find-args.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
import { Type } from '../common/core.types';
import funcGetLastFixture from '../mock-helper/func.get-last-fixture';
import { MockedDebugElement } from '../mock-render/types';

const detectEl = (args: any[]): undefined | MockedDebugElement => {
return Array.isArray(args[0]) || typeof args[0] !== 'object'
? undefined
: args[0]?.debugElement
? args[0].debugElement
: args[0];
};

const detectSel = (args: any[], el: any) => {
return el || !args[0] ? args[1] : args[0];
};

const detectNotFound = (args: any[], el: any, defaultNotFoundValue: any): any => {
return args.length === 3 ? args[2] : !el && args[0] && args.length === 2 ? args[1] : defaultNotFoundValue;
};

export default (
args: any[],
defaultNotFoundValue?: any,
Expand All @@ -9,18 +26,12 @@ export default (
notFoundValue: any;
sel: string | Type<any> | [string] | [string, any];
} => {
const el: undefined | MockedDebugElement =
Array.isArray(args[0]) || typeof args[0] !== 'object'
? undefined
: args[0].debugElement
? args[0].debugElement
: args[0];
const sel = el || !args[0] ? args[1] : args[0];
const notFoundValue: any =
el && args.length === 3 ? args[2] : !el && args.length === 2 ? args[1] : defaultNotFoundValue;
const el = detectEl(args);
const sel = detectSel(args, el);
const notFoundValue = detectNotFound(args, el, defaultNotFoundValue);

return {
el,
el: el ?? (args[0] && funcGetLastFixture()?.debugElement) ?? undefined,
notFoundValue,
sel,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ const getMeta = (token: any): Directive | undefined => {
return undefined;
};

export default (el: DebugNode, token: any): Directive | undefined => {
export default (el: DebugNode | null | undefined, token: any): Directive | undefined => {
if (!el) {
return undefined;
}

try {
const provider = funcGetProvider(token);
const instance = el.injector.get(provider);
Expand Down
20 changes: 15 additions & 5 deletions libs/ng-mocks/src/lib/mock-helper/mock-helper.attributes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,14 @@ import mockHelperGet from './mock-helper.get';

const defaultNotFoundValue = {}; // simulating Symbol

const parseArgs = (args: any[]): [MockedDebugElement, string, any] => [
const parseArgs = (args: any[]): [MockedDebugElement | null | undefined, string, any] => [
args[0],
args[1],
args.length === 3 ? args[2] : defaultNotFoundValue,
];

export default (label: string, attr: 'inputs' | 'outputs', ...args: any[]) => {
const [el, sel, notFoundValue] = parseArgs(args);

for (const token of el.providerTokens) {
const detectAttribute = (el: MockedDebugElement | null | undefined, attr: 'inputs' | 'outputs', sel: string) => {
for (const token of el?.providerTokens || []) {
const meta = funcParseProviderTokensDirectives(el, token);
if (!meta) {
continue;
Expand All @@ -29,6 +27,18 @@ export default (label: string, attr: 'inputs' | 'outputs', ...args: any[]) => {
return mockHelperGet(el, token)[prop];
}
}

throw new Error('Not found');
};

export default (label: string, attr: 'inputs' | 'outputs', ...args: any[]) => {
const [el, sel, notFoundValue] = parseArgs(args);

try {
return detectAttribute(el, attr, sel);
} catch (e) {
// nothing to do
}
if (notFoundValue !== defaultNotFoundValue) {
return notFoundValue;
}
Expand Down
4 changes: 1 addition & 3 deletions libs/ng-mocks/src/lib/mock-helper/mock-helper.find-all.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import funcGetLastFixture from './func.get-last-fixture';
import funcParseFindArgs from './func.parse-find-args';
import funcParseFindTerm from './func.parse-find-term';

export default (...args: any[]) => {
const { el, sel } = funcParseFindArgs(args);
const debugElement = el || funcGetLastFixture()?.debugElement;

return debugElement?.queryAll(funcParseFindTerm(sel)) || [];
return el?.queryAll(funcParseFindTerm(sel)) || [];
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import funcGetLastFixture from './func.get-last-fixture';
import funcParseFindArgs from './func.parse-find-args';
import funcParseFindArgsName from './func.parse-find-args-name';
import mockHelperFindInstances from './mock-helper.find-instances';
Expand All @@ -7,9 +6,8 @@ const defaultNotFoundValue = {}; // simulating Symbol

export default (...args: any[]) => {
const { el, sel, notFoundValue } = funcParseFindArgs(args, defaultNotFoundValue);
const debugElement = el || funcGetLastFixture()?.debugElement;

const result = mockHelperFindInstances(debugElement, sel);
const result = mockHelperFindInstances(el, sel);
if (result.length) {
return result[0];
}
Expand Down
10 changes: 5 additions & 5 deletions libs/ng-mocks/src/lib/mock-helper/mock-helper.find-instances.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,29 @@ import { getSourceOfMock } from '../common/func.get-source-of-mock';
import { MockedDebugNode } from '../mock-render/types';

import funcGetFromNode from './func.get-from-node';
import funcGetLastFixture from './func.get-last-fixture';
import funcParseFindArgs from './func.parse-find-args';

interface DebugNode {
childNodes?: MockedDebugNode[];
}

function nestedCheck<T>(result: T[], node: MockedDebugNode & DebugNode, proto: Type<T>) {
funcGetFromNode(result, node, proto);
function nestedCheck<T>(result: T[], node: (MockedDebugNode & DebugNode) | undefined, proto: Type<T>) {
if (node) {
funcGetFromNode(result, node, proto);
}
for (const childNode of node?.childNodes || []) {
nestedCheck(result, childNode, proto);
}
}

export default <T>(...args: any[]): T[] => {
const { el, sel } = funcParseFindArgs(args);
const debugElement = el || funcGetLastFixture()?.debugElement;
if (typeof sel !== 'function') {
throw new Error('Only classes are accepted');
}

const result: T[] = [];
nestedCheck(result, debugElement, getSourceOfMock(sel));
nestedCheck(result, el, getSourceOfMock(sel));

return result;
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import funcGetLastFixture from './func.get-last-fixture';
import funcParseFindArgs from './func.parse-find-args';
import funcParseFindArgsName from './func.parse-find-args-name';
import mockHelperFindTemplateRefs from './mock-helper.find-template-refs';
Expand All @@ -7,9 +6,8 @@ const defaultNotFoundValue = {}; // simulating Symbol

export default (...args: any[]) => {
const { el, sel, notFoundValue } = funcParseFindArgs(args, defaultNotFoundValue);
const debugElement = el || funcGetLastFixture()?.debugElement;

const result = debugElement ? mockHelperFindTemplateRefs(debugElement, sel) : [];
const result = el ? mockHelperFindTemplateRefs(el, sel) : [];
if (result.length) {
return result[0];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { TemplateRef } from '@angular/core';
import { Type } from '../common/core.types';
import { MockedDebugNode } from '../mock-render/types';

import funcGetLastFixture from './func.get-last-fixture';
import funcParseFindArgs from './func.parse-find-args';
import funcParseProviderTokensDirectives from './func.parse-provider-tokens-directives';
import mockHelperInput from './mock-helper.input';
Expand Down Expand Up @@ -121,12 +120,11 @@ const getDetector = (selector: string | Type<any> | [string] | [string, any] | a

export default (...args: any[]): Array<TemplateRef<any>> => {
const { el, sel } = funcParseFindArgs(args);
const debugElement = el || funcGetLastFixture()?.debugElement;

const detector = getDetector(sel);

const result: Array<TemplateRef<any>> = [];
nestedCheck(result, debugElement, node => {
nestedCheck(result, el, node => {
const value = detector(node);
if (value) {
result.push(value);
Expand Down
4 changes: 1 addition & 3 deletions libs/ng-mocks/src/lib/mock-helper/mock-helper.find.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import funcGetLastFixture from './func.get-last-fixture';
import funcParseFindArgs from './func.parse-find-args';
import funcParseFindArgsName from './func.parse-find-args-name';
import funcParseFindTerm from './func.parse-find-term';
Expand All @@ -7,9 +6,8 @@ const defaultNotFoundValue = {}; // simulating Symbol

export default (...args: any[]) => {
const { el, sel, notFoundValue } = funcParseFindArgs(args, defaultNotFoundValue);
const debugElement = el || funcGetLastFixture()?.debugElement;

const result = debugElement?.query(funcParseFindTerm(sel));
const result = el?.query(funcParseFindTerm(sel));
if (result) {
return result;
}
Expand Down
4 changes: 2 additions & 2 deletions libs/ng-mocks/src/lib/mock-helper/mock-helper.get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const defaultNotFoundValue = {}; // simulating Symbol
const parseArgs = <T>(
args: any[],
): {
el: MockedDebugElement;
el: MockedDebugElement | null | undefined;
notFoundValue: any;
sel: Type<T>;
} => ({
Expand All @@ -27,7 +27,7 @@ export default <T>(...args: any[]) => {
}

// Looking for related structural directive.
const prevNode = el.nativeNode.previousSibling;
const prevNode = el?.nativeNode.previousSibling;
const matches =
!prevNode || prevNode.nodeName !== '#comment' || !el || !el.parent
? []
Expand Down

0 comments on commit 397ecf8

Please sign in to comment.