diff --git a/docs/articles/api/ngMocks/findInstances.md b/docs/articles/api/ngMocks/findInstances.md index e524f4561c..1dcc105670 100644 --- a/docs/articles/api/ngMocks/findInstances.md +++ b/docs/articles/api/ngMocks/findInstances.md @@ -3,7 +3,7 @@ title: ngMocks.findInstances description: Documentation about ngMocks.findInstances from ng-mocks library --- -Returns an array of all found components, directives, pipes or services which belong to the current element and all its children. +Returns an array of all found components, directives, pipes or services which belong to matched elements and all its children. If the element is not specified, then the current fixture is used. - `ngMocks.findInstances( fixture?, directive )` @@ -29,6 +29,7 @@ const pipes = ngMocks.findInstances('div span.text', MyPipe); ``` :::important -A css selector helps to find the first matched element. -It will be used to look up the desired declaration. +A css selector helps to find instances in all matched `DebugElements`. +Therefore, the same instance can be found several times via nested `DebugElements` with the same selector. +In this case, the instance will be added to the returning array only once. ::: diff --git a/libs/ng-mocks/src/lib/mock-helper/find-instance/mock-helper.find-instances.ts b/libs/ng-mocks/src/lib/mock-helper/find-instance/mock-helper.find-instances.ts index 33e9c6aa59..573bd7b360 100644 --- a/libs/ng-mocks/src/lib/mock-helper/find-instance/mock-helper.find-instances.ts +++ b/libs/ng-mocks/src/lib/mock-helper/find-instance/mock-helper.find-instances.ts @@ -1,6 +1,6 @@ import { getSourceOfMock } from '../../common/func.get-source-of-mock'; import mockHelperCrawl from '../crawl/mock-helper.crawl'; -import mockHelperFind from '../find/mock-helper.find'; +import mockHelperFindAll from '../find/mock-helper.find-all'; import funcGetFromNode from '../func.get-from-node'; import funcGetLastFixture from '../func.get-last-fixture'; import funcParseFindArgs from '../func.parse-find-args'; @@ -15,13 +15,16 @@ export default (...args: any[]): T[] => { const declaration = getSourceOfMock(sel); const result: T[] = []; - mockHelperCrawl( - mockHelperFind(funcGetLastFixture(), el, undefined), - node => { - funcGetFromNode(result, node, declaration); - }, - true, - ); + const elements = mockHelperFindAll(funcGetLastFixture(), el, undefined); + for (const element of elements) { + mockHelperCrawl( + element, + node => { + funcGetFromNode(result, node, declaration); + }, + true, + ); + } return result; }; diff --git a/libs/ng-mocks/src/lib/mock-helper/find/mock-helper.find-all.ts b/libs/ng-mocks/src/lib/mock-helper/find/mock-helper.find-all.ts index e08fbb5165..bc8f13c91d 100644 --- a/libs/ng-mocks/src/lib/mock-helper/find/mock-helper.find-all.ts +++ b/libs/ng-mocks/src/lib/mock-helper/find/mock-helper.find-all.ts @@ -1,10 +1,15 @@ import { DebugElement } from '@angular/core'; +import isDebugNode from '../format/is-debug-node'; + import funcParseFindArgs from './func.parse-find-args'; import funcParseFindTerm from './func.parse-find-term'; export default (...args: any[]): DebugElement[] => { const [el, sel] = funcParseFindArgs(args); + if (isDebugNode(sel)) { + return [sel as any]; + } return el?.queryAll(funcParseFindTerm(sel)) || []; }; diff --git a/tests/issue-2105/test.spec.ts b/tests/issue-2105/test.spec.ts new file mode 100644 index 0000000000..9b65affce9 --- /dev/null +++ b/tests/issue-2105/test.spec.ts @@ -0,0 +1,59 @@ +import { Component, Input, NgModule } from '@angular/core'; +import { MockBuilder, MockRender, ngMocks } from 'ng-mocks'; + +@Component({ + selector: 'target', + template: ' {{ value }} ', +}) +class TargetComponent { + @Input() public readonly value: string | null = null; +} + +@NgModule({ + declarations: [TargetComponent], +}) +class TargetModule {} + +// @see https://github.com/ike18t/ng-mocks/issues/2105 +describe('issue-2105', () => { + beforeEach(() => MockBuilder(TargetComponent, TargetModule)); + + it('finds all instances', () => { + const fixture = MockRender(` +
+ + +
+ + +
+
+ + +
+ + +
+
+
+ `); + + expect(ngMocks.formatText(fixture)).toEqual('1 2 3 4 5 6 7 8'); + + // looking for all + { + const instances = ngMocks.findInstances('div', TargetComponent); + expect(instances.length).toEqual(8); + } + + // looking for children only + // it should collect data from child1, child2 and child3. + { + const instances = ngMocks.findInstances( + 'div.child', + TargetComponent, + ); + expect(instances.length).toEqual(6); + } + }); +});