From 806898d13290cd1771e14f183322d71d845eb6b0 Mon Sep 17 00:00:00 2001 From: Sabrina Mack Date: Sat, 22 Jun 2024 13:30:12 -0700 Subject: [PATCH] fix: unable to bind ngIf in angular 17+ Use new angular control flow to avoid missing directive while mocking child templates Solves #8884 --- .../render/generate-template.ts | 12 +++- tests/issue-8884/test.spec.ts | 66 +++++++++++++++++++ 2 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 tests/issue-8884/test.spec.ts diff --git a/libs/ng-mocks/src/lib/mock-component/render/generate-template.ts b/libs/ng-mocks/src/lib/mock-component/render/generate-template.ts index da227d836e..5ae5e13630 100644 --- a/libs/ng-mocks/src/lib/mock-component/render/generate-template.ts +++ b/libs/ng-mocks/src/lib/mock-component/render/generate-template.ts @@ -1,9 +1,15 @@ -import { Query, TemplateRef, ViewChild, ViewContainerRef } from '@angular/core'; +import { Query, TemplateRef, ViewChild, ViewContainerRef, VERSION } from '@angular/core'; +const hasControlFlow = Number.parseInt(VERSION.major, 10) >= 17; const viewChildArgs: any = { read: ViewContainerRef, static: false }; -const viewChildTemplate = (selector: string, key: string): string => - `
`; +const viewChildTemplate = (selector: string, key: string): string => { + const content = `
`; + const condition = `ngMocksRender_${key}_${selector}`; + return hasControlFlow + ? `@if (${condition}) { ${content} }` + : `${content}`; +}; const isTemplateRefQuery = (query: Query): boolean => { if (query.isViewQuery) { diff --git a/tests/issue-8884/test.spec.ts b/tests/issue-8884/test.spec.ts new file mode 100644 index 0000000000..12d2171461 --- /dev/null +++ b/tests/issue-8884/test.spec.ts @@ -0,0 +1,66 @@ +import { + Component, + ContentChild, + NgModule, + TemplateRef, + VERSION, +} from '@angular/core'; + +import { MockBuilder, MockRender, ngMocks } from 'ng-mocks'; + +// @see https://github.com/help-me-mom/ng-mocks/issues/8884 +describe('issue-8884', () => { + ngMocks.throwOnConsole(); + + if (Number.parseInt(VERSION.major, 10) < 17) { + it('needs a17+', () => { + expect(true).toBeTruthy(); + }); + + return; + } + + describe('when standalone component does not import NgIf', () => { + @Component({ + selector: 'app-standalone', + standalone: true, + template: ``, + }) + class StandaloneComponent { + @ContentChild('content') + content?: TemplateRef; + } + + beforeEach(() => MockBuilder(null, StandaloneComponent)); + + it('should create', () => { + MockRender(`Test content`); + + expect(ngMocks.findInstance(StandaloneComponent)).toBeTruthy(); + }); + }); + + describe('when NgIf is not avaiable to a component in a module', () => { + @Component({ + selector: 'app-target', + template: ``, + }) + class TargetComponent { + @ContentChild('content') + content?: TemplateRef; + } + + @NgModule({ + declarations: [TargetComponent], + }) + class TargetModule {} + + beforeEach(() => MockBuilder(null, TargetModule)); + + it('should create', () => { + MockRender(`Test content`); + + expect(ngMocks.findInstance(TargetComponent)).toBeTruthy(); + }); + }); +});