forked from help-me-mom/ng-mocks
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: find ng-container via ngMocks.reveal and revealAll
closes #289
- Loading branch information
Showing
31 changed files
with
1,210 additions
and
176 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
52 changes: 52 additions & 0 deletions
52
libs/ng-mocks/src/lib/mock-helper/crawl/crawl-by-attribute-value.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { MockedDebugNode } from '../../mock-render/types'; | ||
|
||
import funcGetPublicProviderKeys from './func.get-public-provider-keys'; | ||
import funcParseInputsAndRequiresAttributes from './func.parse-inputs-and-requires-attributes'; | ||
|
||
const detectInClassic = (node: MockedDebugNode, attribute: string, value: any): boolean => { | ||
for (const key of funcGetPublicProviderKeys(node)) { | ||
const [inputs, expectedAttributes, nodeIndex] = funcParseInputsAndRequiresAttributes(node, key); | ||
for (const input of inputs || []) { | ||
const [prop, alias] = input.split(': '); | ||
if (attribute !== (alias || prop) || expectedAttributes.indexOf(prop) === -1) { | ||
continue; | ||
} | ||
if (value === (node.injector as any).view.nodes[nodeIndex].instance[prop]) { | ||
return true; | ||
} | ||
} | ||
} | ||
|
||
return false; | ||
}; | ||
|
||
const detectInIvy = (node: MockedDebugNode, attribute: string, value: any): boolean => { | ||
const attrs = (node.injector as any)._tNode?.attrs || []; | ||
let step = 2; | ||
for (let index = 0; index < attrs.length; index += step) { | ||
// 3 is a divider between static and dynamic bindings | ||
if (typeof attrs[index] === 'number') { | ||
step = 1; | ||
continue; | ||
} | ||
const attr = attrs[index]; | ||
if (attr !== attribute || !(node.injector as any)._tNode.inputs[attr]) { | ||
continue; | ||
} | ||
const [attrIndex, attrProp] = (node.injector as any)._tNode.inputs[attr]; | ||
|
||
if (value === (node.injector as any)._lView[attrIndex][attrProp]) { | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
}; | ||
|
||
export default (attribute: string, value: any): ((node: MockedDebugNode) => boolean) => node => { | ||
if (detectInClassic(node, attribute, value)) { | ||
return true; | ||
} | ||
|
||
return detectInIvy(node, attribute, value); | ||
}; |
18 changes: 18 additions & 0 deletions
18
libs/ng-mocks/src/lib/mock-helper/crawl/crawl-by-attribute.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { MockedDebugNode } from '../../mock-render/types'; | ||
|
||
import detectAttributeInSelectors from './detect-attribute-in-selectors'; | ||
import detectSelectorsFromNode from './detect-selectors-from-node'; | ||
|
||
export default (attribute: string): ((node: MockedDebugNode) => boolean) => node => { | ||
const [selectors, attributes] = detectSelectorsFromNode(node); | ||
|
||
if (attributes.indexOf(attribute) !== -1) { | ||
return true; | ||
} | ||
|
||
if (detectAttributeInSelectors(selectors, attribute)) { | ||
return true; | ||
} | ||
|
||
return false; | ||
}; |
22 changes: 22 additions & 0 deletions
22
libs/ng-mocks/src/lib/mock-helper/crawl/crawl-by-declaration.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { AnyType } from '../../common/core.types'; | ||
import { getSourceOfMock } from '../../common/func.get-source-of-mock'; | ||
import { MockedDebugNode } from '../../mock-render/types'; | ||
|
||
export default (declaration: AnyType<any>): ((node: MockedDebugNode) => boolean) => { | ||
const source = getSourceOfMock(declaration); | ||
|
||
return node => { | ||
try { | ||
if (node.providerTokens.indexOf(source) === -1) { | ||
return false; | ||
} | ||
node.injector.get(source); | ||
|
||
return true; | ||
} catch (e) { | ||
// nothing to do. | ||
} | ||
|
||
return false; | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { MockedDebugNode } from '../../mock-render/types'; | ||
|
||
export default (id: string): ((node: MockedDebugNode) => boolean) => node => { | ||
return !!node.references[id]; | ||
}; |
10 changes: 10 additions & 0 deletions
10
libs/ng-mocks/src/lib/mock-helper/crawl/crawl-by-tag-name.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { MockedDebugNode } from '../../mock-render/types'; | ||
|
||
import detectSelectorsFromNode from './detect-selectors-from-node'; | ||
import detectTagNameInSelectors from './detect-tag-name-in-selectors'; | ||
|
||
export default (attribute: string): ((node: MockedDebugNode) => boolean) => node => { | ||
const [selectors] = detectSelectorsFromNode(node); | ||
|
||
return detectTagNameInSelectors(selectors, attribute); | ||
}; |
16 changes: 16 additions & 0 deletions
16
libs/ng-mocks/src/lib/mock-helper/crawl/detect-attribute-in-selectors.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
export default (selectors: string[], query: string): boolean => { | ||
for (const selector of selectors) { | ||
const attributes = selector.match(/\[([^\]=]+)/g); | ||
if (!attributes) { | ||
continue; | ||
} | ||
|
||
for (const attribute of attributes) { | ||
if (attribute === `[${query}`) { | ||
return true; | ||
} | ||
} | ||
} | ||
|
||
return false; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { AnyType } from '../../common/core.types'; | ||
import { MockedDebugNode } from '../../mock-render/types'; | ||
|
||
import crawlByAttribute from './crawl-by-attribute'; | ||
import crawlByAttributeValue from './crawl-by-attribute-value'; | ||
import crawlByDeclaration from './crawl-by-declaration'; | ||
import crawlById from './crawl-by-id'; | ||
import crawlByTagName from './crawl-by-tag-name'; | ||
|
||
type SELECTOR = string | AnyType<any> | [any] | [any, any]; | ||
|
||
const isCrawlByAttribute = (selector: SELECTOR): selector is [string] => { | ||
return Array.isArray(selector) && selector.length === 1 && typeof selector[0] === 'string'; | ||
}; | ||
|
||
const isCrawlByAttributeValue = (selector: SELECTOR): selector is [string, any] => { | ||
return Array.isArray(selector) && selector.length === 2 && typeof selector[0] === 'string'; | ||
}; | ||
|
||
const isCrawlById = (selector: SELECTOR): selector is string => { | ||
return typeof selector === 'string' && selector.indexOf('#') === 0 && selector.length > 1; | ||
}; | ||
|
||
const isCrawlByTagName = (selector: SELECTOR): selector is string => { | ||
return typeof selector === 'string' && selector.indexOf('#') !== 0 && selector.length > 0; | ||
}; | ||
|
||
const isCrawlByDeclaration = (selector: SELECTOR): selector is AnyType<any> => { | ||
return typeof selector === 'function'; | ||
}; | ||
|
||
export default (selector: SELECTOR): ((node: MockedDebugNode) => boolean) => { | ||
if (isCrawlByAttribute(selector)) { | ||
return crawlByAttribute(selector[0]); | ||
} | ||
if (isCrawlByAttributeValue(selector)) { | ||
return crawlByAttributeValue(selector[0], selector[1]); | ||
} | ||
if (isCrawlById(selector)) { | ||
return crawlById(selector.substr(1)); | ||
} | ||
if (isCrawlByTagName(selector)) { | ||
return crawlByTagName(selector); | ||
} | ||
if (isCrawlByDeclaration(selector)) { | ||
return crawlByDeclaration(selector); | ||
} | ||
|
||
throw new Error(`Unknown selector`); | ||
}; |
62 changes: 62 additions & 0 deletions
62
libs/ng-mocks/src/lib/mock-helper/crawl/detect-selectors-from-node.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { MockedDebugNode } from '../../mock-render/types'; | ||
import funcParseProviderTokensDirectives from '../func.parse-provider-tokens-directives'; | ||
|
||
import funcGetPublicProviderKeys from './func.get-public-provider-keys'; | ||
import funcParseInputsAndRequiresAttributes from './func.parse-inputs-and-requires-attributes'; | ||
|
||
const collectSelectors = (node: MockedDebugNode): string[] => { | ||
const selectors: string[] = []; | ||
|
||
for (const token of node.providerTokens) { | ||
const meta = funcParseProviderTokensDirectives(node, token); | ||
if (meta?.selector && selectors.indexOf(meta.selector) === -1) { | ||
selectors.push(meta.selector); | ||
} | ||
} | ||
|
||
return selectors; | ||
}; | ||
|
||
const collectAttributesClassic = (node: MockedDebugNode): string[] => { | ||
const result: string[] = []; | ||
|
||
for (const key of funcGetPublicProviderKeys(node)) { | ||
const [inputs, expectedAttributes] = funcParseInputsAndRequiresAttributes(node, key); | ||
for (const input of inputs) { | ||
const [prop, alias] = input.split(': '); | ||
const attr = alias || prop; | ||
if (expectedAttributes.indexOf(prop) !== -1 && result.indexOf(attr) === -1) { | ||
result.push(attr); | ||
} | ||
} | ||
} | ||
|
||
return result; | ||
}; | ||
|
||
const collectAttributesIvy = (node: MockedDebugNode): string[] => { | ||
const result: string[] = []; | ||
|
||
const attrs = (node.injector as any)._tNode?.attrs || []; | ||
let step = 2; | ||
for (let index = 0; index < attrs.length; index += step) { | ||
// 3 is a divider between static and dynamic bindings | ||
if (typeof attrs[index] === 'number') { | ||
step = 1; | ||
continue; | ||
} | ||
const attr = attrs[index]; | ||
if ((node.injector as any)._tNode.inputs[attr] && result.indexOf(attr) === -1) { | ||
result.push(attr); | ||
} | ||
} | ||
|
||
return result; | ||
}; | ||
|
||
export default (node: MockedDebugNode): [string[], string[]] => { | ||
const selectors = collectSelectors(node); | ||
const attributes = [...collectAttributesClassic(node), ...collectAttributesIvy(node)]; | ||
|
||
return [selectors, attributes]; | ||
}; |
15 changes: 15 additions & 0 deletions
15
libs/ng-mocks/src/lib/mock-helper/crawl/detect-tag-name-in-selectors.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
const regExp = new RegExp('\\[.*?\\]', 'g'); | ||
|
||
export default (selectors: string[], query: string): boolean => { | ||
for (const selector of selectors) { | ||
const attributes = selector.replace(regExp, '').split(','); | ||
|
||
for (const attribute of attributes) { | ||
if (attribute.trim() === query) { | ||
return true; | ||
} | ||
} | ||
} | ||
|
||
return false; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { MockedDebugNode } from '../../mock-render/types'; | ||
|
||
export default (node: MockedDebugNode): boolean => { | ||
return node.nativeNode.nodeName === '#text'; | ||
}; |
5 changes: 5 additions & 0 deletions
5
libs/ng-mocks/src/lib/mock-helper/crawl/func.get-public-provider-keys.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { MockedDebugNode } from '../../mock-render/types'; | ||
|
||
export default (node: MockedDebugNode): string[] => { | ||
return (node.injector as any).elDef ? Object.keys((node.injector as any).elDef.element.publicProviders) : []; | ||
}; |
15 changes: 15 additions & 0 deletions
15
libs/ng-mocks/src/lib/mock-helper/crawl/func.parse-inputs-and-requires-attributes.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { MockedDebugNode } from '../../mock-render/types'; | ||
import funcParseProviderTokensDirectives from '../func.parse-provider-tokens-directives'; | ||
|
||
export default (node: MockedDebugNode, key: string): [string[], string[], number] => { | ||
const config = (node.injector as any).elDef.element.publicProviders[key]; | ||
const token = config.provider.value; | ||
if (!token) { | ||
return [[], [], 0]; | ||
} | ||
const meta = funcParseProviderTokensDirectives(node, token); | ||
|
||
const requiredAttributes = config.bindings.map((binding: any) => binding.nonMinifiedName || binding.name); | ||
|
||
return [meta?.inputs || [], requiredAttributes, config.nodeIndex]; | ||
}; |
20 changes: 20 additions & 0 deletions
20
libs/ng-mocks/src/lib/mock-helper/crawl/mock-helper.crawl-all.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import funcParseFindArgs from '../func.parse-find-args'; | ||
|
||
import detectCrawler from './detect-crawler'; | ||
import detectTextNode from './detect-text-node'; | ||
import nestedCheck from './nested-check'; | ||
|
||
export default (...args: any[]): any[] => { | ||
const { el, sel } = funcParseFindArgs(args); | ||
|
||
const detector = detectCrawler(sel); | ||
|
||
const result: any[] = []; | ||
nestedCheck(el, node => { | ||
if (!detectTextNode(node) && detector(node)) { | ||
result.push(node); | ||
} | ||
}); | ||
|
||
return result; | ||
}; |
33 changes: 33 additions & 0 deletions
33
libs/ng-mocks/src/lib/mock-helper/crawl/mock-helper.crawl.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import funcParseFindArgs from '../func.parse-find-args'; | ||
import funcParseFindArgsName from '../func.parse-find-args-name'; | ||
|
||
import detectCrawler from './detect-crawler'; | ||
import detectTextNode from './detect-text-node'; | ||
import nestedCheck from './nested-check'; | ||
|
||
const defaultNotFoundValue = {}; // simulating Symbol | ||
|
||
export default (...args: any[]): any => { | ||
const { el, sel, notFoundValue } = funcParseFindArgs(args, defaultNotFoundValue); | ||
|
||
const detector = detectCrawler(sel); | ||
|
||
let result; | ||
nestedCheck(el, node => { | ||
if (!detectTextNode(node) && detector(node)) { | ||
result = node; | ||
|
||
return true; | ||
} | ||
|
||
return false; | ||
}); | ||
if (result) { | ||
return result; | ||
} | ||
if (notFoundValue !== defaultNotFoundValue) { | ||
return notFoundValue; | ||
} | ||
|
||
throw new Error(`Cannot find a DebugElement via ngMocks.reveal(${funcParseFindArgsName(sel)})`); | ||
}; |
Oops, something went wrong.