Skip to content

Commit

Permalink
feat(cdk/testing): add methods getOptionalHarness and hasHarness (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
mmalerba committed Feb 5, 2022
1 parent dd59b4a commit 64606fa
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 0 deletions.
26 changes: 26 additions & 0 deletions src/cdk/testing/component-harness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,31 @@ export interface HarnessLoader {
*/
getHarness<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T>;

/**
* 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<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T | null>;

/**
* 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.
* @param query A query for a harness to create
* @return A list instances of the given harness type.
*/
getAllHarnesses<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T[]>;

/**
* 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<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<boolean>;
}

/**
Expand Down Expand Up @@ -403,10 +421,18 @@ export abstract class ContentContainerComponentHarness<S extends string = string
return (await this.getRootHarnessLoader()).getHarness(query);
}

async getHarnessOrNull<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T | null> {
return (await this.getRootHarnessLoader()).getHarnessOrNull(query);
}

async getAllHarnesses<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T[]> {
return (await this.getRootHarnessLoader()).getAllHarnesses(query);
}

async hasHarness<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<boolean> {
return (await this.getRootHarnessLoader()).hasHarness(query);
}

/**
* Gets the root harness loader from which to start
* searching for content contained by this harness.
Expand Down
10 changes: 10 additions & 0 deletions src/cdk/testing/harness-environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,21 @@ export abstract class HarnessEnvironment<E> implements HarnessLoader, LocatorFac
return this.locatorFor(query)();
}

// Implemented as part of the `HarnessLoader` interface.
getHarnessOrNull<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T | null> {
return this.locatorForOptional(query)();
}

// Implemented as part of the `HarnessLoader` interface.
getAllHarnesses<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T[]> {
return this.locatorForAll(query)();
}

// Implemented as part of the `HarnessLoader` interface.
async hasHarness<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<boolean> {
return (await this.locatorForOptional(query)()) !== null;
}

// Implemented as part of the `HarnessLoader` interface.
async getChildLoader(selector: string): Promise<HarnessLoader> {
return this.createEnvironment(
Expand Down
18 changes: 18 additions & 0 deletions src/cdk/testing/tests/cross-environment.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down
10 changes: 10 additions & 0 deletions tools/public_api_guard/cdk/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,11 @@ export abstract class ContentContainerComponentHarness<S extends string = string
getChildLoader(selector: S): Promise<HarnessLoader>;
// (undocumented)
getHarness<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T>;
// (undocumented)
getHarnessOrNull<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T | null>;
protected getRootHarnessLoader(): Promise<HarnessLoader>;
// (undocumented)
hasHarness<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<boolean>;
}

// @public
Expand Down Expand Up @@ -103,12 +107,16 @@ export abstract class HarnessEnvironment<E> implements HarnessLoader, LocatorFac
// (undocumented)
getHarness<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T>;
// (undocumented)
getHarnessOrNull<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T | null>;
// (undocumented)
harnessLoaderFor(selector: string): Promise<HarnessLoader>;
// (undocumented)
harnessLoaderForAll(selector: string): Promise<HarnessLoader[]>;
// (undocumented)
harnessLoaderForOptional(selector: string): Promise<HarnessLoader | null>;
// (undocumented)
hasHarness<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<boolean>;
// (undocumented)
locatorFor<T extends (HarnessQuery<any> | string)[]>(...queries: T): AsyncFactoryFn<LocatorFnResult<T>>;
// (undocumented)
locatorForAll<T extends (HarnessQuery<any> | string)[]>(...queries: T): AsyncFactoryFn<LocatorFnResult<T>[]>;
Expand All @@ -131,6 +139,8 @@ export interface HarnessLoader {
getAllHarnesses<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T[]>;
getChildLoader(selector: string): Promise<HarnessLoader>;
getHarness<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T>;
getHarnessOrNull<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T | null>;
hasHarness<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<boolean>;
}

// @public
Expand Down

0 comments on commit 64606fa

Please sign in to comment.