diff --git a/.eslintrc.js b/.eslintrc.js
index ca50012..65e8203 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -28,5 +28,12 @@ module.exports = {
'jest/no-done-callback': 'off',
},
},
+ {
+ files: ['lib/fixture/**/*.+(js|ts)'],
+ rules: {
+ 'no-empty-pattern': 'off',
+ 'no-underscore-dangle': ['error', {allow: ['__testingLibraryReviver']}],
+ },
+ },
],
}
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 3eac2fe..6050de1 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -13,12 +13,16 @@ on:
jobs:
build:
- name: Build + Test + Release / Node ${{ matrix.node }}
+ name: Build + Test + Release / Node ${{ matrix.node }} / playwright@${{ matrix.playwright }}
runs-on: ubuntu-latest
strategy:
matrix:
node: ['12', '14', '16']
- playwright: ['1.12.0', 'latest']
+ # TODO: technically we still support down to 1.12 but `locator.waitFor`
+ # was introduced in 1.16 so anything earlier blows up type-checking.
+ # This minimum will be bumped in the next breaking release that will be
+ # entirely built around the `Locator` APIs, so update this then.
+ playwright: ['1.16.0', 'latest']
steps:
- name: Checkout
@@ -32,7 +36,7 @@ jobs:
- name: Update to npm 7
run: npm i -g npm@7 --registry=https://registry.npmjs.org
- - uses: actions/cache@v3.0.1
+ - uses: actions/cache@v3.0.8
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
@@ -47,11 +51,22 @@ jobs:
npm install playwright@${{ matrix.playwright }}
npm install @playwright/test@${{ matrix.playwright }}
- - name: Check types, run lint + tests
+ - name: Check types
+ run: npm run test:types
+
+ - name: Run lint + tests
+ if: ${{ matrix.playwright == 'latest' }}
+ run: |
+ npm why playwright
+ npm why @playwright/test
+ npm run test
+
+ - name: Run lint + tests
+ if: ${{ matrix.playwright != 'latest' }}
run: |
npm why playwright
npm why @playwright/test
- npm run validate
+ npm run test:legacy
# Only release on Node 14
diff --git a/.node-version b/.node-version
index 31102b2..2a4e4ab 100644
--- a/.node-version
+++ b/.node-version
@@ -1 +1 @@
-14.18.1
+16.17.0
diff --git a/README.md b/README.md
index 50d6adf..e76a97f 100644
--- a/README.md
+++ b/README.md
@@ -22,103 +22,271 @@
-## ✨ Features
+## 🎛 Features
-All of your favorite user-centric querying functions from **@testing-library/react** and **@testing-library/dom** available from Playwright!
+All of your favorite user-centric querying functions from **@testing-library/react** and **@testing-library/dom** available from within Playwright!
-- Playwright Test [fixture](https://playwright.dev/docs/test-fixtures) — **`@playwright-testing-library/test/fixture`** or...
-- Standalone queries — **`playwright-testing-library`**/**`@playwright-testing-library/test`**
-- Asynchronous assertion helper (via **[wait-for-expect](https://github.com/TheBrainFamily/wait-for-expect)**)
+- Playwright Test [fixture](https://playwright.dev/docs/test-fixtures) for **@playwright/test** via **@playwright-testing-library/test**
+ - ✨ **New** — `Locator` queries fixture (`locatorFixtures`) [↓](#playwright-test-locator-fixture)
+ - `ElementHandle` queries fixture (`fixtures`) [↓](#legacy-playwright-test-fixture)
+- Standalone queries for **playwright** via **playwright-testing-library**
+ - `ElementHandle` queries (`getDocument` + `queries`) [↓](#standalone-playwright-queries)
+ - Asynchronous `waitFor` assertion helper (via **[wait-for-expect](https://github.com/TheBrainFamily/wait-for-expect)**)
-## 🌱 Getting Started
-
-### 1. Install
+## 🌱 Installation
```bash
-# For use with Playwright
+# For use with Playwright Test (@playwright/test)
+npm install --save-dev @playwright-testing-library/test
+
+# For use with Playwright (playwright)
npm install --save-dev playwright-testing-library
+```
-# For use with Playwright Test
-npm install --save-dev @playwright-testing-library/test
+## 📝 Usage
+
+There are currently a few different ways to use Playwright Testing Library, depending, however using the `Locator` queries fixture with Playwright Test (**@playwright/test**) is the recommended approach.
+
+> ⚠️ The `ElementHandle` query APIs were created before Playwright introduced its `Locator` API and will be replaced in the next major version of Playwright Testing Library. If you can't use **@playwright/test** at the moment, you'll need to use the `ElementHandle` query API, but a migration path will be provided when we switch to the new `Locator` APIs.
+
+### Playwright Test Fixture
+
+Using the `Locator` Playwright Test (**@playwright/test**) fixture with **@playwright-testing-library/test**.
+
+#### Setup
+
+```ts
+import {test as base} from '@playwright/test'
+import {
+ locatorFixtures as fixtures,
+ LocatorFixtures as TestingLibraryFixtures,
+} from '@playwright-testing-library/test/fixture'
+
+const test = base.extend(fixtures)
+
+const {expect} = test
+
+test('my form', async ({screen, within}) => {
+ // Screen provides `Locator` queries scoped to current Playwright `Page`
+ const formLocator = screen.getByTestId('my-form')
+
+ // Scope queries to `Locator` with `within`
+ // (note that this is a fixture from `test`, not the `within` import)
+ const emailInputLocator = within(formLocator).getByLabelText('Email')
+
+ // Interact via `Locator` API 🥳
+ await emailInputLocator.fill('email@playwright.dev')
+ await emailInputLocator.press('Enter')
+
+ // Screen also provides Playwright's `Page` API
+ screen.goto('/account')
+
+ const emailLocator = screen.getByRole('heading', {level: 2})
+
+ // Assert via `Locator` APIs 🎉
+ await expect(emailLocator).toHaveText('email@playwright.dev')
+})
```
-or
+#### Configuration
-```bash
-# For use with Playwright
-yarn add --dev playwright-testing-library
+The `Locator` query API is configured using Playwright's `use` API. See Playwright's documentation for [global](https://playwright.dev/docs/api/class-testconfig#test-config-use), [project](https://playwright.dev/docs/api/class-testproject#test-project-use), and [test](https://playwright.dev/docs/api/class-test#test-use).
+
+##### Global
+
+Configuring Testing Library globally in `playwright.config.ts`
+
+```ts
+import type {PlaywrightTestConfig} from '@playwright/test'
+
+const config: PlaywrightTestConfig = {
+ use: {
+ // These are the defaults
+ testIdAttribute: 'data-testid',
+ asyncUtilTimeout: 1000,
+ asyncUtilExpectedState: 'visible',
+ },
+}
-# For use with Playwright Test
-yarn add --dev @playwright-testing-library/test
+export default config
```
-### 2a. Use _Playwright Test [fixture](https://playwright.dev/docs/test-fixtures)_
+##### Local
+
+Scoping Testing Library configuration to test suites or `describe` blocks
```ts
-import {test as baseTest} from '@playwright/test'
+import {test as base} from '@playwright/test'
+import {
+ locatorFixtures as fixtures,
+ LocatorFixtures as TestingLibraryFixtures,
+} from '@playwright-testing-library/test/fixture'
+
+const test = base.extend(fixtures)
+
+const {describe, expect, use} = test
+
+// Entire test suite
+use({testIdAttribute: 'data-custom-test-id'})
+
+describe(() => {
+ // Specific block
+ use({
+ testIdAttribute: 'some-other-test-id',
+ asyncUtilsTimeout: 5000,
+ asyncUtilExpectedState: 'attached',
+ })
+
+ test('my form', async ({screen}) => {
+ // ...
+ })
+})
+```
+
+### Legacy Playwright Test Fixture
+
+Using the `ElementHandle` Playwright Test (**@playwright/test**) fixture with **@playwright-testing-library/test**.
+
+> ⚠️ See note in [Usage](#-usage) as you should be using the `Locator` fixture if possible
+
+#### Setup
+
+```ts
+import {test as base} from '@playwright/test'
import {fixtures, within, TestingLibraryFixtures} from '@playwright-testing-library/test/fixture'
-// As only fixture
-const test = baseTest.extend(fixtures)
+const test = base.extend(fixtures)
-// Alternatively, with other fixtures
-interface Fixtures extends TestingLibraryFixtures {
- // ... additional fixture types
-}
+const {expect} = test
+
+test('my form', async ({page, queries}) => {
+ // Query methods are available in `test` blocks
+ const formHandle = await queries.getByTestId('my-form')
+
+ // Scope queries to an `ElementHandle` with `within`
+ const emailInputHandle = await within(formHandle).getByLabelText('Email')
-const test = baseTest.extend({
- ...fixtures,
- // ... additional fixtures
+ // Interact via `ElementHandle` API
+ await emailInputHandle.fill('email@playwright.dev')
+ await emailInputHandle.press('Enter')
+
+ page.goto('/account')
+
+ const emailHandle = queries.getByRole('heading', {level: 2})
+
+ // Assert via `ElementHandle` APIs
+ expect(await emailHandle.textContent()).toEqual('email@playwright.dev')
})
+```
-const {expect} = test
+#### Configuration
+
+```ts
+import {test as base} from '@playwright/test'
+import {
+ configure,
+ fixtures,
+ within,
+ TestingLibraryFixtures,
+} from '@playwright-testing-library/test/fixture'
-// Query methods are available in `test` blocks
-test('my form', async ({queries: {getByTestId}}) => {
- const $form = await getByTestId('my-form')
+const test = base.extend(fixtures)
- // Scope queries with `within`
- const {getByLabelText} = within($form)
+const {beforeEach, describe, expect} = test
- const $email = await getByLabelText('Email')
+// Global (these are the defaults)
+configure({asyncUtilTimeout: 1000, testIdAttribute: 'data-testid'})
- // Interact with Playwright like usual
- await $email.type('playwright@example.com')
+// Specific block
+describe('my page', () => {
+ beforeEach(() => configure({asyncUtilTimeout: 5000, testIdAttribute: 'data-custom-test-id'}))
- // ...
+ afterEach(() => configure({}))
+
+ test('my form', async ({page, queries}) => {
+ // ...
+ })
})
```
-### 2b. Use _standalone queries_
+### Standalone Playwright Queries
+
+Using the `ElementHandle` queries with Playwright (**playwright**) and **playwright-testing-library**.
-```js
-const {webkit} = require('playwright') // or 'firefox' or 'chromium'
-const {getDocument, queries} = require('playwright-testing-library')
+> ⚠️ See note in [Usage](#-usage) as you should be using **@playwright/test** with the `Locator` fixture if possible. The `Locator` queries will be made available for standalone **playwright** in the next major release.
-const {getByTestId, getByLabelText} = queries
+```ts
+import {beforeAll, expect, jest, test} from '@jest/globals'
+import {webkit} from 'playwright' // or 'firefox' or 'chromium'
+import {getDocument, queries, within} from 'playwright-testing-library'
+
+let browser: playwright.Browser
+let page: playwright.Page
+
+beforeAll(() => {
+ const browser = await webkit.launch()
+ const page = await browser.newPage()
+})
-const browser = await webkit.launch()
-const page = await browser.newPage()
+test('my form', () => {
+ // Get `ElementHandle` for document from `Page`
+ const documentHandle = await getDocument(page)
-// Grab ElementHandle for document
-const $document = await getDocument(page)
+ // Global query methods take document handle as the first parameter
+ const formHandle = await queries.getByTestId(documentHandle, 'my-form')
-// Your favorite query methods are available
-const $form = await getByTestId($document, 'my-form')
+ // Scope queries to an `ElementHandle` with `within`
+ const emailInputHandle = await within(formHandle).getByLabelText('Email')
-// Returned elements are ElementHandles too!
-const $email = await getByLabelText($form, 'Email')
+ // Interact via `ElementHandle` API
+ await emailInputHandle.fill('email@playwright.dev')
+ await emailInputHandle.press('Enter')
-// Interact with playwright like usual
-await $email.type('playwright@example.com')
+ page.goto('/account')
-// ...
+ const accountHandle = getDocument(page)
+ const emailHandle = queries.getByRole(accountHandle, 'heading', {level: 2})
+
+ // Assert via `ElementHandle` APIs
+ expect(await emailHandle.textContent()).toEqual('email@playwright.dev')
+})
+```
+
+#### Configuration
+
+```ts
+import {beforeEach, afterEach, expect, jest, test} from '@jest/globals'
+import {configure, getDocument, queries, within} from 'playwright-testing-library'
+
+// Global (these are the defaults)
+configure({asyncUtilTimeout: 1000, testIdAttribute: 'data-testid'})
+
+// Specific block
+describe('my page', () => {
+ beforeEach(() => configure({asyncUtilTimeout: 5000, testIdAttribute: 'data-custom-test-id'}))
+
+ afterEach(() => configure({}))
+
+ test('my form', async ({page, queries}) => {
+ // ...
+ })
+})
```
## 🔌 API
+### Testing Library
+
+All queries from **[@testing-library/dom](https://github.com/testing-library/dom-testing-library#usage)** are supported.
+
+> 📝 The **`find*`** queries for the `Locator` queries return `Promise` which resolves when the element is found before the timeout specified via `asyncUtilTimeout`
+
+### Additional
+
Unique methods, not part of **@testing-library/dom**
+> ⚠️ These only apply to the `ElementHandle` queries
+
- Get an `ElementHandle` for the document
```ts
@@ -135,72 +303,23 @@ Unique methods, not part of **@testing-library/dom**
): Promise<{}>
```
----
-
-The **[@testing-library/dom](https://github.com/testing-library/dom-testing-library#usage)** — All **`get*`** and **`query*`** methods are supported.
-
-- `getQueriesForElement(handle: ElementHandle): ElementHandle & QueryUtils` - extend the input object with the query API and return it
-- `getNodeText(handle: ElementHandle): Promise` - get the text content of the element
-- `queries: QueryUtils` - the query subset of `@testing-library/dom` exports
- - `queryByPlaceholderText`
- - `queryAllByPlaceholderText`
- - `getByPlaceholderText`
- - `getAllByPlaceholderText`
- - `findByPlaceholderText`
- - `findAllByPlaceholderText`
- - `queryByText`
- - `queryAllByText`
- - `getByText`
- - `getAllByText`
- - `findByText`
- - `findAllByText`
- - `queryByLabelText`
- - `queryAllByLabelText`
- - `getByLabelText`
- - `getAllByLabelText`
- - `findByLabelText`
- - `findAllByLabelText`
- - `queryByAltText`
- - `queryAllByAltText`
- - `getByAltText`
- - `getAllByAltText`
- - `findByAltText`
- - `findAllByAltText`
- - `queryByTestId`
- - `queryAllByTestId`
- - `getByTestId`
- - `getAllByTestId`
- - `findByTestId`
- - `findAllByTestId`
- - `queryByTitle`
- - `queryAllByTitle`
- - `getByTitle`
- - `getAllByTitle`
- - `findByTitle`
- - `findAllByTitle`
- - `queryByDisplayValue`,
- - `queryAllByDisplayValue`,
- - `getByDisplayValue`,
- - `getAllByDisplayValue`,
- - `findByDisplayValue`,
- - `findAllByDisplayValue`,
-
## Known Limitations
-- Async utilities `waitForElement`, `waitForElementToBeRemoved` and `waitForDomChange` are not exposed. Consider using a `find*` query.
-- `fireEvent` method is not exposed, use Playwright's built-ins instead.
-- `expect` assertion extensions are not available.
+- Only `testIdAttribute` and `asyncUtilTimeout` are supported as configuration options
+- Async utilities `waitForElement`, `waitForElementToBeRemoved` and `waitForDomChange` are not exposed. Consider using a `find*` query or a Playwright built-in like [`Locator.waitFor()`](https://playwright.dev/docs/api/class-locator#locator-wait-for).
+- The `fireEvent` method is not exposed, use Playwright's built-ins instead.
+- Assertion extensions from [**jest-dom**](https://testing-library.com/docs/ecosystem-jest-dom/) are not compatible, use Playwright Test if possible.
+- The [`getNodeText()`](https://testing-library.com/docs/dom-testing-library/api-custom-queries/#getnodetext) function is not currently supported for `Locator`.
## Special Thanks
- [pptr-testing-library](https://github.com/testing-library/pptr-testing-library)
-- [@testing-library/dom](https://github.com/testing-library/dom-testing-library) of course!
+- [@testing-library/dom](https://github.com/testing-library/dom-testing-library)
## Related Playwright Test Utilities
- [jest-playwright](https://github.com/playwright-community/jest-playwright)
- [expect-playwright](https://github.com/playwright-community/expect-playwright)
-- Yours! Name TBD, PR welcome ;)
## LICENSE
diff --git a/lib/common.ts b/lib/common.ts
index e515a5a..09bcf7c 100644
--- a/lib/common.ts
+++ b/lib/common.ts
@@ -1,6 +1,24 @@
-import {Queries} from './typedefs'
+import {Config as TestingLibraryConfig, queries} from '@testing-library/dom'
-export const queryNames: Array = [
+export type Config = Pick
+
+export const configureTestingLibraryScript = (
+ script: string,
+ {testIdAttribute, asyncUtilTimeout}: Partial,
+) => {
+ const withTestId = testIdAttribute
+ ? script.replace(
+ /testIdAttribute: (['|"])data-testid(['|"])/g,
+ `testIdAttribute: $1${testIdAttribute}$2`,
+ )
+ : script
+
+ return asyncUtilTimeout
+ ? withTestId.replace(/asyncUtilTimeout: \d+/g, `asyncUtilTimeout: ${asyncUtilTimeout}`)
+ : withTestId
+}
+
+export const queryNames: Array = [
'queryByPlaceholderText',
'queryAllByPlaceholderText',
'getByPlaceholderText',
diff --git a/lib/fixture.ts b/lib/fixture/element-handle.ts
similarity index 50%
rename from lib/fixture.ts
rename to lib/fixture/element-handle.ts
index c3f6978..7bc12c1 100644
--- a/lib/fixture.ts
+++ b/lib/fixture/element-handle.ts
@@ -1,15 +1,10 @@
import type {PlaywrightTestArgs, TestFixture} from '@playwright/test'
-import {queryNames} from './common'
-import type {FixtureQueries as Queries} from './typedefs'
+import {getDocument, queries as unscopedQueries} from '..'
+import {queryNames} from '../common'
+import type {FixtureQueries as Queries} from '../typedefs'
-import {getDocument, queries as unscopedQueries} from '.'
-
-interface TestingLibraryFixtures {
- queries: Queries
-}
-
-const fixture: TestFixture = async ({page}, use) => {
+const queriesFixture: TestFixture = async ({page}, use) => {
const queries = {} as Queries
queryNames.forEach(name => {
@@ -27,8 +22,5 @@ const fixture: TestFixture = async ({page}, use) =>
await use(queries)
}
-const fixtures = {queries: fixture}
-
-export {configure} from '.'
-export {fixture, fixtures}
-export type {Queries, TestingLibraryFixtures}
+export {queriesFixture}
+export type {Queries}
diff --git a/lib/fixture/helpers.ts b/lib/fixture/helpers.ts
new file mode 100644
index 0000000..cd4fef4
--- /dev/null
+++ b/lib/fixture/helpers.ts
@@ -0,0 +1,17 @@
+const replacer = (_: string, value: unknown) => {
+ if (value instanceof RegExp) return `__REGEXP ${value.toString()}`
+
+ return value
+}
+
+const reviver = (_: string, value: string) => {
+ if (value.toString().includes('__REGEXP ')) {
+ const match = /\/(.*)\/(.*)?/.exec(value.split('__REGEXP ')[1])
+
+ return new RegExp(match![1], match![2] || '')
+ }
+
+ return value
+}
+
+export {replacer, reviver}
diff --git a/lib/fixture/index.ts b/lib/fixture/index.ts
new file mode 100644
index 0000000..e5e54fd
--- /dev/null
+++ b/lib/fixture/index.ts
@@ -0,0 +1,49 @@
+import {Fixtures} from '@playwright/test'
+
+import type {Queries as ElementHandleQueries} from './element-handle'
+import {queriesFixture as elementHandleQueriesFixture} from './element-handle'
+import {
+ Queries as LocatorQueries,
+ installTestingLibraryFixture,
+ queriesFixture as locatorQueriesFixture,
+ options,
+ queriesFor,
+ registerSelectorsFixture,
+ screenFixture,
+ withinFixture,
+} from './locator'
+import type {Config, Screen} from './types'
+import {Within} from './types'
+
+const elementHandleFixtures: Fixtures = {queries: elementHandleQueriesFixture}
+const locatorFixtures: Fixtures = {
+ queries: locatorQueriesFixture,
+ screen: screenFixture,
+ within: withinFixture,
+ registerSelectors: registerSelectorsFixture,
+ installTestingLibrary: installTestingLibraryFixture,
+ ...options,
+}
+
+interface ElementHandleFixtures {
+ queries: ElementHandleQueries
+}
+
+interface LocatorFixtures extends Partial {
+ queries: LocatorQueries
+ screen: Screen
+ within: Within
+ registerSelectors: void
+ installTestingLibrary: void
+}
+
+export {configure} from '..'
+
+export type {ElementHandleFixtures as TestingLibraryFixtures, LocatorFixtures}
+export {
+ locatorFixtures,
+ locatorQueriesFixture,
+ elementHandleQueriesFixture as fixture,
+ elementHandleFixtures as fixtures,
+ queriesFor,
+}
diff --git a/lib/fixture/locator/fixtures.ts b/lib/fixture/locator/fixtures.ts
new file mode 100644
index 0000000..701d055
--- /dev/null
+++ b/lib/fixture/locator/fixtures.ts
@@ -0,0 +1,138 @@
+import type {Locator, PlaywrightTestArgs, TestFixture} from '@playwright/test'
+import {Page, selectors} from '@playwright/test'
+
+import type {
+ Config,
+ LocatorQueries as Queries,
+ Screen,
+ SelectorEngine,
+ SynchronousQuery,
+ Within,
+ WithinReturn,
+} from '../types'
+
+import {buildTestingLibraryScript, queryToSelector} from './helpers'
+import {isAllQuery, queriesFor, screenFor, synchronousQueryNames} from './queries'
+
+type TestArguments = PlaywrightTestArgs & Config
+
+const defaultConfig: Config = {
+ asyncUtilExpectedState: 'visible',
+ asyncUtilTimeout: 1000,
+ testIdAttribute: 'data-testid',
+}
+
+const options = Object.fromEntries(
+ Object.entries(defaultConfig).map(([key, value]) => [key, [value, {option: true}] as const]),
+)
+
+const queriesFixture: TestFixture = async (
+ {page, asyncUtilExpectedState, asyncUtilTimeout},
+ use,
+) => use(queriesFor(page, {asyncUtilExpectedState, asyncUtilTimeout}))
+
+const screenFixture: TestFixture = async (
+ {page, asyncUtilExpectedState, asyncUtilTimeout},
+ use,
+) => {
+ const {proxy, revoke} = screenFor(page, {asyncUtilExpectedState, asyncUtilTimeout})
+
+ await use(proxy)
+
+ revoke()
+}
+
+const withinFixture: TestFixture = async (
+ {asyncUtilExpectedState, asyncUtilTimeout},
+ use,
+) =>
+ use((root: Root) =>
+ 'goto' in root
+ ? screenFor(root, {asyncUtilExpectedState, asyncUtilTimeout}).proxy
+ : (queriesFor(root, {asyncUtilExpectedState, asyncUtilTimeout}) as WithinReturn),
+ )
+
+declare const queryName: SynchronousQuery
+
+const engine: () => SelectorEngine = () => ({
+ query(root, selector) {
+ const args = JSON.parse(selector, window.__testingLibraryReviver) as unknown as Parameters<
+ Queries[typeof queryName]
+ >
+
+ if (isAllQuery(queryName))
+ throw new Error(
+ `PlaywrightTestingLibrary: the plural '${queryName}' was used to create this Locator`,
+ )
+
+ // @ts-expect-error
+ const result = window.TestingLibraryDom[queryName](root, ...args)
+
+ return result
+ },
+ queryAll(root, selector) {
+ const testingLibrary = window.TestingLibraryDom
+ const args = JSON.parse(selector, window.__testingLibraryReviver) as unknown as Parameters<
+ Queries[typeof queryName]
+ >
+
+ // @ts-expect-error
+ const result = testingLibrary[queryName](root, ...args)
+
+ if (!result) return []
+
+ return Array.isArray(result) ? result : [result]
+ },
+})
+
+const registerSelectorsFixture: [
+ TestFixture,
+ {scope: 'worker'; auto?: boolean},
+] = [
+ async ({}, use) => {
+ try {
+ await Promise.all(
+ synchronousQueryNames.map(async name =>
+ selectors.register(
+ queryToSelector(name),
+ `(${engine.toString().replace(/queryName/g, `"${name}"`)})()`,
+ ),
+ ),
+ )
+ } catch (error) {
+ // eslint-disable-next-line no-console
+ console.error(
+ 'PlaywrightTestingLibrary: failed to register Testing Library functions\n',
+ error,
+ )
+ }
+ await use()
+ },
+ {scope: 'worker', auto: true},
+]
+
+const installTestingLibraryFixture: [
+ TestFixture,
+ {scope: 'test'; auto?: boolean},
+] = [
+ async ({context, asyncUtilExpectedState, asyncUtilTimeout, testIdAttribute}, use) => {
+ await context.addInitScript(
+ await buildTestingLibraryScript({
+ config: {asyncUtilExpectedState, asyncUtilTimeout, testIdAttribute},
+ }),
+ )
+
+ await use()
+ },
+ {scope: 'test', auto: true},
+]
+
+export {
+ installTestingLibraryFixture,
+ options,
+ queriesFixture,
+ registerSelectorsFixture,
+ screenFixture,
+ withinFixture,
+}
+export type {Queries}
diff --git a/lib/fixture/locator/helpers.ts b/lib/fixture/locator/helpers.ts
new file mode 100644
index 0000000..5e4914a
--- /dev/null
+++ b/lib/fixture/locator/helpers.ts
@@ -0,0 +1,50 @@
+import {promises as fs} from 'fs'
+
+import {configureTestingLibraryScript} from '../../common'
+import {reviver} from '../helpers'
+import type {Config, Selector, SynchronousQuery} from '../types'
+
+const queryToSelector = (query: SynchronousQuery) =>
+ query.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase() as Selector
+
+const buildTestingLibraryScript = async ({config}: {config: Config}) => {
+ const testingLibraryDom = await fs.readFile(
+ require.resolve('@testing-library/dom/dist/@testing-library/dom.umd.js'),
+ 'utf8',
+ )
+
+ const configuredTestingLibraryDom = configureTestingLibraryScript(testingLibraryDom, config)
+
+ return `
+ ${configuredTestingLibraryDom}
+
+ window.__testingLibraryReviver = ${reviver.toString()};
+ `
+}
+
+/**
+ * Alternative version of `Array.prototype.includes` that allows testing for
+ * the existence of an item with a type that is a _superset_ of the type of the
+ * items in the array.
+ *
+ * This allows us to use it to check whether an item of type `string` exists in
+ * an array of string literals (e.g: `['foo', 'bar'] as const`) without TypeScript
+ * complaining. It will, however, throw a compiler error if you try to pass an item
+ * of type `number`.
+ *
+ * @example
+ * const things = ['foo', 'bar'] as const;
+ *
+ * // error
+ * const hasThing = (t: string) => things.includes(t);
+ *
+ * // compiles
+ * const hasThing = (t: string) => includes(things, t);
+ *
+ * @param array array to search
+ * @param item item to search for
+ */
+const includes = (array: ReadonlyArray, item: U): item is T =>
+ array.includes(item as T)
+
+export {buildTestingLibraryScript, includes, queryToSelector}
diff --git a/lib/fixture/locator/index.ts b/lib/fixture/locator/index.ts
new file mode 100644
index 0000000..c07e4ac
--- /dev/null
+++ b/lib/fixture/locator/index.ts
@@ -0,0 +1,10 @@
+export {
+ installTestingLibraryFixture,
+ options,
+ queriesFixture,
+ registerSelectorsFixture,
+ screenFixture,
+ withinFixture,
+} from './fixtures'
+export type {Queries} from './fixtures'
+export {queriesFor} from './queries'
diff --git a/lib/fixture/locator/queries.ts b/lib/fixture/locator/queries.ts
new file mode 100644
index 0000000..a2fbeaf
--- /dev/null
+++ b/lib/fixture/locator/queries.ts
@@ -0,0 +1,122 @@
+import type {Locator, Page} from '@playwright/test'
+import {errors} from '@playwright/test'
+import {queries} from '@testing-library/dom'
+
+import {replacer} from '../helpers'
+import type {
+ AllQuery,
+ Config,
+ FindQuery,
+ GetQuery,
+ LocatorQueries as Queries,
+ Query,
+ QueryQuery,
+ Screen,
+ SynchronousQuery,
+} from '../types'
+
+import {includes, queryToSelector} from './helpers'
+
+const isAllQuery = (query: Query): query is AllQuery => query.includes('All')
+
+const isFindQuery = (query: Query): query is FindQuery => query.startsWith('find')
+const isNotFindQuery = (query: Query): query is Exclude =>
+ !query.startsWith('find')
+
+const allQueryNames = Object.keys(queries) as Query[]
+const synchronousQueryNames = allQueryNames.filter(isNotFindQuery)
+
+const findQueryToGetQuery = (query: FindQuery) => query.replace(/^find/, 'get') as GetQuery
+const findQueryToQueryQuery = (query: FindQuery) => query.replace(/^find/, 'query') as QueryQuery
+
+const createFindQuery =
+ (
+ pageOrLocator: Page | Locator,
+ query: FindQuery,
+ {asyncUtilTimeout, asyncUtilExpectedState}: Partial = {},
+ ) =>
+ async (...[id, options, waitForElementOptions]: Parameters) => {
+ const synchronousOptions = ([id, options] as const).filter(Boolean)
+
+ const locator = pageOrLocator.locator(
+ `${queryToSelector(findQueryToQueryQuery(query))}=${JSON.stringify(
+ synchronousOptions,
+ replacer,
+ )}`,
+ )
+
+ const {state: expectedState = asyncUtilExpectedState, timeout = asyncUtilTimeout} =
+ waitForElementOptions ?? {}
+
+ try {
+ await locator.first().waitFor({state: expectedState, timeout})
+ } catch (error) {
+ // In the case of a `waitFor` timeout from Playwright, we want to
+ // surface the appropriate error from Testing Library, so run the
+ // query one more time as `get*` knowing that it will fail with the
+ // error that we want the user to see instead of the `TimeoutError`
+ if (error instanceof errors.TimeoutError) {
+ const timeoutLocator = pageOrLocator
+ .locator(
+ `${queryToSelector(findQueryToGetQuery(query))}=${JSON.stringify(
+ synchronousOptions,
+ replacer,
+ )}`,
+ )
+ .first()
+
+ // Handle case where element is attached, but hidden, and the expected
+ // state is set to `visible`. In this case, dereferencing the
+ // `Locator` instance won't throw a `get*` query error, so just
+ // surface the original Playwright timeout error
+ if (expectedState === 'visible' && !(await timeoutLocator.isVisible())) {
+ throw error
+ }
+
+ // In all other cases, dereferencing the `Locator` instance here should
+ // cause the above `get*` query to throw an error in Testing Library
+ return timeoutLocator.waitFor({state: expectedState, timeout})
+ }
+
+ throw error
+ }
+
+ return locator
+ }
+
+/**
+ * Given a `Page` or `Locator` instance, return an object of Testing Library
+ * query methods that return a `Locator` instance for the queried element
+ *
+ * @internal this API is not currently intended for public usage and may be
+ * removed or changed outside of semantic release versioning. If possible, you
+ * should use the `locatorFixtures` with **@playwright/test** instead.
+ * @see {@link locatorFixtures}
+ *
+ * @param pageOrLocator `Page` or `Locator` instance to use as the query root
+ * @param config Testing Library configuration to apply to queries
+ *
+ * @returns object containing scoped Testing Library query methods
+ */
+const queriesFor = (pageOrLocator: Page | Locator, config?: Partial) =>
+ allQueryNames.reduce(
+ (rest, query) => ({
+ ...rest,
+ [query]: isFindQuery(query)
+ ? createFindQuery(pageOrLocator, query, config)
+ : (...args: Parameters) =>
+ pageOrLocator.locator(`${queryToSelector(query)}=${JSON.stringify(args, replacer)}`),
+ }),
+ {} as Queries,
+ )
+
+const screenFor = (page: Page, config: Partial) =>
+ Proxy.revocable(page, {
+ get(target, property, receiver) {
+ return includes(allQueryNames, property)
+ ? queriesFor(page, config)[property]
+ : Reflect.get(target, property, receiver)
+ },
+ }) as {proxy: Screen; revoke: () => void}
+
+export {allQueryNames, isAllQuery, isNotFindQuery, queriesFor, screenFor, synchronousQueryNames}
diff --git a/lib/fixture/types.ts b/lib/fixture/types.ts
new file mode 100644
index 0000000..c367e4b
--- /dev/null
+++ b/lib/fixture/types.ts
@@ -0,0 +1,85 @@
+import {Locator, Page} from '@playwright/test'
+import type * as TestingLibraryDom from '@testing-library/dom'
+import {queries} from '@testing-library/dom'
+
+import type {Config as CommonConfig} from '../common'
+
+import {reviver} from './helpers'
+
+/**
+ * This type was copied across from Playwright
+ *
+ * @see {@link https://github.com/microsoft/playwright/blob/82ff85b106e31ffd7b3702aef260c9c460cfb10c/packages/playwright-core/src/client/types.ts#L108-L117}
+ */
+export type SelectorEngine = {
+ /**
+ * Returns the first element matching given selector in the root's subtree.
+ */
+ query(root: HTMLElement, selector: string): HTMLElement | null
+ /**
+ * Returns all elements matching given selector in the root's subtree.
+ */
+ queryAll(root: HTMLElement, selector: string): HTMLElement[]
+}
+
+type Queries = typeof queries
+type WaitForState = Exclude[0], undefined>['state']
+type AsyncUtilExpectedState = Extract
+
+type ConvertQuery = Query extends (
+ el: HTMLElement,
+ ...rest: infer Rest
+) => HTMLElement | (HTMLElement[] | null) | (HTMLElement | null)
+ ? (...args: Rest) => Locator
+ : Query extends (
+ el: HTMLElement,
+ id: infer Id,
+ options: infer Options,
+ waitForOptions: infer WaitForOptions,
+ ) => Promise
+ ? (
+ id: Id,
+ options?: Options,
+ waitForOptions?: WaitForOptions & {state?: AsyncUtilExpectedState},
+ ) => Promise
+ : never
+
+type KebabCase = S extends `${infer C}${infer T}`
+ ? T extends Uncapitalize
+ ? `${Uncapitalize}${KebabCase}`
+ : `${Uncapitalize}-${KebabCase}`
+ : S
+
+export type LocatorQueries = {[K in keyof Queries]: ConvertQuery}
+
+export type WithinReturn = Root extends Page ? Screen : LocatorQueries
+export type Screen = LocatorQueries & Page
+export type Within = (locator: Root) => WithinReturn
+
+export type Query = keyof Queries
+
+export type AllQuery = Extract
+export type FindQuery = Extract
+export type GetQuery = Extract
+export type QueryQuery = Extract
+export type SynchronousQuery = Exclude
+
+export type Selector = KebabCase
+
+export interface Config extends CommonConfig {
+ asyncUtilExpectedState: AsyncUtilExpectedState
+}
+export interface ConfigFn {
+ (existingConfig: Config): Partial
+}
+
+export type ConfigDelta = ConfigFn | Partial
+export type Configure = (configDelta: ConfigDelta) => void
+export type ConfigureLocator = (configDelta: ConfigDelta) => Config
+
+declare global {
+ interface Window {
+ TestingLibraryDom: typeof TestingLibraryDom
+ __testingLibraryReviver: typeof reviver
+ }
+}
diff --git a/lib/index.ts b/lib/index.ts
index bbd2725..45f444c 100644
--- a/lib/index.ts
+++ b/lib/index.ts
@@ -6,8 +6,8 @@ import * as path from 'path'
import {JSHandle, Page} from 'playwright'
import waitForExpect from 'wait-for-expect'
-import {queryNames} from './common'
-import {ConfigurationOptions, ElementHandle, Queries, ScopedQueries} from './typedefs'
+import {Config, configureTestingLibraryScript, queryNames} from './common'
+import {ElementHandle, Queries, ScopedQueries} from './typedefs'
const domLibraryAsString = readFileSync(
path.join(__dirname, '../dom-testing-library.js'),
@@ -176,26 +176,28 @@ export function wait(
export const waitFor = wait
-export function configure(options: Partial): void {
- if (!options) {
+/**
+ * Configuration API for legacy queries that return `ElementHandle` instances.
+ * Only `testIdAttribute` and `asyncUtilTimeout` are currently supported.
+
+ * @see {@link https://testing-library.com/docs/dom-testing-library/api-configuration}
+ *
+ * ⚠️ This API has no effect on the queries that return `Locator` instances. Use
+ * `test.use` instead to configure the `Locator` queries.
+ *
+ * @see {@link https://github.com/testing-library/playwright-testing-library/releases/tag/v4.4.0-beta.2}
+ *
+ * @param config
+ */
+export function configure(config: Partial): void {
+ if (!config) {
return
}
- const {testIdAttribute, asyncUtilTimeout} = options
-
- if (testIdAttribute) {
- delegateFnBodyToExecuteInPage = delegateFnBodyToExecuteInPageInitial.replace(
- /testIdAttribute: (['|"])data-testid(['|"])/g,
- `testIdAttribute: $1${testIdAttribute}$2`,
- )
- }
-
- if (asyncUtilTimeout) {
- delegateFnBodyToExecuteInPage = delegateFnBodyToExecuteInPageInitial.replace(
- /asyncUtilTimeout: \d+/g,
- `asyncUtilTimeout: ${asyncUtilTimeout}`,
- )
- }
+ delegateFnBodyToExecuteInPage = configureTestingLibraryScript(
+ delegateFnBodyToExecuteInPageInitial,
+ config,
+ )
}
export function getQueriesForElement(
diff --git a/lib/typedefs.ts b/lib/typedefs.ts
index 9fcc5c7..89a29cd 100644
--- a/lib/typedefs.ts
+++ b/lib/typedefs.ts
@@ -188,8 +188,3 @@ export interface Queries extends QueryMethods {
getQueriesForElement(): ScopedQueries
getNodeText(el: Element): Promise
}
-
-export interface ConfigurationOptions {
- testIdAttribute: string
- asyncUtilTimeout: number
-}
diff --git a/package-lock.json b/package-lock.json
index 454fcbb..7df5213 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,11 +17,11 @@
"@playwright/test": "^1.25.0",
"@rollup/plugin-commonjs": "^21.0.0",
"@rollup/plugin-node-resolve": "^13.0.5",
- "@rollup/plugin-replace": "^3.0.0",
+ "@rollup/plugin-replace": "^4.0.0",
"@types/jest": "^27.0.2",
"@types/jscodeshift": "^0.11.2",
"generate-export-aliases": "^1.1.0",
- "husky": "^7.0.2",
+ "husky": "^8.0.1",
"jscodeshift": "^0.13.0",
"npm-run-all": "^4.1.5",
"playwright": "^1.25.0",
@@ -2417,19 +2417,19 @@
}
},
"node_modules/@eslint/eslintrc": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz",
- "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==",
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz",
+ "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==",
"dev": true,
"dependencies": {
"ajv": "^6.12.4",
"debug": "^4.3.2",
- "espree": "^9.3.1",
- "globals": "^13.9.0",
+ "espree": "^9.3.2",
+ "globals": "^13.15.0",
"ignore": "^5.2.0",
"import-fresh": "^3.2.1",
"js-yaml": "^4.1.0",
- "minimatch": "^3.0.4",
+ "minimatch": "^3.1.2",
"strip-json-comments": "^3.1.1"
},
"engines": {
@@ -2437,9 +2437,9 @@
}
},
"node_modules/@eslint/eslintrc/node_modules/globals": {
- "version": "13.13.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz",
- "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==",
+ "version": "13.17.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz",
+ "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==",
"dev": true,
"dependencies": {
"type-fest": "^0.20.2"
@@ -2476,18 +2476,22 @@
}
},
"node_modules/@hover/javascript": {
- "version": "6.82.0",
- "resolved": "https://registry.npmjs.org/@hover/javascript/-/javascript-6.82.0.tgz",
- "integrity": "sha512-k/MahVWgV2NLFfD1IZuklB4a7DmCRITAbvzb4WpKfNMaDTqJ4EBbK6jxyvPUP9UySdpJWTSb3WhngIs0h5SIiQ==",
+ "version": "6.90.0",
+ "resolved": "https://registry.npmjs.org/@hover/javascript/-/javascript-6.90.0.tgz",
+ "integrity": "sha512-FOMyktsyOI9S2axKtqgCAX1usnoRr6VxVvaOLomPqeWXYjzYmH7fcFRtsQl3ObOdNmqhVBwxIa+Sf5PoeVvLmQ==",
"dev": true,
"dependencies": {
"@commitlint/cli": "^16.1.0",
"@commitlint/config-conventional": "^16.2.1",
"@commitlint/prompt": "^16.1.0",
"@types/jest": "^27.0.2",
+ "@types/lodash.has": "^4.5.6",
+ "@types/mkdirp": "^1.0.2",
"@types/node": ">=17.x",
+ "@types/rimraf": "^3.0.2",
+ "@types/which": "^2.0.1",
"@typescript-eslint/eslint-plugin": "^5.13.0",
- "@typescript-eslint/parser": "^5.13.0",
+ "@typescript-eslint/parser": "^5.27.0",
"arrify": "^2.0.1",
"commitizen": "^4.2.4",
"concurrently": "^7.0.0",
@@ -2495,19 +2499,19 @@
"cross-env": "^7.0.3",
"cross-spawn": "^7.0.1",
"doctoc": "^2.1.0",
- "eslint": "^8.8.0",
+ "eslint": "^8.16.0",
"eslint-config-airbnb": "19.0.0",
- "eslint-config-airbnb-typescript": "^16.1.0",
- "eslint-config-prettier": "^8.3.0",
+ "eslint-config-airbnb-typescript": "^17.0.0",
+ "eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jest": "^26.1.1",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.0.0",
- "eslint-plugin-react": "^7.27.0",
+ "eslint-plugin-react": "^7.30.0",
"eslint-plugin-react-hooks": "^4.3.0",
- "glob": "^7.2.0",
+ "glob": "^8.0.3",
"is-ci": "^3.0.1",
- "jest": "^27.4.7",
+ "jest": "^27.5.1",
"jest-github-actions-reporter": "^1.0.3",
"jest-watch-typeahead": "^1.0.0",
"lint-staged": "^12.3.4",
@@ -2517,10 +2521,10 @@
"read-pkg-up": "^7.0.1",
"rimraf": "^3.0.2",
"ts-jest": "^27.1.3",
- "tslib": "^2.3.1",
+ "tslib": "^2.4.0",
"typescript": "^4",
"which": "^2.0.2",
- "yargs-parser": "^21.0.0"
+ "yargs-parser": "^21.0.1"
},
"bin": {
"hover-scripts": "dist/index.js"
@@ -2531,10 +2535,50 @@
"yarn": ">=1"
}
},
+ "node_modules/@hover/javascript/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@hover/javascript/node_modules/glob": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz",
+ "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@hover/javascript/node_modules/minimatch": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
+ "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/@humanwhocodes/config-array": {
- "version": "0.9.5",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz",
- "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==",
+ "version": "0.10.4",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz",
+ "integrity": "sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==",
"dev": true,
"dependencies": {
"@humanwhocodes/object-schema": "^1.2.1",
@@ -2545,6 +2589,16 @@
"node": ">=10.10.0"
}
},
+ "node_modules/@humanwhocodes/gitignore-to-minimatch": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz",
+ "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
"node_modules/@humanwhocodes/object-schema": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
@@ -3508,15 +3562,15 @@
}
},
"node_modules/@rollup/plugin-node-resolve": {
- "version": "13.1.3",
- "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.1.3.tgz",
- "integrity": "sha512-BdxNk+LtmElRo5d06MGY4zoepyrXX1tkzX2hrnPEZ53k78GuOMWLqmJDGIIOPwVRIFZrLQOo+Yr6KtCuLIA0AQ==",
+ "version": "13.3.0",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.3.0.tgz",
+ "integrity": "sha512-Lus8rbUo1eEcnS4yTFKLZrVumLPY+YayBdWXgFSHYhTT2iJbMhoaaBL3xl5NCdeRytErGr8tZ0L71BMRmnlwSw==",
"dev": true,
"dependencies": {
"@rollup/pluginutils": "^3.1.0",
"@types/resolve": "1.17.1",
- "builtin-modules": "^3.1.0",
"deepmerge": "^4.2.2",
+ "is-builtin-module": "^3.1.0",
"is-module": "^1.0.0",
"resolve": "^1.19.0"
},
@@ -3528,9 +3582,9 @@
}
},
"node_modules/@rollup/plugin-replace": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-3.1.0.tgz",
- "integrity": "sha512-pA3XRUrSKybVYqmH5TqWNZpGxF+VV+1GrYchKgCNIj2vsSOX7CVm2RCtx8p2nrC7xvkziYyK+lSi74T93MU3YA==",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-4.0.0.tgz",
+ "integrity": "sha512-+rumQFiaNac9y64OHtkHGmdjm7us9bo1PlbgQfdihQtuNxzjpaB064HbRnewUOggLQxVCCyINfStkgmBeQpv1g==",
"dev": true,
"dependencies": {
"@rollup/pluginutils": "^3.1.0",
@@ -3769,6 +3823,16 @@
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
"dev": true
},
+ "node_modules/@types/glob": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==",
+ "dev": true,
+ "dependencies": {
+ "@types/minimatch": "*",
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/graceful-fs": {
"version": "4.1.5",
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz",
@@ -3843,9 +3907,9 @@
"dev": true
},
"node_modules/@types/jscodeshift": {
- "version": "0.11.3",
- "resolved": "https://registry.npmjs.org/@types/jscodeshift/-/jscodeshift-0.11.3.tgz",
- "integrity": "sha512-pM0JD9kWVDH9DQp5Y6td16924V3MwZHei8P3cTeuFhXpzpk0K+iWraBZz8wF61QkFs9fZeAQNX0q8SG0+TFm2w==",
+ "version": "0.11.5",
+ "resolved": "https://registry.npmjs.org/@types/jscodeshift/-/jscodeshift-0.11.5.tgz",
+ "integrity": "sha512-7JV0qdblTeWFigevmwFUgROXX395F+MQx6v0YqPn8Bx0B4Sng6alEejz9PENzgLYpG+zL0O4tGdBzc4gKZH8XA==",
"dev": true,
"dependencies": {
"ast-types": "^0.14.1",
@@ -3864,12 +3928,42 @@
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
"dev": true
},
+ "node_modules/@types/lodash": {
+ "version": "4.14.184",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.184.tgz",
+ "integrity": "sha512-RoZphVtHbxPZizt4IcILciSWiC6dcn+eZ8oX9IWEYfDMcocdd42f7NPI6fQj+6zI8y4E0L7gu2pcZKLGTRaV9Q==",
+ "dev": true
+ },
+ "node_modules/@types/lodash.has": {
+ "version": "4.5.7",
+ "resolved": "https://registry.npmjs.org/@types/lodash.has/-/lodash.has-4.5.7.tgz",
+ "integrity": "sha512-nfbAzRbsZBdzSAkL9iiLy4SQk89uuFcXBFwZ7pf6oZhBgPvNys8BY5Twp/w8XvZKGt1o6cAa85wX4QhqO3uQ7A==",
+ "dev": true,
+ "dependencies": {
+ "@types/lodash": "*"
+ }
+ },
+ "node_modules/@types/minimatch": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.0.tgz",
+ "integrity": "sha512-0RJHq5FqDWo17kdHe+SMDJLfxmLaqHbWnqZ6gNKzDvStUlrmx/eKIY17+ifLS1yybo7X86aUshQMlittDOVNnw==",
+ "dev": true
+ },
"node_modules/@types/minimist": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz",
"integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==",
"dev": true
},
+ "node_modules/@types/mkdirp": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-1.0.2.tgz",
+ "integrity": "sha512-o0K1tSO0Dx5X6xlU5F1D6625FawhC3dU3iqr25lluNv/+/QIVH8RLNEiVokgIZo+mz+87w/3Mkg/VvQS+J51fQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/node": {
"version": "17.0.23",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz",
@@ -3902,12 +3996,28 @@
"@types/node": "*"
}
},
+ "node_modules/@types/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-F3OznnSLAUxFrCEu/L5PY8+ny8DtcFRjx7fZZ9bycvXRi3KPTRS9HOitGZwvPg0juRhXFWIeKX58cnX5YqLohQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/glob": "*",
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/stack-utils": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.0.tgz",
"integrity": "sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==",
"dev": true
},
+ "node_modules/@types/which": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@types/which/-/which-2.0.1.tgz",
+ "integrity": "sha512-Jjakcv8Roqtio6w1gr0D7y6twbhx6gGgFGF5BLwajPpnOIOxFkakFhCq+LmyyeAz7BX6ULrjBOxdKaCDy+4+dQ==",
+ "dev": true
+ },
"node_modules/@types/yargs": {
"version": "15.0.14",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz",
@@ -3970,15 +4080,15 @@
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "5.19.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.19.0.tgz",
- "integrity": "sha512-yhktJjMCJX8BSBczh1F/uY8wGRYrBeyn84kH6oyqdIJwTGKmzX5Qiq49LRQ0Jh0LXnWijEziSo6BRqny8nqLVQ==",
+ "version": "5.35.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.35.1.tgz",
+ "integrity": "sha512-XL2TBTSrh3yWAsMYpKseBYTVpvudNf69rPOWXWVBI08My2JVT5jR66eTt4IgQFHA/giiKJW5dUD4x/ZviCKyGg==",
"dev": true,
"dependencies": {
- "@typescript-eslint/scope-manager": "5.19.0",
- "@typescript-eslint/types": "5.19.0",
- "@typescript-eslint/typescript-estree": "5.19.0",
- "debug": "^4.3.2"
+ "@typescript-eslint/scope-manager": "5.35.1",
+ "@typescript-eslint/types": "5.35.1",
+ "@typescript-eslint/typescript-estree": "5.35.1",
+ "debug": "^4.3.4"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -3996,6 +4106,95 @@
}
}
},
+ "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": {
+ "version": "5.35.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.35.1.tgz",
+ "integrity": "sha512-kCYRSAzIW9ByEIzmzGHE50NGAvAP3wFTaZevgWva7GpquDyFPFcmvVkFJGWJJktg/hLwmys/FZwqM9EKr2u24Q==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.35.1",
+ "@typescript-eslint/visitor-keys": "5.35.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": {
+ "version": "5.35.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.35.1.tgz",
+ "integrity": "sha512-FDaujtsH07VHzG0gQ6NDkVVhi1+rhq0qEvzHdJAQjysN+LHDCKDKCBRlZFFE0ec0jKxiv0hN63SNfExy0KrbQQ==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": {
+ "version": "5.35.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.35.1.tgz",
+ "integrity": "sha512-JUqE1+VRTGyoXlDWWjm6MdfpBYVq+hixytrv1oyjYIBEOZhBCwtpp5ZSvBt4wIA1MKWlnaC2UXl2XmYGC3BoQA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.35.1",
+ "@typescript-eslint/visitor-keys": "5.35.1",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": {
+ "version": "5.35.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.35.1.tgz",
+ "integrity": "sha512-cEB1DvBVo1bxbW/S5axbGPE6b7FIMAbo3w+AGq6zNDA7+NYJOIkKj/sInfTv4edxd4PxJSgdN4t6/pbvgA+n5g==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.35.1",
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/parser/node_modules/semver": {
+ "version": "7.3.7",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+ "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/@typescript-eslint/scope-manager": {
"version": "5.19.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.19.0.tgz",
@@ -4142,9 +4341,9 @@
"dev": true
},
"node_modules/acorn": {
- "version": "8.7.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
- "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
+ "version": "8.8.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
+ "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==",
"dev": true,
"bin": {
"acorn": "bin/acorn"
@@ -4342,14 +4541,14 @@
"dev": true
},
"node_modules/array-includes": {
- "version": "3.1.4",
- "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz",
- "integrity": "sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==",
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz",
+ "integrity": "sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
- "define-properties": "^1.1.3",
- "es-abstract": "^1.19.1",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5",
"get-intrinsic": "^1.1.1",
"is-string": "^1.0.7"
},
@@ -4857,12 +5056,15 @@
"dev": true
},
"node_modules/builtin-modules": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz",
- "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==",
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
+ "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==",
"dev": true,
"engines": {
"node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/cache-base": {
@@ -5984,15 +6186,19 @@
}
},
"node_modules/define-properties": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
- "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
+ "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
"dev": true,
"dependencies": {
- "object-keys": "^1.0.12"
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
},
"engines": {
"node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/define-property": {
@@ -6275,17 +6481,19 @@
}
},
"node_modules/es-abstract": {
- "version": "1.19.4",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.4.tgz",
- "integrity": "sha512-flV8e5g9/xulChMG48Fygk1ptpo4lQRJ0eJYtxJFgi7pklLx7EFcOJ34jnvr8pbWlaFN/AT1cZpe0hiFel9Hqg==",
+ "version": "1.20.1",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz",
+ "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
+ "function.prototype.name": "^1.1.5",
"get-intrinsic": "^1.1.1",
"get-symbol-description": "^1.0.0",
"has": "^1.0.3",
+ "has-property-descriptors": "^1.0.0",
"has-symbols": "^1.0.3",
"internal-slot": "^1.0.3",
"is-callable": "^1.2.4",
@@ -6297,9 +6505,10 @@
"object-inspect": "^1.12.0",
"object-keys": "^1.1.1",
"object.assign": "^4.1.2",
- "string.prototype.trimend": "^1.0.4",
- "string.prototype.trimstart": "^1.0.4",
- "unbox-primitive": "^1.0.1"
+ "regexp.prototype.flags": "^1.4.3",
+ "string.prototype.trimend": "^1.0.5",
+ "string.prototype.trimstart": "^1.0.5",
+ "unbox-primitive": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
@@ -6435,13 +6644,14 @@
}
},
"node_modules/eslint": {
- "version": "8.13.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.13.0.tgz",
- "integrity": "sha512-D+Xei61eInqauAyTJ6C0q6x9mx7kTUC1KZ0m0LSEexR0V+e94K12LmWX076ZIsldwfQ2RONdaJe0re0TRGQbRQ==",
+ "version": "8.22.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.22.0.tgz",
+ "integrity": "sha512-ci4t0sz6vSRKdmkOGmprBo6fmI4PrphDFMy5JEq/fNS0gQkJM3rLmrqcp8ipMcdobH3KtUP40KniAE9W19S4wA==",
"dev": true,
"dependencies": {
- "@eslint/eslintrc": "^1.2.1",
- "@humanwhocodes/config-array": "^0.9.2",
+ "@eslint/eslintrc": "^1.3.0",
+ "@humanwhocodes/config-array": "^0.10.4",
+ "@humanwhocodes/gitignore-to-minimatch": "^1.0.2",
"ajv": "^6.10.0",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.2",
@@ -6451,14 +6661,17 @@
"eslint-scope": "^7.1.1",
"eslint-utils": "^3.0.0",
"eslint-visitor-keys": "^3.3.0",
- "espree": "^9.3.1",
+ "espree": "^9.3.3",
"esquery": "^1.4.0",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
"file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
"functional-red-black-tree": "^1.0.1",
"glob-parent": "^6.0.1",
- "globals": "^13.6.0",
+ "globals": "^13.15.0",
+ "globby": "^11.1.0",
+ "grapheme-splitter": "^1.0.4",
"ignore": "^5.2.0",
"import-fresh": "^3.0.0",
"imurmurhash": "^0.1.4",
@@ -6467,7 +6680,7 @@
"json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.4.1",
"lodash.merge": "^4.6.2",
- "minimatch": "^3.0.4",
+ "minimatch": "^3.1.2",
"natural-compare": "^1.4.0",
"optionator": "^0.9.1",
"regexpp": "^3.2.0",
@@ -6527,24 +6740,24 @@
}
},
"node_modules/eslint-config-airbnb-typescript": {
- "version": "16.2.0",
- "resolved": "https://registry.npmjs.org/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-16.2.0.tgz",
- "integrity": "sha512-OUaMPZpTOZGKd5tXOjJ9PRU4iYNW/Z5DoHIynjsVK/FpkWdiY5+nxQW6TiJAlLwVI1l53xUOrnlZWtVBVQzuWA==",
+ "version": "17.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-17.0.0.tgz",
+ "integrity": "sha512-elNiuzD0kPAPTXjFWg+lE24nMdHMtuxgYoD30OyMD6yrW1AhFZPAg27VX7d3tzOErw+dgJTNWfRSDqEcXb4V0g==",
"dev": true,
"dependencies": {
"eslint-config-airbnb-base": "^15.0.0"
},
"peerDependencies": {
- "@typescript-eslint/eslint-plugin": "^5.0.0",
+ "@typescript-eslint/eslint-plugin": "^5.13.0",
"@typescript-eslint/parser": "^5.0.0",
"eslint": "^7.32.0 || ^8.2.0",
"eslint-plugin-import": "^2.25.3"
}
},
"node_modules/eslint-config-prettier": {
- "version": "8.3.0",
- "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz",
- "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==",
+ "version": "8.5.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz",
+ "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==",
"dev": true,
"bin": {
"eslint-config-prettier": "bin/cli.js"
@@ -6810,25 +7023,25 @@
}
},
"node_modules/eslint-plugin-react": {
- "version": "7.29.4",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.29.4.tgz",
- "integrity": "sha512-CVCXajliVh509PcZYRFyu/BoUEz452+jtQJq2b3Bae4v3xBUWPLCmtmBM+ZinG4MzwmxJgJ2M5rMqhqLVn7MtQ==",
+ "version": "7.31.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.0.tgz",
+ "integrity": "sha512-BWriBttYYCnfb4RO9SB91Og8uA9CPcBMl5UlCOCtuYW1UjhN3QypzEcEHky4ZIRZDKjbO2Blh9BjP8E7W/b1SA==",
"dev": true,
"dependencies": {
- "array-includes": "^3.1.4",
- "array.prototype.flatmap": "^1.2.5",
+ "array-includes": "^3.1.5",
+ "array.prototype.flatmap": "^1.3.0",
"doctrine": "^2.1.0",
"estraverse": "^5.3.0",
"jsx-ast-utils": "^2.4.1 || ^3.0.0",
"minimatch": "^3.1.2",
"object.entries": "^1.1.5",
"object.fromentries": "^2.0.5",
- "object.hasown": "^1.1.0",
+ "object.hasown": "^1.1.1",
"object.values": "^1.1.5",
"prop-types": "^15.8.1",
"resolve": "^2.0.0-next.3",
"semver": "^6.3.0",
- "string.prototype.matchall": "^4.0.6"
+ "string.prototype.matchall": "^4.0.7"
},
"engines": {
"node": ">=4"
@@ -7007,9 +7220,9 @@
}
},
"node_modules/eslint/node_modules/globals": {
- "version": "13.10.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.10.0.tgz",
- "integrity": "sha512-piHC3blgLGFjvOuMmWZX60f+na1lXFDhQXBf1UYp2fXPXqvEUbOhNwi6BsQ0bQishwedgnjkwv1d9zKf+MWw3g==",
+ "version": "13.17.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz",
+ "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==",
"dev": true,
"dependencies": {
"type-fest": "^0.20.2"
@@ -7067,17 +7280,20 @@
}
},
"node_modules/espree": {
- "version": "9.3.1",
- "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz",
- "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==",
+ "version": "9.3.3",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.3.tgz",
+ "integrity": "sha512-ORs1Rt/uQTqUKjDdGCyrtYxbazf5umATSf/K4qxjmZHORR6HJk+2s/2Pqe+Kk49HHINC/xNIrGfgh8sZcll0ng==",
"dev": true,
"dependencies": {
- "acorn": "^8.7.0",
- "acorn-jsx": "^5.3.1",
+ "acorn": "^8.8.0",
+ "acorn-jsx": "^5.3.2",
"eslint-visitor-keys": "^3.3.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
"node_modules/esprima": {
@@ -7803,12 +8019,39 @@
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
},
+ "node_modules/function.prototype.name": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz",
+ "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.0",
+ "functions-have-names": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/functional-red-black-tree": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
"integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
"dev": true
},
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/generate-export-aliases": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/generate-export-aliases/-/generate-export-aliases-1.1.0.tgz",
@@ -8040,6 +8283,12 @@
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
"dev": true
},
+ "node_modules/grapheme-splitter": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
+ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
+ "dev": true
+ },
"node_modules/hard-rejection": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz",
@@ -8062,9 +8311,9 @@
}
},
"node_modules/has-bigints": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz",
- "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
+ "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -8078,6 +8327,18 @@
"node": ">=4"
}
},
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
+ "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.1.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
@@ -8259,15 +8520,15 @@
}
},
"node_modules/husky": {
- "version": "7.0.4",
- "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.4.tgz",
- "integrity": "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==",
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.1.tgz",
+ "integrity": "sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==",
"dev": true,
"bin": {
"husky": "lib/bin.js"
},
"engines": {
- "node": ">=12"
+ "node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/typicode"
@@ -8477,21 +8738,25 @@
"dev": true
},
"node_modules/is-bigint": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz",
- "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==",
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+ "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
"dev": true,
+ "dependencies": {
+ "has-bigints": "^1.0.1"
+ },
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-boolean-object": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz",
- "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==",
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+ "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
"dev": true,
"dependencies": {
- "call-bind": "^1.0.0"
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
@@ -8506,6 +8771,21 @@
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
"dev": true
},
+ "node_modules/is-builtin-module": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.0.tgz",
+ "integrity": "sha512-phDA4oSGt7vl1n5tJvTWooWWAsXLY+2xCnxNqvKhGEzujg+A43wPlPOyDg3C8XQHN+6k/JTQWJ/j0dQh/qr+Hw==",
+ "dev": true,
+ "dependencies": {
+ "builtin-modules": "^3.3.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/is-callable": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz",
@@ -8682,10 +8962,13 @@
}
},
"node_modules/is-number-object": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz",
- "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==",
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
+ "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
"dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
"engines": {
"node": ">= 0.4"
},
@@ -12889,13 +13172,13 @@
}
},
"node_modules/object.hasown": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.0.tgz",
- "integrity": "sha512-MhjYRfj3GBlhSkDHo6QmvgjRLXQ2zndabdf3nX0yTyZK9rPfxb6uRpAac8HXNLy1GpqWtZ81Qh4v3uOls2sRAg==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.1.tgz",
+ "integrity": "sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A==",
"dev": true,
"dependencies": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.19.1"
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -13793,13 +14076,14 @@
}
},
"node_modules/regexp.prototype.flags": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz",
- "integrity": "sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ==",
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
+ "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
- "define-properties": "^1.1.3"
+ "define-properties": "^1.1.3",
+ "functions-have-names": "^1.2.2"
},
"engines": {
"node": ">= 0.4"
@@ -14273,9 +14557,9 @@
}
},
"node_modules/shell-quote": {
- "version": "1.7.2",
- "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz",
- "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==",
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz",
+ "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==",
"dev": true
},
"node_modules/side-channel": {
@@ -14886,26 +15170,28 @@
}
},
"node_modules/string.prototype.trimend": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
- "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz",
+ "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
- "define-properties": "^1.1.3"
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/string.prototype.trimstart": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
- "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz",
+ "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
- "define-properties": "^1.1.3"
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -15473,9 +15759,9 @@
}
},
"node_modules/tslib": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
- "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==",
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
+ "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
"dev": true
},
"node_modules/tsutils": {
@@ -15564,14 +15850,14 @@
}
},
"node_modules/unbox-primitive": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
- "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+ "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
"dev": true,
"dependencies": {
- "function-bind": "^1.1.1",
- "has-bigints": "^1.0.1",
- "has-symbols": "^1.0.2",
+ "call-bind": "^1.0.2",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.0.3",
"which-boxed-primitive": "^1.0.2"
},
"funding": {
@@ -17958,26 +18244,26 @@
}
},
"@eslint/eslintrc": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz",
- "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==",
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz",
+ "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==",
"dev": true,
"requires": {
"ajv": "^6.12.4",
"debug": "^4.3.2",
- "espree": "^9.3.1",
- "globals": "^13.9.0",
+ "espree": "^9.3.2",
+ "globals": "^13.15.0",
"ignore": "^5.2.0",
"import-fresh": "^3.2.1",
"js-yaml": "^4.1.0",
- "minimatch": "^3.0.4",
+ "minimatch": "^3.1.2",
"strip-json-comments": "^3.1.1"
},
"dependencies": {
"globals": {
- "version": "13.13.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz",
- "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==",
+ "version": "13.17.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz",
+ "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==",
"dev": true,
"requires": {
"type-fest": "^0.20.2"
@@ -17998,18 +18284,22 @@
}
},
"@hover/javascript": {
- "version": "6.82.0",
- "resolved": "https://registry.npmjs.org/@hover/javascript/-/javascript-6.82.0.tgz",
- "integrity": "sha512-k/MahVWgV2NLFfD1IZuklB4a7DmCRITAbvzb4WpKfNMaDTqJ4EBbK6jxyvPUP9UySdpJWTSb3WhngIs0h5SIiQ==",
+ "version": "6.90.0",
+ "resolved": "https://registry.npmjs.org/@hover/javascript/-/javascript-6.90.0.tgz",
+ "integrity": "sha512-FOMyktsyOI9S2axKtqgCAX1usnoRr6VxVvaOLomPqeWXYjzYmH7fcFRtsQl3ObOdNmqhVBwxIa+Sf5PoeVvLmQ==",
"dev": true,
"requires": {
"@commitlint/cli": "^16.1.0",
"@commitlint/config-conventional": "^16.2.1",
"@commitlint/prompt": "^16.1.0",
"@types/jest": "^27.0.2",
+ "@types/lodash.has": "^4.5.6",
+ "@types/mkdirp": "^1.0.2",
"@types/node": ">=17.x",
+ "@types/rimraf": "^3.0.2",
+ "@types/which": "^2.0.1",
"@typescript-eslint/eslint-plugin": "^5.13.0",
- "@typescript-eslint/parser": "^5.13.0",
+ "@typescript-eslint/parser": "^5.27.0",
"arrify": "^2.0.1",
"commitizen": "^4.2.4",
"concurrently": "^7.0.0",
@@ -18017,19 +18307,19 @@
"cross-env": "^7.0.3",
"cross-spawn": "^7.0.1",
"doctoc": "^2.1.0",
- "eslint": "^8.8.0",
+ "eslint": "^8.16.0",
"eslint-config-airbnb": "19.0.0",
- "eslint-config-airbnb-typescript": "^16.1.0",
- "eslint-config-prettier": "^8.3.0",
+ "eslint-config-airbnb-typescript": "^17.0.0",
+ "eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jest": "^26.1.1",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.0.0",
- "eslint-plugin-react": "^7.27.0",
+ "eslint-plugin-react": "^7.30.0",
"eslint-plugin-react-hooks": "^4.3.0",
- "glob": "^7.2.0",
+ "glob": "^8.0.3",
"is-ci": "^3.0.1",
- "jest": "^27.4.7",
+ "jest": "^27.5.1",
"jest-github-actions-reporter": "^1.0.3",
"jest-watch-typeahead": "^1.0.0",
"lint-staged": "^12.3.4",
@@ -18039,16 +18329,49 @@
"read-pkg-up": "^7.0.1",
"rimraf": "^3.0.2",
"ts-jest": "^27.1.3",
- "tslib": "^2.3.1",
+ "tslib": "^2.4.0",
"typescript": "^4",
"which": "^2.0.2",
- "yargs-parser": "^21.0.0"
+ "yargs-parser": "^21.0.1"
+ },
+ "dependencies": {
+ "brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "glob": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz",
+ "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
+ }
+ },
+ "minimatch": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
+ "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ }
+ }
}
},
"@humanwhocodes/config-array": {
- "version": "0.9.5",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz",
- "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==",
+ "version": "0.10.4",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz",
+ "integrity": "sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==",
"dev": true,
"requires": {
"@humanwhocodes/object-schema": "^1.2.1",
@@ -18056,6 +18379,12 @@
"minimatch": "^3.0.4"
}
},
+ "@humanwhocodes/gitignore-to-minimatch": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz",
+ "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==",
+ "dev": true
+ },
"@humanwhocodes/object-schema": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
@@ -18781,23 +19110,23 @@
}
},
"@rollup/plugin-node-resolve": {
- "version": "13.1.3",
- "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.1.3.tgz",
- "integrity": "sha512-BdxNk+LtmElRo5d06MGY4zoepyrXX1tkzX2hrnPEZ53k78GuOMWLqmJDGIIOPwVRIFZrLQOo+Yr6KtCuLIA0AQ==",
+ "version": "13.3.0",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.3.0.tgz",
+ "integrity": "sha512-Lus8rbUo1eEcnS4yTFKLZrVumLPY+YayBdWXgFSHYhTT2iJbMhoaaBL3xl5NCdeRytErGr8tZ0L71BMRmnlwSw==",
"dev": true,
"requires": {
"@rollup/pluginutils": "^3.1.0",
"@types/resolve": "1.17.1",
- "builtin-modules": "^3.1.0",
"deepmerge": "^4.2.2",
+ "is-builtin-module": "^3.1.0",
"is-module": "^1.0.0",
"resolve": "^1.19.0"
}
},
"@rollup/plugin-replace": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-3.1.0.tgz",
- "integrity": "sha512-pA3XRUrSKybVYqmH5TqWNZpGxF+VV+1GrYchKgCNIj2vsSOX7CVm2RCtx8p2nrC7xvkziYyK+lSi74T93MU3YA==",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-4.0.0.tgz",
+ "integrity": "sha512-+rumQFiaNac9y64OHtkHGmdjm7us9bo1PlbgQfdihQtuNxzjpaB064HbRnewUOggLQxVCCyINfStkgmBeQpv1g==",
"dev": true,
"requires": {
"@rollup/pluginutils": "^3.1.0",
@@ -19004,6 +19333,16 @@
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
"dev": true
},
+ "@types/glob": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==",
+ "dev": true,
+ "requires": {
+ "@types/minimatch": "*",
+ "@types/node": "*"
+ }
+ },
"@types/graceful-fs": {
"version": "4.1.5",
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz",
@@ -19071,9 +19410,9 @@
}
},
"@types/jscodeshift": {
- "version": "0.11.3",
- "resolved": "https://registry.npmjs.org/@types/jscodeshift/-/jscodeshift-0.11.3.tgz",
- "integrity": "sha512-pM0JD9kWVDH9DQp5Y6td16924V3MwZHei8P3cTeuFhXpzpk0K+iWraBZz8wF61QkFs9fZeAQNX0q8SG0+TFm2w==",
+ "version": "0.11.5",
+ "resolved": "https://registry.npmjs.org/@types/jscodeshift/-/jscodeshift-0.11.5.tgz",
+ "integrity": "sha512-7JV0qdblTeWFigevmwFUgROXX395F+MQx6v0YqPn8Bx0B4Sng6alEejz9PENzgLYpG+zL0O4tGdBzc4gKZH8XA==",
"dev": true,
"requires": {
"ast-types": "^0.14.1",
@@ -19092,12 +19431,42 @@
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
"dev": true
},
+ "@types/lodash": {
+ "version": "4.14.184",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.184.tgz",
+ "integrity": "sha512-RoZphVtHbxPZizt4IcILciSWiC6dcn+eZ8oX9IWEYfDMcocdd42f7NPI6fQj+6zI8y4E0L7gu2pcZKLGTRaV9Q==",
+ "dev": true
+ },
+ "@types/lodash.has": {
+ "version": "4.5.7",
+ "resolved": "https://registry.npmjs.org/@types/lodash.has/-/lodash.has-4.5.7.tgz",
+ "integrity": "sha512-nfbAzRbsZBdzSAkL9iiLy4SQk89uuFcXBFwZ7pf6oZhBgPvNys8BY5Twp/w8XvZKGt1o6cAa85wX4QhqO3uQ7A==",
+ "dev": true,
+ "requires": {
+ "@types/lodash": "*"
+ }
+ },
+ "@types/minimatch": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.0.tgz",
+ "integrity": "sha512-0RJHq5FqDWo17kdHe+SMDJLfxmLaqHbWnqZ6gNKzDvStUlrmx/eKIY17+ifLS1yybo7X86aUshQMlittDOVNnw==",
+ "dev": true
+ },
"@types/minimist": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz",
"integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==",
"dev": true
},
+ "@types/mkdirp": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-1.0.2.tgz",
+ "integrity": "sha512-o0K1tSO0Dx5X6xlU5F1D6625FawhC3dU3iqr25lluNv/+/QIVH8RLNEiVokgIZo+mz+87w/3Mkg/VvQS+J51fQ==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
"@types/node": {
"version": "17.0.23",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz",
@@ -19130,12 +19499,28 @@
"@types/node": "*"
}
},
+ "@types/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-F3OznnSLAUxFrCEu/L5PY8+ny8DtcFRjx7fZZ9bycvXRi3KPTRS9HOitGZwvPg0juRhXFWIeKX58cnX5YqLohQ==",
+ "dev": true,
+ "requires": {
+ "@types/glob": "*",
+ "@types/node": "*"
+ }
+ },
"@types/stack-utils": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.0.tgz",
"integrity": "sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==",
"dev": true
},
+ "@types/which": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@types/which/-/which-2.0.1.tgz",
+ "integrity": "sha512-Jjakcv8Roqtio6w1gr0D7y6twbhx6gGgFGF5BLwajPpnOIOxFkakFhCq+LmyyeAz7BX6ULrjBOxdKaCDy+4+dQ==",
+ "dev": true
+ },
"@types/yargs": {
"version": "15.0.14",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz",
@@ -19178,15 +19563,67 @@
}
},
"@typescript-eslint/parser": {
- "version": "5.19.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.19.0.tgz",
- "integrity": "sha512-yhktJjMCJX8BSBczh1F/uY8wGRYrBeyn84kH6oyqdIJwTGKmzX5Qiq49LRQ0Jh0LXnWijEziSo6BRqny8nqLVQ==",
+ "version": "5.35.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.35.1.tgz",
+ "integrity": "sha512-XL2TBTSrh3yWAsMYpKseBYTVpvudNf69rPOWXWVBI08My2JVT5jR66eTt4IgQFHA/giiKJW5dUD4x/ZviCKyGg==",
"dev": true,
"requires": {
- "@typescript-eslint/scope-manager": "5.19.0",
- "@typescript-eslint/types": "5.19.0",
- "@typescript-eslint/typescript-estree": "5.19.0",
- "debug": "^4.3.2"
+ "@typescript-eslint/scope-manager": "5.35.1",
+ "@typescript-eslint/types": "5.35.1",
+ "@typescript-eslint/typescript-estree": "5.35.1",
+ "debug": "^4.3.4"
+ },
+ "dependencies": {
+ "@typescript-eslint/scope-manager": {
+ "version": "5.35.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.35.1.tgz",
+ "integrity": "sha512-kCYRSAzIW9ByEIzmzGHE50NGAvAP3wFTaZevgWva7GpquDyFPFcmvVkFJGWJJktg/hLwmys/FZwqM9EKr2u24Q==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "5.35.1",
+ "@typescript-eslint/visitor-keys": "5.35.1"
+ }
+ },
+ "@typescript-eslint/types": {
+ "version": "5.35.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.35.1.tgz",
+ "integrity": "sha512-FDaujtsH07VHzG0gQ6NDkVVhi1+rhq0qEvzHdJAQjysN+LHDCKDKCBRlZFFE0ec0jKxiv0hN63SNfExy0KrbQQ==",
+ "dev": true
+ },
+ "@typescript-eslint/typescript-estree": {
+ "version": "5.35.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.35.1.tgz",
+ "integrity": "sha512-JUqE1+VRTGyoXlDWWjm6MdfpBYVq+hixytrv1oyjYIBEOZhBCwtpp5ZSvBt4wIA1MKWlnaC2UXl2XmYGC3BoQA==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "5.35.1",
+ "@typescript-eslint/visitor-keys": "5.35.1",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ }
+ },
+ "@typescript-eslint/visitor-keys": {
+ "version": "5.35.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.35.1.tgz",
+ "integrity": "sha512-cEB1DvBVo1bxbW/S5axbGPE6b7FIMAbo3w+AGq6zNDA7+NYJOIkKj/sInfTv4edxd4PxJSgdN4t6/pbvgA+n5g==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "5.35.1",
+ "eslint-visitor-keys": "^3.3.0"
+ }
+ },
+ "semver": {
+ "version": "7.3.7",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+ "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ }
}
},
"@typescript-eslint/scope-manager": {
@@ -19273,9 +19710,9 @@
"dev": true
},
"acorn": {
- "version": "8.7.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
- "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
+ "version": "8.8.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
+ "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==",
"dev": true
},
"acorn-globals": {
@@ -19424,14 +19861,14 @@
"dev": true
},
"array-includes": {
- "version": "3.1.4",
- "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz",
- "integrity": "sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==",
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz",
+ "integrity": "sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==",
"dev": true,
"requires": {
"call-bind": "^1.0.2",
- "define-properties": "^1.1.3",
- "es-abstract": "^1.19.1",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5",
"get-intrinsic": "^1.1.1",
"is-string": "^1.0.7"
}
@@ -19813,9 +20250,9 @@
"dev": true
},
"builtin-modules": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz",
- "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==",
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
+ "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==",
"dev": true
},
"cache-base": {
@@ -20675,12 +21112,13 @@
"dev": true
},
"define-properties": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
- "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
+ "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
"dev": true,
"requires": {
- "object-keys": "^1.0.12"
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
}
},
"define-property": {
@@ -20891,17 +21329,19 @@
}
},
"es-abstract": {
- "version": "1.19.4",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.4.tgz",
- "integrity": "sha512-flV8e5g9/xulChMG48Fygk1ptpo4lQRJ0eJYtxJFgi7pklLx7EFcOJ34jnvr8pbWlaFN/AT1cZpe0hiFel9Hqg==",
+ "version": "1.20.1",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz",
+ "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==",
"dev": true,
"requires": {
"call-bind": "^1.0.2",
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
+ "function.prototype.name": "^1.1.5",
"get-intrinsic": "^1.1.1",
"get-symbol-description": "^1.0.0",
"has": "^1.0.3",
+ "has-property-descriptors": "^1.0.0",
"has-symbols": "^1.0.3",
"internal-slot": "^1.0.3",
"is-callable": "^1.2.4",
@@ -20913,9 +21353,10 @@
"object-inspect": "^1.12.0",
"object-keys": "^1.1.1",
"object.assign": "^4.1.2",
- "string.prototype.trimend": "^1.0.4",
- "string.prototype.trimstart": "^1.0.4",
- "unbox-primitive": "^1.0.1"
+ "regexp.prototype.flags": "^1.4.3",
+ "string.prototype.trimend": "^1.0.5",
+ "string.prototype.trimstart": "^1.0.5",
+ "unbox-primitive": "^1.0.2"
}
},
"es-shim-unscopables": {
@@ -21011,13 +21452,14 @@
}
},
"eslint": {
- "version": "8.13.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.13.0.tgz",
- "integrity": "sha512-D+Xei61eInqauAyTJ6C0q6x9mx7kTUC1KZ0m0LSEexR0V+e94K12LmWX076ZIsldwfQ2RONdaJe0re0TRGQbRQ==",
+ "version": "8.22.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.22.0.tgz",
+ "integrity": "sha512-ci4t0sz6vSRKdmkOGmprBo6fmI4PrphDFMy5JEq/fNS0gQkJM3rLmrqcp8ipMcdobH3KtUP40KniAE9W19S4wA==",
"dev": true,
"requires": {
- "@eslint/eslintrc": "^1.2.1",
- "@humanwhocodes/config-array": "^0.9.2",
+ "@eslint/eslintrc": "^1.3.0",
+ "@humanwhocodes/config-array": "^0.10.4",
+ "@humanwhocodes/gitignore-to-minimatch": "^1.0.2",
"ajv": "^6.10.0",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.2",
@@ -21027,14 +21469,17 @@
"eslint-scope": "^7.1.1",
"eslint-utils": "^3.0.0",
"eslint-visitor-keys": "^3.3.0",
- "espree": "^9.3.1",
+ "espree": "^9.3.3",
"esquery": "^1.4.0",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
"file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
"functional-red-black-tree": "^1.0.1",
"glob-parent": "^6.0.1",
- "globals": "^13.6.0",
+ "globals": "^13.15.0",
+ "globby": "^11.1.0",
+ "grapheme-splitter": "^1.0.4",
"ignore": "^5.2.0",
"import-fresh": "^3.0.0",
"imurmurhash": "^0.1.4",
@@ -21043,7 +21488,7 @@
"json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.4.1",
"lodash.merge": "^4.6.2",
- "minimatch": "^3.0.4",
+ "minimatch": "^3.1.2",
"natural-compare": "^1.4.0",
"optionator": "^0.9.1",
"regexpp": "^3.2.0",
@@ -21104,9 +21549,9 @@
}
},
"globals": {
- "version": "13.10.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.10.0.tgz",
- "integrity": "sha512-piHC3blgLGFjvOuMmWZX60f+na1lXFDhQXBf1UYp2fXPXqvEUbOhNwi6BsQ0bQishwedgnjkwv1d9zKf+MWw3g==",
+ "version": "13.17.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz",
+ "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==",
"dev": true,
"requires": {
"type-fest": "^0.20.2"
@@ -21165,18 +21610,18 @@
}
},
"eslint-config-airbnb-typescript": {
- "version": "16.2.0",
- "resolved": "https://registry.npmjs.org/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-16.2.0.tgz",
- "integrity": "sha512-OUaMPZpTOZGKd5tXOjJ9PRU4iYNW/Z5DoHIynjsVK/FpkWdiY5+nxQW6TiJAlLwVI1l53xUOrnlZWtVBVQzuWA==",
+ "version": "17.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-17.0.0.tgz",
+ "integrity": "sha512-elNiuzD0kPAPTXjFWg+lE24nMdHMtuxgYoD30OyMD6yrW1AhFZPAg27VX7d3tzOErw+dgJTNWfRSDqEcXb4V0g==",
"dev": true,
"requires": {
"eslint-config-airbnb-base": "^15.0.0"
}
},
"eslint-config-prettier": {
- "version": "8.3.0",
- "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz",
- "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==",
+ "version": "8.5.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz",
+ "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==",
"dev": true,
"requires": {}
},
@@ -21376,25 +21821,25 @@
}
},
"eslint-plugin-react": {
- "version": "7.29.4",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.29.4.tgz",
- "integrity": "sha512-CVCXajliVh509PcZYRFyu/BoUEz452+jtQJq2b3Bae4v3xBUWPLCmtmBM+ZinG4MzwmxJgJ2M5rMqhqLVn7MtQ==",
+ "version": "7.31.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.0.tgz",
+ "integrity": "sha512-BWriBttYYCnfb4RO9SB91Og8uA9CPcBMl5UlCOCtuYW1UjhN3QypzEcEHky4ZIRZDKjbO2Blh9BjP8E7W/b1SA==",
"dev": true,
"requires": {
- "array-includes": "^3.1.4",
- "array.prototype.flatmap": "^1.2.5",
+ "array-includes": "^3.1.5",
+ "array.prototype.flatmap": "^1.3.0",
"doctrine": "^2.1.0",
"estraverse": "^5.3.0",
"jsx-ast-utils": "^2.4.1 || ^3.0.0",
"minimatch": "^3.1.2",
"object.entries": "^1.1.5",
"object.fromentries": "^2.0.5",
- "object.hasown": "^1.1.0",
+ "object.hasown": "^1.1.1",
"object.values": "^1.1.5",
"prop-types": "^15.8.1",
"resolve": "^2.0.0-next.3",
"semver": "^6.3.0",
- "string.prototype.matchall": "^4.0.6"
+ "string.prototype.matchall": "^4.0.7"
},
"dependencies": {
"doctrine": {
@@ -21467,13 +21912,13 @@
"dev": true
},
"espree": {
- "version": "9.3.1",
- "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz",
- "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==",
+ "version": "9.3.3",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.3.tgz",
+ "integrity": "sha512-ORs1Rt/uQTqUKjDdGCyrtYxbazf5umATSf/K4qxjmZHORR6HJk+2s/2Pqe+Kk49HHINC/xNIrGfgh8sZcll0ng==",
"dev": true,
"requires": {
- "acorn": "^8.7.0",
- "acorn-jsx": "^5.3.1",
+ "acorn": "^8.8.0",
+ "acorn-jsx": "^5.3.2",
"eslint-visitor-keys": "^3.3.0"
}
},
@@ -22044,12 +22489,30 @@
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
},
+ "function.prototype.name": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz",
+ "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.0",
+ "functions-have-names": "^1.2.2"
+ }
+ },
"functional-red-black-tree": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
"integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
"dev": true
},
+ "functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true
+ },
"generate-export-aliases": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/generate-export-aliases/-/generate-export-aliases-1.1.0.tgz",
@@ -22217,6 +22680,12 @@
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
"dev": true
},
+ "grapheme-splitter": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
+ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
+ "dev": true
+ },
"hard-rejection": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz",
@@ -22233,9 +22702,9 @@
}
},
"has-bigints": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz",
- "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
+ "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
"dev": true
},
"has-flag": {
@@ -22243,6 +22712,15 @@
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
},
+ "has-property-descriptors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
+ "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
+ "dev": true,
+ "requires": {
+ "get-intrinsic": "^1.1.1"
+ }
+ },
"has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
@@ -22383,9 +22861,9 @@
"dev": true
},
"husky": {
- "version": "7.0.4",
- "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.4.tgz",
- "integrity": "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==",
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.1.tgz",
+ "integrity": "sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==",
"dev": true
},
"iconv-lite": {
@@ -22546,18 +23024,22 @@
"dev": true
},
"is-bigint": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz",
- "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==",
- "dev": true
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+ "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "dev": true,
+ "requires": {
+ "has-bigints": "^1.0.1"
+ }
},
"is-boolean-object": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz",
- "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==",
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+ "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
"dev": true,
"requires": {
- "call-bind": "^1.0.0"
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
}
},
"is-buffer": {
@@ -22566,6 +23048,15 @@
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
"dev": true
},
+ "is-builtin-module": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.0.tgz",
+ "integrity": "sha512-phDA4oSGt7vl1n5tJvTWooWWAsXLY+2xCnxNqvKhGEzujg+A43wPlPOyDg3C8XQHN+6k/JTQWJ/j0dQh/qr+Hw==",
+ "dev": true,
+ "requires": {
+ "builtin-modules": "^3.3.0"
+ }
+ },
"is-callable": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz",
@@ -22683,10 +23174,13 @@
"dev": true
},
"is-number-object": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz",
- "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==",
- "dev": true
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
+ "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+ "dev": true,
+ "requires": {
+ "has-tostringtag": "^1.0.0"
+ }
},
"is-obj": {
"version": "2.0.0",
@@ -25845,13 +26339,13 @@
}
},
"object.hasown": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.0.tgz",
- "integrity": "sha512-MhjYRfj3GBlhSkDHo6QmvgjRLXQ2zndabdf3nX0yTyZK9rPfxb6uRpAac8HXNLy1GpqWtZ81Qh4v3uOls2sRAg==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.1.tgz",
+ "integrity": "sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A==",
"dev": true,
"requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.19.1"
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5"
}
},
"object.pick": {
@@ -26508,13 +27002,14 @@
}
},
"regexp.prototype.flags": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz",
- "integrity": "sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ==",
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
+ "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==",
"dev": true,
"requires": {
"call-bind": "^1.0.2",
- "define-properties": "^1.1.3"
+ "define-properties": "^1.1.3",
+ "functions-have-names": "^1.2.2"
}
},
"regexpp": {
@@ -26868,9 +27363,9 @@
"dev": true
},
"shell-quote": {
- "version": "1.7.2",
- "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz",
- "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==",
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz",
+ "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==",
"dev": true
},
"side-channel": {
@@ -27364,23 +27859,25 @@
}
},
"string.prototype.trimend": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
- "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz",
+ "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==",
"dev": true,
"requires": {
"call-bind": "^1.0.2",
- "define-properties": "^1.1.3"
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5"
}
},
"string.prototype.trimstart": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
- "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz",
+ "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==",
"dev": true,
"requires": {
"call-bind": "^1.0.2",
- "define-properties": "^1.1.3"
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5"
}
},
"strip-ansi": {
@@ -27790,9 +28287,9 @@
}
},
"tslib": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
- "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==",
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
+ "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
"dev": true
},
"tsutils": {
@@ -27855,14 +28352,14 @@
"dev": true
},
"unbox-primitive": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
- "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+ "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
"dev": true,
"requires": {
- "function-bind": "^1.1.1",
- "has-bigints": "^1.0.1",
- "has-symbols": "^1.0.2",
+ "call-bind": "^1.0.2",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.0.3",
"which-boxed-primitive": "^1.0.2"
}
},
diff --git a/package.json b/package.json
index d7dec9e..e8a26c3 100644
--- a/package.json
+++ b/package.json
@@ -19,11 +19,12 @@
"prepare:playwright-test:package": "jscodeshift -t ./playwright-test/rename-imports.ts --extensions=ts --parser=ts ./lib",
"prepublishOnly": "npm run build",
"start:standalone": "hover-scripts test",
- "test": "run-s build:testing-library test:*",
+ "test": "run-s build:testing-library test:standalone test:fixture",
+ "test:legacy": "run-s build:testing-library test:standalone test:fixture:legacy",
"test:fixture": "playwright test",
+ "test:fixture:legacy": "playwright test test/fixture/element-handles.test.ts",
"test:standalone": "hover-scripts test --no-watch",
- "test:types": "tsc --noEmit",
- "validate": "run-s test"
+ "test:types": "tsc --noEmit"
},
"repository": {
"type": "git",
@@ -56,11 +57,11 @@
"@playwright/test": "^1.25.0",
"@rollup/plugin-commonjs": "^21.0.0",
"@rollup/plugin-node-resolve": "^13.0.5",
- "@rollup/plugin-replace": "^3.0.0",
+ "@rollup/plugin-replace": "^4.0.0",
"@types/jest": "^27.0.2",
"@types/jscodeshift": "^0.11.2",
"generate-export-aliases": "^1.1.0",
- "husky": "^7.0.2",
+ "husky": "^8.0.1",
"jscodeshift": "^0.13.0",
"npm-run-all": "^4.1.5",
"playwright": "^1.25.0",
diff --git a/test/fixture/configure.test.ts b/test/fixture/configure.test.ts
new file mode 100644
index 0000000..dba69eb
--- /dev/null
+++ b/test/fixture/configure.test.ts
@@ -0,0 +1,48 @@
+import * as path from 'path'
+
+import * as playwright from '@playwright/test'
+
+import {
+ LocatorFixtures as TestingLibraryFixtures,
+ locatorFixtures as fixtures,
+} from '../../lib/fixture'
+
+const test = playwright.test.extend(fixtures)
+
+const {expect} = test
+
+test.use({testIdAttribute: 'data-new-id'})
+
+test.describe('global configuration', () => {
+ test.beforeEach(async ({page}) => {
+ await page.goto(`file://${path.join(__dirname, '../fixtures/page.html')}`)
+ })
+
+ test('queries with test ID configured in module scope', async ({queries}) => {
+ const defaultTestIdLocator = queries.queryByTestId('testid-text-input')
+ const customTestIdLocator = queries.queryByTestId('first-level-header')
+
+ await expect(defaultTestIdLocator).not.toBeVisible()
+ await expect(customTestIdLocator).toBeVisible()
+ })
+
+ test.describe('overridding global configuration', () => {
+ test.use({testIdAttribute: 'data-id'})
+
+ test('overrides test ID configured in module scope', async ({queries}) => {
+ const globalTestIdLocator = queries.queryByTestId('first-level-header')
+ const overriddenTestIdLocator = queries.queryByTestId('second-level-header')
+
+ await expect(globalTestIdLocator).not.toBeVisible()
+ await expect(overriddenTestIdLocator).toBeVisible()
+ })
+ })
+
+ test("page override doesn't modify global configuration", async ({queries}) => {
+ const defaultTestIdLocator = queries.queryByTestId('testid-text-input')
+ const customTestIdLocator = queries.queryByTestId('first-level-header')
+
+ await expect(defaultTestIdLocator).not.toBeVisible()
+ await expect(customTestIdLocator).toBeVisible()
+ })
+})
diff --git a/test/fixture/element-handles.test.ts b/test/fixture/element-handles.test.ts
new file mode 100644
index 0000000..c674e99
--- /dev/null
+++ b/test/fixture/element-handles.test.ts
@@ -0,0 +1,218 @@
+import * as path from 'path'
+
+import * as playwright from '@playwright/test'
+
+import {getDocument, getQueriesForElement, within} from '../../lib'
+import {TestingLibraryFixtures, configure, fixtures} from '../../lib/fixture'
+
+const test = playwright.test.extend(fixtures)
+
+const {expect} = test
+
+test.describe('lib/fixture.ts', () => {
+ test.describe('standard page', () => {
+ test.beforeEach(async ({page}) => {
+ await page.goto(`file://${path.join(__dirname, '../fixtures/page.html')}`)
+ })
+
+ test.afterEach(async ({page}) => page.close())
+
+ test('should handle the query* methods', async ({queries: {queryByText}}) => {
+ const element = await queryByText('Hello h1')
+
+ expect(element).toBeTruthy()
+ expect(await element.textContent()).toEqual('Hello h1')
+ })
+
+ test('should use the new v3 methods', async ({queries: {queryByRole}}) => {
+ const element = await queryByRole('presentation')
+
+ expect(element).toBeTruthy()
+ expect(await element.textContent()).toContain('Layout table')
+ })
+
+ test('should handle regex matching', async ({queries: {queryByText}}) => {
+ const element = await queryByText(/HeLlO h(1|7)/i)
+
+ expect(element).toBeTruthy()
+ expect(await element.textContent()).toEqual('Hello h1')
+ })
+
+ test('should handle the get* methods', async ({queries: {getByTestId}, page}) => {
+ const element = await getByTestId('testid-text-input')
+
+ expect(await page.evaluate(el => el.outerHTML, element)).toMatch(
+ ``,
+ )
+ })
+
+ test('attaches `getNodeText`', async ({queries}) => {
+ const element = await queries.getByText('Hello h1')
+
+ expect(await queries.getNodeText(element)).toEqual('Hello h1')
+ })
+
+ test('handles page navigations', async ({queries: {getByText}, page}) => {
+ await page.goto(`file://${path.join(__dirname, '../fixtures/page.html')}`)
+
+ const element = await getByText('Hello h1')
+
+ expect(await element.textContent()).toEqual('Hello h1')
+ })
+
+ test('should handle the get* method failures', async ({queries}) => {
+ const {getByTitle} = queries
+ // Use the scoped element so the pretty HTML snapshot is smaller
+
+ await expect(async () => getByTitle('missing')).rejects.toThrow()
+ })
+
+ 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 queryAll* methods', async ({queries, page}) => {
+ const {queryAllByText} = queries
+ const elements = await queryAllByText(/Hello/)
+ expect(elements).toHaveLength(3)
+
+ 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]),
+ ])
+
+ expect(text).toEqual(['Hello h1', 'Hello h2', 'Hello h3'])
+ })
+
+ 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 page.evaluate(el => el.textContent, elements[0])
+
+ 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'})
+
+ const text = await page.evaluate(el => el.textContent, element)
+
+ expect(text).toEqual('Hello 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)
+
+ expect(text).toEqual('getByRole Test')
+ })
+
+ 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(1)
+ expect(hiddenElements).toHaveLength(2)
+ })
+
+ 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')
+
+ 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 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'))
+
+ expect(await queryByText('Hello h1')).toBeFalsy()
+ expect(await queryByText('Hello h3')).toBeTruthy()
+ })
+
+ test.describe('configuration', () => {
+ test.afterEach(() => {
+ configure({testIdAttribute: 'data-testid'}) // cleanup
+ })
+
+ test('should support custom data-testid attribute name', async ({queries}) => {
+ configure({testIdAttribute: 'data-id'})
+
+ const element = await queries.getByTestId('second-level-header')
+
+ expect(await queries.getNodeText(element)).toEqual('Hello h2')
+ })
+
+ test('should support subsequent changing the data-testid attribute names', async ({
+ queries,
+ }) => {
+ configure({testIdAttribute: 'data-id'})
+ configure({testIdAttribute: 'data-new-id'})
+
+ 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: 3000})).toBeTruthy()
+ })
+
+ test('should handle the findByAll* methods', async ({queries}) => {
+ const {findAllByText} = queries
+ const elements = await findAllByText(/Hello/, {}, {timeout: 3000})
+ expect(elements).toHaveLength(2)
+
+ const text = await Promise.all([elements[0].textContent(), elements[1].textContent()])
+
+ expect(text).toEqual(['Hello h1', 'Hello h2'])
+ })
+ })
+})
diff --git a/test/fixture/fixture.test.ts b/test/fixture/fixture.test.ts
deleted file mode 100644
index 0cee28f..0000000
--- a/test/fixture/fixture.test.ts
+++ /dev/null
@@ -1,211 +0,0 @@
-import * as path from 'path'
-
-import * as playwright from '@playwright/test'
-
-import {getDocument, getQueriesForElement, within} from '../../lib'
-import {TestingLibraryFixtures, configure, fixtures} from '../../lib/fixture'
-
-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')
-
- expect(element).toBeTruthy()
- expect(await element.textContent()).toEqual('Hello h1')
- })
-
- test('should use the new v3 methods', async ({queries: {queryByRole}}) => {
- const element = await queryByRole('presentation')
-
- expect(element).toBeTruthy()
- expect(await element.textContent()).toContain('Layout table')
- })
-
- test('should handle regex matching', async ({queries: {queryByText}}) => {
- const element = await queryByText(/HeLlO h(1|7)/i)
-
- expect(element).toBeTruthy()
- expect(await element.textContent()).toEqual('Hello h1')
- })
-
- test('should handle the get* methods', async ({queries: {getByTestId}, page}) => {
- const element = await getByTestId('testid-text-input')
-
- expect(await page.evaluate(el => el.outerHTML, element)).toMatch(
- ``,
- )
- })
-
- test('attaches `getNodeText`', async ({queries}) => {
- const element = await queries.getByText('Hello h1')
-
- expect(await queries.getNodeText(element)).toEqual('Hello h1')
- })
-
- test('handles page navigations', async ({queries: {getByText}, page}) => {
- await page.goto(`file://${path.join(__dirname, '../fixtures/page.html')}`)
-
- const element = await getByText('Hello h1')
-
- expect(await element.textContent()).toEqual('Hello h1')
- })
-
- test('should handle the get* method failures', async ({queries}) => {
- const {getByTitle} = queries
- // Use the scoped element so the pretty HTML snapshot is smaller
-
- await expect(async () => getByTitle('missing')).rejects.toThrow()
- })
-
- 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 queryAll* methods', async ({queries, page}) => {
- const {queryAllByText} = queries
- const elements = await queryAllByText(/Hello/)
- expect(elements).toHaveLength(3)
-
- 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]),
- ])
-
- expect(text).toEqual(['Hello h1', 'Hello h2', 'Hello h3'])
- })
-
- 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 page.evaluate(el => el.textContent, elements[0])
-
- 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'})
-
- const text = await page.evaluate(el => el.textContent, element)
-
- expect(text).toEqual('Hello 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)
-
- expect(text).toEqual('getByRole Test')
- })
-
- 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(1)
- expect(hiddenElements).toHaveLength(2)
- })
-
- 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}}) => {
- expect.assertions(1)
-
- 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')
-
- 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 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'))
-
- expect(await queryByText('Hello h1')).toBeFalsy()
- expect(await queryByText('Hello h3')).toBeTruthy()
- })
-
- test.describe('configuration', () => {
- test.afterEach(() => {
- configure({testIdAttribute: 'data-testid'}) // cleanup
- })
-
- test('should support custom data-testid attribute name', async ({queries}) => {
- configure({testIdAttribute: 'data-id'})
-
- const element = await queries.getByTestId('second-level-header')
-
- expect(await queries.getNodeText(element)).toEqual('Hello h2')
- })
-
- test('should support subsequent changing the data-testid attribute names', async ({
- queries,
- }) => {
- configure({testIdAttribute: 'data-id'})
- configure({testIdAttribute: 'data-new-id'})
-
- 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('should handle the findBy* methods', async ({queries}) => {
- const {findByText} = queries
- expect(await findByText('Loaded!', {}, {timeout: 7000})).toBeTruthy()
- })
-
- test('should handle the findByAll* methods', async ({queries}) => {
- const {findAllByText} = queries
- const elements = await findAllByText(/Hello/, {}, {timeout: 7000})
- expect(elements).toHaveLength(2)
-
- const text = await Promise.all([elements[0].textContent(), elements[1].textContent()])
-
- expect(text).toEqual(['Hello h1', 'Hello h2'])
- })
- })
-})
diff --git a/test/fixture/locators.test.ts b/test/fixture/locators.test.ts
new file mode 100644
index 0000000..6666003
--- /dev/null
+++ b/test/fixture/locators.test.ts
@@ -0,0 +1,349 @@
+import * as path from 'path'
+
+import * as playwright from '@playwright/test'
+
+import {
+ LocatorFixtures as TestingLibraryFixtures,
+ locatorFixtures as fixtures,
+} from '../../lib/fixture'
+
+const test = playwright.test.extend(fixtures)
+
+const {expect} = test
+
+test.describe('lib/fixture.ts (locators)', () => {
+ test.describe('standard page', () => {
+ test.beforeEach(async ({page}) => {
+ await page.goto(`file://${path.join(__dirname, '../fixtures/page.html')}`)
+ })
+
+ test.afterEach(async ({page}) => page.close())
+
+ test('should handle the query* methods', async ({queries: {queryByText}}) => {
+ const locator = queryByText('Hello h1')
+
+ expect(locator).toBeTruthy()
+ expect(await locator.textContent()).toEqual('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')
+ })
+
+ test('should handle regex matching', async ({queries: {queryByText}}) => {
+ const locator = queryByText(/HeLlO h(1|7)/i)
+
+ expect(locator).toBeTruthy()
+ expect(await locator.textContent()).toEqual('Hello h1')
+ })
+
+ test('should handle the get* methods', async ({queries: {getByTestId}}) => {
+ const locator = getByTestId('testid-text-input')
+
+ expect(await locator.evaluate(el => el.outerHTML)).toMatch(
+ ``,
+ )
+ })
+
+ test('handles page navigations', async ({queries: {getByText}, page}) => {
+ await page.goto(`file://${path.join(__dirname, '../fixtures/page.html')}`)
+
+ const locator = getByText('Hello h1')
+
+ expect(await locator.textContent()).toEqual('Hello h1')
+ })
+
+ test('should handle the get* method failures', async ({queries}) => {
+ const {getByTitle} = queries
+ // Use the scoped element so the pretty HTML snapshot is smaller
+
+ await expect(async () => getByTitle('missing').textContent()).rejects.toThrow()
+ })
+
+ test('should handle the LabelText methods', async ({queries}) => {
+ const {getByLabelText} = queries
+ const locator = getByLabelText('Label A')
+
+ /* istanbul ignore next */
+ expect(await locator.evaluate(el => el.outerHTML)).toMatch(
+ ``,
+ )
+ })
+
+ test('should handle the queryAll* methods', async ({queries}) => {
+ const {queryAllByText} = queries
+ const locator = queryAllByText(/Hello/)
+
+ expect(await locator.count()).toEqual(3)
+
+ const text = await Promise.all([
+ locator.nth(0).textContent(),
+ locator.nth(1).textContent(),
+ locator.nth(2).textContent(),
+ ])
+
+ expect(text).toEqual(['Hello h1', 'Hello h2', 'Hello h3'])
+ })
+
+ test('should handle the queryAll* methods with a selector', async ({queries}) => {
+ const {queryAllByText} = queries
+ const locator = queryAllByText(/Hello/, {selector: 'h2'})
+
+ expect(await locator.count()).toEqual(1)
+
+ expect(await locator.textContent()).toEqual('Hello h2')
+ })
+
+ test('should handle the getBy* methods with a selector', async ({queries}) => {
+ const {getByText} = queries
+ const locator = getByText(/Hello/, {selector: '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/})
+
+ expect(await element.textContent()).toEqual('getByRole Test')
+ })
+
+ test('supports `hidden` option when querying by role', async ({queries: {queryAllByRole}}) => {
+ const elements = queryAllByRole('img')
+ const hiddenElements = queryAllByRole('img', {hidden: true})
+
+ expect(await elements.count()).toEqual(1)
+ expect(await hiddenElements.count()).toEqual(2)
+ })
+
+ 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}, within}) => {
+ const form = queryByRole('form', {name: 'User'})
+
+ const {queryByLabelText} = within(form)
+
+ const outerLocator = queryByLabelText('Name')
+ const innerLocator = queryByLabelText('Username')
+
+ expect(await outerLocator.count()).toBe(0)
+ expect(await innerLocator.count()).toBe(1)
+ })
+
+ test('when `Page` instance is provided, `within` returns a `Screen`', async ({
+ page,
+ within,
+ }) => {
+ const screen = within(page)
+
+ await screen.goto(`file://${path.join(__dirname, '../fixtures/page.html')}`)
+
+ const form = screen.queryByRole('form', {name: 'User'})
+
+ const {queryByLabelText} = within(form)
+
+ const outerLocator = queryByLabelText('Name')
+ const innerLocator = queryByLabelText('Username')
+
+ expect(await outerLocator.count()).toBe(0)
+ expect(await innerLocator.count()).toBe(1)
+ })
+
+ 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')
+
+ expect(await locator.textContent()).toEqual('Hello h2')
+ })
+ })
+
+ 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')
+
+ expect(await locator.textContent()).toEqual('Hello h1')
+ })
+ })
+ })
+
+ test('screen fixture responds to Page and Query methods', async ({screen}) => {
+ const locator = screen.getByRole('button', {name: /getBy.*Test/})
+ expect(await locator.textContent()).toEqual('getByRole Test')
+
+ await screen.goto(`file://${path.join(__dirname, '../fixtures/late-page.html')}`)
+
+ const delayedLocator = await screen.findByText('Loaded!', undefined, {timeout: 3000})
+ expect(await delayedLocator.textContent()).toEqual('Loaded!')
+ })
+ })
+
+ 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 locator = await queries.findByText('Loaded!', undefined, {timeout: 3000})
+
+ expect(await locator.textContent()).toEqual('Loaded!')
+ })
+
+ test('should handle the findAllBy* methods', async ({queries}) => {
+ const locator = await queries.findAllByText(/Hello/, undefined, {timeout: 3000})
+
+ const text = await Promise.all([locator.nth(0).textContent(), locator.nth(1).textContent()])
+
+ expect(text).toEqual(['Hello h1', 'Hello h2'])
+ })
+
+ test('throws Testing Library error when locator times out', async ({queries}) => {
+ const query = async () => queries.findByText(/Loaded!/, undefined, {timeout: 500})
+
+ await expect(query).rejects.toThrowError(
+ expect.objectContaining({
+ message: expect.stringContaining('TestingLibraryElementError'),
+ }),
+ )
+ })
+
+ test('throws Playwright error when locator times out for visible state (but is attached)', async ({
+ queries,
+ }) => {
+ const query = async () =>
+ queries.findByText(/Hidden/, undefined, {state: 'visible', timeout: 500})
+
+ await expect(query).rejects.toThrowError(
+ expect.objectContaining({
+ message: expect.stringContaining('500'),
+ }),
+ )
+ })
+
+ test('throws Testing Library error when locator times out for attached state', async ({
+ queries,
+ }) => {
+ const query = async () =>
+ queries.findByText(/Loaded!/, undefined, {state: 'attached', timeout: 500})
+
+ await expect(query).rejects.toThrowError(
+ expect.objectContaining({
+ message: expect.stringContaining('TestingLibraryElementError'),
+ }),
+ )
+ })
+
+ test('throws Testing Library error when multi-element locator times out', async ({queries}) => {
+ const query = async () => queries.findAllByText(/Hello/, undefined, {timeout: 500})
+
+ await expect(query).rejects.toThrowError(
+ expect.objectContaining({
+ message: expect.stringContaining('TestingLibraryElementError'),
+ }),
+ )
+ })
+
+ test.describe('configuring asynchronous queries via `use`', () => {
+ test.use({asyncUtilTimeout: 3000})
+
+ test('reads timeout configuration from `use` configuration', async ({queries, page}) => {
+ // Ensure this test fails if we don't set `timeout` correctly in the `waitFor` in our find query
+ page.setDefaultTimeout(4000)
+
+ const locator = await queries.findByText('Loaded!')
+
+ expect(await locator.textContent()).toEqual('Loaded!')
+ })
+
+ test.describe('with custom test ID attribute from `use`', () => {
+ test.use({testIdAttribute: 'data-customid'})
+
+ test('reads test ID configuration from `use` configuration', async ({queries, page}) => {
+ // Ensure this test fails if we don't set `timeout` correctly in the `waitFor` in our find query
+ page.setDefaultTimeout(4000)
+
+ const locator = await queries.findByTestId('loaded')
+
+ expect(await locator.textContent()).toEqual('Loaded!')
+ })
+ })
+ })
+
+ test('waits for hidden element to be visible when `visible` is passed for state', async ({
+ queries,
+ }) => {
+ await expect(queries.getByText('Hidden')).toBeHidden()
+
+ const locator = await queries.findByText('Hidden', undefined, {
+ timeout: 3000,
+ state: 'visible',
+ })
+
+ expect(await locator.textContent()).toEqual('Hidden')
+ })
+
+ test.describe('configuring asynchronous queries with `visible` state', () => {
+ test.use({asyncUtilExpectedState: 'visible'})
+
+ test('waits for hidden element to be visible', async ({queries}) => {
+ await expect(queries.getByText('Hidden')).toBeHidden()
+
+ const locator = await queries.findByText('Hidden', undefined, {timeout: 3000})
+
+ expect(await locator.textContent()).toEqual('Hidden')
+ })
+ })
+
+ test('waits for hidden element to be attached when `attached` is passed for state', async ({
+ queries,
+ }) => {
+ await expect(queries.queryByText('Attached')).toHaveCount(0)
+
+ const locator = await queries.findByText('Attached', undefined, {
+ timeout: 3000,
+ state: 'attached',
+ })
+
+ expect(await locator.textContent()).toEqual('Attached')
+ await expect(locator).toBeHidden()
+ })
+
+ test.describe('configuring asynchronous queries with `attached` state', () => {
+ test.use({asyncUtilExpectedState: 'attached'})
+
+ test('waits for hidden element to be attached', async ({queries}) => {
+ await expect(queries.queryByText('Attached')).toHaveCount(0)
+
+ const locator = await queries.findByText('Attached', undefined, {timeout: 3000})
+
+ expect(await locator.textContent()).toEqual('Attached')
+ await expect(locator).toBeHidden()
+ })
+ })
+ })
+})
diff --git a/test/fixtures/late-page.html b/test/fixtures/late-page.html
index 87f5474..ea0eae2 100644
--- a/test/fixtures/late-page.html
+++ b/test/fixtures/late-page.html
@@ -2,10 +2,12 @@
Loading...
+ Hidden
diff --git a/test/fixtures/page.html b/test/fixtures/page.html
index a014c3a..c95039f 100644
--- a/test/fixtures/page.html
+++ b/test/fixtures/page.html
@@ -21,10 +21,22 @@ Hello h3
aria-hidden="true"
role="img"
xmlns="http://www.w3.org/2000/svg"
+ width="128px"
viewBox="0 0 512 512"
>