Skip to content

Commit

Permalink
fix: unable to bind ngIf in angular 17+
Browse files Browse the repository at this point in the history
Use new angular control flow to avoid missing directive while mocking child templates

Solves #8884
  • Loading branch information
sabrina-10kc committed Jul 23, 2024
1 parent 5b10131 commit f6e45d3
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 3 deletions.
12 changes: 9 additions & 3 deletions libs/ng-mocks/src/lib/mock-component/render/generate-template.ts
Original file line number Diff line number Diff line change
@@ -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 =>
`<div *ngIf="ngMocksRender_${key}_${selector}" data-${key}="${selector}"><ng-template #${key}_${selector}></ng-template></div>`;
const viewChildTemplate = (selector: string, key: string): string => {
const content = `<div data-${key}="${selector}"><ng-template #${key}_${selector}></ng-template></div>`;
const condition = `ngMocksRender_${key}_${selector}`;
return hasControlFlow
? `@if (${condition}) { ${content} }`
: `<ng-template [ngIf]="${condition}">${content}</ng-template>`;
};

const isTemplateRefQuery = (query: Query): boolean => {
if (query.isViewQuery) {
Expand Down
66 changes: 66 additions & 0 deletions tests/issue-8884/test.spec.ts
Original file line number Diff line number Diff line change
@@ -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: `<ng-template [ngTemplateOutlet]="content" />`,
})
class StandaloneComponent {
@ContentChild('content')
content?: TemplateRef<any>;
}

beforeEach(() => MockBuilder(null, StandaloneComponent));

it('should create', () => {
MockRender(`<app-standalone>Test content</app-standalone>`);

expect(ngMocks.findInstance(StandaloneComponent)).toBeTruthy();
});
});

describe('when NgIf is not avaiable to a component in a module', () => {
@Component({
selector: 'app-target',
template: `<ng-template [ngTemplateOutlet]="content" />`,
})
class TargetComponent {
@ContentChild('content')
content?: TemplateRef<any>;
}

@NgModule({
declarations: [TargetComponent],
})
class TargetModule {}

beforeEach(() => MockBuilder(null, TargetModule));

it('should create', () => {
MockRender(`<app-target>Test content</app-target>`);

expect(ngMocks.findInstance(TargetComponent)).toBeTruthy();
});
});
});

0 comments on commit f6e45d3

Please sign in to comment.