Skip to content

Commit a55f675

Browse files
committed
fix(material/testing): Fix newly introduced issue caused by the addition
of floating label functionality to MatFormFieldControlHarness class Adding anything to this abstract class causes compilation issues when using MatFormFieldHarness.getControl(...) to fetch a type other than the directly supported types. The most common problems arise when fetching MatAutocompleteHarness or MatChipGridHarness, but I have found instances of other components such as MatCheckboxHarness. Moving the functionality to a base class resolves this.
1 parent 42b6ee6 commit a55f675

File tree

7 files changed

+17
-76
lines changed

7 files changed

+17
-76
lines changed

src/cdk/testing/component-harness.ts

+1-45
Original file line numberDiff line numberDiff line change
@@ -119,17 +119,6 @@ export interface HarnessLoader {
119119
*/
120120
getHarnessOrNull<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T | null>;
121121

122-
/**
123-
* Searches for an instance of the component corresponding to the given harness type under the
124-
* `HarnessLoader`'s root element, and returns a `ComponentHarness` for the instance on the page
125-
* at the given index. If no matching component exists at that index, an error is thrown.
126-
* @param query A query for a harness to create
127-
* @param index The zero-indexed offset of the matching component instance to return
128-
* @return An instance of the given harness type.
129-
* @throws If a matching component instance can't be found at the given index.
130-
*/
131-
getHarnessAtIndex<T extends ComponentHarness>(query: HarnessQuery<T>, index: number): Promise<T>;
132-
133122
/**
134123
* Searches for all instances of the component corresponding to the given harness type under the
135124
* `HarnessLoader`'s root element, and returns a list `ComponentHarness` for each instance.
@@ -138,14 +127,6 @@ export interface HarnessLoader {
138127
*/
139128
getAllHarnesses<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T[]>;
140129

141-
/**
142-
* Searches for all instances of the component corresponding to the given harness type under the
143-
* `HarnessLoader`'s root element, and returns the total count of all matching components.
144-
* @param query A query for a harness to create
145-
* @return An integer indicating the number of instances that were found.
146-
*/
147-
countHarnesses<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<number>;
148-
149130
/**
150131
* Searches for an instance of the component corresponding to the given harness type under the
151132
* `HarnessLoader`'s root element, and returns a boolean indicating if any were found.
@@ -519,20 +500,6 @@ export abstract class ContentContainerComponentHarness<S extends string = string
519500
return (await this.getRootHarnessLoader()).getHarnessOrNull(query);
520501
}
521502

522-
/**
523-
* Gets a matching harness for the given query and index within the current harness's content.
524-
* @param query The harness query to search for.
525-
* @param index The zero-indexed offset of the component to find.
526-
* @returns The first harness matching the given query.
527-
* @throws If no matching harness is found.
528-
*/
529-
async getHarnessAtIndex<T extends ComponentHarness>(
530-
query: HarnessQuery<T>,
531-
index: number,
532-
): Promise<T> {
533-
return (await this.getRootHarnessLoader()).getHarnessAtIndex(query, index);
534-
}
535-
536503
/**
537504
* Gets all matching harnesses for the given query within the current harness's content.
538505
* @param query The harness query to search for.
@@ -542,23 +509,12 @@ export abstract class ContentContainerComponentHarness<S extends string = string
542509
return (await this.getRootHarnessLoader()).getAllHarnesses(query);
543510
}
544511

545-
/**
546-
* Returns the number of matching harnesses for the given query within the current harness's
547-
* content.
548-
*
549-
* @param query The harness query to search for.
550-
* @returns The number of matching harnesses for the given query.
551-
*/
552-
async countHarnesses<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<number> {
553-
return (await this.getRootHarnessLoader()).countHarnesses(query);
554-
}
555-
556512
/**
557513
* Checks whether there is a matching harnesses for the given query within the current harness's
558514
* content.
559515
*
560516
* @param query The harness query to search for.
561-
* @returns Whether there is matching harnesses for the given query.
517+
* @returns Whetehr there is matching harnesses for the given query.
562518
*/
563519
async hasHarness<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<boolean> {
564520
return (await this.getRootHarnessLoader()).hasHarness(query);

src/material/datepicker/testing/date-range-input-harness.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ export class MatDateRangeInputHarness extends DatepickerTriggerHarnessBase {
9393

9494
/** Gets the floating label text for the range input, if it exists. */
9595
async getLabel(): Promise<string | null> {
96-
// Copied from MatFormFieldControlHarness since this class cannot extend two classes
96+
// Copied from MatFormFieldControlHarnessBase since this class cannot extend two classes
9797
const documentRootLocator = await this.documentRootLocatorFactory();
9898
const labelId = await (await this.host()).getAttribute('aria-labelledby');
9999
const hostId = await (await this.host()).getAttribute('id');

src/material/datepicker/testing/datepicker-input-harness-base.ts

+2-7
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99
import {ComponentHarnessConstructor, HarnessPredicate} from '@angular/cdk/testing';
10-
import {MatFormFieldControlHarness} from '@angular/material/form-field/testing/control';
10+
import {MatFormFieldControlHarnessBase} from '@angular/material/form-field/testing/control';
1111
import {DatepickerInputHarnessFilters} from './datepicker-harness-filters';
1212

1313
/** Sets up the filter predicates for a datepicker input harness. */
@@ -28,7 +28,7 @@ export function getInputPredicate<T extends MatDatepickerInputHarnessBase>(
2828
}
2929

3030
/** Base class for datepicker input harnesses. */
31-
export abstract class MatDatepickerInputHarnessBase extends MatFormFieldControlHarness {
31+
export abstract class MatDatepickerInputHarnessBase extends MatFormFieldControlHarnessBase {
3232
/** Whether the input is disabled. */
3333
async isDisabled(): Promise<boolean> {
3434
return (await this.host()).getProperty<boolean>('disabled');
@@ -39,11 +39,6 @@ export abstract class MatDatepickerInputHarnessBase extends MatFormFieldControlH
3939
return (await this.host()).getProperty<boolean>('required');
4040
}
4141

42-
/** Gets the floating label text for the input, if it exists. */
43-
async getLabel(): Promise<string | null> {
44-
return await this._getFloatingLabelText();
45-
}
46-
4742
/** Gets the value of the input. */
4843
async getValue(): Promise<string> {
4944
// The "value" property of the native input is always defined.

src/material/form-field/testing/control/form-field-control-harness.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,16 @@ import {ComponentHarness} from '@angular/cdk/testing';
1212
* Base class for custom form-field control harnesses. Harnesses for
1313
* custom controls with form-fields need to implement this interface.
1414
*/
15-
export abstract class MatFormFieldControlHarness extends ComponentHarness {
15+
export abstract class MatFormFieldControlHarness extends ComponentHarness {}
16+
17+
/**
18+
* Shared functionality for many MatFormFieldControlHarnesses
19+
*/
20+
export abstract class MatFormFieldControlHarnessBase extends MatFormFieldControlHarness {
1621
private readonly floatingLabelSelector = '.mdc-floating-label';
1722

1823
/** Gets the text content of the floating label, if it exists. */
19-
protected async _getFloatingLabelText(): Promise<string | null> {
24+
public async getLabel(): Promise<string | null> {
2025
const documentRootLocator = await this.documentRootLocatorFactory();
2126
const labelId = await (await this.host()).getAttribute('aria-labelledby');
2227
const hostId = await (await this.host()).getAttribute('id');

src/material/input/testing/input-harness.ts

+2-7
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
*/
88

99
import {HarnessPredicate, parallel} from '@angular/cdk/testing';
10-
import {MatFormFieldControlHarness} from '@angular/material/form-field/testing/control';
10+
import {MatFormFieldControlHarnessBase} from '@angular/material/form-field/testing/control';
1111
import {coerceBooleanProperty} from '@angular/cdk/coercion';
1212
import {InputHarnessFilters} from './input-harness-filters';
1313

1414
/** Harness for interacting with a standard Material inputs in tests. */
15-
export class MatInputHarness extends MatFormFieldControlHarness {
15+
export class MatInputHarness extends MatFormFieldControlHarnessBase {
1616
private readonly _documentRootLocator = this.documentRootLocatorFactory();
1717

1818
// TODO: We do not want to handle `select` elements with `matNativeControl` because
@@ -99,11 +99,6 @@ export class MatInputHarness extends MatFormFieldControlHarness {
9999
return await (await this.host()).getProperty<string>('id');
100100
}
101101

102-
/** Gets the floating label text for the input, if it exists. */
103-
async getLabel(): Promise<string | null> {
104-
return await this._getFloatingLabelText();
105-
}
106-
107102
/**
108103
* Focuses the input and returns a promise that indicates when the
109104
* action is complete.

src/material/input/testing/native-select-harness.ts

+2-7
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@
77
*/
88

99
import {HarnessPredicate, parallel} from '@angular/cdk/testing';
10-
import {MatFormFieldControlHarness} from '../../form-field/testing/control';
10+
import {MatFormFieldControlHarnessBase} from '../../form-field/testing/control';
1111
import {MatNativeOptionHarness} from './native-option-harness';
1212
import {
1313
NativeOptionHarnessFilters,
1414
NativeSelectHarnessFilters,
1515
} from './native-select-harness-filters';
1616

1717
/** Harness for interacting with a native `select` in tests. */
18-
export class MatNativeSelectHarness extends MatFormFieldControlHarness {
18+
export class MatNativeSelectHarness extends MatFormFieldControlHarnessBase {
1919
static hostSelector = 'select[matNativeControl]';
2020

2121
/**
@@ -61,11 +61,6 @@ export class MatNativeSelectHarness extends MatFormFieldControlHarness {
6161
return await (await this.host()).getProperty<string>('id');
6262
}
6363

64-
/** Gets the floating label text for the input, if it exists. */
65-
async getLabel(): Promise<string | null> {
66-
return await this._getFloatingLabelText();
67-
}
68-
6964
/** Focuses the select and returns a void promise that indicates when the action is complete. */
7065
async focus(): Promise<void> {
7166
return (await this.host()).focus();

src/material/select/testing/select-harness.ts

+2-7
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ import {
1313
OptionHarnessFilters,
1414
OptgroupHarnessFilters,
1515
} from '@angular/material/core/testing';
16-
import {MatFormFieldControlHarness} from '@angular/material/form-field/testing/control';
16+
import {MatFormFieldControlHarnessBase} from '@angular/material/form-field/testing/control';
1717
import {SelectHarnessFilters} from './select-harness-filters';
1818

1919
/** Harness for interacting with a mat-select in tests. */
20-
export class MatSelectHarness extends MatFormFieldControlHarness {
20+
export class MatSelectHarness extends MatFormFieldControlHarnessBase {
2121
static hostSelector = '.mat-mdc-select';
2222
private _prefix = 'mat-mdc';
2323
private _optionClass = MatOptionHarness;
@@ -74,11 +74,6 @@ export class MatSelectHarness extends MatFormFieldControlHarness {
7474
return value.text();
7575
}
7676

77-
/** Gets the floating label text for the select, if it exists. */
78-
async getLabel(): Promise<string | null> {
79-
return await this._getFloatingLabelText();
80-
}
81-
8277
/** Focuses the select and returns a void promise that indicates when the action is complete. */
8378
async focus(): Promise<void> {
8479
return (await this.host()).focus();

0 commit comments

Comments
 (0)