feat(assertions): support toBeEditable({ editable }) (#17065)
This commit is contained in:
parent
92f44e34d6
commit
f0c5810609
|
|
@ -511,6 +511,9 @@ var locator = Page.Locator("input");
|
||||||
await Expect(locator).ToBeEditableAsync();
|
await Expect(locator).ToBeEditableAsync();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### option: LocatorAssertions.toBeEditable.editable
|
||||||
|
* since: v1.26
|
||||||
|
- `editable` <[boolean]>
|
||||||
### option: LocatorAssertions.toBeEditable.timeout = %%-js-assertions-timeout-%%
|
### option: LocatorAssertions.toBeEditable.timeout = %%-js-assertions-timeout-%%
|
||||||
* since: v1.18
|
* since: v1.18
|
||||||
### option: LocatorAssertions.toBeEditable.timeout = %%-csharp-java-python-assertions-timeout-%%
|
### option: LocatorAssertions.toBeEditable.timeout = %%-csharp-java-python-assertions-timeout-%%
|
||||||
|
|
|
||||||
|
|
@ -1034,6 +1034,8 @@ export class InjectedScript {
|
||||||
elementState = progress.injectedScript.elementState(element, 'disabled');
|
elementState = progress.injectedScript.elementState(element, 'disabled');
|
||||||
} else if (expression === 'to.be.editable') {
|
} else if (expression === 'to.be.editable') {
|
||||||
elementState = progress.injectedScript.elementState(element, 'editable');
|
elementState = progress.injectedScript.elementState(element, 'editable');
|
||||||
|
} else if (expression === 'to.be.readonly') {
|
||||||
|
elementState = !progress.injectedScript.elementState(element, 'editable');
|
||||||
} else if (expression === 'to.be.empty') {
|
} else if (expression === 'to.be.empty') {
|
||||||
if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA')
|
if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA')
|
||||||
elementState = !(element as HTMLInputElement).value;
|
elementState = !(element as HTMLInputElement).value;
|
||||||
|
|
|
||||||
|
|
@ -58,10 +58,11 @@ export function toBeDisabled(
|
||||||
export function toBeEditable(
|
export function toBeEditable(
|
||||||
this: ReturnType<Expect['getState']>,
|
this: ReturnType<Expect['getState']>,
|
||||||
locator: LocatorEx,
|
locator: LocatorEx,
|
||||||
options?: { timeout?: number },
|
options?: { editable?: boolean, timeout?: number },
|
||||||
) {
|
) {
|
||||||
return toBeTruthy.call(this, 'toBeEditable', locator, 'Locator', async (isNot, timeout, customStackTrace) => {
|
return toBeTruthy.call(this, 'toBeEditable', locator, 'Locator', async (isNot, timeout, customStackTrace) => {
|
||||||
return await locator._expect(customStackTrace, 'to.be.editable', { isNot, timeout });
|
const editable = !options || options.editable === undefined || options.editable === true;
|
||||||
|
return await locator._expect(customStackTrace, editable ? 'to.be.editable' : 'to.be.readonly', { isNot, timeout });
|
||||||
}, options);
|
}, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
2
packages/playwright-test/types/test.d.ts
vendored
2
packages/playwright-test/types/test.d.ts
vendored
|
|
@ -3274,6 +3274,8 @@ interface LocatorAssertions {
|
||||||
* @param options
|
* @param options
|
||||||
*/
|
*/
|
||||||
toBeEditable(options?: {
|
toBeEditable(options?: {
|
||||||
|
editable?: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Time to retry the assertion for. Defaults to `timeout` in `TestConfig.expect`.
|
* Time to retry the assertion for. Defaults to `timeout` in `TestConfig.expect`.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -78,12 +78,38 @@ test.describe('toBeChecked', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('toBeEditable', async ({ page }) => {
|
test.describe('toBeEditable', () => {
|
||||||
|
test('default', async ({ page }) => {
|
||||||
await page.setContent('<input></input>');
|
await page.setContent('<input></input>');
|
||||||
const locator = page.locator('input');
|
const locator = page.locator('input');
|
||||||
await expect(locator).toBeEditable();
|
await expect(locator).toBeEditable();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('with not', async ({ page }) => {
|
||||||
|
await page.setContent('<input readonly></input>');
|
||||||
|
const locator = page.locator('input');
|
||||||
|
await expect(locator).not.toBeEditable();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('with editable:true', async ({ page }) => {
|
||||||
|
await page.setContent('<input></input>');
|
||||||
|
const locator = page.locator('input');
|
||||||
|
await expect(locator).toBeEditable({ editable: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('with editable:false', async ({ page }) => {
|
||||||
|
await page.setContent('<input readonly></input>');
|
||||||
|
const locator = page.locator('input');
|
||||||
|
await expect(locator).toBeEditable({ editable: false });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('with not and editable:false', async ({ page }) => {
|
||||||
|
await page.setContent('<input></input>');
|
||||||
|
const locator = page.locator('input');
|
||||||
|
await expect(locator).not.toBeEditable({ editable: false });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test.describe('toBeEnabled', () => {
|
test.describe('toBeEnabled', () => {
|
||||||
test('default', async ({ page }) => {
|
test('default', async ({ page }) => {
|
||||||
await page.setContent('<button>Text</button>');
|
await page.setContent('<button>Text</button>');
|
||||||
|
|
|
||||||
|
|
@ -242,6 +242,12 @@ test('should propose only the relevant matchers when custom expect matcher class
|
||||||
await test.expect(res as any).toHaveURL('https://example.com');
|
await test.expect(res as any).toHaveURL('https://example.com');
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
await test.expect(123).toHaveURL('https://example.com');
|
await test.expect(123).toHaveURL('https://example.com');
|
||||||
|
|
||||||
|
await test.expect(page.locator('foo')).toBeChecked();
|
||||||
|
await test.expect(page.locator('foo')).not.toBeChecked({ checked: true });
|
||||||
|
|
||||||
|
await test.expect(page.locator('foo')).not.toBeEditable();
|
||||||
|
await test.expect(page.locator('foo')).toBeEditable({ editable: false });
|
||||||
});
|
});
|
||||||
`
|
`
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue