From 30dc57930931e15a0364b70813b385c3da0dd650 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Wed, 7 Aug 2024 13:40:18 +0200 Subject: [PATCH] fix(browser): keep querying elements even if locator is created with elementLocator, add pubic @vitest/browser/utils (#6296) --- .github/workflows/ci.yml | 8 +- packages/browser/package.json | 4 + packages/browser/rollup.config.js | 7 +- .../src/client/tester/locators/index.ts | 12 +- .../src/client/tester/locators/playwright.ts | 14 +- .../src/client/tester/locators/preview.ts | 17 +- .../src/client/tester/locators/webdriverio.ts | 9 +- .../browser/src/client/tester/public-utils.ts | 72 ++++ .../browser/src/client/tester/tester.html | 2 +- packages/browser/src/client/tester/tester.ts | 15 + packages/browser/utils.d.ts | 21 ++ packages/utils/src/display.ts | 6 +- packages/utils/src/index.ts | 1 + pnpm-lock.yaml | 339 ++++++++++++++++-- test/browser/fixtures/locators/query.test.ts | 16 + test/browser/package.json | 1 + test/browser/specs/locators.test.ts | 3 +- .../test/__snapshots__/utils.test.ts.snap | 37 ++ test/browser/test/utils.test.ts | 35 +- 19 files changed, 566 insertions(+), 53 deletions(-) create mode 100644 packages/browser/src/client/tester/public-utils.ts create mode 100644 packages/browser/utils.d.ts create mode 100644 test/browser/fixtures/locators/query.test.ts create mode 100644 test/browser/test/__snapshots__/utils.test.ts.snap diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5b6da83feeda..a25bb0e4609d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,13 +40,15 @@ jobs: strategy: matrix: os: [ubuntu-latest] - node_version: [18, 20] + # Reset back to 20 after https://github.com/nodejs/node/issues/53648 + # (The issues is closed, but the error persist even after 20.14) + node_version: [18, 20.14] # node_version: [18, 20, 22] 22 when LTS is close enough include: - os: macos-14 - node_version: 20 + node_version: 20.14 - os: windows-latest - node_version: 20 + node_version: 20.14 fail-fast: false steps: diff --git a/packages/browser/package.json b/packages/browser/package.json index 323ad8030670..5b38326a7799 100644 --- a/packages/browser/package.json +++ b/packages/browser/package.json @@ -44,6 +44,10 @@ "types": "./dist/locators/index.d.ts", "default": "./dist/locators/index.js" }, + "./utils": { + "types": "./utils.d.ts", + "default": "./dist/utils.js" + }, "./*": "./*" }, "main": "./dist/index.js", diff --git a/packages/browser/rollup.config.js b/packages/browser/rollup.config.js index dde7cfce2ed8..b1b901bbdeb2 100644 --- a/packages/browser/rollup.config.js +++ b/packages/browser/rollup.config.js @@ -66,6 +66,7 @@ export default () => 'locators/webdriverio': './src/client/tester/locators/webdriverio.ts', 'locators/preview': './src/client/tester/locators/preview.ts', 'locators/index': './src/client/tester/locators/index.ts', + 'utils': './src/client/tester/public-utils.ts', }, output: { dir: 'dist', @@ -129,9 +130,11 @@ export default () => ], }, { - input: './src/client/tester/locators/index.ts', + input: { + 'locators/index': './src/client/tester/locators/index.ts', + }, output: { - file: 'dist/locators/index.d.ts', + dir: 'dist', format: 'esm', }, external, diff --git a/packages/browser/src/client/tester/locators/index.ts b/packages/browser/src/client/tester/locators/index.ts index 229e33eeeac7..0816f2fd54dd 100644 --- a/packages/browser/src/client/tester/locators/index.ts +++ b/packages/browser/src/client/tester/locators/index.ts @@ -12,7 +12,6 @@ import type { BrowserRPC } from '@vitest/browser/client' import { Ivya, type ParsedSelector, - asLocator, getByAltTextSelector, getByLabelSelector, getByPlaceholderSelector, @@ -24,6 +23,7 @@ import { import type { WorkerGlobalState } from 'vitest' import type { BrowserRunnerState } from '../../utils' import { getBrowserState, getWorkerState } from '../../utils' +import { getElementError } from '../public-utils' // we prefer using playwright locators because they are more powerful and support Shadow DOM export const selectorEngine = Ivya.create({ @@ -45,8 +45,8 @@ export abstract class Locator { public abstract selector: string private _parsedSelector: ParsedSelector | undefined + protected _container?: Element | undefined protected _pwSelector?: string | undefined - protected _forceElement?: Element | undefined public click(options: UserEventClickOptions = {}): Promise { return this.triggerCommand('__vitest_click', this.selector, options) @@ -143,9 +143,6 @@ export abstract class Locator { } public query(): Element | null { - if (this._forceElement) { - return this._forceElement - } const parsedSelector = this._parsedSelector || (this._parsedSelector = selectorEngine.parseSelector(this._pwSelector || this.selector)) return selectorEngine.querySelector(parsedSelector, document.documentElement, true) } @@ -153,15 +150,12 @@ export abstract class Locator { public element(): Element { const element = this.query() if (!element) { - throw new Error(`element not found: ${asLocator('javascript', this._pwSelector || this.selector)}`) + throw getElementError(this._pwSelector || this.selector, this._container || document.documentElement) } return element } public elements(): Element[] { - if (this._forceElement) { - return [this._forceElement] - } const parsedSelector = this._parsedSelector || (this._parsedSelector = selectorEngine.parseSelector(this._pwSelector || this.selector)) return selectorEngine.querySelectorAll(parsedSelector, document.documentElement) } diff --git a/packages/browser/src/client/tester/locators/playwright.ts b/packages/browser/src/client/tester/locators/playwright.ts index 750f8552dd2a..60e9075a185a 100644 --- a/packages/browser/src/client/tester/locators/playwright.ts +++ b/packages/browser/src/client/tester/locators/playwright.ts @@ -34,20 +34,26 @@ page.extend({ }, elementLocator(element: Element) { - return new PlaywrightLocator(selectorEngine.generateSelectorSimple(element), element) + return new PlaywrightLocator( + selectorEngine.generateSelectorSimple(element), + element, + ) }, }) class PlaywrightLocator extends Locator { - constructor(public selector: string, protected _forceElement?: Element) { + constructor(public selector: string, protected _container?: Element) { super() } protected locator(selector: string) { - return new PlaywrightLocator(`${this.selector} >> ${selector}`) + return new PlaywrightLocator(`${this.selector} >> ${selector}`, this._container) } protected elementLocator(element: Element) { - return new PlaywrightLocator(selectorEngine.generateSelectorSimple(element), element) + return new PlaywrightLocator( + selectorEngine.generateSelectorSimple(element), + element, + ) } } diff --git a/packages/browser/src/client/tester/locators/preview.ts b/packages/browser/src/client/tester/locators/preview.ts index fac183581e1a..f1484af9bef9 100644 --- a/packages/browser/src/client/tester/locators/preview.ts +++ b/packages/browser/src/client/tester/locators/preview.ts @@ -10,6 +10,7 @@ import { getByTitleSelector, } from 'ivya' import { convertElementToCssSelector } from '../../utils' +import { getElementError } from '../public-utils' import { Locator, selectorEngine } from './index' page.extend({ @@ -36,19 +37,22 @@ page.extend({ }, elementLocator(element: Element) { - return new PreviewLocator(selectorEngine.generateSelectorSimple(element), element) + return new PreviewLocator( + selectorEngine.generateSelectorSimple(element), + element, + ) }, }) class PreviewLocator extends Locator { - constructor(protected _pwSelector: string, protected _forceElement?: Element) { + constructor(protected _pwSelector: string, protected _container?: Element) { super() } override get selector() { const selectors = this.elements().map(element => convertElementToCssSelector(element)) if (!selectors.length) { - throw new Error(`element not found: ${this._pwSelector}`) + throw getElementError(this._pwSelector, this._container || document.documentElement) } return selectors.join(', ') } @@ -100,10 +104,13 @@ class PreviewLocator extends Locator { } protected locator(selector: string) { - return new PreviewLocator(`${this._pwSelector} >> ${selector}`) + return new PreviewLocator(`${this._pwSelector} >> ${selector}`, this._container) } protected elementLocator(element: Element) { - return new PreviewLocator(selectorEngine.generateSelectorSimple(element), element) + return new PreviewLocator( + selectorEngine.generateSelectorSimple(element), + element, + ) } } diff --git a/packages/browser/src/client/tester/locators/webdriverio.ts b/packages/browser/src/client/tester/locators/webdriverio.ts index 6e37200f0a56..7313d9493ff5 100644 --- a/packages/browser/src/client/tester/locators/webdriverio.ts +++ b/packages/browser/src/client/tester/locators/webdriverio.ts @@ -9,6 +9,7 @@ import { getByTitleSelector, } from 'ivya' import { convertElementToCssSelector } from '../../utils' +import { getElementError } from '../public-utils' import { Locator, selectorEngine } from './index' page.extend({ @@ -35,19 +36,19 @@ page.extend({ }, elementLocator(element: Element) { - return new WebdriverIOLocator(selectorEngine.generateSelectorSimple(element), element) + return new WebdriverIOLocator(selectorEngine.generateSelectorSimple(element)) }, }) class WebdriverIOLocator extends Locator { - constructor(protected _pwSelector: string, protected _forceElement?: Element) { + constructor(protected _pwSelector: string, protected _container?: Element) { super() } override get selector() { const selectors = this.elements().map(element => convertElementToCssSelector(element)) if (!selectors.length) { - throw new Error(`element not found: ${this._pwSelector}`) + throw getElementError(this._pwSelector, this._container || document.documentElement) } return selectors.join(', ') } @@ -58,7 +59,7 @@ class WebdriverIOLocator extends Locator { } protected locator(selector: string) { - return new WebdriverIOLocator(`${this._pwSelector} >> ${selector}`) + return new WebdriverIOLocator(`${this._pwSelector} >> ${selector}`, this._container) } protected elementLocator(element: Element) { diff --git a/packages/browser/src/client/tester/public-utils.ts b/packages/browser/src/client/tester/public-utils.ts new file mode 100644 index 000000000000..760f957415cf --- /dev/null +++ b/packages/browser/src/client/tester/public-utils.ts @@ -0,0 +1,72 @@ +import { type Locator, type LocatorSelectors, page } from '@vitest/browser/context' +import { type StringifyOptions, stringify } from 'vitest/utils' +import { asLocator } from 'ivya' + +export function getElementLocatorSelectors(element: Element): LocatorSelectors { + const locator = page.elementLocator(element) + return { + getByAltText: (altText, options) => locator.getByAltText(altText, options), + getByLabelText: (labelText, options) => locator.getByLabelText(labelText, options), + getByPlaceholder: (placeholderText, options) => locator.getByPlaceholder(placeholderText, options), + getByRole: (role, options) => locator.getByRole(role, options), + getByTestId: testId => locator.getByTestId(testId), + getByText: (text, options) => locator.getByText(text, options), + getByTitle: (title, options) => locator.getByTitle(title, options), + } +} + +type PrettyDOMOptions = Omit + +export function debug( + el?: Element | Locator | null | (Element | Locator)[], + maxLength?: number, + options?: PrettyDOMOptions, +): void { + if (Array.isArray(el)) { + // eslint-disable-next-line no-console + el.forEach(e => console.log(prettyDOM(e, maxLength, options))) + } + else { + // eslint-disable-next-line no-console + console.log(prettyDOM(el, maxLength, options)) + } +} + +export function prettyDOM( + dom?: Element | Locator | undefined | null, + maxLength: number = Number(import.meta.env.DEBUG_PRINT_LIMIT ?? 7000), + prettyFormatOptions: PrettyDOMOptions = {}, +): string { + if (maxLength === 0) { + return '' + } + + if (!dom) { + dom = document.body + } + + if ('element' in dom && 'all' in dom) { + dom = dom.element() + } + + const type = typeof dom + if (type !== 'object' || !dom.outerHTML) { + const typeName = type === 'object' ? dom.constructor.name : type + throw new TypeError(`Expecting a valid DOM element, but got ${typeName}.`) + } + + const pretty = stringify(dom, Number.POSITIVE_INFINITY, { + maxLength, + highlight: true, + ...prettyFormatOptions, + }) + return dom.outerHTML.length > maxLength + ? `${pretty.slice(0, maxLength)}...` + : pretty +} + +export function getElementError(selector: string, container: Element): Error { + const error = new Error(`Cannot find element with locator: ${asLocator('javascript', selector)}\n\n${prettyDOM(container)}`) + error.name = 'VitestBrowserElementError' + return error +} diff --git a/packages/browser/src/client/tester/tester.html b/packages/browser/src/client/tester/tester.html index f437c975d506..1bf9f3ff32f1 100644 --- a/packages/browser/src/client/tester/tester.html +++ b/packages/browser/src/client/tester/tester.html @@ -21,7 +21,7 @@ {__VITEST_INTERNAL_SCRIPTS__} {__VITEST_SCRIPTS__} - + {__VITEST_APPEND__} diff --git a/packages/browser/src/client/tester/tester.ts b/packages/browser/src/client/tester/tester.ts index cb100a2bb71f..631111c0fc9e 100644 --- a/packages/browser/src/client/tester/tester.ts +++ b/packages/browser/src/client/tester/tester.ts @@ -1,4 +1,5 @@ import { SpyModule, collectTests, setupCommonEnv, startTests } from 'vitest/browser' +import { page } from '@vitest/browser/context' import { channel, client, onCancel } from '@vitest/browser/client' import { getBrowserState, getConfig, getWorkerState } from '../utils' import { setupDialogsSpy } from './dialog' @@ -8,6 +9,8 @@ import { browserHashMap, initiateRunner } from './runner' import { VitestBrowserClientMocker } from './mocker' import { setupExpectDom } from './expect-element' +const cleanupSymbol = Symbol.for('vitest:component-cleanup') + const url = new URL(location.href) const reloadStart = url.searchParams.get('__reloadStart') @@ -123,6 +126,18 @@ async function executeTests(method: 'run' | 'collect', files: string[]) { } } finally { + try { + if (cleanupSymbol in page) { + (page[cleanupSymbol] as any)() + } + } + catch (error: any) { + await client.rpc.onUnhandledError({ + name: error.name, + message: error.message, + stack: String(error.stack), + }, 'Cleanup Error') + } state.environmentTeardownRun = true debug('finished running tests') done(files) diff --git a/packages/browser/utils.d.ts b/packages/browser/utils.d.ts new file mode 100644 index 000000000000..fa8790aeef97 --- /dev/null +++ b/packages/browser/utils.d.ts @@ -0,0 +1,21 @@ +// should be in sync with tester/public-utils.ts +// we cannot bundle it because vitest depend on the @vitest/browser and vise versa +// fortunately, the file is quite small + +import { LocatorSelectors } from '@vitest/browser/context' +import { StringifyOptions } from 'vitest/utils' + +type PrettyDOMOptions = Omit + +export declare function getElementLocatorSelectors(element: Element): LocatorSelectors +export declare function debug( + el?: Element | Locator | null | (Element | Locator)[], + maxLength?: number, + options?: PrettyDOMOptions, +): void +export declare function prettyDOM( + dom?: Element | Locator | undefined | null, + maxLength?: number, + prettyFormatOptions?: PrettyDOMOptions, +): string +export declare function getElementError(selector: string, container?: Element): Error diff --git a/packages/utils/src/display.ts b/packages/utils/src/display.ts index 67c9902b1776..8b89da59cdb1 100644 --- a/packages/utils/src/display.ts +++ b/packages/utils/src/display.ts @@ -41,10 +41,14 @@ const PLUGINS = [ AsymmetricMatcher, ] +export interface StringifyOptions extends PrettyFormatOptions { + maxLength?: number +} + export function stringify( object: unknown, maxDepth = 10, - { maxLength, ...options }: PrettyFormatOptions & { maxLength?: number } = {}, + { maxLength, ...options }: StringifyOptions = {}, ): string { const MAX_LENGTH = maxLength ?? 10000 let result diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 6b87a5c4fcb2..ea8d8456f15d 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -29,6 +29,7 @@ export { inspect, objDisplay, } from './display' +export type { StringifyOptions } from './display' export { positionToOffset, offsetToLineNumber, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ceea91672c41..1acb35bcf8f0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -37,7 +37,7 @@ importers: devDependencies: '@antfu/eslint-config': specifier: ^2.24.1 - version: 2.24.1(@vue/compiler-sfc@3.4.35)(eslint@9.8.0)(svelte@3.59.1)(typescript@5.5.4)(vitest@packages+vitest) + version: 2.24.1(@vue/compiler-sfc@3.4.36)(eslint@9.8.0)(svelte@3.59.1)(typescript@5.5.4)(vitest@packages+vitest) '@antfu/ni': specifier: ^0.22.0 version: 0.22.0 @@ -736,7 +736,7 @@ importers: version: 1.1.44 '@testing-library/vue': specifier: ^8.1.0 - version: 8.1.0(@vue/compiler-sfc@3.4.35)(vue@3.4.35(typescript@5.5.4)) + version: 8.1.0(@vue/compiler-sfc@3.4.36)(vue@3.4.35(typescript@5.5.4)) '@types/codemirror': specifier: ^5.60.15 version: 5.60.15 @@ -802,7 +802,7 @@ importers: version: 5.3.3(@types/node@20.14.14)(terser@5.22.0) vite-plugin-pages: specifier: ^0.32.3 - version: 0.32.3(@vue/compiler-sfc@3.4.35)(vite@5.3.3(@types/node@20.14.14)(terser@5.22.0))(vue-router@4.4.2(vue@3.4.35(typescript@5.5.4))) + version: 0.32.3(@vue/compiler-sfc@3.4.36)(vite@5.3.3(@types/node@20.14.14)(terser@5.22.0))(vue-router@4.4.2(vue@3.4.35(typescript@5.5.4))) vue: specifier: ^3.4.35 version: 3.4.35(typescript@5.5.4) @@ -1102,6 +1102,9 @@ importers: react-dom: specifier: ^18.3.1 version: 18.3.1(react@18.3.1) + strip-ansi: + specifier: ^7.1.0 + version: 7.1.0 url: specifier: ^0.11.3 version: 0.11.3 @@ -1248,7 +1251,7 @@ importers: version: 3.0.3 '@vitejs/plugin-vue': specifier: latest - version: 5.1.2(vite@5.3.3(@types/node@20.14.14)(terser@5.22.0))(vue@3.4.35(typescript@5.5.4)) + version: 5.1.2(vite@5.3.3(@types/node@20.14.14)(terser@5.22.0))(vue@3.4.36(typescript@5.5.4)) '@vitest/browser': specifier: workspace:* version: link:../../packages/browser @@ -1287,10 +1290,10 @@ importers: version: link:../../packages/vitest vue: specifier: latest - version: 3.4.35(typescript@5.5.4) + version: 3.4.36(typescript@5.5.4) webdriverio: specifier: latest - version: 8.39.1(typescript@5.5.4) + version: 8.40.0 test/global-setup: devDependencies: @@ -1408,7 +1411,7 @@ importers: version: link:../../packages/vitest webdriverio: specifier: latest - version: 8.39.1(typescript@5.5.4) + version: 8.40.0 test/workspaces: devDependencies: @@ -3103,6 +3106,11 @@ packages: engines: {node: '>=16.3.0'} hasBin: true + '@puppeteer/browsers@1.9.1': + resolution: {integrity: sha512-PuvK6xZzGhKPvlx3fpfdM2kYY3P/hB1URtK8wA7XUJ6prn6pp22zvJHu48th0SGcHL9SutbPHrFuQgfXTFobWA==} + engines: {node: '>=16.3.0'} + hasBin: true + '@remix-run/router@1.16.0': resolution: {integrity: sha512-Quz1KOffeEf/zwkCBM3kBtH4ZoZ+pT3xIXBG4PPW/XFtDP7EGhtTiC2+gpL9GnR7+Qdet5Oa6cYSvwKYg6kN9Q==} engines: {node: '>=14.0.0'} @@ -4019,6 +4027,9 @@ packages: '@vue/compiler-core@3.4.35': resolution: {integrity: sha512-gKp0zGoLnMYtw4uS/SJRRO7rsVggLjvot3mcctlMXunYNsX+aRJDqqw/lV5/gHK91nvaAAlWFgdVl020AW1Prg==} + '@vue/compiler-core@3.4.36': + resolution: {integrity: sha512-qBkndgpwFKdupmOPoiS10i7oFdN7a+4UNDlezD0GlQ1kuA1pNrscg9g12HnB5E8hrWSuEftRsbJhL1HI2zpJhg==} + '@vue/compiler-dom@3.4.26': resolution: {integrity: sha512-4CWbR5vR9fMg23YqFOhr6t6WB1Fjt62d6xdFPyj8pxrYub7d+OgZaObMsoxaF9yBUHPMiPFK303v61PwAuGvZA==} @@ -4028,18 +4039,27 @@ packages: '@vue/compiler-dom@3.4.35': resolution: {integrity: sha512-pWIZRL76/oE/VMhdv/ovZfmuooEni6JPG1BFe7oLk5DZRo/ImydXijoZl/4kh2406boRQ7lxTYzbZEEXEhj9NQ==} + '@vue/compiler-dom@3.4.36': + resolution: {integrity: sha512-eEIjy4GwwZTFon/Y+WO8tRRNGqylaRlA79T1RLhUpkOzJ7EtZkkb8MurNfkqY6x6Qiu0R7ESspEF7GkPR/4yYg==} + '@vue/compiler-sfc@3.4.26': resolution: {integrity: sha512-It1dp+FAOCgluYSVYlDn5DtZBxk1NCiJJfu2mlQqa/b+k8GL6NG/3/zRbJnHdhV2VhxFghaDq5L4K+1dakW6cw==} '@vue/compiler-sfc@3.4.35': resolution: {integrity: sha512-xacnRS/h/FCsjsMfxBkzjoNxyxEyKyZfBch/P4vkLRvYJwe5ChXmZZrj8Dsed/752H2Q3JE8kYu9Uyha9J6PgA==} + '@vue/compiler-sfc@3.4.36': + resolution: {integrity: sha512-rhuHu7qztt/rNH90dXPTzhB7hLQT2OC4s4GrPVqmzVgPY4XBlfWmcWzn4bIPEWNImt0CjO7kfHAf/1UXOtx3vw==} + '@vue/compiler-ssr@3.4.26': resolution: {integrity: sha512-FNwLfk7LlEPRY/g+nw2VqiDKcnDTVdCfBREekF8X74cPLiWHUX6oldktf/Vx28yh4STNy7t+/yuLoMBBF7YDiQ==} '@vue/compiler-ssr@3.4.35': resolution: {integrity: sha512-7iynB+0KB1AAJKk/biENTV5cRGHRdbdaD7Mx3nWcm1W8bVD6QmnH3B4AHhQQ1qZHhqFwzEzMwiytXm3PX1e60A==} + '@vue/compiler-ssr@3.4.36': + resolution: {integrity: sha512-Wt1zyheF0zVvRJyhY74uxQbnkXV2Le/JPOrAxooR4rFYKC7cFr+cRqW6RU3cM/bsTy7sdZ83IDuy/gLPSfPGng==} + '@vue/devtools-api@6.6.3': resolution: {integrity: sha512-0MiMsFma/HqA6g3KLKn+AGpL1kgKhFWszC9U29NfpWK5LE7bjeXxySWJrOJ77hBz+TBrBQ7o4QJqbPbqbs8rJw==} @@ -4074,18 +4094,27 @@ packages: '@vue/reactivity@3.4.35': resolution: {integrity: sha512-Ggtz7ZZHakriKioveJtPlStYardwQH6VCs9V13/4qjHSQb/teE30LVJNrbBVs4+aoYGtTQKJbTe4CWGxVZrvEw==} + '@vue/reactivity@3.4.36': + resolution: {integrity: sha512-wN1aoCwSoqrt1yt8wO0gc13QaC+Vk1o6AoSt584YHNnz6TGDhh1NCMUYgAnvp4HEIkLdGsaC1bvu/P+wpoDEXw==} + '@vue/runtime-core@3.4.26': resolution: {integrity: sha512-AFJDLpZvhT4ujUgZSIL9pdNcO23qVFh7zWCsNdGQBw8ecLNxOOnPcK9wTTIYCmBJnuPHpukOwo62a2PPivihqw==} '@vue/runtime-core@3.4.35': resolution: {integrity: sha512-D+BAjFoWwT5wtITpSxwqfWZiBClhBbR+bm0VQlWYFOadUUXFo+5wbe9ErXhLvwguPiLZdEF13QAWi2vP3ZD5tA==} + '@vue/runtime-core@3.4.36': + resolution: {integrity: sha512-9+TR14LAVEerZWLOm/N/sG2DVYhrH2bKgFrbH/FVt/Q8Jdw4OtdcGMRC6Tx8VAo0DA1eqAqrZaX0fbOaOxxZ4A==} + '@vue/runtime-dom@3.4.26': resolution: {integrity: sha512-UftYA2hUXR2UOZD/Fc3IndZuCOOJgFxJsWOxDkhfVcwLbsfh2CdXE2tG4jWxBZuDAs9J9PzRTUFt1PgydEtItw==} '@vue/runtime-dom@3.4.35': resolution: {integrity: sha512-yGOlbos+MVhlS5NWBF2HDNgblG8e2MY3+GigHEyR/dREAluvI5tuUUgie3/9XeqhPE4LF0i2wjlduh5thnfOqw==} + '@vue/runtime-dom@3.4.36': + resolution: {integrity: sha512-2Qe2fKkLxgZBVvHrG0QMNLL4bsx7Ae88pyXebY2WnQYABpOnGYvA+axMbcF9QwM4yxnsv+aELbC0eiNVns7mGw==} + '@vue/server-renderer@3.4.26': resolution: {integrity: sha512-xoGAqSjYDPGAeRWxeoYwqJFD/gw7mpgzOvSxEmjWaFO2rE6qpbD1PC172YRpvKhrihkyHJkNDADFXTfCyVGhKw==} peerDependencies: @@ -4096,6 +4125,11 @@ packages: peerDependencies: vue: 3.4.35 + '@vue/server-renderer@3.4.36': + resolution: {integrity: sha512-2XW90Rq8+Y7S1EIsAuubZVLm0gCU8HYb5mRAruFdwfC3XSOU5/YKePz29csFzsch8hXaY5UHh7ZMddmi1XTJEA==} + peerDependencies: + vue: 3.4.36 + '@vue/shared@3.4.26': resolution: {integrity: sha512-Fg4zwR0GNnjzodMt3KRy2AWGMKQXByl56+4HjN87soxLNU9P5xcJkstAlIeEF3cU6UYOzmJl1tV0dVPGIljCnQ==} @@ -4108,6 +4142,9 @@ packages: '@vue/shared@3.4.35': resolution: {integrity: sha512-hvuhBYYDe+b1G8KHxsQ0diDqDMA8D9laxWZhNAjE83VZb5UDaXl9Xnz7cGdDSyiHM90qqI/CyGMcpBpiDy6VVQ==} + '@vue/shared@3.4.36': + resolution: {integrity: sha512-fdPLStwl1sDfYuUftBaUVn2pIrVFDASYerZSrlBvVBfylObPA1gtcWJHy5Ox8jLEJ524zBibss488Q3SZtU1uA==} + '@vue/test-utils@2.4.6': resolution: {integrity: sha512-FMxEjOpYNYiFe0GkaHsnJPXFHxQ6m4t8vI/ElPGpMWxZKpmRvQ33OIrvRXemy6yha03RxhOlQuy+gZMC3CQSow==} @@ -4222,6 +4259,10 @@ packages: resolution: {integrity: sha512-yNuGPMPibY91s936gnJCHWlStvIyDrwLwGfLC/NCdTin4F7HL4Gp5iJnHWkJFty1/DfFi8jjoIUBNLM8HEez+A==} engines: {node: ^16.13 || >=18} + '@wdio/config@8.40.0': + resolution: {integrity: sha512-sE+sBXUz4ZggS253hLNVu64ZCpm5ZidQ/IJNeM9Exh5OcsuZEnSeuqCZnd4ytK68A2heyZk8r2OjYZriA4l/Sg==} + engines: {node: ^16.13 || >=18} + '@wdio/logger@8.28.0': resolution: {integrity: sha512-/s6zNCqwy1hoc+K4SJypis0Ud0dlJ+urOelJFO1x0G0rwDRWyFiUP6ijTaCcFxAm29jYEcEPWijl2xkVIHwOyA==} engines: {node: ^16.13 || >=18} @@ -4256,6 +4297,10 @@ packages: resolution: {integrity: sha512-jY+n6jlGeK+9Tx8T659PKLwMQTGpLW5H78CSEWgZLbjbVSr2LfGR8Lx0CRktNXxAtqEVZPj16Pi74OtAhvhE6Q==} engines: {node: ^16.13 || >=18} + '@wdio/utils@8.40.0': + resolution: {integrity: sha512-P9b6XbRDRfCsZvdA70VYQrnsbkDVwEXlAGe4v4hcdgFxz81w+k4IX5bFUb7IB33E+3EZ/GhJWVU3QHgI9Y0u6w==} + engines: {node: ^16.13 || >=18} + '@yeger/debounce@2.0.9': resolution: {integrity: sha512-yapSa71O56W0zotDlgv7z/equgK61Ozb8rSEWsNX7oN543oUMucWVWIlDp73/Jg7D08xAkw+E23OVLe1xIBS7A==} @@ -4707,6 +4752,11 @@ packages: peerDependencies: devtools-protocol: '*' + chromium-bidi@0.5.8: + resolution: {integrity: sha512-blqh+1cEQbHBKmok3rVJkBlBxt9beKBgOsxbFgs7UJcoVbbeZ+K7+6liAsjgpc8l1Xd55cQUy14fXZdGSb4zIw==} + peerDependencies: + devtools-protocol: '*' + ci-info@3.9.0: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} @@ -5168,12 +5218,18 @@ packages: devtools-protocol@0.0.1147663: resolution: {integrity: sha512-hyWmRrexdhbZ1tcJUGpO95ivbRhWXz++F4Ko+n21AY5PNln2ovoJw+8ZMNDTtip+CNFQfrtLVh/w4009dXO/eQ==} + devtools-protocol@0.0.1232444: + resolution: {integrity: sha512-pM27vqEfxSxRkTMnF+XCmxSEb6duO5R+t8A9DEEJgy4Wz2RVanje2mmj99B6A3zv2r/qGfYlOvYznUhuokizmg==} + devtools-protocol@0.0.1261483: resolution: {integrity: sha512-7vJvejpzA5DTfZVkr7a8sGpEAzEiAqcgmRTB0LSUrWeOicwL09lMQTzxHtFNVhJ1OOJkgYdH6Txvy9E5j3VOUQ==} devtools-protocol@0.0.1302984: resolution: {integrity: sha512-Rgh2Sk5fUSCtEx4QGH9iwTyECdFPySG2nlz5J8guGh2Wlha6uzSOCq/DCEC8faHlLaMPZJMuZ4ovgcX4LvOkKA==} + devtools-protocol@0.0.1335233: + resolution: {integrity: sha512-bNTJw/m+v0JvQEsaI0l+i6mETHHf7VwZbQzT5GNSveGuYjip8uyjeF/qg84bsIPU+lFypnZr10a+cbcee6I8pg==} + dezalgo@1.0.4: resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==} @@ -5278,6 +5334,10 @@ packages: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} + entities@5.0.0: + resolution: {integrity: sha512-BeJFvFRJddxobhvEdm5GqHzRV/X+ACeuw0/BuuxsCh1EUZcAIz8+kYmBp/LrQuloy6K1f3a0M7+IhmZ7QnkISA==} + engines: {node: '>=0.12'} + error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} @@ -7527,6 +7587,10 @@ packages: resolution: {integrity: sha512-0LdR757eTj/JfuU7TL2YCuAZnxWXu3tkJbg4Oq3geW/qFNT/32T0sp2HnZ9O0lMR4q3vwAt0+xCA8SR0WAD0og==} engines: {node: '>= 14'} + proxy-agent@6.3.1: + resolution: {integrity: sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==} + engines: {node: '>= 14'} + proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} @@ -7555,6 +7619,10 @@ packages: typescript: optional: true + puppeteer-core@21.11.0: + resolution: {integrity: sha512-ArbnyA3U5SGHokEvkfWjW+O8hOxV1RSJxOgriX/3A4xZRqixt9ZFHD0yPgZQF05Qj0oAqi8H/7stDorjoHY90Q==} + engines: {node: '>=16.13.2'} + qs@6.10.3: resolution: {integrity: sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==} engines: {node: '>=0.6'} @@ -8750,6 +8818,9 @@ packages: url@0.11.3: resolution: {integrity: sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==} + urlpattern-polyfill@10.0.0: + resolution: {integrity: sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==} + use-sync-external-store@1.2.0: resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} peerDependencies: @@ -8976,6 +9047,14 @@ packages: typescript: optional: true + vue@3.4.36: + resolution: {integrity: sha512-mIFvbLgjODfx3Iy1SrxOsiPpDb8Bo3EU+87ioimOZzZTOp15IEdAels70IjBOLO3ZFlLW5AhdwY4dWbXVQKYow==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + w3c-xmlserializer@5.0.0: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} @@ -9003,6 +9082,10 @@ packages: resolution: {integrity: sha512-Kc3+SfiH4ufyrIht683VT2vnJocx0pfH8rYdyPvEh1b2OYewtFTHK36k9rBDHZiBmk6jcSXs4M2xeFgOuon9Lg==} engines: {node: ^16.13 || >=18} + webdriver@8.40.0: + resolution: {integrity: sha512-pAuU8FbFXox837UgxjC2yT4s+goLBcqohdCSZJ1f1wG/XMsgjDHmouU6+f1SHHG7/I0IDGEZIsRD01RM57F3OA==} + engines: {node: ^16.13 || >=18} + webdriverio@8.32.2: resolution: {integrity: sha512-Z0Wc/dHFfWGWJZpaQ8u910/LG0E9EIVTO7J5yjqWx2XtXz2LzQMxYwNRnvNLhY/1tI4y/cZxI6kFMWr8wD2TtA==} engines: {node: ^16.13 || >=18} @@ -9021,6 +9104,15 @@ packages: devtools: optional: true + webdriverio@8.40.0: + resolution: {integrity: sha512-AYFLdfVt3wcDdnyxRDBlysOgB3XryLZrZdmtjUU842IyMcoV4Cq3SdVgz9aj9tskSeIJ3G37KgDEf5znnd5f3Q==} + engines: {node: ^16.13 || >=18} + peerDependencies: + devtools: ^8.14.0 + peerDependenciesMeta: + devtools: + optional: true + webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} @@ -9394,7 +9486,7 @@ snapshots: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - '@antfu/eslint-config@2.24.1(@vue/compiler-sfc@3.4.35)(eslint@9.8.0)(svelte@3.59.1)(typescript@5.5.4)(vitest@packages+vitest)': + '@antfu/eslint-config@2.24.1(@vue/compiler-sfc@3.4.36)(eslint@9.8.0)(svelte@3.59.1)(typescript@5.5.4)(vitest@packages+vitest)': dependencies: '@antfu/install-pkg': 0.3.3 '@clack/prompts': 0.7.0 @@ -9422,7 +9514,7 @@ snapshots: eslint-plugin-vitest: 0.5.4(@typescript-eslint/eslint-plugin@8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.8.0)(typescript@5.5.4))(eslint@9.8.0)(typescript@5.5.4))(eslint@9.8.0)(typescript@5.5.4)(vitest@packages+vitest) eslint-plugin-vue: 9.27.0(eslint@9.8.0) eslint-plugin-yml: 1.14.0(eslint@9.8.0) - eslint-processor-vue-blocks: 0.1.2(@vue/compiler-sfc@3.4.35)(eslint@9.8.0) + eslint-processor-vue-blocks: 0.1.2(@vue/compiler-sfc@3.4.36)(eslint@9.8.0) globals: 15.8.0 jsonc-eslint-parser: 2.4.0 local-pkg: 0.5.0 @@ -9579,7 +9671,7 @@ snapshots: '@babel/generator@7.24.10': dependencies: - '@babel/types': 7.24.9 + '@babel/types': 7.25.2 '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 jsesc: 2.5.2 @@ -9716,7 +9808,7 @@ snapshots: '@babel/helper-member-expression-to-functions@7.24.7': dependencies: '@babel/traverse': 7.24.8 - '@babel/types': 7.24.9 + '@babel/types': 7.25.2 transitivePeerDependencies: - supports-color @@ -9802,7 +9894,7 @@ snapshots: '@babel/helper-optimise-call-expression@7.24.7': dependencies: - '@babel/types': 7.24.9 + '@babel/types': 7.25.2 '@babel/helper-plugin-utils@7.24.0': {} @@ -9843,7 +9935,7 @@ snapshots: '@babel/helper-skip-transparent-expression-wrappers@7.24.7': dependencies: '@babel/traverse': 7.24.8 - '@babel/types': 7.24.9 + '@babel/types': 7.25.2 transitivePeerDependencies: - supports-color @@ -10602,8 +10694,8 @@ snapshots: '@babel/helper-function-name': 7.24.7 '@babel/helper-hoist-variables': 7.24.7 '@babel/helper-split-export-declaration': 7.24.7 - '@babel/parser': 7.24.8 - '@babel/types': 7.24.9 + '@babel/parser': 7.25.3 + '@babel/types': 7.25.2 debug: 4.3.6 globals: 11.12.0 transitivePeerDependencies: @@ -11242,6 +11334,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@puppeteer/browsers@1.9.1': + dependencies: + debug: 4.3.4 + extract-zip: 2.0.1 + progress: 2.0.3 + proxy-agent: 6.3.1 + tar-fs: 3.0.4 + unbzip2-stream: 1.4.3 + yargs: 17.7.2 + transitivePeerDependencies: + - supports-color + '@remix-run/router@1.16.0': {} '@rollup/plugin-babel@5.3.1(@babel/core@7.25.2)(@types/babel__core@7.20.5)(rollup@4.20.0)': @@ -11693,14 +11797,14 @@ snapshots: dependencies: '@testing-library/dom': 10.4.0 - '@testing-library/vue@8.1.0(@vue/compiler-sfc@3.4.35)(vue@3.4.35(typescript@5.5.4))': + '@testing-library/vue@8.1.0(@vue/compiler-sfc@3.4.36)(vue@3.4.35(typescript@5.5.4))': dependencies: '@babel/runtime': 7.24.4 '@testing-library/dom': 9.3.4 '@vue/test-utils': 2.4.6 vue: 3.4.35(typescript@5.5.4) optionalDependencies: - '@vue/compiler-sfc': 3.4.35 + '@vue/compiler-sfc': 3.4.36 '@tootallnate/quickjs-emscripten@0.23.0': {} @@ -12284,6 +12388,11 @@ snapshots: vite: 5.3.3(@types/node@20.14.14)(terser@5.22.0) vue: 3.4.35(typescript@5.5.4) + '@vitejs/plugin-vue@5.1.2(vite@5.3.3(@types/node@20.14.14)(terser@5.22.0))(vue@3.4.36(typescript@5.5.4))': + dependencies: + vite: 5.3.3(@types/node@20.14.14)(terser@5.22.0) + vue: 3.4.36(typescript@5.5.4) + '@vitest/browser@2.0.5(playwright@1.45.3)(typescript@5.5.4)(vitest@packages+vitest)(webdriverio@8.32.2(typescript@5.5.4))': dependencies: '@testing-library/dom': 10.4.0 @@ -12360,7 +12469,7 @@ snapshots: '@vue/compiler-core@3.4.33': dependencies: - '@babel/parser': 7.24.8 + '@babel/parser': 7.25.3 '@vue/shared': 3.4.33 entities: 4.5.0 estree-walker: 2.0.2 @@ -12374,6 +12483,14 @@ snapshots: estree-walker: 2.0.2 source-map-js: 1.2.0 + '@vue/compiler-core@3.4.36': + dependencies: + '@babel/parser': 7.25.3 + '@vue/shared': 3.4.36 + entities: 5.0.0 + estree-walker: 2.0.2 + source-map-js: 1.2.0 + '@vue/compiler-dom@3.4.26': dependencies: '@vue/compiler-core': 3.4.26 @@ -12389,6 +12506,11 @@ snapshots: '@vue/compiler-core': 3.4.35 '@vue/shared': 3.4.35 + '@vue/compiler-dom@3.4.36': + dependencies: + '@vue/compiler-core': 3.4.36 + '@vue/shared': 3.4.36 + '@vue/compiler-sfc@3.4.26': dependencies: '@babel/parser': 7.24.4 @@ -12413,6 +12535,18 @@ snapshots: postcss: 8.4.40 source-map-js: 1.2.0 + '@vue/compiler-sfc@3.4.36': + dependencies: + '@babel/parser': 7.25.3 + '@vue/compiler-core': 3.4.36 + '@vue/compiler-dom': 3.4.36 + '@vue/compiler-ssr': 3.4.36 + '@vue/shared': 3.4.36 + estree-walker: 2.0.2 + magic-string: 0.30.11 + postcss: 8.4.40 + source-map-js: 1.2.0 + '@vue/compiler-ssr@3.4.26': dependencies: '@vue/compiler-dom': 3.4.26 @@ -12423,6 +12557,11 @@ snapshots: '@vue/compiler-dom': 3.4.35 '@vue/shared': 3.4.35 + '@vue/compiler-ssr@3.4.36': + dependencies: + '@vue/compiler-dom': 3.4.36 + '@vue/shared': 3.4.36 + '@vue/devtools-api@6.6.3': {} '@vue/devtools-api@7.3.6': @@ -12477,6 +12616,10 @@ snapshots: dependencies: '@vue/shared': 3.4.35 + '@vue/reactivity@3.4.36': + dependencies: + '@vue/shared': 3.4.36 + '@vue/runtime-core@3.4.26': dependencies: '@vue/reactivity': 3.4.26 @@ -12487,6 +12630,11 @@ snapshots: '@vue/reactivity': 3.4.35 '@vue/shared': 3.4.35 + '@vue/runtime-core@3.4.36': + dependencies: + '@vue/reactivity': 3.4.36 + '@vue/shared': 3.4.36 + '@vue/runtime-dom@3.4.26': dependencies: '@vue/runtime-core': 3.4.26 @@ -12500,6 +12648,13 @@ snapshots: '@vue/shared': 3.4.35 csstype: 3.1.3 + '@vue/runtime-dom@3.4.36': + dependencies: + '@vue/reactivity': 3.4.36 + '@vue/runtime-core': 3.4.36 + '@vue/shared': 3.4.36 + csstype: 3.1.3 + '@vue/server-renderer@3.4.26(vue@3.4.26(typescript@5.5.4))': dependencies: '@vue/compiler-ssr': 3.4.26 @@ -12512,6 +12667,12 @@ snapshots: '@vue/shared': 3.4.35 vue: 3.4.35(typescript@5.5.4) + '@vue/server-renderer@3.4.36(vue@3.4.36(typescript@5.5.4))': + dependencies: + '@vue/compiler-ssr': 3.4.36 + '@vue/shared': 3.4.36 + vue: 3.4.36(typescript@5.5.4) + '@vue/shared@3.4.26': {} '@vue/shared@3.4.31': {} @@ -12520,6 +12681,8 @@ snapshots: '@vue/shared@3.4.35': {} + '@vue/shared@3.4.36': {} + '@vue/test-utils@2.4.6': dependencies: js-beautify: 1.15.1 @@ -12617,6 +12780,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@wdio/config@8.40.0': + dependencies: + '@wdio/logger': 8.38.0 + '@wdio/types': 8.39.0 + '@wdio/utils': 8.40.0 + decamelize: 6.0.0 + deepmerge-ts: 5.1.0 + glob: 10.4.1 + import-meta-resolve: 4.0.0 + transitivePeerDependencies: + - supports-color + '@wdio/logger@8.28.0': dependencies: chalk: 5.3.0 @@ -12683,6 +12858,24 @@ snapshots: transitivePeerDependencies: - supports-color + '@wdio/utils@8.40.0': + dependencies: + '@puppeteer/browsers': 1.7.0 + '@wdio/logger': 8.38.0 + '@wdio/types': 8.39.0 + decamelize: 6.0.0 + deepmerge-ts: 5.1.0 + edgedriver: 5.6.0 + geckodriver: 4.3.2 + get-port: 7.0.0 + import-meta-resolve: 4.0.0 + locate-app: 2.1.0 + safaridriver: 0.1.2 + split2: 4.2.0 + wait-port: 1.0.4 + transitivePeerDependencies: + - supports-color + '@yeger/debounce@2.0.9': {} '@zip.js/zip.js@2.7.45': {} @@ -13189,6 +13382,12 @@ snapshots: devtools-protocol: 0.0.1147663 mitt: 3.0.0 + chromium-bidi@0.5.8(devtools-protocol@0.0.1232444): + dependencies: + devtools-protocol: 0.0.1232444 + mitt: 3.0.1 + urlpattern-polyfill: 10.0.0 + ci-info@3.9.0: {} ci-info@4.0.0: {} @@ -13602,10 +13801,14 @@ snapshots: devtools-protocol@0.0.1147663: {} + devtools-protocol@0.0.1232444: {} + devtools-protocol@0.0.1261483: {} devtools-protocol@0.0.1302984: {} + devtools-protocol@0.0.1335233: {} + dezalgo@1.0.4: dependencies: asap: 2.0.6 @@ -13709,6 +13912,8 @@ snapshots: entities@4.5.0: {} + entities@5.0.0: {} + error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 @@ -14104,9 +14309,9 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-processor-vue-blocks@0.1.2(@vue/compiler-sfc@3.4.35)(eslint@9.8.0): + eslint-processor-vue-blocks@0.1.2(@vue/compiler-sfc@3.4.36)(eslint@9.8.0): dependencies: - '@vue/compiler-sfc': 3.4.35 + '@vue/compiler-sfc': 3.4.36 eslint: 9.8.0 eslint-rule-composer@0.3.0: {} @@ -16484,6 +16689,19 @@ snapshots: transitivePeerDependencies: - supports-color + proxy-agent@6.3.1: + dependencies: + agent-base: 7.1.0 + debug: 4.3.6 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.5 + lru-cache: 7.18.3 + pac-proxy-agent: 7.0.1 + proxy-from-env: 1.1.0 + socks-proxy-agent: 8.0.2 + transitivePeerDependencies: + - supports-color + proxy-from-env@1.1.0: {} psl@1.9.0: {} @@ -16515,6 +16733,20 @@ snapshots: - supports-color - utf-8-validate + puppeteer-core@21.11.0: + dependencies: + '@puppeteer/browsers': 1.9.1 + chromium-bidi: 0.5.8(devtools-protocol@0.0.1232444) + cross-fetch: 4.0.0 + debug: 4.3.4 + devtools-protocol: 0.0.1232444 + ws: 8.16.0 + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - utf-8-validate + qs@6.10.3: dependencies: side-channel: 1.0.4 @@ -17875,6 +18107,8 @@ snapshots: punycode: 1.4.1 qs: 6.11.2 + urlpattern-polyfill@10.0.0: {} + use-sync-external-store@1.2.0(react@18.3.1): dependencies: react: 18.3.1 @@ -17915,7 +18149,7 @@ snapshots: unist-util-stringify-position: 4.0.0 vfile-message: 4.0.2 - vite-plugin-pages@0.32.3(@vue/compiler-sfc@3.4.35)(vite@5.3.3(@types/node@20.14.14)(terser@5.22.0))(vue-router@4.4.2(vue@3.4.35(typescript@5.5.4))): + vite-plugin-pages@0.32.3(@vue/compiler-sfc@3.4.36)(vite@5.3.3(@types/node@20.14.14)(terser@5.22.0))(vue-router@4.4.2(vue@3.4.35(typescript@5.5.4))): dependencies: '@types/debug': 4.1.12 debug: 4.3.6 @@ -17928,7 +18162,7 @@ snapshots: vite: 5.3.3(@types/node@20.14.14)(terser@5.22.0) yaml: 2.4.5 optionalDependencies: - '@vue/compiler-sfc': 3.4.35 + '@vue/compiler-sfc': 3.4.36 vue-router: 4.4.2(vue@3.4.35(typescript@5.5.4)) transitivePeerDependencies: - supports-color @@ -18125,6 +18359,16 @@ snapshots: optionalDependencies: typescript: 5.5.4 + vue@3.4.36(typescript@5.5.4): + dependencies: + '@vue/compiler-dom': 3.4.36 + '@vue/compiler-sfc': 3.4.36 + '@vue/runtime-dom': 3.4.36 + '@vue/server-renderer': 3.4.36(vue@3.4.36(typescript@5.5.4)) + '@vue/shared': 3.4.36 + optionalDependencies: + typescript: 5.5.4 + w3c-xmlserializer@5.0.0: dependencies: xml-name-validator: 5.0.0 @@ -18183,6 +18427,24 @@ snapshots: - supports-color - utf-8-validate + webdriver@8.40.0: + dependencies: + '@types/node': 20.14.14 + '@types/ws': 8.5.12 + '@wdio/config': 8.40.0 + '@wdio/logger': 8.38.0 + '@wdio/protocols': 8.38.0 + '@wdio/types': 8.39.0 + '@wdio/utils': 8.40.0 + deepmerge-ts: 5.1.0 + got: 12.6.1 + ky: 0.33.3 + ws: 8.18.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + webdriverio@8.32.2(typescript@5.5.4): dependencies: '@types/node': 20.14.13 @@ -18250,6 +18512,39 @@ snapshots: - typescript - utf-8-validate + webdriverio@8.40.0: + dependencies: + '@types/node': 20.14.13 + '@wdio/config': 8.40.0 + '@wdio/logger': 8.38.0 + '@wdio/protocols': 8.38.0 + '@wdio/repl': 8.24.12 + '@wdio/types': 8.39.0 + '@wdio/utils': 8.40.0 + archiver: 7.0.1 + aria-query: 5.3.0 + css-shorthand-properties: 1.1.1 + css-value: 0.0.1 + devtools-protocol: 0.0.1335233 + grapheme-splitter: 1.0.4 + import-meta-resolve: 4.0.0 + is-plain-obj: 4.1.0 + jszip: 3.10.1 + lodash.clonedeep: 4.5.0 + lodash.zip: 4.2.0 + minimatch: 9.0.5 + puppeteer-core: 21.11.0 + query-selector-shadow-dom: 1.0.1 + resq: 1.11.0 + rgb2hex: 0.2.5 + serialize-error: 11.0.2 + webdriver: 8.40.0 + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - utf-8-validate + webidl-conversions@3.0.1: {} webidl-conversions@4.0.2: {} diff --git a/test/browser/fixtures/locators/query.test.ts b/test/browser/fixtures/locators/query.test.ts new file mode 100644 index 000000000000..4b74bd6bac70 --- /dev/null +++ b/test/browser/fixtures/locators/query.test.ts @@ -0,0 +1,16 @@ +import { page } from '@vitest/browser/context'; +import { afterEach, expect, test } from 'vitest'; + +afterEach(() => { + document.body.innerHTML = '' +}) + +test('can find a body element', () => { + expect(page.elementLocator(document.body).element()).toBe(document.body); +}) + +test('can find elements inside the body', () => { + document.body.innerHTML = '
hello
' + const screen = page.elementLocator(document.body) + expect(screen.getByText('hello').element()).toBe(document.querySelector('span')); +}) \ No newline at end of file diff --git a/test/browser/package.json b/test/browser/package.json index 173e6c7cdd5a..57609afb6308 100644 --- a/test/browser/package.json +++ b/test/browser/package.json @@ -29,6 +29,7 @@ "playwright": "^1.41.0", "react": "^18.3.1", "react-dom": "^18.3.1", + "strip-ansi": "^7.1.0", "url": "^0.11.3", "vitest": "workspace:*", "webdriverio": "^8.32.2" diff --git a/test/browser/specs/locators.test.ts b/test/browser/specs/locators.test.ts index 1a9a615dbfbf..753926422536 100644 --- a/test/browser/specs/locators.test.ts +++ b/test/browser/specs/locators.test.ts @@ -9,5 +9,6 @@ test('locators work correctly', async () => { expect(stderr).toBe('') expect(stdout).toContain('✓ blog.test.tsx') - expect(stdout).toContain('1 passed (1)') + expect(stdout).toContain('✓ query.test.ts') + expect(stdout).toContain('Test Files 2 passed (2)') }) diff --git a/test/browser/test/__snapshots__/utils.test.ts.snap b/test/browser/test/__snapshots__/utils.test.ts.snap new file mode 100644 index 000000000000..c0ab66b34255 --- /dev/null +++ b/test/browser/test/__snapshots__/utils.test.ts.snap @@ -0,0 +1,37 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`prints default document 1`] = `""`; + +exports[`prints default document 2`] = ` +" +
+ + hello + +
+" +`; + +exports[`prints the element 1`] = ` +" +
+ + hello + +
+" +`; + +exports[`prints the element with attributes 1`] = ` +" +
+ + hello + +
+" +`; diff --git a/test/browser/test/utils.test.ts b/test/browser/test/utils.test.ts index 1e004a202c12..35da40c046c8 100644 --- a/test/browser/test/utils.test.ts +++ b/test/browser/test/utils.test.ts @@ -1,6 +1,39 @@ import { inspect } from 'vitest/utils' -import { expect, it } from 'vitest' +import { afterEach, expect, it, test } from 'vitest' +import stripAnsi from 'strip-ansi' + +import { prettyDOM } from '@vitest/browser/utils' + +afterEach(() => { + document.body.innerHTML = '' +}) it('utils package correctly uses loupe', async () => { expect(inspect({ test: 1 })).toBe('{ test: 1 }') }) + +test('prints default document', () => { + expect(stripAnsi(prettyDOM())).toMatchSnapshot() + + const div = document.createElement('div') + div.innerHTML = 'hello' + document.body.append(div) + + expect(stripAnsi(prettyDOM())).toMatchSnapshot() +}) + +test('prints the element', () => { + const div = document.createElement('div') + div.innerHTML = 'hello' + document.body.append(div) + + expect(stripAnsi(prettyDOM())).toMatchSnapshot() +}) + +test('prints the element with attributes', () => { + const div = document.createElement('div') + div.innerHTML = 'hello' + document.body.append(div) + + expect(stripAnsi(prettyDOM())).toMatchSnapshot() +})