From b1b0ab29acb42d1c6c4fc0fa5c811ad930bcc3be Mon Sep 17 00:00:00 2001 From: Jamie Rolfs Date: Wed, 31 Aug 2022 21:21:06 -0700 Subject: [PATCH 1/3] refactor: use `queries` from Testing Library to enumerate queries --- lib/fixture/locator/fixtures.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/fixture/locator/fixtures.ts b/lib/fixture/locator/fixtures.ts index 10095f6..f137549 100644 --- a/lib/fixture/locator/fixtures.ts +++ b/lib/fixture/locator/fixtures.ts @@ -1,12 +1,20 @@ import type {Locator, Page, PlaywrightTestArgs, TestFixture} from '@playwright/test' import {selectors} from '@playwright/test' +import {queries} from '@testing-library/dom' -import {queryNames as allQueryNames} from '../../common' import {replacer} from '../helpers' -import type {Config, LocatorQueries as Queries, SelectorEngine, SupportedQuery} from '../types' +import type { + Config, + LocatorQueries as Queries, + Query, + SelectorEngine, + SupportedQuery, +} from '../types' import {buildTestingLibraryScript, isAllQuery, isNotFindQuery, queryToSelector} from './helpers' +const allQueryNames = Object.keys(queries) as Query[] + const queryNames = allQueryNames.filter(isNotFindQuery) const defaultConfig: Config = {testIdAttribute: 'data-testid', asyncUtilTimeout: 1000} From 9a843fd2f7690f54f92a33042f3687a047262009 Mon Sep 17 00:00:00 2001 From: Jamie Rolfs Date: Wed, 31 Aug 2022 21:23:51 -0700 Subject: [PATCH 2/3] =?UTF-8?q?refactor:=20rename=20'supported'=20?= =?UTF-8?q?=E2=86=92=20'synchronous'=20query,=20move=20helper=20stuff?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/fixture/locator/fixtures.ts | 37 ++++++++++----------------------- lib/fixture/locator/helpers.ts | 33 +++++++++++++++++++++++++---- lib/fixture/types.ts | 5 +++-- 3 files changed, 43 insertions(+), 32 deletions(-) diff --git a/lib/fixture/locator/fixtures.ts b/lib/fixture/locator/fixtures.ts index f137549..1641256 100644 --- a/lib/fixture/locator/fixtures.ts +++ b/lib/fixture/locator/fixtures.ts @@ -1,43 +1,28 @@ -import type {Locator, Page, PlaywrightTestArgs, TestFixture} from '@playwright/test' +import type {Locator, PlaywrightTestArgs, TestFixture} from '@playwright/test' import {selectors} from '@playwright/test' -import {queries} from '@testing-library/dom' -import {replacer} from '../helpers' -import type { - Config, - LocatorQueries as Queries, - Query, - SelectorEngine, - SupportedQuery, -} from '../types' +import type {Config, LocatorQueries as Queries, SelectorEngine, SynchronousQuery} from '../types' -import {buildTestingLibraryScript, isAllQuery, isNotFindQuery, queryToSelector} from './helpers' +import { + buildTestingLibraryScript, + isAllQuery, + queriesFor, + queryToSelector, + synchronousQueryNames, +} from './helpers' -const allQueryNames = Object.keys(queries) as Query[] - -const queryNames = allQueryNames.filter(isNotFindQuery) const defaultConfig: Config = {testIdAttribute: 'data-testid', asyncUtilTimeout: 1000} const options = Object.fromEntries( Object.entries(defaultConfig).map(([key, value]) => [key, [value, {option: true}] as const]), ) -const queriesFor = (pageOrLocator: Page | Locator) => - queryNames.reduce( - (rest, query) => ({ - ...rest, - [query]: (...args: Parameters) => - pageOrLocator.locator(`${queryToSelector(query)}=${JSON.stringify(args, replacer)}`), - }), - {} as Queries, - ) - const queriesFixture: TestFixture = async ({page}, use) => use(queriesFor(page)) const within = (locator: Locator): Queries => queriesFor(locator) -declare const queryName: SupportedQuery +declare const queryName: SynchronousQuery const engine: () => SelectorEngine = () => ({ query(root, selector) { @@ -77,7 +62,7 @@ const registerSelectorsFixture: [ async ({}, use) => { try { await Promise.all( - queryNames.map(async name => + synchronousQueryNames.map(async name => selectors.register( queryToSelector(name), `(${engine.toString().replace(/queryName/g, `"${name}"`)})()`, diff --git a/lib/fixture/locator/helpers.ts b/lib/fixture/locator/helpers.ts index a4829c9..622738c 100644 --- a/lib/fixture/locator/helpers.ts +++ b/lib/fixture/locator/helpers.ts @@ -1,14 +1,27 @@ import {promises as fs} from 'fs' +import type {Locator, Page} from '@playwright/test' +import {queries} from '@testing-library/dom' + import {configureTestingLibraryScript} from '../../common' -import {reviver} from '../helpers' -import type {AllQuery, Config, FindQuery, Query, Selector, SupportedQuery} from '../types' +import {replacer, reviver} from '../helpers' +import type { + AllQuery, + Config, + FindQuery, + LocatorQueries as Queries, + Query, + Selector, + SynchronousQuery, +} from '../types' + +const allQueryNames = Object.keys(queries) as Query[] const isAllQuery = (query: Query): query is AllQuery => query.includes('All') const isNotFindQuery = (query: Query): query is Exclude => !query.startsWith('find') -const queryToSelector = (query: SupportedQuery) => +const queryToSelector = (query: SynchronousQuery) => query.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase() as Selector const buildTestingLibraryScript = async ({config}: {config: Config}) => { @@ -26,4 +39,16 @@ const buildTestingLibraryScript = async ({config}: {config: Config}) => { ` } -export {isAllQuery, isNotFindQuery, queryToSelector, buildTestingLibraryScript} +const synchronousQueryNames = allQueryNames.filter(isNotFindQuery) + +const queriesFor = (pageOrLocator: Page | Locator) => + synchronousQueryNames.reduce( + (rest, query) => ({ + ...rest, + [query]: (...args: Parameters) => + pageOrLocator.locator(`${queryToSelector(query)}=${JSON.stringify(args, replacer)}`), + }), + {} as Queries, + ) + +export {buildTestingLibraryScript, isAllQuery, queriesFor, queryToSelector, synchronousQueryNames} diff --git a/lib/fixture/types.ts b/lib/fixture/types.ts index d8f9ef5..974de30 100644 --- a/lib/fixture/types.ts +++ b/lib/fixture/types.ts @@ -45,9 +45,10 @@ export type Query = keyof Queries export type AllQuery = Extract export type FindQuery = Extract -export type SupportedQuery = Exclude +export type GetQuery = Extract +export type SynchronousQuery = Exclude -export type Selector = KebabCase +export type Selector = KebabCase export type {Config} export interface ConfigFn { From 2bc86e1a7f9e265716602cd9a344788edda42215 Mon Sep 17 00:00:00 2001 From: Jamie Rolfs Date: Wed, 31 Aug 2022 21:25:58 -0700 Subject: [PATCH 3/3] test: isolate 'standard' page (no timeout) in `describe` blocks --- test/fixture/element-handles.test.ts | 263 ++++++++++++++------------- test/fixture/locators.test.ts | 220 +++++++++++----------- 2 files changed, 249 insertions(+), 234 deletions(-) diff --git a/test/fixture/element-handles.test.ts b/test/fixture/element-handles.test.ts index f97261a..bd74084 100644 --- a/test/fixture/element-handles.test.ts +++ b/test/fixture/element-handles.test.ts @@ -10,187 +10,196 @@ const test = playwright.test.extend(fixtures) const {expect} = test test.describe('lib/fixture.ts', () => { - test.beforeEach(async ({page}) => { - await page.goto(`file://${path.join(__dirname, '../fixtures/page.html')}`) - }) - - test('should handle the query* methods', async ({queries: {queryByText}}) => { - const element = await queryByText('Hello h1') + test.describe('standard page', () => { + test.beforeEach(async ({page}) => { + await page.goto(`file://${path.join(__dirname, '../fixtures/page.html')}`) + }) - expect(element).toBeTruthy() - expect(await element.textContent()).toEqual('Hello h1') - }) + test.afterEach(async ({page}) => page.close()) - test('should use the new v3 methods', async ({queries: {queryByRole}}) => { - const element = await queryByRole('presentation') + test('should handle the query* methods', async ({queries: {queryByText}}) => { + const element = await queryByText('Hello h1') - expect(element).toBeTruthy() - expect(await element.textContent()).toContain('Layout table') - }) + expect(element).toBeTruthy() + expect(await element.textContent()).toEqual('Hello h1') + }) - test('should handle regex matching', async ({queries: {queryByText}}) => { - const element = await queryByText(/HeLlO h(1|7)/i) + test('should use the new v3 methods', async ({queries: {queryByRole}}) => { + const element = await queryByRole('presentation') - expect(element).toBeTruthy() - expect(await element.textContent()).toEqual('Hello h1') - }) + expect(element).toBeTruthy() + expect(await element.textContent()).toContain('Layout table') + }) - test('should handle the get* methods', async ({queries: {getByTestId}, page}) => { - const element = await getByTestId('testid-text-input') + test('should handle regex matching', async ({queries: {queryByText}}) => { + const element = await queryByText(/HeLlO h(1|7)/i) - expect(await page.evaluate(el => el.outerHTML, element)).toMatch( - ``, - ) - }) + expect(element).toBeTruthy() + expect(await element.textContent()).toEqual('Hello h1') + }) - test('attaches `getNodeText`', async ({queries}) => { - const element = await queries.getByText('Hello h1') + test('should handle the get* methods', async ({queries: {getByTestId}, page}) => { + const element = await getByTestId('testid-text-input') - expect(await queries.getNodeText(element)).toEqual('Hello h1') - }) + expect(await page.evaluate(el => el.outerHTML, element)).toMatch( + ``, + ) + }) - test('handles page navigations', async ({queries: {getByText}, page}) => { - await page.goto(`file://${path.join(__dirname, '../fixtures/page.html')}`) + test('attaches `getNodeText`', async ({queries}) => { + const element = await queries.getByText('Hello h1') - const element = await getByText('Hello h1') + expect(await queries.getNodeText(element)).toEqual('Hello h1') + }) - expect(await element.textContent()).toEqual('Hello h1') - }) + test('handles page navigations', async ({queries: {getByText}, page}) => { + await page.goto(`file://${path.join(__dirname, '../fixtures/page.html')}`) - test('should handle the get* method failures', async ({queries}) => { - const {getByTitle} = queries - // Use the scoped element so the pretty HTML snapshot is smaller + const element = await getByText('Hello h1') - await expect(async () => getByTitle('missing')).rejects.toThrow() - }) + expect(await element.textContent()).toEqual('Hello h1') + }) - test('should handle the LabelText methods', async ({queries, page}) => { - const {getByLabelText} = queries - const element = await getByLabelText('Label A') - /* istanbul ignore next */ - expect(await page.evaluate(el => el.outerHTML, element)).toMatch( - ``, - ) - }) + test('should handle the get* method failures', async ({queries}) => { + const {getByTitle} = queries + // Use the scoped element so the pretty HTML snapshot is smaller - test('should handle the queryAll* methods', async ({queries, page}) => { - const {queryAllByText} = queries - const elements = await queryAllByText(/Hello/) - expect(elements).toHaveLength(3) + await expect(async () => getByTitle('missing')).rejects.toThrow() + }) - const text = await Promise.all([ - page.evaluate(el => el.textContent, elements[0]), - page.evaluate(el => el.textContent, elements[1]), - page.evaluate(el => el.textContent, elements[2]), - ]) + test('should handle the LabelText methods', async ({queries, page}) => { + const {getByLabelText} = queries + const element = await getByLabelText('Label A') + /* istanbul ignore next */ + expect(await page.evaluate(el => el.outerHTML, element)).toMatch( + ``, + ) + }) - expect(text).toEqual(['Hello h1', 'Hello h2', 'Hello h3']) - }) + test('should handle the queryAll* methods', async ({queries, page}) => { + const {queryAllByText} = queries + const elements = await queryAllByText(/Hello/) + expect(elements).toHaveLength(3) - test('should handle the queryAll* methods with a selector', async ({queries, page}) => { - const {queryAllByText} = queries - const elements = await queryAllByText(/Hello/, {selector: 'h2'}) - expect(elements).toHaveLength(1) + const text = await Promise.all([ + page.evaluate(el => el.textContent, elements[0]), + page.evaluate(el => el.textContent, elements[1]), + page.evaluate(el => el.textContent, elements[2]), + ]) - const text = await page.evaluate(el => el.textContent, elements[0]) + expect(text).toEqual(['Hello h1', 'Hello h2', 'Hello h3']) + }) - expect(text).toEqual('Hello h2') - }) + test('should handle the queryAll* methods with a selector', async ({queries, page}) => { + const {queryAllByText} = queries + const elements = await queryAllByText(/Hello/, {selector: 'h2'}) + expect(elements).toHaveLength(1) - test('should handle the getBy* methods with a selector', async ({queries, page}) => { - const {getByText} = queries - const element = await getByText(/Hello/, {selector: 'h2'}) + const text = await page.evaluate(el => el.textContent, elements[0]) - const text = await page.evaluate(el => el.textContent, element) + expect(text).toEqual('Hello h2') + }) - expect(text).toEqual('Hello h2') - }) + test('should handle the getBy* methods with a selector', async ({queries, page}) => { + const {getByText} = queries + const element = await getByText(/Hello/, {selector: 'h2'}) - test('should handle the getBy* methods with a regex name', async ({queries, page}) => { - const {getByRole} = queries - const element = await getByRole('button', {name: /getBy.*Test/}) + const text = await page.evaluate(el => el.textContent, element) - const text = await page.evaluate(el => el.textContent, element) + expect(text).toEqual('Hello h2') + }) - expect(text).toEqual('getByRole Test') - }) + test('should handle the getBy* methods with a regex name', async ({queries, page}) => { + const {getByRole} = queries + const element = await getByRole('button', {name: /getBy.*Test/}) - test('supports `hidden` option when querying by role', async ({queries: {queryAllByRole}}) => { - const elements = await queryAllByRole('img') - const hiddenElements = await queryAllByRole('img', {hidden: true}) + const text = await page.evaluate(el => el.textContent, element) - expect(elements).toHaveLength(1) - expect(hiddenElements).toHaveLength(2) - }) + expect(text).toEqual('getByRole Test') + }) - test.describe('querying by role with `level` option', () => { - test('retrieves the correct elements when querying all by role', async ({ - queries: {queryAllByRole}, - }) => { - const elements = await queryAllByRole('heading') - const levelOneElements = await queryAllByRole('heading', {level: 3}) + test('supports `hidden` option when querying by role', async ({queries: {queryAllByRole}}) => { + const elements = await queryAllByRole('img') + const hiddenElements = await queryAllByRole('img', {hidden: true}) - expect(elements).toHaveLength(3) - expect(levelOneElements).toHaveLength(1) + expect(elements).toHaveLength(1) + expect(hiddenElements).toHaveLength(2) }) - test('does not throw when querying for a specific element', async ({queries: {getByRole}}) => { - await expect(getByRole('heading', {level: 3})).resolves.not.toThrow() + test.describe('querying by role with `level` option', () => { + test('retrieves the correct elements when querying all by role', async ({ + queries: {queryAllByRole}, + }) => { + const elements = await queryAllByRole('heading') + const levelOneElements = await queryAllByRole('heading', {level: 3}) + + expect(elements).toHaveLength(3) + expect(levelOneElements).toHaveLength(1) + }) + + test('does not throw when querying for a specific element', async ({ + queries: {getByRole}, + }) => { + await expect(getByRole('heading', {level: 3})).resolves.not.toThrow() + }) }) - }) - test('should get text content', async ({page}) => { - const document = await getDocument(page) - const $h3 = await document.$('#scoped h3') + test('should get text content', async ({page}) => { + const document = await getDocument(page) + const $h3 = await document.$('#scoped h3') - expect(await $h3.textContent()).toEqual('Hello h3') - }) - - test('scoping queries with `within`', async ({queries: {getByTestId}}) => { - // eslint-disable-next-line @typescript-eslint/unbound-method - const {queryByText} = within(await getByTestId('scoped')) + expect(await $h3.textContent()).toEqual('Hello h3') + }) - expect(await queryByText('Hello h1')).toBeFalsy() - expect(await queryByText('Hello h3')).toBeTruthy() - }) + test('scoping queries with `within`', async ({queries: {getByTestId}}) => { + // eslint-disable-next-line @typescript-eslint/unbound-method + const {queryByText} = within(await getByTestId('scoped')) - test('scoping queries with `getQueriesForElement`', async ({queries: {getByTestId}}) => { - // eslint-disable-next-line @typescript-eslint/unbound-method - const {queryByText} = getQueriesForElement(await getByTestId('scoped')) + expect(await queryByText('Hello h1')).toBeFalsy() + expect(await queryByText('Hello h3')).toBeTruthy() + }) - expect(await queryByText('Hello h1')).toBeFalsy() - expect(await queryByText('Hello h3')).toBeTruthy() - }) + test('scoping queries with `getQueriesForElement`', async ({queries: {getByTestId}}) => { + // eslint-disable-next-line @typescript-eslint/unbound-method + const {queryByText} = getQueriesForElement(await getByTestId('scoped')) - test.describe('configuration', () => { - test.afterEach(() => { - configure({testIdAttribute: 'data-testid'}) // cleanup + expect(await queryByText('Hello h1')).toBeFalsy() + expect(await queryByText('Hello h3')).toBeTruthy() }) - test('should support custom data-testid attribute name', async ({queries}) => { - configure({testIdAttribute: 'data-id'}) + test.describe('configuration', () => { + test.afterEach(() => { + configure({testIdAttribute: 'data-testid'}) // cleanup + }) - const element = await queries.getByTestId('second-level-header') + test('should support custom data-testid attribute name', async ({queries}) => { + configure({testIdAttribute: 'data-id'}) - expect(await queries.getNodeText(element)).toEqual('Hello h2') - }) + const element = await queries.getByTestId('second-level-header') - test('should support subsequent changing the data-testid attribute names', async ({ - queries, - }) => { - configure({testIdAttribute: 'data-id'}) - configure({testIdAttribute: 'data-new-id'}) + expect(await queries.getNodeText(element)).toEqual('Hello h2') + }) - const element = await queries.getByTestId('first-level-header') + test('should support subsequent changing the data-testid attribute names', async ({ + queries, + }) => { + configure({testIdAttribute: 'data-id'}) + configure({testIdAttribute: 'data-new-id'}) - expect(await queries.getNodeText(element)).toEqual('Hello h1') + const element = await queries.getByTestId('first-level-header') + + expect(await queries.getNodeText(element)).toEqual('Hello h1') + }) }) }) + test.describe('deferred page', () => { test.beforeEach(async ({page}) => { await page.goto(`file://${path.join(__dirname, '../fixtures/late-page.html')}`) }) + test.afterEach(async ({page}) => page.close()) + test('should handle the findBy* methods', async ({queries}) => { const {findByText} = queries expect(await findByText('Loaded!', {}, {timeout: 7000})).toBeTruthy() diff --git a/test/fixture/locators.test.ts b/test/fixture/locators.test.ts index 7dc56ea..7dbee45 100644 --- a/test/fixture/locators.test.ts +++ b/test/fixture/locators.test.ts @@ -13,156 +13,162 @@ const test = playwright.test.extend(fixtures) const {expect} = test test.describe('lib/fixture.ts (locators)', () => { - test.beforeEach(async ({page}) => { - await page.goto(`file://${path.join(__dirname, '../fixtures/page.html')}`) - }) + test.describe('standard page', () => { + test.beforeEach(async ({page}) => { + await page.goto(`file://${path.join(__dirname, '../fixtures/page.html')}`) + }) - test('should handle the query* methods', async ({queries: {queryByText}}) => { - const locator = queryByText('Hello h1') + test.afterEach(async ({page}) => page.close()) - expect(locator).toBeTruthy() - expect(await locator.textContent()).toEqual('Hello h1') - }) + test('should handle the query* methods', async ({queries: {queryByText}}) => { + const locator = queryByText('Hello h1') - test('should use the new v3 methods', async ({queries: {queryByRole}}) => { - const locator = queryByRole('presentation') - - expect(locator).toBeTruthy() - expect(await locator.textContent()).toContain('Layout table') - }) + expect(locator).toBeTruthy() + expect(await locator.textContent()).toEqual('Hello h1') + }) - test('should handle regex matching', async ({queries: {queryByText}}) => { - const locator = queryByText(/HeLlO h(1|7)/i) + test('should use the new v3 methods', async ({queries: {queryByRole}}) => { + const locator = queryByRole('presentation') - expect(locator).toBeTruthy() - expect(await locator.textContent()).toEqual('Hello h1') - }) + expect(locator).toBeTruthy() + expect(await locator.textContent()).toContain('Layout table') + }) - test('should handle the get* methods', async ({queries: {getByTestId}}) => { - const locator = getByTestId('testid-text-input') + test('should handle regex matching', async ({queries: {queryByText}}) => { + const locator = queryByText(/HeLlO h(1|7)/i) - expect(await locator.evaluate(el => el.outerHTML)).toMatch( - ``, - ) - }) + expect(locator).toBeTruthy() + expect(await locator.textContent()).toEqual('Hello h1') + }) - test('handles page navigations', async ({queries: {getByText}, page}) => { - await page.goto(`file://${path.join(__dirname, '../fixtures/page.html')}`) + test('should handle the get* methods', async ({queries: {getByTestId}}) => { + const locator = getByTestId('testid-text-input') - const locator = getByText('Hello h1') + expect(await locator.evaluate(el => el.outerHTML)).toMatch( + ``, + ) + }) - expect(await locator.textContent()).toEqual('Hello h1') - }) + test('handles page navigations', async ({queries: {getByText}, page}) => { + await page.goto(`file://${path.join(__dirname, '../fixtures/page.html')}`) - test('should handle the get* method failures', async ({queries}) => { - const {getByTitle} = queries - // Use the scoped element so the pretty HTML snapshot is smaller + const locator = getByText('Hello h1') - await expect(async () => getByTitle('missing').textContent()).rejects.toThrow() - }) + expect(await locator.textContent()).toEqual('Hello h1') + }) - test('should handle the LabelText methods', async ({queries}) => { - const {getByLabelText} = queries - const locator = getByLabelText('Label A') + test('should handle the get* method failures', async ({queries}) => { + const {getByTitle} = queries + // Use the scoped element so the pretty HTML snapshot is smaller - /* istanbul ignore next */ - expect(await locator.evaluate(el => el.outerHTML)).toMatch( - ``, - ) - }) + await expect(async () => getByTitle('missing').textContent()).rejects.toThrow() + }) - test('should handle the queryAll* methods', async ({queries}) => { - const {queryAllByText} = queries - const locator = queryAllByText(/Hello/) + test('should handle the LabelText methods', async ({queries}) => { + const {getByLabelText} = queries + const locator = getByLabelText('Label A') - expect(await locator.count()).toEqual(3) + /* istanbul ignore next */ + expect(await locator.evaluate(el => el.outerHTML)).toMatch( + ``, + ) + }) - const text = await Promise.all([ - locator.nth(0).textContent(), - locator.nth(1).textContent(), - locator.nth(2).textContent(), - ]) + test('should handle the queryAll* methods', async ({queries}) => { + const {queryAllByText} = queries + const locator = queryAllByText(/Hello/) - expect(text).toEqual(['Hello h1', 'Hello h2', 'Hello h3']) - }) + expect(await locator.count()).toEqual(3) - test('should handle the queryAll* methods with a selector', async ({queries}) => { - const {queryAllByText} = queries - const locator = queryAllByText(/Hello/, {selector: 'h2'}) + const text = await Promise.all([ + locator.nth(0).textContent(), + locator.nth(1).textContent(), + locator.nth(2).textContent(), + ]) - expect(await locator.count()).toEqual(1) + expect(text).toEqual(['Hello h1', 'Hello h2', 'Hello h3']) + }) - expect(await locator.textContent()).toEqual('Hello h2') - }) + test('should handle the queryAll* methods with a selector', async ({queries}) => { + const {queryAllByText} = queries + const locator = queryAllByText(/Hello/, {selector: 'h2'}) - test('should handle the getBy* methods with a selector', async ({queries}) => { - const {getByText} = queries - const locator = getByText(/Hello/, {selector: 'h2'}) + expect(await locator.count()).toEqual(1) - expect(await locator.textContent()).toEqual('Hello h2') - }) + expect(await locator.textContent()).toEqual('Hello h2') + }) - test('should handle the getBy* methods with a regex name', async ({queries}) => { - const {getByRole} = queries - const element = getByRole('button', {name: /getBy.*Test/}) + test('should handle the getBy* methods with a selector', async ({queries}) => { + const {getByText} = queries + const locator = getByText(/Hello/, {selector: 'h2'}) - expect(await element.textContent()).toEqual('getByRole Test') - }) + expect(await locator.textContent()).toEqual('Hello h2') + }) - test('supports `hidden` option when querying by role', async ({queries: {queryAllByRole}}) => { - const elements = queryAllByRole('img') - const hiddenElements = queryAllByRole('img', {hidden: true}) + test('should handle the getBy* methods with a regex name', async ({queries}) => { + const {getByRole} = queries + const element = getByRole('button', {name: /getBy.*Test/}) - expect(await elements.count()).toEqual(1) - expect(await hiddenElements.count()).toEqual(2) - }) + expect(await element.textContent()).toEqual('getByRole Test') + }) - test.describe('querying by role with `level` option', () => { - test('retrieves the correct elements when querying all by role', async ({ - queries: {queryAllByRole}, - }) => { - const locator = queryAllByRole('heading') - const levelOneLocator = queryAllByRole('heading', {level: 3}) + test('supports `hidden` option when querying by role', async ({queries: {queryAllByRole}}) => { + const elements = queryAllByRole('img') + const hiddenElements = queryAllByRole('img', {hidden: true}) - expect(await locator.count()).toEqual(3) - expect(await levelOneLocator.count()).toEqual(1) + expect(await elements.count()).toEqual(1) + expect(await hiddenElements.count()).toEqual(2) }) - test('does not throw when querying for a specific element', async ({queries: {getByRole}}) => { - await expect(getByRole('heading', {level: 3}).textContent()).resolves.not.toThrow() + test.describe('querying by role with `level` option', () => { + test('retrieves the correct elements when querying all by role', async ({ + queries: {queryAllByRole}, + }) => { + const locator = queryAllByRole('heading') + const levelOneLocator = queryAllByRole('heading', {level: 3}) + + expect(await locator.count()).toEqual(3) + expect(await levelOneLocator.count()).toEqual(1) + }) + + test('does not throw when querying for a specific element', async ({ + queries: {getByRole}, + }) => { + await expect(getByRole('heading', {level: 3}).textContent()).resolves.not.toThrow() + }) }) - }) - test('scopes to container with `within`', async ({queries: {queryByRole}}) => { - const form = queryByRole('form', {name: 'User'}) + test('scopes to container with `within`', async ({queries: {queryByRole}}) => { + const form = queryByRole('form', {name: 'User'}) - const {queryByLabelText} = within(form) + const {queryByLabelText} = within(form) - const outerLocator = queryByLabelText('Name') - const innerLocator = queryByLabelText('Username') + const outerLocator = queryByLabelText('Name') + const innerLocator = queryByLabelText('Username') - expect(await outerLocator.count()).toBe(0) - expect(await innerLocator.count()).toBe(1) - }) + expect(await outerLocator.count()).toBe(0) + expect(await innerLocator.count()).toBe(1) + }) - test.describe('configuration', () => { - test.describe('custom data-testeid', () => { - test.use({testIdAttribute: 'data-id'}) + test.describe('configuration', () => { + test.describe('custom data-testid', () => { + test.use({testIdAttribute: 'data-id'}) - test('supports custom data-testid attribute name', async ({queries}) => { - const locator = queries.getByTestId('second-level-header') + test('supports custom data-testid attribute name', async ({queries}) => { + const locator = queries.getByTestId('second-level-header') - expect(await locator.textContent()).toEqual('Hello h2') + expect(await locator.textContent()).toEqual('Hello h2') + }) }) - }) - test.describe('nested configuration', () => { - test.use({testIdAttribute: 'data-new-id'}) + test.describe('nested configuration', () => { + test.use({testIdAttribute: 'data-new-id'}) - test('supports nested data-testid attribute names', async ({queries}) => { - const locator = queries.getByTestId('first-level-header') + test('supports nested data-testid attribute names', async ({queries}) => { + const locator = queries.getByTestId('first-level-header') - expect(await locator.textContent()).toEqual('Hello h1') + expect(await locator.textContent()).toEqual('Hello h1') + }) }) }) })