From ebd378705c13b35ecd0e7243f4c3da164b802c4b Mon Sep 17 00:00:00 2001 From: Miles Malerba Date: Thu, 8 Apr 2021 10:44:01 -0700 Subject: [PATCH 1/2] docs(cdk/testing): copy over doc comments from base class to subclasses On our docs site, the docs are not inherited from the base class. This PR also marks our ProtractorHarnessEnvironment as deprecated --- .../testing/protractor/protractor-element.ts | 58 ++++++++++++++++++- .../protractor-harness-environment.ts | 24 +++++++- src/cdk/testing/test-element.ts | 8 +-- .../testbed/testbed-harness-environment.ts | 15 +++++ src/cdk/testing/testbed/unit-test-element.ts | 52 +++++++++++++++++ .../testing/webdriver/webdriver-element.ts | 52 +++++++++++++++++ .../webdriver-harness-environment.ts | 12 ++++ 7 files changed, 212 insertions(+), 9 deletions(-) diff --git a/src/cdk/testing/protractor/protractor-element.ts b/src/cdk/testing/protractor/protractor-element.ts index a6ccd20e7476..eba83f392098 100644 --- a/src/cdk/testing/protractor/protractor-element.ts +++ b/src/cdk/testing/protractor/protractor-element.ts @@ -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 { return browser.executeScript('arguments[0].blur()', this.element); } + /** Clear the element's input (for input and textarea elements only). */ async clear(): Promise { 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; + /** Click the element at the element's center. */ + click(location: 'center', modifiers?: ModifierKeys): Promise; + /** + * 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; async click(...args: [ModifierKeys?] | ['center', ModifierKeys?] | [number, number, ModifierKeys?]): Promise { 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; async rightClick(...args: [ModifierKeys?] | ['center', ModifierKeys?] | [number, number, ModifierKeys?]): Promise { await this._dispatchClickEventSequence(args, Button.RIGHT); } + /** Focus the element. */ async focus(): Promise { 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 { return this.element.getCssValue(property); } + /** Hovers the mouse over the element. */ async hover(): Promise { return browser.actions() .mouseMove(await this.element.getWebElement()) .perform(); } + /** Moves the mouse away from the element. */ async mouseAway(): Promise { 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; + /** + * 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; async sendKeys(...modifiersAndKeys: any[]): Promise { const first = modifiersAndKeys[0]; @@ -135,6 +175,10 @@ 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 { if (options?.exclude) { return browser.executeScript(_getTextWithExcludedElements, this.element, options.exclude); @@ -142,30 +186,36 @@ export class ProtractorElement implements TestElement { return this.element.getText(); } + /** Gets the value for the given attribute from the element. */ async getAttribute(name: string): Promise { 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 { 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 { 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 { 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 { 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 { const options = await this.element.all(by.css('option')); const indexes = new Set(optionIndexes); // Convert to a set to remove duplicates. @@ -187,6 +237,7 @@ export class ProtractorElement implements TestElement { } } + /** Checks whether this element matches the given selector. */ async matchesSelector(selector: string): Promise { return browser.executeScript(` return (Element.prototype.matches || @@ -194,10 +245,15 @@ export class ProtractorElement implements TestElement { `, this.element, selector); } + /** Checks whether the element is focused. */ async isFocused(): Promise { 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): Promise { return browser.executeScript(_dispatchEvent, name, this.element, data); } diff --git a/src/cdk/testing/protractor/protractor-harness-environment.ts b/src/cdk/testing/protractor/protractor-harness-environment.ts index 5f6ea8cd8adb..debe54dee2e0 100644 --- a/src/cdk/testing/protractor/protractor-harness-environment.ts +++ b/src/cdk/testing/protractor/protractor-harness-environment.ts @@ -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; @@ -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 { /** The options for this environment. */ private _options: ProtractorHarnessEnvironmentOptions; @@ -45,25 +53,37 @@ export class ProtractorHarnessEnvironment extends HarnessEnvironment {} + /** @docs-private */ async waitForTasksOutsideAngular(): Promise { // 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 { 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 { const elementArrayFinder = this._options.queryFn(selector, this.rawRootElement); const length = await elementArrayFinder.count(); diff --git a/src/cdk/testing/test-element.ts b/src/cdk/testing/test-element.ts index b2a3ef1ea623..031ff4f3d513 100644 --- a/src/cdk/testing/test-element.ts +++ b/src/cdk/testing/test-element.ts @@ -145,18 +145,14 @@ export interface TestElement { /** Checks whether the element is focused. */ isFocused(): Promise; - /** - * Sets the value of a property of an input. - */ + /** Sets the value of a property of an input. */ setInputValue(value: string): Promise; // 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; /** diff --git a/src/cdk/testing/testbed/testbed-harness-environment.ts b/src/cdk/testing/testbed/testbed-harness-environment.ts index 460971077d04..4991a665f7f9 100644 --- a/src/cdk/testing/testbed/testbed-harness-environment.ts +++ b/src/cdk/testing/testbed/testbed-harness-environment.ts @@ -145,6 +145,11 @@ export class TestbedHarnessEnvironment extends HarnessEnvironment { 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 { if (!disableAutoChangeDetection) { if (this._destroyed) { @@ -155,6 +160,10 @@ export class TestbedHarnessEnvironment extends HarnessEnvironment { } } + /** + * 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 { // 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 @@ -173,18 +182,24 @@ export class TestbedHarnessEnvironment extends HarnessEnvironment { 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 { 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 { await this.forceStabilize(); return Array.from(this._options.queryFn(selector, this.rawRootElement)); diff --git a/src/cdk/testing/testbed/unit-test-element.ts b/src/cdk/testing/testbed/unit-test-element.ts index 253cbb2a887a..22a393227de5 100644 --- a/src/cdk/testing/testbed/unit-test-element.ts +++ b/src/cdk/testing/testbed/unit-test-element.ts @@ -67,11 +67,13 @@ const keyMap = { export class UnitTestElement implements TestElement { constructor(readonly element: Element, private _stabilize: () => Promise) {} + /** Blur the element. */ async blur(): Promise { triggerBlur(this.element as HTMLElement); await this._stabilize(); } + /** Clear the element's input (for input and textarea elements only). */ async clear(): Promise { if (!isTextInput(this.element)) { throw Error('Attempting to clear an invalid element'); @@ -80,23 +82,47 @@ export class UnitTestElement implements TestElement { await this._stabilize(); } + /** + * 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; + /** Click the element at the element's center. */ + click(location: 'center', modifiers?: ModifierKeys): Promise; + /** + * 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; async click(...args: [ModifierKeys?] | ['center', ModifierKeys?] | [number, number, ModifierKeys?]): Promise { await this._dispatchMouseEventSequence('click', args, 0); await this._stabilize(); } + /** + * 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; async rightClick(...args: [ModifierKeys?] | ['center', ModifierKeys?] | [number, number, ModifierKeys?]): Promise { await this._dispatchMouseEventSequence('contextmenu', args, 2); await this._stabilize(); } + /** Focus the element. */ async focus(): Promise { triggerFocus(this.element as HTMLElement); await this._stabilize(); } + /** Get the computed value of the given CSS property for the element. */ async getCssValue(property: string): Promise { await this._stabilize(); // TODO(mmalerba): Consider adding value normalization if we run into common cases where its @@ -104,19 +130,29 @@ export class UnitTestElement implements TestElement { return getComputedStyle(this.element).getPropertyValue(property); } + /** Hovers the mouse over the element. */ async hover(): Promise { this._dispatchPointerEventIfSupported('pointerenter'); dispatchMouseEvent(this.element, 'mouseenter'); await this._stabilize(); } + /** Moves the mouse away from the element. */ async mouseAway(): Promise { this._dispatchPointerEventIfSupported('pointerleave'); dispatchMouseEvent(this.element, 'mouseleave'); await this._stabilize(); } + /** + * 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; + /** + * 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; async sendKeys(...modifiersAndKeys: any[]): Promise { const args = modifiersAndKeys.map(k => typeof k === 'number' ? keyMap[k as TestKey] : k); @@ -124,6 +160,10 @@ export class UnitTestElement implements TestElement { await this._stabilize(); } + /** + * Gets the text from the element. + * @param options Options that affect what text is included. + */ async text(options?: TextOptions): Promise { await this._stabilize(); if (options?.exclude) { @@ -132,31 +172,37 @@ export class UnitTestElement implements TestElement { return (this.element.textContent || '').trim(); } + /** Gets the value for the given attribute from the element. */ async getAttribute(name: string): Promise { await this._stabilize(); return this.element.getAttribute(name); } + /** Checks whether the element has the given class. */ async hasClass(name: string): Promise { await this._stabilize(); return this.element.classList.contains(name); } + /** Gets the dimensions of the element. */ async getDimensions(): Promise { await this._stabilize(); return this.element.getBoundingClientRect(); } + /** Gets the value of a property of an element. */ async getProperty(name: string): Promise { await this._stabilize(); return (this.element as any)[name]; } + /** Sets the value of a property of an input. */ async setInputValue(value: string): Promise { (this.element as any).value = value; await this._stabilize(); } + /** Selects the options at the specified indexes inside of a native `select` element. */ async selectOptions(...optionIndexes: number[]): Promise { let hasChanged = false; const options = this.element.querySelectorAll('option'); @@ -181,6 +227,7 @@ export class UnitTestElement implements TestElement { } } + /** Checks whether this element matches the given selector. */ async matchesSelector(selector: string): Promise { await this._stabilize(); const elementPrototype = Element.prototype as any; @@ -188,11 +235,16 @@ export class UnitTestElement implements TestElement { .call(this.element, selector); } + /** Checks whether the element is focused. */ async isFocused(): Promise { await this._stabilize(); return document.activeElement === this.element; } + /** + * Dispatches an event with a particular name. + * @param name Name of the event to be dispatched. + */ async dispatchEvent(name: string, data?: Record): Promise { const event = createFakeEvent(name); diff --git a/src/cdk/testing/webdriver/webdriver-element.ts b/src/cdk/testing/webdriver/webdriver-element.ts index 4379921ffaed..7ac91012ece1 100644 --- a/src/cdk/testing/webdriver/webdriver-element.ts +++ b/src/cdk/testing/webdriver/webdriver-element.ts @@ -24,49 +24,85 @@ export class WebDriverElement implements TestElement { readonly element: () => webdriver.WebElement, private _stabilize: () => Promise) {} + /** Blur the element. */ async blur(): Promise { await this._executeScript(((element: HTMLElement) => element.blur()), this.element()); await this._stabilize(); } + /** Clear the element's input (for input and textarea elements only). */ async clear(): Promise { await this.element().clear(); await this._stabilize(); } + /** + * 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; + /** Click the element at the element's center. */ + click(location: 'center', modifiers?: ModifierKeys): Promise; + /** + * 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; async click(...args: [ModifierKeys?] | ['center', ModifierKeys?] | [number, number, ModifierKeys?]): Promise { await this._dispatchClickEventSequence(args, webdriver.Button.LEFT); await this._stabilize(); } + /** + * 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; async rightClick(...args: [ModifierKeys?] | ['center', ModifierKeys?] | [number, number, ModifierKeys?]): Promise { await this._dispatchClickEventSequence(args, webdriver.Button.RIGHT); await this._stabilize(); } + /** Focus the element. */ async focus(): Promise { await this._executeScript((element: HTMLElement) => element.focus(), this.element()); await this._stabilize(); } + /** Get the computed value of the given CSS property for the element. */ async getCssValue(property: string): Promise { await this._stabilize(); return this.element().getCssValue(property); } + /** Hovers the mouse over the element. */ async hover(): Promise { await this._actions().mouseMove(this.element()).perform(); await this._stabilize(); } + /** Moves the mouse away from the element. */ async mouseAway(): Promise { await this._actions().mouseMove(this.element(), {x: -1, y: -1}).perform(); await this._stabilize(); } + /** + * 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; + /** + * 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; async sendKeys(...modifiersAndKeys: any[]): Promise { const first = modifiersAndKeys[0]; @@ -91,6 +127,10 @@ export class WebDriverElement implements TestElement { await this._stabilize(); } + /** + * Gets the text from the element. + * @param options Options that affect what text is included. + */ async text(options?: TextOptions): Promise { await this._stabilize(); if (options?.exclude) { @@ -99,6 +139,7 @@ export class WebDriverElement implements TestElement { return this.element().getText(); } + /** Gets the value for the given attribute from the element. */ async getAttribute(name: string): Promise { await this._stabilize(); return this._executeScript( @@ -106,12 +147,14 @@ export class WebDriverElement implements TestElement { this.element(), name); } + /** Checks whether the element has the given class. */ async hasClass(name: string): Promise { await this._stabilize(); 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 { await this._stabilize(); const {width, height} = await this.element().getSize(); @@ -119,6 +162,7 @@ export class WebDriverElement implements TestElement { return {width, height, left, top}; } + /** Gets the value of a property of an element. */ async getProperty(name: string): Promise { await this._stabilize(); return this._executeScript( @@ -126,6 +170,7 @@ export class WebDriverElement implements TestElement { this.element(), name); } + /** Sets the value of a property of an input. */ async setInputValue(newValue: string): Promise { await this._executeScript( (element: HTMLInputElement, value: string) => element.value = value, @@ -133,6 +178,7 @@ export class WebDriverElement implements TestElement { await this._stabilize(); } + /** Selects the options at the specified indexes inside of a native `select` element. */ async selectOptions(...optionIndexes: number[]): Promise { await this._stabilize(); const options = await this.element().findElements(webdriver.By.css('option')); @@ -157,6 +203,7 @@ export class WebDriverElement implements TestElement { } } + /** Checks whether this element matches the given selector. */ async matchesSelector(selector: string): Promise { await this._stabilize(); return this._executeScript((element: Element, s: string) => @@ -165,12 +212,17 @@ export class WebDriverElement implements TestElement { this.element(), selector); } + /** Checks whether the element is focused. */ async isFocused(): Promise { await this._stabilize(); return webdriver.WebElement.equals( this.element(), this.element().getDriver().switchTo().activeElement()); } + /** + * Dispatches an event with a particular name. + * @param name Name of the event to be dispatched. + */ async dispatchEvent(name: string, data?: Record): Promise { await this._executeScript(dispatchEvent, name, this.element(), data); await this._stabilize(); diff --git a/src/cdk/testing/webdriver/webdriver-harness-environment.ts b/src/cdk/testing/webdriver/webdriver-harness-environment.ts index b250107fa597..f51d0d6bb736 100644 --- a/src/cdk/testing/webdriver/webdriver-harness-environment.ts +++ b/src/cdk/testing/webdriver/webdriver-harness-environment.ts @@ -92,23 +92,32 @@ export class WebDriverHarnessEnvironment extends HarnessEnvironment<() => webdri () => driver.findElement(webdriver.By.css('body')), options); } + /** + * 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 { await this.rawRootElement().getDriver().executeAsyncScript(whenStable); } + /** @docs-private */ async waitForTasksOutsideAngular(): Promise { // TODO: figure out how we can do this for the webdriver environment. // https://github.com/angular/components/issues/17412 } + /** Gets the root element for the document. */ protected getDocumentRoot(): () => webdriver.WebElement { return () => this.rawRootElement().getDriver().findElement(webdriver.By.css('body')); } + /** Creates a `TestElement` from a raw element. */ protected createTestElement(element: () => webdriver.WebElement): TestElement { return new WebDriverElement(element, () => this.forceStabilize()); } + /** Creates a `HarnessLoader` rooted at the given raw element. */ protected createEnvironment(element: () => webdriver.WebElement): HarnessEnvironment<() => webdriver.WebElement> { return new WebDriverHarnessEnvironment(element, this._options); @@ -117,6 +126,9 @@ export class WebDriverHarnessEnvironment extends HarnessEnvironment<() => webdri // Note: This seems to be working, though we may need to re-evaluate if we encounter issues with // stale element references. `() => Promise` seems like a more correct // return type, though supporting it would require changes to the public harness API. + /** + * Gets a list of all elements matching the given selector under this environment's root element. + */ protected async getAllRawElements(selector: string): Promise<(() => webdriver.WebElement)[]> { const els = await this._options.queryFn(selector, this.rawRootElement); return els.map((x: webdriver.WebElement) => () => x); From 5bcbeb902b5fbd616bd97f66ae86b5a3b0b678d2 Mon Sep 17 00:00:00 2001 From: Miles Malerba Date: Thu, 8 Apr 2021 13:43:31 -0700 Subject: [PATCH 2/2] fixup! docs(cdk/testing): copy over doc comments from base class to subclasses --- tools/public_api_guard/cdk/testing/protractor.d.ts | 14 ++++---------- tools/public_api_guard/cdk/testing/testbed.d.ts | 14 ++++---------- tools/public_api_guard/cdk/testing/webdriver.d.ts | 14 ++++---------- 3 files changed, 12 insertions(+), 30 deletions(-) diff --git a/tools/public_api_guard/cdk/testing/protractor.d.ts b/tools/public_api_guard/cdk/testing/protractor.d.ts index 9706421b9181..cbe7dff0ef4c 100644 --- a/tools/public_api_guard/cdk/testing/protractor.d.ts +++ b/tools/public_api_guard/cdk/testing/protractor.d.ts @@ -3,11 +3,9 @@ export declare class ProtractorElement implements TestElement { constructor(element: ElementFinder); blur(): Promise; clear(): Promise; - click(...args: [ModifierKeys?] | ['center', ModifierKeys?] | [ - number, - number, - ModifierKeys? - ]): Promise; + click(modifiers?: ModifierKeys): Promise; + click(location: 'center', modifiers?: ModifierKeys): Promise; + click(relativeX: number, relativeY: number, modifiers?: ModifierKeys): Promise; dispatchEvent(name: string, data?: Record): Promise; focus(): Promise; getAttribute(name: string): Promise; @@ -19,11 +17,7 @@ export declare class ProtractorElement implements TestElement { isFocused(): Promise; matchesSelector(selector: string): Promise; mouseAway(): Promise; - rightClick(...args: [ModifierKeys?] | ['center', ModifierKeys?] | [ - number, - number, - ModifierKeys? - ]): Promise; + rightClick(relativeX: number, relativeY: number, modifiers?: ModifierKeys): Promise; selectOptions(...optionIndexes: number[]): Promise; sendKeys(...keys: (string | TestKey)[]): Promise; sendKeys(modifiers: ModifierKeys, ...keys: (string | TestKey)[]): Promise; diff --git a/tools/public_api_guard/cdk/testing/testbed.d.ts b/tools/public_api_guard/cdk/testing/testbed.d.ts index 93a0430e9a0b..389ac3ec74b4 100644 --- a/tools/public_api_guard/cdk/testing/testbed.d.ts +++ b/tools/public_api_guard/cdk/testing/testbed.d.ts @@ -21,11 +21,9 @@ export declare class UnitTestElement implements TestElement { constructor(element: Element, _stabilize: () => Promise); blur(): Promise; clear(): Promise; - click(...args: [ModifierKeys?] | ['center', ModifierKeys?] | [ - number, - number, - ModifierKeys? - ]): Promise; + click(modifiers?: ModifierKeys): Promise; + click(location: 'center', modifiers?: ModifierKeys): Promise; + click(relativeX: number, relativeY: number, modifiers?: ModifierKeys): Promise; dispatchEvent(name: string, data?: Record): Promise; focus(): Promise; getAttribute(name: string): Promise; @@ -37,11 +35,7 @@ export declare class UnitTestElement implements TestElement { isFocused(): Promise; matchesSelector(selector: string): Promise; mouseAway(): Promise; - rightClick(...args: [ModifierKeys?] | ['center', ModifierKeys?] | [ - number, - number, - ModifierKeys? - ]): Promise; + rightClick(relativeX: number, relativeY: number, modifiers?: ModifierKeys): Promise; selectOptions(...optionIndexes: number[]): Promise; sendKeys(...keys: (string | TestKey)[]): Promise; sendKeys(modifiers: ModifierKeys, ...keys: (string | TestKey)[]): Promise; diff --git a/tools/public_api_guard/cdk/testing/webdriver.d.ts b/tools/public_api_guard/cdk/testing/webdriver.d.ts index d5ad9e883c57..7cfc61333b06 100644 --- a/tools/public_api_guard/cdk/testing/webdriver.d.ts +++ b/tools/public_api_guard/cdk/testing/webdriver.d.ts @@ -5,11 +5,9 @@ export declare class WebDriverElement implements TestElement { constructor(element: () => webdriver.WebElement, _stabilize: () => Promise); blur(): Promise; clear(): Promise; - click(...args: [ModifierKeys?] | ['center', ModifierKeys?] | [ - number, - number, - ModifierKeys? - ]): Promise; + click(modifiers?: ModifierKeys): Promise; + click(location: 'center', modifiers?: ModifierKeys): Promise; + click(relativeX: number, relativeY: number, modifiers?: ModifierKeys): Promise; dispatchEvent(name: string, data?: Record): Promise; focus(): Promise; getAttribute(name: string): Promise; @@ -21,11 +19,7 @@ export declare class WebDriverElement implements TestElement { isFocused(): Promise; matchesSelector(selector: string): Promise; mouseAway(): Promise; - rightClick(...args: [ModifierKeys?] | ['center', ModifierKeys?] | [ - number, - number, - ModifierKeys? - ]): Promise; + rightClick(relativeX: number, relativeY: number, modifiers?: ModifierKeys): Promise; selectOptions(...optionIndexes: number[]): Promise; sendKeys(...keys: (string | TestKey)[]): Promise; sendKeys(modifiers: ModifierKeys, ...keys: (string | TestKey)[]): Promise;