Skip to content

docs(cdk/testing): copy over doc comments from base class to subclasses #22437

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 2 commits into from
Apr 12, 2021
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
58 changes: 57 additions & 1 deletion src/cdk/testing/protractor/protractor-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,49 +69,89 @@ function toProtractorModifierKeys(modifiers: ModifierKeys): string[] {
return result;
}

/** A `TestElement` implementation for Protractor. */
/**
* A `TestElement` implementation for Protractor.
* @deprecated
* @breaking-change 13.0.0
*/
export class ProtractorElement implements TestElement {
constructor(readonly element: ElementFinder) {}

/** Blur the element. */
async blur(): Promise<void> {
return browser.executeScript('arguments[0].blur()', this.element);
}

/** Clear the element's input (for input and textarea elements only). */
async clear(): Promise<void> {
return this.element.clear();
}

/**
* 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(modifiers?: ModifierKeys): Promise<void>;
/** Click the element at the element's center. */
click(location: 'center', modifiers?: ModifierKeys): 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.
* @param relativeY Coordinate within the element, along the Y-axis at which to click.
* @param modifiers Modifier keys held while clicking
*/
click(relativeX: number, relativeY: number, modifiers?: ModifierKeys): Promise<void>;
async click(...args: [ModifierKeys?] | ['center', ModifierKeys?] |
[number, number, ModifierKeys?]): Promise<void> {
await this._dispatchClickEventSequence(args, Button.LEFT);
}

/**
* Right clicks on the element at the specified coordinates relative to the top-left of it.
* @param relativeX Coordinate within the element, along the X-axis at which to click.
* @param relativeY Coordinate within the element, along the Y-axis at which to click.
* @param modifiers Modifier keys held while clicking
*/
rightClick(relativeX: number, relativeY: number, modifiers?: ModifierKeys): Promise<void>;
async rightClick(...args: [ModifierKeys?] | ['center', ModifierKeys?] |
[number, number, ModifierKeys?]): Promise<void> {
await this._dispatchClickEventSequence(args, Button.RIGHT);
}

/** Focus the element. */
async focus(): Promise<void> {
return browser.executeScript('arguments[0].focus()', this.element);
}

/** Get the computed value of the given CSS property for the element. */
async getCssValue(property: string): Promise<string> {
return this.element.getCssValue(property);
}

/** Hovers the mouse over the element. */
async hover(): Promise<void> {
return browser.actions()
.mouseMove(await this.element.getWebElement())
.perform();
}

/** Moves the mouse away from the element. */
async mouseAway(): Promise<void> {
return browser.actions()
.mouseMove(await this.element.getWebElement(), {x: -1, y: -1})
.perform();
}

/**
* Sends the given string to the input as a series of key presses. Also fires input events
* and attempts to add the string to the Element's value.
*/
async sendKeys(...keys: (string | TestKey)[]): Promise<void>;
/**
* Sends the given string to the input as a series of key presses. Also fires input events
* and attempts to add the string to the Element's value.
*/
async sendKeys(modifiers: ModifierKeys, ...keys: (string | TestKey)[]): Promise<void>;
async sendKeys(...modifiersAndKeys: any[]): Promise<void> {
const first = modifiersAndKeys[0];
Expand All @@ -135,37 +175,47 @@ export class ProtractorElement implements TestElement {
return this.element.sendKeys(...keys);
}

/**
* Gets the text from the element.
* @param options Options that affect what text is included.
*/
async text(options?: TextOptions): Promise<string> {
if (options?.exclude) {
return browser.executeScript(_getTextWithExcludedElements, this.element, options.exclude);
}
return this.element.getText();
}

/** Gets the value for the given attribute from the element. */
async getAttribute(name: string): Promise<string|null> {
return browser.executeScript(
`return arguments[0].getAttribute(arguments[1])`, this.element, name);
}

/** Checks whether the element has the given class. */
async hasClass(name: string): Promise<boolean> {
const classes = (await this.getAttribute('class')) || '';
return new Set(classes.split(/\s+/).filter(c => c)).has(name);
}

/** Gets the dimensions of the element. */
async getDimensions(): Promise<ElementDimensions> {
const {width, height} = await this.element.getSize();
const {x: left, y: top} = await this.element.getLocation();
return {width, height, left, top};
}

/** Gets the value of a property of an element. */
async getProperty(name: string): Promise<any> {
return browser.executeScript(`return arguments[0][arguments[1]]`, this.element, name);
}

/** Sets the value of a property of an input. */
async setInputValue(value: string): Promise<void> {
return browser.executeScript(`arguments[0].value = arguments[1]`, this.element, value);
}

/** Selects the options at the specified indexes inside of a native `select` element. */
async selectOptions(...optionIndexes: number[]): Promise<void> {
const options = await this.element.all(by.css('option'));
const indexes = new Set(optionIndexes); // Convert to a set to remove duplicates.
Expand All @@ -187,17 +237,23 @@ export class ProtractorElement implements TestElement {
}
}

/** Checks whether this element matches the given selector. */
async matchesSelector(selector: string): Promise<boolean> {
return browser.executeScript(`
return (Element.prototype.matches ||
Element.prototype.msMatchesSelector).call(arguments[0], arguments[1])
`, this.element, selector);
}

/** Checks whether the element is focused. */
async isFocused(): Promise<boolean> {
return this.element.equals(browser.driver.switchTo().activeElement());
}

/**
* Dispatches an event with a particular name.
* @param name Name of the event to be dispatched.
*/
async dispatchEvent(name: string, data?: Record<string, EventData>): Promise<void> {
return browser.executeScript(_dispatchEvent, name, this.element, data);
}
Expand Down
24 changes: 22 additions & 2 deletions src/cdk/testing/protractor/protractor-harness-environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ import {HarnessEnvironment, HarnessLoader, TestElement} from '@angular/cdk/testi
import {by, element as protractorElement, ElementArrayFinder, ElementFinder} from 'protractor';
import {ProtractorElement} from './protractor-element';

/** Options to configure the environment. */
/**
* Options to configure the environment.
* @deprecated
* @breaking-change 13.0.0
*/
export interface ProtractorHarnessEnvironmentOptions {
/** The query function used to find DOM elements. */
queryFn: (selector: string, root: ElementFinder) => ElementArrayFinder;
Expand All @@ -21,7 +25,11 @@ const defaultEnvironmentOptions: ProtractorHarnessEnvironmentOptions = {
queryFn: (selector: string, root: ElementFinder) => root.all(by.css(selector))
};

/** A `HarnessEnvironment` implementation for Protractor. */
/**
* A `HarnessEnvironment` implementation for Protractor.
* @deprecated
* @breaking-change 13.0.0
*/
export class ProtractorHarnessEnvironment extends HarnessEnvironment<ElementFinder> {
/** The options for this environment. */
private _options: ProtractorHarnessEnvironmentOptions;
Expand All @@ -45,25 +53,37 @@ export class ProtractorHarnessEnvironment extends HarnessEnvironment<ElementFind
throw Error('This TestElement was not created by the ProtractorHarnessEnvironment');
}

/**
* Flushes change detection and async tasks captured in the Angular zone.
* In most cases it should not be necessary to call this manually. However, there may be some edge
* cases where it is needed to fully flush animation events.
*/
async forceStabilize(): Promise<void> {}

/** @docs-private */
async waitForTasksOutsideAngular(): Promise<void> {
// TODO: figure out how we can do this for the protractor environment.
// https://github.com/angular/components/issues/17412
}

/** Gets the root element for the document. */
protected getDocumentRoot(): ElementFinder {
return protractorElement(by.css('body'));
}

/** Creates a `TestElement` from a raw element. */
protected createTestElement(element: ElementFinder): TestElement {
return new ProtractorElement(element);
}

/** Creates a `HarnessLoader` rooted at the given raw element. */
protected createEnvironment(element: ElementFinder): HarnessEnvironment<ElementFinder> {
return new ProtractorHarnessEnvironment(element, this._options);
}

/**
* Gets a list of all elements matching the given selector under this environment's root element.
*/
protected async getAllRawElements(selector: string): Promise<ElementFinder[]> {
const elementArrayFinder = this._options.queryFn(selector, this.rawRootElement);
const length = await elementArrayFinder.count();
Expand Down
8 changes: 2 additions & 6 deletions src/cdk/testing/test-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,18 +145,14 @@ export interface TestElement {
/** Checks whether the element is focused. */
isFocused(): Promise<boolean>;

/**
* Sets the value of a property of an input.
*/
/** Sets the value of a property of an input. */
setInputValue(value: string): Promise<void>;

// Note that ideally here we'd be selecting options based on their value, rather than their
// index, but we're limited by `@angular/forms` which will modify the option value in some cases.
// Since the value will be truncated, we can't rely on it to do the lookup in the DOM. See:
// https://github.com/angular/angular/blob/master/packages/forms/src/directives/select_control_value_accessor.ts#L19
/**
* Selects the options at the specified indexes inside of a native `select` element.
*/
/** Selects the options at the specified indexes inside of a native `select` element. */
selectOptions(...optionIndexes: number[]): Promise<void>;

/**
Expand Down
15 changes: 15 additions & 0 deletions src/cdk/testing/testbed/testbed-harness-environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,11 @@ export class TestbedHarnessEnvironment extends HarnessEnvironment<Element> {
return environment.createComponentHarness(harnessType, fixture.nativeElement);
}

/**
* Flushes change detection and async tasks captured in the Angular zone.
* In most cases it should not be necessary to call this manually. However, there may be some edge
* cases where it is needed to fully flush animation events.
*/
async forceStabilize(): Promise<void> {
if (!disableAutoChangeDetection) {
if (this._destroyed) {
Expand All @@ -155,6 +160,10 @@ export class TestbedHarnessEnvironment extends HarnessEnvironment<Element> {
}
}

/**
* Waits for all scheduled or running async tasks to complete. This allows harness
* authors to wait for async tasks outside of the Angular zone.
*/
async waitForTasksOutsideAngular(): Promise<void> {
// If we run in the fake async zone, we run "flush" to run any scheduled tasks. This
// ensures that the harnesses behave inside of the FakeAsyncTestZone similar to the
Expand All @@ -173,18 +182,24 @@ export class TestbedHarnessEnvironment extends HarnessEnvironment<Element> {
await this._taskState.pipe(takeWhile(state => !state.stable)).toPromise();
}

/** Gets the root element for the document. */
protected getDocumentRoot(): Element {
return document.body;
}

/** Creates a `TestElement` from a raw element. */
protected createTestElement(element: Element): TestElement {
return new UnitTestElement(element, () => this.forceStabilize());
}

/** Creates a `HarnessLoader` rooted at the given raw element. */
protected createEnvironment(element: Element): HarnessEnvironment<Element> {
return new TestbedHarnessEnvironment(element, this._fixture, this._options);
}

/**
* Gets a list of all elements matching the given selector under this environment's root element.
*/
protected async getAllRawElements(selector: string): Promise<Element[]> {
await this.forceStabilize();
return Array.from(this._options.queryFn(selector, this.rawRootElement));
Expand Down
Loading