From 53b29ca0c0675c39d696e97ff783835f76292a16 Mon Sep 17 00:00:00 2001
From: Tim Deschryver <28659384+timdeschryver@users.noreply.github.com>
Date: Thu, 29 Sep 2022 13:10:02 +0000
Subject: [PATCH 1/3] docs: add issue as an example
---
.../src/app/issues/issue-316.spec.ts | 78 +++++++++++++++++++
1 file changed, 78 insertions(+)
create mode 100644 apps/example-app/src/app/issues/issue-316.spec.ts
diff --git a/apps/example-app/src/app/issues/issue-316.spec.ts b/apps/example-app/src/app/issues/issue-316.spec.ts
new file mode 100644
index 0000000..4dd3881
--- /dev/null
+++ b/apps/example-app/src/app/issues/issue-316.spec.ts
@@ -0,0 +1,78 @@
+import { Component, Input } from '@angular/core'
+import { render, screen } from '@testing-library/angular'
+
+describe('TagComponent', () => {
+ it('create a tag default primary', async () => {
+ await render(`primary`, {
+ declarations: [TagComponent],
+ })
+
+ expect(screen.getByText(/primary/i)).toBeInTheDocument()
+ expect(screen.getByRole('tag')).toHaveClass('hc-tag-primary')
+ })
+})
+
+
+@Component({
+ selector: 'hc-tag',
+ template: `
+
+
+
+ `,
+ styles: [
+ `
+ .hc-tag {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--neutral-white);
+ padding: 4px 10px;
+ border-radius: 6px;
+ }
+
+ .hc-tag-primary {
+ background-color: var(--primary-default);
+ }
+
+ .hc-tag-success {
+ background-color: var(--green-default);
+ }
+
+ .hc-tag-info {
+ background-color: var(--primary-default);
+ }
+
+ .hc-tag-warning {
+ background-color: var(--yellow-default);
+ }
+
+ .hc-tag-danger {
+ background-color: var(--red-default);
+ }
+
+ .hc-tag-rounded {
+ border-radius: 10rem;
+ }
+ `,
+ ],
+})
+export class TagComponent {
+ @Input() severity: 'success' | 'info' | 'warning' | 'danger' | 'primary' = 'primary'
+ @Input() rounded = false
+ @Input() ariaLabel?: string
+
+ get classes() {
+ return {
+ ['hc-tag']: true,
+ [`hc-tag-${this.severity}`]: true,
+ ['hc-tag-rounded']: this.rounded,
+ }
+ }
+}
+
From 02a688b9797adf4452feb0077a08e218246e59a9 Mon Sep 17 00:00:00 2001
From: "allcontributors[bot]"
<46447321+allcontributors[bot]@users.noreply.github.com>
Date: Mon, 28 Nov 2022 17:08:33 +0100
Subject: [PATCH 2/3] docs: add JJosephttg as a contributor for code, and test
(#334)
* docs: update README.md [skip ci]
* docs: update .all-contributorsrc [skip ci]
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
---
.all-contributorsrc | 13 ++++++-
README.md | 87 +++++++++++++++++++++++----------------------
2 files changed, 57 insertions(+), 43 deletions(-)
diff --git a/.all-contributorsrc b/.all-contributorsrc
index df2ae0b..bc403e2 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -312,6 +312,16 @@
"contributions": [
"code"
]
+ },
+ {
+ "login": "JJosephttg",
+ "name": "Josh Joseph",
+ "avatar_url": "https://avatars.githubusercontent.com/u/23690250?v=4",
+ "profile": "https://github.com/JJosephttg",
+ "contributions": [
+ "code",
+ "test"
+ ]
}
],
"contributorsPerLine": 7,
@@ -319,5 +329,6 @@
"projectOwner": "testing-library",
"repoType": "github",
"repoHost": "https://github.com",
- "skipCi": true
+ "skipCi": true,
+ "commitConvention": "angular"
}
diff --git a/README.md b/README.md
index 2d46cd9..231a0a0 100644
--- a/README.md
+++ b/README.md
@@ -183,48 +183,51 @@ Thanks goes to these people ([emoji key][emojis]):
From 6e951ad36366310551b128a406187862730e16f2 Mon Sep 17 00:00:00 2001
From: Josh Joseph
Date: Mon, 28 Nov 2022 11:09:55 -0500
Subject: [PATCH 3/3] feat: childComponentOverrides property to override nested
child providers (#332)
---
projects/testing-library/src/lib/models.ts | 25 ++++++
.../src/lib/testing-library.ts | 10 ++-
projects/testing-library/tests/render.spec.ts | 81 ++++++++++++++-----
3 files changed, 94 insertions(+), 22 deletions(-)
diff --git a/projects/testing-library/src/lib/models.ts b/projects/testing-library/src/lib/models.ts
index 953c244..1f33192 100644
--- a/projects/testing-library/src/lib/models.ts
+++ b/projects/testing-library/src/lib/models.ts
@@ -186,6 +186,26 @@ export interface RenderComponentOptions[];
/**
* @description
* A collection of imports to override a standalone component's imports with.
@@ -273,6 +293,11 @@ export interface RenderComponentOptions {
+ component: Type;
+ providers: any[];
+}
+
// eslint-disable-next-line @typescript-eslint/ban-types
export interface RenderTemplateOptions
extends RenderComponentOptions {
diff --git a/projects/testing-library/src/lib/testing-library.ts b/projects/testing-library/src/lib/testing-library.ts
index 933e982..24e2085 100644
--- a/projects/testing-library/src/lib/testing-library.ts
+++ b/projects/testing-library/src/lib/testing-library.ts
@@ -25,7 +25,7 @@ import {
queries as dtlQueries,
} from '@testing-library/dom';
import type { Queries, BoundFunctions } from '@testing-library/dom';
-import { RenderComponentOptions, RenderTemplateOptions, RenderResult } from './models';
+import { RenderComponentOptions, RenderTemplateOptions, RenderResult, ComponentOverride } from './models';
import { getConfig } from './config';
const mountedFixtures = new Set>();
@@ -55,6 +55,7 @@ export async function render(
wrapper = WrapperComponent as Type,
componentProperties = {},
componentProviders = [],
+ childComponentOverrides = [],
ɵcomponentImports: componentImports,
excludeComponentDeclaration = false,
routes = [],
@@ -85,6 +86,7 @@ export async function render(
schemas: [...schemas],
});
overrideComponentImports(sut, componentImports);
+ overrideChildComponentProviders(childComponentOverrides);
await TestBed.compileComponents();
@@ -282,6 +284,12 @@ function overrideComponentImports(sut: Type | string, imports:
}
}
+function overrideChildComponentProviders(componentOverrides: ComponentOverride[]) {
+ componentOverrides?.forEach(({ component, providers }) => {
+ TestBed.overrideComponent(component, { set: { providers } });
+ });
+}
+
function hasOnChangesHook(componentInstance: SutType): componentInstance is SutType & OnChanges {
return (
'ngOnChanges' in componentInstance && typeof (componentInstance as SutType & OnChanges).ngOnChanges === 'function'
diff --git a/projects/testing-library/tests/render.spec.ts b/projects/testing-library/tests/render.spec.ts
index 1faec70..4200bc9 100644
--- a/projects/testing-library/tests/render.spec.ts
+++ b/projects/testing-library/tests/render.spec.ts
@@ -7,6 +7,7 @@ import {
SimpleChanges,
APP_INITIALIZER,
ApplicationInitStatus,
+ Injectable,
} from '@angular/core';
import { NoopAnimationsModule, BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { TestBed } from '@angular/core/testing';
@@ -19,7 +20,7 @@ import { render, fireEvent, screen } from '../src/public_api';
`,
})
-class FixtureComponent { }
+class FixtureComponent {}
test('creates queries and events', async () => {
const view = await render(FixtureComponent);
@@ -50,46 +51,84 @@ describe('standalone', () => {
describe('standalone with child', () => {
@Component({
- selector: 'child-fixture',
+ selector: 'atl-child-fixture',
template: `A child fixture`,
standalone: true,
})
- class ChildFixture { }
+ class ChildFixtureComponent {}
@Component({
- selector: 'child-fixture',
+ selector: 'atl-child-fixture',
template: `A mock child fixture`,
standalone: true,
})
- class MockChildFixture { }
+ class MockChildFixtureComponent {}
@Component({
- selector: 'parent-fixture',
+ selector: 'atl-parent-fixture',
template: `Parent fixture
-
`,
+ `,
standalone: true,
- imports: [ChildFixture],
+ imports: [ChildFixtureComponent],
})
- class ParentFixture { }
+ class ParentFixtureComponent {}
it('renders the standalone component with child', async () => {
- await render(ParentFixture);
- expect(screen.getByText('Parent fixture'));
- expect(screen.getByText('A child fixture'));
+ await render(ParentFixtureComponent);
+ expect(screen.getByText('Parent fixture')).toBeInTheDocument();
+ expect(screen.getByText('A child fixture')).toBeInTheDocument();
});
- it('renders the standalone component with child', async () => {
- await render(ParentFixture, { ɵcomponentImports: [MockChildFixture] });
- expect(screen.getByText('Parent fixture'));
- expect(screen.getByText('A mock child fixture'));
+ it('renders the standalone component with child given ɵcomponentImports', async () => {
+ await render(ParentFixtureComponent, { ɵcomponentImports: [MockChildFixtureComponent] });
+ expect(screen.getByText('Parent fixture')).toBeInTheDocument();
+ expect(screen.getByText('A mock child fixture')).toBeInTheDocument();
});
it('rejects render of template with componentImports set', () => {
- const result = render(``, {
- imports: [ParentFixture],
- ɵcomponentImports: [MockChildFixture],
+ const view = render(``, {
+ imports: [ParentFixtureComponent],
+ ɵcomponentImports: [MockChildFixtureComponent],
+ });
+ return expect(view).rejects.toMatchObject({ message: /Error while rendering/ });
+ });
+});
+
+describe('childComponentOverrides', () => {
+ @Injectable()
+ class MySimpleService {
+ public value = 'real';
+ }
+
+ @Component({
+ selector: 'atl-child-fixture',
+ template: `{{ simpleService.value }}`,
+ standalone: true,
+ providers: [MySimpleService],
+ })
+ class NestedChildFixtureComponent {
+ public constructor(public simpleService: MySimpleService) {}
+ }
+
+ @Component({
+ selector: 'atl-parent-fixture',
+ template: ``,
+ standalone: true,
+ imports: [NestedChildFixtureComponent],
+ })
+ class ParentFixtureComponent {}
+
+ it('renders with overridden child service when specified', async () => {
+ await render(ParentFixtureComponent, {
+ childComponentOverrides: [
+ {
+ component: NestedChildFixtureComponent,
+ providers: [{ provide: MySimpleService, useValue: { value: 'fake' } }],
+ },
+ ],
});
- return expect(result).rejects.toMatchObject({ message: /Error while rendering/ });
+
+ expect(screen.getByText('fake')).toBeInTheDocument();
});
});
@@ -117,7 +156,7 @@ describe('animationModule', () => {
@NgModule({
declarations: [FixtureComponent],
})
- class FixtureModule { }
+ class FixtureModule {}
describe('excludeComponentDeclaration', () => {
it('does not throw if component is declared in an imported module', async () => {
await render(FixtureComponent, {