chore: revert toHaveAttribute type sig and overloads (#17406)
Relates #16517. Revert "docs(python): add missing NotToHaveAttribute overloads (#17371)" This reverts commit2e1ea29614. Revert "docs(release-notes): add 1.26 release notes for language ports (#17345)" This reverts commit4b8a85e69d. Revert "test: unflake "should support boolean attribute with options" (#17024)" This reverts commit1dc05bd4c6. Revert "fix: support toHaveAttribute(name, options) (#16941)" This reverts commitf30ac1d678. Revert "feat: expect(locator).toHaveAttribute to assert attribute presence (#16767)" This reverts commit622c73cc1e.
This commit is contained in:
parent
a6d9aa8708
commit
8d639ae50e
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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`].
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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<Expect['getState']>,
|
||||
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(
|
||||
|
|
|
|||
23
packages/playwright-test/types/test.d.ts
vendored
23
packages/playwright-test/types/test.d.ts
vendored
|
|
@ -3450,11 +3450,10 @@ interface LocatorAssertions {
|
|||
}): Promise<void>;
|
||||
|
||||
/**
|
||||
* 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<void>;
|
||||
|
||||
/**
|
||||
* 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<void>;
|
||||
|
||||
/**
|
||||
* Ensures the [Locator] points to an element with given CSS classes. This needs to be a full match or using a relaxed
|
||||
* regular expression.
|
||||
|
|
|
|||
|
|
@ -228,22 +228,10 @@ test.describe('toHaveURL', () => {
|
|||
|
||||
test.describe('toHaveAttribute', () => {
|
||||
test('pass', async ({ page }) => {
|
||||
await page.setContent('<div checked id=node>Text content</div>');
|
||||
await page.setContent('<div id=node>Text content</div>');
|
||||
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('<div checked id=node>Text content</div>');
|
||||
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', () => {
|
||||
|
|
|
|||
|
|
@ -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({
|
||||
|
|
|
|||
Loading…
Reference in a new issue