diff --git a/exercises/01.sunsetting-jsdom/01.problem.break-jsdom/package.json b/exercises/01.sunsetting-jsdom/01.problem.break-jsdom/package.json index 3305645..afded6c 100644 --- a/exercises/01.sunsetting-jsdom/01.problem.break-jsdom/package.json +++ b/exercises/01.sunsetting-jsdom/01.problem.break-jsdom/package.json @@ -19,9 +19,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "jsdom": "^26.0.0", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } } diff --git a/exercises/01.sunsetting-jsdom/01.problem.break-jsdom/tsconfig.test.json b/exercises/01.sunsetting-jsdom/01.problem.break-jsdom/tsconfig.test.json index 3b4ebef..2c91d02 100644 --- a/exercises/01.sunsetting-jsdom/01.problem.break-jsdom/tsconfig.test.json +++ b/exercises/01.sunsetting-jsdom/01.problem.break-jsdom/tsconfig.test.json @@ -3,6 +3,6 @@ "include": ["src/**/*", "src/**/*.test.ts*"], "exclude": [], "compilerOptions": { - "types": ["vitest/globals"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/01.sunsetting-jsdom/01.problem.break-jsdom/vite.config.ts b/exercises/01.sunsetting-jsdom/01.problem.break-jsdom/vite.config.ts index fcac120..5733e8d 100644 --- a/exercises/01.sunsetting-jsdom/01.problem.break-jsdom/vite.config.ts +++ b/exercises/01.sunsetting-jsdom/01.problem.break-jsdom/vite.config.ts @@ -1,4 +1,4 @@ -/// +/// import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' diff --git a/exercises/01.sunsetting-jsdom/01.solution.break-jsdom/package.json b/exercises/01.sunsetting-jsdom/01.solution.break-jsdom/package.json index d961e7d..9089d4e 100644 --- a/exercises/01.sunsetting-jsdom/01.solution.break-jsdom/package.json +++ b/exercises/01.sunsetting-jsdom/01.solution.break-jsdom/package.json @@ -18,9 +18,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "jsdom": "^26.0.0", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } } diff --git a/exercises/01.sunsetting-jsdom/01.solution.break-jsdom/tsconfig.test.json b/exercises/01.sunsetting-jsdom/01.solution.break-jsdom/tsconfig.test.json index 3b4ebef..2c91d02 100644 --- a/exercises/01.sunsetting-jsdom/01.solution.break-jsdom/tsconfig.test.json +++ b/exercises/01.sunsetting-jsdom/01.solution.break-jsdom/tsconfig.test.json @@ -3,6 +3,6 @@ "include": ["src/**/*", "src/**/*.test.ts*"], "exclude": [], "compilerOptions": { - "types": ["vitest/globals"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/01.sunsetting-jsdom/01.solution.break-jsdom/vite.config.ts b/exercises/01.sunsetting-jsdom/01.solution.break-jsdom/vite.config.ts index fcac120..5733e8d 100644 --- a/exercises/01.sunsetting-jsdom/01.solution.break-jsdom/vite.config.ts +++ b/exercises/01.sunsetting-jsdom/01.solution.break-jsdom/vite.config.ts @@ -1,4 +1,4 @@ -/// +/// import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' diff --git a/exercises/02.vitest-browser-mode/01.problem.installation-and-setup/README.mdx b/exercises/02.vitest-browser-mode/01.problem.installation-and-setup/README.mdx index 4a8f855..0e5acdd 100644 --- a/exercises/02.vitest-browser-mode/01.problem.installation-and-setup/README.mdx +++ b/exercises/02.vitest-browser-mode/01.problem.installation-and-setup/README.mdx @@ -32,7 +32,7 @@ The installation step is done, and now it's time to configure Vitest is it can r To enable the Browser Mode in Vitest, I need to set `test.browser.enabled` to `true` in my `vite.config.ts`/`vitest.config.ts`: ```ts filename=vite.config.ts remove=10 add=11-13 -/// +/// import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -52,7 +52,7 @@ export default defineConfig({ As the next step, I need to tell Vitest what browsers I want for testing my components. Let's use Chromium by setting the `test.browser.instances` correctly: ```ts filename=vite.config.ts add=11-15 -/// +/// import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -76,7 +76,7 @@ export default defineConfig({ ## Configure TypeScript -The last thing that remains is to extend the TypeScript configuration to recognize DOM-specific matches, like `expect().toBeVisible()` as they come built-in in Vitest. +The last thing that remains is to make sure TypeScript sees the Vitest globals and browser context types. First, I will remove the `import '@testing-library/jest-dom/vitest'` import we previously had in the test: @@ -84,7 +84,7 @@ First, I will remove the `import '@testing-library/jest-dom/vitest'` import we p import '@testing-library/jest-dom/vitest' ``` -And replace it with a type reference to Vitest's browser matchers in `tsconfig.test.json`: +Finally, confirm that `tsconfig.test.json` includes `vitest/globals` and `@vitest/browser/context` in `compilerOptions.types`: ```json filename=tsconfig.test.json add=9 { @@ -92,11 +92,7 @@ And replace it with a type reference to Vitest's browser matchers in `tsconfig.t "include": ["src/**/*", "src/**/*.test.ts*"], "exclude": [], "compilerOptions": { - "types": [ - "vitest/globals", - // 👇 - "@vitest/browser/matchers" - ] + "types": ["vitest/globals", "@vitest/browser/context"] } } ``` diff --git a/exercises/02.vitest-browser-mode/01.problem.installation-and-setup/package.json b/exercises/02.vitest-browser-mode/01.problem.installation-and-setup/package.json index eb169bc..306a112 100644 --- a/exercises/02.vitest-browser-mode/01.problem.installation-and-setup/package.json +++ b/exercises/02.vitest-browser-mode/01.problem.installation-and-setup/package.json @@ -17,10 +17,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.0.5", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "jsdom": "^26.0.0", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.0.7" + "vitest": "^4.0.17" } } diff --git a/exercises/02.vitest-browser-mode/01.problem.installation-and-setup/tsconfig.test.json b/exercises/02.vitest-browser-mode/01.problem.installation-and-setup/tsconfig.test.json index 3b4ebef..2c91d02 100644 --- a/exercises/02.vitest-browser-mode/01.problem.installation-and-setup/tsconfig.test.json +++ b/exercises/02.vitest-browser-mode/01.problem.installation-and-setup/tsconfig.test.json @@ -3,6 +3,6 @@ "include": ["src/**/*", "src/**/*.test.ts*"], "exclude": [], "compilerOptions": { - "types": ["vitest/globals"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/02.vitest-browser-mode/01.problem.installation-and-setup/vite.config.ts b/exercises/02.vitest-browser-mode/01.problem.installation-and-setup/vite.config.ts index fcac120..5733e8d 100644 --- a/exercises/02.vitest-browser-mode/01.problem.installation-and-setup/vite.config.ts +++ b/exercises/02.vitest-browser-mode/01.problem.installation-and-setup/vite.config.ts @@ -1,4 +1,4 @@ -/// +/// import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' diff --git a/exercises/02.vitest-browser-mode/01.solution.installation-and-setup/package.json b/exercises/02.vitest-browser-mode/01.solution.installation-and-setup/package.json index ef37c3e..373a2b6 100644 --- a/exercises/02.vitest-browser-mode/01.solution.installation-and-setup/package.json +++ b/exercises/02.vitest-browser-mode/01.solution.installation-and-setup/package.json @@ -15,10 +15,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0", + "vitest": "^4.0.17", "vitest-browser-react": "^0.2.0" } } diff --git a/exercises/02.vitest-browser-mode/01.solution.installation-and-setup/tsconfig.test.json b/exercises/02.vitest-browser-mode/01.solution.installation-and-setup/tsconfig.test.json index bfa76d1..2c91d02 100644 --- a/exercises/02.vitest-browser-mode/01.solution.installation-and-setup/tsconfig.test.json +++ b/exercises/02.vitest-browser-mode/01.solution.installation-and-setup/tsconfig.test.json @@ -3,6 +3,6 @@ "include": ["src/**/*", "src/**/*.test.ts*"], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/matchers"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/02.vitest-browser-mode/01.solution.installation-and-setup/vite.config.ts b/exercises/02.vitest-browser-mode/01.solution.installation-and-setup/vite.config.ts index ab21f6e..5ac85bc 100644 --- a/exercises/02.vitest-browser-mode/01.solution.installation-and-setup/vite.config.ts +++ b/exercises/02.vitest-browser-mode/01.solution.installation-and-setup/vite.config.ts @@ -1,4 +1,4 @@ -/// +/// import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' diff --git a/exercises/02.vitest-browser-mode/02.problem.migrate-the-test/package.json b/exercises/02.vitest-browser-mode/02.problem.migrate-the-test/package.json index 6db3deb..7cee9d7 100644 --- a/exercises/02.vitest-browser-mode/02.problem.migrate-the-test/package.json +++ b/exercises/02.vitest-browser-mode/02.problem.migrate-the-test/package.json @@ -15,10 +15,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0", + "vitest": "^4.0.17", "vitest-browser-react": "^0.2.0" } } diff --git a/exercises/02.vitest-browser-mode/02.problem.migrate-the-test/tsconfig.test.json b/exercises/02.vitest-browser-mode/02.problem.migrate-the-test/tsconfig.test.json index bfa76d1..2c91d02 100644 --- a/exercises/02.vitest-browser-mode/02.problem.migrate-the-test/tsconfig.test.json +++ b/exercises/02.vitest-browser-mode/02.problem.migrate-the-test/tsconfig.test.json @@ -3,6 +3,6 @@ "include": ["src/**/*", "src/**/*.test.ts*"], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/matchers"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/02.vitest-browser-mode/02.problem.migrate-the-test/vite.config.ts b/exercises/02.vitest-browser-mode/02.problem.migrate-the-test/vite.config.ts index ab21f6e..5ac85bc 100644 --- a/exercises/02.vitest-browser-mode/02.problem.migrate-the-test/vite.config.ts +++ b/exercises/02.vitest-browser-mode/02.problem.migrate-the-test/vite.config.ts @@ -1,4 +1,4 @@ -/// +/// import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' diff --git a/exercises/02.vitest-browser-mode/02.solution.migrate-the-test/package.json b/exercises/02.vitest-browser-mode/02.solution.migrate-the-test/package.json index a2b24b4..a2683bb 100644 --- a/exercises/02.vitest-browser-mode/02.solution.migrate-the-test/package.json +++ b/exercises/02.vitest-browser-mode/02.solution.migrate-the-test/package.json @@ -15,9 +15,10 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } } diff --git a/exercises/02.vitest-browser-mode/02.solution.migrate-the-test/tsconfig.test.json b/exercises/02.vitest-browser-mode/02.solution.migrate-the-test/tsconfig.test.json index bfa76d1..2c91d02 100644 --- a/exercises/02.vitest-browser-mode/02.solution.migrate-the-test/tsconfig.test.json +++ b/exercises/02.vitest-browser-mode/02.solution.migrate-the-test/tsconfig.test.json @@ -3,6 +3,6 @@ "include": ["src/**/*", "src/**/*.test.ts*"], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/matchers"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/02.vitest-browser-mode/02.solution.migrate-the-test/vite.config.ts b/exercises/02.vitest-browser-mode/02.solution.migrate-the-test/vite.config.ts index ab21f6e..5ac85bc 100644 --- a/exercises/02.vitest-browser-mode/02.solution.migrate-the-test/vite.config.ts +++ b/exercises/02.vitest-browser-mode/02.solution.migrate-the-test/vite.config.ts @@ -1,4 +1,4 @@ -/// +/// import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' diff --git a/exercises/02.vitest-browser-mode/03.problem.playwright/README.mdx b/exercises/02.vitest-browser-mode/03.problem.playwright/README.mdx index 23f0ca1..c1680ad 100644 --- a/exercises/02.vitest-browser-mode/03.problem.playwright/README.mdx +++ b/exercises/02.vitest-browser-mode/03.problem.playwright/README.mdx @@ -21,8 +21,8 @@ In this workshop, we will be using Playwright as the browser provider for Vitest 👨‍💼 Your task is to introduce Playwright to the existing Vitest setup. It will consist of multiple steps: -1. Install `playwright` as a dependency in the project; -1. In `vite.config.ts`, update `test.browser.provider` to use `'playwright'` as the browser provider; -1. In `tsconfig.test.json`, update the `compilerOptions.types` to include the Playwright type definitions for `expect()` matchers. +1. Install `playwright` and `@vitest/browser-playwright` as dependencies in the project; +1. In `vite.config.ts`, import `playwright` from `@vitest/browser-playwright` and set `test.browser.provider` to `playwright()`; +1. In `tsconfig.test.json`, update the `compilerOptions.types` to include the Vitest browser context types. Once you are done with it, make sure that the tests are still passing by running `npm test`. Good luck! diff --git a/exercises/02.vitest-browser-mode/03.problem.playwright/package.json b/exercises/02.vitest-browser-mode/03.problem.playwright/package.json index 6264b83..9e1eb2b 100644 --- a/exercises/02.vitest-browser-mode/03.problem.playwright/package.json +++ b/exercises/02.vitest-browser-mode/03.problem.playwright/package.json @@ -15,9 +15,10 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } } diff --git a/exercises/02.vitest-browser-mode/03.problem.playwright/tsconfig.test.json b/exercises/02.vitest-browser-mode/03.problem.playwright/tsconfig.test.json index 4ee7dd6..2302389 100644 --- a/exercises/02.vitest-browser-mode/03.problem.playwright/tsconfig.test.json +++ b/exercises/02.vitest-browser-mode/03.problem.playwright/tsconfig.test.json @@ -5,11 +5,7 @@ "compilerOptions": { "types": [ "vitest/globals", - // 💣 Remove the default browser matcher types. - "@vitest/browser/matchers" - - // 🐨 Instead, include the matcher types from Playwright. - // 💰 "@vitest/browser/providers/playwright" + "@vitest/browser/context" ] } } diff --git a/exercises/02.vitest-browser-mode/03.problem.playwright/vite.config.ts b/exercises/02.vitest-browser-mode/03.problem.playwright/vite.config.ts index 6bec327..48c341e 100644 --- a/exercises/02.vitest-browser-mode/03.problem.playwright/vite.config.ts +++ b/exercises/02.vitest-browser-mode/03.problem.playwright/vite.config.ts @@ -1,5 +1,6 @@ -/// +/// import { defineConfig } from 'vite' +import { playwright } from '@vitest/browser-playwright' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -13,7 +14,7 @@ export default defineConfig({ browser: { enabled: true, // 🐨 Set a custom browser provider via the `provider` option. - // 💰 provider: 'playwright', + // 💰 provider: playwright(), instances: [ { browser: 'chromium', diff --git a/exercises/02.vitest-browser-mode/03.solution.playwright/README.mdx b/exercises/02.vitest-browser-mode/03.solution.playwright/README.mdx index d219c35..191e1bd 100644 --- a/exercises/02.vitest-browser-mode/03.solution.playwright/README.mdx +++ b/exercises/02.vitest-browser-mode/03.solution.playwright/README.mdx @@ -2,10 +2,10 @@ -Let's start by installing `playwright`: +Let's start by installing `playwright` and the Vitest Playwright provider: ```sh nonumber -npm i -D playwright +npm i -D playwright @vitest/browser-playwright ``` Playwright needs browser executables to be present on your machine to run. In this workshop, I am using Chromium as my browser of choice, so I can install just that particular browser by running the following command: @@ -16,11 +16,12 @@ npx playwright install --with-deps chromium > 🦉 You can provide the Playwright CLI with a specific browser you want to be installed. This reduces its footprint in the system by fetching only the browsers you need. -The next step is to tell Vitest to use Playwright as the browser provider for component tests. In `vite.config.ts`, set the `test.browser.provider` option to `'playwright'`: +The next step is to tell Vitest to use Playwright as the browser provider for component tests. In `vite.config.ts`, import `playwright` from `@vitest/browser-playwright` and set `test.browser.provider` to `playwright()`: ```ts filename=vite.config.ts add=12 -/// +/// import { defineConfig } from 'vite' +import { playwright } from '@vitest/browser-playwright' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -30,7 +31,7 @@ export default defineConfig({ globals: true, browser: { enabled: true, - provider: 'playwright', + provider: playwright(), instances: [ { browser: 'chromium', @@ -41,7 +42,7 @@ export default defineConfig({ }) ``` -And, finally, let's update the type definitions for the assertion matchers to be those from Playwright in `tsconfig.test.json`: +And, finally, let's add the Vitest browser context types in `tsconfig.test.json`: ```json filename=tsconfig.test.json remove=9 add=10 { @@ -52,8 +53,7 @@ And, finally, let's update the type definitions for the assertion matchers to be "module": "preserve", "types": [ "vitest/globals", - "@vitest/browser/matchers", - "@vitest/browser/providers/playwright" + "@vitest/browser/context" ] } } diff --git a/exercises/02.vitest-browser-mode/03.solution.playwright/package.json b/exercises/02.vitest-browser-mode/03.solution.playwright/package.json index 7a0447a..62fc577 100644 --- a/exercises/02.vitest-browser-mode/03.solution.playwright/package.json +++ b/exercises/02.vitest-browser-mode/03.solution.playwright/package.json @@ -15,10 +15,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } } diff --git a/exercises/02.vitest-browser-mode/03.solution.playwright/tsconfig.test.json b/exercises/02.vitest-browser-mode/03.solution.playwright/tsconfig.test.json index 873b5aa..2c91d02 100644 --- a/exercises/02.vitest-browser-mode/03.solution.playwright/tsconfig.test.json +++ b/exercises/02.vitest-browser-mode/03.solution.playwright/tsconfig.test.json @@ -3,6 +3,6 @@ "include": ["src/**/*", "src/**/*.test.ts*"], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/providers/playwright"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/02.vitest-browser-mode/03.solution.playwright/vite.config.ts b/exercises/02.vitest-browser-mode/03.solution.playwright/vite.config.ts index 3f7f954..0710082 100644 --- a/exercises/02.vitest-browser-mode/03.solution.playwright/vite.config.ts +++ b/exercises/02.vitest-browser-mode/03.solution.playwright/vite.config.ts @@ -1,5 +1,6 @@ -/// +/// import { defineConfig } from 'vite' +import { playwright } from '@vitest/browser-playwright' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -12,7 +13,7 @@ export default defineConfig({ globals: true, browser: { enabled: true, - provider: 'playwright', + provider: playwright(), instances: [ { browser: 'chromium', diff --git a/exercises/02.vitest-browser-mode/04.problem.shared-assets/package.json b/exercises/02.vitest-browser-mode/04.problem.shared-assets/package.json index 6ecb443..6d05e8d 100644 --- a/exercises/02.vitest-browser-mode/04.problem.shared-assets/package.json +++ b/exercises/02.vitest-browser-mode/04.problem.shared-assets/package.json @@ -15,10 +15,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } } diff --git a/exercises/02.vitest-browser-mode/04.problem.shared-assets/tsconfig.test.json b/exercises/02.vitest-browser-mode/04.problem.shared-assets/tsconfig.test.json index 873b5aa..2c91d02 100644 --- a/exercises/02.vitest-browser-mode/04.problem.shared-assets/tsconfig.test.json +++ b/exercises/02.vitest-browser-mode/04.problem.shared-assets/tsconfig.test.json @@ -3,6 +3,6 @@ "include": ["src/**/*", "src/**/*.test.ts*"], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/providers/playwright"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/02.vitest-browser-mode/04.problem.shared-assets/vite.config.ts b/exercises/02.vitest-browser-mode/04.problem.shared-assets/vite.config.ts index 352b47e..bcc06d4 100644 --- a/exercises/02.vitest-browser-mode/04.problem.shared-assets/vite.config.ts +++ b/exercises/02.vitest-browser-mode/04.problem.shared-assets/vite.config.ts @@ -1,5 +1,6 @@ -/// +/// import { defineConfig } from 'vite' +import { playwright } from '@vitest/browser-playwright' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -12,7 +13,7 @@ export default defineConfig({ globals: true, browser: { enabled: true, - provider: 'playwright', + provider: playwright(), instances: [ { browser: 'chromium', diff --git a/exercises/02.vitest-browser-mode/04.solution.shared-assets/README.mdx b/exercises/02.vitest-browser-mode/04.solution.shared-assets/README.mdx index 55fd842..96f85b2 100644 --- a/exercises/02.vitest-browser-mode/04.solution.shared-assets/README.mdx +++ b/exercises/02.vitest-browser-mode/04.solution.shared-assets/README.mdx @@ -32,7 +32,7 @@ Since we added this new file, we have to tell TypeScript how it should be handle ], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/providers/playwright"] + "types": ["vitest/globals", "@vitest/browser/context"] } } ``` @@ -42,8 +42,9 @@ Now all that remains is to tell Vitest to use this file as the global setup for In `vite.config.ts`, I will provide the path to this setup file as the value for the `setupFiles` property on the current browser instance: ```ts filename=vite.config.ts add=16 -/// +/// import { defineConfig } from 'vite' +import { playwright } from '@vitest/browser-playwright' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -53,7 +54,7 @@ export default defineConfig({ globals: true, browser: { enabled: true, - provider: 'playwright', + provider: playwright(), instances: [ { browser: 'chromium', diff --git a/exercises/02.vitest-browser-mode/04.solution.shared-assets/package.json b/exercises/02.vitest-browser-mode/04.solution.shared-assets/package.json index 419412e..84b4e2d 100644 --- a/exercises/02.vitest-browser-mode/04.solution.shared-assets/package.json +++ b/exercises/02.vitest-browser-mode/04.solution.shared-assets/package.json @@ -15,10 +15,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } } diff --git a/exercises/02.vitest-browser-mode/04.solution.shared-assets/tsconfig.test.json b/exercises/02.vitest-browser-mode/04.solution.shared-assets/tsconfig.test.json index fd369e8..768bacb 100644 --- a/exercises/02.vitest-browser-mode/04.solution.shared-assets/tsconfig.test.json +++ b/exercises/02.vitest-browser-mode/04.solution.shared-assets/tsconfig.test.json @@ -3,6 +3,6 @@ "include": ["vitest.browser.setup.ts", "src/**/*", "src/**/*.test.ts*"], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/providers/playwright"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/02.vitest-browser-mode/04.solution.shared-assets/vite.config.ts b/exercises/02.vitest-browser-mode/04.solution.shared-assets/vite.config.ts index fb9a9bd..98e5675 100644 --- a/exercises/02.vitest-browser-mode/04.solution.shared-assets/vite.config.ts +++ b/exercises/02.vitest-browser-mode/04.solution.shared-assets/vite.config.ts @@ -1,5 +1,6 @@ -/// +/// import { defineConfig } from 'vite' +import { playwright } from '@vitest/browser-playwright' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -12,7 +13,7 @@ export default defineConfig({ globals: true, browser: { enabled: true, - provider: 'playwright', + provider: playwright(), instances: [ { browser: 'chromium', diff --git a/exercises/02.vitest-browser-mode/05.problem.multiple-workspaces/README.mdx b/exercises/02.vitest-browser-mode/05.problem.multiple-workspaces/README.mdx index e0f107e..c6a1155 100644 --- a/exercises/02.vitest-browser-mode/05.problem.multiple-workspaces/README.mdx +++ b/exercises/02.vitest-browser-mode/05.problem.multiple-workspaces/README.mdx @@ -1,14 +1,14 @@ -# Multiple workspaces +# Multiple projects Our current Vitest configuration runs _all tests_ in Browser Mode. This isn't ideal when you need to run different types of tests in the same project - like unit and integration tests running in a Node.js environment alongside browser-based component tests. -You can fix this by introducing _different workspaces_ for different types of tests. In fact, I think this is just the right task for you... +You can fix this by introducing _different projects_ for different types of tests. In fact, I think this is just the right task for you... 👨‍💼 In this one, you will expand the Vitest configuration to support running multiple types of tests in the same project. This will be a multi-step process to make sure you have Vitest and TypeScript configured correctly for your tests. -🐨 First, update `vite.config.ts` to list multiple [workspaces](https://main.vitest.dev/guide/workspace.html#configuration). Define one for unit tests and another for component tests. +🐨 First, update `vite.config.ts` to list multiple [projects](https://vitest.dev/guide/projects.html). Define one for unit tests and another for component tests. 🐨 Next, rename `tsconfig.test.json` to `tsconfig.test.browser.json`. This TypeScript configuration will only apply to the component tests now. Update its `include` setting to target `**/*.browser.test.ts*` files: @@ -49,6 +49,6 @@ You can fix this by introducing _different workspaces_ for different types of te } ``` -🐨 Finally, rename the existing `file-preview.test.tsx` component test to `file-preview.browser.test.tsx` to be included in the correct Vitest workspace. +🐨 Finally, rename the existing `file-preview.test.tsx` component test to `file-preview.browser.test.tsx` to be included in the correct Vitest project. See you on the other side once you're done to go through each step in more detail. diff --git a/exercises/02.vitest-browser-mode/05.problem.multiple-workspaces/package.json b/exercises/02.vitest-browser-mode/05.problem.multiple-workspaces/package.json index 25c4532..da2ae4e 100644 --- a/exercises/02.vitest-browser-mode/05.problem.multiple-workspaces/package.json +++ b/exercises/02.vitest-browser-mode/05.problem.multiple-workspaces/package.json @@ -15,10 +15,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } } diff --git a/exercises/02.vitest-browser-mode/05.problem.multiple-workspaces/tsconfig.test.json b/exercises/02.vitest-browser-mode/05.problem.multiple-workspaces/tsconfig.test.json index fd369e8..768bacb 100644 --- a/exercises/02.vitest-browser-mode/05.problem.multiple-workspaces/tsconfig.test.json +++ b/exercises/02.vitest-browser-mode/05.problem.multiple-workspaces/tsconfig.test.json @@ -3,6 +3,6 @@ "include": ["vitest.browser.setup.ts", "src/**/*", "src/**/*.test.ts*"], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/providers/playwright"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/02.vitest-browser-mode/05.problem.multiple-workspaces/vite.config.ts b/exercises/02.vitest-browser-mode/05.problem.multiple-workspaces/vite.config.ts index 0562619..1e05368 100644 --- a/exercises/02.vitest-browser-mode/05.problem.multiple-workspaces/vite.config.ts +++ b/exercises/02.vitest-browser-mode/05.problem.multiple-workspaces/vite.config.ts @@ -1,5 +1,6 @@ -/// +/// import { defineConfig } from 'vite' +import { playwright } from '@vitest/browser-playwright' // 🐨 Import `configDefaults` from `vitest/config` // 💰 import { foo } from 'bar' import react from '@vitejs/plugin-react' @@ -10,15 +11,15 @@ export default defineConfig({ server: { port: process.env.PORT ? Number(process.env.PORT) : undefined, }, - // 🐨 Add a new property called `workspace`. + // 🐨 Add a new property called `projects`. // As the value, provide an array with two entries. - // 💰 test: { workspace: [{}, {}] } + // 💰 test: { projects: [{}, {}] } // - // 🐨 In the first entry of the `workspace` array, + // 🐨 In the first entry of the `projects` array, // define a `test` property and give it a `test.name` equal to "unit". // 💰 { test: { name: 'unit' } } // - // 🐨 In the unit test workspace, set `globals` to true + // 🐨 In the unit test project, set `globals` to true // and `environment` to "node". // 💰 globals: true // 💰 environment: 'node' @@ -29,17 +30,17 @@ export default defineConfig({ // 🐨 Since "**/*.test.ts" will match ALL tests, exclude // the browser tests by providing the `exclude` property // and including the browser test pattern there. - // 🦉 Vitest workspaces override the default configuration, + // 🦉 Vitest projects override the default configuration, // which means that the `exclude` array must include the // default values to ignore tests from `node_modules`, for example. // 💰 exclude: [...defaultConfig.exclude, '**/*.browser.test.ts(x)?'] // - // Now, switch to the second entry in the `workspace` array. + // Now, switch to the second entry in the `projects` array. // 🐨 First, set the `extends` property to `true`. Let's extend the // root-level options, like `plugins` to have consistent behavior in prod and tests. // 💰 { extends: true, test: {} } // - // 🐨 Next, add these properties to the `test` in this workspace: + // 🐨 Next, add these properties to the `test` in this project: // { // name: "browser", // globals: true, @@ -47,7 +48,7 @@ export default defineConfig({ // } // // 🐨 Finally, copy the existing `browser` configuration - // under the `test` property of the second workspace. + // under the `test` property of the second project. // 💰 { test: { name: 'browser', browser: {...} }} // // 💣 Delete this root-level `test` property altogether. @@ -55,7 +56,7 @@ export default defineConfig({ globals: true, browser: { enabled: true, - provider: 'playwright', + provider: playwright(), instances: [ { browser: 'chromium', diff --git a/exercises/02.vitest-browser-mode/05.solution.multiple-workspaces/README.mdx b/exercises/02.vitest-browser-mode/05.solution.multiple-workspaces/README.mdx index d206ca7..06b7b83 100644 --- a/exercises/02.vitest-browser-mode/05.solution.multiple-workspaces/README.mdx +++ b/exercises/02.vitest-browser-mode/05.solution.multiple-workspaces/README.mdx @@ -1,22 +1,23 @@ -# Multiple workspaces +# Multiple projects Real-world projects often combine multiple types of tests at the same time. Vitest is a great choice for both unit and integration tests, but those two have quite different requirements and, as a result, may need different setups. -Vitest solves this by using _workspaces_. +Vitest solves this by using _projects_. -## Vitest Workspaces +## Vitest Projects -A [workspace](https://main.vitest.dev/guide/workspace.html) allows you to describe multiple configurations independently. Think of it as a package workspace, where a single repo can host multiple different packages. In the same way, a single Vitest process can run multiple different test projects. +A [project](https://vitest.dev/guide/projects.html) allows you to describe multiple configurations independently. Think of it as a package workspace, where a single repo can host multiple different packages. In the same way, a single Vitest process can run multiple different test projects. -Workspaces are listed in the `test.workspace` property in your Vitest config, and can include paths to nested packages or Vitest config files or inline configuration. +Projects are listed in the `test.projects` property in your Vitest config, and can include paths to nested packages or Vitest config files or inline configuration. -I will define two workspaces: +I will define two projects: ```ts filename=vite.config.ts add=12-18,21-36 -/// +/// import { defineConfig } from 'vite' +import { playwright } from '@vitest/browser-playwright' import { configDefaults } from 'vitest/config' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -24,7 +25,7 @@ import tailwindcss from '@tailwindcss/vite' export default defineConfig({ plugins: [react(), tailwindcss()], test: { - workspace: [ + projects: [ { test: { name: 'unit', @@ -42,7 +43,7 @@ export default defineConfig({ include: ['**/*.browser.test.ts(x)?'], browser: { enabled: true, - provider: 'playwright', + provider: playwright(), instances: [ { browser: 'chromium', @@ -59,7 +60,7 @@ export default defineConfig({ Let's go over them in more detail. -The first workspace include the configuration for running unit tests: +The first project includes the configuration for running unit tests: ```ts filename=vite.config.ts nonumber { @@ -73,14 +74,14 @@ The first workspace include the configuration for running unit tests: }, ``` -- `name` gives this workspace a name and allows me to run it in isolation anytime I want by providing the `--project=unit` option to the Vitest CLI; +- `name` gives this project a name and allows me to run it in isolation anytime I want by providing the `--project=unit` option to the Vitest CLI; - `include` lists the test file patterns to include in this run. In this case, I want for the unit tests to cover test files ending with `*.test.ts`; - `exclude` does the opposite of `include`, listing the file patterns to _ignore_. Since my browser tests also end with `*.test.ts`, I need to exclude them not to be confused with unit tests; -- `environment` controls the test environment used for this workspace. I want my unit tests to run in Node.js, so I provide `'node'` as the enivornment here. +- `environment` controls the test environment used for this project. I want my unit tests to run in Node.js, so I provide `'node'` as the enivornment here. -> :owl: Notice that each workspace lists Vitest configuration starting from the root by including the `test` key again. This is handy because each workspace can have a different set of Vite options and `plugins` for different test files. +> :owl: Notice that each project lists Vitest configuration starting from the root by including the `test` key again. This is handy because each project can have a different set of Vite options and `plugins` for different test files. -Similarly, here's the workspace for the browser (component) tests: +Similarly, here's the project for the browser (component) tests: ```ts filename=vite.config.ts nonumber { @@ -91,7 +92,7 @@ Similarly, here's the workspace for the browser (component) tests: include: ['**/*.browser.test.ts(x)?'], browser: { enabled: true, - provider: 'playwright', + provider: playwright(), instances: [ { browser: 'chromium', @@ -103,7 +104,7 @@ Similarly, here's the workspace for the browser (component) tests: }, ``` -Here, I'm naming this workspace `'browser'` and configuring it to include only `*.browser.test.ts(x)` test files. These will be my component tests. For the rest of the configuration, I simply moved the existing `test.browser` configuration under this workspace and left it as-is. +Here, I'm naming this project `'browser'` and configuring it to include only `*.browser.test.ts(x)` test files. These will be my component tests. For the rest of the configuration, I simply moved the existing `test.browser` configuration under this project and left it as-is. ## TypeScript @@ -126,7 +127,7 @@ Let's start with the unit tests: } ``` -Similar to how I've configured Vitest workspaces to apply only to specific file patterns, I tell TypeScript to apply this configuration only to the `*.test.ts` files, excluding the browser tests at `*.browser.test.ts*`. The most important bit here is the `compilerOptions.types` property: +Similar to how I've configured Vitest projects to apply only to specific file patterns, I tell TypeScript to apply this configuration only to the `*.test.ts` files, excluding the browser tests at `*.browser.test.ts*`. The most important bit here is the `compilerOptions.types` property: ```json filename=tsconfig.test.unit.json nonumber "types": ["node", "vitest/globals"] @@ -150,7 +151,7 @@ Next, I rename the existing `tsconfig.test.json` to `tsconfig.test.browser.json` ], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/providers/playwright"] + "types": ["vitest/globals", "@vitest/browser/context"] } } ``` diff --git a/exercises/02.vitest-browser-mode/05.solution.multiple-workspaces/package.json b/exercises/02.vitest-browser-mode/05.solution.multiple-workspaces/package.json index d029c25..7c434e8 100644 --- a/exercises/02.vitest-browser-mode/05.solution.multiple-workspaces/package.json +++ b/exercises/02.vitest-browser-mode/05.solution.multiple-workspaces/package.json @@ -18,10 +18,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } } diff --git a/exercises/02.vitest-browser-mode/05.solution.multiple-workspaces/tsconfig.test.browser.json b/exercises/02.vitest-browser-mode/05.solution.multiple-workspaces/tsconfig.test.browser.json index b8dbf34..326e69f 100644 --- a/exercises/02.vitest-browser-mode/05.solution.multiple-workspaces/tsconfig.test.browser.json +++ b/exercises/02.vitest-browser-mode/05.solution.multiple-workspaces/tsconfig.test.browser.json @@ -7,6 +7,6 @@ ], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/providers/playwright"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/02.vitest-browser-mode/05.solution.multiple-workspaces/vite.config.ts b/exercises/02.vitest-browser-mode/05.solution.multiple-workspaces/vite.config.ts index e3035c8..2f2bf03 100644 --- a/exercises/02.vitest-browser-mode/05.solution.multiple-workspaces/vite.config.ts +++ b/exercises/02.vitest-browser-mode/05.solution.multiple-workspaces/vite.config.ts @@ -1,5 +1,6 @@ -/// +/// import { defineConfig } from 'vite' +import { playwright } from '@vitest/browser-playwright' import { configDefaults } from 'vitest/config' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -10,7 +11,7 @@ export default defineConfig({ port: process.env.PORT ? Number(process.env.PORT) : undefined, }, test: { - workspace: [ + projects: [ { test: { name: 'unit', @@ -28,7 +29,7 @@ export default defineConfig({ include: ['./src/**/*.browser.test.ts(x)?'], browser: { enabled: true, - provider: 'playwright', + provider: playwright(), instances: [ { browser: 'chromium', diff --git a/exercises/02.vitest-browser-mode/README.mdx b/exercises/02.vitest-browser-mode/README.mdx index 0971471..64d10e9 100644 --- a/exercises/02.vitest-browser-mode/README.mdx +++ b/exercises/02.vitest-browser-mode/README.mdx @@ -36,6 +36,6 @@ There are also a few advantages I find in Vitest Browser Mode when compared to o - **Consistency**. Vitest can use your existing Vite configuration both for your app and for your tests. This means a smaller difference between your production and tested code, which is always a win. - **Component rendering model**. Running in the browser, your components can render similarly to how they are rendered in production. Vitest has a more [straightforward rendering flow](https://github.com/vitest-dev/vitest-browser-react/blob/1d6be8ca8d94bb2289b6260886f76a6e527c45f7/src/pure.tsx#L50) compared to [Playwright Component Testing](https://github.com/microsoft/playwright/blob/91f46bb5d057a284ff33def5802aba496033c030/packages/playwright-ct-core/src/mount.ts#L61), where Playwright has to channel the rendering from the test (Node.js) to the browser. -- **Flexibility**. You can use Vitest for both unit tests, Node.js integration tests, and in-browser integration tests. In fact, Vitest makes that easy to do with the concept of workspaces, which you will get your hands on later in this workshop. +- **Flexibility**. You can use Vitest for both unit tests, Node.js integration tests, and in-browser integration tests. In fact, Vitest makes that easy to do with the concept of projects, which you will get your hands on later in this workshop. Alright, we've set the scene well. Now it's time you put Vitest Browser Mode to work in your tests. Let's go! diff --git a/exercises/03.best-practices/01.problem.queries/package.json b/exercises/03.best-practices/01.problem.queries/package.json index 729f665..9e30c71 100644 --- a/exercises/03.best-practices/01.problem.queries/package.json +++ b/exercises/03.best-practices/01.problem.queries/package.json @@ -15,10 +15,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } } diff --git a/exercises/03.best-practices/01.problem.queries/tsconfig.test.browser.json b/exercises/03.best-practices/01.problem.queries/tsconfig.test.browser.json index b8dbf34..326e69f 100644 --- a/exercises/03.best-practices/01.problem.queries/tsconfig.test.browser.json +++ b/exercises/03.best-practices/01.problem.queries/tsconfig.test.browser.json @@ -7,6 +7,6 @@ ], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/providers/playwright"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/03.best-practices/01.problem.queries/vite.config.ts b/exercises/03.best-practices/01.problem.queries/vite.config.ts index b7554c7..a7cdbc4 100644 --- a/exercises/03.best-practices/01.problem.queries/vite.config.ts +++ b/exercises/03.best-practices/01.problem.queries/vite.config.ts @@ -1,5 +1,6 @@ -/// +/// import { defineConfig } from 'vite' +import { playwright } from '@vitest/browser-playwright' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -14,7 +15,7 @@ export default defineConfig({ browser: { enabled: true, headless: true, - provider: 'playwright', + provider: playwright(), instances: [ { browser: 'chromium', diff --git a/exercises/03.best-practices/01.solution.queries/package.json b/exercises/03.best-practices/01.solution.queries/package.json index 59df7ba..d4fa1ff 100644 --- a/exercises/03.best-practices/01.solution.queries/package.json +++ b/exercises/03.best-practices/01.solution.queries/package.json @@ -15,10 +15,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } } diff --git a/exercises/03.best-practices/01.solution.queries/tsconfig.test.browser.json b/exercises/03.best-practices/01.solution.queries/tsconfig.test.browser.json index b8dbf34..326e69f 100644 --- a/exercises/03.best-practices/01.solution.queries/tsconfig.test.browser.json +++ b/exercises/03.best-practices/01.solution.queries/tsconfig.test.browser.json @@ -7,6 +7,6 @@ ], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/providers/playwright"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/03.best-practices/01.solution.queries/vite.config.ts b/exercises/03.best-practices/01.solution.queries/vite.config.ts index b7554c7..a7cdbc4 100644 --- a/exercises/03.best-practices/01.solution.queries/vite.config.ts +++ b/exercises/03.best-practices/01.solution.queries/vite.config.ts @@ -1,5 +1,6 @@ -/// +/// import { defineConfig } from 'vite' +import { playwright } from '@vitest/browser-playwright' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -14,7 +15,7 @@ export default defineConfig({ browser: { enabled: true, headless: true, - provider: 'playwright', + provider: playwright(), instances: [ { browser: 'chromium', diff --git a/exercises/03.best-practices/02.problem.user-events/package.json b/exercises/03.best-practices/02.problem.user-events/package.json index f315432..3c1314f 100644 --- a/exercises/03.best-practices/02.problem.user-events/package.json +++ b/exercises/03.best-practices/02.problem.user-events/package.json @@ -15,10 +15,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } } diff --git a/exercises/03.best-practices/02.problem.user-events/tsconfig.test.browser.json b/exercises/03.best-practices/02.problem.user-events/tsconfig.test.browser.json index b8dbf34..326e69f 100644 --- a/exercises/03.best-practices/02.problem.user-events/tsconfig.test.browser.json +++ b/exercises/03.best-practices/02.problem.user-events/tsconfig.test.browser.json @@ -7,6 +7,6 @@ ], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/providers/playwright"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/03.best-practices/02.problem.user-events/vite.config.ts b/exercises/03.best-practices/02.problem.user-events/vite.config.ts index b7554c7..a7cdbc4 100644 --- a/exercises/03.best-practices/02.problem.user-events/vite.config.ts +++ b/exercises/03.best-practices/02.problem.user-events/vite.config.ts @@ -1,5 +1,6 @@ -/// +/// import { defineConfig } from 'vite' +import { playwright } from '@vitest/browser-playwright' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -14,7 +15,7 @@ export default defineConfig({ browser: { enabled: true, headless: true, - provider: 'playwright', + provider: playwright(), instances: [ { browser: 'chromium', diff --git a/exercises/03.best-practices/02.solution.user-events/package.json b/exercises/03.best-practices/02.solution.user-events/package.json index d0c19c6..b08c094 100644 --- a/exercises/03.best-practices/02.solution.user-events/package.json +++ b/exercises/03.best-practices/02.solution.user-events/package.json @@ -15,10 +15,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } } diff --git a/exercises/03.best-practices/02.solution.user-events/tsconfig.test.browser.json b/exercises/03.best-practices/02.solution.user-events/tsconfig.test.browser.json index b8dbf34..326e69f 100644 --- a/exercises/03.best-practices/02.solution.user-events/tsconfig.test.browser.json +++ b/exercises/03.best-practices/02.solution.user-events/tsconfig.test.browser.json @@ -7,6 +7,6 @@ ], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/providers/playwright"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/03.best-practices/02.solution.user-events/vite.config.ts b/exercises/03.best-practices/02.solution.user-events/vite.config.ts index b7554c7..a7cdbc4 100644 --- a/exercises/03.best-practices/02.solution.user-events/vite.config.ts +++ b/exercises/03.best-practices/02.solution.user-events/vite.config.ts @@ -1,5 +1,6 @@ -/// +/// import { defineConfig } from 'vite' +import { playwright } from '@vitest/browser-playwright' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -14,7 +15,7 @@ export default defineConfig({ browser: { enabled: true, headless: true, - provider: 'playwright', + provider: playwright(), instances: [ { browser: 'chromium', diff --git a/exercises/03.best-practices/03.problem.network-mocking/README.mdx b/exercises/03.best-practices/03.problem.network-mocking/README.mdx index 5f30b3b..f64144c 100644 --- a/exercises/03.best-practices/03.problem.network-mocking/README.mdx +++ b/exercises/03.best-practices/03.problem.network-mocking/README.mdx @@ -80,7 +80,7 @@ Since it's a new TypeScript module, you need to tell TypeScript how to handle it ], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/providers/playwright"] + "types": ["vitest/globals", "@vitest/browser/context"] } } ``` diff --git a/exercises/03.best-practices/03.problem.network-mocking/package.json b/exercises/03.best-practices/03.problem.network-mocking/package.json index f1851db..a0ac6aa 100644 --- a/exercises/03.best-practices/03.problem.network-mocking/package.json +++ b/exercises/03.best-practices/03.problem.network-mocking/package.json @@ -15,10 +15,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } } diff --git a/exercises/03.best-practices/03.problem.network-mocking/tsconfig.test.browser.json b/exercises/03.best-practices/03.problem.network-mocking/tsconfig.test.browser.json index b8dbf34..326e69f 100644 --- a/exercises/03.best-practices/03.problem.network-mocking/tsconfig.test.browser.json +++ b/exercises/03.best-practices/03.problem.network-mocking/tsconfig.test.browser.json @@ -7,6 +7,6 @@ ], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/providers/playwright"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/03.best-practices/03.problem.network-mocking/vite.config.ts b/exercises/03.best-practices/03.problem.network-mocking/vite.config.ts index b7554c7..a7cdbc4 100644 --- a/exercises/03.best-practices/03.problem.network-mocking/vite.config.ts +++ b/exercises/03.best-practices/03.problem.network-mocking/vite.config.ts @@ -1,5 +1,6 @@ -/// +/// import { defineConfig } from 'vite' +import { playwright } from '@vitest/browser-playwright' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -14,7 +15,7 @@ export default defineConfig({ browser: { enabled: true, headless: true, - provider: 'playwright', + provider: playwright(), instances: [ { browser: 'chromium', diff --git a/exercises/03.best-practices/03.solution.network-mocking/package.json b/exercises/03.best-practices/03.solution.network-mocking/package.json index dd9d29c..2aca2ac 100644 --- a/exercises/03.best-practices/03.solution.network-mocking/package.json +++ b/exercises/03.best-practices/03.solution.network-mocking/package.json @@ -15,12 +15,13 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "msw": "^2.7.3", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" }, "msw": { "workerDirectory": [ diff --git a/exercises/03.best-practices/03.solution.network-mocking/src/main.tsx b/exercises/03.best-practices/03.solution.network-mocking/src/main.tsx index b5273ba..1653870 100644 --- a/exercises/03.best-practices/03.solution.network-mocking/src/main.tsx +++ b/exercises/03.best-practices/03.solution.network-mocking/src/main.tsx @@ -4,7 +4,7 @@ import './index.css' import { App } from './app.jsx' async function enableMocking() { - if (process.env.NODE_ENV === 'development') { + if (import.meta.env.DEV) { const { worker } = await import('./mocks/browser.js') await worker.start({ diff --git a/exercises/03.best-practices/03.solution.network-mocking/tsconfig.test.browser.json b/exercises/03.best-practices/03.solution.network-mocking/tsconfig.test.browser.json index c59f172..74c3de8 100644 --- a/exercises/03.best-practices/03.solution.network-mocking/tsconfig.test.browser.json +++ b/exercises/03.best-practices/03.solution.network-mocking/tsconfig.test.browser.json @@ -8,6 +8,6 @@ ], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/providers/playwright"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/03.best-practices/03.solution.network-mocking/vite.config.ts b/exercises/03.best-practices/03.solution.network-mocking/vite.config.ts index b7554c7..a7cdbc4 100644 --- a/exercises/03.best-practices/03.solution.network-mocking/vite.config.ts +++ b/exercises/03.best-practices/03.solution.network-mocking/vite.config.ts @@ -1,5 +1,6 @@ -/// +/// import { defineConfig } from 'vite' +import { playwright } from '@vitest/browser-playwright' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -14,7 +15,7 @@ export default defineConfig({ browser: { enabled: true, headless: true, - provider: 'playwright', + provider: playwright(), instances: [ { browser: 'chromium', diff --git a/exercises/03.best-practices/04.problem.element-presence/package.json b/exercises/03.best-practices/04.problem.element-presence/package.json index 4f89df4..60f4c69 100644 --- a/exercises/03.best-practices/04.problem.element-presence/package.json +++ b/exercises/03.best-practices/04.problem.element-presence/package.json @@ -15,12 +15,13 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "msw": "^2.7.3", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" }, "msw": { "workerDirectory": [ diff --git a/exercises/03.best-practices/04.problem.element-presence/src/main.tsx b/exercises/03.best-practices/04.problem.element-presence/src/main.tsx index 7876383..7b5466c 100644 --- a/exercises/03.best-practices/04.problem.element-presence/src/main.tsx +++ b/exercises/03.best-practices/04.problem.element-presence/src/main.tsx @@ -4,7 +4,7 @@ import './index.css' import { App } from './app.jsx' async function enableMocking() { - if (process.env.NODE_ENV === 'development') { + if (import.meta.env.DEV) { const { worker } = await import('./mocks/browser.js') await worker.start() } diff --git a/exercises/03.best-practices/04.problem.element-presence/tsconfig.test.browser.json b/exercises/03.best-practices/04.problem.element-presence/tsconfig.test.browser.json index c59f172..74c3de8 100644 --- a/exercises/03.best-practices/04.problem.element-presence/tsconfig.test.browser.json +++ b/exercises/03.best-practices/04.problem.element-presence/tsconfig.test.browser.json @@ -8,6 +8,6 @@ ], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/providers/playwright"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/03.best-practices/04.problem.element-presence/vite.config.ts b/exercises/03.best-practices/04.problem.element-presence/vite.config.ts index b7554c7..a7cdbc4 100644 --- a/exercises/03.best-practices/04.problem.element-presence/vite.config.ts +++ b/exercises/03.best-practices/04.problem.element-presence/vite.config.ts @@ -1,5 +1,6 @@ -/// +/// import { defineConfig } from 'vite' +import { playwright } from '@vitest/browser-playwright' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -14,7 +15,7 @@ export default defineConfig({ browser: { enabled: true, headless: true, - provider: 'playwright', + provider: playwright(), instances: [ { browser: 'chromium', diff --git a/exercises/03.best-practices/04.solution.element-presence/package.json b/exercises/03.best-practices/04.solution.element-presence/package.json index 1bccd9d..889b182 100644 --- a/exercises/03.best-practices/04.solution.element-presence/package.json +++ b/exercises/03.best-practices/04.solution.element-presence/package.json @@ -15,12 +15,13 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "msw": "^2.7.3", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" }, "msw": { "workerDirectory": [ diff --git a/exercises/03.best-practices/04.solution.element-presence/src/main.tsx b/exercises/03.best-practices/04.solution.element-presence/src/main.tsx index 7876383..7b5466c 100644 --- a/exercises/03.best-practices/04.solution.element-presence/src/main.tsx +++ b/exercises/03.best-practices/04.solution.element-presence/src/main.tsx @@ -4,7 +4,7 @@ import './index.css' import { App } from './app.jsx' async function enableMocking() { - if (process.env.NODE_ENV === 'development') { + if (import.meta.env.DEV) { const { worker } = await import('./mocks/browser.js') await worker.start() } diff --git a/exercises/03.best-practices/04.solution.element-presence/tsconfig.test.browser.json b/exercises/03.best-practices/04.solution.element-presence/tsconfig.test.browser.json index c59f172..74c3de8 100644 --- a/exercises/03.best-practices/04.solution.element-presence/tsconfig.test.browser.json +++ b/exercises/03.best-practices/04.solution.element-presence/tsconfig.test.browser.json @@ -8,6 +8,6 @@ ], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/providers/playwright"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/03.best-practices/04.solution.element-presence/vite.config.ts b/exercises/03.best-practices/04.solution.element-presence/vite.config.ts index b7554c7..a7cdbc4 100644 --- a/exercises/03.best-practices/04.solution.element-presence/vite.config.ts +++ b/exercises/03.best-practices/04.solution.element-presence/vite.config.ts @@ -1,5 +1,6 @@ -/// +/// import { defineConfig } from 'vite' +import { playwright } from '@vitest/browser-playwright' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -14,7 +15,7 @@ export default defineConfig({ browser: { enabled: true, headless: true, - provider: 'playwright', + provider: playwright(), instances: [ { browser: 'chromium', diff --git a/exercises/03.best-practices/05.problem.page-navigation/package.json b/exercises/03.best-practices/05.problem.page-navigation/package.json index 2565511..29e533b 100644 --- a/exercises/03.best-practices/05.problem.page-navigation/package.json +++ b/exercises/03.best-practices/05.problem.page-navigation/package.json @@ -16,12 +16,13 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "msw": "^2.7.3", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" }, "msw": { "workerDirectory": [ diff --git a/exercises/03.best-practices/05.problem.page-navigation/src/main.tsx b/exercises/03.best-practices/05.problem.page-navigation/src/main.tsx index 7876383..7b5466c 100644 --- a/exercises/03.best-practices/05.problem.page-navigation/src/main.tsx +++ b/exercises/03.best-practices/05.problem.page-navigation/src/main.tsx @@ -4,7 +4,7 @@ import './index.css' import { App } from './app.jsx' async function enableMocking() { - if (process.env.NODE_ENV === 'development') { + if (import.meta.env.DEV) { const { worker } = await import('./mocks/browser.js') await worker.start() } diff --git a/exercises/03.best-practices/05.problem.page-navigation/tsconfig.test.browser.json b/exercises/03.best-practices/05.problem.page-navigation/tsconfig.test.browser.json index c59f172..74c3de8 100644 --- a/exercises/03.best-practices/05.problem.page-navigation/tsconfig.test.browser.json +++ b/exercises/03.best-practices/05.problem.page-navigation/tsconfig.test.browser.json @@ -8,6 +8,6 @@ ], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/providers/playwright"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/03.best-practices/05.problem.page-navigation/vite.config.ts b/exercises/03.best-practices/05.problem.page-navigation/vite.config.ts index b7554c7..a7cdbc4 100644 --- a/exercises/03.best-practices/05.problem.page-navigation/vite.config.ts +++ b/exercises/03.best-practices/05.problem.page-navigation/vite.config.ts @@ -1,5 +1,6 @@ -/// +/// import { defineConfig } from 'vite' +import { playwright } from '@vitest/browser-playwright' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -14,7 +15,7 @@ export default defineConfig({ browser: { enabled: true, headless: true, - provider: 'playwright', + provider: playwright(), instances: [ { browser: 'chromium', diff --git a/exercises/03.best-practices/05.solution.page-navigation/package.json b/exercises/03.best-practices/05.solution.page-navigation/package.json index b2e3e0a..ca3b214 100644 --- a/exercises/03.best-practices/05.solution.page-navigation/package.json +++ b/exercises/03.best-practices/05.solution.page-navigation/package.json @@ -16,12 +16,13 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "msw": "^2.7.3", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" }, "msw": { "workerDirectory": [ diff --git a/exercises/03.best-practices/05.solution.page-navigation/src/main.tsx b/exercises/03.best-practices/05.solution.page-navigation/src/main.tsx index 7876383..7b5466c 100644 --- a/exercises/03.best-practices/05.solution.page-navigation/src/main.tsx +++ b/exercises/03.best-practices/05.solution.page-navigation/src/main.tsx @@ -4,7 +4,7 @@ import './index.css' import { App } from './app.jsx' async function enableMocking() { - if (process.env.NODE_ENV === 'development') { + if (import.meta.env.DEV) { const { worker } = await import('./mocks/browser.js') await worker.start() } diff --git a/exercises/03.best-practices/05.solution.page-navigation/tsconfig.test.browser.json b/exercises/03.best-practices/05.solution.page-navigation/tsconfig.test.browser.json index ace611a..7043593 100644 --- a/exercises/03.best-practices/05.solution.page-navigation/tsconfig.test.browser.json +++ b/exercises/03.best-practices/05.solution.page-navigation/tsconfig.test.browser.json @@ -8,6 +8,6 @@ "compilerOptions": { "target": "esnext", "module": "preserve", - "types": ["vitest/globals", "@vitest/browser/providers/playwright"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/03.best-practices/05.solution.page-navigation/vite.config.ts b/exercises/03.best-practices/05.solution.page-navigation/vite.config.ts index b7554c7..a7cdbc4 100644 --- a/exercises/03.best-practices/05.solution.page-navigation/vite.config.ts +++ b/exercises/03.best-practices/05.solution.page-navigation/vite.config.ts @@ -1,5 +1,6 @@ -/// +/// import { defineConfig } from 'vite' +import { playwright } from '@vitest/browser-playwright' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -14,7 +15,7 @@ export default defineConfig({ browser: { enabled: true, headless: true, - provider: 'playwright', + provider: playwright(), instances: [ { browser: 'chromium', diff --git a/exercises/04.debugging/01.problem.dom-snapshots/package.json b/exercises/04.debugging/01.problem.dom-snapshots/package.json index 6dbd007..03b082f 100644 --- a/exercises/04.debugging/01.problem.dom-snapshots/package.json +++ b/exercises/04.debugging/01.problem.dom-snapshots/package.json @@ -15,10 +15,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } } diff --git a/exercises/04.debugging/01.problem.dom-snapshots/tsconfig.test.browser.json b/exercises/04.debugging/01.problem.dom-snapshots/tsconfig.test.browser.json index c59f172..74c3de8 100644 --- a/exercises/04.debugging/01.problem.dom-snapshots/tsconfig.test.browser.json +++ b/exercises/04.debugging/01.problem.dom-snapshots/tsconfig.test.browser.json @@ -8,6 +8,6 @@ ], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/providers/playwright"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/04.debugging/01.problem.dom-snapshots/vite.config.ts b/exercises/04.debugging/01.problem.dom-snapshots/vite.config.ts index b7554c7..a7cdbc4 100644 --- a/exercises/04.debugging/01.problem.dom-snapshots/vite.config.ts +++ b/exercises/04.debugging/01.problem.dom-snapshots/vite.config.ts @@ -1,5 +1,6 @@ -/// +/// import { defineConfig } from 'vite' +import { playwright } from '@vitest/browser-playwright' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -14,7 +15,7 @@ export default defineConfig({ browser: { enabled: true, headless: true, - provider: 'playwright', + provider: playwright(), instances: [ { browser: 'chromium', diff --git a/exercises/04.debugging/01.solution.dom-snapshots/package.json b/exercises/04.debugging/01.solution.dom-snapshots/package.json index 4cecb69..1ac3d9e 100644 --- a/exercises/04.debugging/01.solution.dom-snapshots/package.json +++ b/exercises/04.debugging/01.solution.dom-snapshots/package.json @@ -15,10 +15,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } } diff --git a/exercises/04.debugging/01.solution.dom-snapshots/tsconfig.test.browser.json b/exercises/04.debugging/01.solution.dom-snapshots/tsconfig.test.browser.json index c59f172..74c3de8 100644 --- a/exercises/04.debugging/01.solution.dom-snapshots/tsconfig.test.browser.json +++ b/exercises/04.debugging/01.solution.dom-snapshots/tsconfig.test.browser.json @@ -8,6 +8,6 @@ ], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/providers/playwright"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/04.debugging/01.solution.dom-snapshots/vite.config.ts b/exercises/04.debugging/01.solution.dom-snapshots/vite.config.ts index b7554c7..a7cdbc4 100644 --- a/exercises/04.debugging/01.solution.dom-snapshots/vite.config.ts +++ b/exercises/04.debugging/01.solution.dom-snapshots/vite.config.ts @@ -1,5 +1,6 @@ -/// +/// import { defineConfig } from 'vite' +import { playwright } from '@vitest/browser-playwright' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -14,7 +15,7 @@ export default defineConfig({ browser: { enabled: true, headless: true, - provider: 'playwright', + provider: playwright(), instances: [ { browser: 'chromium', diff --git a/exercises/04.debugging/02.problem.debugger/README.mdx b/exercises/04.debugging/02.problem.debugger/README.mdx index 68a7538..3d7baf1 100644 --- a/exercises/04.debugging/02.problem.debugger/README.mdx +++ b/exercises/04.debugging/02.problem.debugger/README.mdx @@ -65,7 +65,7 @@ This configuration tells Visual Studio Code how to launch your application (in o - `Run Vitest Browser`, which will run our tests with a few special arguments: - `--inspect-brk`, which tells Node.js to spawn a debugger process. If provided, Vitest will arrange appropriate debugging mode in your browser provider automatically; - - `--browser`, which tells Vitest to run only the browser tests/workspaces; + - `--browser`, which tells Vitest to run only the browser tests/projects; - `--no-file-parallelism`, which forces Vitest to run our test cases in sequence (required for the debugger to work properly). - `Attach to Vitest Browser`, which will attach a Chome DevTools instance exposed by the browser tests to the built-in debugger in Visual Studio Code. This will allow you to control the debugging experience directly from your IDE. diff --git a/exercises/04.debugging/02.problem.debugger/package.json b/exercises/04.debugging/02.problem.debugger/package.json index b80ffdc..5eb2ae0 100644 --- a/exercises/04.debugging/02.problem.debugger/package.json +++ b/exercises/04.debugging/02.problem.debugger/package.json @@ -15,10 +15,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } } diff --git a/exercises/04.debugging/02.problem.debugger/tsconfig.test.browser.json b/exercises/04.debugging/02.problem.debugger/tsconfig.test.browser.json index c59f172..74c3de8 100644 --- a/exercises/04.debugging/02.problem.debugger/tsconfig.test.browser.json +++ b/exercises/04.debugging/02.problem.debugger/tsconfig.test.browser.json @@ -8,6 +8,6 @@ ], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/providers/playwright"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/04.debugging/02.problem.debugger/vite.config.ts b/exercises/04.debugging/02.problem.debugger/vite.config.ts index 85e9082..ca010f2 100644 --- a/exercises/04.debugging/02.problem.debugger/vite.config.ts +++ b/exercises/04.debugging/02.problem.debugger/vite.config.ts @@ -1,5 +1,6 @@ -/// +/// import { defineConfig } from 'vite' +import { playwright } from '@vitest/browser-playwright' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -14,7 +15,7 @@ export default defineConfig({ browser: { enabled: true, headless: !process.env.DEBUG, - provider: 'playwright', + provider: playwright(), instances: [ { browser: 'chromium', diff --git a/exercises/04.debugging/02.solution.debugger/package.json b/exercises/04.debugging/02.solution.debugger/package.json index a7bfa96..3eb9034 100644 --- a/exercises/04.debugging/02.solution.debugger/package.json +++ b/exercises/04.debugging/02.solution.debugger/package.json @@ -15,10 +15,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } } diff --git a/exercises/04.debugging/02.solution.debugger/tsconfig.test.browser.json b/exercises/04.debugging/02.solution.debugger/tsconfig.test.browser.json index c59f172..74c3de8 100644 --- a/exercises/04.debugging/02.solution.debugger/tsconfig.test.browser.json +++ b/exercises/04.debugging/02.solution.debugger/tsconfig.test.browser.json @@ -8,6 +8,6 @@ ], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/providers/playwright"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/04.debugging/02.solution.debugger/vite.config.ts b/exercises/04.debugging/02.solution.debugger/vite.config.ts index 85e9082..ca010f2 100644 --- a/exercises/04.debugging/02.solution.debugger/vite.config.ts +++ b/exercises/04.debugging/02.solution.debugger/vite.config.ts @@ -1,5 +1,6 @@ -/// +/// import { defineConfig } from 'vite' +import { playwright } from '@vitest/browser-playwright' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -14,7 +15,7 @@ export default defineConfig({ browser: { enabled: true, headless: !process.env.DEBUG, - provider: 'playwright', + provider: playwright(), instances: [ { browser: 'chromium', diff --git a/exercises/04.debugging/03.problem.breakpoints/package.json b/exercises/04.debugging/03.problem.breakpoints/package.json index 739f2e7..d48dec0 100644 --- a/exercises/04.debugging/03.problem.breakpoints/package.json +++ b/exercises/04.debugging/03.problem.breakpoints/package.json @@ -15,10 +15,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } } diff --git a/exercises/04.debugging/03.problem.breakpoints/tsconfig.test.browser.json b/exercises/04.debugging/03.problem.breakpoints/tsconfig.test.browser.json index c59f172..74c3de8 100644 --- a/exercises/04.debugging/03.problem.breakpoints/tsconfig.test.browser.json +++ b/exercises/04.debugging/03.problem.breakpoints/tsconfig.test.browser.json @@ -8,6 +8,6 @@ ], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/providers/playwright"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/04.debugging/03.problem.breakpoints/vite.config.ts b/exercises/04.debugging/03.problem.breakpoints/vite.config.ts index 85e9082..ca010f2 100644 --- a/exercises/04.debugging/03.problem.breakpoints/vite.config.ts +++ b/exercises/04.debugging/03.problem.breakpoints/vite.config.ts @@ -1,5 +1,6 @@ -/// +/// import { defineConfig } from 'vite' +import { playwright } from '@vitest/browser-playwright' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -14,7 +15,7 @@ export default defineConfig({ browser: { enabled: true, headless: !process.env.DEBUG, - provider: 'playwright', + provider: playwright(), instances: [ { browser: 'chromium', diff --git a/exercises/04.debugging/03.solution.breakpoints/package.json b/exercises/04.debugging/03.solution.breakpoints/package.json index caba5c1..4833297 100644 --- a/exercises/04.debugging/03.solution.breakpoints/package.json +++ b/exercises/04.debugging/03.solution.breakpoints/package.json @@ -15,10 +15,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } } diff --git a/exercises/04.debugging/03.solution.breakpoints/tsconfig.test.browser.json b/exercises/04.debugging/03.solution.breakpoints/tsconfig.test.browser.json index c59f172..74c3de8 100644 --- a/exercises/04.debugging/03.solution.breakpoints/tsconfig.test.browser.json +++ b/exercises/04.debugging/03.solution.breakpoints/tsconfig.test.browser.json @@ -8,6 +8,6 @@ ], "exclude": [], "compilerOptions": { - "types": ["vitest/globals", "@vitest/browser/providers/playwright"] + "types": ["vitest/globals", "@vitest/browser/context"] } } diff --git a/exercises/04.debugging/03.solution.breakpoints/vite.config.ts b/exercises/04.debugging/03.solution.breakpoints/vite.config.ts index 85e9082..ca010f2 100644 --- a/exercises/04.debugging/03.solution.breakpoints/vite.config.ts +++ b/exercises/04.debugging/03.solution.breakpoints/vite.config.ts @@ -1,5 +1,6 @@ -/// +/// import { defineConfig } from 'vite' +import { playwright } from '@vitest/browser-playwright' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' @@ -14,7 +15,7 @@ export default defineConfig({ browser: { enabled: true, headless: !process.env.DEBUG, - provider: 'playwright', + provider: playwright(), instances: [ { browser: 'chromium', diff --git a/package-lock.json b/package-lock.json index 3ebab6a..2965c96 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,8 @@ "eslint": "^9.9.0", "pkgmgr": "^1.1.1", "prettier": "^3.3.3", - "typescript": "^5.7.3" + "typescript": "^5.7.3", + "vitest": "^4.0.17" }, "engines": { "git": ">=2.18.0", @@ -26,6 +27,7 @@ "exercises/01.sunsetting-jsdom/01.problem.break-jsdom": { "name": "exercises_01.sunsetting-jsdom_01.problem.break-jsdom", "dependencies": { + "@vitest/browser": "^4.0.17", "react": "^19.0.0", "react-dom": "^19.0.0" }, @@ -38,15 +40,17 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", + "@vitest/browser-playwright": "^4.0.17", "jsdom": "^26.0.0", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } }, "exercises/01.sunsetting-jsdom/01.solution.break-jsdom": { "name": "exercises_01.sunsetting-jsdom_01.solution.break-jsdom", "dependencies": { + "@vitest/browser": "^4.0.17", "react": "^19.0.0", "react-dom": "^19.0.0" }, @@ -58,10 +62,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", + "@vitest/browser-playwright": "^4.0.17", "jsdom": "^26.0.0", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } }, "exercises/02.vitest-browser-mode/01.problem.installation-and-setup": { @@ -77,11 +82,12 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.0.5", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "jsdom": "^26.0.0", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.0.7" + "vitest": "^4.0.17" } }, "exercises/02.vitest-browser-mode/01.solution.installation-and-setup": { @@ -95,10 +101,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0", + "vitest": "^4.0.17", "vitest-browser-react": "^0.2.0" } }, @@ -113,10 +120,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0", + "vitest": "^4.0.17", "vitest-browser-react": "^0.2.0" } }, @@ -131,10 +139,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } }, "exercises/02.vitest-browser-mode/03.problem.playwright": { @@ -148,10 +157,11 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } }, "exercises/02.vitest-browser-mode/03.solution.playwright": { @@ -165,11 +175,12 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } }, "exercises/02.vitest-browser-mode/04.problem.shared-assets": { @@ -183,11 +194,12 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } }, "exercises/02.vitest-browser-mode/04.solution.shared-assets": { @@ -201,11 +213,12 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } }, "exercises/02.vitest-browser-mode/05.problem.multiple-workspaces": { @@ -219,11 +232,12 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } }, "exercises/02.vitest-browser-mode/05.solution.multiple-workspaces": { @@ -238,11 +252,12 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } }, "exercises/03.best-practices/01.problem.accessibility-selectors": { @@ -275,11 +290,12 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } }, "exercises/03.best-practices/01.solution.accessibility-selectors": { @@ -312,11 +328,12 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } }, "exercises/03.best-practices/02.problem.user-events": { @@ -330,11 +347,12 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } }, "exercises/03.best-practices/02.solution.user-events": { @@ -348,11 +366,12 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } }, "exercises/03.best-practices/03.problem.network-mocking": { @@ -366,11 +385,12 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } }, "exercises/03.best-practices/03.solution.network-mocking": { @@ -384,12 +404,13 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "msw": "^2.7.3", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } }, "exercises/03.best-practices/04.problem.element-presence": { @@ -403,12 +424,13 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "msw": "^2.7.3", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } }, "exercises/03.best-practices/04.solution.element-presence": { @@ -422,12 +444,13 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "msw": "^2.7.3", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } }, "exercises/03.best-practices/05.problem.page-navigation": { @@ -442,12 +465,13 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "msw": "^2.7.3", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } }, "exercises/03.best-practices/05.solution.page-navigation": { @@ -462,12 +486,13 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "msw": "^2.7.3", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } }, "exercises/03.best-practices/06.solution.react-hooks": { @@ -502,11 +527,12 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } }, "exercises/04.debugging/01.solution.dom-snapshots": { @@ -520,11 +546,12 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } }, "exercises/04.debugging/02.problem.debugger": { @@ -538,11 +565,12 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } }, "exercises/04.debugging/02.solution.debugger": { @@ -556,11 +584,12 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } }, "exercises/04.debugging/03.problem.breakpoints": { @@ -574,11 +603,12 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } }, "exercises/04.debugging/03.solution.breakpoints": { @@ -592,11 +622,12 @@ "@types/react": "^19.0.6", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", - "@vitest/browser": "^3.2.0", + "@vitest/browser": "^4.0.17", + "@vitest/browser-playwright": "^4.0.17", "playwright": "^1.49.1", "tailwindcss": "^4.0.11", "vite": "^6.2.0", - "vitest": "^3.2.0" + "vitest": "^4.0.17" } }, "exercises/04.debugging/04.problem.debug-console": { @@ -1937,10 +1968,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { @@ -2039,7 +2069,6 @@ "version": "1.0.0-next.28", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz", "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==", - "dev": true, "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { @@ -2308,6 +2337,13 @@ "win32" ] }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, "node_modules/@tailwindcss/node": { "version": "4.0.11", "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.0.11.tgz", @@ -2710,13 +2746,14 @@ } }, "node_modules/@types/chai": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz", - "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", "dev": true, "license": "MIT", "dependencies": { - "@types/deep-eql": "*" + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" } }, "node_modules/@types/cookie": { @@ -2743,7 +2780,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true, "license": "MIT" }, "node_modules/@types/gensync": { @@ -3031,41 +3067,76 @@ } }, "node_modules/@vitest/browser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-3.2.0.tgz", - "integrity": "sha512-sVpX5m53lX9/0ehAqkcTSQeJK1SVlTlvBrwE8rPQ2KJQgb/Iiorx+3y+VQdzIJ+CDqfG89bQEA5l1Z02VogDsA==", + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-4.0.17.tgz", + "integrity": "sha512-cgf2JZk2fv5or3efmOrRJe1V9Md89BPgz4ntzbf84yAb+z2hW6niaGFinl9aFzPZ1q3TGfWZQWZ9gXTFThs2Qw==", + "license": "MIT", + "dependencies": { + "@vitest/mocker": "4.0.17", + "@vitest/utils": "4.0.17", + "magic-string": "^0.30.21", + "pixelmatch": "7.1.0", + "pngjs": "^7.0.0", + "sirv": "^3.0.2", + "tinyrainbow": "^3.0.3", + "ws": "^8.18.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "vitest": "4.0.17" + } + }, + "node_modules/@vitest/browser-playwright": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@vitest/browser-playwright/-/browser-playwright-4.0.17.tgz", + "integrity": "sha512-CE9nlzslHX6Qz//MVrjpulTC9IgtXTbJ+q7Rx1HD+IeSOWv4NHIRNHPA6dB4x01d9paEqt+TvoqZfmgq40DxEQ==", "dev": true, "license": "MIT", "dependencies": { - "@testing-library/dom": "^10.4.0", - "@testing-library/user-event": "^14.6.1", - "@vitest/mocker": "3.2.0", - "@vitest/utils": "3.2.0", - "magic-string": "^0.30.17", - "sirv": "^3.0.1", - "tinyrainbow": "^2.0.0", - "ws": "^8.18.2" + "@vitest/browser": "4.0.17", + "@vitest/mocker": "4.0.17", + "tinyrainbow": "^3.0.3" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "playwright": "*", - "vitest": "3.2.0", - "webdriverio": "^7.0.0 || ^8.0.0 || ^9.0.0" + "vitest": "4.0.17" }, "peerDependenciesMeta": { "playwright": { - "optional": true - }, - "safaridriver": { - "optional": true - }, - "webdriverio": { - "optional": true + "optional": false } } }, + "node_modules/@vitest/browser/node_modules/@vitest/pretty-format": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.17.tgz", + "integrity": "sha512-Ah3VAYmjcEdHg6+MwFE17qyLqBHZ+ni2ScKCiW2XrlSBV4H3Z7vYfPfz7CWQ33gyu76oc0Ai36+kgLU3rfF4nw==", + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/browser/node_modules/@vitest/utils": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.17.tgz", + "integrity": "sha512-RG6iy+IzQpa9SB8HAFHJ9Y+pTzI+h8553MrciN9eC6TFBErqrQaTas4vG+MVj8S4uKk8uTT2p0vgZPnTdxd96w==", + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.0.17", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/@vitest/eslint-plugin": { "version": "1.1.31", "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.1.31.tgz", @@ -3087,40 +3158,22 @@ } } }, - "node_modules/@vitest/expect": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.0.tgz", - "integrity": "sha512-0v4YVbhDKX3SKoy0PHWXpKhj44w+3zZkIoVES9Ex2pq+u6+Bijijbi2ua5kE+h3qT6LBWFTNZSCOEU37H8Y5sA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/chai": "^5.2.2", - "@vitest/spy": "3.2.0", - "@vitest/utils": "3.2.0", - "chai": "^5.2.0", - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, "node_modules/@vitest/mocker": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.0.tgz", - "integrity": "sha512-HFcW0lAMx3eN9vQqis63H0Pscv0QcVMo1Kv8BNysZbxcmHu3ZUYv59DS6BGYiGQ8F5lUkmsfMMlPm4DJFJdf/A==", - "dev": true, + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.17.tgz", + "integrity": "sha512-+ZtQhLA3lDh1tI2wxe3yMsGzbp7uuJSWBM1iTIKCbppWTSBN09PUC+L+fyNlQApQoR+Ps8twt2pbSSXg2fQVEQ==", "license": "MIT", "dependencies": { - "@vitest/spy": "3.2.0", + "@vitest/spy": "4.0.17", "estree-walker": "^3.0.3", - "magic-string": "^0.30.17" + "magic-string": "^0.30.21" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "msw": "^2.4.9", - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + "vite": "^6.0.0 || ^7.0.0-0" }, "peerDependenciesMeta": { "msw": { @@ -3131,72 +3184,11 @@ } } }, - "node_modules/@vitest/pretty-format": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.0.tgz", - "integrity": "sha512-gUUhaUmPBHFkrqnOokmfMGRBMHhgpICud9nrz/xpNV3/4OXCn35oG+Pl8rYYsKaTNd/FAIrqRHnwpDpmYxCYZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.0.tgz", - "integrity": "sha512-bXdmnHxuB7fXJdh+8vvnlwi/m1zvu+I06i1dICVcDQFhyV4iKw2RExC/acavtDn93m/dRuawUObKsrNE1gJacA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/utils": "3.2.0", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.0.tgz", - "integrity": "sha512-z7P/EneBRMe7hdvWhcHoXjhA6at0Q4ipcoZo6SqgxLyQQ8KSMMCmvw1cSt7FHib3ozt0wnRHc37ivuUMbxzG/A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "3.2.0", - "magic-string": "^0.30.17", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/spy": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.0.tgz", - "integrity": "sha512-s3+TkCNUIEOX99S0JwNDfsHRaZDDZZR/n8F0mop0PmsEbQGKZikCGpTGZ6JRiHuONKew3Fb5//EPwCP+pUX9cw==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyspy": "^4.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.0.tgz", - "integrity": "sha512-gXXOe7Fj6toCsZKVQouTRLJftJwmvbhH5lKOBR6rlP950zUq9AitTUjnFoXS/CqjBC2aoejAztLPzzuva++XBw==", - "dev": true, + "node_modules/@vitest/mocker/node_modules/@vitest/spy": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.17.tgz", + "integrity": "sha512-I1bQo8QaP6tZlTomQNWKJE6ym4SHf3oLS7ceNjozxxgzavRAgZDc06T7kD8gb9bXKEgcLNt00Z+kZO6KaJ62Ew==", "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "3.2.0", - "loupe": "^3.1.3", - "tinyrainbow": "^2.0.0" - }, "funding": { "url": "https://opencollective.com/vitest" } @@ -3566,16 +3558,6 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -3657,23 +3639,6 @@ ], "license": "CC-BY-4.0" }, - "node_modules/chai": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", - "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", - "dev": true, - "license": "MIT", - "dependencies": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -3691,16 +3656,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/check-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 16" - } - }, "node_modules/cli-width": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", @@ -3972,16 +3927,6 @@ "dev": true, "license": "MIT" }, - "node_modules/deep-eql": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -4774,7 +4719,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, "license": "MIT", "dependencies": { "@types/estree": "^1.0.0" @@ -4903,9 +4847,9 @@ "link": true }, "node_modules/expect-type": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.1.tgz", - "integrity": "sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -4974,11 +4918,14 @@ } }, "node_modules/fdir": { - "version": "6.4.5", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.5.tgz", - "integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, "peerDependencies": { "picomatch": "^3 || ^4" }, @@ -6400,13 +6347,6 @@ "loose-envify": "cli.js" } }, - "node_modules/loupe": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", - "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", - "dev": true, - "license": "MIT" - }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -6428,13 +6368,12 @@ } }, "node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", - "dev": true, + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" + "@jridgewell/sourcemap-codec": "^1.5.5" } }, "node_modules/math-intrinsics": { @@ -6521,7 +6460,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -6736,6 +6674,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -6878,16 +6827,6 @@ "dev": true, "license": "MIT" }, - "node_modules/pathval": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", - "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.16" - } - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -6908,6 +6847,18 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pixelmatch": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-7.1.0.tgz", + "integrity": "sha512-1wrVzJ2STrpmONHKBy228LM1b84msXDUoAzVEl0R8Mz4Ce6EPr+IVtxm8+yvrqLYMHswREkjYFaMxnyGnaY3Ng==", + "license": "ISC", + "dependencies": { + "pngjs": "^7.0.0" + }, + "bin": { + "pixelmatch": "bin/pixelmatch" + } + }, "node_modules/pkgmgr": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pkgmgr/-/pkgmgr-1.1.1.tgz", @@ -6960,6 +6911,15 @@ "node": ">=18" } }, + "node_modules/pngjs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz", + "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==", + "license": "MIT", + "engines": { + "node": ">=14.19.0" + } + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", @@ -7756,10 +7716,9 @@ } }, "node_modules/sirv": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.1.tgz", - "integrity": "sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==", - "dev": true, + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", + "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", "license": "MIT", "dependencies": { "@polka/url": "^1.0.0-next.24", @@ -7805,9 +7764,9 @@ } }, "node_modules/std-env": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", - "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", "dev": true, "license": "MIT" }, @@ -7999,22 +7958,15 @@ "dev": true, "license": "MIT" }, - "node_modules/tinyexec": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", - "dev": true, - "license": "MIT" - }, "node_modules/tinyglobby": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", - "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dev": true, "license": "MIT", "dependencies": { - "fdir": "^6.4.4", - "picomatch": "^4.0.2" + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { "node": ">=12.0.0" @@ -8024,9 +7976,9 @@ } }, "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", "engines": { @@ -8036,31 +7988,10 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/tinypool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.0.tgz", - "integrity": "sha512-7CotroY9a8DKsKprEy/a14aCCm8jYVmR7aFy4fpkZM8sdpNJbKkixuNjgM50yCmip2ezc8z4N7k3oe2+rfRJCQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.0.0 || >=20.0.0" - } - }, "node_modules/tinyrainbow": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", - "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tinyspy": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.3.tgz", - "integrity": "sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==", - "dev": true, + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", + "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", "license": "MIT", "engines": { "node": ">=14.0.0" @@ -8103,7 +8034,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -8462,29 +8392,6 @@ } } }, - "node_modules/vite-node": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.0.tgz", - "integrity": "sha512-8Fc5Ko5Y4URIJkmMF/iFP1C0/OJyY+VGVe9Nw6WAdZyw4bTO+eVg9mwxWkQp/y8NnAoQY3o9KAvE1ZdA2v+Vmg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cac": "^6.7.14", - "debug": "^4.4.1", - "es-module-lexer": "^1.7.0", - "pathe": "^2.0.3", - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" - }, - "bin": { - "vite-node": "vite-node.mjs" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, "node_modules/vite/node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -8501,51 +8408,50 @@ } }, "node_modules/vitest": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.0.tgz", - "integrity": "sha512-P7Nvwuli8WBNmeMHHek7PnGW4oAZl9za1fddfRVidZar8wDZRi7hpznLKQePQ8JPLwSBEYDK11g+++j7uFJV8Q==", + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.17.tgz", + "integrity": "sha512-FQMeF0DJdWY0iOnbv466n/0BudNdKj1l5jYgl5JVTwjSsZSlqyXFt/9+1sEyhR6CLowbZpV7O1sCHrzBhucKKg==", "dev": true, "license": "MIT", "dependencies": { - "@types/chai": "^5.2.2", - "@vitest/expect": "3.2.0", - "@vitest/mocker": "3.2.0", - "@vitest/pretty-format": "^3.2.0", - "@vitest/runner": "3.2.0", - "@vitest/snapshot": "3.2.0", - "@vitest/spy": "3.2.0", - "@vitest/utils": "3.2.0", - "chai": "^5.2.0", - "debug": "^4.4.1", - "expect-type": "^1.2.1", - "magic-string": "^0.30.17", + "@vitest/expect": "4.0.17", + "@vitest/mocker": "4.0.17", + "@vitest/pretty-format": "4.0.17", + "@vitest/runner": "4.0.17", + "@vitest/snapshot": "4.0.17", + "@vitest/spy": "4.0.17", + "@vitest/utils": "4.0.17", + "es-module-lexer": "^1.7.0", + "expect-type": "^1.2.2", + "magic-string": "^0.30.21", + "obug": "^2.1.1", "pathe": "^2.0.3", - "picomatch": "^4.0.2", - "std-env": "^3.9.0", + "picomatch": "^4.0.3", + "std-env": "^3.10.0", "tinybench": "^2.9.0", - "tinyexec": "^0.3.2", - "tinyglobby": "^0.2.14", - "tinypool": "^1.1.0", - "tinyrainbow": "^2.0.0", - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", - "vite-node": "3.2.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.0.3", + "vite": "^6.0.0 || ^7.0.0", "why-is-node-running": "^2.3.0" }, "bin": { "vitest": "vitest.mjs" }, "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "@edge-runtime/vm": "*", - "@types/debug": "^4.1.12", - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.2.0", - "@vitest/ui": "3.2.0", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.0.17", + "@vitest/browser-preview": "4.0.17", + "@vitest/browser-webdriverio": "4.0.17", + "@vitest/ui": "4.0.17", "happy-dom": "*", "jsdom": "*" }, @@ -8553,13 +8459,19 @@ "@edge-runtime/vm": { "optional": true }, - "@types/debug": { + "@opentelemetry/api": { "optional": true }, "@types/node": { "optional": true }, - "@vitest/browser": { + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { "optional": true }, "@vitest/ui": { @@ -8602,10 +8514,104 @@ } } }, + "node_modules/vitest/node_modules/@vitest/expect": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.17.tgz", + "integrity": "sha512-mEoqP3RqhKlbmUmntNDDCJeTDavDR+fVYkSOw8qRwJFaW/0/5zA9zFeTrHqNtcmwh6j26yMmwx2PqUDPzt5ZAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.0.17", + "@vitest/utils": "4.0.17", + "chai": "^6.2.1", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest/node_modules/@vitest/pretty-format": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.17.tgz", + "integrity": "sha512-Ah3VAYmjcEdHg6+MwFE17qyLqBHZ+ni2ScKCiW2XrlSBV4H3Z7vYfPfz7CWQ33gyu76oc0Ai36+kgLU3rfF4nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest/node_modules/@vitest/runner": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.17.tgz", + "integrity": "sha512-JmuQyf8aMWoo/LmNFppdpkfRVHJcsgzkbCA+/Bk7VfNH7RE6Ut2qxegeyx2j3ojtJtKIbIGy3h+KxGfYfk28YQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.0.17", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest/node_modules/@vitest/snapshot": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.17.tgz", + "integrity": "sha512-npPelD7oyL+YQM2gbIYvlavlMVWUfNNGZPcu0aEUQXt7FXTuqhmgiYupPnAanhKvyP6Srs2pIbWo30K0RbDtRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.0.17", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest/node_modules/@vitest/spy": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.17.tgz", + "integrity": "sha512-I1bQo8QaP6tZlTomQNWKJE6ym4SHf3oLS7ceNjozxxgzavRAgZDc06T7kD8gb9bXKEgcLNt00Z+kZO6KaJ62Ew==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest/node_modules/@vitest/utils": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.17.tgz", + "integrity": "sha512-RG6iy+IzQpa9SB8HAFHJ9Y+pTzI+h8553MrciN9eC6TFBErqrQaTas4vG+MVj8S4uKk8uTT2p0vgZPnTdxd96w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.0.17", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest/node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/vitest/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", "engines": { @@ -8615,6 +8621,16 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/vitest/node_modules/tinyexec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/w3c-xmlserializer": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", @@ -8857,10 +8873,9 @@ } }, "node_modules/ws": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz", - "integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==", - "dev": true, + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", "license": "MIT", "engines": { "node": ">=10.0.0" diff --git a/package.json b/package.json index b8bef32..2d86e4b 100644 --- a/package.json +++ b/package.json @@ -42,9 +42,10 @@ "devDependencies": { "@epic-web/config": "^1.18.3", "eslint": "^9.9.0", + "pkgmgr": "^1.1.1", "prettier": "^3.3.3", "typescript": "^5.7.3", - "pkgmgr": "^1.1.1" + "vitest": "^4.0.17" }, "prettier": "@epic-web/config/prettier" }