From 64606fa65bd0d307a87d8a64b7db0da90105102c Mon Sep 17 00:00:00 2001 From: Miles Malerba Date: Sat, 5 Feb 2022 08:06:34 +0000 Subject: [PATCH] feat(cdk/testing): add methods `getOptionalHarness` and `hasHarness` (#24355) --- src/cdk/testing/component-harness.ts | 26 +++++++++++++++++++ src/cdk/testing/harness-environment.ts | 10 +++++++ .../testing/tests/cross-environment.spec.ts | 18 +++++++++++++ tools/public_api_guard/cdk/testing.md | 10 +++++++ 4 files changed, 64 insertions(+) diff --git a/src/cdk/testing/component-harness.ts b/src/cdk/testing/component-harness.ts index 81aa3476b521..79bec66ad5ad 100644 --- a/src/cdk/testing/component-harness.ts +++ b/src/cdk/testing/component-harness.ts @@ -96,6 +96,16 @@ export interface HarnessLoader { */ getHarness(query: HarnessQuery): Promise; + /** + * Searches for an instance of the component corresponding to the given harness type under the + * `HarnessLoader`'s root element, and returns a `ComponentHarness` for that instance. If multiple + * matching components are found, a harness for the first one is returned. If no matching + * component is found, null is returned. + * @param query A query for a harness to create + * @return An instance of the given harness type (or null if not found). + */ + getHarnessOrNull(query: HarnessQuery): Promise; + /** * Searches for all instances of the component corresponding to the given harness type under the * `HarnessLoader`'s root element, and returns a list `ComponentHarness` for each instance. @@ -103,6 +113,14 @@ export interface HarnessLoader { * @return A list instances of the given harness type. */ getAllHarnesses(query: HarnessQuery): Promise; + + /** + * Searches for an instance of the component corresponding to the given harness type under the + * `HarnessLoader`'s root element, and returns a boolean indicating if any were found. + * @param query A query for a harness to create + * @return A boolean indicating if an instance was found. + */ + hasHarness(query: HarnessQuery): Promise; } /** @@ -403,10 +421,18 @@ export abstract class ContentContainerComponentHarness(query: HarnessQuery): Promise { + return (await this.getRootHarnessLoader()).getHarnessOrNull(query); + } + async getAllHarnesses(query: HarnessQuery): Promise { return (await this.getRootHarnessLoader()).getAllHarnesses(query); } + async hasHarness(query: HarnessQuery): Promise { + return (await this.getRootHarnessLoader()).hasHarness(query); + } + /** * Gets the root harness loader from which to start * searching for content contained by this harness. diff --git a/src/cdk/testing/harness-environment.ts b/src/cdk/testing/harness-environment.ts index cb2ea81521aa..277a842e7f19 100644 --- a/src/cdk/testing/harness-environment.ts +++ b/src/cdk/testing/harness-environment.ts @@ -117,11 +117,21 @@ export abstract class HarnessEnvironment implements HarnessLoader, LocatorFac return this.locatorFor(query)(); } + // Implemented as part of the `HarnessLoader` interface. + getHarnessOrNull(query: HarnessQuery): Promise { + return this.locatorForOptional(query)(); + } + // Implemented as part of the `HarnessLoader` interface. getAllHarnesses(query: HarnessQuery): Promise { return this.locatorForAll(query)(); } + // Implemented as part of the `HarnessLoader` interface. + async hasHarness(query: HarnessQuery): Promise { + return (await this.locatorForOptional(query)()) !== null; + } + // Implemented as part of the `HarnessLoader` interface. async getChildLoader(selector: string): Promise { return this.createEnvironment( diff --git a/src/cdk/testing/tests/cross-environment.spec.ts b/src/cdk/testing/tests/cross-environment.spec.ts index e6d6827670ce..553b3b916da7 100644 --- a/src/cdk/testing/tests/cross-environment.spec.ts +++ b/src/cdk/testing/tests/cross-environment.spec.ts @@ -89,10 +89,28 @@ export function crossEnvironmentSpecs( } }); + it('should get first matching component for optional harness', async () => { + const harness = await loader.getHarnessOrNull(SubComponentHarness); + expect(harness).not.toBeNull(); + expect(await (await harness!.title()).text()).toBe('List of test tools'); + }); + + it('should get null if no matching component found for optional harness', async () => { + const countersLoader = await loader.getChildLoader('.counters'); + const harness = await countersLoader.getHarnessOrNull(SubComponentHarness); + expect(harness).toBeNull(); + }); + it('should get all matching components for all harnesses', async () => { const harnesses = await loader.getAllHarnesses(SubComponentHarness); expect(harnesses.length).toBe(4); }); + + it('should check if harness is found', async () => { + const countersLoader = await loader.getChildLoader('.counters'); + expect(await loader.hasHarness(SubComponentHarness)).toBe(true); + expect(await countersLoader.hasHarness(SubComponentHarness)).toBe(false); + }); }); describe('ComponentHarness', () => { diff --git a/tools/public_api_guard/cdk/testing.md b/tools/public_api_guard/cdk/testing.md index 3d7a0ad36201..a256b1a5cd15 100644 --- a/tools/public_api_guard/cdk/testing.md +++ b/tools/public_api_guard/cdk/testing.md @@ -56,7 +56,11 @@ export abstract class ContentContainerComponentHarness; // (undocumented) getHarness(query: HarnessQuery): Promise; + // (undocumented) + getHarnessOrNull(query: HarnessQuery): Promise; protected getRootHarnessLoader(): Promise; + // (undocumented) + hasHarness(query: HarnessQuery): Promise; } // @public @@ -103,12 +107,16 @@ export abstract class HarnessEnvironment implements HarnessLoader, LocatorFac // (undocumented) getHarness(query: HarnessQuery): Promise; // (undocumented) + getHarnessOrNull(query: HarnessQuery): Promise; + // (undocumented) harnessLoaderFor(selector: string): Promise; // (undocumented) harnessLoaderForAll(selector: string): Promise; // (undocumented) harnessLoaderForOptional(selector: string): Promise; // (undocumented) + hasHarness(query: HarnessQuery): Promise; + // (undocumented) locatorFor | string)[]>(...queries: T): AsyncFactoryFn>; // (undocumented) locatorForAll | string)[]>(...queries: T): AsyncFactoryFn[]>; @@ -131,6 +139,8 @@ export interface HarnessLoader { getAllHarnesses(query: HarnessQuery): Promise; getChildLoader(selector: string): Promise; getHarness(query: HarnessQuery): Promise; + getHarnessOrNull(query: HarnessQuery): Promise; + hasHarness(query: HarnessQuery): Promise; } // @public