Skip to content

Commit f0f46f3

Browse files
fix(root): ignore signal-based queries
closes #8634
1 parent 5c98e73 commit f0f46f3

File tree

3 files changed

+110
-4
lines changed

3 files changed

+110
-4
lines changed

libs/ng-mocks/src/lib/common/decorate.queries.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,13 @@ const generateFinalQueries = (queries: {
2626
const scanKeys: string[] = [];
2727

2828
for (const key of Object.keys(queries)) {
29-
const query: Query & { ngMetadataName?: string } = queries[key];
30-
final.push([key, query]);
29+
const query: Query & { ngMetadataName?: string; isSignal?: boolean } = queries[key];
3130

32-
if (!query.isViewQuery && !isInternalKey(key)) {
31+
if (!query.isSignal) {
32+
final.push([key, query]);
33+
}
34+
35+
if (!query.isViewQuery && !query.isSignal && !isInternalKey(key)) {
3336
scanKeys.push(key);
3437
final.push([`__ngMocksVcr_${key}`, cloneVcrQuery(query)]);
3538
}

libs/ng-mocks/src/lib/mock-component/render/generate-template.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,13 @@ export default (queries?: Record<keyof any, any>): string => {
2727
}
2828

2929
for (const key of Object.keys(queries)) {
30-
const query: Query = queries[key];
30+
const query: Query & { isSignal?: boolean } = queries[key];
3131
if (!isTemplateRefQuery(query)) {
3232
continue;
3333
}
34+
if (query.isSignal) {
35+
continue;
36+
}
3437
if (typeof query.selector === 'string') {
3538
const selector = query.selector.replace(new RegExp('\\W', 'mg'), '_');
3639
queries[`__mockView_key_${selector}`] = new ViewChild(`key_${selector}`, viewChildArgs);

tests-e2e/src/issue-8634/test.spec.ts

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import {
2+
Component,
3+
ElementRef,
4+
Input,
5+
contentChild,
6+
contentChildren,
7+
input,
8+
viewChild,
9+
viewChildren,
10+
} from '@angular/core';
11+
import { MockBuilder, MockRender } from 'ng-mocks';
12+
13+
@Component({
14+
selector: 'app-nested',
15+
standalone: true,
16+
template: `
17+
<div #meow>Nested content</div>
18+
19+
<h3>Queries:</h3>
20+
<ul>
21+
<li>meowViewChild: {{ !!meowViewChild() }}</li>
22+
<li>meowViewChildren: {{ !!meowViewChildren() }}</li>
23+
<li>meowContentChild: {{ !!meowContentChild() }}</li>
24+
<li>meowContentChildren: {{ !!meowContentChildren() }}</li>
25+
</ul>
26+
`,
27+
})
28+
class NestedComponent {
29+
readonly meowViewChild = viewChild<ElementRef>('meow');
30+
readonly meowViewChildren = viewChildren<ElementRef>('meow');
31+
readonly meowContentChild = contentChild<ElementRef>('meow');
32+
readonly meowContentChildren = contentChildren<ElementRef>('meow');
33+
34+
readonly name = input.required<string>();
35+
}
36+
37+
@Component({
38+
selector: 'app-target',
39+
standalone: true,
40+
imports: [NestedComponent],
41+
template: `
42+
<app-nested></app-nested>
43+
<div>name: {{ name }}</div>
44+
`,
45+
})
46+
class TargetComponent {
47+
@Input() public readonly name: string = '';
48+
}
49+
50+
@Component({
51+
selector: 'app-separate',
52+
standalone: true,
53+
template: `
54+
<div>Is odd: {{ count() % 2 === 1 }}</div>
55+
56+
<h3>Queries:</h3>
57+
<ul>
58+
<li>meowViewChild: {{ !!meowViewChild() }}</li>
59+
<li>meowViewChildren: {{ !!meowViewChildren() }}</li>
60+
<li>meowContentChild: {{ !!meowContentChild() }}</li>
61+
<li>meowContentChildren: {{ !!meowContentChildren() }}</li>
62+
</ul>
63+
`,
64+
})
65+
class SeparateComponent {
66+
readonly count = input.required();
67+
68+
readonly meowViewChild = viewChild<ElementRef>('meow');
69+
readonly meowViewChildren = viewChildren<ElementRef>('meow');
70+
readonly meowContentChild = contentChild<ElementRef>('meow');
71+
readonly meowContentChildren = contentChildren<ElementRef>('meow');
72+
}
73+
74+
describe('issue-8634', () => {
75+
describe('child component', () => {
76+
beforeEach(() => MockBuilder(TargetComponent));
77+
78+
it('should not fail because of the usage of viewChild/contendChild', () => {
79+
const fixture = MockRender(TargetComponent, {
80+
name: 'sandbox',
81+
});
82+
expect(fixture.nativeElement.innerHTML).toContain(
83+
'name: sandbox',
84+
);
85+
});
86+
});
87+
88+
describe('referenced component', () => {
89+
beforeEach(() => MockBuilder(SeparateComponent));
90+
91+
it('should not fail because of the usage of viewChild/contendChild', () => {
92+
const fixture = MockRender(SeparateComponent, {
93+
count: 3,
94+
});
95+
expect(fixture.nativeElement.innerHTML).toContain(
96+
'Is odd: true',
97+
);
98+
});
99+
});
100+
});

0 commit comments

Comments
 (0)