Skip to content

Commit

Permalink
fix(ngMocks.findInstance): finds pipes in attributes #2314
Browse files Browse the repository at this point in the history
  • Loading branch information
satanTime committed May 1, 2022
1 parent 12cf99d commit 1b8868f
Show file tree
Hide file tree
Showing 11 changed files with 252 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import nestedCheck from './nested-check';

export default (
sel: DebugNode | DebugNodeSelector,
callback: (node: DebugNode) => void | boolean,
callback: (node: DebugNode, parent?: DebugNode) => void | boolean,
includeTextNode = false,
): void => {
const el = mockHelperFind(funcGetLastFixture(), sel, undefined);
Expand Down
27 changes: 27 additions & 0 deletions libs/ng-mocks/src/lib/mock-helper/crawl/nested-check-parent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { MockedDebugNode } from '../../mock-render/types';

import elDefCompare from './el-def-compare';
import elDefGetNode from './el-def-get-node';
import elDefGetParent from './el-def-get-parent';

const detectParent = (node: MockedDebugNode, parent: MockedDebugNode | undefined): MockedDebugNode | undefined => {
if (parent) {
return parent;
}

const expected = elDefGetParent(node);
const currentParent = node.parent ? elDefGetNode(node.parent) : undefined;
if (node.parent && elDefCompare(expected, currentParent)) {
return node.parent;
}
for (const childNode of node.parent?.childNodes || []) {
const childElDef = elDefGetNode(childNode);
if (elDefCompare(expected, childElDef)) {
return childNode;
}
}

return undefined;
};

export default ((): typeof detectParent => detectParent)();
26 changes: 2 additions & 24 deletions libs/ng-mocks/src/lib/mock-helper/crawl/nested-check.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,8 @@
import { MockedDebugNode } from '../../mock-render/types';

import detectTextNode from './detect-text-node';
import elDefCompare from './el-def-compare';
import elDefGetNode from './el-def-get-node';
import elDefGetParent from './el-def-get-parent';
import nestedCheckChildren from './nested-check-children';

const detectParent = (node: MockedDebugNode, parent: MockedDebugNode | undefined): MockedDebugNode | undefined => {
if (parent) {
return parent;
}

const expected = elDefGetParent(node);
const currentParent = node.parent ? elDefGetNode(node.parent) : undefined;
if (node.parent && elDefCompare(expected, currentParent)) {
return node.parent;
}
for (const childNode of node.parent?.childNodes || []) {
const childElDef = elDefGetNode(childNode);
if (elDefCompare(expected, childElDef)) {
return childNode;
}
}

return undefined;
};
import nestedCheckParent from './nested-check-parent';

const nestedCheck = (
node: MockedDebugNode | null | undefined,
Expand All @@ -38,7 +16,7 @@ const nestedCheck = (
if (!includeTextNode && detectTextNode(node)) {
return false;
}
if (check(node, detectParent(node, parent))) {
if (check(node, nestedCheckParent(node, parent))) {
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@ export default <T>(...args: any[]): T => {
if (fixture) {
mockHelperCrawl(
mockHelperFind(fixture, el, undefined),
node => {
(node, parent) => {
funcGetFromNode(result, node, declaration);
if (result.length === 0 && parent && parent.nativeNode.nodeName === '#comment') {
funcGetFromNode(result, parent, declaration);
}

return result.length > 0;
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,15 @@ export default <T>(...args: any[]): T[] => {
for (const element of elements) {
mockHelperCrawl(
element,
node => {
(node, parent) => {
if (scanned.indexOf(node) === -1) {
funcGetFromNode(result, node, declaration);
scanned.push(node);
}
if (parent && parent.nativeNode.nodeName === '#comment' && scanned.indexOf(parent) === -1) {
funcGetFromNode(result, parent, declaration);
scanned.push(parent);
}
},
true,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,8 @@ const getParentWithInjector = (node: (DebugNode & Node) | null): Injector | unde
return undefined;
};

export default <T>(
result: T[],
node: (DebugNode & Node) | null | undefined,
proto: Type<T> | InjectionToken<T>,
): void => {
if (!node?.injector || node.injector.constructor.name === 'NullInjector') {
export default <T>(result: T[], node: DebugNode & Node, proto: Type<T> | InjectionToken<T>): void => {
if (!node.injector || node.injector.constructor.name === 'NullInjector') {
return;
}

Expand Down
26 changes: 24 additions & 2 deletions libs/ng-mocks/src/lib/mock-helper/func.get-from-node-scan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@ import { DebugNode } from '@angular/core';
import { Type } from '../common/core.types';

const detectGatherFlag = (gather: boolean, el: DebugNode | null, node: any): boolean => {
// LContainer for structural directives can be a trigger for pipes.
if (
el &&
el.nativeNode &&
el.nativeNode.nodeName === '#comment' &&
Array.isArray(node) &&
node[0] === el.nativeNode
) {
return true;
}

// LContainer should stop the scan.
if (Array.isArray(node)) {
return false;
Expand All @@ -12,6 +23,12 @@ const detectGatherFlag = (gather: boolean, el: DebugNode | null, node: any): boo
return gather;
}

// checking if a commentNode belongs to the current element.
// it comes from structural directives.
if (node.nodeName === '#comment') {
return node === el.nativeNode;
}

// checking if a textNode belongs to the current element.
if (node.nodeName === '#text') {
return node.parentNode === el.nativeNode;
Expand Down Expand Up @@ -44,8 +61,13 @@ const scan = <T>(
scanned.push(nodes);
let gather = gatherDefault;

for (const raw of nodes) {
const node = normalize(raw);
let nodesLength = nodes.length;
if (nodes.length > 1 && nodes[1] && typeof nodes[1] === 'object' && nodes[1].bindingStartIndex) {
nodesLength = nodes[1].bindingStartIndex;
}

for (let index = 0; index < nodesLength; index += 1) {
const node = normalize(nodes[index]);
if (isNotObject(node)) {
continue;
}
Expand Down
6 changes: 1 addition & 5 deletions libs/ng-mocks/src/lib/mock-helper/func.get-from-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,7 @@ export interface Node {
parent?: (DebugNode & Node) | null;
}

export default <T>(
result: T[],
node: (DebugNode & Node) | null | undefined,
proto: Type<T> | InjectionToken<T>,
): T[] => {
export default <T>(result: T[], node: DebugNode & Node, proto: Type<T> | InjectionToken<T>): T[] => {
funcGetFromNodeInjector(result, node, proto);
if (!isNgDef(proto, 't')) {
funcGetFromNodeStandard(result, node, proto);
Expand Down
49 changes: 0 additions & 49 deletions libs/ng-mocks/src/lib/mock-helper/mock-helper.get.spec.ts

This file was deleted.

35 changes: 21 additions & 14 deletions libs/ng-mocks/src/lib/mock-helper/mock-helper.get.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { DebugElement } from '@angular/core';

import { Type } from '../common/core.types';
import { getSourceOfMock } from '../common/func.get-source-of-mock';
import { MockedDebugElement } from '../mock-render/types';

import mockHelperFind from './find/mock-helper.find';
import funcGetFromNode from './func.get-from-node';
import funcGetLastFixture from './func.get-last-fixture';
import nestedCheckParent from './crawl/nested-check-parent';

const defaultNotFoundValue = {}; // simulating Symbol

Expand All @@ -22,24 +25,28 @@ const parseArgs = <T>(

export default <T>(...args: any[]) => {
const { el, sel, notFoundValue } = parseArgs<T>(args);
const root = mockHelperFind(funcGetLastFixture(), el, undefined);
const root: DebugElement | undefined = mockHelperFind(funcGetLastFixture(), el, undefined);
const source = getSourceOfMock(sel);

const res1 = funcGetFromNode([], root, getSourceOfMock(sel));
if (res1.length > 0) {
return res1[0];
// Looking in the root.
if (root) {
const result = funcGetFromNode([], root, source);
if (result.length > 0) {
return result[0];
}
}

// Looking for related structural directive.
const prevNode = root?.nativeNode.previousSibling;
const matches =
!prevNode || prevNode.nodeName !== '#comment' || !root || !root.parent
? []
: root.parent.queryAllNodes(node => node.nativeNode === prevNode);
const matchedNode = matches[0];
const res2 = funcGetFromNode([], matchedNode, getSourceOfMock(sel));
if (res2.length > 0) {
return res2[0];
// Looking for a related structural directive.
if (root) {
const parent = nestedCheckParent(root, undefined);
if (parent && parent.nativeNode.nodeName === '#comment') {
const result = funcGetFromNode([], parent, source);
if (result.length > 0) {
return result[0];
}
}
}

if (notFoundValue !== defaultNotFoundValue) {
return notFoundValue;
}
Expand Down
Loading

0 comments on commit 1b8868f

Please sign in to comment.