From 8d639ae50e123296fb7ec737d5e1104a5ffb9ec1 Mon Sep 17 00:00:00 2001 From: Ross Wollman Date: Fri, 16 Sep 2022 14:17:35 -0400 Subject: [PATCH] chore: revert toHaveAttribute type sig and overloads (#17406) Relates #16517. Revert "docs(python): add missing NotToHaveAttribute overloads (#17371)" This reverts commit 2e1ea296144c1d38f90815c02167a2e51f3b2b40. Revert "docs(release-notes): add 1.26 release notes for language ports (#17345)" This reverts commit 4b8a85e69d2ded2089595ff24616eb381f59cff1. Revert "test: unflake "should support boolean attribute with options" (#17024)" This reverts commit 1dc05bd4c60209542d35624d5f39b7a2a44cce3e. Revert "fix: support toHaveAttribute(name, options) (#16941)" This reverts commit f30ac1d67827fbcf3f8be7a851ef81b761842c52. Revert "feat: expect(locator).toHaveAttribute to assert attribute presence (#16767)" This reverts commit 622c73cc1e677834ebdc27e95c89ff101bdccf54. --- docs/src/api/class-locatorassertions.md | 99 +++---------------- docs/src/release-notes-csharp.md | 32 ------ docs/src/release-notes-java.md | 30 ------ docs/src/release-notes-js.md | 1 - docs/src/release-notes-python.md | 30 ------ .../src/server/injected/injectedScript.ts | 6 +- .../playwright-test/src/matchers/matchers.ts | 22 +---- packages/playwright-test/types/test.d.ts | 23 +---- tests/page/expect-misc.spec.ts | 14 +-- tests/playwright-test/expect.spec.ts | 20 ---- 10 files changed, 23 insertions(+), 254 deletions(-) diff --git a/docs/src/api/class-locatorassertions.md b/docs/src/api/class-locatorassertions.md index 467eca3fd0..04ce5ad9fb 100644 --- a/docs/src/api/class-locatorassertions.md +++ b/docs/src/api/class-locatorassertions.md @@ -213,46 +213,29 @@ Whether to use `element.innerText` instead of `element.textContent` when retriev ### option: LocatorAssertions.NotToContainText.timeout = %%-csharp-java-python-assertions-timeout-%% * since: v1.18 -## async method: LocatorAssertions.NotToHaveAttribute#1 -* since: v1.18 +## async method: LocatorAssertions.NotToHaveAttribute +* since: v1.20 * langs: python -The opposite of [`method: LocatorAssertions.toHaveAttribute#1`]. +The opposite of [`method: LocatorAssertions.toHaveAttribute`]. -### param: LocatorAssertions.NotToHaveAttribute#1.name +### param: LocatorAssertions.NotToHaveAttribute.name * since: v1.18 - `name` <[string]> Attribute name. -### param: LocatorAssertions.NotToHaveAttribute#1.value +### param: LocatorAssertions.NotToHaveAttribute.value * since: v1.18 - `value` <[string]|[RegExp]> Expected attribute value. -### option: LocatorAssertions.NotToHaveAttribute#1.timeout = %%-js-assertions-timeout-%% +### option: LocatorAssertions.NotToHaveAttribute.timeout = %%-js-assertions-timeout-%% * since: v1.18 -### option: LocatorAssertions.NotToHaveAttribute#1.timeout = %%-csharp-java-python-assertions-timeout-%% +### option: LocatorAssertions.NotToHaveAttribute.timeout = %%-csharp-java-python-assertions-timeout-%% * since: v1.18 -## async method: LocatorAssertions.NotToHaveAttribute#2 -* since: v1.26 -* langs: python - -The opposite of [`method: LocatorAssertions.toHaveAttribute#2`]. - -### param: LocatorAssertions.NotToHaveAttribute#2.name -* since: v1.26 -- `name` <[string]> - -Attribute name. - -### option: LocatorAssertions.NotToHaveAttribute#2.timeout = %%-js-assertions-timeout-%% -* since: v1.26 -### option: LocatorAssertions.NotToHaveAttribute#2.timeout = %%-csharp-java-python-assertions-timeout-%% -* since: v1.26 - ## async method: LocatorAssertions.NotToHaveClass * since: v1.20 * langs: python @@ -921,16 +904,15 @@ Whether to use `element.innerText` instead of `element.textContent` when retriev * since: v1.18 -## async method: LocatorAssertions.toHaveAttribute#1 -* since: v1.18 +## async method: LocatorAssertions.toHaveAttribute +* since: v1.20 * langs: - alias-java: hasAttribute -Ensures the [Locator] points to an element with given attribute value. +Ensures the [Locator] points to an element with given attribute. ```js const locator = page.locator('input'); -// Assert attribute with given value. await expect(locator).toHaveAttribute('type', 'text'); ``` @@ -957,76 +939,23 @@ var locator = Page.Locator("input"); await Expect(locator).ToHaveAttributeAsync("type", "text"); ``` -### param: LocatorAssertions.toHaveAttribute#1.name +### param: LocatorAssertions.toHaveAttribute.name * since: v1.18 - `name` <[string]> Attribute name. -### param: LocatorAssertions.toHaveAttribute#1.value +### param: LocatorAssertions.toHaveAttribute.value * since: v1.18 - `value` <[string]|[RegExp]> Expected attribute value. -### option: LocatorAssertions.toHaveAttribute#1.timeout = %%-js-assertions-timeout-%% +### option: LocatorAssertions.toHaveAttribute.timeout = %%-js-assertions-timeout-%% * since: v1.18 -### option: LocatorAssertions.toHaveAttribute#1.timeout = %%-csharp-java-python-assertions-timeout-%% +### option: LocatorAssertions.toHaveAttribute.timeout = %%-csharp-java-python-assertions-timeout-%% * since: v1.18 -## async method: LocatorAssertions.toHaveAttribute#2 -* since: v1.26 -* langs: - - alias-java: hasAttribute - -Ensures the [Locator] points to an element with given attribute. The method will assert attribute -presence. - -```js -const locator = page.locator('input'); -// Assert attribute existence. -await expect(locator).toHaveAttribute('disabled'); -await expect(locator).not.toHaveAttribute('open'); -``` - -```java -assertThat(page.locator("input")).hasAttribute("disabled"); -assertThat(page.locator("input")).not().hasAttribute("open"); -``` - -```python async -from playwright.async_api import expect - -locator = page.locator("input") -await expect(locator).to_have_attribute("disabled") -await expect(locator).not_to_have_attribute("open") -``` - -```python sync -from playwright.sync_api import expect - -locator = page.locator("input") -expect(locator).to_have_attribute("disabled") -expect(locator).not_to_have_attribute("open") -``` - -```csharp -var locator = Page.Locator("input"); -await Expect(locator).ToHaveAttributeAsync("disabled"); -await Expect(locator).Not.ToHaveAttributeAsync("open"); -``` - -### param: LocatorAssertions.toHaveAttribute#2.name -* since: v1.26 -- `name` <[string]> - -Attribute name. - -### option: LocatorAssertions.toHaveAttribute#2.timeout = %%-js-assertions-timeout-%% -* since: v1.26 -### option: LocatorAssertions.toHaveAttribute#2.timeout = %%-csharp-java-python-assertions-timeout-%% -* since: v1.26 - ## async method: LocatorAssertions.toHaveClass * since: v1.20 * langs: diff --git a/docs/src/release-notes-csharp.md b/docs/src/release-notes-csharp.md index 51d1549bf1..671e25b2c7 100644 --- a/docs/src/release-notes-csharp.md +++ b/docs/src/release-notes-csharp.md @@ -4,38 +4,6 @@ title: "Release notes" toc_max_heading_level: 2 --- -## Version 1.26 - -### Assertions - -- [`method: LocatorAssertions.toHaveAttribute#2`] can now be used for asserting attribute existence. -- New option `Enabled` for [`method: LocatorAssertions.toBeEnabled`]. -- [`method: LocatorAssertions.toHaveText`] now pierces open shadow roots. -- New option `Editable` for [`method: LocatorAssertions.toBeEditable`]. -- New option `Visible` for [`method: LocatorAssertions.toBeVisible`]. -- [`method: APIResponseAssertions.toBeOK`] is now available. - -### Other highlights - -- New option `MaxRedirects` for [`method: APIRequestContext.get`] and others to limit redirect count. -- Codegen now supports NUnit and MSTest frameworks. -- ASP .NET is now supported. - -### Behavior Change - -A bunch of Playwright APIs already support the `WaitUntil: WaitUntilState.DOMContentLoaded` option. -For example: - -```csharp -await Page.GotoAsync("https://playwright.dev", new() { WaitUntil = WaitUntilState.DOMContentLoaded }); -``` - -Prior to 1.26, this would wait for all iframes to fire the `DOMContentLoaded` -event. - -To align with web specification, the `WaitUntilState.DOMContentLoaded` value only waits for -the target frame to fire the `'DOMContentLoaded'` event. Use `WaitUntil: WaitUntilState.Load` to wait for all iframes. - ## Version 1.25 ### New .runsettings file support diff --git a/docs/src/release-notes-java.md b/docs/src/release-notes-java.md index 16b4240dba..1e57cb3fda 100644 --- a/docs/src/release-notes-java.md +++ b/docs/src/release-notes-java.md @@ -4,36 +4,6 @@ title: "Release notes" toc_max_heading_level: 2 --- -## Version 1.26 - -### Assertions - -- [`method: LocatorAssertions.toHaveAttribute#2`] can now be used for asserting attribute existence. -- New option `enabled` for [`method: LocatorAssertions.toBeEnabled`]. -- [`method: LocatorAssertions.toHaveText`] now pierces open shadow roots. -- New option `editable` for [`method: LocatorAssertions.toBeEditable`]. -- New option `visible` for [`method: LocatorAssertions.toBeVisible`]. - -### Other highlights - -- New option `setMaxRedirects` for [`method: APIRequestContext.get`] and others to limit redirect count. -- Docker images are now using OpenJDK 17. - -### Behavior Change - -A bunch of Playwright APIs already support the `setWaitUntil(WaitUntilState.DOMCONTENTLOADED)` option. -For example: - -```js -page.navigate("https://playwright.dev", new Page.NavigateOptions().setWaitUntil(WaitUntilState.DOMCONTENTLOADED)); -``` - -Prior to 1.26, this would wait for all iframes to fire the `DOMContentLoaded` -event. - -To align with web specification, the `WaitUntilState.DOMCONTENTLOADED` value only waits for -the target frame to fire the `'DOMContentLoaded'` event. Use `setWaitUntil(WaitUntilState.LOAD)` to wait for all iframes. - ## Version 1.25 ### New APIs & changes diff --git a/docs/src/release-notes-js.md b/docs/src/release-notes-js.md index d744c0c401..fab7e1f28e 100644 --- a/docs/src/release-notes-js.md +++ b/docs/src/release-notes-js.md @@ -18,7 +18,6 @@ Read more in [our documentation](./docker#experimental-playwright-test-docker-in ### Assertions -- [`method: LocatorAssertions.toHaveAttribute#2`] can now be used for asserting attribute existence. - New option `enabled` for [`method: LocatorAssertions.toBeEnabled`]. - [`method: LocatorAssertions.toHaveText`] now pierces open shadow roots. - New option `editable` for [`method: LocatorAssertions.toBeEditable`]. diff --git a/docs/src/release-notes-python.md b/docs/src/release-notes-python.md index 3988b84156..4fcea137c1 100644 --- a/docs/src/release-notes-python.md +++ b/docs/src/release-notes-python.md @@ -4,36 +4,6 @@ title: "Release notes" toc_max_heading_level: 2 --- -## Version 1.26 - -### Assertions - -- [`method: LocatorAssertions.toHaveAttribute#2`] can now be used for asserting attribute existence. -- New option `enabled` for [`method: LocatorAssertions.toBeEnabled`]. -- [`method: LocatorAssertions.toHaveText`] now pierces open shadow roots. -- New option `editable` for [`method: LocatorAssertions.toBeEditable`]. -- New option `visible` for [`method: LocatorAssertions.toBeVisible`]. - -### Other highlights - -- New option `max_redirects` for [`method: APIRequestContext.get`] and others to limit redirect count. -- Python 3.11 is now supported. - -### Behavior Change - -A bunch of Playwright APIs already support the `wait_until: "domcontentloaded"` option. -For example: - -```python -page.goto("https://playwright.dev", wait_until="domcontentloaded") -``` - -Prior to 1.26, this would wait for all iframes to fire the `DOMContentLoaded` -event. - -To align with web specification, the `'domcontentloaded'` value only waits for -the target frame to fire the `'DOMContentLoaded'` event. Use `wait_until="load"` to wait for all iframes. - ## Version 1.25 ### Announcements diff --git a/packages/playwright-core/src/server/injected/injectedScript.ts b/packages/playwright-core/src/server/injected/injectedScript.ts index df9f119887..fe757d123e 100644 --- a/packages/playwright-core/src/server/injected/injectedScript.ts +++ b/packages/playwright-core/src/server/injected/injectedScript.ts @@ -1038,9 +1038,7 @@ export class InjectedScript { { // Element state / boolean values. let elementState: boolean | 'error:notconnected' | 'error:notcheckbox' | undefined; - if (expression === 'to.have.attribute') { - elementState = element.hasAttribute(options.expressionArg); - } else if (expression === 'to.be.checked') { + if (expression === 'to.be.checked') { elementState = progress.injectedScript.elementState(element, 'checked'); } else if (expression === 'to.be.unchecked') { elementState = progress.injectedScript.elementState(element, 'unchecked'); @@ -1100,7 +1098,7 @@ export class InjectedScript { { // Single text value. let received: string | undefined; - if (expression === 'to.have.attribute.value') { + if (expression === 'to.have.attribute') { received = element.getAttribute(options.expressionArg) || ''; } else if (expression === 'to.have.class') { received = element.classList.toString(); diff --git a/packages/playwright-test/src/matchers/matchers.ts b/packages/playwright-test/src/matchers/matchers.ts index 3627a9fb3b..bccb016aff 100644 --- a/packages/playwright-test/src/matchers/matchers.ts +++ b/packages/playwright-test/src/matchers/matchers.ts @@ -17,7 +17,7 @@ import type { Locator, Page, APIResponse } from 'playwright-core'; import type { FrameExpectOptions } from 'playwright-core/lib/client/types'; import { colors } from 'playwright-core/lib/utilsBundle'; -import { constructURLBasedOnBaseURL, isRegExp } from 'playwright-core/lib/utils'; +import { constructURLBasedOnBaseURL } from 'playwright-core/lib/utils'; import type { Expect } from '../types'; import { expectTypes, callLogText } from '../util'; import { toBeTruthy } from './toBeTruthy'; @@ -141,25 +141,13 @@ export function toHaveAttribute( this: ReturnType, locator: LocatorEx, name: string, - expected: string | RegExp | undefined | { timeout?: number}, + expected: string | RegExp, options?: { timeout?: number }, ) { - if (!options) { - // Update params for the case toHaveAttribute(name, options); - if (typeof expected === 'object' && !isRegExp(expected)) { - options = expected; - expected = undefined; - } - } - if (expected === undefined) { - return toBeTruthy.call(this, 'toHaveAttribute', locator, 'Locator', async (isNot, timeout, customStackTrace) => { - return await locator._expect(customStackTrace, 'to.have.attribute', { expressionArg: name, isNot, timeout }); - }, options); - } return toMatchText.call(this, 'toHaveAttribute', locator, 'Locator', async (isNot, timeout, customStackTrace) => { - const expectedText = toExpectedTextValues([expected as (string | RegExp)]); - return await locator._expect(customStackTrace, 'to.have.attribute.value', { expressionArg: name, expectedText, isNot, timeout }); - }, expected as (string | RegExp), options); + const expectedText = toExpectedTextValues([expected]); + return await locator._expect(customStackTrace, 'to.have.attribute', { expressionArg: name, expectedText, isNot, timeout }); + }, expected, options); } export function toHaveClass( diff --git a/packages/playwright-test/types/test.d.ts b/packages/playwright-test/types/test.d.ts index c78ad4a558..556933d456 100644 --- a/packages/playwright-test/types/test.d.ts +++ b/packages/playwright-test/types/test.d.ts @@ -3450,11 +3450,10 @@ interface LocatorAssertions { }): Promise; /** - * Ensures the [Locator] points to an element with given attribute value. + * Ensures the [Locator] points to an element with given attribute. * * ```js * const locator = page.locator('input'); - * // Assert attribute with given value. * await expect(locator).toHaveAttribute('type', 'text'); * ``` * @@ -3469,26 +3468,6 @@ interface LocatorAssertions { timeout?: number; }): Promise; - /** - * Ensures the [Locator] points to an element with given attribute. The method will assert attribute presence. - * - * ```js - * const locator = page.locator('input'); - * // Assert attribute existence. - * await expect(locator).toHaveAttribute('disabled'); - * await expect(locator).not.toHaveAttribute('open'); - * ``` - * - * @param name Attribute name. - * @param options - */ - toHaveAttribute(name: string, options?: { - /** - * Time to retry the assertion for. Defaults to `timeout` in `TestConfig.expect`. - */ - timeout?: number; - }): Promise; - /** * Ensures the [Locator] points to an element with given CSS classes. This needs to be a full match or using a relaxed * regular expression. diff --git a/tests/page/expect-misc.spec.ts b/tests/page/expect-misc.spec.ts index 67848bd419..3b48c0d49e 100644 --- a/tests/page/expect-misc.spec.ts +++ b/tests/page/expect-misc.spec.ts @@ -228,22 +228,10 @@ test.describe('toHaveURL', () => { test.describe('toHaveAttribute', () => { test('pass', async ({ page }) => { - await page.setContent('
Text content
'); + await page.setContent('
Text content
'); const locator = page.locator('#node'); - await expect(locator).toHaveAttribute('id'); - await expect(locator).toHaveAttribute('checked'); - await expect(locator).not.toHaveAttribute('open'); await expect(locator).toHaveAttribute('id', 'node'); }); - - test('should support boolean attribute with options', async ({ page }) => { - await page.setContent('
Text content
'); - const locator = page.locator('#node'); - await expect(locator).toHaveAttribute('id', { timeout: 5000 }); - await expect(locator).toHaveAttribute('checked', { timeout: 5000 }); - await expect(locator).not.toHaveAttribute('open', { timeout: 5000 }); - await expect(locator).toHaveAttribute('id', 'node', { timeout: 5000 }); - }); }); test.describe('toHaveCSS', () => { diff --git a/tests/playwright-test/expect.spec.ts b/tests/playwright-test/expect.spec.ts index 112b431351..d6b457b73f 100644 --- a/tests/playwright-test/expect.spec.ts +++ b/tests/playwright-test/expect.spec.ts @@ -299,26 +299,6 @@ test('should return void/Promise when appropriate', async ({ runTSC }) => { expect(result.exitCode).toBe(0); }); -test('should suppport toHaveAttribute withou optional value', async ({ runTSC }) => { - const result = await runTSC({ - 'a.spec.ts': ` - const { test } = pwt; - test('custom matchers', async ({ page }) => { - const locator = page.locator('#node'); - await test.expect(locator).toHaveAttribute('name', 'value'); - await test.expect(locator).toHaveAttribute('name', 'value', { timeout: 10 }); - await test.expect(locator).toHaveAttribute('disabled'); - await test.expect(locator).toHaveAttribute('disabled', { timeout: 10 }); - // @ts-expect-error - await test.expect(locator).toHaveAttribute('disabled', { foo: 1 }); - // @ts-expect-error - await test.expect(locator).toHaveAttribute('name', 'value', 'opt'); - }); - ` - }); - expect(result.exitCode).toBe(0); -}); - test.describe('helpful expect errors', () => { test('top-level', async ({ runInlineTest }) => { const result = await runInlineTest({