diff --git a/docs/src/intro-js.md b/docs/src/intro-js.md index a79cfac75f..aa23327eb9 100644 --- a/docs/src/intro-js.md +++ b/docs/src/intro-js.md @@ -85,32 +85,12 @@ Refer to [configuration](./test-configuration.md) section for configuring test r ## Writing assertions -Playwright Test uses [expect](https://jestjs.io/docs/expect) library for test assertions. It provides a lot of matchers like `toEqual`, `toContain`, `toMatch`, `toMatchSnapshot` and many more. Playwright also extends this set with the following matchers: +Playwright Test uses [expect](https://jestjs.io/docs/expect) library for test assertions. It extends it with the Playwright-specific matchers to achieve greater testing ergonomics. -- `toBeChecked` -- `toBeDisabled` -- `toBeEditable` -- `toBeEmpty` -- `toBeEnabled` -- `toBeFocused` -- `toBeHidden` -- `toBeSelected` -- `toBeVisible` -- `toContainText` -- `toHaveAttr` -- `toHaveClass` -- `toHaveCount` -- `toHaveCSS` -- `toHaveData` -- `toHaveId` -- `toHaveProp` -- `toHaveText` -- `toHaveTitle` -- `toHaveURL` -- `toHaveValue` -- `toMatchSnapshot` +Learn more about [test assertions here](./test-assertions.md). + +Here is a quick example of using them: -- Find out more in the [assertions](./assertions.md) guide ```js js-flavor=js // example.spec.js @@ -123,7 +103,7 @@ test('my test', async ({ page }) => { await expect(page).toHaveTitle('Playwright'); // Expect an attribute "to be strictly equal" to the value. - await expect(page.locator('text=Get Started').toHaveAttr('href', '/docs/intro'); + await expect(page.locator('text=Get Started').toHaveAttribute('href', '/docs/intro'); // Expect an element "to be visible". await expect(page.locator('text=Learn more')).toBeVisible(); @@ -148,7 +128,7 @@ test('my test', async ({ page }) => { await expect(page).toHaveTitle('Playwright'); // Expect an attribute "to be strictly equal" to the value. - await expect(page.locator('text=Get Started').toHaveAttr('href', '/docs/intro'); + await expect(page.locator('text=Get Started').toHaveAttribute('href', '/docs/intro'); // Expect an element "to be visible". await expect(page.locator('text=Learn more')).toBeVisible(); diff --git a/docs/src/test-assertions-js.md b/docs/src/test-assertions-js.md index 0a3c40dc8f..b9be989e8b 100644 --- a/docs/src/test-assertions-js.md +++ b/docs/src/test-assertions-js.md @@ -107,17 +107,6 @@ const locator = await page.locator('.my-element'); await expect(locator).toBeHidden(); ``` -## expect(locator).toBeSelected -- `options` - - `timeout`: <[number]> Time to retry assertion for, defaults to [`property: Fixtures.actionTimeout`]. - -Ensures [Locator] points to a selected option. - -```js -const locator = await page.locator('option[value=Three]'); -await expect(locator).toBeSelected(); -``` - ## expect(locator).toBeVisible - `options` - `timeout`: <[number]> Time to retry assertion for, defaults to [`property: Fixtures.actionTimeout`]. @@ -142,7 +131,7 @@ const locator = await page.locator('.title'); await expect(locator).toContainText('substring'); ``` -## expect(locator).toHaveAttr(name, value) +## expect(locator).toHaveAttribute(name, value) - `name`: <[string]> Attribute name - `value`: <[string]|[RegExp]> Attribute value - `options` @@ -152,7 +141,7 @@ Ensures [Locator] points to an element with given attribute. ```js const locator = await page.locator('input'); -await expect(locator).toHaveAttr('type', 'text'); +await expect(locator).toHaveAttribute('type', 'text'); ``` ## expect(locator).toHaveClass(expected) @@ -199,19 +188,6 @@ const locator = await page.locator('button'); await expect(locator).toHaveCSS('display', 'flex'); ``` -## expect(locator).toHaveData(name, value) -- `name`: <[string]> Data attribute name -- `value`: <[string]|[RegExp]> Data value -- `options` - - `timeout`: <[number]> Time to retry assertion for, defaults to [`property: Fixtures.actionTimeout`]. - -Ensures [Locator] points to an element with given data binding. - -```js -const locator = await page.locator('input'); -await expect(locator).toHaveData('mydata', 'myvalue'); -``` - ## expect(locator).toHaveId(id) - `id`: <[string]> Element id - `options` @@ -224,7 +200,7 @@ const locator = await page.locator('input'); await expect(locator).toHaveId('lastname'); ``` -## expect(locator).toHaveProp(name, value) +## expect(locator).toHaveJSProperty(name, value) - `name`: <[string]> Property name - `value`: <[any]> Property value - `options` @@ -235,7 +211,7 @@ of a primitive type as well as a plain serializable JavaScript object. ```js const locator = await page.locator('.component'); -await expect(locator).toHaveProp('loaded', true); +await expect(locator).toHaveJSProperty('loaded', true); ``` ## expect(locator).toHaveText(expected, options) diff --git a/src/test/expect.ts b/src/test/expect.ts index 7215acff14..b5175ed678 100644 --- a/src/test/expect.ts +++ b/src/test/expect.ts @@ -23,16 +23,14 @@ import { toBeEnabled, toBeFocused, toBeHidden, - toBeSelected, toBeVisible, toContainText, - toHaveAttr, + toHaveAttribute, toHaveClass, toHaveCount, toHaveCSS, - toHaveData, toHaveId, - toHaveProp, + toHaveJSProperty, toHaveText, toHaveTitle, toHaveURL, @@ -54,16 +52,14 @@ const customMatchers = { toBeEnabled, toBeFocused, toBeHidden, - toBeSelected, toBeVisible, toContainText, - toHaveAttr, + toHaveAttribute, toHaveClass, toHaveCount, toHaveCSS, - toHaveData, toHaveId, - toHaveProp, + toHaveJSProperty, toHaveText, toHaveTitle, toHaveURL, diff --git a/src/test/matchers/matchers.ts b/src/test/matchers/matchers.ts index a352a2ceb9..0b7fa86e11 100644 --- a/src/test/matchers/matchers.ts +++ b/src/test/matchers/matchers.ts @@ -96,18 +96,6 @@ export function toBeHidden( }, options); } -export function toBeSelected( - this: ReturnType, - locator: Locator, - options?: { timeout?: number }, -) { - return toBeTruthy.call(this, 'toBeSelected', locator, 'Locator', async timeout => { - return await locator.evaluate(element => { - return (element as HTMLOptionElement).selected; - }, { timeout }); - }, options); -} - export function toBeVisible( this: ReturnType, locator: Locator, @@ -131,14 +119,14 @@ export function toContainText( }, expected, { ...options, matchSubstring: true }); } -export function toHaveAttr( +export function toHaveAttribute( this: ReturnType, locator: Locator, name: string, expected: string | RegExp, options?: { timeout?: number }, ) { - return toMatchText.call(this, 'toHaveAttr', locator, 'Locator', async timeout => { + return toMatchText.call(this, 'toHaveAttribute', locator, 'Locator', async timeout => { return await locator.getAttribute(name, { timeout }) || ''; }, expected, options); } @@ -185,18 +173,6 @@ export function toHaveCSS( }, expected, options); } -export function toHaveData( - this: ReturnType, - locator: Locator, - name: string, - expected: string | RegExp, - options?: { timeout?: number }, -) { - return toMatchText.call(this, 'toHaveData', locator, 'Locator', async timeout => { - return await locator.getAttribute('data-' + name, { timeout }) || ''; - }, expected, options); -} - export function toHaveId( this: ReturnType, locator: Locator, @@ -208,14 +184,14 @@ export function toHaveId( }, expected, options); } -export function toHaveProp( +export function toHaveJSProperty( this: ReturnType, locator: Locator, name: string, expected: any, options?: { timeout?: number }, ) { - return toEqual.call(this, 'toHaveProp', locator, 'Locator', async timeout => { + return toEqual.call(this, 'toHaveJSProperty', locator, 'Locator', async timeout => { return await locator.evaluate((element, name) => (element as any)[name], name, { timeout }); }, expected, options); } diff --git a/tests/playwright-test/playwright.expect.misc.spec.ts b/tests/playwright-test/playwright.expect.misc.spec.ts index 747d7a551f..0e7f78e3f6 100644 --- a/tests/playwright-test/playwright.expect.misc.spec.ts +++ b/tests/playwright-test/playwright.expect.misc.spec.ts @@ -32,7 +32,7 @@ test('should support toHaveCount', async ({ runInlineTest }) => { expect(result.exitCode).toBe(0); }); -test('should support toHaveProp', async ({ runInlineTest }) => { +test('should support toHaveJSProperty', async ({ runInlineTest }) => { const result = await runInlineTest({ 'a.test.ts': ` const { test } = pwt; @@ -41,14 +41,14 @@ test('should support toHaveProp', async ({ runInlineTest }) => { await page.setContent('
'); await page.$eval('div', e => e.foo = { a: 1, b: 'string', c: new Date(1627503992000) }); const locator = page.locator('div'); - await expect(locator).toHaveProp('foo', { a: 1, b: 'string', c: new Date(1627503992000) }); + await expect(locator).toHaveJSProperty('foo', { a: 1, b: 'string', c: new Date(1627503992000) }); }); test('fail', async ({ page }) => { await page.setContent('
'); await page.$eval('div', e => e.foo = { a: 1, b: 'string', c: new Date(1627503992000) }); const locator = page.locator('div'); - await expect(locator).toHaveProp('foo', { a: 1, b: 'string', c: new Date(1627503992001) }, { timeout: 1000 }); + await expect(locator).toHaveJSProperty('foo', { a: 1, b: 'string', c: new Date(1627503992001) }, { timeout: 1000 }); }); `, }, { workers: 1 }); diff --git a/tests/playwright-test/playwright.expect.text.spec.ts b/tests/playwright-test/playwright.expect.text.spec.ts index 81314d9ad5..d0dd33c827 100644 --- a/tests/playwright-test/playwright.expect.text.spec.ts +++ b/tests/playwright-test/playwright.expect.text.spec.ts @@ -141,7 +141,7 @@ test('should support toHaveText with innerText', async ({ runInlineTest }) => { expect(result.exitCode).toBe(0); }); -test('should support toHaveAttr', async ({ runInlineTest }) => { +test('should support toHaveAttribute', async ({ runInlineTest }) => { const result = await runInlineTest({ 'a.test.ts': ` const { test } = pwt; @@ -149,23 +149,7 @@ test('should support toHaveAttr', async ({ runInlineTest }) => { test('pass', async ({ page }) => { await page.setContent('
Text content
'); const locator = page.locator('#node'); - await expect(locator).toHaveAttr('id', 'node'); - }); - `, - }, { workers: 1 }); - expect(result.passed).toBe(1); - expect(result.exitCode).toBe(0); -}); - -test('should support toHaveData', async ({ runInlineTest }) => { - const result = await runInlineTest({ - 'a.test.ts': ` - const { test } = pwt; - - test('pass', async ({ page }) => { - await page.setContent('
Text content
'); - const locator = page.locator('#node'); - await expect(locator).toHaveAttr('id', 'node'); + await expect(locator).toHaveAttribute('id', 'node'); }); `, }, { workers: 1 }); diff --git a/tests/playwright-test/playwright.expect.true.spec.ts b/tests/playwright-test/playwright.expect.true.spec.ts index 5ebb35cc76..c62320b641 100644 --- a/tests/playwright-test/playwright.expect.true.spec.ts +++ b/tests/playwright-test/playwright.expect.true.spec.ts @@ -128,7 +128,7 @@ test('should support toBeVisible, toBeHidden', async ({ runInlineTest }) => { expect(result.exitCode).toBe(0); }); -test('should support toBeFocused, toBeSelected', async ({ runInlineTest }) => { +test('should support toBeFocused', async ({ runInlineTest }) => { const result = await runInlineTest({ 'a.test.ts': ` const { test } = pwt; @@ -139,23 +139,8 @@ test('should support toBeFocused, toBeSelected', async ({ runInlineTest }) => { await locator.focus(); await expect(locator).toBeFocused({ timeout: 1000 }); }); - - test('selected', async ({ page }) => { - await page.setContent(''); - const locator = page.locator('option'); - await expect(locator).toBeSelected(); - }); - - test('fail on strict option', async ({ page }) => { - await page.setContent(''); - const locator = page.locator('option'); - await expect(locator).toBeSelected(); - }); `, }, { workers: 1 }); - const output = stripAscii(result.output); - expect(output).toContain('strict mode violation'); - expect(result.passed).toBe(2); - expect(result.failed).toBe(1); - expect(result.exitCode).toBe(1); + expect(result.passed).toBe(1); + expect(result.exitCode).toBe(0); }); diff --git a/types/testExpect.d.ts b/types/testExpect.d.ts index 91d325c414..5dbd04d0c0 100644 --- a/types/testExpect.d.ts +++ b/types/testExpect.d.ts @@ -109,11 +109,6 @@ declare global { */ toBeVisible(options?: { timeout?: number }): Promise; - /** - * Asserts given select option is selected - */ - toBeSelected(options?: { timeout?: number }): Promise; - /** * Asserts element's text content matches given pattern or contains given substring. */ @@ -122,7 +117,7 @@ declare global { /** * Asserts element's attributes `name` matches expected value. */ - toHaveAttr(expected: string | RegExp, name: string, options?: { timeout?: number }): Promise; + toHaveAttribute(expected: string | RegExp, name: string, options?: { timeout?: number }): Promise; /** * Asserts that DOM node has a given CSS class. @@ -139,11 +134,6 @@ declare global { */ toHaveCSS(expected: string | RegExp, name: string, options?: { timeout?: number }): Promise; - /** - * Asserts element's data attribute data-`name` matches expected value. - */ - toHaveData(expected: string | RegExp, name: string, options?: { timeout?: number }): Promise; - /** * Asserts element's `id` attribute matches expected value. */ @@ -152,7 +142,7 @@ declare global { /** * Asserts JavaScript object that corresponds to the Node has a property with given value. */ - toHaveProp(name: string, value: any, options?: { timeout?: number }): Promise; + toHaveJSProperty(name: string, value: any, options?: { timeout?: number }): Promise; /** * Asserts element's text content.