diff --git a/packages/e2e-cypress/src/templates/base/src/components/QuasarCheckComponents.vue b/packages/e2e-cypress/src/templates/base/src/components/QuasarCheckComponents.vue
index 2f6cab85..b819f74b 100644
--- a/packages/e2e-cypress/src/templates/base/src/components/QuasarCheckComponents.vue
+++ b/packages/e2e-cypress/src/templates/base/src/components/QuasarCheckComponents.vue
@@ -1,9 +1,9 @@
-
-
+
+
- Value1
- Value2
+ Value1
+ Value2
diff --git a/packages/e2e-cypress/src/templates/base/src/components/QuasarDate.vue b/packages/e2e-cypress/src/templates/base/src/components/QuasarDate.vue
index b6a20f78..91b709ed 100644
--- a/packages/e2e-cypress/src/templates/base/src/components/QuasarDate.vue
+++ b/packages/e2e-cypress/src/templates/base/src/components/QuasarDate.vue
@@ -1,11 +1,12 @@
-
+
-
+
diff --git a/packages/e2e-cypress/src/templates/base/src/components/QuasarDialog.vue b/packages/e2e-cypress/src/templates/base/src/components/QuasarDialog.vue
index 600f8507..6b034db4 100644
--- a/packages/e2e-cypress/src/templates/base/src/components/QuasarDialog.vue
+++ b/packages/e2e-cypress/src/templates/base/src/components/QuasarDialog.vue
@@ -8,6 +8,7 @@
- Am I on screen?
+ Am I on screen?
diff --git a/packages/e2e-cypress/src/templates/base/src/components/QuasarMenu.vue b/packages/e2e-cypress/src/templates/base/src/components/QuasarMenu.vue
index 746613de..681574b0 100644
--- a/packages/e2e-cypress/src/templates/base/src/components/QuasarMenu.vue
+++ b/packages/e2e-cypress/src/templates/base/src/components/QuasarMenu.vue
@@ -1,5 +1,5 @@
-
+
@@ -19,4 +19,4 @@ import { defineComponent } from 'vue';
export default defineComponent({
name: 'QuasarMenu',
});
-
\ No newline at end of file
+
diff --git a/packages/e2e-cypress/src/templates/base/src/components/QuasarPageSticky.vue b/packages/e2e-cypress/src/templates/base/src/components/QuasarPageSticky.vue
index fb4981c4..42c5e789 100644
--- a/packages/e2e-cypress/src/templates/base/src/components/QuasarPageSticky.vue
+++ b/packages/e2e-cypress/src/templates/base/src/components/QuasarPageSticky.vue
@@ -1,6 +1,6 @@
-
+
{{ title }}
diff --git a/packages/e2e-cypress/src/templates/base/src/components/QuasarSelect.vue b/packages/e2e-cypress/src/templates/base/src/components/QuasarSelect.vue
index a130e768..896aad47 100644
--- a/packages/e2e-cypress/src/templates/base/src/components/QuasarSelect.vue
+++ b/packages/e2e-cypress/src/templates/base/src/components/QuasarSelect.vue
@@ -2,6 +2,7 @@
- {{ selected }}
+ {{ selected }}
diff --git a/packages/e2e-playwright/src/templates/component-test/src/components/AppCheckComponents.vue b/packages/e2e-playwright/src/templates/component-test/src/components/AppCheckComponents.vue
new file mode 100644
index 00000000..07aafdb4
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/component-test/src/components/AppCheckComponents.vue
@@ -0,0 +1,27 @@
+
+
+
+
+ Value1
+ Value2
+
+
+
+
diff --git a/packages/e2e-playwright/src/templates/component-test/src/components/AppDark.vue b/packages/e2e-playwright/src/templates/component-test/src/components/AppDark.vue
new file mode 100644
index 00000000..7379d52e
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/component-test/src/components/AppDark.vue
@@ -0,0 +1,35 @@
+
+
+ {{ $q.dark.isActive ? 'Dark ' : 'Light' }} content
+
+
+
+
+
+
diff --git a/packages/e2e-playwright/src/templates/component-test/src/components/AppDate.vue b/packages/e2e-playwright/src/templates/component-test/src/components/AppDate.vue
new file mode 100644
index 00000000..c7992f72
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/component-test/src/components/AppDate.vue
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/e2e-playwright/src/templates/component-test/src/components/AppDialog.vue b/packages/e2e-playwright/src/templates/component-test/src/components/AppDialog.vue
new file mode 100644
index 00000000..b954d1c7
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/component-test/src/components/AppDialog.vue
@@ -0,0 +1,65 @@
+
+
+
+
+ {{ message }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/e2e-playwright/src/templates/component-test/src/components/AppDrawer.vue b/packages/e2e-playwright/src/templates/component-test/src/components/AppDrawer.vue
new file mode 100644
index 00000000..8c6a01b2
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/component-test/src/components/AppDrawer.vue
@@ -0,0 +1,33 @@
+
+
+
+
+ Am I on screen?
+
+
+
+
+
diff --git a/packages/e2e-playwright/src/templates/component-test/src/components/AppMenu.vue b/packages/e2e-playwright/src/templates/component-test/src/components/AppMenu.vue
new file mode 100644
index 00000000..dee88d6a
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/component-test/src/components/AppMenu.vue
@@ -0,0 +1,22 @@
+
+
+
+
+
+ Item 1
+
+
+ Item 2
+
+
+
+
+
+
+
diff --git a/packages/e2e-playwright/src/templates/component-test/src/components/AppPageSticky.vue b/packages/e2e-playwright/src/templates/component-test/src/components/AppPageSticky.vue
new file mode 100644
index 00000000..3c68eb2a
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/component-test/src/components/AppPageSticky.vue
@@ -0,0 +1,21 @@
+
+
+
+ {{ title }}
+
+
+
+
+
diff --git a/packages/e2e-playwright/src/templates/component-test/src/components/AppSelect.vue b/packages/e2e-playwright/src/templates/component-test/src/components/AppSelect.vue
new file mode 100644
index 00000000..18e25400
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/component-test/src/components/AppSelect.vue
@@ -0,0 +1,54 @@
+
+
+
+ {{ selected }}
+
+
+
diff --git a/packages/e2e-playwright/src/templates/component-test/src/components/AppTooltip.vue b/packages/e2e-playwright/src/templates/component-test/src/components/AppTooltip.vue
new file mode 100644
index 00000000..846ce654
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/component-test/src/components/AppTooltip.vue
@@ -0,0 +1,23 @@
+
+
+ Button
+
+ Here I am!
+
+
+
+
+
diff --git a/packages/e2e-playwright/src/templates/component-test/src/components/color-assertions.vue b/packages/e2e-playwright/src/templates/component-test/src/components/color-assertions.vue
new file mode 100644
index 00000000..841cd639
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/component-test/src/components/color-assertions.vue
@@ -0,0 +1,3 @@
+
+ Text1
+
diff --git a/packages/e2e-playwright/src/templates/github-workflow/.github/workflows/playwright.yml b/packages/e2e-playwright/src/templates/github-workflow/.github/workflows/playwright.yml
new file mode 100644
index 00000000..c18fe4c5
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/github-workflow/.github/workflows/playwright.yml
@@ -0,0 +1,27 @@
+name: Playwright Tests
+on:
+ push:
+ branches: [main, master]
+ pull_request:
+ branches: [main, master]
+jobs:
+ test:
+ timeout-minutes: 60
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 22.x
+ - name: Install dependencies
+ run: npm install -g pnpm && pnpm install
+ - name: Install Playwright Browsers
+ run: pnpm exec playwright install --with-deps
+ - name: Run Playwright tests
+ run: pnpm exec playwright test
+ - uses: actions/upload-artifact@v4
+ if: ${{ !cancelled() }}
+ with:
+ name: playwright-report
+ path: playwright-report/
+ retention-days: 30
diff --git a/packages/e2e-playwright/src/templates/javascript/base/playwright.config.js b/packages/e2e-playwright/src/templates/javascript/base/playwright.config.js
new file mode 100644
index 00000000..6d235b8a
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/javascript/base/playwright.config.js
@@ -0,0 +1,80 @@
+// @ts-check
+import { defineConfig, devices } from '@playwright/test';
+
+/**
+ * Read environment variables from file.
+ * https://github.com/motdotla/dotenv
+ */
+// import dotenv from 'dotenv';
+// import path from 'path';
+// dotenv.config({ path: path.resolve(__dirname, '.env') });
+
+/**
+ * @see https://playwright.dev/docs/test-configuration
+ */
+export default defineConfig({
+ testDir: './test',
+ /* Run tests in files in parallel */
+ fullyParallel: true,
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
+ forbidOnly: !!process.env.CI,
+ /* Retry on CI only */
+ retries: process.env.CI ? 2 : 0,
+ /* Opt out of parallel tests on CI. */
+ workers: process.env.CI ? 1 : undefined,
+ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
+ reporter: 'html',
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
+ use: {
+ /* Base URL to use in actions like `await page.goto('/')`. */
+ baseURL: 'http://localhost:<%= devServerPort %>',
+
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
+ trace: 'on-first-retry',
+ },
+
+ /* Configure projects for major browsers */
+ projects: [
+ {
+ name: 'chromium',
+ use: { ...devices['Desktop Chrome'] },
+ },
+
+ {
+ name: 'firefox',
+ use: { ...devices['Desktop Firefox'] },
+ },
+
+ {
+ name: 'webkit',
+ use: { ...devices['Desktop Safari'] },
+ },
+
+ /* Test against mobile viewports. */
+ // {
+ // name: 'Mobile Chrome',
+ // use: { ...devices['Pixel 5'] },
+ // },
+ // {
+ // name: 'Mobile Safari',
+ // use: { ...devices['iPhone 12'] },
+ // },
+
+ /* Test against branded browsers. */
+ // {
+ // name: 'Microsoft Edge',
+ // use: { ...devices['Desktop Edge'], channel: 'msedge' },
+ // },
+ // {
+ // name: 'Google Chrome',
+ // use: { ...devices['Desktop Chrome'], channel: 'chrome' },
+ // },
+ ],
+
+ /* Run your local dev server before starting the tests */
+ webServer: {
+ command: 'quasar dev -p <%= devServerPort %>',
+ url: 'http://localhost:<%= devServerPort %>',
+ reuseExistingServer: !process.env.CI,
+ },
+});
diff --git a/packages/e2e-playwright/src/templates/javascript/base/test/playwright/home.spec.js b/packages/e2e-playwright/src/templates/javascript/base/test/playwright/home.spec.js
new file mode 100644
index 00000000..18173075
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/javascript/base/test/playwright/home.spec.js
@@ -0,0 +1,20 @@
+import {
+ test,
+ expect,
+} from '@quasar/quasar-app-extension-testing-e2e-playwright';
+
+test('has title', async ({ page }) => {
+ await page.goto('https://playwright.dev/');
+
+ await expect(page).toHaveTitle(/Playwright/);
+});
+
+test('get started link', async ({ page }) => {
+ await page.goto('https://playwright.dev/');
+
+ await page.getByRole('link', { name: 'Get started' }).click();
+
+ await expect(
+ page.getByRole('heading', { name: 'Installation' }),
+ ).toBeVisible();
+});
diff --git a/packages/e2e-playwright/src/templates/javascript/component-test/playwright-ct.config.js b/packages/e2e-playwright/src/templates/javascript/component-test/playwright-ct.config.js
new file mode 100644
index 00000000..b35beede
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/javascript/component-test/playwright-ct.config.js
@@ -0,0 +1,105 @@
+// @ts-check
+
+import { defineConfig, devices } from '@playwright/experimental-ct-vue';
+import vue from '@vitejs/plugin-vue';
+import { quasar, transformAssetUrls } from '@quasar/vite-plugin';
+<% if (codeCoverageIsEnabled) { %> import istanbul from 'vite-plugin-istanbul'; <% } %>
+// import { fileURLToPath } from 'node:url';
+// import AutoImport from 'unplugin-auto-import/vite';
+// import Components from 'unplugin-vue-components/vite';
+
+/**
+ * See https://playwright.dev/docs/test-configuration.
+ */
+export default defineConfig({
+ testDir: './src/components',
+ /* The base directory, relative to the config file, for snapshot files created with toMatchSnapshot and toHaveScreenshot. */
+ snapshotDir: './__snapshots__',
+ /* Maximum time one test can run for. */
+ timeout: 10 * 1000,
+ /* Run tests in files in parallel */
+ fullyParallel: true,
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
+ forbidOnly: !!process.env.CI,
+ /* Retry on CI only */
+ retries: process.env.CI ? 2 : 0,
+ /* Opt out of parallel tests on CI. */
+ workers: process.env.CI ? 1 : undefined,
+ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
+ reporter: 'html',
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
+ use: {
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
+ trace: 'on-first-retry',
+
+ /* Port to use for Playwright component endpoint. */
+ ctPort: 3100,
+
+ ctViteConfig: <% if(codeCoverageIsEnabled) { %> async <% } %> () => {
+ <% if (codeCoverageIsEnabled) { %> const { default: istanbul } = await import('vite-plugin-istanbul'); <% } %>
+
+ return {
+ build: {
+ sourcemap: true
+ },
+ plugins: [
+ vue({ template: { transformAssetUrls } }),
+ // AutoImport({
+ // imports: [
+ // 'vue',
+ // 'vue-router',
+ // '@vueuse/head',
+ // 'pinia',
+ // 'quasar',
+ // {
+ // '@/store': ['useStore'],
+ // },
+ // ],
+ // dts: 'src/auto-imports.d.ts',
+ // eslintrc: {
+ // enabled: true,
+ // },
+ // }),
+ // Components({
+ // dirs: ['src/components'],
+ // extensions: ['vue'],
+ // }),
+ quasar({
+ // sassVariables: fileURLToPath(
+ // new URL('./src/quasar-variables.sass', import.meta.url),
+ // ),
+ }),
+ <% if(codeCoverageIsEnabled) { %>
+ // Instrument the code for nyc/istanbul code coverage
+ istanbul({
+ include: ['src/**/*'],
+ exclude: ['node_modules', 'test/', 'dist/', 'coverage/', '__tests__'],
+ extension: ['.js', '.ts', '.vue'],
+ requireEnv: true,
+ forceBuildInstrument: true,
+ checkProd: false,
+ cypress: false,
+ }) <% } %>
+ ],
+ }
+ },
+},
+
+ /* Configure projects for major browsers */
+ projects: [
+ {
+ name: 'chromium',
+ use: { ...devices['Desktop Chrome'] },
+ },
+ {
+ name: 'firefox',
+ use: { ...devices['Desktop Firefox'] },
+ },
+ {
+ name: 'webkit',
+ use: { ...devices['Desktop Safari'] },
+ },
+],
+});
+
+
diff --git a/packages/e2e-playwright/src/templates/javascript/component-test/playwright/index.html b/packages/e2e-playwright/src/templates/javascript/component-test/playwright/index.html
new file mode 100644
index 00000000..2468b1c8
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/javascript/component-test/playwright/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ Testing Page
+
+
+
+
+
+
diff --git a/packages/e2e-playwright/src/templates/javascript/component-test/playwright/index.js b/packages/e2e-playwright/src/templates/javascript/component-test/playwright/index.js
new file mode 100644
index 00000000..3c83cc58
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/javascript/component-test/playwright/index.js
@@ -0,0 +1,20 @@
+// See https://quasar.dev/start/vite-plugin for available options
+import 'quasar/src/css/index.sass';
+import '../src/css/app.scss';
+import { Quasar, Dialog } from 'quasar';
+import { beforeMount } from '@playwright/experimental-ct-vue/hooks';
+import '@quasar/extras/material-icons/material-icons.css';
+// import '@quasar/extras/mdi-v7/mdi-v7.css';
+
+beforeMount(({ app }) => {
+ // Setup other stuff you need before mounting the component. You can setup i18n, etc here.
+ // See https://playwright.dev/docs/test-components#frequently-asked-questions
+ app.use(Quasar, {
+ plugins: {
+ // Setup plugins used in your components
+ // Notify,
+ // Loading
+ Dialog,
+ },
+ });
+});
diff --git a/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppButton.spec.js b/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppButton.spec.js
new file mode 100644
index 00000000..24f29302
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppButton.spec.js
@@ -0,0 +1,50 @@
+import {
+ test,
+ expect,
+} from '@quasar/quasar-app-extension-testing-e2e-playwright/ct';
+import AppButton from 'src/components/AppButton.vue';
+
+test('renders a message', async ({ mount }) => {
+ const label = 'Hello there';
+ const component = await mount(AppButton, { props: { label } });
+
+ await expect(component).toContainText(label);
+});
+
+test('renders another message', async ({ mount }) => {
+ const label = 'Will this work?';
+ const component = await mount(AppButton, { props: { label } });
+ await expect(component).toContainText(label);
+});
+
+test('should have a `positive` color', async ({ mount }) => {
+ const button = await mount(AppButton);
+
+ const bgColor = await button.evaluate(
+ (el) => window.getComputedStyle(el).backgroundColor,
+ );
+ const textColor = await button.evaluate(
+ (el) => window.getComputedStyle(el).color,
+ );
+
+ const quasarPositiveVar = 'rgb(33, 186, 69)';
+ expect(bgColor).toBe(quasarPositiveVar);
+ expect(textColor).toBe('rgb(255, 255, 255)');
+});
+
+test('should emit `test` upon click', async ({ mount }) => {
+ let eventCount = 0;
+
+ const component = await mount(AppButton, {
+ on: {
+ test: () => {
+ eventCount++;
+ },
+ },
+ });
+
+ await component.click();
+ expect(eventCount).toBe(1);
+ await component.click();
+ expect(eventCount).toBe(2);
+});
diff --git a/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppCheckComponents.spec.js b/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppCheckComponents.spec.js
new file mode 100644
index 00000000..d228fb40
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppCheckComponents.spec.js
@@ -0,0 +1,47 @@
+import AppCheckComponents from '../AppCheckComponents.vue';
+import {
+ test,
+ expect,
+} from '@quasar/quasar-app-extension-testing-e2e-playwright/ct';
+
+test.describe('AppCheckbox', () => {
+ test('can be used with normal Playwright commands', async ({ mount }) => {
+ const component = await mount(AppCheckComponents);
+
+ const checkbox = component.getByTestId('checkbox');
+ await checkbox.check();
+ await expect(checkbox).toBeChecked();
+
+ await checkbox.uncheck();
+ await expect(checkbox).not.toBeChecked();
+ });
+});
+
+test.describe('QuasarToggle', () => {
+ test('can be used with normal Playwright commands', async ({ mount }) => {
+ const component = await mount(AppCheckComponents);
+
+ const toggle = component.getByTestId('toggle');
+ await toggle.check();
+ await expect(toggle).toBeChecked();
+
+ await toggle.uncheck();
+ await expect(toggle).not.toBeChecked();
+ });
+});
+
+test.describe('QuasarRadio', () => {
+ test('can be used with normal Playwright commands', async ({ mount }) => {
+ const component = await mount(AppCheckComponents);
+
+ const radio1 = component.getByTestId('radio-1');
+ const radio2 = component.getByTestId('radio-2');
+
+ await radio1.check();
+ await expect(radio1).toBeChecked();
+
+ await radio2.check();
+ await expect(radio2).toBeChecked();
+ await expect(radio1).not.toBeChecked();
+ });
+});
diff --git a/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppDark.spec.js b/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppDark.spec.js
new file mode 100644
index 00000000..16aa7f6e
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppDark.spec.js
@@ -0,0 +1,18 @@
+import {
+ test,
+ expect,
+} from '@quasar/quasar-app-extension-testing-e2e-playwright/ct';
+import AppDark from '../AppDark.vue';
+
+test('changes its color', async ({ mount }) => {
+ const darkCard = await mount(AppDark);
+
+ await expect(darkCard).not.toHaveClass(/q-dark/);
+
+ const darkModeToggleButton = darkCard.getByTestId('dark-mode-toggle-button');
+ await darkModeToggleButton.click();
+ await expect(darkCard).toHaveClass(/q-dark/);
+
+ await darkModeToggleButton.click();
+ await expect(darkCard).not.toHaveClass(/q-dark/);
+});
diff --git a/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppDate.spec.js b/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppDate.spec.js
new file mode 100644
index 00000000..78a1c3b8
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppDate.spec.js
@@ -0,0 +1,44 @@
+import AppDate from '../AppDate.vue';
+import {
+ selectDate,
+ test,
+ expect,
+} from '@quasar/quasar-app-extension-testing-e2e-playwright/ct';
+
+const targetDate = '2023/02/23';
+
+test.describe('AppDate', () => {
+ test('selects a date by date string', async ({ mount }) => {
+ const component = await mount(AppDate);
+ const subject = component.getByTestId('date-picker');
+
+ await selectDate(subject, targetDate);
+ await expect(component.getByTestId('selected-date-input')).toHaveValue(
+ targetDate,
+ );
+ await component.unmount();
+ });
+
+ test('selects a date by date object', async ({ mount }) => {
+ const component = await mount(AppDate);
+
+ const subject = component.getByTestId('date-picker');
+ await selectDate(subject, targetDate);
+ await expect(component.getByTestId('selected-date-input')).toHaveValue(
+ targetDate,
+ );
+ await component.unmount();
+ });
+
+ test('selects a date displayed in a popup proxy', async ({ mount, page }) => {
+ const component = await mount(AppDate);
+
+ await component.getByTestId('open-date-picker-popup-button').click();
+
+ const datePickerDialog = page.getByTestId('date-proxy');
+ await selectDate(datePickerDialog, targetDate);
+ await expect(component.getByTestId('selected-date-input')).toHaveValue(
+ targetDate,
+ );
+ });
+});
diff --git a/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppDialog.spec.js b/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppDialog.spec.js
new file mode 100644
index 00000000..235a8982
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppDialog.spec.js
@@ -0,0 +1,47 @@
+import DialogWrapper from 'app/test/playwright/wrappers/DialogWrapper.vue';
+import AppDialog from '../ApDialog.vue';
+import {
+ test,
+ expect,
+ withinDialog,
+} from '@quasar/quasar-app-extension-testing-e2e-playwright/ct';
+
+test.describe('AppDialog', () => {
+ test('should show a dialog with a message', async ({ mount, page }) => {
+ const message = 'Hello, I am a dialog';
+ await mount(DialogWrapper, {
+ props: {
+ component: AppDialog,
+ componentProps: { message },
+ },
+ });
+
+ await withinDialog(page, async (dialog) => {
+ await expect(dialog).toContainText(message);
+
+ await dialog.getByTestId('ok-button').click();
+ await dialog.waitFor({ state: 'hidden' });
+ });
+ });
+
+ test('should keep the dialog open when not dismissed', async ({
+ mount,
+ page,
+ }) => {
+ const message = 'Hello, I am a dialog';
+ await mount(DialogWrapper, {
+ props: {
+ component: AppDialog,
+ componentProps: { message, persistent: true },
+ },
+ });
+
+ await withinDialog(page, {
+ fn: async (dialog) => {
+ await expect(dialog).toContainText(message);
+ await expect(dialog).toBeVisible();
+ },
+ persistent: true,
+ });
+ });
+});
diff --git a/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppDrawer.spec.js b/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppDrawer.spec.js
new file mode 100644
index 00000000..c38dd839
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppDrawer.spec.js
@@ -0,0 +1,36 @@
+import {
+ test,
+ expect,
+} from '@quasar/quasar-app-extension-testing-e2e-playwright/ct';
+import LayoutContainer from 'app/test/playwright/wrappers/LayoutContainer.vue';
+import AppDrawer from '../AppDrawer.vue';
+
+test.describe('AppDrawer', () => {
+ test('should show a drawer', async ({ mount }) => {
+ try {
+ const component = await mount(LayoutContainer, {
+ props: {
+ component: AppDrawer,
+ },
+ });
+
+ // Check that the drawer exists and the button is initially not visible
+ await expect(component.getByTestId('drawer')).toBeVisible();
+ await expect(component.getByTestId('button')).not.toBeInViewport();
+
+ // Scroll to the bottom of the scroll area
+ await component.locator('.q-scrollarea .scroll').evaluate((el) => {
+ el.scrollTo({ top: el.scrollHeight, behavior: 'smooth' });
+ });
+
+ // Wait for scrolling to complete and check button visibility
+ await component
+ .locator('.q-scrollarea .scroll')
+ .getByTestId('button')
+ .waitFor({ state: 'visible' });
+ await expect(component.getByTestId('button')).toBeInViewport();
+ } catch (error) {
+ console.error(error);
+ }
+ });
+});
diff --git a/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppMenu.spec.js b/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppMenu.spec.js
new file mode 100644
index 00000000..5ca87632
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppMenu.spec.js
@@ -0,0 +1,28 @@
+import AppMenu from '../AppMenu.vue';
+import {
+ withinMenu,
+ test,
+ expect,
+} from '@quasar/quasar-app-extension-testing-e2e-playwright/ct';
+
+test.describe('AppMenu', () => {
+ test('click an item by content', async ({ mount, page }) => {
+ const component = await mount(AppMenu);
+ await component.click();
+
+ await withinMenu(page, async (menu) => {
+ await expect(menu).toBeVisible();
+ await menu.locator('.q-item:has-text("Item 1")').click();
+ });
+ });
+
+ test('click an item by cardinality', async ({ mount, page }) => {
+ const component = await mount(AppMenu);
+ await component.click();
+
+ await withinMenu(page, async (menu) => {
+ await expect(menu).toBeVisible();
+ await menu.locator('.q-item').nth(1).click();
+ });
+ });
+});
diff --git a/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppPageSticky.spec.js b/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppPageSticky.spec.js
new file mode 100644
index 00000000..6bbdbfb7
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppPageSticky.spec.js
@@ -0,0 +1,35 @@
+import {
+ test,
+ expect,
+} from '@quasar/quasar-app-extension-testing-e2e-playwright/ct';
+import LayoutContainer from 'app/test/playwright/wrappers/LayoutContainer.vue';
+import AppPageSticky from '../QuasarPageSticky.vue';
+
+test.describe('AppPageSticky', () => {
+ test('should show a sticky at the bottom-right of the page', async ({
+ mount,
+ page,
+ }) => {
+ const component = await mount(LayoutContainer, {
+ props: {
+ component: AppPageSticky,
+ },
+ });
+
+ const button = component.getByTestId('button');
+ await expect(button).toBeVisible();
+
+ const buttonBox = await button.boundingBox();
+ const viewport = page.viewportSize();
+
+ if (!buttonBox || !viewport) {
+ throw new Error('Could not read bounding box or viewport size');
+ }
+
+ const buttonBottom = buttonBox.y + buttonBox.height;
+ const buttonRight = buttonBox.x + buttonBox.width;
+
+ expect(buttonBottom).toBeCloseTo(viewport.height - 18, 1);
+ expect(buttonRight).toBeCloseTo(viewport.width - 18, 1);
+ });
+});
diff --git a/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppSelect.spec.js b/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppSelect.spec.js
new file mode 100644
index 00000000..1e2979cd
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppSelect.spec.js
@@ -0,0 +1,49 @@
+import AppSelect from '../AppSelect.vue';
+import {
+ selectQSelectOption,
+ test,
+ expect,
+} from '@quasar/quasar-app-extension-testing-e2e-playwright/ct';
+
+test.describe('AppSelect', () => {
+ test('makes sure the select is disabled', async ({ mount }) => {
+ const component = await mount(AppSelect, {
+ props: { disable: true },
+ });
+
+ // We need the root of the select component, so we use this instead. The data-testid gets passed to the
+ // native element and not to the root div of the component
+ const selectComponent = component.locator('.q-select');
+ await expect(selectComponent).toHaveAttribute('aria-disabled', 'true');
+ });
+
+ test('selects an option by content', async ({ mount }) => {
+ const component = await mount(AppSelect);
+ await selectQSelectOption(component, 'Option 1');
+
+ const selectValue = component.getByTestId('select-value');
+ await expect(selectValue).toHaveText('Option 1');
+ });
+
+ test('selects an option by cardinality', async ({ mount }) => {
+ const component = await mount(AppSelect);
+ await selectQSelectOption(component, 1);
+
+ const selectValue = component.getByTestId('select-value');
+ await expect(selectValue).toHaveText('Option 2');
+ });
+
+ test('selects an option asynchronously', async ({ mount }) => {
+ const component = await mount(AppSelect, {
+ props: { loadOptionsAsync: true },
+ });
+
+ const spinner = component.locator('.q-spinner');
+ await expect(spinner).toBeHidden();
+
+ await selectQSelectOption(component, 'Option 3');
+
+ const selectValue = component.getByTestId('select-value');
+ await expect(selectValue).toHaveText('Option 3');
+ });
+});
diff --git a/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppTooltip.spec.js b/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppTooltip.spec.js
new file mode 100644
index 00000000..7ae83f4d
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/javascript/component-test/src/components/___tests__/AppTooltip.spec.js
@@ -0,0 +1,15 @@
+import {
+ test,
+ expect,
+} from '@quasar/quasar-app-extension-testing-e2e-playwright/ct';
+import AppTooltip from '../AppTooltip.vue';
+
+test.describe('AppTooltip', () => {
+ test('should show a tooltip', async ({ mount, page }) => {
+ const button = await mount(AppTooltip);
+ await button.hover();
+
+ const tooltip = page.locator('.q-tooltip');
+ await expect(tooltip).toContainText('Here I am!');
+ });
+});
diff --git a/packages/e2e-playwright/src/templates/typescript/base/playwright.config.ts b/packages/e2e-playwright/src/templates/typescript/base/playwright.config.ts
new file mode 100644
index 00000000..cc9dea38
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/typescript/base/playwright.config.ts
@@ -0,0 +1,79 @@
+import { defineConfig, devices } from '@playwright/test';
+
+/**
+ * Read environment variables from file.
+ * https://github.com/motdotla/dotenv
+ */
+// import dotenv from 'dotenv';
+// import path from 'path';
+// dotenv.config({ path: path.resolve(__dirname, '.env') });
+
+/**
+ * See https://playwright.dev/docs/test-configuration.
+ */
+export default defineConfig({
+ testDir: './test/playwright',
+ /* Run tests in files in parallel */
+ fullyParallel: true,
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
+ forbidOnly: !!process.env.CI,
+ /* Retry on CI only */
+ retries: process.env.CI ? 2 : 0,
+ /* Opt out of parallel tests on CI. */
+ workers: process.env.CI ? 1 : undefined,
+ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
+ reporter: 'html',
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
+ use: {
+ /* Base URL to use in actions like `await page.goto('/')`. */
+ baseURL: 'http://localhost:<%= devServerPort %>',
+
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
+ trace: 'on-first-retry',
+ },
+
+ /* Configure projects for major browsers */
+ projects: [
+ {
+ name: 'chromium',
+ use: { ...devices['Desktop Chrome'] },
+ },
+
+ {
+ name: 'firefox',
+ use: { ...devices['Desktop Firefox'] },
+ },
+
+ {
+ name: 'webkit',
+ use: { ...devices['Desktop Safari'] },
+ },
+
+ /* Test against mobile viewports. */
+ // {
+ // name: 'Mobile Chrome',
+ // use: { ...devices['Pixel 5'] },
+ // },
+ // {
+ // name: 'Mobile Safari',
+ // use: { ...devices['iPhone 12'] },
+ // },
+
+ /* Test against branded browsers. */
+ // {
+ // name: 'Microsoft Edge',
+ // use: { ...devices['Desktop Edge'], channel: 'msedge' },
+ // },
+ // {
+ // name: 'Google Chrome',
+ // use: { ...devices['Desktop Chrome'], channel: 'chrome' },
+ // },
+ ],
+
+ /* Run your local dev server before starting the tests */
+ webServer: {
+ command: 'quasar dev -p <%= devServerPort %>',
+ url: 'http://localhost:<%= devServerPort %>',
+ reuseExistingServer: !process.env.CI,
+ },
+});
diff --git a/packages/e2e-playwright/src/templates/typescript/base/test/playwright/home.spec.ts b/packages/e2e-playwright/src/templates/typescript/base/test/playwright/home.spec.ts
new file mode 100644
index 00000000..18173075
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/typescript/base/test/playwright/home.spec.ts
@@ -0,0 +1,20 @@
+import {
+ test,
+ expect,
+} from '@quasar/quasar-app-extension-testing-e2e-playwright';
+
+test('has title', async ({ page }) => {
+ await page.goto('https://playwright.dev/');
+
+ await expect(page).toHaveTitle(/Playwright/);
+});
+
+test('get started link', async ({ page }) => {
+ await page.goto('https://playwright.dev/');
+
+ await page.getByRole('link', { name: 'Get started' }).click();
+
+ await expect(
+ page.getByRole('heading', { name: 'Installation' }),
+ ).toBeVisible();
+});
diff --git a/packages/e2e-playwright/src/templates/typescript/component-test/playwright-ct.config.ts b/packages/e2e-playwright/src/templates/typescript/component-test/playwright-ct.config.ts
new file mode 100644
index 00000000..8ae3cfbd
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/typescript/component-test/playwright-ct.config.ts
@@ -0,0 +1,99 @@
+import { defineConfig, devices } from '@playwright/experimental-ct-vue';
+import vue from '@vitejs/plugin-vue';
+import { quasar, transformAssetUrls } from '@quasar/vite-plugin';
+// import { fileURLToPath } from 'node:url';
+// import AutoImport from 'unplugin-auto-import/vite';
+// import Components from 'unplugin-vue-components/vite';
+
+/**
+ * See https://playwright.dev/docs/test-configuration.
+ */
+export default defineConfig({
+ testDir: './src/components',
+ /* The base directory, relative to the config file, for snapshot files created with toMatchSnapshot and toHaveScreenshot. */
+ snapshotDir: './__snapshots__',
+ /* Maximum time one test can run for. */
+ timeout: 10 * 1000,
+ /* Run tests in files in parallel */
+ fullyParallel: true,
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
+ forbidOnly: !!process.env.CI,
+ /* Retry on CI only */
+ retries: process.env.CI ? 2 : 0,
+ /* Opt out of parallel tests on CI. */
+ workers: process.env.CI ? 1 : undefined,
+ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
+ reporter: 'html',
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
+ use: {
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
+ trace: 'on-first-retry',
+
+ /* Port to use for Playwright component endpoint. */
+ ctPort: 3100,
+
+ ctViteConfig: <% if(codeCoverageIsEnabled) { %> async <% } %> () => {
+ <% if (codeCoverageIsEnabled) { %> const { default: istanbul } = await import('vite-plugin-istanbul'); <% } %>
+ return {
+ build: {
+ sourcemap: true
+ },
+ plugins: [
+ vue({ template: { transformAssetUrls } }),
+ // AutoImport({
+ // imports: [
+ // 'vue',
+ // 'vue-router',
+ // '@vueuse/head',
+ // 'pinia',
+ // 'quasar',
+ // {
+ // '@/store': ['useStore'],
+ // },
+ // ],
+ // dts: 'src/auto-imports.d.ts',
+ // eslintrc: {
+ // enabled: true,
+ // },
+ // }),
+ // Components({
+ // dirs: ['src/components'],
+ // extensions: ['vue'],
+ // }),
+ quasar({
+ // sassVariables: fileURLToPath(
+ // new URL('./src/quasar-variables.sass', import.meta.url),
+ // ),
+ }),
+ <% if(codeCoverageIsEnabled) { %>
+ // Instrument the code for nyc/istanbul code coverage
+ istanbul({
+ include: ['src/**/*'],
+ exclude: ['node_modules', 'test/', 'dist/', 'coverage/', '__tests__'],
+ extension: ['.js', '.ts', '.vue'],
+ requireEnv: true,
+ forceBuildInstrument: true,
+ checkProd: false,
+ cypress: false,
+ }) <% } %>
+ ],
+ }
+ },
+},
+
+/* Configure projects for major browsers */
+projects: [
+ {
+ name: 'chromium',
+ use: { ...devices['Desktop Chrome'] },
+ },
+ {
+ name: 'firefox',
+ use: { ...devices['Desktop Firefox'] },
+ },
+ {
+ name: 'webkit',
+ use: { ...devices['Desktop Safari'] },
+ },
+],
+});
diff --git a/packages/e2e-playwright/src/templates/typescript/component-test/playwright/index.html b/packages/e2e-playwright/src/templates/typescript/component-test/playwright/index.html
new file mode 100644
index 00000000..000deead
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/typescript/component-test/playwright/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ Testing Page
+
+
+
+
+
+
diff --git a/packages/e2e-playwright/src/templates/typescript/component-test/playwright/index.ts b/packages/e2e-playwright/src/templates/typescript/component-test/playwright/index.ts
new file mode 100644
index 00000000..f5265b82
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/typescript/component-test/playwright/index.ts
@@ -0,0 +1,20 @@
+// See https://quasar.dev/start/vite-plugin
+import 'quasar/src/css/index.sass';
+import '../src/css/app.scss';
+import { Quasar, Dialog } from 'quasar';
+import { beforeMount } from '@playwright/experimental-ct-vue/hooks';
+import '@quasar/extras/material-icons/material-icons.css';
+// import '@quasar/extras/mdi-v7/mdi-v7.css';
+
+beforeMount(async ({ app }) => {
+ // Setup other stuff you need before mounting the component. You can setup i18n, pinia, etc here.
+ // See https://playwright.dev/docs/test-components#frequently-asked-questions
+ app.use(Quasar, {
+ plugins: {
+ // Setup plugins used in your components
+ // Notify,
+ // Loading
+ Dialog,
+ },
+ });
+});
diff --git a/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppButton.spec.ts b/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppButton.spec.ts
new file mode 100644
index 00000000..8aada2df
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppButton.spec.ts
@@ -0,0 +1,43 @@
+import { test, expect } from '@quasar/quasar-app-extension-testing-e2e-playwright/ct';
+import AppButton from 'src/components/AppButton.vue';
+
+test('renders a message', async ({ mount }) => {
+ const label = 'Hello there';
+ const component = await mount(AppButton, { props: { label } });
+
+ await expect(component).toContainText(label);
+});
+
+test('renders another message', async ({ mount }) => {
+ const label = 'Will this work?';
+ const component = await mount(AppButton, { props: { label } });
+ await expect(component).toContainText(label);
+});
+
+test('should have a `positive` color', async ({ mount }) => {
+ const button = await mount(AppButton);
+
+ const bgColor = await button.evaluate((el) => window.getComputedStyle(el).backgroundColor);
+ const textColor = await button.evaluate((el) => window.getComputedStyle(el).color);
+
+ const quasarPositiveVar = 'rgb(33, 186, 69)';
+ expect(bgColor).toBe(quasarPositiveVar);
+ expect(textColor).toBe('rgb(255, 255, 255)');
+});
+
+test('should emit `test` upon click', async ({ mount }) => {
+ let eventCount = 0;
+
+ const component = await mount(AppButton, {
+ on: {
+ test: () => {
+ eventCount++;
+ },
+ },
+ });
+
+ await component.click();
+ expect(eventCount).toBe(1);
+ await component.click();
+ expect(eventCount).toBe(2);
+});
diff --git a/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppCheckComponents.spec.ts b/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppCheckComponents.spec.ts
new file mode 100644
index 00000000..73346903
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppCheckComponents.spec.ts
@@ -0,0 +1,44 @@
+import AppCheckComponents from '../AppCheckComponents.vue';
+import { test, expect } from '@quasar/quasar-app-extension-testing-e2e-playwright/ct';
+
+test.describe('QuasarCheckbox', () => {
+ test('can be used with normal Playwright commands', async ({ mount }) => {
+ const component = await mount(AppCheckComponents);
+
+ const checkbox = component.getByTestId('checkbox');
+ await checkbox.check();
+ await expect(checkbox).toBeChecked();
+
+ await checkbox.uncheck();
+ await expect(checkbox).not.toBeChecked();
+ });
+});
+
+test.describe('QuasarToggle', () => {
+ test('can be used with normal Playwright commands', async ({ mount }) => {
+ const component = await mount(AppCheckComponents);
+
+ const toggle = component.getByTestId('toggle');
+ await toggle.check();
+ await expect(toggle).toBeChecked();
+
+ await toggle.uncheck();
+ await expect(toggle).not.toBeChecked();
+ });
+});
+
+test.describe('QuasarRadio', () => {
+ test('can be used with normal Playwright commands', async ({ mount }) => {
+ const component = await mount(AppCheckComponents);
+
+ const radio1 = component.getByTestId('radio-1');
+ const radio2 = component.getByTestId('radio-2');
+
+ await radio1.check();
+ await expect(radio1).toBeChecked();
+
+ await radio2.check();
+ await expect(radio2).toBeChecked();
+ await expect(radio1).not.toBeChecked();
+ });
+});
diff --git a/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppDark.spec.ts b/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppDark.spec.ts
new file mode 100644
index 00000000..67baa5a2
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppDark.spec.ts
@@ -0,0 +1,15 @@
+import { test, expect } from '@quasar/quasar-app-extension-testing-e2e-playwright/ct';
+import AppDark from '../AppDark.vue';
+
+test('changes its color', async ({ mount }) => {
+ const darkCard = await mount(AppDark);
+
+ await expect(darkCard).not.toHaveClass(/q-dark/);
+
+ const darkModeToggleButton = darkCard.getByTestId('dark-mode-toggle-button');
+ await darkModeToggleButton.click();
+ await expect(darkCard).toHaveClass(/q-dark/);
+
+ await darkModeToggleButton.click();
+ await expect(darkCard).not.toHaveClass(/q-dark/);
+});
diff --git a/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppDate.spec.ts b/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppDate.spec.ts
new file mode 100644
index 00000000..452a16fb
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppDate.spec.ts
@@ -0,0 +1,34 @@
+import AppDate from '../AppDate.vue';
+import { selectDate, test, expect } from '@quasar/quasar-app-extension-testing-e2e-playwright/ct';
+
+const targetDate = '2023/02/23';
+
+test.describe('AppDate', () => {
+ test('selects a date by date string', async ({ mount }) => {
+ const component = await mount(AppDate);
+ const subject = component.getByTestId('date-picker');
+
+ await selectDate(subject, targetDate);
+ await expect(component.getByTestId('selected-date-input')).toHaveValue(targetDate);
+ await component.unmount();
+ });
+
+ test('selects a date by date object', async ({ mount }) => {
+ const component = await mount(AppDate);
+
+ const subject = component.getByTestId('date-picker');
+ await selectDate(subject, targetDate);
+ await expect(component.getByTestId('selected-date-input')).toHaveValue(targetDate);
+ await component.unmount();
+ });
+
+ test('selects a date displayed in a popup proxy', async ({ mount, page }) => {
+ const component = await mount(AppDate);
+
+ await component.getByTestId('open-date-picker-popup-button').click();
+
+ const datePickerDialog = page.getByTestId('date-proxy');
+ await selectDate(datePickerDialog, targetDate);
+ await expect(component.getByTestId('selected-date-input')).toHaveValue(targetDate);
+ });
+});
diff --git a/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppDialog.spec.ts b/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppDialog.spec.ts
new file mode 100644
index 00000000..1f2a581f
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppDialog.spec.ts
@@ -0,0 +1,40 @@
+import DialogWrapper from 'app/test/playwright/wrappers/DialogWrapper.vue';
+import AppDialog from '../AppDialog.vue';
+import { test, expect, withinDialog } from '@quasar/quasar-app-extension-testing-e2e-playwright/ct';
+
+test.describe('AppDialog', () => {
+ test('should show a dialog with a message', async ({ mount, page }) => {
+ const message = 'Hello, I am a dialog';
+ await mount(DialogWrapper, {
+ props: {
+ component: AppDialog,
+ componentProps: { message },
+ },
+ });
+
+ await withinDialog(page, async (dialog) => {
+ await expect(dialog).toContainText(message);
+
+ await dialog.getByTestId('ok-button').click();
+ await dialog.waitFor({ state: 'hidden' });
+ });
+ });
+
+ test('should keep the dialog open when not dismissed', async ({ mount, page }) => {
+ const message = 'Hello, I am a dialog';
+ await mount(DialogWrapper, {
+ props: {
+ component: AppDialog,
+ componentProps: { message, persistent: true },
+ },
+ });
+
+ await withinDialog(page, {
+ fn: async (dialog) => {
+ await expect(dialog).toContainText(message);
+ await expect(dialog).toBeVisible();
+ },
+ persistent: true,
+ });
+ });
+});
diff --git a/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppDrawer.spec.ts b/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppDrawer.spec.ts
new file mode 100644
index 00000000..04292a6e
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppDrawer.spec.ts
@@ -0,0 +1,33 @@
+import { test, expect } from '@quasar/quasar-app-extension-testing-e2e-playwright/ct';
+import LayoutContainer from 'app/test/playwright/wrappers/LayoutContainer.vue';
+import AppDrawer from '../AppDrawer.vue';
+
+test.describe('AppDrawer', () => {
+ test('should show a drawer', async ({ mount }) => {
+ try {
+ const component = await mount(LayoutContainer, {
+ props: {
+ component: AppDrawer,
+ },
+ });
+
+ // Check that the drawer exists and the button is initially not visible
+ await expect(component.getByTestId('drawer')).toBeVisible();
+ await expect(component.getByTestId('button')).not.toBeInViewport();
+
+ // Scroll to the bottom of the scroll area
+ await component.locator('.q-scrollarea .scroll').evaluate((el) => {
+ el.scrollTo({ top: el.scrollHeight, behavior: 'smooth' });
+ });
+
+ // Wait for scrolling to complete and check button visibility
+ await component
+ .locator('.q-scrollarea .scroll')
+ .getByTestId('button')
+ .waitFor({ state: 'visible' });
+ await expect(component.getByTestId('button')).toBeInViewport();
+ } catch (error) {
+ console.error(error);
+ }
+ });
+});
diff --git a/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppMenu.spec.ts b/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppMenu.spec.ts
new file mode 100644
index 00000000..3324ecaf
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppMenu.spec.ts
@@ -0,0 +1,24 @@
+import AppMenu from '../QuasarMenu.vue';
+import { withinMenu, test, expect } from '@quasar/quasar-app-extension-testing-e2e-playwright/ct';
+
+test.describe('AppMenu', () => {
+ test('click an item by content', async ({ mount, page }) => {
+ const component = await mount(AppMenu);
+ await component.click();
+
+ await withinMenu(page, async (menu) => {
+ await expect(menu).toBeVisible();
+ await menu.locator('.q-item:has-text("Item 1")').click();
+ });
+ });
+
+ test('click an item by cardinality', async ({ mount, page }) => {
+ const component = await mount(AppMenu);
+ await component.click();
+
+ await withinMenu(page, async (menu) => {
+ await expect(menu).toBeVisible();
+ await menu.locator('.q-item').nth(1).click();
+ });
+ });
+});
diff --git a/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppPageSticky.spec.ts b/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppPageSticky.spec.ts
new file mode 100644
index 00000000..ff65a385
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppPageSticky.spec.ts
@@ -0,0 +1,30 @@
+import { test, expect } from '@quasar/quasar-app-extension-testing-e2e-playwright/ct';
+import LayoutContainer from 'app/test/playwright/wrappers/LayoutContainer.vue';
+import AppPageSticky from '../QuasarPageSticky.vue';
+
+test.describe('AppPageSticky', () => {
+ test('should show a sticky at the bottom-right of the page', async ({ mount, page }) => {
+ const component = await mount(LayoutContainer, {
+ props: {
+ component: AppPageSticky,
+ },
+ });
+
+ const button = component.getByTestId('button');
+ await expect(button).toBeVisible();
+
+ const buttonBox = await button.boundingBox();
+ const viewport = page.viewportSize();
+
+ // eslint-disable-next-line playwright/no-conditional-in-test
+ if (!buttonBox || !viewport) {
+ throw new Error('Could not read bounding box or viewport size');
+ }
+
+ const buttonBottom: number = buttonBox.y + buttonBox.height;
+ const buttonRight: number = buttonBox.x + buttonBox.width;
+
+ expect(buttonBottom).toBeCloseTo(viewport.height - 18, 1);
+ expect(buttonRight).toBeCloseTo(viewport.width - 18, 1);
+ });
+});
diff --git a/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppSelect.spec.ts b/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppSelect.spec.ts
new file mode 100644
index 00000000..5c54a604
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppSelect.spec.ts
@@ -0,0 +1,45 @@
+import AppSelect from '../AppSelect.vue';
+import { selectQSelectOption, test, expect } from '@quasar/quasar-app-extension-testing-e2e-playwright/ct';
+
+test.describe('AppSelect', () => {
+ test('makes sure the select is disabled', async ({ mount }) => {
+ const component = await mount(AppSelect, {
+ props: { disable: true },
+ });
+
+ // We need the root of the select component, so we use this instead. The data-testid gets passed to the
+ // native element and not to the root div of the component
+ const selectComponent = component.locator('.q-select');
+ await expect(selectComponent).toHaveAttribute('aria-disabled', 'true');
+ });
+
+ test('selects an option by content', async ({ mount }) => {
+ const component = await mount(AppSelect);
+ await selectQSelectOption(component, 'Option 1');
+
+ const selectValue = component.getByTestId('select-value');
+ await expect(selectValue).toHaveText('Option 1');
+ });
+
+ test('selects an option by cardinality', async ({ mount }) => {
+ const component = await mount(AppSelect);
+ await selectQSelectOption(component, 1);
+
+ const selectValue = component.getByTestId('select-value');
+ await expect(selectValue).toHaveText('Option 2');
+ });
+
+ test('selects an option asynchronously', async ({ mount }) => {
+ const component = await mount(AppSelect, {
+ props: { loadOptionsAsync: true },
+ });
+
+ const spinner = component.locator('.q-spinner');
+ await expect(spinner).toBeHidden();
+
+ await selectQSelectOption(component, 'Option 3');
+
+ const selectValue = component.getByTestId('select-value');
+ await expect(selectValue).toHaveText('Option 3');
+ });
+});
diff --git a/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppTooltip.spec.ts b/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppTooltip.spec.ts
new file mode 100644
index 00000000..3c98053f
--- /dev/null
+++ b/packages/e2e-playwright/src/templates/typescript/component-test/src/components/___tests__/AppTooltip.spec.ts
@@ -0,0 +1,12 @@
+import { test, expect } from '@quasar/quasar-app-extension-testing-e2e-playwright/ct';
+import AppTooltip from '../QuasarTooltip.vue';
+
+test.describe('AppTooltip', () => {
+ test('should show a tooltip', async ({ mount, page }) => {
+ const button = await mount(AppTooltip);
+ await button.hover();
+
+ const tooltip = page.locator('.q-tooltip');
+ await expect(tooltip).toContainText('Here I am!');
+ });
+});
diff --git a/packages/e2e-playwright/src/uninstall.js b/packages/e2e-playwright/src/uninstall.js
new file mode 100644
index 00000000..699d3247
--- /dev/null
+++ b/packages/e2e-playwright/src/uninstall.js
@@ -0,0 +1,10 @@
+/**
+ * Quasar App Extension uninstall script
+ *
+ * Docs: https://quasar.dev/app-extensions/development-guide/uninstall-api
+ */
+
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+export default function (api) {
+ //
+}
diff --git a/packages/e2e-playwright/src/utils/base-fixture.ts b/packages/e2e-playwright/src/utils/base-fixture.ts
new file mode 100644
index 00000000..b963ea99
--- /dev/null
+++ b/packages/e2e-playwright/src/utils/base-fixture.ts
@@ -0,0 +1,58 @@
+import { test as baseTest, Locator } from '@playwright/test';
+import { addCoverageToContext } from './coverage.js';
+import {
+ WithinPortalCallback,
+ WithinPortalDerivateOptions,
+} from './portal-helper.js';
+import { withinSelectMenu, withinDialog, withinMenu } from './portals.js';
+import { selectDate } from './select-date.js';
+import { selectQSelectOption, uncheckQuasarComponent, checkQuasarComponent, expectQuasarChecked } from './select.js';
+import { expectColor, expectBackgroundColor } from './color-assertions.js';
+export { expect } from '@playwright/test';
+
+type PortalFnOrOptions = WithinPortalCallback | WithinPortalDerivateOptions;
+
+interface BaseTest {
+ withinDialog: (fnOrOptions: PortalFnOrOptions) => Promise;
+ withinMenu: (fnOrOptions: PortalFnOrOptions) => Promise;
+ withinSelectMenu: (fnOrOptions: PortalFnOrOptions) => Promise;
+ selectDate: typeof selectDate;
+ selectQSelectOption: typeof selectQSelectOption;
+ checkQuasarComponent: typeof checkQuasarComponent;
+ uncheckQuasarComponent: typeof uncheckQuasarComponent;
+ expectQuasarChecked: typeof expectQuasarChecked;
+ expectColor: typeof expectColor;
+ expectBackgroundColor: typeof expectBackgroundColor;
+}
+
+export const test = baseTest.extend({
+ context: async ({ context }, use) => addCoverageToContext(context, use),
+ withinDialog: async ({ page }, use) => {
+ const withinDialogWrapper = (
+ fnOrOptions: PortalFnOrOptions,
+ ): Promise => withinDialog(page, fnOrOptions);
+
+ await use(withinDialogWrapper);
+ },
+ withinMenu: async ({ page }, use) => {
+ const withinMenuWrapper = (
+ fnOrOptions: PortalFnOrOptions,
+ ): Promise => withinMenu(page, fnOrOptions);
+
+ await use(withinMenuWrapper);
+ },
+ withinSelectMenu: async ({ page }, use) => {
+ const withinSelectMenuWrapper = (
+ fnOrOptions: PortalFnOrOptions,
+ ): Promise => withinSelectMenu(page, fnOrOptions);
+
+ await use(withinSelectMenuWrapper);
+ },
+ selectDate: async ({ }, use) => await use(selectDate),
+ selectQSelectOption: async ({ }, use) => await use(selectQSelectOption),
+ checkQuasarComponent: async ({ }, use) => await use(checkQuasarComponent),
+ uncheckQuasarComponent: async ({ }, use) => await use(uncheckQuasarComponent),
+ expectQuasarChecked: async ({ }, use) => await use(expectQuasarChecked),
+ expectColor: async ({ }, use) => await use(expectColor),
+ expectBackgroundColor: async ({ }, use) => await use(expectBackgroundColor),
+});
diff --git a/packages/e2e-playwright/src/utils/color-assertions.ts b/packages/e2e-playwright/src/utils/color-assertions.ts
new file mode 100644
index 00000000..03eefbd7
--- /dev/null
+++ b/packages/e2e-playwright/src/utils/color-assertions.ts
@@ -0,0 +1,59 @@
+import { expect, Locator } from '@playwright/test';
+
+
+/**
+ * Asserts that an element has the expected color style property
+ * @param locator - Playwright locator for the element
+ * @param property - CSS color property to check ('color' or 'background-color')
+ * @param expectedStyle - Expected color value
+ */
+export async function expectColorStyle(
+ locator: Locator,
+ property: 'color' | 'background-color',
+ expectedStyle: string,
+) {
+ const page = locator.page();
+
+ // Wait for the element to be visible before checking colors
+ await expect(locator).toBeVisible();
+
+ const actualStyle = await page.evaluate(
+ ({ selector, property }) => {
+ const element = document.querySelector(selector);
+ if (!element || !(element instanceof HTMLElement)) {
+ return;
+ }
+
+ const computedStyle = getComputedStyle(element);
+ return computedStyle.getPropertyValue(property);
+ },
+ {
+ selector: await locator.evaluate((el) => {
+ el.id = 'temp-element';
+
+ return `#${el.id}`;
+ }),
+ property,
+ },
+ );
+
+ expect(actualStyle).toBe(expectedStyle);
+}
+
+/**
+ * Asserts that an element has the expected text color
+ * @param locator - Playwright locator for the element
+ * @param expectedColor - Expected color value
+ */
+export function expectColor(locator: Locator, expectedColor: string) {
+ return expectColorStyle(locator, 'color', expectedColor);
+}
+
+/**
+ * Asserts that an element has the expected background color
+ * @param locator - Playwright locator for the element
+ * @param expectedBackground - Expected background color value
+ */
+export function expectBackgroundColor(locator: Locator, expectedBackgrouind: string) {
+ return expectColorStyle(locator, 'background-color', expectedBackgrouind);
+}
diff --git a/packages/e2e-playwright/src/utils/coverage.ts b/packages/e2e-playwright/src/utils/coverage.ts
new file mode 100644
index 00000000..8c986193
--- /dev/null
+++ b/packages/e2e-playwright/src/utils/coverage.ts
@@ -0,0 +1,85 @@
+import * as fs from 'fs';
+import * as crypto from 'crypto';
+import * as path from 'path';
+import { type BrowserContext } from '@playwright/test';
+
+// We may want to provide a means by which the user can use an alternative path
+const NYC_OUTPUT_DIR = path.join(process.cwd(), '.nyc_output');
+
+function generateUUID() {
+ return crypto.randomBytes(16).toString('hex');
+}
+
+/**
+ * Sets up and collects code coverage for the given Playwright browser context.
+ * Coverage collection is conditionally enabled based on the `VITE_COVERAGE` environment variable.
+ *
+ * The function performs the following steps when coverage is enabled:
+ * 1. Adds an initialization script to the browser context. This script runs before
+ * every page load within the context and attaches a 'beforeunload' event listener
+ * to the browser's `window`. This listener attempts to capture the `window.__coverage__`
+ * object (standard for Istanbul/v8 coverage) and send it back to Node.js
+ * via an exposed function before the page unloads.
+ * 2. Creates the output directory for coverage reports on the Node.js file system.
+ * 3. Exposes a Node.js function named `collectIstanbulCoverage` to the browser's `window` object.
+ * When this browser-side function is called (by the init script or later `page.evaluate` calls),
+ * the corresponding Node.js function executes, receiving the coverage JSON string
+ * and writing it to a unique JSON file in the designated output directory.
+ * 4. Executes the main test logic provided by the `use` function.
+ * 5. After the main test logic completes, it iterates through all pages currently open
+ * in the context and explicitly evaluates a script on each. This script manually
+ * calls the exposed `window.collectIstanbulCoverage` function to ensure any remaining
+ * coverage data from pages that didn't trigger 'beforeunload' (e.g., tests that
+ * finished without navigation or closing the page) is collected.
+ *
+ * @param context The Playwright browser context for which to collect coverage.
+ * @param use The Playwright test fixture's `use` function,
+ * which is called to execute the main test body with the configured context.
+ */
+
+// @link https://github.com/anishkny/playwright-test-coverage
+export async function addCoverageToContext(context: BrowserContext, use: (_: BrowserContext) => Promise) {
+ if (process.env.VITE_COVERAGE !== 'true') {
+ // `requireEnv` of istanbul should also prevent instrumentation if this flag is not set. So even if
+ // we remove this check, the coverage will not be collected if the flag is not set.
+ // Let's ignore the rest of the code since coverage is disabled.
+ return use(context);
+ }
+
+ // Add beforeunload listener to collect coverage
+ await context.addInitScript(
+ () => {
+ window.addEventListener('beforeunload', () => {
+ window.collectIstanbulCoverage?.(JSON.stringify(window.__coverage__));
+ });
+ });
+
+ await fs.promises.mkdir(NYC_OUTPUT_DIR, { recursive: true });
+
+ // Expose function to save coverage from browser
+ await context.exposeFunction(
+ 'collectIstanbulCoverage',
+ (coverageJSON: string) => {
+ if (!coverageJSON) {
+ return;
+ }
+ fs.writeFileSync(
+ path.join(
+ NYC_OUTPUT_DIR,
+ `playwright_coverage_${generateUUID()}.json`,
+ ),
+ coverageJSON,
+ );
+ },
+ );
+
+ await use(context);
+
+ // Goes through all browser pages in the page context and collects the coverage using the exposed function.
+ for (const page of context.pages()) {
+ await page.evaluate(
+ () => {
+ window.collectIstanbulCoverage?.(JSON.stringify(window.__coverage__));
+ });
+ }
+}
\ No newline at end of file
diff --git a/packages/e2e-playwright/src/utils/portal-helper.ts b/packages/e2e-playwright/src/utils/portal-helper.ts
new file mode 100644
index 00000000..ebaa5f85
--- /dev/null
+++ b/packages/e2e-playwright/src/utils/portal-helper.ts
@@ -0,0 +1,89 @@
+import { expect, Locator, Page } from '@playwright/test';
+
+/**
+ * Callback function that operates on a locator within a portal
+ * @typeParam T - Return type of the callback function, defaults to void
+ */
+export type WithinPortalCallback = (
+ locator: Locator,
+) => T | Promise;
+
+/**
+ * Configuration options for portal derivate commands
+ */
+export interface WithinPortalDerivateOptions {
+ /**
+ * The data-testid attribute value to target specific elements
+ */
+ dataTest?: string;
+
+ /**
+ * If true, doesn't expect the portal to be hidden after the callback is executed
+ */
+ persistent?: boolean;
+
+ /**
+ * Custom selector to override the default selector
+ */
+ selector?: string;
+
+ /**
+ * Callback function to execute within the portal
+ */
+ fn: WithinPortalCallback;
+}
+
+/**
+ * Generic command to interact with portals in Quasar components (dialogs, menus, etc.)
+ *
+ * @param page - Playwright Page or Locator to search within
+ * @param selectorDefault - Default CSS selector for the portal
+ * @param selectorSuffixes - Additional selectors to append to the base selector
+ * @param fnOrOptions - Callback function or options for interacting with the portal
+ * @returns Locator for the portal element
+ */
+export async function portalDerivateCommand(
+ page: Locator | Page,
+ selectorDefault: string,
+ selectorSuffixes: string | string[],
+ fnOrOptions: WithinPortalCallback | WithinPortalDerivateOptions,
+): Promise {
+ const selectorSuffixesArray = Array.isArray(selectorSuffixes)
+ ? selectorSuffixes
+ : [selectorSuffixes];
+
+ const {
+ dataTest = '',
+ persistent = false,
+ selector = selectorDefault,
+ } = typeof fnOrOptions === 'function' ? {} : fnOrOptions;
+
+ const fn = typeof fnOrOptions === 'function' ? fnOrOptions : fnOrOptions.fn;
+
+ const portalSelector = selectorSuffixesArray
+ .map((selectorSuffix) => {
+ // This is the selector used by getTestById(), it is likely not going to change anytime soon because of the number of projects that will break
+ // So we should be fine using it here this way.
+ const testId = `[data-testid="${dataTest}"]`;
+
+ return dataTest
+ ? `${testId}${selectorSuffix}`
+ : `${selector}${selectorSuffix}`;
+ })
+ .join(',');
+
+ const locator = page.locator(portalSelector);
+
+ // Wait for exactly one matching dialog to be present in the DOM.
+ await expect(locator).toHaveCount(1);
+
+ // Execute the callback with the first (and only) located element
+ await fn(locator.first());
+
+ // If not persistent, verify that the portal has been closed/hidden
+ if (!persistent) {
+ await expect(locator).not.toBeVisible();
+ }
+
+ return locator;
+}
diff --git a/packages/e2e-playwright/src/utils/portals.ts b/packages/e2e-playwright/src/utils/portals.ts
new file mode 100644
index 00000000..3e3dd9b8
--- /dev/null
+++ b/packages/e2e-playwright/src/utils/portals.ts
@@ -0,0 +1,37 @@
+import { Locator, Page } from '@playwright/test';
+import {
+ portalDerivateCommand,
+ WithinPortalCallback,
+ WithinPortalDerivateOptions,
+} from './portal-helper.js';
+
+export async function withinDialog(
+ page: Page,
+ fnOrOptions: WithinPortalCallback | WithinPortalDerivateOptions,
+) {
+ return portalDerivateCommand(page, '.q-dialog', '', fnOrOptions);
+}
+
+export async function withinMenu(
+ page: Page,
+ fnOrOptions: WithinPortalCallback | WithinPortalDerivateOptions,
+) {
+ return portalDerivateCommand(
+ page,
+ '.q-menu',
+ [':not([role])', '[role=menu]'],
+ fnOrOptions,
+ );
+}
+
+export async function withinSelectMenu(
+ subject: Page | Locator,
+ fnOrOptions: WithinPortalCallback | WithinPortalDerivateOptions,
+) {
+ return portalDerivateCommand(
+ subject,
+ '.q-menu',
+ '[role=listbox]',
+ fnOrOptions,
+ );
+}
diff --git a/packages/e2e-playwright/src/utils/select-date.ts b/packages/e2e-playwright/src/utils/select-date.ts
new file mode 100644
index 00000000..b31a24cd
--- /dev/null
+++ b/packages/e2e-playwright/src/utils/select-date.ts
@@ -0,0 +1,61 @@
+import { Locator, expect } from '@playwright/test';
+
+/**
+ * Selects a date in a Quasar date picker component
+ * @param subject - Locator for the QDate component
+ * @param value - Date to select (can be Date object or string)
+ * @param options - Optional configuration options
+ */
+export async function selectDate(
+ subject: Locator,
+ value: Date | string,
+ options: { timeout?: number } = {}
+) {
+ const timeout = options.timeout || 5000;
+
+ // Verify we're working with a QDate component
+ const hasQDateClass = await subject.evaluate((el) =>
+ el.classList.contains('q-date'),
+ );
+
+ if (!hasQDateClass) {
+ throw new Error('Subject is not a QDate component. Make sure you are targeting a Quasar date picker.');
+ }
+
+ const targetDate = typeof value === 'string' ? new Date(value) : value;
+
+ // Wait for date picker to be fully rendered
+ await subject
+ .locator('.q-date__navigation div:not(.q-date__arrow)')
+ .last()
+ .waitFor();
+ const yearSelector = subject
+ .locator('.q-date__navigation div:not(.q-date__arrow)')
+ .last();
+ const monthSelector = subject
+ .locator('.q-date__navigation div:not(.q-date__arrow)')
+ .first();
+
+ const targetYear = targetDate.getFullYear();
+ const targetMonth = targetDate.getMonth();
+ const targetDay = targetDate.getDate();
+
+ const currentYear = await yearSelector.textContent();
+ if (currentYear !== targetYear.toString()) {
+ await yearSelector.click();
+ await subject.locator(`text=${targetYear}`).click();
+ }
+
+ // Select month
+ await monthSelector.click();
+ const monthOption = subject.locator('.q-date__months-item').nth(targetMonth);
+ await expect(monthOption).toBeVisible();
+ await monthOption.click();
+
+ // Select day
+ const daySelector = subject
+ .locator(`.q-date__calendar-item--in:has-text("${targetDay}")`)
+ .first();
+ await expect(daySelector).toBeVisible({ timeout });
+ await daySelector.click();
+}
diff --git a/packages/e2e-playwright/src/utils/select.ts b/packages/e2e-playwright/src/utils/select.ts
new file mode 100644
index 00000000..870501cb
--- /dev/null
+++ b/packages/e2e-playwright/src/utils/select.ts
@@ -0,0 +1,136 @@
+import { expect, Locator } from '@playwright/test';
+
+/**
+ * Determines if a component is a Quasar checkbox, toggle, or radio button
+ * @param element - Playwright locator for the element
+ * @returns Boolean indicating if the element is a check-based component
+ */
+async function isCheckBasedComponent(element: Locator): Promise {
+ const className = await element.getAttribute('class');
+ return ['q-checkbox', 'q-toggle', 'q-radio'].some((item) =>
+ className?.includes(item),
+ );
+}
+
+/**
+ * Selects one or more options from a Quasar QSelect component
+ * @param element - Playwright locator for the QSelect component
+ * @param valueOrTextOrIndex - Value, text content, or index of the option(s) to select
+ */
+export async function selectQSelectOption(
+ element: Locator,
+ valueOrTextOrIndex: string | number | Array,
+) {
+ // Ensure the element is visible and enabled
+ await expect(element).toBeVisible();
+ await expect(element).not.toBeDisabled();
+
+ const hasNativeSelect = await element.evaluate((el) =>
+ el.classList.contains('q-field__native'),
+ );
+ // Handle .q-field__native elements by finding parent .q-select
+ if (hasNativeSelect) {
+ const parentQSelect = element.locator(
+ 'xpath=ancestor::*[contains(@class, "q-select")][1]',
+ );
+ if (await parentQSelect.count()) {
+ element = parentQSelect;
+ }
+ }
+
+ const isMultiple = await element.evaluate((el) =>
+ el.classList.contains('q-select--multiple'),
+ );
+ const values = Array.isArray(valueOrTextOrIndex)
+ ? valueOrTextOrIndex
+ : [valueOrTextOrIndex];
+
+ if (values.length === 0) {
+ throw new Error('Playwright: select requires at least one value');
+ }
+
+ await element.click();
+
+ // Wait for the menu to appear
+ const menu = element.page().locator('.q-menu:visible');
+ await expect(menu).toBeVisible();
+
+ for (const value of values) {
+ let option: Locator;
+ if (typeof value === 'string') {
+ option = menu.locator(`.q-item[role=option]:has-text("${value}")`);
+ } else {
+ option = menu.locator('.q-item[role=option]').nth(value);
+ }
+
+ await expect(option).toBeVisible();
+ await option.click();
+
+ if (!isMultiple) {
+ break;
+ }
+ }
+}
+
+/**
+ * Checks a Quasar checkbox, toggle, or radio component
+ * @param element - Playwright locator for the component
+ */
+export async function checkQuasarComponent(element: Locator) {
+ await expect(element).toBeVisible();
+ await expect(element).not.toBeDisabled();
+
+ const isCheckBased = await isCheckBasedComponent(element);
+ if (!isCheckBased) {
+ await element.check();
+ return;
+ }
+
+ const checked = await element.getAttribute('aria-checked');
+ if (checked !== 'true') {
+ await element.click();
+
+ // Verify the component was actually checked
+ await expect(element).toHaveAttribute('aria-checked', 'true');
+ }
+}
+
+/**
+ * Unchecks a Quasar checkbox or toggle component
+ * @param element - Playwright locator for the component
+ */
+export async function uncheckQuasarComponent(element: Locator) {
+ await expect(element).toBeVisible();
+ await expect(element).not.toBeDisabled();
+
+ const isCheckBased = await isCheckBasedComponent(element);
+ if (!isCheckBased) {
+ await element.uncheck();
+ return;
+ }
+
+ const checked = await element.getAttribute('aria-checked');
+ if (checked !== 'false') {
+ await element.click();
+
+ // Verify the component was actually unchecked
+ await expect(element).toHaveAttribute('aria-checked', 'false');
+ }
+}
+
+/**
+ * Asserts that a Quasar checkbox, toggle, or radio component is checked or unchecked
+ * @param element - Playwright locator for the component
+ * @param expected - Expected checked state (true = checked, false = unchecked)
+ */
+export async function expectQuasarChecked(
+ element: Locator,
+ expected: boolean,
+) {
+ await expect(element).toBeVisible();
+
+ await expect(element).toHaveAttribute(
+ 'aria-checked',
+ expected ? 'true' : 'false',
+ );
+}
diff --git a/packages/e2e-playwright/tsconfig-cjs.json b/packages/e2e-playwright/tsconfig-cjs.json
new file mode 100644
index 00000000..fbf76d10
--- /dev/null
+++ b/packages/e2e-playwright/tsconfig-cjs.json
@@ -0,0 +1,8 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "module": "CommonJS",
+ "outDir": "dist/cjs",
+ "moduleResolution": "node"
+ }
+}
\ No newline at end of file
diff --git a/packages/e2e-playwright/tsconfig.json b/packages/e2e-playwright/tsconfig.json
new file mode 100644
index 00000000..1446681b
--- /dev/null
+++ b/packages/e2e-playwright/tsconfig.json
@@ -0,0 +1,26 @@
+{
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "@utils/*": ["src/utils/*"]
+ },
+ "strict": true,
+ "sourceMap": true,
+ "target": "ESNext",
+ "moduleResolution": "node",
+ "outDir": "dist/esm",
+ "skipLibCheck": true,
+ "esModuleInterop": true,
+ "module": "ESNext",
+ "allowJs": true,
+ "declaration": true,
+ "declarationDir": "dist/types"
+ },
+ "include": [
+ "src/main.ts",
+ "src/ct/main.ts",
+ "coverage.d.ts",
+ "src/utils/coverage.ts",
+ "src/*.js"
+ ]
+}
diff --git a/packages/unit-vitest/package.json b/packages/unit-vitest/package.json
index bcbf5073..00743653 100644
--- a/packages/unit-vitest/package.json
+++ b/packages/unit-vitest/package.json
@@ -33,12 +33,15 @@
"lodash-es": "^4.17.21",
"vite-tsconfig-paths": "^5.1.4"
},
+ "devDependenciesComments": {
+ "rimraf": "Other packages in the monorepo require node <=18, so let's not update it to continue supporting lower versions. Updating with prevent installation of those packages"
+ },
"devDependencies": {
"@types/lodash-es": "^4.17.12",
"@vitest/ui": "^3.1.2",
"@vue/test-utils": "^2.4.6",
"quasar": "^2.18.1",
- "rimraf": "^6.0.1",
+ "rimraf": "^5.0.5",
"vitest": "^3.1.2",
"vue": "^3.5.13"
},
@@ -54,4 +57,4 @@
"optional": true
}
}
-}
+}
\ No newline at end of file
diff --git a/test-vite-app-v1-vite4/.eslintrc.js b/test-vite-app-v1-vite4/.eslintrc.js
index 5396741b..edb94b93 100644
--- a/test-vite-app-v1-vite4/.eslintrc.js
+++ b/test-vite-app-v1-vite4/.eslintrc.js
@@ -111,5 +111,9 @@ module.exports = {
'@typescript-eslint/no-unused-expressions': 'off',
},
},
+ {
+ files: ['src/components/**/*.spec.{js,ts}', 'test/**/*.spec.{js,ts}'],
+ extends: 'plugin:playwright/recommended',
+ },
],
};
diff --git a/test-vite-app-v1-vite4/.gitignore b/test-vite-app-v1-vite4/.gitignore
index 374c78ee..b42b4e91 100644
--- a/test-vite-app-v1-vite4/.gitignore
+++ b/test-vite-app-v1-vite4/.gitignore
@@ -34,3 +34,15 @@ yarn-error.log*
.nyc_output
coverage/
+
+
+# Playwright
+/test-results/
+/playwright-report/
+/blob-report
+/playwright/.cache/
+
+
+# Coverage
+.nyc_output
+/coverage
diff --git a/test-vite-app-v1-vite4/.nycrc b/test-vite-app-v1-vite4/.nycrc
index ad64fc3f..ac43bd45 100644
--- a/test-vite-app-v1-vite4/.nycrc
+++ b/test-vite-app-v1-vite4/.nycrc
@@ -1,3 +1,3 @@
-{
- "extends": "@quasar/quasar-app-extension-testing-e2e-cypress/nyc-config-preset"
-}
+{
+ "extends": "@quasar/quasar-app-extension-testing-e2e-playwright/nyc-preset"
+}
\ No newline at end of file
diff --git a/test-vite-app-v1-vite4/cypress.config.ts b/test-vite-app-v1-vite4/cypress.config.ts
index 13e98c85..df66c4f1 100644
--- a/test-vite-app-v1-vite4/cypress.config.ts
+++ b/test-vite-app-v1-vite4/cypress.config.ts
@@ -15,9 +15,6 @@ export default defineConfig({
baseUrl: 'http://localhost:8080/',
supportFile: 'test/cypress/support/e2e.ts',
specPattern: 'test/cypress/e2e/**/*.cy.{js,jsx,ts,tsx}',
- // Vite takes quite some time for cold startup, we manually set this in the testing repo
- // to avoid timeout problems when running local smoke tests
- defaultCommandTimeout: 10000,
},
component: {
setupNodeEvents(on, config) {
diff --git a/test-vite-app-v1-vite4/package.json b/test-vite-app-v1-vite4/package.json
index b602dffe..4ebffc0f 100644
--- a/test-vite-app-v1-vite4/package.json
+++ b/test-vite-app-v1-vite4/package.json
@@ -11,18 +11,26 @@
"invoke:cypress": "quasar ext invoke @quasar/testing-e2e-cypress && yarn format",
"invoke:all": "yarn invoke:cypress",
"sync:invoke:cypress": "yarn sync:cypress && yarn invoke:cypress",
- "sync:invoke:all": "yarn sync:invoke:cypress",
+ "sync:playwright": "yarn --cwd ../packages/e2e-playwright build:local && yarn add -D ../packages/e2e-playwright",
+ "invoke:playwright": "quasar ext invoke @quasar/testing-e2e-playwright && yarn format",
+ "sync:invoke:playwright": "yarn sync:playwright && yarn invoke:playwright",
+ "sync:invoke:all": "yarn sync:invoke:cypress && yarn sync:invoke:playwright",
"test:cypress": "yarn test:e2e:ci && yarn test:component:ci",
- "test:all": "yarn test:cypress",
+ "test:playwright": "yarn test:e2e:ci && yarn test:component:ci",
+ "test:all": "yarn test:cypress && yarn test:playwright",
+ "sync:invoke:test:playwright": "yarn sync:invoke:playwright && yarn test:playwright",
"sync:invoke:test:cypress": "yarn sync:invoke:cypress && yarn test:cypress",
"sync:invoke:test:all": "yarn sync:invoke:test:cypress",
"lint": "eslint --ext .js,.ts,.vue ./",
"format": "prettier --write \"**/*.{js,ts,vue,scss,html,md,json}\" --ignore-path .gitignore",
- "test": "echo \"See package.json => scripts for available tests.\" && exit 0",
- "test:e2e": "cross-env NODE_ENV=test start-test \"quasar dev\" http-get://127.0.0.1:8080 \"cypress open --e2e\"",
- "test:e2e:ci": "cross-env NODE_ENV=test start-test \"quasar dev\" http-get://127.0.0.1:8080 \"cypress run --e2e\"",
- "test:component": "cross-env NODE_ENV=test cypress open --component",
- "test:component:ci": "cross-env NODE_ENV=test cypress run --component"
+ "test": "yarn test:clear && yarn test:component:ci && yarn test:e2e:ci && yarn coverage-report",
+ "test:e2e": "cross-env NODE_ENV=test VITE_COVERAGE=true playwright test --ui",
+ "test:e2e:ci": "cross-env NODE_ENV=test VITE_COVERAGE=true playwright test",
+ "test:component": "cross-env NODE_ENV=test VITE_COVERAGE=true playwright test -c playwright-ct.config.ts --ui",
+ "test:component:ci": "cross-env NODE_ENV=test VITE_COVERAGE=true playwright test -c playwright-ct.config.ts",
+ "test:clear": "rimraf .nyc_output coverage",
+ "test:report": "playwright show-report",
+ "coverage-report": "nyc report --reporter=html --reporter=text"
},
"dependencies": {
"@quasar/extras": "^1.16.6",
@@ -38,8 +46,11 @@
},
"devDependencies": {
"@intlify/vite-plugin-vue-i18n": "^3.3.1",
+ "@playwright/experimental-ct-vue": "^1.50.0",
+ "@playwright/test": "^1.49.1",
"@quasar/app-vite": "^1.7.1",
"@quasar/quasar-app-extension-testing-e2e-cypress": "../packages/e2e-cypress",
+ "@quasar/quasar-app-extension-testing-e2e-playwright": "../packages/e2e-playwright",
"@types/node": "^18.17.15",
"@typescript-eslint/eslint-plugin": "^5.54.0",
"@typescript-eslint/parser": "^5.54.0",
@@ -49,6 +60,7 @@
"eslint": "^8.49.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-cypress": "^3.6.0",
+ "eslint-plugin-playwright": "^2.1.0",
"eslint-plugin-vue": "^9.17.0",
"prettier": "^3.0.3",
"typescript": "^4.9.5"
diff --git a/test-vite-app-v1-vite4/playwright-ct.config.ts b/test-vite-app-v1-vite4/playwright-ct.config.ts
new file mode 100644
index 00000000..a4a4edc4
--- /dev/null
+++ b/test-vite-app-v1-vite4/playwright-ct.config.ts
@@ -0,0 +1,105 @@
+import { defineConfig, devices } from '@playwright/experimental-ct-vue';
+import vue from '@vitejs/plugin-vue';
+import { quasar, transformAssetUrls } from '@quasar/vite-plugin';
+// import { fileURLToPath } from 'node:url';
+// import AutoImport from 'unplugin-auto-import/vite';
+// import Components from 'unplugin-vue-components/vite';
+
+/**
+ * See https://playwright.dev/docs/test-configuration.
+ */
+export default defineConfig({
+ testDir: './src/components',
+ /* The base directory, relative to the config file, for snapshot files created with toMatchSnapshot and toHaveScreenshot. */
+ snapshotDir: './__snapshots__',
+ /* Maximum time one test can run for. */
+ timeout: 10 * 1000,
+ /* Run tests in files in parallel */
+ fullyParallel: true,
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
+ forbidOnly: !!process.env.CI,
+ /* Retry on CI only */
+ retries: process.env.CI ? 2 : 0,
+ /* Opt out of parallel tests on CI. */
+ workers: process.env.CI ? 1 : undefined,
+ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
+ reporter: 'html',
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
+ use: {
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
+ trace: 'on-first-retry',
+
+ /* Port to use for Playwright component endpoint. */
+ ctPort: 3100,
+
+ ctViteConfig: async () => {
+ const { default: istanbul } = await import('vite-plugin-istanbul');
+ return {
+ build: {
+ sourcemap: true,
+ },
+ plugins: [
+ vue({ template: { transformAssetUrls } }),
+ // AutoImport({
+ // imports: [
+ // 'vue',
+ // 'vue-router',
+ // '@vueuse/head',
+ // 'pinia',
+ // 'quasar',
+ // {
+ // '@/store': ['useStore'],
+ // },
+ // ],
+ // dts: 'src/auto-imports.d.ts',
+ // eslintrc: {
+ // enabled: true,
+ // },
+ // }),
+ // Components({
+ // dirs: ['src/components'],
+ // extensions: ['vue'],
+ // }),
+ quasar({
+ // sassVariables: fileURLToPath(
+ // new URL('./src/quasar-variables.sass', import.meta.url),
+ // ),
+ }),
+
+ // Instrument the code for nyc/istanbul code coverage
+ istanbul({
+ include: ['src/**/*'],
+ exclude: [
+ 'node_modules',
+ 'test/',
+ 'dist/',
+ 'coverage/',
+ '__tests__',
+ ],
+ extension: ['.js', '.ts', '.vue'],
+ requireEnv: true,
+ forceBuildInstrument: true,
+ checkProd: false,
+ cypress: false,
+ }),
+ ],
+ };
+ },
+ },
+
+ /* Configure projects for major browsers */
+ projects: [
+ {
+ name: 'chromium',
+ use: { ...devices['Desktop Chrome'] },
+ },
+ {
+ name: 'firefox',
+ use: { ...devices['Desktop Firefox'] },
+ },
+ {
+ name: 'webkit',
+ use: { ...devices['Desktop Safari'] },
+ },
+ ],
+});
diff --git a/test-vite-app-v1-vite4/playwright.config.ts b/test-vite-app-v1-vite4/playwright.config.ts
new file mode 100644
index 00000000..9fdf0aed
--- /dev/null
+++ b/test-vite-app-v1-vite4/playwright.config.ts
@@ -0,0 +1,79 @@
+import { defineConfig, devices, PlaywrightTestConfig } from '@playwright/test';
+
+/**
+ * Read environment variables from file.
+ * https://github.com/motdotla/dotenv
+ */
+// import dotenv from 'dotenv';
+// import path from 'path';
+// dotenv.config({ path: path.resolve(__dirname, '.env') });
+
+/**
+ * See https://playwright.dev/docs/test-configuration.
+ */
+export default defineConfig({
+ testDir: './test/playwright',
+ /* Run tests in files in parallel */
+ fullyParallel: true,
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
+ forbidOnly: !!process.env.CI,
+ /* Retry on CI only */
+ retries: process.env.CI ? 2 : 0,
+ /* Opt out of parallel tests on CI. */
+ workers: process.env.CI ? 1 : undefined,
+ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
+ reporter: 'html',
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
+ use: {
+ /* Base URL to use in actions like `await page.goto('/')`. */
+ baseURL: 'http://localhost:8080',
+
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
+ trace: 'on-first-retry',
+ },
+
+ /* Configure projects for major browsers */
+ projects: [
+ {
+ name: 'chromium',
+ use: { ...devices['Desktop Chrome'] },
+ },
+
+ {
+ name: 'firefox',
+ use: { ...devices['Desktop Firefox'] },
+ },
+
+ {
+ name: 'webkit',
+ use: { ...devices['Desktop Safari'] },
+ },
+
+ /* Test against mobile viewports. */
+ // {
+ // name: 'Mobile Chrome',
+ // use: { ...devices['Pixel 5'] },
+ // },
+ // {
+ // name: 'Mobile Safari',
+ // use: { ...devices['iPhone 12'] },
+ // },
+
+ /* Test against branded browsers. */
+ // {
+ // name: 'Microsoft Edge',
+ // use: { ...devices['Desktop Edge'], channel: 'msedge' },
+ // },
+ // {
+ // name: 'Google Chrome',
+ // use: { ...devices['Desktop Chrome'], channel: 'chrome' },
+ // },
+ ],
+
+ /* Run your local dev server before starting the tests */
+ webServer: {
+ command: 'quasar dev -p 8080',
+ url: 'http://localhost:8080',
+ reuseExistingServer: !process.env.CI,
+ },
+} as PlaywrightTestConfig);
diff --git a/test-vite-app-v1-vite4/playwright/index.html b/test-vite-app-v1-vite4/playwright/index.html
new file mode 100644
index 00000000..56da0401
--- /dev/null
+++ b/test-vite-app-v1-vite4/playwright/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ Testing Page
+
+
+
+
+
+
diff --git a/test-vite-app-v1-vite4/playwright/index.ts b/test-vite-app-v1-vite4/playwright/index.ts
new file mode 100644
index 00000000..f5265b82
--- /dev/null
+++ b/test-vite-app-v1-vite4/playwright/index.ts
@@ -0,0 +1,20 @@
+// See https://quasar.dev/start/vite-plugin
+import 'quasar/src/css/index.sass';
+import '../src/css/app.scss';
+import { Quasar, Dialog } from 'quasar';
+import { beforeMount } from '@playwright/experimental-ct-vue/hooks';
+import '@quasar/extras/material-icons/material-icons.css';
+// import '@quasar/extras/mdi-v7/mdi-v7.css';
+
+beforeMount(async ({ app }) => {
+ // Setup other stuff you need before mounting the component. You can setup i18n, pinia, etc here.
+ // See https://playwright.dev/docs/test-components#frequently-asked-questions
+ app.use(Quasar, {
+ plugins: {
+ // Setup plugins used in your components
+ // Notify,
+ // Loading
+ Dialog,
+ },
+ });
+});
diff --git a/test-vite-app-v1-vite4/quasar.extensions.json b/test-vite-app-v1-vite4/quasar.extensions.json
index 03cb9431..7029904a 100644
--- a/test-vite-app-v1-vite4/quasar.extensions.json
+++ b/test-vite-app-v1-vite4/quasar.extensions.json
@@ -2,5 +2,11 @@
"@quasar/testing-e2e-cypress": {
"port": 8080,
"options": ["code-coverage"]
+ },
+ "@quasar/testing-e2e-playwright": {
+ "port": 8080,
+ "githubWorkflow": true,
+ "installBrowsers": true,
+ "enableCodeCoverage": true
}
}
diff --git a/test-vite-app-v1-vite4/src/components/AppButton.vue b/test-vite-app-v1-vite4/src/components/AppButton.vue
new file mode 100644
index 00000000..a840fe38
--- /dev/null
+++ b/test-vite-app-v1-vite4/src/components/AppButton.vue
@@ -0,0 +1,23 @@
+
+
+
+
+
diff --git a/test-vite-app-v1-vite4/src/components/AppCheckComponents.vue b/test-vite-app-v1-vite4/src/components/AppCheckComponents.vue
new file mode 100644
index 00000000..623ccac1
--- /dev/null
+++ b/test-vite-app-v1-vite4/src/components/AppCheckComponents.vue
@@ -0,0 +1,30 @@
+
+
+
+
+ Value1
+ Value2
+
+
+
diff --git a/test-vite-app-v1-vite4/src/components/AppDark.vue b/test-vite-app-v1-vite4/src/components/AppDark.vue
new file mode 100644
index 00000000..a5f2282b
--- /dev/null
+++ b/test-vite-app-v1-vite4/src/components/AppDark.vue
@@ -0,0 +1,35 @@
+
+
+ {{ $q.dark.isActive ? 'Dark ' : 'Light' }} content
+
+
+
+
+
+
diff --git a/test-vite-app-v1-vite4/src/components/AppDate.vue b/test-vite-app-v1-vite4/src/components/AppDate.vue
new file mode 100644
index 00000000..41b1ea7a
--- /dev/null
+++ b/test-vite-app-v1-vite4/src/components/AppDate.vue
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test-vite-app-v1-vite4/src/components/AppDialog.vue b/test-vite-app-v1-vite4/src/components/AppDialog.vue
new file mode 100644
index 00000000..0d2ed487
--- /dev/null
+++ b/test-vite-app-v1-vite4/src/components/AppDialog.vue
@@ -0,0 +1,71 @@
+
+
+
+
+ {{ message }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test-vite-app-v1-vite4/src/components/AppDrawer.vue b/test-vite-app-v1-vite4/src/components/AppDrawer.vue
new file mode 100644
index 00000000..f65b882e
--- /dev/null
+++ b/test-vite-app-v1-vite4/src/components/AppDrawer.vue
@@ -0,0 +1,33 @@
+
+
+
+
+ Am I on screen?
+
+
+
+
+
diff --git a/test-vite-app-v1-vite4/src/components/AppMenu.vue b/test-vite-app-v1-vite4/src/components/AppMenu.vue
new file mode 100644
index 00000000..a28ec48e
--- /dev/null
+++ b/test-vite-app-v1-vite4/src/components/AppMenu.vue
@@ -0,0 +1,22 @@
+
+
+
+
+
+ Item 1
+
+
+ Item 2
+
+
+
+
+
+
+
diff --git a/test-vite-app-v1-vite4/src/components/AppPageSticky.vue b/test-vite-app-v1-vite4/src/components/AppPageSticky.vue
new file mode 100644
index 00000000..25861bc7
--- /dev/null
+++ b/test-vite-app-v1-vite4/src/components/AppPageSticky.vue
@@ -0,0 +1,21 @@
+
+
+
+ {{ title }}
+
+
+
+
+
diff --git a/test-vite-app-v1-vite4/src/components/AppSelect.vue b/test-vite-app-v1-vite4/src/components/AppSelect.vue
new file mode 100644
index 00000000..fb19c0b4
--- /dev/null
+++ b/test-vite-app-v1-vite4/src/components/AppSelect.vue
@@ -0,0 +1,54 @@
+
+
+
+ {{ selected }}
+
+
+
diff --git a/test-vite-app-v1-vite4/src/components/AppTooltip.vue b/test-vite-app-v1-vite4/src/components/AppTooltip.vue
new file mode 100644
index 00000000..1ab513cb
--- /dev/null
+++ b/test-vite-app-v1-vite4/src/components/AppTooltip.vue
@@ -0,0 +1,28 @@
+
+
+ Button
+
+ Here I am!
+
+
+
+
+
diff --git a/test-vite-app-v1-vite4/src/components/ColorAssertion.vue b/test-vite-app-v1-vite4/src/components/ColorAssertion.vue
new file mode 100644
index 00000000..841cd639
--- /dev/null
+++ b/test-vite-app-v1-vite4/src/components/ColorAssertion.vue
@@ -0,0 +1,3 @@
+
+ Text1
+
diff --git a/test-vite-app-v1-vite4/src/components/QuasarCheckComponents.vue b/test-vite-app-v1-vite4/src/components/QuasarCheckComponents.vue
index f49ea26b..2678290e 100644
--- a/test-vite-app-v1-vite4/src/components/QuasarCheckComponents.vue
+++ b/test-vite-app-v1-vite4/src/components/QuasarCheckComponents.vue
@@ -1,9 +1,21 @@
-
-
+
+
- Value1
- Value2
+ Value1
+ Value2
diff --git a/test-vite-app-v1-vite4/src/components/QuasarDate.vue b/test-vite-app-v1-vite4/src/components/QuasarDate.vue
index 962b4e0a..30d185fa 100644
--- a/test-vite-app-v1-vite4/src/components/QuasarDate.vue
+++ b/test-vite-app-v1-vite4/src/components/QuasarDate.vue
@@ -1,11 +1,12 @@
-
+
-
+
diff --git a/test-vite-app-v1-vite4/src/components/QuasarDialog.vue b/test-vite-app-v1-vite4/src/components/QuasarDialog.vue
index c88b9930..6451da46 100644
--- a/test-vite-app-v1-vite4/src/components/QuasarDialog.vue
+++ b/test-vite-app-v1-vite4/src/components/QuasarDialog.vue
@@ -8,6 +8,7 @@
- Am I on screen?
+ Am I on screen?
diff --git a/test-vite-app-v1-vite4/src/components/QuasarMenu.vue b/test-vite-app-v1-vite4/src/components/QuasarMenu.vue
index daed3aa4..4ff02d2e 100644
--- a/test-vite-app-v1-vite4/src/components/QuasarMenu.vue
+++ b/test-vite-app-v1-vite4/src/components/QuasarMenu.vue
@@ -1,5 +1,5 @@
-
+
diff --git a/test-vite-app-v1-vite4/src/components/QuasarPageSticky.vue b/test-vite-app-v1-vite4/src/components/QuasarPageSticky.vue
index 7c8223d3..9fce30f1 100644
--- a/test-vite-app-v1-vite4/src/components/QuasarPageSticky.vue
+++ b/test-vite-app-v1-vite4/src/components/QuasarPageSticky.vue
@@ -1,6 +1,12 @@
-
+
{{ title }}
diff --git a/test-vite-app-v1-vite4/src/components/QuasarSelect.vue b/test-vite-app-v1-vite4/src/components/QuasarSelect.vue
index 13d763f0..eefc5e5a 100644
--- a/test-vite-app-v1-vite4/src/components/QuasarSelect.vue
+++ b/test-vite-app-v1-vite4/src/components/QuasarSelect.vue
@@ -2,6 +2,7 @@
- {{ selected }}
+ {{ selected }}
diff --git a/test-vite-app-v1-vite4/test/playwright/wrappers/LayoutContainer.vue b/test-vite-app-v1-vite4/test/playwright/wrappers/LayoutContainer.vue
new file mode 100644
index 00000000..079fe47a
--- /dev/null
+++ b/test-vite-app-v1-vite4/test/playwright/wrappers/LayoutContainer.vue
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
diff --git a/test-vite-app-v1-vite4/tsconfig.json b/test-vite-app-v1-vite4/tsconfig.json
index bd323f03..f83f70cb 100644
--- a/test-vite-app-v1-vite4/tsconfig.json
+++ b/test-vite-app-v1-vite4/tsconfig.json
@@ -1,6 +1,9 @@
{
"extends": "@quasar/app-vite/tsconfig-preset",
"compilerOptions": {
- "baseUrl": "."
+ "baseUrl": ".",
+ "moduleResolution": "nodenext",
+ "module": "NodeNext",
+ "target": "ESNext"
}
}
diff --git a/test-vite-app-v1-vite4/yarn.lock b/test-vite-app-v1-vite4/yarn.lock
index 4a29d5b6..f43aed38 100644
--- a/test-vite-app-v1-vite4/yarn.lock
+++ b/test-vite-app-v1-vite4/yarn.lock
@@ -23,12 +23,47 @@
"@babel/highlight" "^7.22.13"
chalk "^2.4.2"
+"@babel/code-frame@^7.27.1":
+ version "7.27.1"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be"
+ integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.27.1"
+ js-tokens "^4.0.0"
+ picocolors "^1.1.1"
+
"@babel/compat-data@^7.22.9":
version "7.22.9"
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.9.tgz#71cdb00a1ce3a329ce4cbec3a44f9fef35669730"
integrity sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==
-"@babel/core@^7.12.3", "@babel/core@^7.7.5":
+"@babel/compat-data@^7.27.2":
+ version "7.27.2"
+ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.27.2.tgz#4183f9e642fd84e74e3eea7ffa93a412e3b102c9"
+ integrity sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==
+
+"@babel/core@^7.23.9":
+ version "7.27.1"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.27.1.tgz#89de51e86bd12246003e3524704c49541b16c3e6"
+ integrity sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==
+ dependencies:
+ "@ampproject/remapping" "^2.2.0"
+ "@babel/code-frame" "^7.27.1"
+ "@babel/generator" "^7.27.1"
+ "@babel/helper-compilation-targets" "^7.27.1"
+ "@babel/helper-module-transforms" "^7.27.1"
+ "@babel/helpers" "^7.27.1"
+ "@babel/parser" "^7.27.1"
+ "@babel/template" "^7.27.1"
+ "@babel/traverse" "^7.27.1"
+ "@babel/types" "^7.27.1"
+ convert-source-map "^2.0.0"
+ debug "^4.1.0"
+ gensync "^1.0.0-beta.2"
+ json5 "^2.2.3"
+ semver "^6.3.1"
+
+"@babel/core@^7.7.5":
version "7.22.17"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.17.tgz#2f9b0b395985967203514b24ee50f9fd0639c866"
integrity sha512-2EENLmhpwplDux5PSsZnSbnSkB3tZ6QTksgO25xwEL7pIDcNOMhF5v/s6RzwjMZzZzw9Ofc30gHv5ChCC8pifQ==
@@ -59,6 +94,17 @@
"@jridgewell/trace-mapping" "^0.3.17"
jsesc "^2.5.1"
+"@babel/generator@^7.27.1":
+ version "7.27.1"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.27.1.tgz#862d4fad858f7208edd487c28b58144036b76230"
+ integrity sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==
+ dependencies:
+ "@babel/parser" "^7.27.1"
+ "@babel/types" "^7.27.1"
+ "@jridgewell/gen-mapping" "^0.3.5"
+ "@jridgewell/trace-mapping" "^0.3.25"
+ jsesc "^3.0.2"
+
"@babel/helper-compilation-targets@^7.22.15":
version "7.22.15"
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz#0698fc44551a26cf29f18d4662d5bf545a6cfc52"
@@ -70,6 +116,17 @@
lru-cache "^5.1.1"
semver "^6.3.1"
+"@babel/helper-compilation-targets@^7.27.1":
+ version "7.27.2"
+ resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz#46a0f6efab808d51d29ce96858dd10ce8732733d"
+ integrity sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==
+ dependencies:
+ "@babel/compat-data" "^7.27.2"
+ "@babel/helper-validator-option" "^7.27.1"
+ browserslist "^4.24.0"
+ lru-cache "^5.1.1"
+ semver "^6.3.1"
+
"@babel/helper-environment-visitor@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz#f06dd41b7c1f44e1f8da6c4055b41ab3a09a7e98"
@@ -97,6 +154,14 @@
dependencies:
"@babel/types" "^7.22.15"
+"@babel/helper-module-imports@^7.27.1":
+ version "7.27.1"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz#7ef769a323e2655e126673bb6d2d6913bbead204"
+ integrity sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==
+ dependencies:
+ "@babel/traverse" "^7.27.1"
+ "@babel/types" "^7.27.1"
+
"@babel/helper-module-transforms@^7.22.17":
version "7.22.17"
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.17.tgz#7edf129097a51ccc12443adbc6320e90eab76693"
@@ -108,6 +173,15 @@
"@babel/helper-split-export-declaration" "^7.22.6"
"@babel/helper-validator-identifier" "^7.22.15"
+"@babel/helper-module-transforms@^7.27.1":
+ version "7.27.1"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz#e1663b8b71d2de948da5c4fb2a20ca4f3ec27a6f"
+ integrity sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==
+ dependencies:
+ "@babel/helper-module-imports" "^7.27.1"
+ "@babel/helper-validator-identifier" "^7.27.1"
+ "@babel/traverse" "^7.27.1"
+
"@babel/helper-simple-access@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de"
@@ -127,16 +201,31 @@
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f"
integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==
+"@babel/helper-string-parser@^7.27.1":
+ version "7.27.1"
+ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687"
+ integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==
+
"@babel/helper-validator-identifier@^7.22.15", "@babel/helper-validator-identifier@^7.22.5":
version "7.22.15"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz#601fa28e4cc06786c18912dca138cec73b882044"
integrity sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ==
+"@babel/helper-validator-identifier@^7.27.1":
+ version "7.27.1"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8"
+ integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==
+
"@babel/helper-validator-option@^7.22.15":
version "7.22.15"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz#694c30dfa1d09a6534cdfcafbe56789d36aba040"
integrity sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==
+"@babel/helper-validator-option@^7.27.1":
+ version "7.27.1"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f"
+ integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==
+
"@babel/helpers@^7.22.15":
version "7.22.15"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.22.15.tgz#f09c3df31e86e3ea0b7ff7556d85cdebd47ea6f1"
@@ -146,6 +235,14 @@
"@babel/traverse" "^7.22.15"
"@babel/types" "^7.22.15"
+"@babel/helpers@^7.27.1":
+ version "7.27.1"
+ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.27.1.tgz#ffc27013038607cdba3288e692c3611c06a18aa4"
+ integrity sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==
+ dependencies:
+ "@babel/template" "^7.27.1"
+ "@babel/types" "^7.27.1"
+
"@babel/highlight@^7.22.13":
version "7.22.13"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.13.tgz#9cda839e5d3be9ca9e8c26b6dd69e7548f0cbf16"
@@ -155,7 +252,7 @@
chalk "^2.4.2"
js-tokens "^4.0.0"
-"@babel/parser@^7.14.7", "@babel/parser@^7.22.15", "@babel/parser@^7.22.16":
+"@babel/parser@^7.22.15", "@babel/parser@^7.22.16":
version "7.22.16"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.16.tgz#180aead7f247305cce6551bea2720934e2fa2c95"
integrity sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==
@@ -165,6 +262,13 @@
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.6.tgz#ba1c9e512bda72a47e285ae42aff9d2a635a9e3b"
integrity sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==
+"@babel/parser@^7.23.9", "@babel/parser@^7.27.1", "@babel/parser@^7.27.2":
+ version "7.27.2"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.27.2.tgz#577518bedb17a2ce4212afd052e01f7df0941127"
+ integrity sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==
+ dependencies:
+ "@babel/types" "^7.27.1"
+
"@babel/template@^7.22.15", "@babel/template@^7.22.5":
version "7.22.15"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38"
@@ -174,6 +278,15 @@
"@babel/parser" "^7.22.15"
"@babel/types" "^7.22.15"
+"@babel/template@^7.27.1":
+ version "7.27.2"
+ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.2.tgz#fa78ceed3c4e7b63ebf6cb39e5852fca45f6809d"
+ integrity sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==
+ dependencies:
+ "@babel/code-frame" "^7.27.1"
+ "@babel/parser" "^7.27.2"
+ "@babel/types" "^7.27.1"
+
"@babel/traverse@^7.22.15", "@babel/traverse@^7.22.17":
version "7.22.17"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.17.tgz#b23c203ab3707e3be816043081b4a994fcacec44"
@@ -190,6 +303,19 @@
debug "^4.1.0"
globals "^11.1.0"
+"@babel/traverse@^7.27.1":
+ version "7.27.1"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.27.1.tgz#4db772902b133bbddd1c4f7a7ee47761c1b9f291"
+ integrity sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==
+ dependencies:
+ "@babel/code-frame" "^7.27.1"
+ "@babel/generator" "^7.27.1"
+ "@babel/parser" "^7.27.1"
+ "@babel/template" "^7.27.1"
+ "@babel/types" "^7.27.1"
+ debug "^4.3.1"
+ globals "^11.1.0"
+
"@babel/types@^7.22.15", "@babel/types@^7.22.17", "@babel/types@^7.22.5":
version "7.22.17"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.17.tgz#f753352c4610ffddf9c8bc6823f9ff03e2303eee"
@@ -199,6 +325,14 @@
"@babel/helper-validator-identifier" "^7.22.15"
to-fast-properties "^2.0.0"
+"@babel/types@^7.27.1":
+ version "7.27.1"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.27.1.tgz#9defc53c16fc899e46941fc6901a9eea1c9d8560"
+ integrity sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==
+ dependencies:
+ "@babel/helper-string-parser" "^7.27.1"
+ "@babel/helper-validator-identifier" "^7.27.1"
+
"@colors/colors@1.5.0":
version "1.5.0"
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
@@ -477,6 +611,18 @@
fast-glob "^3.2.5"
source-map "0.6.1"
+"@isaacs/cliui@^8.0.2":
+ version "8.0.2"
+ resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550"
+ integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==
+ dependencies:
+ string-width "^5.1.2"
+ string-width-cjs "npm:string-width@^4.2.0"
+ strip-ansi "^7.0.1"
+ strip-ansi-cjs "npm:strip-ansi@^6.0.1"
+ wrap-ansi "^8.1.0"
+ wrap-ansi-cjs "npm:wrap-ansi@^7.0.0"
+
"@istanbuljs/load-nyc-config@^1.0.0", "@istanbuljs/load-nyc-config@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced"
@@ -488,7 +634,14 @@
js-yaml "^3.13.1"
resolve-from "^5.0.0"
-"@istanbuljs/schema@^0.1.2":
+"@istanbuljs/nyc-config-typescript@^1.0.2":
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/@istanbuljs/nyc-config-typescript/-/nyc-config-typescript-1.0.2.tgz#1f5235b28540a07219ae0dd42014912a0b19cf89"
+ integrity sha512-iKGIyMoyJuFnJRSVTZ78POIRvNnwZaWIf8vG4ZS3rQq58MMDrqEX2nnzx0R28V2X8JvmKYiqY9FP2hlJsm8A0w==
+ dependencies:
+ "@istanbuljs/schema" "^0.1.2"
+
+"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3":
version "0.1.3"
resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98"
integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==
@@ -502,6 +655,15 @@
"@jridgewell/sourcemap-codec" "^1.4.10"
"@jridgewell/trace-mapping" "^0.3.9"
+"@jridgewell/gen-mapping@^0.3.5":
+ version "0.3.8"
+ resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz#4f0e06362e01362f823d348f1872b08f666d8142"
+ integrity sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==
+ dependencies:
+ "@jridgewell/set-array" "^1.2.1"
+ "@jridgewell/sourcemap-codec" "^1.4.10"
+ "@jridgewell/trace-mapping" "^0.3.24"
+
"@jridgewell/resolve-uri@^3.1.0":
version "3.1.1"
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721"
@@ -512,6 +674,11 @@
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
+"@jridgewell/set-array@^1.2.1":
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280"
+ integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==
+
"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.4.15":
version "1.4.15"
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
@@ -525,6 +692,14 @@
"@jridgewell/resolve-uri" "^3.1.0"
"@jridgewell/sourcemap-codec" "^1.4.14"
+"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25":
+ version "0.3.25"
+ resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0"
+ integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==
+ dependencies:
+ "@jridgewell/resolve-uri" "^3.1.0"
+ "@jridgewell/sourcemap-codec" "^1.4.14"
+
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
@@ -551,6 +726,35 @@
resolved "https://registry.yarnpkg.com/@one-ini/wasm/-/wasm-0.1.1.tgz#6013659736c9dbfccc96e8a9c2b3de317df39323"
integrity sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==
+"@pkgjs/parseargs@^0.11.0":
+ version "0.11.0"
+ resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
+ integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
+
+"@playwright/experimental-ct-core@1.52.0":
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/@playwright/experimental-ct-core/-/experimental-ct-core-1.52.0.tgz#3fa18bc7952deaf141ad2a2c1cdfcff1de6c7192"
+ integrity sha512-DiDEammXxt8OIFDfoNitoOZyHFJAu6aYi0abmHl0IZgOQHxccP6UX50aTEnSTTUWCfwUWB0Vd8TKJ6w122WJEw==
+ dependencies:
+ playwright "1.52.0"
+ playwright-core "1.52.0"
+ vite "^6.2.6"
+
+"@playwright/experimental-ct-vue@^1.50.0":
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/@playwright/experimental-ct-vue/-/experimental-ct-vue-1.52.0.tgz#8c5ca57e98def53e6befeadb0a433a9141d133b3"
+ integrity sha512-MaUVEZZ+eo/UH/qWLwUzDl2SgjYyGQUVrGFVayUX07TASS4FDMRV8f8Jjkk0t7iYeFfWE2ZyZS1muLeWeP7qXg==
+ dependencies:
+ "@playwright/experimental-ct-core" "1.52.0"
+ "@vitejs/plugin-vue" "^5.2.0"
+
+"@playwright/test@^1.49.1":
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.52.0.tgz#267ec595b43a8f4fa5e444ea503689629e91a5b8"
+ integrity sha512-uh6W7sb55hl7D6vsAeA+V2p5JnlAqzhqFyF0VcJkKZXkgnFcVG9PziERRHQfPLfNGx1C292a4JqbWzhR8L4R1g==
+ dependencies:
+ playwright "1.52.0"
+
"@quasar/app-vite@^1.7.1":
version "1.7.1"
resolved "https://registry.yarnpkg.com/@quasar/app-vite/-/app-vite-1.7.1.tgz#2e114a703b4673ddb710a68bf3433bd221a59ae7"
@@ -597,14 +801,22 @@
integrity sha512-yHvp2Z73LuS29fhjE+dSzUvEKGCuTTy+WGIsAYxbnhBVW2rTYlYmFQfGdOPdzNreHZh+G/1D56n0Q6ClZxJHKg==
"@quasar/quasar-app-extension-testing-e2e-cypress@../packages/e2e-cypress":
- version "6.2.0"
+ version "6.2.1"
dependencies:
"@cypress/code-coverage" "^3.12.26"
cross-env "^7.0.3"
lodash "^4.17.21"
nyc "^15.1.0"
start-server-and-test "^2.0.3"
- vite-plugin-istanbul "^5.0.0"
+ vite-plugin-istanbul "^7.0.0"
+
+"@quasar/quasar-app-extension-testing-e2e-playwright@../packages/e2e-playwright":
+ version "0.0.1"
+ dependencies:
+ "@istanbuljs/nyc-config-typescript" "^1.0.2"
+ cross-env "^7.0.3"
+ nyc "^17.1.0"
+ vite-plugin-istanbul "^7.0.0"
"@quasar/render-ssr-error@^1.0.3":
version "1.0.3"
@@ -878,7 +1090,7 @@
"@typescript-eslint/types" "5.62.0"
eslint-visitor-keys "^3.3.0"
-"@vitejs/plugin-vue@^2.2.0", "@vitejs/plugin-vue@^4.0.0":
+"@vitejs/plugin-vue@^2.2.0", "@vitejs/plugin-vue@^4.0.0", "@vitejs/plugin-vue@^5.2.0":
version "4.6.0"
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-4.6.0.tgz#6e1011303f8224e04d339756f1fa398ba79fc0b3"
integrity sha512-XHuyFdAikWRmHuAd89FOyUGIjrBU5KlxJtyi2hVeR9ySGFxQwE0bl5xAQju/ArMq5azdBivY4d+D2yPKwoYWUg==
@@ -1009,6 +1221,11 @@ acorn@^7.1.1, acorn@^7.4.1:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
+acorn@^8.14.0:
+ version "8.14.1"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb"
+ integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==
+
acorn@^8.9.0:
version "8.10.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5"
@@ -1059,6 +1276,11 @@ ansi-regex@^5.0.1:
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
+ansi-regex@^6.0.1:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654"
+ integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==
+
ansi-styles@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
@@ -1073,6 +1295,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
dependencies:
color-convert "^2.0.1"
+ansi-styles@^6.1.0:
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5"
+ integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==
+
anymatch@~3.1.2:
version "3.1.3"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e"
@@ -1341,6 +1568,16 @@ browserslist@^4.21.10, browserslist@^4.21.9:
node-releases "^2.0.13"
update-browserslist-db "^1.0.11"
+browserslist@^4.24.0:
+ version "4.24.5"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.5.tgz#aa0f5b8560fe81fde84c6dcb38f759bafba0e11b"
+ integrity sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==
+ dependencies:
+ caniuse-lite "^1.0.30001716"
+ electron-to-chromium "^1.5.149"
+ node-releases "^2.0.19"
+ update-browserslist-db "^1.1.3"
+
buffer-crc32@^0.2.1, buffer-crc32@^0.2.13, buffer-crc32@~0.2.3:
version "0.2.13"
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
@@ -1426,6 +1663,11 @@ caniuse-lite@^1.0.30001517, caniuse-lite@^1.0.30001520:
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001534.tgz#f24a9b2a6d39630bac5c132b5dff89b39a12e7dd"
integrity sha512-vlPVrhsCS7XaSh2VvWluIQEzVhefrUQcEsQWSS5A5V+dM07uv1qHeQzAOTGIMy9i3e9bH15+muvI/UHojVgS/Q==
+caniuse-lite@^1.0.30001716:
+ version "1.0.30001717"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001717.tgz#5d9fec5ce09796a1893013825510678928aca129"
+ integrity sha512-auPpttCq6BDEG8ZAuHJIplGw6GODhjw+/11e7IjpnYCxZcW/ONgPs0KVBJ0d1bY3e2+7PRe5RCLyP+PfwVgkYw==
+
caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
@@ -1682,6 +1924,11 @@ convert-source-map@^1.7.0:
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f"
integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==
+convert-source-map@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a"
+ integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==
+
cookie-signature@1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
@@ -1731,6 +1978,15 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
shebang-command "^2.0.0"
which "^2.0.1"
+cross-spawn@^7.0.6:
+ version "7.0.6"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
+ integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
+ dependencies:
+ path-key "^3.1.0"
+ shebang-command "^2.0.0"
+ which "^2.0.1"
+
cssesc@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
@@ -1907,6 +2163,11 @@ duplexer@~0.1.1:
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
+eastasianwidth@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb"
+ integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==
+
ecc-jsbn@~0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
@@ -1935,6 +2196,11 @@ electron-to-chromium@^1.4.477:
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.519.tgz#01b9bc3f1bb50c4971bdd1eeca6d9a73575bd581"
integrity sha512-kqs9oGYL4UFVkLKhqCTgBCYZv+wZ374yABDMqlDda9HvlkQxvSr7kgf4hfWVjMieDbX+1MwPHFBsOGCMIBaFKg==
+electron-to-chromium@^1.5.149:
+ version "1.5.151"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.151.tgz#5edd6c17e1b2f14b4662c41b9379f96cc8c2bb7c"
+ integrity sha512-Rl6uugut2l9sLojjS4H4SAr3A4IgACMLgpuEMPYCVcKydzfyPrn5absNRju38IhQOf/NwjJY8OGWjlteqYeBCA==
+
elementtree@0.1.7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/elementtree/-/elementtree-0.1.7.tgz#9ac91be6e52fb6e6244c4e54a4ac3ed8ae8e29c0"
@@ -1947,6 +2213,11 @@ emoji-regex@^8.0.0:
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
+emoji-regex@^9.2.2:
+ version "9.2.2"
+ resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
+ integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
+
encodeurl@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
@@ -2158,6 +2429,11 @@ escalade@^3.1.1:
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
+escalade@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5"
+ integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==
+
escape-html@~1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
@@ -2185,6 +2461,13 @@ eslint-plugin-cypress@^3.6.0:
dependencies:
globals "^13.20.0"
+eslint-plugin-playwright@^2.1.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-playwright/-/eslint-plugin-playwright-2.2.0.tgz#d7eda21e670274fc0c006e11ba5cc2c8417b2a6e"
+ integrity sha512-qSQpAw7RcSzE3zPp8FMGkthaCWovHZ/BsXtpmnGax9vQLIovlh1bsZHEa2+j2lv9DWhnyeLM/qZmp7ffQZfQvg==
+ dependencies:
+ globals "^13.23.0"
+
eslint-plugin-vue@^9.17.0:
version "9.17.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-9.17.0.tgz#4501547373f246547083482838b4c8f4b28e5932"
@@ -2231,6 +2514,11 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
+eslint-visitor-keys@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45"
+ integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==
+
eslint@^8.49.0:
version "8.49.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.49.0.tgz#09d80a89bdb4edee2efcf6964623af1054bf6d42"
@@ -2274,6 +2562,15 @@ eslint@^8.49.0:
strip-ansi "^6.0.1"
text-table "^0.2.0"
+espree@^10.3.0:
+ version "10.3.0"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-10.3.0.tgz#29267cf5b0cb98735b65e64ba07e0ed49d1eed8a"
+ integrity sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==
+ dependencies:
+ acorn "^8.14.0"
+ acorn-jsx "^5.3.2"
+ eslint-visitor-keys "^4.2.0"
+
espree@^6.0.0:
version "6.2.1"
resolved "https://registry.yarnpkg.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a"
@@ -2605,6 +2902,14 @@ foreground-child@^2.0.0:
cross-spawn "^7.0.0"
signal-exit "^3.0.2"
+foreground-child@^3.1.0, foreground-child@^3.3.0:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f"
+ integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==
+ dependencies:
+ cross-spawn "^7.0.6"
+ signal-exit "^4.0.1"
+
forever-agent@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
@@ -2683,6 +2988,11 @@ fs.realpath@^1.0.0:
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
+fsevents@2.3.2:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
+ integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
+
fsevents@~2.3.2:
version "2.3.3"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
@@ -2787,6 +3097,18 @@ glob-parent@^6.0.2:
dependencies:
is-glob "^4.0.3"
+glob@^10.4.1:
+ version "10.4.5"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956"
+ integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==
+ dependencies:
+ foreground-child "^3.1.0"
+ jackspeak "^3.1.2"
+ minimatch "^9.0.4"
+ minipass "^7.1.2"
+ package-json-from-dist "^1.0.0"
+ path-scurry "^1.11.1"
+
glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.3:
version "7.2.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
@@ -2829,6 +3151,13 @@ globals@^13.19.0, globals@^13.20.0:
dependencies:
type-fest "^0.20.2"
+globals@^13.23.0:
+ version "13.24.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171"
+ integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==
+ dependencies:
+ type-fest "^0.20.2"
+
globby@11.1.0, globby@^11.1.0:
version "11.1.0"
resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
@@ -3190,16 +3519,16 @@ istanbul-lib-instrument@^4.0.0:
istanbul-lib-coverage "^3.0.0"
semver "^6.3.0"
-istanbul-lib-instrument@^5.1.0:
- version "5.2.1"
- resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d"
- integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==
+istanbul-lib-instrument@^6.0.2, istanbul-lib-instrument@^6.0.3:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz#fa15401df6c15874bcb2105f773325d78c666765"
+ integrity sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==
dependencies:
- "@babel/core" "^7.12.3"
- "@babel/parser" "^7.14.7"
- "@istanbuljs/schema" "^0.1.2"
+ "@babel/core" "^7.23.9"
+ "@babel/parser" "^7.23.9"
+ "@istanbuljs/schema" "^0.1.3"
istanbul-lib-coverage "^3.2.0"
- semver "^6.3.0"
+ semver "^7.5.4"
istanbul-lib-processinfo@^2.0.2:
version "2.0.3"
@@ -3239,6 +3568,15 @@ istanbul-reports@^3.0.2:
html-escaper "^2.0.0"
istanbul-lib-report "^3.0.0"
+jackspeak@^3.1.2:
+ version "3.4.3"
+ resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a"
+ integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==
+ dependencies:
+ "@isaacs/cliui" "^8.0.2"
+ optionalDependencies:
+ "@pkgjs/parseargs" "^0.11.0"
+
joi@^17.11.0:
version "17.12.2"
resolved "https://registry.yarnpkg.com/joi/-/joi-17.12.2.tgz#283a664dabb80c7e52943c557aab82faea09f521"
@@ -3290,6 +3628,11 @@ jsesc@^2.5.1:
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
+jsesc@^3.0.2:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d"
+ integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==
+
json-buffer@3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
@@ -3493,6 +3836,11 @@ lower-case@^1.1.1:
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
integrity sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==
+lru-cache@^10.2.0:
+ version "10.4.3"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119"
+ integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==
+
lru-cache@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
@@ -3614,11 +3962,23 @@ minimatch@^5.0.1, minimatch@^5.1.0:
dependencies:
brace-expansion "^2.0.1"
+minimatch@^9.0.4:
+ version "9.0.5"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5"
+ integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==
+ dependencies:
+ brace-expansion "^2.0.1"
+
minimist@^1.2.6, minimist@^1.2.8:
version "1.2.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
+"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2:
+ version "7.1.2"
+ resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707"
+ integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==
+
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
@@ -3683,6 +4043,11 @@ node-releases@^2.0.13:
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d"
integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==
+node-releases@^2.0.19:
+ version "2.0.19"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314"
+ integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==
+
nopt@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-6.0.0.tgz#245801d8ebf409c6df22ab9d95b65e1309cdb16d"
@@ -3747,6 +4112,39 @@ nyc@15.1.0, nyc@^15.1.0:
test-exclude "^6.0.0"
yargs "^15.0.2"
+nyc@^17.1.0:
+ version "17.1.0"
+ resolved "https://registry.yarnpkg.com/nyc/-/nyc-17.1.0.tgz#b6349a401a62ffeb912bd38ea9a018839fdb6eb1"
+ integrity sha512-U42vQ4czpKa0QdI1hu950XuNhYqgoM+ZF1HT+VuUHL9hPfDPVvNQyltmMqdE9bUHMVa+8yNbc3QKTj8zQhlVxQ==
+ dependencies:
+ "@istanbuljs/load-nyc-config" "^1.0.0"
+ "@istanbuljs/schema" "^0.1.2"
+ caching-transform "^4.0.0"
+ convert-source-map "^1.7.0"
+ decamelize "^1.2.0"
+ find-cache-dir "^3.2.0"
+ find-up "^4.1.0"
+ foreground-child "^3.3.0"
+ get-package-type "^0.1.0"
+ glob "^7.1.6"
+ istanbul-lib-coverage "^3.0.0"
+ istanbul-lib-hook "^3.0.0"
+ istanbul-lib-instrument "^6.0.2"
+ istanbul-lib-processinfo "^2.0.2"
+ istanbul-lib-report "^3.0.0"
+ istanbul-lib-source-maps "^4.0.0"
+ istanbul-reports "^3.0.2"
+ make-dir "^3.0.0"
+ node-preload "^0.2.1"
+ p-map "^3.0.0"
+ process-on-spawn "^1.0.0"
+ resolve-from "^5.0.0"
+ rimraf "^3.0.0"
+ signal-exit "^3.0.2"
+ spawn-wrap "^2.0.0"
+ test-exclude "^6.0.0"
+ yargs "^15.0.2"
+
object-inspect@^1.13.3:
version "1.13.4"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213"
@@ -3886,6 +4284,11 @@ package-hash@^4.0.0:
lodash.flattendeep "^4.4.0"
release-zalgo "^1.0.0"
+package-json-from-dist@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505"
+ integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==
+
param-case@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247"
@@ -3920,6 +4323,14 @@ path-key@^3.0.0, path-key@^3.1.0:
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
+path-scurry@^1.11.1:
+ version "1.11.1"
+ resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2"
+ integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==
+ dependencies:
+ lru-cache "^10.2.0"
+ minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
+
path-to-regexp@0.1.7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
@@ -3952,6 +4363,11 @@ picocolors@^1.0.0:
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
+picocolors@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"
+ integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
+
picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
@@ -3977,6 +4393,20 @@ pkg-dir@^4.1.0:
dependencies:
find-up "^4.0.0"
+playwright-core@1.52.0:
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.52.0.tgz#238f1f0c3edd4ebba0434ce3f4401900319a3dca"
+ integrity sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==
+
+playwright@1.52.0:
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.52.0.tgz#26cb9a63346651e1c54c8805acfd85683173d4bd"
+ integrity sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==
+ dependencies:
+ playwright-core "1.52.0"
+ optionalDependencies:
+ fsevents "2.3.2"
+
postcss-selector-parser@^6.0.13:
version "6.0.13"
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz#d05d8d76b1e8e173257ef9d60b706a8e5e99bf1b"
@@ -4440,6 +4870,11 @@ signal-exit@^3.0.2, signal-exit@^3.0.3:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
+signal-exit@^4.0.1:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04"
+ integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==
+
slash@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
@@ -4548,6 +4983,15 @@ stream-combiner@~0.0.4:
dependencies:
duplexer "~0.1.1"
+"string-width-cjs@npm:string-width@^4.2.0":
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
+ integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+ dependencies:
+ emoji-regex "^8.0.0"
+ is-fullwidth-code-point "^3.0.0"
+ strip-ansi "^6.0.1"
+
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
@@ -4557,6 +5001,15 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
+string-width@^5.0.1, string-width@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794"
+ integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==
+ dependencies:
+ eastasianwidth "^0.2.0"
+ emoji-regex "^9.2.2"
+ strip-ansi "^7.0.1"
+
string_decoder@^1.1.1:
version "1.3.0"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
@@ -4571,6 +5024,13 @@ string_decoder@~1.1.1:
dependencies:
safe-buffer "~5.1.0"
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+ integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+ dependencies:
+ ansi-regex "^5.0.1"
+
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
@@ -4578,6 +5038,13 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1:
dependencies:
ansi-regex "^5.0.1"
+strip-ansi@^7.0.1:
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
+ integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==
+ dependencies:
+ ansi-regex "^6.0.1"
+
strip-bom@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878"
@@ -4645,6 +5112,15 @@ test-exclude@^6.0.0:
glob "^7.1.4"
minimatch "^3.0.4"
+test-exclude@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-7.0.1.tgz#20b3ba4906ac20994e275bbcafd68d510264c2a2"
+ integrity sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==
+ dependencies:
+ "@istanbuljs/schema" "^0.1.2"
+ glob "^10.4.1"
+ minimatch "^9.0.4"
+
text-table@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
@@ -4812,6 +5288,14 @@ update-browserslist-db@^1.0.11:
escalade "^3.1.1"
picocolors "^1.0.0"
+update-browserslist-db@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz#348377dd245216f9e7060ff50b15a1b740b75420"
+ integrity sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==
+ dependencies:
+ escalade "^3.2.0"
+ picocolors "^1.1.1"
+
upper-case@^1.1.1:
version "1.1.3"
resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598"
@@ -4853,18 +5337,19 @@ verror@1.10.0:
core-util-is "1.0.2"
extsprintf "^1.2.0"
-vite-plugin-istanbul@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/vite-plugin-istanbul/-/vite-plugin-istanbul-5.0.0.tgz#7539d76d7c3cafb7b3b0f2371a4e3a69031dcd44"
- integrity sha512-Tg9zDmm/u4SdEDFbEWHBz7mmFe7jhLRmArA2XCmw5yydEFCARU9r4TxqFFnBFWCL63D9A7XA7VELulOO5T5o/g==
+vite-plugin-istanbul@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/vite-plugin-istanbul/-/vite-plugin-istanbul-7.0.0.tgz#97b80bd0199b316e5a9c4e757633c9273ca4f5f4"
+ integrity sha512-UAXSyS0zslaSP1yCdO54YwrTkoY3VxCBH8y8MAy3I+E6uqT07LEsVOFEHueeDJ+vyyeaA9Rkqz/j6LACJTzTKw==
dependencies:
"@istanbuljs/load-nyc-config" "^1.1.0"
- espree "^9.6.1"
- istanbul-lib-instrument "^5.1.0"
- picocolors "^1.0.0"
- test-exclude "^6.0.0"
+ espree "^10.3.0"
+ istanbul-lib-instrument "^6.0.3"
+ picocolors "^1.1.1"
+ source-map "^0.7.4"
+ test-exclude "^7.0.1"
-vite@^2.9.13, vite@^4.0.0:
+vite@^2.9.13, vite@^4.0.0, vite@^6.2.6:
version "4.5.1"
resolved "https://registry.yarnpkg.com/vite/-/vite-4.5.1.tgz#3370986e1ed5dbabbf35a6c2e1fb1e18555b968a"
integrity sha512-AXXFaAJ8yebyqzoNB9fu2pHoo/nWX+xZlaRwoeYUxEqBO+Zj4msE5G+BhGBll9lYEKv9Hfks52PAF2X7qDYXQA==
@@ -4968,6 +5453,15 @@ wildcard@^2.0.0:
resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67"
integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+ integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+ dependencies:
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+
wrap-ansi@^6.0.1, wrap-ansi@^6.2.0:
version "6.2.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
@@ -4986,6 +5480,15 @@ wrap-ansi@^7.0.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"
+wrap-ansi@^8.1.0:
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
+ integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==
+ dependencies:
+ ansi-styles "^6.1.0"
+ string-width "^5.0.1"
+ strip-ansi "^7.0.1"
+
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
diff --git a/test-vite-app-v1-vite5/.eslintrc.js b/test-vite-app-v1-vite5/.eslintrc.js
index 5396741b..40cf5a78 100644
--- a/test-vite-app-v1-vite5/.eslintrc.js
+++ b/test-vite-app-v1-vite5/.eslintrc.js
@@ -111,5 +111,9 @@ module.exports = {
'@typescript-eslint/no-unused-expressions': 'off',
},
},
+ {
+ files: ['src/**/*.spec.{js,ts}', 'test/**/*.spec.{js,ts}'],
+ extends: 'plugin:playwright/recommended',
+ },
],
};
diff --git a/test-vite-app-v1-vite5/.gitignore b/test-vite-app-v1-vite5/.gitignore
index 374c78ee..b42b4e91 100644
--- a/test-vite-app-v1-vite5/.gitignore
+++ b/test-vite-app-v1-vite5/.gitignore
@@ -34,3 +34,15 @@ yarn-error.log*
.nyc_output
coverage/
+
+
+# Playwright
+/test-results/
+/playwright-report/
+/blob-report
+/playwright/.cache/
+
+
+# Coverage
+.nyc_output
+/coverage
diff --git a/test-vite-app-v1-vite5/.nycrc b/test-vite-app-v1-vite5/.nycrc
index ad64fc3f..ac43bd45 100644
--- a/test-vite-app-v1-vite5/.nycrc
+++ b/test-vite-app-v1-vite5/.nycrc
@@ -1,3 +1,3 @@
-{
- "extends": "@quasar/quasar-app-extension-testing-e2e-cypress/nyc-config-preset"
-}
+{
+ "extends": "@quasar/quasar-app-extension-testing-e2e-playwright/nyc-preset"
+}
\ No newline at end of file
diff --git a/test-vite-app-v1-vite5/cypress.config.ts b/test-vite-app-v1-vite5/cypress.config.ts
index c21b721e..6bda2d6c 100644
--- a/test-vite-app-v1-vite5/cypress.config.ts
+++ b/test-vite-app-v1-vite5/cypress.config.ts
@@ -15,9 +15,6 @@ export default defineConfig({
baseUrl: 'http://localhost:8080/',
supportFile: 'test/cypress/support/e2e.ts',
specPattern: 'test/cypress/e2e/**/*.cy.{js,jsx,ts,tsx}',
- // Vite takes quite some time for cold startup, we manually set this in the testing repo
- // to avoid timeout problems when running local smoke tests
- defaultCommandTimeout: 10000,
},
component: {
setupNodeEvents(on, config) {
diff --git a/test-vite-app-v1-vite5/package.json b/test-vite-app-v1-vite5/package.json
index 91f7f663..0db2c4fa 100644
--- a/test-vite-app-v1-vite5/package.json
+++ b/test-vite-app-v1-vite5/package.json
@@ -14,23 +14,29 @@
"invoke:all": "yarn invoke:vitest && yarn invoke:cypress",
"sync:invoke:vitest": "yarn sync:vitest && yarn invoke:vitest",
"sync:invoke:cypress": "yarn sync:cypress && yarn invoke:cypress",
+ "sync:playwright": "yarn --cwd ../packages/e2e-playwright build:local && yarn add -D ../packages/e2e-playwright",
+ "invoke:playwright": "quasar ext invoke @quasar/testing-e2e-playwright && yarn format",
+ "sync:invoke:playwright": "yarn sync:playwright && yarn invoke:playwright",
"sync:invoke:all": "yarn sync:invoke:vitest && yarn sync:invoke:cypress",
"test:vitest": "yarn test:unit:ci",
"test:cypress": "yarn test:e2e:ci && yarn test:component:ci",
"test:all": "yarn test:vitest && yarn test:cypress",
"sync:invoke:test:vitest": "yarn sync:invoke:vitest && yarn test:vitest",
"sync:invoke:test:cypress": "yarn sync:invoke:cypress && yarn test:cypress",
- "sync:invoke:test:all": "yarn sync:invoke:test:vitest && yarn sync:invoke:test:cypress",
+ "sync:invoke:test:all": "yarn sync:invoke:test:vitest && yarn sync:invoke:test:cypress && yarn sync:invoke:playwright",
"lint": "eslint --ext .js,.ts,.vue ./",
"format": "prettier --write \"**/*.{js,ts,vue,scss,html,md,json}\" --ignore-path .gitignore",
- "test": "echo \"See package.json => scripts for available tests.\" && exit 0",
+ "test": "yarn test:clear && yarn test:component:ci && yarn test:e2e:ci && yarn coverage-report",
"test:unit:ui": "vitest --ui",
"test:unit": "vitest",
"test:unit:ci": "vitest run",
- "test:e2e": "cross-env NODE_ENV=test start-test \"quasar dev\" http-get://127.0.0.1:8080 \"cypress open --e2e\"",
- "test:e2e:ci": "cross-env NODE_ENV=test start-test \"quasar dev\" http-get://127.0.0.1:8080 \"cypress run --e2e\"",
- "test:component": "cross-env NODE_ENV=test cypress open --component",
- "test:component:ci": "cross-env NODE_ENV=test cypress run --component"
+ "test:e2e": "cross-env NODE_ENV=test VITE_COVERAGE=true playwright test --ui",
+ "test:e2e:ci": "cross-env NODE_ENV=test VITE_COVERAGE=true playwright test",
+ "test:component": "cross-env NODE_ENV=test VITE_COVERAGE=true playwright test -c playwright-ct.config.ts --ui",
+ "test:component:ci": "cross-env NODE_ENV=test VITE_COVERAGE=true playwright test -c playwright-ct.config.ts",
+ "test:clear": "rimraf .nyc_output coverage",
+ "test:report": "playwright show-report",
+ "coverage-report": "nyc report --reporter=html --reporter=text"
},
"dependencies": {
"@quasar/extras": "^1.16.6",
@@ -46,8 +52,11 @@
},
"devDependencies": {
"@intlify/vite-plugin-vue-i18n": "^3.3.1",
+ "@playwright/experimental-ct-vue": "^1.50.0",
+ "@playwright/test": "^1.49.1",
"@quasar/app-vite": "^1.7.1",
"@quasar/quasar-app-extension-testing-e2e-cypress": "../packages/e2e-cypress",
+ "@quasar/quasar-app-extension-testing-e2e-playwright": "../packages/e2e-playwright",
"@quasar/quasar-app-extension-testing-unit-vitest": "../packages/unit-vitest",
"@types/node": "^18.17.15",
"@typescript-eslint/eslint-plugin": "^5.54.0",
@@ -59,6 +68,7 @@
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-cypress": "^3.6.0",
+ "eslint-plugin-playwright": "^2.1.0",
"eslint-plugin-vue": "^9.19.2",
"prettier": "^3.1.1",
"typescript": "^4.9.5",
diff --git a/test-vite-app-v1-vite5/playwright-ct.config.ts b/test-vite-app-v1-vite5/playwright-ct.config.ts
new file mode 100644
index 00000000..162d0ef9
--- /dev/null
+++ b/test-vite-app-v1-vite5/playwright-ct.config.ts
@@ -0,0 +1,108 @@
+import {
+ defineConfig,
+ devices,
+} from '@playwright/experimental-ct-vue';
+import vue from '@vitejs/plugin-vue';
+import { quasar, transformAssetUrls } from '@quasar/vite-plugin';
+// import { fileURLToPath } from 'node:url';
+// import AutoImport from 'unplugin-auto-import/vite';
+// import Components from 'unplugin-vue-components/vite';
+
+/**
+ * See https://playwright.dev/docs/test-configuration.
+ */
+export default defineConfig({
+ testDir: './src/components',
+ /* The base directory, relative to the config file, for snapshot files created with toMatchSnapshot and toHaveScreenshot. */
+ snapshotDir: './__snapshots__',
+ /* Maximum time one test can run for. */
+ timeout: 10 * 1000,
+ /* Run tests in files in parallel */
+ fullyParallel: true,
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
+ forbidOnly: !!process.env.CI,
+ /* Retry on CI only */
+ retries: process.env.CI ? 2 : 0,
+ /* Opt out of parallel tests on CI. */
+ workers: process.env.CI ? 1 : undefined,
+ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
+ reporter: 'html',
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
+ use: {
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
+ trace: 'on-first-retry',
+
+ /* Port to use for Playwright component endpoint. */
+ ctPort: 3100,
+
+ ctViteConfig: async () => {
+ const { default: istanbul } = await import('vite-plugin-istanbul');
+ return {
+ build: {
+ sourcemap: true,
+ },
+ plugins: [
+ vue({ template: { transformAssetUrls } }),
+ // AutoImport({
+ // imports: [
+ // 'vue',
+ // 'vue-router',
+ // '@vueuse/head',
+ // 'pinia',
+ // 'quasar',
+ // {
+ // '@/store': ['useStore'],
+ // },
+ // ],
+ // dts: 'src/auto-imports.d.ts',
+ // eslintrc: {
+ // enabled: true,
+ // },
+ // }),
+ // Components({
+ // dirs: ['src/components'],
+ // extensions: ['vue'],
+ // }),
+ quasar({
+ // sassVariables: fileURLToPath(
+ // new URL('./src/quasar-variables.sass', import.meta.url),
+ // ),
+ }),
+
+ // Instrument the code for nyc/istanbul code coverage
+ istanbul({
+ include: ['src/**/*'],
+ exclude: [
+ 'node_modules',
+ 'test/',
+ 'dist/',
+ 'coverage/',
+ '__tests__',
+ ],
+ extension: ['.js', '.ts', '.vue'],
+ requireEnv: true,
+ forceBuildInstrument: true,
+ checkProd: false,
+ cypress: false,
+ }),
+ ],
+ };
+ },
+ },
+
+ /* Configure projects for major browsers */
+ projects: [
+ {
+ name: 'chromium',
+ use: { ...devices['Desktop Chrome'] },
+ },
+ {
+ name: 'firefox',
+ use: { ...devices['Desktop Firefox'] },
+ },
+ {
+ name: 'webkit',
+ use: { ...devices['Desktop Safari'] },
+ },
+ ],
+});
diff --git a/test-vite-app-v1-vite5/playwright.config.ts b/test-vite-app-v1-vite5/playwright.config.ts
new file mode 100644
index 00000000..9fdf0aed
--- /dev/null
+++ b/test-vite-app-v1-vite5/playwright.config.ts
@@ -0,0 +1,79 @@
+import { defineConfig, devices, PlaywrightTestConfig } from '@playwright/test';
+
+/**
+ * Read environment variables from file.
+ * https://github.com/motdotla/dotenv
+ */
+// import dotenv from 'dotenv';
+// import path from 'path';
+// dotenv.config({ path: path.resolve(__dirname, '.env') });
+
+/**
+ * See https://playwright.dev/docs/test-configuration.
+ */
+export default defineConfig({
+ testDir: './test/playwright',
+ /* Run tests in files in parallel */
+ fullyParallel: true,
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
+ forbidOnly: !!process.env.CI,
+ /* Retry on CI only */
+ retries: process.env.CI ? 2 : 0,
+ /* Opt out of parallel tests on CI. */
+ workers: process.env.CI ? 1 : undefined,
+ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
+ reporter: 'html',
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
+ use: {
+ /* Base URL to use in actions like `await page.goto('/')`. */
+ baseURL: 'http://localhost:8080',
+
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
+ trace: 'on-first-retry',
+ },
+
+ /* Configure projects for major browsers */
+ projects: [
+ {
+ name: 'chromium',
+ use: { ...devices['Desktop Chrome'] },
+ },
+
+ {
+ name: 'firefox',
+ use: { ...devices['Desktop Firefox'] },
+ },
+
+ {
+ name: 'webkit',
+ use: { ...devices['Desktop Safari'] },
+ },
+
+ /* Test against mobile viewports. */
+ // {
+ // name: 'Mobile Chrome',
+ // use: { ...devices['Pixel 5'] },
+ // },
+ // {
+ // name: 'Mobile Safari',
+ // use: { ...devices['iPhone 12'] },
+ // },
+
+ /* Test against branded browsers. */
+ // {
+ // name: 'Microsoft Edge',
+ // use: { ...devices['Desktop Edge'], channel: 'msedge' },
+ // },
+ // {
+ // name: 'Google Chrome',
+ // use: { ...devices['Desktop Chrome'], channel: 'chrome' },
+ // },
+ ],
+
+ /* Run your local dev server before starting the tests */
+ webServer: {
+ command: 'quasar dev -p 8080',
+ url: 'http://localhost:8080',
+ reuseExistingServer: !process.env.CI,
+ },
+} as PlaywrightTestConfig);
diff --git a/test-vite-app-v1-vite5/playwright/index.html b/test-vite-app-v1-vite5/playwright/index.html
new file mode 100644
index 00000000..56da0401
--- /dev/null
+++ b/test-vite-app-v1-vite5/playwright/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ Testing Page
+
+
+
+
+
+
diff --git a/test-vite-app-v1-vite5/playwright/index.ts b/test-vite-app-v1-vite5/playwright/index.ts
new file mode 100644
index 00000000..f5265b82
--- /dev/null
+++ b/test-vite-app-v1-vite5/playwright/index.ts
@@ -0,0 +1,20 @@
+// See https://quasar.dev/start/vite-plugin
+import 'quasar/src/css/index.sass';
+import '../src/css/app.scss';
+import { Quasar, Dialog } from 'quasar';
+import { beforeMount } from '@playwright/experimental-ct-vue/hooks';
+import '@quasar/extras/material-icons/material-icons.css';
+// import '@quasar/extras/mdi-v7/mdi-v7.css';
+
+beforeMount(async ({ app }) => {
+ // Setup other stuff you need before mounting the component. You can setup i18n, pinia, etc here.
+ // See https://playwright.dev/docs/test-components#frequently-asked-questions
+ app.use(Quasar, {
+ plugins: {
+ // Setup plugins used in your components
+ // Notify,
+ // Loading
+ Dialog,
+ },
+ });
+});
diff --git a/test-vite-app-v1-vite5/quasar.extensions.json b/test-vite-app-v1-vite5/quasar.extensions.json
index d1d129a1..ede86e7a 100644
--- a/test-vite-app-v1-vite5/quasar.extensions.json
+++ b/test-vite-app-v1-vite5/quasar.extensions.json
@@ -5,5 +5,11 @@
},
"@quasar/testing-unit-vitest": {
"options": ["ui"]
+ },
+ "@quasar/testing-e2e-playwright": {
+ "port": 8080,
+ "githubWorkflow": true,
+ "installBrowsers": true,
+ "enableCodeCoverage": true
}
}
diff --git a/test-vite-app-v1-vite5/src/components/AppButton.vue b/test-vite-app-v1-vite5/src/components/AppButton.vue
new file mode 100644
index 00000000..a840fe38
--- /dev/null
+++ b/test-vite-app-v1-vite5/src/components/AppButton.vue
@@ -0,0 +1,23 @@
+
+
+
+
+
diff --git a/test-vite-app-v1-vite5/src/components/AppCheckComponents.vue b/test-vite-app-v1-vite5/src/components/AppCheckComponents.vue
new file mode 100644
index 00000000..623ccac1
--- /dev/null
+++ b/test-vite-app-v1-vite5/src/components/AppCheckComponents.vue
@@ -0,0 +1,30 @@
+
+
+
+
+ Value1
+ Value2
+
+
+
diff --git a/test-vite-app-v1-vite5/src/components/AppDark.vue b/test-vite-app-v1-vite5/src/components/AppDark.vue
new file mode 100644
index 00000000..a5f2282b
--- /dev/null
+++ b/test-vite-app-v1-vite5/src/components/AppDark.vue
@@ -0,0 +1,35 @@
+
+
+ {{ $q.dark.isActive ? 'Dark ' : 'Light' }} content
+
+
+
+
+
+
diff --git a/test-vite-app-v1-vite5/src/components/AppDate.vue b/test-vite-app-v1-vite5/src/components/AppDate.vue
new file mode 100644
index 00000000..41b1ea7a
--- /dev/null
+++ b/test-vite-app-v1-vite5/src/components/AppDate.vue
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test-vite-app-v1-vite5/src/components/AppDialog.vue b/test-vite-app-v1-vite5/src/components/AppDialog.vue
new file mode 100644
index 00000000..0d2ed487
--- /dev/null
+++ b/test-vite-app-v1-vite5/src/components/AppDialog.vue
@@ -0,0 +1,71 @@
+
+
+
+
+ {{ message }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test-vite-app-v1-vite5/src/components/AppDrawer.vue b/test-vite-app-v1-vite5/src/components/AppDrawer.vue
new file mode 100644
index 00000000..f65b882e
--- /dev/null
+++ b/test-vite-app-v1-vite5/src/components/AppDrawer.vue
@@ -0,0 +1,33 @@
+
+
+
+
+ Am I on screen?
+
+
+
+
+
diff --git a/test-vite-app-v1-vite5/src/components/AppMenu.vue b/test-vite-app-v1-vite5/src/components/AppMenu.vue
new file mode 100644
index 00000000..a28ec48e
--- /dev/null
+++ b/test-vite-app-v1-vite5/src/components/AppMenu.vue
@@ -0,0 +1,22 @@
+
+
+
+
+
+ Item 1
+
+
+ Item 2
+
+
+
+
+
+
+
diff --git a/test-vite-app-v1-vite5/src/components/AppPageSticky.vue b/test-vite-app-v1-vite5/src/components/AppPageSticky.vue
new file mode 100644
index 00000000..25861bc7
--- /dev/null
+++ b/test-vite-app-v1-vite5/src/components/AppPageSticky.vue
@@ -0,0 +1,21 @@
+
+
+
+ {{ title }}
+
+
+
+
+
diff --git a/test-vite-app-v1-vite5/src/components/AppSelect.vue b/test-vite-app-v1-vite5/src/components/AppSelect.vue
new file mode 100644
index 00000000..fb19c0b4
--- /dev/null
+++ b/test-vite-app-v1-vite5/src/components/AppSelect.vue
@@ -0,0 +1,54 @@
+
+
+
+ {{ selected }}
+
+
+
diff --git a/test-vite-app-v1-vite5/src/components/AppTooltip.vue b/test-vite-app-v1-vite5/src/components/AppTooltip.vue
new file mode 100644
index 00000000..1ab513cb
--- /dev/null
+++ b/test-vite-app-v1-vite5/src/components/AppTooltip.vue
@@ -0,0 +1,28 @@
+
+
+ Button
+
+ Here I am!
+
+
+
+
+
diff --git a/test-vite-app-v1-vite5/src/components/ColorAssertion.vue b/test-vite-app-v1-vite5/src/components/ColorAssertion.vue
new file mode 100644
index 00000000..841cd639
--- /dev/null
+++ b/test-vite-app-v1-vite5/src/components/ColorAssertion.vue
@@ -0,0 +1,3 @@
+
+ Text1
+
diff --git a/test-vite-app-v1-vite5/src/components/QuasarCheckComponents.vue b/test-vite-app-v1-vite5/src/components/QuasarCheckComponents.vue
index f49ea26b..2678290e 100644
--- a/test-vite-app-v1-vite5/src/components/QuasarCheckComponents.vue
+++ b/test-vite-app-v1-vite5/src/components/QuasarCheckComponents.vue
@@ -1,9 +1,21 @@
-
-
+
+
- Value1
- Value2
+ Value1
+ Value2
diff --git a/test-vite-app-v1-vite5/src/components/QuasarDate.vue b/test-vite-app-v1-vite5/src/components/QuasarDate.vue
index 962b4e0a..30d185fa 100644
--- a/test-vite-app-v1-vite5/src/components/QuasarDate.vue
+++ b/test-vite-app-v1-vite5/src/components/QuasarDate.vue
@@ -1,11 +1,12 @@
-
+
-
+
diff --git a/test-vite-app-v1-vite5/src/components/QuasarDialog.vue b/test-vite-app-v1-vite5/src/components/QuasarDialog.vue
index c88b9930..6451da46 100644
--- a/test-vite-app-v1-vite5/src/components/QuasarDialog.vue
+++ b/test-vite-app-v1-vite5/src/components/QuasarDialog.vue
@@ -8,6 +8,7 @@
- Am I on screen?
+ Am I on screen?
diff --git a/test-vite-app-v1-vite5/src/components/QuasarMenu.vue b/test-vite-app-v1-vite5/src/components/QuasarMenu.vue
index daed3aa4..4ff02d2e 100644
--- a/test-vite-app-v1-vite5/src/components/QuasarMenu.vue
+++ b/test-vite-app-v1-vite5/src/components/QuasarMenu.vue
@@ -1,5 +1,5 @@
-
+
diff --git a/test-vite-app-v1-vite5/src/components/QuasarPageSticky.vue b/test-vite-app-v1-vite5/src/components/QuasarPageSticky.vue
index 7c8223d3..9fce30f1 100644
--- a/test-vite-app-v1-vite5/src/components/QuasarPageSticky.vue
+++ b/test-vite-app-v1-vite5/src/components/QuasarPageSticky.vue
@@ -1,6 +1,12 @@
-
+
{{ title }}
diff --git a/test-vite-app-v1-vite5/src/components/QuasarSelect.vue b/test-vite-app-v1-vite5/src/components/QuasarSelect.vue
index 13d763f0..eefc5e5a 100644
--- a/test-vite-app-v1-vite5/src/components/QuasarSelect.vue
+++ b/test-vite-app-v1-vite5/src/components/QuasarSelect.vue
@@ -2,6 +2,7 @@
- {{ selected }}
+ {{ selected }}
diff --git a/test-vite-app-v1-vite5/test/playwright/wrappers/LayoutContainer.vue b/test-vite-app-v1-vite5/test/playwright/wrappers/LayoutContainer.vue
new file mode 100644
index 00000000..079fe47a
--- /dev/null
+++ b/test-vite-app-v1-vite5/test/playwright/wrappers/LayoutContainer.vue
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
diff --git a/test-vite-app-v1-vite5/yarn.lock b/test-vite-app-v1-vite5/yarn.lock
index 8e831f98..c7904a05 100644
--- a/test-vite-app-v1-vite5/yarn.lock
+++ b/test-vite-app-v1-vite5/yarn.lock
@@ -634,6 +634,13 @@
js-yaml "^3.13.1"
resolve-from "^5.0.0"
+"@istanbuljs/nyc-config-typescript@^1.0.2":
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/@istanbuljs/nyc-config-typescript/-/nyc-config-typescript-1.0.2.tgz#1f5235b28540a07219ae0dd42014912a0b19cf89"
+ integrity sha512-iKGIyMoyJuFnJRSVTZ78POIRvNnwZaWIf8vG4ZS3rQq58MMDrqEX2nnzx0R28V2X8JvmKYiqY9FP2hlJsm8A0w==
+ dependencies:
+ "@istanbuljs/schema" "^0.1.2"
+
"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3":
version "0.1.3"
resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98"
@@ -729,6 +736,30 @@
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
+"@playwright/experimental-ct-core@1.52.0":
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/@playwright/experimental-ct-core/-/experimental-ct-core-1.52.0.tgz#3fa18bc7952deaf141ad2a2c1cdfcff1de6c7192"
+ integrity sha512-DiDEammXxt8OIFDfoNitoOZyHFJAu6aYi0abmHl0IZgOQHxccP6UX50aTEnSTTUWCfwUWB0Vd8TKJ6w122WJEw==
+ dependencies:
+ playwright "1.52.0"
+ playwright-core "1.52.0"
+ vite "^6.2.6"
+
+"@playwright/experimental-ct-vue@^1.50.0":
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/@playwright/experimental-ct-vue/-/experimental-ct-vue-1.52.0.tgz#8c5ca57e98def53e6befeadb0a433a9141d133b3"
+ integrity sha512-MaUVEZZ+eo/UH/qWLwUzDl2SgjYyGQUVrGFVayUX07TASS4FDMRV8f8Jjkk0t7iYeFfWE2ZyZS1muLeWeP7qXg==
+ dependencies:
+ "@playwright/experimental-ct-core" "1.52.0"
+ "@vitejs/plugin-vue" "^5.2.0"
+
+"@playwright/test@^1.49.1":
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.52.0.tgz#267ec595b43a8f4fa5e444ea503689629e91a5b8"
+ integrity sha512-uh6W7sb55hl7D6vsAeA+V2p5JnlAqzhqFyF0VcJkKZXkgnFcVG9PziERRHQfPLfNGx1C292a4JqbWzhR8L4R1g==
+ dependencies:
+ playwright "1.52.0"
+
"@polka/url@^1.0.0-next.24":
version "1.0.0-next.24"
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.24.tgz#58601079e11784d20f82d0585865bb42305c4df3"
@@ -780,7 +811,7 @@
integrity sha512-SlOhwzXyPQHWgQIS2ncyDdYdksCJvUYNtgsDQqzAKEG3r3d/ejOxvThle79HTK3Q6HB+gQWFG21Ux00Osr5XSw==
"@quasar/quasar-app-extension-testing-e2e-cypress@../packages/e2e-cypress":
- version "6.2.0"
+ version "6.2.1"
dependencies:
"@cypress/code-coverage" "^3.12.26"
cross-env "^7.0.3"
@@ -789,6 +820,14 @@
start-server-and-test "^2.0.3"
vite-plugin-istanbul "^7.0.0"
+"@quasar/quasar-app-extension-testing-e2e-playwright@../packages/e2e-playwright":
+ version "0.0.1"
+ dependencies:
+ "@istanbuljs/nyc-config-typescript" "^1.0.2"
+ cross-env "^7.0.3"
+ nyc "^17.1.0"
+ vite-plugin-istanbul "^7.0.0"
+
"@quasar/quasar-app-extension-testing-unit-vitest@../packages/unit-vitest":
version "1.2.3"
dependencies:
@@ -1147,7 +1186,7 @@
resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406"
integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==
-"@vitejs/plugin-vue@^2.2.0", "@vitejs/plugin-vue@^4.5.2":
+"@vitejs/plugin-vue@^2.2.0", "@vitejs/plugin-vue@^4.5.2", "@vitejs/plugin-vue@^5.2.0":
version "4.6.0"
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-4.6.0.tgz#6e1011303f8224e04d339756f1fa398ba79fc0b3"
integrity sha512-XHuyFdAikWRmHuAd89FOyUGIjrBU5KlxJtyi2hVeR9ySGFxQwE0bl5xAQju/ArMq5azdBivY4d+D2yPKwoYWUg==
@@ -2134,6 +2173,15 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
shebang-command "^2.0.0"
which "^2.0.1"
+cross-spawn@^7.0.6:
+ version "7.0.6"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
+ integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
+ dependencies:
+ path-key "^3.1.0"
+ shebang-command "^2.0.0"
+ which "^2.0.1"
+
cssesc@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
@@ -2635,6 +2683,13 @@ eslint-plugin-cypress@^3.6.0:
dependencies:
globals "^13.20.0"
+eslint-plugin-playwright@^2.1.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-playwright/-/eslint-plugin-playwright-2.2.0.tgz#d7eda21e670274fc0c006e11ba5cc2c8417b2a6e"
+ integrity sha512-qSQpAw7RcSzE3zPp8FMGkthaCWovHZ/BsXtpmnGax9vQLIovlh1bsZHEa2+j2lv9DWhnyeLM/qZmp7ffQZfQvg==
+ dependencies:
+ globals "^13.23.0"
+
eslint-plugin-vue@^9.19.2:
version "9.19.2"
resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-9.19.2.tgz#7ab83a001a1ac8bccae013c5b9cb5d2c644fb376"
@@ -3110,6 +3165,14 @@ foreground-child@^3.1.0:
cross-spawn "^7.0.0"
signal-exit "^4.0.1"
+foreground-child@^3.3.0:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f"
+ integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==
+ dependencies:
+ cross-spawn "^7.0.6"
+ signal-exit "^4.0.1"
+
forever-agent@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
@@ -3188,6 +3251,11 @@ fs.realpath@^1.0.0:
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
+fsevents@2.3.2:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
+ integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
+
fsevents@~2.3.2, fsevents@~2.3.3:
version "2.3.3"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
@@ -3339,7 +3407,7 @@ globals@^11.1.0:
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
-globals@^13.19.0, globals@^13.20.0:
+globals@^13.19.0, globals@^13.20.0, globals@^13.23.0:
version "13.24.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171"
integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==
@@ -3735,7 +3803,7 @@ istanbul-lib-instrument@^4.0.0:
istanbul-lib-coverage "^3.0.0"
semver "^6.3.0"
-istanbul-lib-instrument@^6.0.3:
+istanbul-lib-instrument@^6.0.2, istanbul-lib-instrument@^6.0.3:
version "6.0.3"
resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz#fa15401df6c15874bcb2105f773325d78c666765"
integrity sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==
@@ -4378,6 +4446,39 @@ nyc@15.1.0, nyc@^15.1.0:
test-exclude "^6.0.0"
yargs "^15.0.2"
+nyc@^17.1.0:
+ version "17.1.0"
+ resolved "https://registry.yarnpkg.com/nyc/-/nyc-17.1.0.tgz#b6349a401a62ffeb912bd38ea9a018839fdb6eb1"
+ integrity sha512-U42vQ4czpKa0QdI1hu950XuNhYqgoM+ZF1HT+VuUHL9hPfDPVvNQyltmMqdE9bUHMVa+8yNbc3QKTj8zQhlVxQ==
+ dependencies:
+ "@istanbuljs/load-nyc-config" "^1.0.0"
+ "@istanbuljs/schema" "^0.1.2"
+ caching-transform "^4.0.0"
+ convert-source-map "^1.7.0"
+ decamelize "^1.2.0"
+ find-cache-dir "^3.2.0"
+ find-up "^4.1.0"
+ foreground-child "^3.3.0"
+ get-package-type "^0.1.0"
+ glob "^7.1.6"
+ istanbul-lib-coverage "^3.0.0"
+ istanbul-lib-hook "^3.0.0"
+ istanbul-lib-instrument "^6.0.2"
+ istanbul-lib-processinfo "^2.0.2"
+ istanbul-lib-report "^3.0.0"
+ istanbul-lib-source-maps "^4.0.0"
+ istanbul-reports "^3.0.2"
+ make-dir "^3.0.0"
+ node-preload "^0.2.1"
+ p-map "^3.0.0"
+ process-on-spawn "^1.0.0"
+ resolve-from "^5.0.0"
+ rimraf "^3.0.0"
+ signal-exit "^3.0.2"
+ spawn-wrap "^2.0.0"
+ test-exclude "^6.0.0"
+ yargs "^15.0.2"
+
object-inspect@^1.13.3:
version "1.13.4"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213"
@@ -4649,6 +4750,20 @@ pkg-dir@^4.1.0:
dependencies:
find-up "^4.0.0"
+playwright-core@1.52.0:
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.52.0.tgz#238f1f0c3edd4ebba0434ce3f4401900319a3dca"
+ integrity sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==
+
+playwright@1.52.0:
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.52.0.tgz#26cb9a63346651e1c54c8805acfd85683173d4bd"
+ integrity sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==
+ dependencies:
+ playwright-core "1.52.0"
+ optionalDependencies:
+ fsevents "2.3.2"
+
postcss-selector-parser@^6.0.13:
version "6.0.14"
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.14.tgz#9d45f1afbebedae6811a17f49d09754f2ad153b3"
@@ -5697,7 +5812,7 @@ vite-tsconfig-paths@^5.1.4:
globrex "^0.1.2"
tsconfck "^3.0.3"
-vite@^2.9.13, "vite@^5.0.0 || ^6.0.0", vite@^5.0.10:
+vite@^2.9.13, "vite@^5.0.0 || ^6.0.0", vite@^5.0.10, vite@^6.2.6:
version "5.0.10"
resolved "https://registry.yarnpkg.com/vite/-/vite-5.0.10.tgz#1e13ef5c3cf5aa4eed81f5df6d107b3c3f1f6356"
integrity sha512-2P8J7WWgmc355HUMlFrwofacvr98DAjoE52BfdbwQtyLH06XKwaL/FMnmKM2crF0iX4MpmMKoDlNCB1ok7zHCw==
diff --git a/test-vite-app-v2/.gitignore b/test-vite-app-v2/.gitignore
index 8969fe6d..536d0637 100644
--- a/test-vite-app-v2/.gitignore
+++ b/test-vite-app-v2/.gitignore
@@ -34,3 +34,15 @@ yarn-error.log*
.nyc_output
coverage/
+
+
+# Playwright
+/test-results/
+/playwright-report/
+/blob-report
+/playwright/.cache/
+
+
+# Coverage
+.nyc_output
+/coverage
diff --git a/test-vite-app-v2/.nycrc b/test-vite-app-v2/.nycrc
index ad64fc3f..ac43bd45 100644
--- a/test-vite-app-v2/.nycrc
+++ b/test-vite-app-v2/.nycrc
@@ -1,3 +1,3 @@
-{
- "extends": "@quasar/quasar-app-extension-testing-e2e-cypress/nyc-config-preset"
-}
+{
+ "extends": "@quasar/quasar-app-extension-testing-e2e-playwright/nyc-preset"
+}
\ No newline at end of file
diff --git a/test-vite-app-v2/coverage.ts b/test-vite-app-v2/coverage.ts
new file mode 100644
index 00000000..ae096411
--- /dev/null
+++ b/test-vite-app-v2/coverage.ts
@@ -0,0 +1,114 @@
+import * as fs from 'fs';
+import * as path from 'path';
+import * as crypto from 'crypto';
+import * as libCoverage from 'istanbul-lib-coverage';
+import { test as baseTest } from '@playwright/experimental-ct-vue';
+
+// Define paths
+const NYC_OUTPUT_DIR: string = path.join(process.cwd(), '.nyc_output');
+const MERGED_COVERAGE_FILE: string = path.join(
+ NYC_OUTPUT_DIR,
+ 'merged-coverage.json',
+);
+
+// Ensure .nyc_output exists
+if (!fs.existsSync(NYC_OUTPUT_DIR)) {
+ fs.mkdirSync(NYC_OUTPUT_DIR, { recursive: true });
+}
+
+// Generate UUID for unique coverage file names
+export function generateUUID(): string {
+ return crypto.randomBytes(16).toString('hex');
+}
+
+// Merge coverage files in .nyc_output
+async function mergeCoverageFiles(): Promise {
+ try {
+ const coverageMap: libCoverage.CoverageMap = libCoverage.createCoverageMap(
+ {},
+ );
+
+ // Read and merge all .json files in .nyc_output
+ const files = fs
+ .readdirSync(NYC_OUTPUT_DIR)
+ .filter((file: string) => file.endsWith('.json'));
+ for (const file of files) {
+ const filePath: string = path.join(NYC_OUTPUT_DIR, file);
+ try {
+ const coverage: libCoverage.CoverageMapData = JSON.parse(
+ fs.readFileSync(filePath, 'utf8'),
+ );
+ coverageMap.merge(coverage);
+ } catch (error) {
+ console.error(`Error processing file ${filePath}:`, error);
+ }
+ }
+
+ // Write merged coverage to file
+ if (Object.keys(coverageMap.data).length > 0) {
+ fs.writeFileSync(
+ MERGED_COVERAGE_FILE,
+ JSON.stringify(coverageMap.data, null, 2),
+ );
+ console.log(`Merged coverage written to ${MERGED_COVERAGE_FILE}`);
+ } else {
+ console.warn('No coverage data found to merge');
+ }
+ } catch (error) {
+ console.error('Error merging coverage files:', error);
+ }
+}
+
+export const test = baseTest.extend({
+ context: async ({ context }, use) => {
+ // Add beforeunload listener to collect coverage
+ await context.addInitScript(() =>
+ window.addEventListener('beforeunload', () =>
+ (window as any).collectIstanbulCoverage(
+ JSON.stringify((window as any).__coverage__),
+ ),
+ ),
+ );
+
+ // Ensure .nyc_output directory exists
+ await fs.promises.mkdir(NYC_OUTPUT_DIR, { recursive: true });
+
+ // Expose function to save coverage from browser
+ await context.exposeFunction(
+ 'collectIstanbulCoverage',
+ (coverageJSON: string) => {
+ if (coverageJSON) {
+ const filePath = path.join(
+ NYC_OUTPUT_DIR,
+ `playwright_coverage_${generateUUID()}.json`,
+ );
+ fs.writeFileSync(filePath, coverageJSON);
+ console.log(`Coverage saved to ${filePath}`);
+ } else {
+ console.log('No coverage data received');
+ }
+ },
+ );
+
+ // Use the context for tests
+ await use(context);
+
+ // Collect coverage from all pages after tests
+ for (const page of context.pages()) {
+ try {
+ await page.evaluate(() =>
+ (window as any).collectIstanbulCoverage(
+ JSON.stringify((window as any).__coverage__),
+ ),
+ );
+ } catch (error) {
+ console.error('Error collecting coverage from page:', error);
+ }
+ }
+
+ // Merge coverage files after tests
+ await mergeCoverageFiles();
+ },
+});
+
+export { expect } from '@playwright/experimental-ct-vue';
diff --git a/test-vite-app-v2/eslint.config.js b/test-vite-app-v2/eslint.config.js
index 6feb020d..2dbcd692 100644
--- a/test-vite-app-v2/eslint.config.js
+++ b/test-vite-app-v2/eslint.config.js
@@ -8,6 +8,7 @@ import {
import pluginCypress from 'eslint-plugin-cypress/flat';
import pluginVue from 'eslint-plugin-vue';
import globals from 'globals';
+import playwright from 'eslint-plugin-playwright';
const config = defineConfigWithVueTs(
{
@@ -103,6 +104,17 @@ const config = defineConfigWithVueTs(
},
},
+ {
+ name: 'custom/playwright',
+
+ ...playwright.configs['flat/recommended'],
+ files: ['src/components/**/*.spec.ts', 'test/**/*.spec.ts'],
+ rules: {
+ ...playwright.configs['flat/recommended'].rules,
+ '@typescript-eslint/unbound-method': 'off',
+ },
+ },
+
{
name: 'custom/vitest',
diff --git a/test-vite-app-v2/package.json b/test-vite-app-v2/package.json
index 6ba33bef..85616401 100644
--- a/test-vite-app-v2/package.json
+++ b/test-vite-app-v2/package.json
@@ -12,28 +12,34 @@
"sync:all": "yarn sync:vitest && yarn sync:cypress",
"invoke:vitest": "quasar ext invoke @quasar/testing-unit-vitest && yarn format",
"invoke:cypress": "quasar ext invoke @quasar/testing-e2e-cypress && yarn format",
+ "invoke:playwright": "quasar ext invoke @quasar/testing-e2e-playwright && yarn format",
"invoke:all": "yarn invoke:vitest && yarn invoke:cypress",
"sync:invoke:vitest": "yarn sync:vitest && yarn invoke:vitest",
"sync:invoke:cypress": "yarn sync:cypress && yarn invoke:cypress",
+ "sync:invoke:playwright": "yarn sync:playwright && yarn invoke:playwright",
"sync:invoke:all": "yarn sync:invoke:vitest && yarn sync:invoke:cypress",
"test:vitest": "yarn test:unit:ci",
"test:cypress": "yarn test:e2e:ci && yarn test:component:ci",
"test:all": "yarn test:vitest && yarn test:cypress",
"sync:invoke:test:vitest": "yarn sync:invoke:vitest && yarn test:vitest",
"sync:invoke:test:cypress": "yarn sync:invoke:cypress && yarn test:cypress",
- "sync:invoke:test:all": "yarn sync:invoke:test:vitest && yarn sync:invoke:test:cypress",
+ "sync:playwright": "yarn --cwd ../packages/e2e-playwright build:local && yarn add -D ../packages/e2e-playwright",
+ "sync:invoke:test:all": "yarn sync:invoke:test:vitest && yarn sync:invoke:test:cypress && yarn sync:invoke:playwright",
"lint": "eslint -c ./eslint.config.js \"./src*/**/*.{ts,js,cjs,mjs,vue}\" --fix",
"format": "prettier --write \"**/*.{js,ts,vue,scss,html,md,json}\" --ignore-path .gitignore",
- "test": "echo \"See package.json => scripts for available tests.\" && exit 0",
+ "test": "yarn test:clear && yarn test:component:ci && yarn test:e2e:ci && yarn coverage-report",
"dev": "quasar dev",
"build": "quasar build",
"test:unit:ui": "vitest --ui",
"test:unit": "vitest",
"test:unit:ci": "vitest run",
- "test:e2e": "cross-env NODE_ENV=test TS_NODE_PROJECT=test/cypress/tsconfig.json start-test \"quasar dev\" http-get://127.0.0.1:8080 \"cypress open --e2e\"",
- "test:e2e:ci": "cross-env NODE_ENV=test TS_NODE_PROJECT=test/cypress/tsconfig.json start-test \"quasar dev\" http-get://127.0.0.1:8080 \"cypress run --e2e\"",
- "test:component": "cross-env NODE_ENV=test TS_NODE_PROJECT=test/cypress/tsconfig.json cypress open --component",
- "test:component:ci": "cross-env NODE_ENV=test TS_NODE_PROJECT=test/cypress/tsconfig.json cypress run --component",
+ "test:e2e": "cross-env NODE_ENV=test VITE_COVERAGE=true playwright test --ui",
+ "test:e2e:ci": "cross-env NODE_ENV=test VITE_COVERAGE=true playwright test",
+ "test:component": "cross-env NODE_ENV=test VITE_COVERAGE=true playwright test -c playwright-ct.config.ts --ui",
+ "test:component:ci": "cross-env NODE_ENV=test VITE_COVERAGE=true playwright test -c playwright-ct.config.ts",
+ "test:clear": "rimraf .nyc_output coverage",
+ "test:report": "playwright show-report",
+ "coverage-report": "nyc report --reporter=html --reporter=text",
"postinstall": "quasar prepare"
},
"dependencies": {
@@ -48,8 +54,11 @@
"devDependencies": {
"@eslint/js": "^9.14.0",
"@intlify/unplugin-vue-i18n": "^4.0.0",
+ "@playwright/experimental-ct-vue": "^1.50.0",
+ "@playwright/test": "^1.49.1",
"@quasar/app-vite": "^2.1.0",
"@quasar/quasar-app-extension-testing-e2e-cypress": "../packages/e2e-cypress",
+ "@quasar/quasar-app-extension-testing-e2e-playwright": "../packages/e2e-playwright",
"@quasar/quasar-app-extension-testing-unit-vitest": "../packages/unit-vitest",
"@types/node": "^20.5.9",
"@vitest/ui": "^3.1.2",
@@ -60,6 +69,7 @@
"cypress": "^14.2.1",
"eslint": "^9.14.0",
"eslint-plugin-cypress": "^4.2.1",
+ "eslint-plugin-playwright": "^2.1.0",
"eslint-plugin-vue": "^9.30.0",
"globals": "^15.12.0",
"prettier": "^3.3.3",
diff --git a/test-vite-app-v2/playwright-ct.config.ts b/test-vite-app-v2/playwright-ct.config.ts
new file mode 100644
index 00000000..4458d7db
--- /dev/null
+++ b/test-vite-app-v2/playwright-ct.config.ts
@@ -0,0 +1,109 @@
+import {
+ defineConfig,
+ devices,
+ type PlaywrightTestConfig,
+} from '@playwright/experimental-ct-vue';
+import vue from '@vitejs/plugin-vue';
+import { quasar, transformAssetUrls } from '@quasar/vite-plugin';
+// import { fileURLToPath } from 'node:url';
+// import AutoImport from 'unplugin-auto-import/vite';
+// import Components from 'unplugin-vue-components/vite';
+
+/**
+ * See https://playwright.dev/docs/test-configuration.
+ */
+export default defineConfig({
+ testDir: './src/components',
+ /* The base directory, relative to the config file, for snapshot files created with toMatchSnapshot and toHaveScreenshot. */
+ snapshotDir: './__snapshots__',
+ /* Maximum time one test can run for. */
+ timeout: 10 * 1000,
+ /* Run tests in files in parallel */
+ fullyParallel: true,
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
+ forbidOnly: !!process.env.CI,
+ /* Retry on CI only */
+ retries: process.env.CI ? 2 : 0,
+ /* Opt out of parallel tests on CI. */
+ workers: process.env.CI ? 1 : undefined,
+ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
+ reporter: 'html',
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
+ use: {
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
+ trace: 'on-first-retry',
+
+ /* Port to use for Playwright component endpoint. */
+ ctPort: 3100,
+
+ ctViteConfig: async () => {
+ const { default: istanbul } = await import('vite-plugin-istanbul');
+ return {
+ build: {
+ sourcemap: true,
+ },
+ plugins: [
+ vue({ template: { transformAssetUrls } }),
+ // AutoImport({
+ // imports: [
+ // 'vue',
+ // 'vue-router',
+ // '@vueuse/head',
+ // 'pinia',
+ // 'quasar',
+ // {
+ // '@/store': ['useStore'],
+ // },
+ // ],
+ // dts: 'src/auto-imports.d.ts',
+ // eslintrc: {
+ // enabled: true,
+ // },
+ // }),
+ // Components({
+ // dirs: ['src/components'],
+ // extensions: ['vue'],
+ // }),
+ quasar({
+ // sassVariables: fileURLToPath(
+ // new URL('./src/quasar-variables.sass', import.meta.url),
+ // ),
+ }),
+
+ // Instrument the code for nyc/istanbul code coverage
+ istanbul({
+ include: ['src/**/*'],
+ exclude: [
+ 'node_modules',
+ 'test/',
+ 'dist/',
+ 'coverage/',
+ '__tests__',
+ ],
+ extension: ['.js', '.ts', '.vue'],
+ requireEnv: true,
+ forceBuildInstrument: true,
+ checkProd: false,
+ cypress: false,
+ }),
+ ],
+ };
+ },
+ },
+
+ /* Configure projects for major browsers */
+ projects: [
+ {
+ name: 'chromium',
+ use: { ...devices['Desktop Chrome'] },
+ },
+ {
+ name: 'firefox',
+ use: { ...devices['Desktop Firefox'] },
+ },
+ {
+ name: 'webkit',
+ use: { ...devices['Desktop Safari'] },
+ },
+ ],
+} as PlaywrightTestConfig);
diff --git a/test-vite-app-v2/playwright.config.ts b/test-vite-app-v2/playwright.config.ts
new file mode 100644
index 00000000..9fdf0aed
--- /dev/null
+++ b/test-vite-app-v2/playwright.config.ts
@@ -0,0 +1,79 @@
+import { defineConfig, devices, PlaywrightTestConfig } from '@playwright/test';
+
+/**
+ * Read environment variables from file.
+ * https://github.com/motdotla/dotenv
+ */
+// import dotenv from 'dotenv';
+// import path from 'path';
+// dotenv.config({ path: path.resolve(__dirname, '.env') });
+
+/**
+ * See https://playwright.dev/docs/test-configuration.
+ */
+export default defineConfig({
+ testDir: './test/playwright',
+ /* Run tests in files in parallel */
+ fullyParallel: true,
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
+ forbidOnly: !!process.env.CI,
+ /* Retry on CI only */
+ retries: process.env.CI ? 2 : 0,
+ /* Opt out of parallel tests on CI. */
+ workers: process.env.CI ? 1 : undefined,
+ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
+ reporter: 'html',
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
+ use: {
+ /* Base URL to use in actions like `await page.goto('/')`. */
+ baseURL: 'http://localhost:8080',
+
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
+ trace: 'on-first-retry',
+ },
+
+ /* Configure projects for major browsers */
+ projects: [
+ {
+ name: 'chromium',
+ use: { ...devices['Desktop Chrome'] },
+ },
+
+ {
+ name: 'firefox',
+ use: { ...devices['Desktop Firefox'] },
+ },
+
+ {
+ name: 'webkit',
+ use: { ...devices['Desktop Safari'] },
+ },
+
+ /* Test against mobile viewports. */
+ // {
+ // name: 'Mobile Chrome',
+ // use: { ...devices['Pixel 5'] },
+ // },
+ // {
+ // name: 'Mobile Safari',
+ // use: { ...devices['iPhone 12'] },
+ // },
+
+ /* Test against branded browsers. */
+ // {
+ // name: 'Microsoft Edge',
+ // use: { ...devices['Desktop Edge'], channel: 'msedge' },
+ // },
+ // {
+ // name: 'Google Chrome',
+ // use: { ...devices['Desktop Chrome'], channel: 'chrome' },
+ // },
+ ],
+
+ /* Run your local dev server before starting the tests */
+ webServer: {
+ command: 'quasar dev -p 8080',
+ url: 'http://localhost:8080',
+ reuseExistingServer: !process.env.CI,
+ },
+} as PlaywrightTestConfig);
diff --git a/test-vite-app-v2/playwright/components.d.ts b/test-vite-app-v2/playwright/components.d.ts
new file mode 100644
index 00000000..e3da39eb
--- /dev/null
+++ b/test-vite-app-v2/playwright/components.d.ts
@@ -0,0 +1,14 @@
+/* eslint-disable */
+// @ts-nocheck
+// Generated by unplugin-vue-components
+// Read more: https://github.com/vuejs/core/pull/3399
+// biome-ignore lint: disable
+export {};
+
+/* prettier-ignore */
+declare module 'vue' {
+ export interface GlobalComponents {
+ RouterLink: typeof import('vue-router')['RouterLink']
+ RouterView: typeof import('vue-router')['RouterView']
+ }
+}
diff --git a/test-vite-app-v2/playwright/index.html b/test-vite-app-v2/playwright/index.html
new file mode 100644
index 00000000..56da0401
--- /dev/null
+++ b/test-vite-app-v2/playwright/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ Testing Page
+
+
+
+
+
+
diff --git a/test-vite-app-v2/playwright/index.ts b/test-vite-app-v2/playwright/index.ts
new file mode 100644
index 00000000..f5265b82
--- /dev/null
+++ b/test-vite-app-v2/playwright/index.ts
@@ -0,0 +1,20 @@
+// See https://quasar.dev/start/vite-plugin
+import 'quasar/src/css/index.sass';
+import '../src/css/app.scss';
+import { Quasar, Dialog } from 'quasar';
+import { beforeMount } from '@playwright/experimental-ct-vue/hooks';
+import '@quasar/extras/material-icons/material-icons.css';
+// import '@quasar/extras/mdi-v7/mdi-v7.css';
+
+beforeMount(async ({ app }) => {
+ // Setup other stuff you need before mounting the component. You can setup i18n, pinia, etc here.
+ // See https://playwright.dev/docs/test-components#frequently-asked-questions
+ app.use(Quasar, {
+ plugins: {
+ // Setup plugins used in your components
+ // Notify,
+ // Loading
+ Dialog,
+ },
+ });
+});
diff --git a/test-vite-app-v2/playwright/src/auto-imports.d.ts b/test-vite-app-v2/playwright/src/auto-imports.d.ts
new file mode 100644
index 00000000..bc722ef2
--- /dev/null
+++ b/test-vite-app-v2/playwright/src/auto-imports.d.ts
@@ -0,0 +1,110 @@
+/* eslint-disable */
+/* prettier-ignore */
+// @ts-nocheck
+// noinspection JSUnusedGlobalSymbols
+// Generated by unplugin-auto-import
+// biome-ignore lint: disable
+export {}
+declare global {
+ const EffectScope: (typeof import('vue'))['EffectScope'];
+ const acceptHMRUpdate: (typeof import('pinia'))['acceptHMRUpdate'];
+ const computed: (typeof import('vue'))['computed'];
+ const createApp: (typeof import('vue'))['createApp'];
+ const createPinia: (typeof import('pinia'))['createPinia'];
+ const customRef: (typeof import('vue'))['customRef'];
+ const defineAsyncComponent: (typeof import('vue'))['defineAsyncComponent'];
+ const defineComponent: (typeof import('vue'))['defineComponent'];
+ const defineStore: (typeof import('pinia'))['defineStore'];
+ const effectScope: (typeof import('vue'))['effectScope'];
+ const getActivePinia: (typeof import('pinia'))['getActivePinia'];
+ const getCurrentInstance: (typeof import('vue'))['getCurrentInstance'];
+ const getCurrentScope: (typeof import('vue'))['getCurrentScope'];
+ const h: (typeof import('vue'))['h'];
+ const inject: (typeof import('vue'))['inject'];
+ const isProxy: (typeof import('vue'))['isProxy'];
+ const isReactive: (typeof import('vue'))['isReactive'];
+ const isReadonly: (typeof import('vue'))['isReadonly'];
+ const isRef: (typeof import('vue'))['isRef'];
+ const mapActions: (typeof import('pinia'))['mapActions'];
+ const mapGetters: (typeof import('pinia'))['mapGetters'];
+ const mapState: (typeof import('pinia'))['mapState'];
+ const mapStores: (typeof import('pinia'))['mapStores'];
+ const mapWritableState: (typeof import('pinia'))['mapWritableState'];
+ const markRaw: (typeof import('vue'))['markRaw'];
+ const nextTick: (typeof import('vue'))['nextTick'];
+ const onActivated: (typeof import('vue'))['onActivated'];
+ const onBeforeMount: (typeof import('vue'))['onBeforeMount'];
+ const onBeforeRouteLeave: (typeof import('vue-router'))['onBeforeRouteLeave'];
+ const onBeforeRouteUpdate: (typeof import('vue-router'))['onBeforeRouteUpdate'];
+ const onBeforeUnmount: (typeof import('vue'))['onBeforeUnmount'];
+ const onBeforeUpdate: (typeof import('vue'))['onBeforeUpdate'];
+ const onDeactivated: (typeof import('vue'))['onDeactivated'];
+ const onErrorCaptured: (typeof import('vue'))['onErrorCaptured'];
+ const onMounted: (typeof import('vue'))['onMounted'];
+ const onRenderTracked: (typeof import('vue'))['onRenderTracked'];
+ const onRenderTriggered: (typeof import('vue'))['onRenderTriggered'];
+ const onScopeDispose: (typeof import('vue'))['onScopeDispose'];
+ const onServerPrefetch: (typeof import('vue'))['onServerPrefetch'];
+ const onUnmounted: (typeof import('vue'))['onUnmounted'];
+ const onUpdated: (typeof import('vue'))['onUpdated'];
+ const onWatcherCleanup: (typeof import('vue'))['onWatcherCleanup'];
+ const provide: (typeof import('vue'))['provide'];
+ const reactive: (typeof import('vue'))['reactive'];
+ const readonly: (typeof import('vue'))['readonly'];
+ const ref: (typeof import('vue'))['ref'];
+ const resolveComponent: (typeof import('vue'))['resolveComponent'];
+ const setActivePinia: (typeof import('pinia'))['setActivePinia'];
+ const setMapStoreSuffix: (typeof import('pinia'))['setMapStoreSuffix'];
+ const shallowReactive: (typeof import('vue'))['shallowReactive'];
+ const shallowReadonly: (typeof import('vue'))['shallowReadonly'];
+ const shallowRef: (typeof import('vue'))['shallowRef'];
+ const storeToRefs: (typeof import('pinia'))['storeToRefs'];
+ const toRaw: (typeof import('vue'))['toRaw'];
+ const toRef: (typeof import('vue'))['toRef'];
+ const toRefs: (typeof import('vue'))['toRefs'];
+ const toValue: (typeof import('vue'))['toValue'];
+ const triggerRef: (typeof import('vue'))['triggerRef'];
+ const unref: (typeof import('vue'))['unref'];
+ const useAttrs: (typeof import('vue'))['useAttrs'];
+ const useCssModule: (typeof import('vue'))['useCssModule'];
+ const useCssVars: (typeof import('vue'))['useCssVars'];
+ const useDialogPluginComponent: (typeof import('quasar'))['useDialogPluginComponent'];
+ const useFormChild: (typeof import('quasar'))['useFormChild'];
+ const useHead: (typeof import('@vueuse/head'))['useHead'];
+ const useId: (typeof import('vue'))['useId'];
+ const useLink: (typeof import('vue-router'))['useLink'];
+ const useMeta: (typeof import('quasar'))['useMeta'];
+ const useModel: (typeof import('vue'))['useModel'];
+ const useQuasar: (typeof import('quasar'))['useQuasar'];
+ const useRoute: (typeof import('vue-router'))['useRoute'];
+ const useRouter: (typeof import('vue-router'))['useRouter'];
+ const useSeoMeta: (typeof import('@vueuse/head'))['useSeoMeta'];
+ const useSlots: (typeof import('vue'))['useSlots'];
+ const useStore: (typeof import('@/store'))['useStore'];
+ const useTemplateRef: (typeof import('vue'))['useTemplateRef'];
+ const watch: (typeof import('vue'))['watch'];
+ const watchEffect: (typeof import('vue'))['watchEffect'];
+ const watchPostEffect: (typeof import('vue'))['watchPostEffect'];
+ const watchSyncEffect: (typeof import('vue'))['watchSyncEffect'];
+}
+// for type re-export
+declare global {
+ // @ts-ignore
+ export type {
+ Component,
+ ComponentPublicInstance,
+ ComputedRef,
+ DirectiveBinding,
+ ExtractDefaultPropTypes,
+ ExtractPropTypes,
+ ExtractPublicPropTypes,
+ InjectionKey,
+ PropType,
+ Ref,
+ MaybeRef,
+ MaybeRefOrGetter,
+ VNode,
+ WritableComputedRef,
+ } from 'vue';
+ import('vue');
+}
diff --git a/test-vite-app-v2/quasar.config.ts b/test-vite-app-v2/quasar.config.ts
index 5d3ca4a6..738e8f0c 100644
--- a/test-vite-app-v2/quasar.config.ts
+++ b/test-vite-app-v2/quasar.config.ts
@@ -117,7 +117,7 @@ export default defineConfig((ctx) => {
// directives: [],
// Quasar plugins
- plugins: [],
+ plugins: ['Dialog'],
},
// animations: 'all', // --- includes all animations
diff --git a/test-vite-app-v2/quasar.extensions.json b/test-vite-app-v2/quasar.extensions.json
index c5da8974..ffb2b824 100644
--- a/test-vite-app-v2/quasar.extensions.json
+++ b/test-vite-app-v2/quasar.extensions.json
@@ -5,5 +5,11 @@
"@quasar/testing-e2e-cypress": {
"port": 8080,
"options": ["code-coverage"]
+ },
+ "@quasar/testing-e2e-playwright": {
+ "port": 8080,
+ "githubWorkflow": true,
+ "installBrowsers": true,
+ "enableCodeCoverage": true
}
}
diff --git a/test-vite-app-v2/src/components/AppButton.vue b/test-vite-app-v2/src/components/AppButton.vue
new file mode 100644
index 00000000..a840fe38
--- /dev/null
+++ b/test-vite-app-v2/src/components/AppButton.vue
@@ -0,0 +1,23 @@
+
+
+
+
+
diff --git a/test-vite-app-v2/src/components/AppCheckComponents.vue b/test-vite-app-v2/src/components/AppCheckComponents.vue
new file mode 100644
index 00000000..623ccac1
--- /dev/null
+++ b/test-vite-app-v2/src/components/AppCheckComponents.vue
@@ -0,0 +1,30 @@
+
+
+
+
+ Value1
+ Value2
+
+
+
diff --git a/test-vite-app-v2/src/components/AppDark.vue b/test-vite-app-v2/src/components/AppDark.vue
new file mode 100644
index 00000000..a5f2282b
--- /dev/null
+++ b/test-vite-app-v2/src/components/AppDark.vue
@@ -0,0 +1,35 @@
+
+
+ {{ $q.dark.isActive ? 'Dark ' : 'Light' }} content
+
+
+
+
+
+
diff --git a/test-vite-app-v2/src/components/AppDate.vue b/test-vite-app-v2/src/components/AppDate.vue
new file mode 100644
index 00000000..41b1ea7a
--- /dev/null
+++ b/test-vite-app-v2/src/components/AppDate.vue
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test-vite-app-v2/src/components/AppDialog.vue b/test-vite-app-v2/src/components/AppDialog.vue
new file mode 100644
index 00000000..0d2ed487
--- /dev/null
+++ b/test-vite-app-v2/src/components/AppDialog.vue
@@ -0,0 +1,71 @@
+
+
+
+
+ {{ message }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test-vite-app-v2/src/components/AppDrawer.vue b/test-vite-app-v2/src/components/AppDrawer.vue
new file mode 100644
index 00000000..f65b882e
--- /dev/null
+++ b/test-vite-app-v2/src/components/AppDrawer.vue
@@ -0,0 +1,33 @@
+
+
+
+
+ Am I on screen?
+
+
+
+
+
diff --git a/test-vite-app-v2/src/components/AppMenu.vue b/test-vite-app-v2/src/components/AppMenu.vue
new file mode 100644
index 00000000..a28ec48e
--- /dev/null
+++ b/test-vite-app-v2/src/components/AppMenu.vue
@@ -0,0 +1,22 @@
+
+
+
+
+
+ Item 1
+
+
+ Item 2
+
+
+
+
+
+
+
diff --git a/test-vite-app-v2/src/components/AppPageSticky.vue b/test-vite-app-v2/src/components/AppPageSticky.vue
new file mode 100644
index 00000000..25861bc7
--- /dev/null
+++ b/test-vite-app-v2/src/components/AppPageSticky.vue
@@ -0,0 +1,21 @@
+
+
+
+ {{ title }}
+
+
+
+
+
diff --git a/test-vite-app-v2/src/components/AppSelect.vue b/test-vite-app-v2/src/components/AppSelect.vue
new file mode 100644
index 00000000..fb19c0b4
--- /dev/null
+++ b/test-vite-app-v2/src/components/AppSelect.vue
@@ -0,0 +1,54 @@
+
+
+
+ {{ selected }}
+
+
+
diff --git a/test-vite-app-v2/src/components/AppTooltip.vue b/test-vite-app-v2/src/components/AppTooltip.vue
new file mode 100644
index 00000000..1ab513cb
--- /dev/null
+++ b/test-vite-app-v2/src/components/AppTooltip.vue
@@ -0,0 +1,28 @@
+
+
+ Button
+
+ Here I am!
+
+
+
+
+
diff --git a/test-vite-app-v2/src/components/QuasarButton.vue b/test-vite-app-v2/src/components/QuasarButton.vue
index fa809984..1ef8909c 100644
--- a/test-vite-app-v2/src/components/QuasarButton.vue
+++ b/test-vite-app-v2/src/components/QuasarButton.vue
@@ -1,7 +1,6 @@
true },
});
diff --git a/test-vite-app-v2/src/components/QuasarCheckComponents.vue b/test-vite-app-v2/src/components/QuasarCheckComponents.vue
index f49ea26b..623ccac1 100644
--- a/test-vite-app-v2/src/components/QuasarCheckComponents.vue
+++ b/test-vite-app-v2/src/components/QuasarCheckComponents.vue
@@ -1,9 +1,13 @@
-
-
+
+
- Value1
- Value2
+ Value1
+ Value2
diff --git a/test-vite-app-v2/src/components/QuasarDate.vue b/test-vite-app-v2/src/components/QuasarDate.vue
index 962b4e0a..41b1ea7a 100644
--- a/test-vite-app-v2/src/components/QuasarDate.vue
+++ b/test-vite-app-v2/src/components/QuasarDate.vue
@@ -1,11 +1,11 @@
-
+
-
+
-
+
-
- {{ date }}
diff --git a/test-vite-app-v2/test/playwright/example.spec.ts b/test-vite-app-v2/test/playwright/example.spec.ts
new file mode 100644
index 00000000..a80e2f01
--- /dev/null
+++ b/test-vite-app-v2/test/playwright/example.spec.ts
@@ -0,0 +1,20 @@
+import {
+ test,
+ expect,
+} from '@quasar/quasar-app-extension-testing-e2e-playwright';
+
+test('has title', async ({ page, withinDialog }) => {
+ await page.goto('/');
+
+ await page.getByTestId('open-dialog-button').click();
+
+ await withinDialog(async (dialog) => {
+ await expect(dialog).toContainText('Hello world!');
+
+ await dialog.getByTestId('ok-button').click();
+ await dialog.waitFor({ state: 'hidden' });
+ });
+
+ // Expect a title "to contain" a substring.
+ await expect(page).toHaveTitle(/Quasar App/);
+});
diff --git a/test-vite-app-v2/test/playwright/home.spec.ts b/test-vite-app-v2/test/playwright/home.spec.ts
new file mode 100644
index 00000000..18173075
--- /dev/null
+++ b/test-vite-app-v2/test/playwright/home.spec.ts
@@ -0,0 +1,20 @@
+import {
+ test,
+ expect,
+} from '@quasar/quasar-app-extension-testing-e2e-playwright';
+
+test('has title', async ({ page }) => {
+ await page.goto('https://playwright.dev/');
+
+ await expect(page).toHaveTitle(/Playwright/);
+});
+
+test('get started link', async ({ page }) => {
+ await page.goto('https://playwright.dev/');
+
+ await page.getByRole('link', { name: 'Get started' }).click();
+
+ await expect(
+ page.getByRole('heading', { name: 'Installation' }),
+ ).toBeVisible();
+});
diff --git a/test-vite-app-v2/test/playwright/wrappers/DialogWrapper.vue b/test-vite-app-v2/test/playwright/wrappers/DialogWrapper.vue
new file mode 100644
index 00000000..e2e18fe3
--- /dev/null
+++ b/test-vite-app-v2/test/playwright/wrappers/DialogWrapper.vue
@@ -0,0 +1,35 @@
+
diff --git a/test-vite-app-v2/test/playwright/wrappers/LayoutContainer.vue b/test-vite-app-v2/test/playwright/wrappers/LayoutContainer.vue
new file mode 100644
index 00000000..079fe47a
--- /dev/null
+++ b/test-vite-app-v2/test/playwright/wrappers/LayoutContainer.vue
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
diff --git a/test-vite-app-v2/vitest.config.mts b/test-vite-app-v2/vitest.config.mts
index 057824e3..9118e8ea 100644
--- a/test-vite-app-v2/vitest.config.mts
+++ b/test-vite-app-v2/vitest.config.mts
@@ -2,6 +2,7 @@ import { defineConfig } from 'vitest/config';
import vue from '@vitejs/plugin-vue';
import { quasar, transformAssetUrls } from '@quasar/vite-plugin';
import tsconfigPaths from 'vite-tsconfig-paths';
+import { PluginOption } from 'vite';
// https://vitejs.dev/config/
export default defineConfig({
@@ -26,5 +27,5 @@ export default defineConfig({
// This is needed to avoid Vitest picking up tsconfig.json files from other unrelated projects in the monorepo
ignoreConfigErrors: true,
}),
- ],
+ ] as PluginOption[],
});
diff --git a/test-vite-app-v2/yarn.lock b/test-vite-app-v2/yarn.lock
index a85d2bdd..94721433 100644
--- a/test-vite-app-v2/yarn.lock
+++ b/test-vite-app-v2/yarn.lock
@@ -10,16 +10,7 @@
"@jridgewell/gen-mapping" "^0.3.5"
"@jridgewell/trace-mapping" "^0.3.24"
-"@babel/code-frame@^7.26.2":
- version "7.26.2"
- resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85"
- integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==
- dependencies:
- "@babel/helper-validator-identifier" "^7.25.9"
- js-tokens "^4.0.0"
- picocolors "^1.0.0"
-
-"@babel/code-frame@^7.27.1":
+"@babel/code-frame@^7.26.2", "@babel/code-frame@^7.27.1":
version "7.27.1"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be"
integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==
@@ -28,38 +19,12 @@
js-tokens "^4.0.0"
picocolors "^1.1.1"
-"@babel/compat-data@^7.26.8":
- version "7.26.8"
- resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.8.tgz#821c1d35641c355284d4a870b8a4a7b0c141e367"
- integrity sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==
-
-"@babel/compat-data@^7.27.1":
- version "7.27.1"
- resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.27.1.tgz#db7cf122745e0a332c44e847ddc4f5e5221a43f6"
- integrity sha512-Q+E+rd/yBzNQhXkG+zQnF58e4zoZfBedaxwzPmicKsiK3nt8iJYrSrDbjwFFDGC4f+rPafqRaPH6TsDoSvMf7A==
+"@babel/compat-data@^7.27.2":
+ version "7.27.2"
+ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.27.2.tgz#4183f9e642fd84e74e3eea7ffa93a412e3b102c9"
+ integrity sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==
"@babel/core@^7.23.9":
- version "7.27.1"
- resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.27.1.tgz#89de51e86bd12246003e3524704c49541b16c3e6"
- integrity sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==
- dependencies:
- "@ampproject/remapping" "^2.2.0"
- "@babel/code-frame" "^7.27.1"
- "@babel/generator" "^7.27.1"
- "@babel/helper-compilation-targets" "^7.27.1"
- "@babel/helper-module-transforms" "^7.27.1"
- "@babel/helpers" "^7.27.1"
- "@babel/parser" "^7.27.1"
- "@babel/template" "^7.27.1"
- "@babel/traverse" "^7.27.1"
- "@babel/types" "^7.27.1"
- convert-source-map "^2.0.0"
- debug "^4.1.0"
- gensync "^1.0.0-beta.2"
- json5 "^2.2.3"
- semver "^6.3.1"
-
-"@babel/core@^7.7.5":
version "7.26.10"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.10.tgz#5c876f83c8c4dcb233ee4b670c0606f2ac3000f9"
integrity sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==
@@ -80,18 +45,28 @@
json5 "^2.2.3"
semver "^6.3.1"
-"@babel/generator@^7.26.10", "@babel/generator@^7.27.0":
- version "7.27.0"
- resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.27.0.tgz#764382b5392e5b9aff93cadb190d0745866cbc2c"
- integrity sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==
+"@babel/core@^7.7.5":
+ version "7.27.1"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.27.1.tgz#89de51e86bd12246003e3524704c49541b16c3e6"
+ integrity sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==
dependencies:
- "@babel/parser" "^7.27.0"
- "@babel/types" "^7.27.0"
- "@jridgewell/gen-mapping" "^0.3.5"
- "@jridgewell/trace-mapping" "^0.3.25"
- jsesc "^3.0.2"
+ "@ampproject/remapping" "^2.2.0"
+ "@babel/code-frame" "^7.27.1"
+ "@babel/generator" "^7.27.1"
+ "@babel/helper-compilation-targets" "^7.27.1"
+ "@babel/helper-module-transforms" "^7.27.1"
+ "@babel/helpers" "^7.27.1"
+ "@babel/parser" "^7.27.1"
+ "@babel/template" "^7.27.1"
+ "@babel/traverse" "^7.27.1"
+ "@babel/types" "^7.27.1"
+ convert-source-map "^2.0.0"
+ debug "^4.1.0"
+ gensync "^1.0.0-beta.2"
+ json5 "^2.2.3"
+ semver "^6.3.1"
-"@babel/generator@^7.27.1":
+"@babel/generator@^7.26.10", "@babel/generator@^7.27.1":
version "7.27.1"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.27.1.tgz#862d4fad858f7208edd487c28b58144036b76230"
integrity sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==
@@ -102,36 +77,17 @@
"@jridgewell/trace-mapping" "^0.3.25"
jsesc "^3.0.2"
-"@babel/helper-compilation-targets@^7.26.5":
- version "7.27.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz#de0c753b1cd1d9ab55d473c5a5cf7170f0a81880"
- integrity sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==
+"@babel/helper-compilation-targets@^7.26.5", "@babel/helper-compilation-targets@^7.27.1":
+ version "7.27.2"
+ resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz#46a0f6efab808d51d29ce96858dd10ce8732733d"
+ integrity sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==
dependencies:
- "@babel/compat-data" "^7.26.8"
- "@babel/helper-validator-option" "^7.25.9"
- browserslist "^4.24.0"
- lru-cache "^5.1.1"
- semver "^6.3.1"
-
-"@babel/helper-compilation-targets@^7.27.1":
- version "7.27.1"
- resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.1.tgz#eac1096c7374f161e4f33fc8ae38f4ddf122087a"
- integrity sha512-2YaDd/Rd9E598B5+WIc8wJPmWETiiJXFYVE60oX8FDohv7rAUU3CQj+A1MgeEmcsk2+dQuEjIe/GDvig0SqL4g==
- dependencies:
- "@babel/compat-data" "^7.27.1"
+ "@babel/compat-data" "^7.27.2"
"@babel/helper-validator-option" "^7.27.1"
browserslist "^4.24.0"
lru-cache "^5.1.1"
semver "^6.3.1"
-"@babel/helper-module-imports@^7.25.9":
- version "7.25.9"
- resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz#e7f8d20602ebdbf9ebbea0a0751fb0f2a4141715"
- integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==
- dependencies:
- "@babel/traverse" "^7.25.9"
- "@babel/types" "^7.25.9"
-
"@babel/helper-module-imports@^7.27.1":
version "7.27.1"
resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz#7ef769a323e2655e126673bb6d2d6913bbead204"
@@ -140,16 +96,7 @@
"@babel/traverse" "^7.27.1"
"@babel/types" "^7.27.1"
-"@babel/helper-module-transforms@^7.26.0":
- version "7.26.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae"
- integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==
- dependencies:
- "@babel/helper-module-imports" "^7.25.9"
- "@babel/helper-validator-identifier" "^7.25.9"
- "@babel/traverse" "^7.25.9"
-
-"@babel/helper-module-transforms@^7.27.1":
+"@babel/helper-module-transforms@^7.26.0", "@babel/helper-module-transforms@^7.27.1":
version "7.27.1"
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz#e1663b8b71d2de948da5c4fb2a20ca4f3ec27a6f"
integrity sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==
@@ -158,45 +105,22 @@
"@babel/helper-validator-identifier" "^7.27.1"
"@babel/traverse" "^7.27.1"
-"@babel/helper-string-parser@^7.25.9":
- version "7.25.9"
- resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c"
- integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==
-
"@babel/helper-string-parser@^7.27.1":
version "7.27.1"
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687"
integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==
-"@babel/helper-validator-identifier@^7.25.9":
- version "7.25.9"
- resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7"
- integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==
-
"@babel/helper-validator-identifier@^7.27.1":
version "7.27.1"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8"
integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==
-"@babel/helper-validator-option@^7.25.9":
- version "7.25.9"
- resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz#86e45bd8a49ab7e03f276577f96179653d41da72"
- integrity sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==
-
"@babel/helper-validator-option@^7.27.1":
version "7.27.1"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f"
integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==
-"@babel/helpers@^7.26.10":
- version "7.27.0"
- resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.27.0.tgz#53d156098defa8243eab0f32fa17589075a1b808"
- integrity sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==
- dependencies:
- "@babel/template" "^7.27.0"
- "@babel/types" "^7.27.0"
-
-"@babel/helpers@^7.27.1":
+"@babel/helpers@^7.26.10", "@babel/helpers@^7.27.1":
version "7.27.1"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.27.1.tgz#ffc27013038607cdba3288e692c3611c06a18aa4"
integrity sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==
@@ -204,21 +128,28 @@
"@babel/template" "^7.27.1"
"@babel/types" "^7.27.1"
-"@babel/parser@^7.23.9", "@babel/parser@^7.27.1":
- version "7.27.1"
- resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.27.1.tgz#c55d5bed74449d1223701f1869b9ee345cc94cc9"
- integrity sha512-I0dZ3ZpCrJ1c04OqlNsQcKiZlsrXf/kkE4FXzID9rIOYICsAbA8mMDzhW/luRNAHdCNt7os/u8wenklZDlUVUQ==
- dependencies:
- "@babel/types" "^7.27.1"
-
-"@babel/parser@^7.25.3", "@babel/parser@^7.26.10", "@babel/parser@^7.27.0":
+"@babel/parser@^7.23.9", "@babel/parser@^7.25.3", "@babel/parser@^7.27.0":
version "7.27.0"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.27.0.tgz#3d7d6ee268e41d2600091cbd4e145ffee85a44ec"
integrity sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==
dependencies:
"@babel/types" "^7.27.0"
-"@babel/template@^7.26.9", "@babel/template@^7.27.0":
+"@babel/parser@^7.26.10", "@babel/parser@^7.27.2":
+ version "7.27.2"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.27.2.tgz#577518bedb17a2ce4212afd052e01f7df0941127"
+ integrity sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==
+ dependencies:
+ "@babel/types" "^7.27.1"
+
+"@babel/parser@^7.27.1":
+ version "7.27.1"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.27.1.tgz#c55d5bed74449d1223701f1869b9ee345cc94cc9"
+ integrity sha512-I0dZ3ZpCrJ1c04OqlNsQcKiZlsrXf/kkE4FXzID9rIOYICsAbA8mMDzhW/luRNAHdCNt7os/u8wenklZDlUVUQ==
+ dependencies:
+ "@babel/types" "^7.27.1"
+
+"@babel/template@^7.26.9":
version "7.27.0"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.0.tgz#b253e5406cc1df1c57dcd18f11760c2dbf40c0b4"
integrity sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==
@@ -228,28 +159,15 @@
"@babel/types" "^7.27.0"
"@babel/template@^7.27.1":
- version "7.27.1"
- resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.1.tgz#b9e4f55c17a92312774dfbdde1b3c01c547bbae2"
- integrity sha512-Fyo3ghWMqkHHpHQCoBs2VnYjR4iWFFjguTDEqA5WgZDOrFesVjMhMM2FSqTKSoUSDO1VQtavj8NFpdRBEvJTtg==
+ version "7.27.2"
+ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.2.tgz#fa78ceed3c4e7b63ebf6cb39e5852fca45f6809d"
+ integrity sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==
dependencies:
"@babel/code-frame" "^7.27.1"
- "@babel/parser" "^7.27.1"
+ "@babel/parser" "^7.27.2"
"@babel/types" "^7.27.1"
-"@babel/traverse@^7.25.9", "@babel/traverse@^7.26.10":
- version "7.27.0"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.27.0.tgz#11d7e644779e166c0442f9a07274d02cd91d4a70"
- integrity sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==
- dependencies:
- "@babel/code-frame" "^7.26.2"
- "@babel/generator" "^7.27.0"
- "@babel/parser" "^7.27.0"
- "@babel/template" "^7.27.0"
- "@babel/types" "^7.27.0"
- debug "^4.3.1"
- globals "^11.1.0"
-
-"@babel/traverse@^7.27.1":
+"@babel/traverse@^7.26.10", "@babel/traverse@^7.27.1":
version "7.27.1"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.27.1.tgz#4db772902b133bbddd1c4f7a7ee47761c1b9f291"
integrity sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==
@@ -262,15 +180,7 @@
debug "^4.3.1"
globals "^11.1.0"
-"@babel/types@^7.25.9", "@babel/types@^7.26.10", "@babel/types@^7.27.0":
- version "7.27.0"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.27.0.tgz#ef9acb6b06c3173f6632d993ecb6d4ae470b4559"
- integrity sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==
- dependencies:
- "@babel/helper-string-parser" "^7.25.9"
- "@babel/helper-validator-identifier" "^7.25.9"
-
-"@babel/types@^7.27.1":
+"@babel/types@^7.26.10", "@babel/types@^7.27.0", "@babel/types@^7.27.1":
version "7.27.1"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.27.1.tgz#9defc53c16fc899e46941fc6901a9eea1c9d8560"
integrity sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==
@@ -345,130 +255,130 @@
debug "^3.1.0"
lodash.once "^4.1.1"
-"@esbuild/aix-ppc64@0.25.3":
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.3.tgz#014180d9a149cffd95aaeead37179433f5ea5437"
- integrity sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==
-
-"@esbuild/android-arm64@0.25.3":
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.3.tgz#649e47e04ddb24a27dc05c395724bc5f4c55cbfe"
- integrity sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==
-
-"@esbuild/android-arm@0.25.3":
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.3.tgz#8a0f719c8dc28a4a6567ef7328c36ea85f568ff4"
- integrity sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==
-
-"@esbuild/android-x64@0.25.3":
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.3.tgz#e2ab182d1fd06da9bef0784a13c28a7602d78009"
- integrity sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==
-
-"@esbuild/darwin-arm64@0.25.3":
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.3.tgz#c7f3166fcece4d158a73dcfe71b2672ca0b1668b"
- integrity sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==
-
-"@esbuild/darwin-x64@0.25.3":
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.3.tgz#d8c5342ec1a4bf4b1915643dfe031ba4b173a87a"
- integrity sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==
-
-"@esbuild/freebsd-arm64@0.25.3":
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.3.tgz#9f7d789e2eb7747d4868817417cc968ffa84f35b"
- integrity sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw==
-
-"@esbuild/freebsd-x64@0.25.3":
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.3.tgz#8ad35c51d084184a8e9e76bb4356e95350a64709"
- integrity sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==
-
-"@esbuild/linux-arm64@0.25.3":
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.3.tgz#3af0da3d9186092a9edd4e28fa342f57d9e3cd30"
- integrity sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A==
-
-"@esbuild/linux-arm@0.25.3":
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.3.tgz#e91cafa95e4474b3ae3d54da12e006b782e57225"
- integrity sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==
-
-"@esbuild/linux-ia32@0.25.3":
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.3.tgz#81025732d85b68ee510161b94acdf7e3007ea177"
- integrity sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw==
-
-"@esbuild/linux-loong64@0.25.3":
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.3.tgz#3c744e4c8d5e1148cbe60a71a11b58ed8ee5deb8"
- integrity sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==
-
-"@esbuild/linux-mips64el@0.25.3":
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.3.tgz#1dfe2a5d63702db9034cc6b10b3087cc0424ec26"
- integrity sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag==
-
-"@esbuild/linux-ppc64@0.25.3":
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.3.tgz#2e85d9764c04a1ebb346dc0813ea05952c9a5c56"
- integrity sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==
-
-"@esbuild/linux-riscv64@0.25.3":
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.3.tgz#a9ea3334556b09f85ccbfead58c803d305092415"
- integrity sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA==
-
-"@esbuild/linux-s390x@0.25.3":
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.3.tgz#f6a7cb67969222b200974de58f105dfe8e99448d"
- integrity sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==
-
-"@esbuild/linux-x64@0.25.3":
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.3.tgz#a237d3578ecdd184a3066b1f425e314ade0f8033"
- integrity sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA==
-
-"@esbuild/netbsd-arm64@0.25.3":
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.3.tgz#4c15c68d8149614ddb6a56f9c85ae62ccca08259"
- integrity sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==
-
-"@esbuild/netbsd-x64@0.25.3":
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.3.tgz#12f6856f8c54c2d7d0a8a64a9711c01a743878d5"
- integrity sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g==
-
-"@esbuild/openbsd-arm64@0.25.3":
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.3.tgz#ca078dad4a34df192c60233b058db2ca3d94bc5c"
- integrity sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==
-
-"@esbuild/openbsd-x64@0.25.3":
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.3.tgz#c9178adb60e140e03a881d0791248489c79f95b2"
- integrity sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w==
-
-"@esbuild/sunos-x64@0.25.3":
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.3.tgz#03765eb6d4214ff27e5230af779e80790d1ee09f"
- integrity sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==
-
-"@esbuild/win32-arm64@0.25.3":
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.3.tgz#f1c867bd1730a9b8dfc461785ec6462e349411ea"
- integrity sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==
-
-"@esbuild/win32-ia32@0.25.3":
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.3.tgz#77491f59ef6c9ddf41df70670d5678beb3acc322"
- integrity sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==
-
-"@esbuild/win32-x64@0.25.3":
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.3.tgz#b17a2171f9074df9e91bfb07ef99a892ac06412a"
- integrity sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==
+"@esbuild/aix-ppc64@0.25.1":
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz#c33cf6bbee34975626b01b80451cbb72b4c6c91d"
+ integrity sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==
+
+"@esbuild/android-arm64@0.25.1":
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.1.tgz#ea766015c7d2655164f22100d33d7f0308a28d6d"
+ integrity sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==
+
+"@esbuild/android-arm@0.25.1":
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.1.tgz#e84d2bf2fe2e6177a0facda3a575b2139fd3cb9c"
+ integrity sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==
+
+"@esbuild/android-x64@0.25.1":
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.1.tgz#58337bee3bc6d78d10425e5500bd11370cfdfbed"
+ integrity sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==
+
+"@esbuild/darwin-arm64@0.25.1":
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.1.tgz#a46805c1c585d451aa83be72500bd6e8495dd591"
+ integrity sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==
+
+"@esbuild/darwin-x64@0.25.1":
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.1.tgz#0643e003bb238c63fc93ddbee7d26a003be3cd98"
+ integrity sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==
+
+"@esbuild/freebsd-arm64@0.25.1":
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.1.tgz#cff18da5469c09986b93e87979de5d6872fe8f8e"
+ integrity sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==
+
+"@esbuild/freebsd-x64@0.25.1":
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.1.tgz#362fc09c2de14987621c1878af19203c46365dde"
+ integrity sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==
+
+"@esbuild/linux-arm64@0.25.1":
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.1.tgz#aa90d5b02efc97a271e124e6d1cea490634f7498"
+ integrity sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==
+
+"@esbuild/linux-arm@0.25.1":
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.1.tgz#dfcefcbac60a20918b19569b4b657844d39db35a"
+ integrity sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==
+
+"@esbuild/linux-ia32@0.25.1":
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.1.tgz#6f9527077ccb7953ed2af02e013d4bac69f13754"
+ integrity sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==
+
+"@esbuild/linux-loong64@0.25.1":
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.1.tgz#287d2412a5456e5860c2839d42a4b51284d1697c"
+ integrity sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==
+
+"@esbuild/linux-mips64el@0.25.1":
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.1.tgz#530574b9e1bc5d20f7a4f44c5f045e26f3783d57"
+ integrity sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==
+
+"@esbuild/linux-ppc64@0.25.1":
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.1.tgz#5d7e6b283a0b321ea42c6bc0abeb9eb99c1f5589"
+ integrity sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==
+
+"@esbuild/linux-riscv64@0.25.1":
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.1.tgz#14fa0cd073c26b4ee2465d18cd1e18eea7859fa8"
+ integrity sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==
+
+"@esbuild/linux-s390x@0.25.1":
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.1.tgz#e677b4b9d1b384098752266ccaa0d52a420dc1aa"
+ integrity sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==
+
+"@esbuild/linux-x64@0.25.1":
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.1.tgz#f1c796b78fff5ce393658313e8c58613198d9954"
+ integrity sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==
+
+"@esbuild/netbsd-arm64@0.25.1":
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.1.tgz#0d280b7dfe3973f111b02d5fe9f3063b92796d29"
+ integrity sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==
+
+"@esbuild/netbsd-x64@0.25.1":
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.1.tgz#be663893931a4bb3f3a009c5cc24fa9681cc71c0"
+ integrity sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==
+
+"@esbuild/openbsd-arm64@0.25.1":
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.1.tgz#d9021b884233673a05dc1cc26de0bf325d824217"
+ integrity sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==
+
+"@esbuild/openbsd-x64@0.25.1":
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.1.tgz#9f1dc1786ed2e2938c404b06bcc48be9a13250de"
+ integrity sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==
+
+"@esbuild/sunos-x64@0.25.1":
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.1.tgz#89aac24a4b4115959b3f790192cf130396696c27"
+ integrity sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==
+
+"@esbuild/win32-arm64@0.25.1":
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.1.tgz#354358647a6ea98ea6d243bf48bdd7a434999582"
+ integrity sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==
+
+"@esbuild/win32-ia32@0.25.1":
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.1.tgz#8cea7340f2647eba951a041dc95651e3908cd4cb"
+ integrity sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==
+
+"@esbuild/win32-x64@0.25.1":
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.1.tgz#7d79922cb2d88f9048f06393dbf62d2e4accb584"
+ integrity sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
version "4.6.1"
@@ -671,6 +581,13 @@
js-yaml "^3.13.1"
resolve-from "^5.0.0"
+"@istanbuljs/nyc-config-typescript@^1.0.2":
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/@istanbuljs/nyc-config-typescript/-/nyc-config-typescript-1.0.2.tgz#1f5235b28540a07219ae0dd42014912a0b19cf89"
+ integrity sha512-iKGIyMoyJuFnJRSVTZ78POIRvNnwZaWIf8vG4ZS3rQq58MMDrqEX2nnzx0R28V2X8JvmKYiqY9FP2hlJsm8A0w==
+ dependencies:
+ "@istanbuljs/schema" "^0.1.2"
+
"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3":
version "0.1.3"
resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98"
@@ -752,6 +669,30 @@
resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.4.tgz#d897170a2b0ba51f78a099edccd968f7b103387c"
integrity sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==
+"@playwright/experimental-ct-core@1.52.0":
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/@playwright/experimental-ct-core/-/experimental-ct-core-1.52.0.tgz#3fa18bc7952deaf141ad2a2c1cdfcff1de6c7192"
+ integrity sha512-DiDEammXxt8OIFDfoNitoOZyHFJAu6aYi0abmHl0IZgOQHxccP6UX50aTEnSTTUWCfwUWB0Vd8TKJ6w122WJEw==
+ dependencies:
+ playwright "1.52.0"
+ playwright-core "1.52.0"
+ vite "^6.2.6"
+
+"@playwright/experimental-ct-vue@^1.50.0":
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/@playwright/experimental-ct-vue/-/experimental-ct-vue-1.52.0.tgz#8c5ca57e98def53e6befeadb0a433a9141d133b3"
+ integrity sha512-MaUVEZZ+eo/UH/qWLwUzDl2SgjYyGQUVrGFVayUX07TASS4FDMRV8f8Jjkk0t7iYeFfWE2ZyZS1muLeWeP7qXg==
+ dependencies:
+ "@playwright/experimental-ct-core" "1.52.0"
+ "@vitejs/plugin-vue" "^5.2.0"
+
+"@playwright/test@^1.49.1":
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.52.0.tgz#267ec595b43a8f4fa5e444ea503689629e91a5b8"
+ integrity sha512-uh6W7sb55hl7D6vsAeA+V2p5JnlAqzhqFyF0VcJkKZXkgnFcVG9PziERRHQfPLfNGx1C292a4JqbWzhR8L4R1g==
+ dependencies:
+ playwright "1.52.0"
+
"@polka/url@^1.0.0-next.24":
version "1.0.0-next.29"
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.29.tgz#5a40109a1ab5f84d6fd8fc928b19f367cbe7e7b1"
@@ -806,7 +747,7 @@
integrity sha512-4aX9XU/oj1+8O2C7LQCgywmoIw7suyUEZMPFFLWI61f21mF55VOsMdLCBhjeFgL5U4EWy079mfOR6/J8thi/ag==
"@quasar/quasar-app-extension-testing-e2e-cypress@../packages/e2e-cypress":
- version "6.2.0"
+ version "6.2.1"
dependencies:
"@cypress/code-coverage" "^3.12.26"
cross-env "^7.0.3"
@@ -815,6 +756,14 @@
start-server-and-test "^2.0.3"
vite-plugin-istanbul "^7.0.0"
+"@quasar/quasar-app-extension-testing-e2e-playwright@../packages/e2e-playwright":
+ version "0.0.1"
+ dependencies:
+ "@istanbuljs/nyc-config-typescript" "^1.0.2"
+ cross-env "^7.0.3"
+ nyc "^17.1.0"
+ vite-plugin-istanbul "^7.0.0"
+
"@quasar/quasar-app-extension-testing-unit-vitest@../packages/unit-vitest":
version "1.2.3"
dependencies:
@@ -1230,6 +1179,11 @@
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-5.2.3.tgz#71a8fc82d4d2e425af304c35bf389506f674d89b"
integrity sha512-IYSLEQj4LgZZuoVpdSUCw3dIynTWQgPlaRP6iAvMle4My0HdYwr5g5wQAfwOeHQBmYwEkqF70nRpSilr6PoUDg==
+"@vitejs/plugin-vue@^5.2.0":
+ version "5.2.4"
+ resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz#9e8a512eb174bfc2a333ba959bbf9de428d89ad8"
+ integrity sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==
+
"@vitest/expect@3.1.2":
version "3.1.2"
resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-3.1.2.tgz#b203a7ad2efa6af96c85f6c116216bda259d2bc8"
@@ -1249,13 +1203,20 @@
estree-walker "^3.0.3"
magic-string "^0.30.17"
-"@vitest/pretty-format@3.1.2", "@vitest/pretty-format@^3.1.2":
+"@vitest/pretty-format@3.1.2":
version "3.1.2"
resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-3.1.2.tgz#689b0604c0b73fdccb144f11b64d70c9233b23b8"
integrity sha512-R0xAiHuWeDjTSB3kQ3OQpT8Rx3yhdOAIm/JM4axXxnG7Q/fS8XUwggv/A4xzbQA+drYRjzkMnpYnOGAc4oeq8w==
dependencies:
tinyrainbow "^2.0.0"
+"@vitest/pretty-format@^3.1.2":
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-3.1.3.tgz#760b9eab5f253d7d2e7dcd28ef34570f584023d4"
+ integrity sha512-i6FDiBeJUGLDKADw2Gb01UtUNb12yyXAqC/mmRWuYl+m/U9GS7s8us5ONmGkGpUUo7/iAYzI2ePVfOZTYvUifA==
+ dependencies:
+ tinyrainbow "^2.0.0"
+
"@vitest/runner@3.1.2":
version "3.1.2"
resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-3.1.2.tgz#ffeba74618046221e944e94f09b565af772170cf"
@@ -1508,11 +1469,21 @@ acorn-jsx@^5.3.2:
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
-acorn@^8.14.0, acorn@^8.5.0, acorn@^8.8.2, acorn@^8.9.0:
+acorn@^8.14.0, acorn@^8.5.0:
version "8.14.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb"
integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==
+acorn@^8.8.2:
+ version "8.12.1"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248"
+ integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==
+
+acorn@^8.9.0:
+ version "8.11.2"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.2.tgz#ca0d78b51895be5390a5903c5b3bdcdaf78ae40b"
+ integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==
+
aggregate-error@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a"
@@ -1554,9 +1525,9 @@ ansi-regex@^5.0.1:
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
ansi-regex@^6.0.1:
- version "6.1.0"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654"
- integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a"
+ integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==
ansi-styles@^4.0.0, ansi-styles@^4.1.0:
version "4.3.0"
@@ -1707,7 +1678,16 @@ aws4@^1.8.0:
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.13.2.tgz#0aa167216965ac9474ccfa83892cfb6b3e1e52ef"
integrity sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==
-axios@^1.6.3, axios@^1.8.2:
+axios@^1.6.3:
+ version "1.6.3"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.3.tgz#7f50f23b3aa246eff43c54834272346c396613f4"
+ integrity sha512-fWyNdeawGam70jXSVlKl+SUNVcL6j6W79CuSIPfi6HnDUmSCH6gyUys/HrqHeA/wU0Az41rRgean494d0Jb+ww==
+ dependencies:
+ follow-redirects "^1.15.0"
+ form-data "^4.0.0"
+ proxy-from-env "^1.1.0"
+
+axios@^1.8.2:
version "1.9.0"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.9.0.tgz#25534e3b72b54540077d33046f77e3b8d7081901"
integrity sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==
@@ -1934,7 +1914,12 @@ camelcase@^5.0.0, camelcase@^5.3.1:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
-caniuse-lite@^1.0.30001688, caniuse-lite@^1.0.30001702:
+caniuse-lite@^1.0.30001688:
+ version "1.0.30001707"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001707.tgz#c5e104d199e6f4355a898fcd995a066c7eb9bf41"
+ integrity sha512-3qtRjw/HQSMlDWf+X79N206fepf4SOOU6SQLMaq/0KkZLmSjPxAkBOQQ+FxbHKfHmYLZFfdWsO3KA90ceHPSnw==
+
+caniuse-lite@^1.0.30001702:
version "1.0.30001715"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001715.tgz#bd325a37ad366e3fe90827d74062807a34fbaeb2"
integrity sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw==
@@ -2255,7 +2240,16 @@ cross-env@^7.0.3:
dependencies:
cross-spawn "^7.0.1"
-cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.3, cross-spawn@^7.0.6:
+cross-spawn@^7.0.0, cross-spawn@^7.0.3:
+ version "7.0.3"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
+ integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
+ dependencies:
+ path-key "^3.1.0"
+ shebang-command "^2.0.0"
+ which "^2.0.1"
+
+cross-spawn@^7.0.1, cross-spawn@^7.0.6:
version "7.0.6"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
@@ -2330,11 +2324,16 @@ dashdash@^1.12.0:
dependencies:
assert-plus "^1.0.0"
-dayjs@1.11.13, dayjs@^1.10.4:
+dayjs@1.11.13:
version "1.11.13"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c"
integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==
+dayjs@^1.10.4:
+ version "1.11.10"
+ resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.10.tgz#68acea85317a6e164457d6d6947564029a6a16a0"
+ integrity sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==
+
de-indent@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
@@ -2347,7 +2346,7 @@ debug@2.6.9:
dependencies:
ms "2.0.0"
-debug@4.4.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@^4.4.0:
+debug@4.4.0, debug@^4.3.3, debug@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a"
integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==
@@ -2361,6 +2360,13 @@ debug@^3.1.0:
dependencies:
ms "^2.1.1"
+debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4:
+ version "4.3.4"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
+ integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
+ dependencies:
+ ms "2.1.2"
+
decamelize@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
@@ -2505,9 +2511,9 @@ ee-first@1.1.1:
integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
electron-to-chromium@^1.5.73:
- version "1.5.142"
- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.142.tgz#1de55d0d19b24b07768c4bfc90f41bd7f248d043"
- integrity sha512-Ah2HgkTu/9RhTDNThBtzu2Wirdy4DC9b0sMT1pUhbkZQ5U/iwmE+PHZX1MpjD5IkJCc2wSghgGG/B04szAx07w==
+ version "1.5.128"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.128.tgz#8ea537b369c32527b3cc47df7973bffe5d3c2980"
+ integrity sha512-bo1A4HH/NS522Ws0QNFIzyPcyUUNV/yyy70Ho1xqfGYzPUme2F/xr4tlEOuM6/A538U1vDA7a4XfCd1CKRegKQ==
elementtree@0.1.7:
version "0.1.7"
@@ -2594,37 +2600,42 @@ es6-error@^4.0.1:
integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==
esbuild@^0.25.0:
- version "0.25.3"
- resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.3.tgz#371f7cb41283e5b2191a96047a7a89562965a285"
- integrity sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==
+ version "0.25.1"
+ resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.1.tgz#a16b8d070b6ad4871935277bda6ccfe852e3fa2f"
+ integrity sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==
optionalDependencies:
- "@esbuild/aix-ppc64" "0.25.3"
- "@esbuild/android-arm" "0.25.3"
- "@esbuild/android-arm64" "0.25.3"
- "@esbuild/android-x64" "0.25.3"
- "@esbuild/darwin-arm64" "0.25.3"
- "@esbuild/darwin-x64" "0.25.3"
- "@esbuild/freebsd-arm64" "0.25.3"
- "@esbuild/freebsd-x64" "0.25.3"
- "@esbuild/linux-arm" "0.25.3"
- "@esbuild/linux-arm64" "0.25.3"
- "@esbuild/linux-ia32" "0.25.3"
- "@esbuild/linux-loong64" "0.25.3"
- "@esbuild/linux-mips64el" "0.25.3"
- "@esbuild/linux-ppc64" "0.25.3"
- "@esbuild/linux-riscv64" "0.25.3"
- "@esbuild/linux-s390x" "0.25.3"
- "@esbuild/linux-x64" "0.25.3"
- "@esbuild/netbsd-arm64" "0.25.3"
- "@esbuild/netbsd-x64" "0.25.3"
- "@esbuild/openbsd-arm64" "0.25.3"
- "@esbuild/openbsd-x64" "0.25.3"
- "@esbuild/sunos-x64" "0.25.3"
- "@esbuild/win32-arm64" "0.25.3"
- "@esbuild/win32-ia32" "0.25.3"
- "@esbuild/win32-x64" "0.25.3"
-
-escalade@^3.1.1, escalade@^3.2.0:
+ "@esbuild/aix-ppc64" "0.25.1"
+ "@esbuild/android-arm" "0.25.1"
+ "@esbuild/android-arm64" "0.25.1"
+ "@esbuild/android-x64" "0.25.1"
+ "@esbuild/darwin-arm64" "0.25.1"
+ "@esbuild/darwin-x64" "0.25.1"
+ "@esbuild/freebsd-arm64" "0.25.1"
+ "@esbuild/freebsd-x64" "0.25.1"
+ "@esbuild/linux-arm" "0.25.1"
+ "@esbuild/linux-arm64" "0.25.1"
+ "@esbuild/linux-ia32" "0.25.1"
+ "@esbuild/linux-loong64" "0.25.1"
+ "@esbuild/linux-mips64el" "0.25.1"
+ "@esbuild/linux-ppc64" "0.25.1"
+ "@esbuild/linux-riscv64" "0.25.1"
+ "@esbuild/linux-s390x" "0.25.1"
+ "@esbuild/linux-x64" "0.25.1"
+ "@esbuild/netbsd-arm64" "0.25.1"
+ "@esbuild/netbsd-x64" "0.25.1"
+ "@esbuild/openbsd-arm64" "0.25.1"
+ "@esbuild/openbsd-x64" "0.25.1"
+ "@esbuild/sunos-x64" "0.25.1"
+ "@esbuild/win32-arm64" "0.25.1"
+ "@esbuild/win32-ia32" "0.25.1"
+ "@esbuild/win32-x64" "0.25.1"
+
+escalade@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
+ integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
+
+escalade@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5"
integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==
@@ -2667,6 +2678,13 @@ eslint-plugin-cypress@^4.2.1:
dependencies:
globals "^15.15.0"
+eslint-plugin-playwright@^2.1.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-playwright/-/eslint-plugin-playwright-2.2.0.tgz#d7eda21e670274fc0c006e11ba5cc2c8417b2a6e"
+ integrity sha512-qSQpAw7RcSzE3zPp8FMGkthaCWovHZ/BsXtpmnGax9vQLIovlh1bsZHEa2+j2lv9DWhnyeLM/qZmp7ffQZfQvg==
+ dependencies:
+ globals "^13.23.0"
+
eslint-plugin-prettier@^5.2.2:
version "5.2.6"
resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.6.tgz#be39e3bb23bb3eeb7e7df0927cdb46e4d7945096"
@@ -3099,6 +3117,11 @@ flatted@^3.2.9, flatted@^3.3.3:
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358"
integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==
+follow-redirects@^1.15.0:
+ version "1.15.3"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.3.tgz#fe2f3ef2690afce7e82ed0b44db08165b207123a"
+ integrity sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==
+
follow-redirects@^1.15.6:
version "1.15.9"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1"
@@ -3112,7 +3135,7 @@ foreground-child@^2.0.0:
cross-spawn "^7.0.0"
signal-exit "^3.0.2"
-foreground-child@^3.1.0:
+foreground-child@^3.1.0, foreground-child@^3.3.0:
version "3.3.1"
resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f"
integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==
@@ -3184,6 +3207,11 @@ fs.realpath@^1.0.0:
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
+fsevents@2.3.2:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
+ integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
+
fsevents@~2.3.2, fsevents@~2.3.3:
version "2.3.3"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
@@ -3309,7 +3337,7 @@ globals@^11.1.0:
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
-globals@^13.24.0:
+globals@^13.23.0, globals@^13.24.0:
version "13.24.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171"
integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==
@@ -3700,7 +3728,7 @@ istanbul-lib-instrument@^4.0.0:
istanbul-lib-coverage "^3.0.0"
semver "^6.3.0"
-istanbul-lib-instrument@^6.0.3:
+istanbul-lib-instrument@^6.0.2, istanbul-lib-instrument@^6.0.3:
version "6.0.3"
resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz#fa15401df6c15874bcb2105f773325d78c666765"
integrity sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==
@@ -4006,6 +4034,13 @@ lru-cache@^5.1.1:
dependencies:
yallist "^3.0.2"
+lru-cache@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
+ integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
+ dependencies:
+ yallist "^4.0.0"
+
magic-string@^0.30.11, magic-string@^0.30.17:
version "0.30.17"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453"
@@ -4160,6 +4195,11 @@ ms@2.0.0:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==
+ms@2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
+ integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
+
ms@2.1.3, ms@^2.1.1, ms@^2.1.3:
version "2.1.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
@@ -4292,6 +4332,39 @@ nyc@15.1.0, nyc@^15.1.0:
test-exclude "^6.0.0"
yargs "^15.0.2"
+nyc@^17.1.0:
+ version "17.1.0"
+ resolved "https://registry.yarnpkg.com/nyc/-/nyc-17.1.0.tgz#b6349a401a62ffeb912bd38ea9a018839fdb6eb1"
+ integrity sha512-U42vQ4czpKa0QdI1hu950XuNhYqgoM+ZF1HT+VuUHL9hPfDPVvNQyltmMqdE9bUHMVa+8yNbc3QKTj8zQhlVxQ==
+ dependencies:
+ "@istanbuljs/load-nyc-config" "^1.0.0"
+ "@istanbuljs/schema" "^0.1.2"
+ caching-transform "^4.0.0"
+ convert-source-map "^1.7.0"
+ decamelize "^1.2.0"
+ find-cache-dir "^3.2.0"
+ find-up "^4.1.0"
+ foreground-child "^3.3.0"
+ get-package-type "^0.1.0"
+ glob "^7.1.6"
+ istanbul-lib-coverage "^3.0.0"
+ istanbul-lib-hook "^3.0.0"
+ istanbul-lib-instrument "^6.0.2"
+ istanbul-lib-processinfo "^2.0.2"
+ istanbul-lib-report "^3.0.0"
+ istanbul-lib-source-maps "^4.0.0"
+ istanbul-reports "^3.0.2"
+ make-dir "^3.0.0"
+ node-preload "^0.2.1"
+ p-map "^3.0.0"
+ process-on-spawn "^1.0.0"
+ resolve-from "^5.0.0"
+ rimraf "^3.0.0"
+ signal-exit "^3.0.2"
+ spawn-wrap "^2.0.0"
+ test-exclude "^6.0.0"
+ yargs "^15.0.2"
+
object-inspect@^1.13.3:
version "1.13.4"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213"
@@ -4592,6 +4665,20 @@ pkg-types@^1.3.0:
mlly "^1.7.4"
pathe "^2.0.1"
+playwright-core@1.52.0:
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.52.0.tgz#238f1f0c3edd4ebba0434ce3f4401900319a3dca"
+ integrity sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==
+
+playwright@1.52.0:
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.52.0.tgz#26cb9a63346651e1c54c8805acfd85683173d4bd"
+ integrity sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==
+ dependencies:
+ playwright-core "1.52.0"
+ optionalDependencies:
+ fsevents "2.3.2"
+
postcss-selector-parser@^6.0.15:
version "6.1.2"
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz#27ecb41fb0e3b6ba7a1ec84fff347f734c7929de"
@@ -5089,11 +5176,18 @@ semver@^6.0.0, semver@^6.3.0, semver@^6.3.1:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
-semver@^7.3.2, semver@^7.3.5, semver@^7.3.6, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.3, semver@^7.7.1:
+semver@^7.3.2, semver@^7.3.5, semver@^7.6.0, semver@^7.6.3, semver@^7.7.1:
version "7.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f"
integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==
+semver@^7.3.6, semver@^7.5.3, semver@^7.5.4:
+ version "7.5.4"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
+ integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
+ dependencies:
+ lru-cache "^6.0.0"
+
send@0.19.0:
version "0.19.0"
resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8"
@@ -5716,9 +5810,9 @@ typescript@~5.5.3:
integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==
ufo@^1.5.4:
- version "1.6.1"
- resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.6.1.tgz#ac2db1d54614d1b22c1d603e3aef44a85d8f146b"
- integrity sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==
+ version "1.5.4"
+ resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.5.4.tgz#16d6949674ca0c9e0fbbae1fa20a71d7b1ded754"
+ integrity sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==
undici-types@~6.19.2:
version "6.19.8"
@@ -5854,7 +5948,21 @@ vite-tsconfig-paths@^5.1.4:
globrex "^0.1.2"
tsconfck "^3.0.3"
-"vite@^5.0.0 || ^6.0.0", vite@^6.1.0:
+"vite@^5.0.0 || ^6.0.0", vite@^6.2.6:
+ version "6.3.5"
+ resolved "https://registry.yarnpkg.com/vite/-/vite-6.3.5.tgz#fec73879013c9c0128c8d284504c6d19410d12a3"
+ integrity sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==
+ dependencies:
+ esbuild "^0.25.0"
+ fdir "^6.4.4"
+ picomatch "^4.0.2"
+ postcss "^8.5.3"
+ rollup "^4.34.9"
+ tinyglobby "^0.2.13"
+ optionalDependencies:
+ fsevents "~2.3.3"
+
+vite@^6.1.0:
version "6.3.3"
resolved "https://registry.yarnpkg.com/vite/-/vite-6.3.3.tgz#497392c3f2243194e4dbf09ea83e9a3dddf49b88"
integrity sha512-5nXH+QsELbFKhsEfWLkHrvgRpTdGJzqOZ+utSdmPTvwHmvU6ITTm3xx+mRusihkcI8GeC7lCDyn3kDtiki9scw==
@@ -6109,6 +6217,11 @@ yallist@^3.0.2:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
+yallist@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
+ integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
+
yaml-eslint-parser@^1.2.2:
version "1.3.0"
resolved "https://registry.yarnpkg.com/yaml-eslint-parser/-/yaml-eslint-parser-1.3.0.tgz#975dd11f8349e18c15c88b0e41a6d0b0377969cd"
diff --git a/test-webpack-app-v3/.eslintrc.js b/test-webpack-app-v3/.eslintrc.js
index 972424aa..5ddff0bf 100644
--- a/test-webpack-app-v3/.eslintrc.js
+++ b/test-webpack-app-v3/.eslintrc.js
@@ -118,5 +118,10 @@ module.exports = {
'plugin:jest/style',
],
},
+
+ {
+ files: ['src/components/**/*.spec.{js,ts}', 'test/**/*.spec.{js,ts}'],
+ extends: 'plugin:playwright/recommended',
+ },
],
};
diff --git a/test-webpack-app-v3/.gitignore b/test-webpack-app-v3/.gitignore
index 553e1345..5bb3a81f 100644
--- a/test-webpack-app-v3/.gitignore
+++ b/test-webpack-app-v3/.gitignore
@@ -31,3 +31,10 @@ yarn-error.log*
*.ntvs*
*.njsproj
*.sln
+
+
+# Playwright
+/test-results/
+/playwright-report/
+/blob-report
+/playwright/.cache/
diff --git a/test-webpack-app-v3/package.json b/test-webpack-app-v3/package.json
index 47fc5c76..2c94a435 100644
--- a/test-webpack-app-v3/package.json
+++ b/test-webpack-app-v3/package.json
@@ -20,20 +20,25 @@
"test:all": "yarn test:jest && yarn test:cypress",
"sync:invoke:test:jest": "yarn sync:invoke:jest && yarn test:jest",
"sync:invoke:test:cypress": "yarn sync:invoke:cypress && yarn test:cypress",
+ "sync:playwright": "yarn --cwd ../packages/e2e-playwright build:local && yarn add -D ../packages/e2e-playwright",
+ "invoke:playwright": "quasar ext invoke @quasar/testing-e2e-playwright && yarn format",
+ "sync:invoke:playwright": "yarn sync:playwright && yarn invoke:playwright",
"sync:invoke:test:all": "yarn sync:invoke:test:jest && yarn sync:invoke:test:cypress",
"lint": "eslint --ext .js,.ts,.vue ./",
"format": "prettier --write \"**/*.{js,ts,vue,scss,html,md,json}\" --ignore-path .gitignore",
- "test": "echo \"See package.json => scripts for available tests.\" && exit 0",
+ "test": "yarn test:clear && yarn test:component:ci && yarn test:e2e:ci",
"test:unit:ui": "majestic",
"test:unit": "jest",
"test:unit:ci": "jest --ci",
"test:unit:coverage": "jest --coverage",
"test:unit:watch": "jest --watch",
"test:unit:watchAll": "jest --watchAll",
- "test:e2e": "cross-env NODE_ENV=test start-test \"quasar dev\" http-get://127.0.0.1:8080 \"cypress open --e2e\"",
- "test:e2e:ci": "cross-env NODE_ENV=test start-test \"quasar dev\" http-get://127.0.0.1:8080 \"cypress run --e2e\"",
+ "test:e2e": "cross-env NODE_ENV=test playwright test --ui",
+ "test:e2e:ci": "cross-env NODE_ENV=test playwright test",
"test:component": "cross-env NODE_ENV=test cypress open --component",
- "test:component:ci": "cross-env NODE_ENV=test cypress run --component"
+ "test:component:ci": "cross-env NODE_ENV=test cypress run --component",
+ "test:clear": "rimraf .nyc_output coverage",
+ "test:report": "playwright show-report"
},
"dependencies": {
"@quasar/extras": "^1.16.6",
@@ -49,8 +54,10 @@
"cypress": "We're keeping this pinned to v12 on purpose to test a setup using the older Cypress version"
},
"devDependencies": {
+ "@playwright/test": "^1.49.1",
"@quasar/app-webpack": "^3.13.2",
"@quasar/quasar-app-extension-testing-e2e-cypress": "../packages/e2e-cypress",
+ "@quasar/quasar-app-extension-testing-e2e-playwright": "../packages/e2e-playwright",
"@quasar/quasar-app-extension-testing-unit-jest": "../packages/unit-jest",
"@types/node": "^18.17.15",
"@typescript-eslint/eslint-plugin": "^7.13.1",
@@ -61,6 +68,7 @@
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-cypress": "^3.6.0",
"eslint-plugin-jest": "^28.8.3",
+ "eslint-plugin-playwright": "^2.1.0",
"eslint-plugin-vue": "^9.17.0",
"jest": "^29.7.0",
"majestic": "^1.7.0",
diff --git a/test-webpack-app-v3/playwright.config.ts b/test-webpack-app-v3/playwright.config.ts
new file mode 100644
index 00000000..64a6a63c
--- /dev/null
+++ b/test-webpack-app-v3/playwright.config.ts
@@ -0,0 +1,79 @@
+import { defineConfig, devices } from '@playwright/test';
+
+/**
+ * Read environment variables from file.
+ * https://github.com/motdotla/dotenv
+ */
+// import dotenv from 'dotenv';
+// import path from 'path';
+// dotenv.config({ path: path.resolve(__dirname, '.env') });
+
+/**
+ * See https://playwright.dev/docs/test-configuration.
+ */
+export default defineConfig({
+ testDir: './test/playwright',
+ /* Run tests in files in parallel */
+ fullyParallel: true,
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
+ forbidOnly: !!process.env.CI,
+ /* Retry on CI only */
+ retries: process.env.CI ? 2 : 0,
+ /* Opt out of parallel tests on CI. */
+ workers: process.env.CI ? 1 : undefined,
+ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
+ reporter: 'html',
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
+ use: {
+ /* Base URL to use in actions like `await page.goto('/')`. */
+ baseURL: 'http://localhost:8080',
+
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
+ trace: 'on-first-retry',
+ },
+
+ /* Configure projects for major browsers */
+ projects: [
+ {
+ name: 'chromium',
+ use: { ...devices['Desktop Chrome'] },
+ },
+
+ {
+ name: 'firefox',
+ use: { ...devices['Desktop Firefox'] },
+ },
+
+ {
+ name: 'webkit',
+ use: { ...devices['Desktop Safari'] },
+ },
+
+ /* Test against mobile viewports. */
+ // {
+ // name: 'Mobile Chrome',
+ // use: { ...devices['Pixel 5'] },
+ // },
+ // {
+ // name: 'Mobile Safari',
+ // use: { ...devices['iPhone 12'] },
+ // },
+
+ /* Test against branded browsers. */
+ // {
+ // name: 'Microsoft Edge',
+ // use: { ...devices['Desktop Edge'], channel: 'msedge' },
+ // },
+ // {
+ // name: 'Google Chrome',
+ // use: { ...devices['Desktop Chrome'], channel: 'chrome' },
+ // },
+ ],
+
+ /* Run your local dev server before starting the tests */
+ webServer: {
+ command: 'quasar dev -p 8080',
+ url: 'http://localhost:8080',
+ reuseExistingServer: !process.env.CI,
+ },
+});
diff --git a/test-webpack-app-v3/quasar.extensions.json b/test-webpack-app-v3/quasar.extensions.json
index 51b40e2f..566bd9b2 100644
--- a/test-webpack-app-v3/quasar.extensions.json
+++ b/test-webpack-app-v3/quasar.extensions.json
@@ -5,5 +5,10 @@
"@quasar/testing-e2e-cypress": {
"port": 8080,
"options": []
+ },
+ "@quasar/testing-e2e-playwright": {
+ "port": 8080,
+ "githubWorkflow": true,
+ "installBrowsers": true
}
}
diff --git a/test-webpack-app-v3/test/playwright/home.spec.ts b/test-webpack-app-v3/test/playwright/home.spec.ts
new file mode 100644
index 00000000..18173075
--- /dev/null
+++ b/test-webpack-app-v3/test/playwright/home.spec.ts
@@ -0,0 +1,20 @@
+import {
+ test,
+ expect,
+} from '@quasar/quasar-app-extension-testing-e2e-playwright';
+
+test('has title', async ({ page }) => {
+ await page.goto('https://playwright.dev/');
+
+ await expect(page).toHaveTitle(/Playwright/);
+});
+
+test('get started link', async ({ page }) => {
+ await page.goto('https://playwright.dev/');
+
+ await page.getByRole('link', { name: 'Get started' }).click();
+
+ await expect(
+ page.getByRole('heading', { name: 'Installation' }),
+ ).toBeVisible();
+});
diff --git a/test-webpack-app-v3/yarn.lock b/test-webpack-app-v3/yarn.lock
index f7531d92..dc1d6b12 100644
--- a/test-webpack-app-v3/yarn.lock
+++ b/test-webpack-app-v3/yarn.lock
@@ -1639,6 +1639,13 @@
js-yaml "^3.13.1"
resolve-from "^5.0.0"
+"@istanbuljs/nyc-config-typescript@^1.0.2":
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/@istanbuljs/nyc-config-typescript/-/nyc-config-typescript-1.0.2.tgz#1f5235b28540a07219ae0dd42014912a0b19cf89"
+ integrity sha512-iKGIyMoyJuFnJRSVTZ78POIRvNnwZaWIf8vG4ZS3rQq58MMDrqEX2nnzx0R28V2X8JvmKYiqY9FP2hlJsm8A0w==
+ dependencies:
+ "@istanbuljs/schema" "^0.1.2"
+
"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3":
version "0.1.3"
resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98"
@@ -1912,6 +1919,13 @@
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
+"@playwright/test@^1.49.1":
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.52.0.tgz#267ec595b43a8f4fa5e444ea503689629e91a5b8"
+ integrity sha512-uh6W7sb55hl7D6vsAeA+V2p5JnlAqzhqFyF0VcJkKZXkgnFcVG9PziERRHQfPLfNGx1C292a4JqbWzhR8L4R1g==
+ dependencies:
+ playwright "1.52.0"
+
"@polka/url@^1.0.0-next.24":
version "1.0.0-next.25"
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.25.tgz#f077fdc0b5d0078d30893396ff4827a13f99e817"
@@ -2016,14 +2030,22 @@
integrity sha512-sbTBHOA+Hi7ah0P6qSm+xfRXqwJ94ct3NKA3Lkq3iNPYuHD7VXbSWtP2eA7Cu9Fd0WjVoPbngf6yFGg46U3IfQ==
"@quasar/quasar-app-extension-testing-e2e-cypress@../packages/e2e-cypress":
- version "6.2.0"
+ version "6.2.1"
dependencies:
"@cypress/code-coverage" "^3.12.26"
cross-env "^7.0.3"
lodash "^4.17.21"
nyc "^15.1.0"
start-server-and-test "^2.0.3"
- vite-plugin-istanbul "^5.0.0"
+ vite-plugin-istanbul "^7.0.0"
+
+"@quasar/quasar-app-extension-testing-e2e-playwright@../packages/e2e-playwright":
+ version "0.0.1"
+ dependencies:
+ "@istanbuljs/nyc-config-typescript" "^1.0.2"
+ cross-env "^7.0.3"
+ nyc "^17.1.0"
+ vite-plugin-istanbul "^7.0.0"
"@quasar/quasar-app-extension-testing-unit-jest@../packages/unit-jest":
version "3.0.3"
@@ -2877,6 +2899,11 @@ acorn@^8.0.4, acorn@^8.1.0, acorn@^8.11.0, acorn@^8.7.1, acorn@^8.8.1, acorn@^8.
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.0.tgz#1627bfa2e058148036133b8d9b51a700663c294c"
integrity sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==
+acorn@^8.14.0:
+ version "8.14.1"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb"
+ integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==
+
agent-base@6:
version "6.0.2"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
@@ -3984,6 +4011,15 @@ cross-spawn@7.0.3, cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, c
shebang-command "^2.0.0"
which "^2.0.1"
+cross-spawn@^7.0.6:
+ version "7.0.6"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
+ integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
+ dependencies:
+ path-key "^3.1.0"
+ shebang-command "^2.0.0"
+ which "^2.0.1"
+
css-declaration-sorter@^6.3.1:
version "6.4.1"
resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz#28beac7c20bad7f1775be3a7129d7eae409a3a71"
@@ -4683,6 +4719,13 @@ eslint-plugin-jest@^28.8.3:
dependencies:
"@typescript-eslint/utils" "^6.0.0 || ^7.0.0 || ^8.0.0"
+eslint-plugin-playwright@^2.1.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-playwright/-/eslint-plugin-playwright-2.2.0.tgz#d7eda21e670274fc0c006e11ba5cc2c8417b2a6e"
+ integrity sha512-qSQpAw7RcSzE3zPp8FMGkthaCWovHZ/BsXtpmnGax9vQLIovlh1bsZHEa2+j2lv9DWhnyeLM/qZmp7ffQZfQvg==
+ dependencies:
+ globals "^13.23.0"
+
eslint-plugin-vue@^9.17.0:
version "9.26.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-9.26.0.tgz#bf7f5cce62c8f878059b91edae44d22974133af5"
@@ -4718,6 +4761,11 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
+eslint-visitor-keys@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45"
+ integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==
+
eslint@^8.49.0:
version "8.57.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668"
@@ -4762,6 +4810,15 @@ eslint@^8.49.0:
strip-ansi "^6.0.1"
text-table "^0.2.0"
+espree@^10.3.0:
+ version "10.3.0"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-10.3.0.tgz#29267cf5b0cb98735b65e64ba07e0ed49d1eed8a"
+ integrity sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==
+ dependencies:
+ acorn "^8.14.0"
+ acorn-jsx "^5.3.2"
+ eslint-visitor-keys "^4.2.0"
+
espree@^9.3.1, espree@^9.6.0, espree@^9.6.1:
version "9.6.1"
resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f"
@@ -5181,6 +5238,14 @@ foreground-child@^3.1.0:
cross-spawn "^7.0.0"
signal-exit "^4.0.1"
+foreground-child@^3.3.0:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f"
+ integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==
+ dependencies:
+ cross-spawn "^7.0.6"
+ signal-exit "^4.0.1"
+
forever-agent@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
@@ -5282,6 +5347,11 @@ fs.realpath@^1.0.0:
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
+fsevents@2.3.2:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
+ integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
+
fsevents@^2.3.2, fsevents@~2.3.2:
version "2.3.3"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
@@ -5387,6 +5457,18 @@ glob@^10.3.3:
package-json-from-dist "^1.0.0"
path-scurry "^1.11.1"
+glob@^10.4.1:
+ version "10.4.5"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956"
+ integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==
+ dependencies:
+ foreground-child "^3.1.0"
+ jackspeak "^3.1.2"
+ minimatch "^9.0.4"
+ minipass "^7.1.2"
+ package-json-from-dist "^1.0.0"
+ path-scurry "^1.11.1"
+
glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.3:
version "7.2.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
@@ -5421,7 +5503,7 @@ globals@^11.1.0:
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
-globals@^13.19.0, globals@^13.20.0, globals@^13.24.0:
+globals@^13.19.0, globals@^13.20.0, globals@^13.23.0, globals@^13.24.0:
version "13.24.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171"
integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==
@@ -6017,7 +6099,7 @@ istanbul-lib-instrument@^4.0.0:
istanbul-lib-coverage "^3.0.0"
semver "^6.3.0"
-istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0:
+istanbul-lib-instrument@^5.0.4:
version "5.2.1"
resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d"
integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==
@@ -6039,6 +6121,17 @@ istanbul-lib-instrument@^6.0.0:
istanbul-lib-coverage "^3.2.0"
semver "^7.5.4"
+istanbul-lib-instrument@^6.0.2, istanbul-lib-instrument@^6.0.3:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz#fa15401df6c15874bcb2105f773325d78c666765"
+ integrity sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==
+ dependencies:
+ "@babel/core" "^7.23.9"
+ "@babel/parser" "^7.23.9"
+ "@istanbuljs/schema" "^0.1.3"
+ istanbul-lib-coverage "^3.2.0"
+ semver "^7.5.4"
+
istanbul-lib-processinfo@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz#366d454cd0dcb7eb6e0e419378e60072c8626169"
@@ -7355,6 +7448,39 @@ nyc@15.1.0, nyc@^15.1.0:
test-exclude "^6.0.0"
yargs "^15.0.2"
+nyc@^17.1.0:
+ version "17.1.0"
+ resolved "https://registry.yarnpkg.com/nyc/-/nyc-17.1.0.tgz#b6349a401a62ffeb912bd38ea9a018839fdb6eb1"
+ integrity sha512-U42vQ4czpKa0QdI1hu950XuNhYqgoM+ZF1HT+VuUHL9hPfDPVvNQyltmMqdE9bUHMVa+8yNbc3QKTj8zQhlVxQ==
+ dependencies:
+ "@istanbuljs/load-nyc-config" "^1.0.0"
+ "@istanbuljs/schema" "^0.1.2"
+ caching-transform "^4.0.0"
+ convert-source-map "^1.7.0"
+ decamelize "^1.2.0"
+ find-cache-dir "^3.2.0"
+ find-up "^4.1.0"
+ foreground-child "^3.3.0"
+ get-package-type "^0.1.0"
+ glob "^7.1.6"
+ istanbul-lib-coverage "^3.0.0"
+ istanbul-lib-hook "^3.0.0"
+ istanbul-lib-instrument "^6.0.2"
+ istanbul-lib-processinfo "^2.0.2"
+ istanbul-lib-report "^3.0.0"
+ istanbul-lib-source-maps "^4.0.0"
+ istanbul-reports "^3.0.2"
+ make-dir "^3.0.0"
+ node-preload "^0.2.1"
+ p-map "^3.0.0"
+ process-on-spawn "^1.0.0"
+ resolve-from "^5.0.0"
+ rimraf "^3.0.0"
+ signal-exit "^3.0.2"
+ spawn-wrap "^2.0.0"
+ test-exclude "^6.0.0"
+ yargs "^15.0.2"
+
object-inspect@^1.13.1:
version "1.13.1"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2"
@@ -7707,6 +7833,11 @@ picocolors@^1.0.0, picocolors@^1.0.1:
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1"
integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==
+picocolors@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"
+ integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
+
picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
@@ -7768,6 +7899,20 @@ pkg-up@^3.1.0:
dependencies:
find-up "^3.0.0"
+playwright-core@1.52.0:
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.52.0.tgz#238f1f0c3edd4ebba0434ce3f4401900319a3dca"
+ integrity sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==
+
+playwright@1.52.0:
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.52.0.tgz#26cb9a63346651e1c54c8805acfd85683173d4bd"
+ integrity sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==
+ dependencies:
+ playwright-core "1.52.0"
+ optionalDependencies:
+ fsevents "2.3.2"
+
postcss-calc@^8.2.3:
version "8.2.4"
resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.2.4.tgz#77b9c29bfcbe8a07ff6693dc87050828889739a5"
@@ -8778,6 +8923,11 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
+source-map@^0.7.4:
+ version "0.7.4"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656"
+ integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==
+
spawn-wrap@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-2.0.0.tgz#103685b8b8f9b79771318827aa78650a610d457e"
@@ -9136,6 +9286,15 @@ test-exclude@^6.0.0:
glob "^7.1.4"
minimatch "^3.0.4"
+test-exclude@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-7.0.1.tgz#20b3ba4906ac20994e275bbcafd68d510264c2a2"
+ integrity sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==
+ dependencies:
+ "@istanbuljs/schema" "^0.1.2"
+ glob "^10.4.1"
+ minimatch "^9.0.4"
+
text-table@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
@@ -9470,16 +9629,17 @@ verror@1.10.0:
core-util-is "1.0.2"
extsprintf "^1.2.0"
-vite-plugin-istanbul@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/vite-plugin-istanbul/-/vite-plugin-istanbul-5.0.0.tgz#7539d76d7c3cafb7b3b0f2371a4e3a69031dcd44"
- integrity sha512-Tg9zDmm/u4SdEDFbEWHBz7mmFe7jhLRmArA2XCmw5yydEFCARU9r4TxqFFnBFWCL63D9A7XA7VELulOO5T5o/g==
+vite-plugin-istanbul@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/vite-plugin-istanbul/-/vite-plugin-istanbul-7.0.0.tgz#97b80bd0199b316e5a9c4e757633c9273ca4f5f4"
+ integrity sha512-UAXSyS0zslaSP1yCdO54YwrTkoY3VxCBH8y8MAy3I+E6uqT07LEsVOFEHueeDJ+vyyeaA9Rkqz/j6LACJTzTKw==
dependencies:
"@istanbuljs/load-nyc-config" "^1.1.0"
- espree "^9.6.1"
- istanbul-lib-instrument "^5.1.0"
- picocolors "^1.0.0"
- test-exclude "^6.0.0"
+ espree "^10.3.0"
+ istanbul-lib-instrument "^6.0.3"
+ picocolors "^1.1.1"
+ source-map "^0.7.4"
+ test-exclude "^7.0.1"
vue-component-type-helpers@^2.0.0:
version "2.0.21"
diff --git a/test-webpack-app-v4/.gitignore b/test-webpack-app-v4/.gitignore
index f1d913c8..e7cbf6fc 100644
--- a/test-webpack-app-v4/.gitignore
+++ b/test-webpack-app-v4/.gitignore
@@ -31,3 +31,10 @@ yarn-error.log*
# local .env files
.env.local*
+
+
+# Playwright
+/test-results/
+/playwright-report/
+/blob-report
+/playwright/.cache/
diff --git a/test-webpack-app-v4/eslint.config.js b/test-webpack-app-v4/eslint.config.js
index 36d54b35..759a38ba 100644
--- a/test-webpack-app-v4/eslint.config.js
+++ b/test-webpack-app-v4/eslint.config.js
@@ -8,6 +8,7 @@ import {
} from '@vue/eslint-config-typescript';
import prettierSkipFormatting from '@vue/eslint-config-prettier/skip-formatting';
import pluginCypress from 'eslint-plugin-cypress/flat';
+import playwright from 'eslint-plugin-playwright';
const config = defineConfigWithVueTs(
{
@@ -89,6 +90,14 @@ const config = defineConfigWithVueTs(
prettierSkipFormatting,
+ {
+ name: 'custom/playwright',
+
+ ...playwright.configs['flat/recommended'],
+ files: ['src/components/**/*.spec.ts', 'test/**/*.spec.ts'],
+ rules: playwright.configs['flat/recommended'].rules,
+ },
+
{
name: 'custom/cypress',
@@ -118,7 +127,7 @@ config.push({
'@typescript-eslint/no-unsafe-call': 'error',
'@typescript-eslint/no-unsafe-member-access': 'error',
'@typescript-eslint/no-unsafe-return': 'error',
- }
+ },
});
export default config;
diff --git a/test-webpack-app-v4/package.json b/test-webpack-app-v4/package.json
index 7596ef76..7b11e9df 100644
--- a/test-webpack-app-v4/package.json
+++ b/test-webpack-app-v4/package.json
@@ -18,17 +18,20 @@
"sync:invoke:all": "yarn sync:invoke:jest && yarn sync:invoke:cypress",
"test:jest": "yarn test:unit:ci",
"test:cypress": "yarn test:e2e:ci && yarn test:component:ci",
+ "sync:playwright": "yarn --cwd ../packages/e2e-playwright build:local && yarn add -D ../packages/e2e-playwright",
+ "invoke:playwright": "quasar ext invoke @quasar/testing-e2e-playwright && yarn format",
+ "sync:invoke:playwright": "yarn sync:playwright && yarn invoke:playwright",
"test:all": "yarn test:jest && yarn test:cypress",
"sync:invoke:test:jest": "yarn sync:invoke:jest && yarn test:jest",
"sync:invoke:test:cypress": "yarn sync:invoke:cypress && yarn test:cypress",
"sync:invoke:test:all": "yarn sync:invoke:test:jest && yarn sync:invoke:test:cypress",
"lint": "eslint -c ./eslint.config.js \"./src*/**/*.{ts,js,cjs,mjs,vue}\" --fix",
"format": "prettier --write \"**/*.{js,ts,vue,scss,html,md,json}\" --ignore-path .gitignore",
- "test": "echo \"See package.json => scripts for available tests.\" && exit 0",
+ "test": "yarn test:clear && yarn test:component:ci && yarn test:e2e:ci",
"dev": "quasar dev",
"build": "quasar build",
- "test:e2e": "cross-env NODE_ENV=test TS_NODE_PROJECT=test/cypress/tsconfig.json start-test \"quasar dev\" http-get://127.0.0.1:8080 \"cypress open --e2e\"",
- "test:e2e:ci": "cross-env NODE_ENV=test TS_NODE_PROJECT=test/cypress/tsconfig.json start-test \"quasar dev\" http-get://127.0.0.1:8080 \"cypress run --e2e\"",
+ "test:e2e": "cross-env NODE_ENV=test playwright test --ui",
+ "test:e2e:ci": "cross-env NODE_ENV=test playwright test",
"test:component": "cross-env NODE_ENV=test TS_NODE_PROJECT=test/cypress/tsconfig.json cypress open --component",
"test:component:ci": "cross-env NODE_ENV=test TS_NODE_PROJECT=test/cypress/tsconfig.json cypress run --component",
"test:unit:ui": "majestic",
@@ -37,7 +40,9 @@
"test:unit:coverage": "jest --coverage",
"test:unit:watch": "jest --watch",
"test:unit:watchAll": "jest --watchAll",
- "postinstall": "quasar prepare"
+ "postinstall": "quasar prepare",
+ "test:clear": "rimraf .nyc_output coverage",
+ "test:report": "playwright show-report"
},
"dependencies": {
"@quasar/extras": "^1.16.6",
@@ -51,8 +56,10 @@
},
"devDependencies": {
"@eslint/js": "^9.14.0",
+ "@playwright/test": "^1.49.1",
"@quasar/app-webpack": "^4.1.0",
"@quasar/quasar-app-extension-testing-e2e-cypress": "../packages/e2e-cypress",
+ "@quasar/quasar-app-extension-testing-e2e-playwright": "../packages/e2e-playwright",
"@quasar/quasar-app-extension-testing-unit-jest": "../packages/unit-jest",
"@types/node": "^20.5.9",
"@vue/eslint-config-prettier": "^10.1.0",
@@ -63,6 +70,7 @@
"eslint": "^9.14.0",
"eslint-plugin-cypress": "^4.2.1",
"eslint-plugin-jest": "^28.8.3",
+ "eslint-plugin-playwright": "^2.1.0",
"eslint-plugin-vue": "^9.30.0",
"eslint-webpack-plugin": "^4.2.0",
"globals": "^15.12.0",
diff --git a/test-webpack-app-v4/playwright.config.ts b/test-webpack-app-v4/playwright.config.ts
new file mode 100644
index 00000000..b0025c82
--- /dev/null
+++ b/test-webpack-app-v4/playwright.config.ts
@@ -0,0 +1,80 @@
+import { defineConfig, devices } from '@playwright/test';
+import { PlaywrightTestConfig } from '@playwright/test';
+
+/**
+ * Read environment variables from file.
+ * https://github.com/motdotla/dotenv
+ */
+// import dotenv from 'dotenv';
+// import path from 'path';
+// dotenv.config({ path: path.resolve(__dirname, '.env') });
+
+/**
+ * See https://playwright.dev/docs/test-configuration.
+ */
+export default defineConfig({
+ testDir: './test/playwright',
+ /* Run tests in files in parallel */
+ fullyParallel: true,
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
+ forbidOnly: !!process.env.CI,
+ /* Retry on CI only */
+ retries: process.env.CI ? 2 : 0,
+ /* Opt out of parallel tests on CI. */
+ workers: process.env.CI ? 1 : undefined,
+ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
+ reporter: 'html',
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
+ use: {
+ /* Base URL to use in actions like `await page.goto('/')`. */
+ baseURL: 'http://localhost:8080',
+
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
+ trace: 'on-first-retry',
+ },
+
+ /* Configure projects for major browsers */
+ projects: [
+ {
+ name: 'chromium',
+ use: { ...devices['Desktop Chrome'] },
+ },
+
+ {
+ name: 'firefox',
+ use: { ...devices['Desktop Firefox'] },
+ },
+
+ {
+ name: 'webkit',
+ use: { ...devices['Desktop Safari'] },
+ },
+
+ /* Test against mobile viewports. */
+ // {
+ // name: 'Mobile Chrome',
+ // use: { ...devices['Pixel 5'] },
+ // },
+ // {
+ // name: 'Mobile Safari',
+ // use: { ...devices['iPhone 12'] },
+ // },
+
+ /* Test against branded browsers. */
+ // {
+ // name: 'Microsoft Edge',
+ // use: { ...devices['Desktop Edge'], channel: 'msedge' },
+ // },
+ // {
+ // name: 'Google Chrome',
+ // use: { ...devices['Desktop Chrome'], channel: 'chrome' },
+ // },
+ ],
+
+ /* Run your local dev server before starting the tests */
+ webServer: {
+ command: 'quasar dev -p 8080',
+ url: 'http://localhost:8080',
+ reuseExistingServer: !process.env.CI,
+ },
+} as PlaywrightTestConfig);
diff --git a/test-webpack-app-v4/quasar.extensions.json b/test-webpack-app-v4/quasar.extensions.json
index 0053fa6d..33040aba 100644
--- a/test-webpack-app-v4/quasar.extensions.json
+++ b/test-webpack-app-v4/quasar.extensions.json
@@ -5,5 +5,10 @@
},
"@quasar/testing-unit-jest": {
"options": ["majestic"]
+ },
+ "@quasar/testing-e2e-playwright": {
+ "port": 8080,
+ "githubWorkflow": true,
+ "installBrowsers": true
}
}
diff --git a/test-webpack-app-v4/src/components/QuasarCheckComponents.vue b/test-webpack-app-v4/src/components/QuasarCheckComponents.vue
index f49ea26b..2678290e 100644
--- a/test-webpack-app-v4/src/components/QuasarCheckComponents.vue
+++ b/test-webpack-app-v4/src/components/QuasarCheckComponents.vue
@@ -1,9 +1,21 @@
-
-
+
+
- Value1
- Value2
+ Value1
+ Value2
diff --git a/test-webpack-app-v4/src/components/QuasarDate.vue b/test-webpack-app-v4/src/components/QuasarDate.vue
index 962b4e0a..30d185fa 100644
--- a/test-webpack-app-v4/src/components/QuasarDate.vue
+++ b/test-webpack-app-v4/src/components/QuasarDate.vue
@@ -1,11 +1,12 @@
-
+
-
+
diff --git a/test-webpack-app-v4/src/components/QuasarDialog.vue b/test-webpack-app-v4/src/components/QuasarDialog.vue
index c88b9930..6451da46 100644
--- a/test-webpack-app-v4/src/components/QuasarDialog.vue
+++ b/test-webpack-app-v4/src/components/QuasarDialog.vue
@@ -8,6 +8,7 @@
- Am I on screen?
+ Am I on screen?
diff --git a/test-webpack-app-v4/src/components/QuasarMenu.vue b/test-webpack-app-v4/src/components/QuasarMenu.vue
index daed3aa4..4ff02d2e 100644
--- a/test-webpack-app-v4/src/components/QuasarMenu.vue
+++ b/test-webpack-app-v4/src/components/QuasarMenu.vue
@@ -1,5 +1,5 @@
-
+
diff --git a/test-webpack-app-v4/src/components/QuasarPageSticky.vue b/test-webpack-app-v4/src/components/QuasarPageSticky.vue
index 7c8223d3..9fce30f1 100644
--- a/test-webpack-app-v4/src/components/QuasarPageSticky.vue
+++ b/test-webpack-app-v4/src/components/QuasarPageSticky.vue
@@ -1,6 +1,12 @@
-
+
{{ title }}
diff --git a/test-webpack-app-v4/src/components/QuasarSelect.vue b/test-webpack-app-v4/src/components/QuasarSelect.vue
index 13d763f0..eefc5e5a 100644
--- a/test-webpack-app-v4/src/components/QuasarSelect.vue
+++ b/test-webpack-app-v4/src/components/QuasarSelect.vue
@@ -2,6 +2,7 @@
- {{ selected }}
+ {{ selected }}