diff --git a/selenium-webdriver/index.d.ts b/selenium-webdriver/index.d.ts index 446286c8fe..92509a66ad 100644 --- a/selenium-webdriver/index.d.ts +++ b/selenium-webdriver/index.d.ts @@ -1295,28 +1295,36 @@ export namespace promise { } } -export namespace until { +/** + * Defines a condition for use with WebDriver's WebDriver#wait wait command. + */ +export class Condition { /** - * Defines a condition to + * @param {string} message A descriptive error message. Should complete the + * sentence 'Waiting [...]' + * @param {function(!WebDriver): OUT} fn The condition function to + * evaluate on each iteration of the wait loop. + * @constructor */ - class Condition { + constructor(message: string, fn: (webdriver: WebDriver) => any); + + /** @return {string} A description of this condition. */ + description(): string; + + /** @type {function(!WebDriver): OUT} */ + fn(webdriver: WebDriver): any; +} + +/** + * Defines a condition that will result in a {@link WebElement}. + * + * @extends {Condition)>} + */ +export class WebElementCondition extends Condition { } + +export namespace until { + /** - * @param {string} message A descriptive error message. Should complete the - * sentence 'Waiting [...]' - * @param {function(!WebDriver): OUT} fn The condition function to - * evaluate on each iteration of the wait loop. - * @constructor - */ - constructor(message: string, fn: (webdriver: WebDriver) => any); - - /** @return {string} A description of this condition. */ - description(): string; - - /** @type {function(!WebDriver): OUT} */ - fn(webdriver: WebDriver): any; - } - - /** * Creates a condition that will wait until the input driver is able to switch * to the designated frame. The target frame may be specified as * @@ -1350,64 +1358,64 @@ export namespace until { * Creates a condition that will wait for the given element to be disabled. * * @param {!WebElement} element The element to test. - * @return {!until.Condition.} The new condition. + * @return {!WebElementCondition} The new condition. * @see WebDriver#isEnabled */ - function elementIsDisabled(element: WebElement): Condition; + function elementIsDisabled(element: WebElement): WebElementCondition; /** * Creates a condition that will wait for the given element to be enabled. * * @param {!WebElement} element The element to test. - * @return {!until.Condition.} The new condition. + * @return {!WebElementCondition} The new condition. * @see WebDriver#isEnabled */ - function elementIsEnabled(element: WebElement): Condition; + function elementIsEnabled(element: WebElement): WebElementCondition; /** * Creates a condition that will wait for the given element to be deselected. * * @param {!WebElement} element The element to test. - * @return {!until.Condition.} The new condition. + * @return {!WebElementCondition} The new condition. * @see WebDriver#isSelected */ - function elementIsNotSelected(element: WebElement): Condition; + function elementIsNotSelected(element: WebElement): WebElementCondition; /** * Creates a condition that will wait for the given element to be in the DOM, * yet not visible to the user. * * @param {!WebElement} element The element to test. - * @return {!until.Condition.} The new condition. + * @return {!WebElementCondition} The new condition. * @see WebDriver#isDisplayed */ - function elementIsNotVisible(element: WebElement): Condition; + function elementIsNotVisible(element: WebElement): WebElementCondition; /** * Creates a condition that will wait for the given element to be selected. * @param {!WebElement} element The element to test. - * @return {!until.Condition.} The new condition. + * @return {!WebElementCondition} The new condition. * @see WebDriver#isSelected */ - function elementIsSelected(element: WebElement): Condition; + function elementIsSelected(element: WebElement): WebElementCondition; /** * Creates a condition that will wait for the given element to become visible. * * @param {!WebElement} element The element to test. - * @return {!until.Condition.} The new condition. + * @return {!WebElementCondition} The new condition. * @see WebDriver#isDisplayed */ - function elementIsVisible(element: WebElement): Condition; + function elementIsVisible(element: WebElement): WebElementCondition; /** * Creates a condition that will loop until an element is * {@link ./WebDriver#findElement found} with the given locator. * * @param {!(By|Function)} locator The locator to use. - * @return {!until.Condition.} The new condition. + * @return {!WebElementCondition} The new condition. */ - function elementLocated(locator: By | Function): Condition; + function elementLocated(locator: By | Function): WebElementCondition; /** * Creates a condition that will wait for the given element's @@ -1416,10 +1424,10 @@ export namespace until { * * @param {!WebElement} element The element to test. * @param {string} substr The substring to search for. - * @return {!until.Condition.} The new condition. + * @return {!WebElementCondition} The new condition. * @see WebDriver#getText */ - function elementTextContains(element: WebElement, substr: string): Condition; + function elementTextContains(element: WebElement, substr: string): WebElementCondition; /** * Creates a condition that will wait for the given element's @@ -1428,10 +1436,10 @@ export namespace until { * * @param {!WebElement} element The element to test. * @param {string} text The expected text. - * @return {!until.Condition.} The new condition. + * @return {!WebElementCondition} The new condition. * @see WebDriver#getText */ - function elementTextIs(element: WebElement, text: string): Condition; + function elementTextIs(element: WebElement, text: string): WebElementCondition; /** * Creates a condition that will wait for the given element's @@ -1440,10 +1448,10 @@ export namespace until { * * @param {!WebElement} element The element to test. * @param {!RegExp} regex The regular expression to test against. - * @return {!until.Condition} The new condition. + * @return {!WebElementCondition} The new condition. * @see WebDriver#getText */ - function elementTextMatches(element: WebElement, regex: RegExp): Condition; + function elementTextMatches(element: WebElement, regex: RegExp): WebElementCondition; /** * Creates a condition that will loop until at least one element is @@ -1451,7 +1459,7 @@ export namespace until { * * @param {!(Locator|By.Hash|Function)} locator The locator * to use. - * @return {!until.Condition.>} The new + * @return {!Condition.>} The new * condition. */ function elementsLocated(locator: By | Function): Condition; @@ -1462,7 +1470,7 @@ export namespace until { * has loaded. * * @param {!WebElement} element The element that should become stale. - * @return {!until.Condition} The new condition. + * @return {!Condition} The new condition. */ function stalenessOf(element: WebElement): Condition; @@ -1472,7 +1480,7 @@ export namespace until { * * @param {string} substr The substring that should be present in the page * title. - * @return {!until.Condition.} The new condition. + * @return {!Condition.} The new condition. */ function titleContains(substr: string): Condition; @@ -1481,7 +1489,7 @@ export namespace until { * given value. * * @param {string} title The expected page title. - * @return {!until.Condition} The new condition. + * @return {!Condition} The new condition. */ function titleIs(title: string): Condition; @@ -1490,9 +1498,37 @@ export namespace until { * given regular expression. * * @param {!RegExp} regex The regular expression to test against. - * @return {!until.Condition.} The new condition. + * @return {!Condition.} The new condition. */ function titleMatches(regex: RegExp): Condition; + + /** + * Creates a condition that will wait for the current page's url to contain + * the given substring. + * + * @param {string} substrUrl The substring that should be present in the current + * URL. + * @return {!Condition} The new condition. + */ + function urlContains(substrUrl: string): Condition; + + /** + * Creates a condition that will wait for the current page's url to match the + * given value. + * + * @param {string} url The expected page url. + * @return {!Condition} The new condition. + */ + function urlIs(url: string): Condition; + + /** + * Creates a condition that will wait for the current page's url to match the + * given regular expression. + * + * @param {!RegExp} regex The regular expression to test against. + * @return {!Condition} The new condition. + */ + function urlMatches(regex: RegExp): Condition; } interface ILocation { @@ -3835,10 +3871,10 @@ export class WebDriver { /** * Schedules a command to wait for a condition to hold. The condition may be - * specified by a {@link until.Condition}, as a custom function, or + * specified by a {@link Condition}, as a custom function, or * as a {@link promise.Promise}. * - * For a {@link until.Condition} or function, the wait will repeatedly + * For a {@link Condition} or function, the wait will repeatedly * evaluate the condition until it returns a truthy value. If any errors occur * while evaluating the condition, they will be allowed to propagate. In the * event a condition returns a {@link promise.Promise promise}, the @@ -3846,6 +3882,10 @@ export class WebDriver { * whether the condition has been satisified. Note the resolution time for * a promise is factored into whether a wait has timed out. * + * Note, if the provided condition is a {@link WebElementCondition}, then + * the wait will return a {@link WebElementPromise} that will resolve to the + * element that satisified the condition. + * * *Example:* waiting up to 10 seconds for an element to be present and visible * on the page. * @@ -3867,7 +3907,7 @@ export class WebDriver { * driver.get(getServerUrl()); * * @param {!(promise.Promise| - * until.Condition| + * Condition| * function(!WebDriver): T)} condition The condition to * wait on, defined as a promise, condition object, or a function to * evaluate as a condition. @@ -3879,7 +3919,57 @@ export class WebDriver { * rejected if the condition times out. * @template T */ - wait(condition: promise.Promise | until.Condition | ((driver: WebDriver) => T) | Function, timeout?: number, opt_message?: string): promise.Promise; + wait(condition: promise.Promise | Condition | ((driver: WebDriver) => T) | Function, opt_timeout?: number, opt_message?: string): promise.Promise; + + /** + * Schedules a command to wait for a condition to hold. The condition may be + * specified by a {@link webdriver.Condition}, as a custom function, or + * as a {@link webdriver.promise.Promise}. + * + * For a {@link webdriver.Condition} or function, the wait will repeatedly + * evaluate the condition until it returns a truthy value. If any errors occur + * while evaluating the condition, they will be allowed to propagate. In the + * event a condition returns a {@link webdriver.promise.Promise promise}, the + * polling loop will wait for it to be resolved and use the resolved value for + * whether the condition has been satisified. Note the resolution time for + * a promise is factored into whether a wait has timed out. + * + * Note, if the provided condition is a {@link WebElementCondition}, then + * the wait will return a {@link WebElementPromise} that will resolve to the + * element that satisified the condition. + * + * *Example:* waiting up to 10 seconds for an element to be present and visible + * on the page. + * + * var button = driver.wait(until.elementLocated(By.id('foo'), 10000); + * button.click(); + * + * This function may also be used to block the command flow on the resolution + * of a {@link webdriver.promise.Promise promise}. When given a promise, the + * command will simply wait for its resolution before completing. A timeout may + * be provided to fail the command if the promise does not resolve before the + * timeout expires. + * + * *Example:* Suppose you have a function, `startTestServer`, that returns a + * promise for when a server is ready for requests. You can block a `WebDriver` + * client on this promise with: + * + * var started = startTestServer(); + * driver.wait(started, 5 * 1000, 'Server should start within 5 seconds'); + * driver.get(getServerUrl()); + * + * @param {!WebElementCondition} condition The condition to + * wait on, defined as a promise, condition object, or a function to + * evaluate as a condition. + * @param {number=} opt_timeout How long to wait for the condition to be true. + * @param {string=} opt_message An optional message to use if the wait times + * out. + * @return {!WebElementPromise} A promise that will be fulfilled + * with the first truthy value returned by the condition function, or + * rejected if the condition times out. + * @template T + */ + wait(condition: WebElementCondition, opt_timeout?: number, opt_message?: string): WebElementPromise; /** * Schedules a command to make the driver sleep for the given amount of time. diff --git a/selenium-webdriver/test/index.ts b/selenium-webdriver/test/index.ts index 80f489d5ac..7081b692a4 100644 --- a/selenium-webdriver/test/index.ts +++ b/selenium-webdriver/test/index.ts @@ -640,7 +640,7 @@ function TestWebDriver() { voidPromise = driver.sleep(123); stringPromise = driver.takeScreenshot(); - var booleanCondition: webdriver.until.Condition; + var booleanCondition: webdriver.Condition; booleanPromise = driver.wait(booleanPromise); booleanPromise = driver.wait(booleanCondition); booleanPromise = driver.wait((driver: webdriver.WebDriver) => true); @@ -850,29 +850,32 @@ function TestUntilModule() { withCapabilities(webdriver.Capabilities.chrome()). build(); - var conditionB: webdriver.until.Condition = new webdriver.until.Condition('message', (driver: webdriver.WebDriver) => true); - var conditionBBase: webdriver.until.Condition = conditionB; - var conditionWebElement: webdriver.until.Condition; - var conditionWebElements: webdriver.until.Condition; + var conditionB: webdriver.Condition = new webdriver.Condition('message', function (driver: webdriver.WebDriver) { return true; }); + var conditionBBase: webdriver.Condition = conditionB; + var conditionWebElement: webdriver.WebElementCondition; + var conditionWebElements: webdriver.Condition; conditionB = webdriver.until.ableToSwitchToFrame(5); - var conditionAlert: webdriver.until.Condition = webdriver.until.alertIsPresent(); + var conditionAlert: webdriver.Condition = webdriver.until.alertIsPresent(); var el: webdriver.WebElement = driver.findElement(webdriver.By.id('id')); - conditionB = webdriver.until.elementIsDisabled(el); - conditionB = webdriver.until.elementIsEnabled(el); - conditionB = webdriver.until.elementIsNotSelected(el); - conditionB = webdriver.until.elementIsNotVisible(el); - conditionB = webdriver.until.elementIsSelected(el); - conditionB = webdriver.until.elementIsVisible(el); - conditionB = webdriver.until.elementTextContains(el, 'text'); - conditionB = webdriver.until.elementTextIs(el, 'text'); - conditionB = webdriver.until.elementTextMatches(el, /text/); conditionB = webdriver.until.stalenessOf(el); conditionB = webdriver.until.titleContains('text'); conditionB = webdriver.until.titleIs('text'); conditionB = webdriver.until.titleMatches(/text/); + conditionB = webdriver.until.urlContains('text'); + conditionB = webdriver.until.urlIs('text'); + conditionB = webdriver.until.urlMatches(/text/); + conditionWebElement = webdriver.until.elementIsDisabled(el); + conditionWebElement = webdriver.until.elementIsEnabled(el); + conditionWebElement = webdriver.until.elementIsNotSelected(el); + conditionWebElement = webdriver.until.elementIsNotVisible(el); + conditionWebElement = webdriver.until.elementIsSelected(el); + conditionWebElement = webdriver.until.elementIsVisible(el); conditionWebElement = webdriver.until.elementLocated(webdriver.By.id('id')); + conditionWebElement = webdriver.until.elementTextContains(el, 'text'); + conditionWebElement = webdriver.until.elementTextIs(el, 'text'); + conditionWebElement = webdriver.until.elementTextMatches(el, /text/); conditionWebElements = webdriver.until.elementsLocated(webdriver.By.className('class')); }