Skip to content

perf(cdk/testing): Improve performance of clicking in unit tests. #20441

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Sep 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/cdk/testing/protractor/protractor-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,11 @@ export class ProtractorElement implements TestElement {
return this.element.clear();
}

async click(...args: number[]): Promise<void> {
async click(...args: [] | ['center'] | [number, number]): Promise<void> {
// Omitting the offset argument to mouseMove results in clicking the center.
// This is the default behavior we want, so we use an empty array of offsetArgs if no args are
// passed to this method.
const offsetArgs = args.length ? [{x: args[0], y: args[1]}] : [];
const offsetArgs = args.length === 2 ? [{x: args[0], y: args[1]}] : [];

await browser.actions()
.mouseMove(await this.element.getWebElement(), ...offsetArgs)
Expand Down
9 changes: 8 additions & 1 deletion src/cdk/testing/test-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,16 @@ export interface TestElement {
/** Clear the element's input (for input and textarea elements only). */
clear(): Promise<void>;

/** Click the element at the element's center. */
/**
* Click the element at the default location for the current environment. If you need to guarantee
* the element is clicked at a specific location, consider using `click('center')` or
* `click(x, y)` instead.
*/
click(): Promise<void>;

/** Click the element at the element's center. */
click(location: 'center'): Promise<void>;

/**
* Click the element at the specified coordinates relative to the top-left of the element.
* @param relativeX Coordinate within the element, along the X-axis at which to click.
Expand Down
22 changes: 13 additions & 9 deletions src/cdk/testing/testbed/unit-test-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,19 @@ export class UnitTestElement implements TestElement {
await this._stabilize();
}

async click(...args: number[]): Promise<void> {
const {left, top, width, height} = await this.getDimensions();
const relativeX = args.length ? args[0] : width / 2;
const relativeY = args.length ? args[1] : height / 2;

// Round the computed click position as decimal pixels are not
// supported by mouse events and could lead to unexpected results.
const clientX = Math.round(left + relativeX);
const clientY = Math.round(top + relativeY);
async click(...args: [] | ['center'] | [number, number]): Promise<void> {
let clientX: number | undefined = undefined;
let clientY: number | undefined = undefined;
if (args.length) {
const {left, top, width, height} = await this.getDimensions();
const relativeX = args[0] === 'center' ? width / 2 : args[0];
const relativeY = args[0] === 'center' ? height / 2 : args[1];

// Round the computed click position as decimal pixels are not
// supported by mouse events and could lead to unexpected results.
clientX = Math.round(left + relativeX);
clientY = Math.round(top + relativeY);
}

this._dispatchPointerEventIfSupported('pointerdown', clientX, clientY);
dispatchMouseEvent(this.element, 'mousedown', clientX, clientY);
Expand Down
9 changes: 8 additions & 1 deletion src/cdk/testing/tests/cross-environment.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,14 @@ export function crossEnvironmentSpecs(
it('should be able to click at a specific position within an element', async () => {
const clickTest = await harness.clickTest();
const clickTestResult = await harness.clickTestResult();
await clickTest.click(50, 50);
await clickTest.click(10, 10);
expect(await clickTestResult.text()).toBe('10-10');
});

it('should be able to click the center of an element', async () => {
const clickTest = await harness.clickTest();
const clickTestResult = await harness.clickTestResult();
await clickTest.click('center');
expect(await clickTestResult.text()).toBe('50-50');
});

Expand Down
13 changes: 11 additions & 2 deletions src/material-experimental/mdc-button/testing/button-harness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,18 @@ export class MatButtonHarness extends ComponentHarness {
(harness, text) => HarnessPredicate.stringMatches(harness.getText(), text));
}

/**
* Clicks the button at the given position relative to its top-left.
* @param relativeX The relative x position of the click.
* @param relativeY The relative y position of the click.
*/
click(relativeX: number, relativeY: number): Promise<void>;
/** Clicks the button at its center. */
click(location: 'center'): Promise<void>;
/** Clicks the button. */
async click(): Promise<void> {
return (await this.host()).click();
click(): Promise<void>;
async click(...args: [] | ['center'] | [number, number]): Promise<void> {
return (await this.host()).click(...(args as []));
}

/** Gets a boolean promise indicating if the button is disabled. */
Expand Down
2 changes: 1 addition & 1 deletion src/material-experimental/mdc-tabs/testing/tab-harness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export class MatTabHarness extends ContentContainerComponentHarness<string> {

/** Selects the given tab by clicking on the label. Tab cannot be selected if disabled. */
async select(): Promise<void> {
await (await this.host()).click();
await (await this.host()).click('center');
}

/** Gets the text content of the tab. */
Expand Down
13 changes: 11 additions & 2 deletions src/material/button/testing/button-harness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,18 @@ export class MatButtonHarness extends ComponentHarness {
(harness, text) => HarnessPredicate.stringMatches(harness.getText(), text));
}

/**
* Clicks the button at the given position relative to its top-left.
* @param relativeX The relative x position of the click.
* @param relativeY The relative y position of the click.
*/
click(relativeX: number, relativeY: number): Promise<void>;
/** Clicks the button at its center. */
click(location: 'center'): Promise<void>;
/** Clicks the button. */
async click(): Promise<void> {
return (await this.host()).click();
click(): Promise<void>;
async click(...args: [] | ['center'] | [number, number]): Promise<void> {
return (await this.host()).click(...(args as []));
}

/** Whether the button is disabled. */
Expand Down
1 change: 1 addition & 0 deletions tools/public_api_guard/cdk/testing.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ export interface TestElement {
blur(): Promise<void>;
clear(): Promise<void>;
click(): Promise<void>;
click(location: 'center'): Promise<void>;
click(relativeX: number, relativeY: number): Promise<void>;
focus(): Promise<void>;
getAttribute(name: string): Promise<string | null>;
Expand Down
2 changes: 1 addition & 1 deletion tools/public_api_guard/cdk/testing/protractor.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ export declare class ProtractorElement implements TestElement {
constructor(element: ElementFinder);
blur(): Promise<void>;
clear(): Promise<void>;
click(...args: number[]): Promise<void>;
click(...args: [] | ['center'] | [number, number]): Promise<void>;
focus(): Promise<void>;
getAttribute(name: string): Promise<string | null>;
getCssValue(property: string): Promise<string>;
Expand Down
2 changes: 1 addition & 1 deletion tools/public_api_guard/cdk/testing/testbed.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export declare class UnitTestElement implements TestElement {
constructor(element: Element, _stabilize: () => Promise<void>);
blur(): Promise<void>;
clear(): Promise<void>;
click(...args: number[]): Promise<void>;
click(...args: [] | ['center'] | [number, number]): Promise<void>;
focus(): Promise<void>;
getAttribute(name: string): Promise<string | null>;
getCssValue(property: string): Promise<string>;
Expand Down
2 changes: 2 additions & 0 deletions tools/public_api_guard/material/button/testing.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ export interface ButtonHarnessFilters extends BaseHarnessFilters {

export declare class MatButtonHarness extends ComponentHarness {
blur(): Promise<void>;
click(relativeX: number, relativeY: number): Promise<void>;
click(location: 'center'): Promise<void>;
click(): Promise<void>;
focus(): Promise<void>;
getText(): Promise<string>;
Expand Down