diff --git a/.gitignore b/.gitignore index 2b55915..fc1995d 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,9 @@ cypress/integration/examples .netlify .env .astro + +# Playwright +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/e2e/README.md b/e2e/README.md new file mode 100644 index 0000000..0572173 --- /dev/null +++ b/e2e/README.md @@ -0,0 +1,64 @@ +# E2E Tests with Playwright and Guidepup + +This directory contains end-to-end tests for the website using Playwright and Guidepup for accessibility testing. + +## Prerequisites + +Before running the tests, you need to install Playwright browsers: + +```bash +pnpm exec playwright install --with-deps chromium +``` + +## Running Tests + +There are several ways to run the tests: + +### Run all tests (headless) +```bash +pnpm run test:e2e +``` + +### Run tests with UI mode (recommended for development) +```bash +pnpm run test:e2e:ui +``` + +### Run tests in headed mode (see the browser) +```bash +pnpm run test:e2e:headed +``` + +### Debug mode +```bash +pnpm run test:e2e:debug +``` + +### View test report +```bash +pnpm run test:e2e:report +``` + +## Test Structure + +- `smoke.spec.ts` - Basic smoke tests that verify: + - The site renders successfully + - The page title is correct + - Main heading is visible + - Page structure includes proper landmarks + - Links are accessible + - Screen reader accessibility (VoiceOver on macOS) + - Proper heading hierarchy + +## Accessibility Testing + +The tests include Guidepup integration for screen reader testing. The VoiceOver test will only run on macOS with WebKit browser. + +## Configuration + +The Playwright configuration is in `playwright.config.ts` at the root of the project. It's configured to: + +- Start the dev server automatically before running tests +- Use http://localhost:4321 as the base URL +- Run tests in Chromium by default +- Generate an HTML report after test completion diff --git a/e2e/smoke.spec.ts b/e2e/smoke.spec.ts new file mode 100644 index 0000000..ed6a2d5 --- /dev/null +++ b/e2e/smoke.spec.ts @@ -0,0 +1,88 @@ +import { test, expect } from '@playwright/test'; +import { voiceOver } from '@guidepup/playwright'; + +test.describe('Smoke tests', () => { + test('should render the homepage successfully', async ({ page }) => { + await page.goto('/'); + + // Wait for the page to be fully loaded + await page.waitForLoadState('networkidle'); + + // Check that the page has loaded + expect(await page.title()).toBeTruthy(); + }); + + test('should display the correct page title', async ({ page }) => { + await page.goto('/'); + + // Verify the page title + const title = await page.title(); + expect(title).toContain('Dan Matthew is an accessibility and design systems consultant'); + }); + + test('should have the main heading visible', async ({ page }) => { + await page.goto('/'); + + // Check for the main heading text + const heading = page.getByText('Accessibility and design systems consultant'); + await expect(heading).toBeVisible(); + }); + + test('should have proper page structure', async ({ page }) => { + await page.goto('/'); + + // Check for main landmark + const main = page.locator('main#main'); + await expect(main).toBeVisible(); + + // Check for navigation + const nav = page.locator('nav'); + await expect(nav).toBeVisible(); + }); + + test('should have accessible links', async ({ page }) => { + await page.goto('/'); + + // Check that social links are present and accessible + const socialLinks = page.getByRole('link', { name: /github|linkedin|bluesky/i }); + expect(await socialLinks.count()).toBeGreaterThan(0); + }); +}); + +test.describe('Screen reader accessibility', () => { + test('should be navigable with VoiceOver', async ({ page, browserName }) => { + test.skip(browserName !== 'webkit', 'VoiceOver is only available on macOS'); + + await page.goto('/'); + + // Start VoiceOver + await voiceOver.start(page); + + try { + // Navigate to the main content + await voiceOver.next(); + + // Get the spoken phrase + const spokenPhrase = await voiceOver.lastSpokenPhrase(); + + // Verify that VoiceOver is reading content + expect(spokenPhrase).toBeTruthy(); + + } finally { + // Always stop VoiceOver + await voiceOver.stop(); + } + }); + + test('should have proper heading hierarchy', async ({ page }) => { + await page.goto('/'); + + // Check that headings are properly structured + const h1Count = await page.locator('h1').count(); + expect(h1Count).toBeGreaterThanOrEqual(1); + + // Verify the page has a logical heading structure + const headings = await page.locator('h1, h2, h3, h4, h5, h6').all(); + expect(headings.length).toBeGreaterThan(0); + }); +}); diff --git a/package.json b/package.json index fc9916e..7296acc 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,8 @@ "description": "", "main": "index.js", "devDependencies": { + "@guidepup/playwright": "^0.14.2", + "@playwright/test": "^1.56.1", "eslint-config-prettier": "^9.1.0", "husky": "^9.1.7", "lint-staged": "^15.2.10", @@ -36,6 +38,11 @@ "format:eslint": "eslint --ext .js,.html . --fix --ignore-path .gitignore", "format:prettier": "prettier \"**/*.js\" --write", "test": "cypress run --spec \"cypress/integration/home_page.spec.js\"", + "test:e2e": "playwright test", + "test:e2e:ui": "playwright test --ui", + "test:e2e:debug": "playwright test --debug", + "test:e2e:headed": "playwright test --headed", + "test:e2e:report": "playwright show-report", "release": "npx standard-version && git push --follow-tags" }, "repository": { diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..721b674 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,30 @@ +import { defineConfig, devices } from '@playwright/test'; + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + fullyParallel: true, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + workers: process.env.CI ? 1 : undefined, + reporter: 'html', + use: { + baseURL: 'http://localhost:4321', + trace: 'on-first-retry', + }, + + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + ], + + webServer: { + command: 'pnpm run dev', + url: 'http://localhost:4321', + reuseExistingServer: !process.env.CI, + }, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index acff261..74dc180 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -36,6 +36,12 @@ importers: specifier: ^9.15.0 version: 9.15.0(jiti@2.4.2) devDependencies: + '@guidepup/playwright': + specifier: ^0.14.2 + version: 0.14.2(@guidepup/guidepup@0.24.0)(@playwright/test@1.56.1) + '@playwright/test': + specifier: ^1.56.1 + version: 1.56.1 eslint-config-prettier: specifier: ^9.1.0 version: 9.1.0(eslint@9.15.0(jiti@2.4.2)) @@ -424,6 +430,15 @@ packages: '@georgedoescode/generative-utils@1.0.38': resolution: {integrity: sha512-TrubU77D6D2RHREzOGU2OqDeHZqptHhyTvPzQ5YybPgNi2CpoRkAiAg80bu50W3RG+X45DD/9xF0nCs1tpd56g==} + '@guidepup/guidepup@0.24.0': + resolution: {integrity: sha512-bbbcJPbZ01Zkxi+L51R4iI7iZ3b2ax3SocqAF0hCgS+Vax6TOft5eZJ37QWRSQM6Xis6OOEVlRhzpM2807WyiA==} + + '@guidepup/playwright@0.14.2': + resolution: {integrity: sha512-EgBpPseUaBS3XNRvSDkS7E+I/+okNZPnqQCHeEg78pa7BMuQDSd61i0VveDSv6L55z1yvRFH7oEZVVlcjgsM6g==} + peerDependencies: + '@guidepup/guidepup': '>=0.22.1' + '@playwright/test': ^1.40.1 + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -658,6 +673,11 @@ packages: resolution: {integrity: sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ==} engines: {node: '>= 10.0.0'} + '@playwright/test@1.56.1': + resolution: {integrity: sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==} + engines: {node: '>=18'} + hasBin: true + '@rollup/pluginutils@5.1.3': resolution: {integrity: sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==} engines: {node: '>=14.0.0'} @@ -1062,6 +1082,9 @@ packages: resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} engines: {node: '>= 0.6'} + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -1485,6 +1508,14 @@ packages: resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==} engines: {node: '>= 6'} + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -1519,6 +1550,10 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + globals@14.0.0: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} @@ -1607,6 +1642,9 @@ packages: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} + if-async@3.7.4: + resolution: {integrity: sha512-BFEH2mZyeF6KZKaKLVPZ0wMjIiWOdjvZ7zbx8ENec0qfZhJwKFbX/4jKM5LTKyJEc/GOqUKiiJ2IFKT9yWrZqA==} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -1622,6 +1660,13 @@ packages: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + inline-style-parser@0.1.1: resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} @@ -1632,6 +1677,10 @@ packages: resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} engines: {node: '>=12'} + interpret@1.4.0: + resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} + engines: {node: '>= 0.10'} + iron-webcrypto@1.2.1: resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} @@ -1648,6 +1697,10 @@ packages: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + is-decimal@2.0.1: resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} @@ -1704,6 +1757,9 @@ packages: resolution: {integrity: sha512-jv+8jaWCl0g2lSBkNSVXdzfBA0npK1HGC2KtWM9FumFRoGS94g3NbCCLVnCYHLjp4GrW2KZeeSTMo5ddtznmGw==} engines: {node: '>=18'} + isarray@0.0.1: + resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} + isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -2055,6 +2111,9 @@ packages: ohash@1.1.4: resolution: {integrity: sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g==} + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + onetime@6.0.0: resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} engines: {node: '>=12'} @@ -2123,6 +2182,10 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -2131,6 +2194,9 @@ packages: resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} engines: {node: '>=12'} + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} @@ -2161,6 +2227,16 @@ packages: pkg-types@1.2.1: resolution: {integrity: sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw==} + playwright-core@1.56.1: + resolution: {integrity: sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==} + engines: {node: '>=18'} + hasBin: true + + playwright@1.56.1: + resolution: {integrity: sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==} + engines: {node: '>=18'} + hasBin: true + postcss@8.4.49: resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} engines: {node: ^10 || ^12 || >=14} @@ -2218,10 +2294,17 @@ packages: resolution: {integrity: sha512-B53pp/8eFBxULg6sfQgjjmy3vZ2CWVt0Nk4OgkSpvmAf3VXfcEUgGASbNWbXiTiExWe8hCIf5HlddNHzrte9jg==} engines: {node: '>=10'} + readable-stream@1.0.34: + resolution: {integrity: sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==} + readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} + rechoir@0.6.2: + resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} + engines: {node: '>= 0.10'} + recma-build-jsx@1.0.0: resolution: {integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==} @@ -2234,6 +2317,9 @@ packages: recma-stringify@1.0.0: resolution: {integrity: sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==} + regedit@5.1.2: + resolution: {integrity: sha512-pQpWqO/I40bMNoMO9kTQx3e5iK542kYcB/Z8X3Y7Hcri6ydc4KZ9ByUsEWFkBRMcwo+2irHuNK5s+pMGPr6VPw==} + regex-recursion@4.3.0: resolution: {integrity: sha512-5LcLnizwjcQ2ALfOj95MjcatxyqF5RPySx9yT+PaXu3Gox2vyAtLDjHB8NTJLtMGkvyau6nI3CfpwFCjPUIs/A==} @@ -2281,6 +2367,11 @@ packages: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} + resolve@1.22.11: + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} + engines: {node: '>= 0.4'} + hasBin: true + restore-cursor@5.1.0: resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} engines: {node: '>=18'} @@ -2341,6 +2432,11 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + shelljs@0.8.5: + resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==} + engines: {node: '>=4'} + hasBin: true + shiki@1.23.1: resolution: {integrity: sha512-8kxV9TH4pXgdKGxNOkrSMydn1Xf6It8lsle0fiqxf7a1149K1WGtdOu3Zb91T5r1JpvRPxqxU3C2XdZZXQnrig==} @@ -2398,6 +2494,9 @@ packages: std-env@3.8.0: resolution: {integrity: sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==} + stream-slicer@0.0.6: + resolution: {integrity: sha512-QsY0LbweYE5L+e+iBQgtkM5WUIf7+kCMA/m2VULv8rEEDDnlDPsPvOHH4nli6uaZOKQEt64u65h0l/eeZo7lCw==} + string-argv@0.3.2: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} @@ -2410,6 +2509,9 @@ packages: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} + string_decoder@0.10.31: + resolution: {integrity: sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==} + stringify-entities@4.0.4: resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} @@ -2443,10 +2545,17 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + system-architecture@0.1.0: resolution: {integrity: sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA==} engines: {node: '>=18'} + through2@0.6.5: + resolution: {integrity: sha512-RkK/CCESdTKQZHdmKICijdKKsCRVHs5KsLZ6pACAmF/1GPUQhonHSXWNERctxEp7RmvjdNbZTL5z9V7nSCXKcg==} + tinyexec@0.3.1: resolution: {integrity: sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==} @@ -2688,6 +2797,13 @@ packages: resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} engines: {node: '>=18'} + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + xxhash-wasm@1.1.0: resolution: {integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==} @@ -3018,6 +3134,19 @@ snapshots: seedrandom: 3.0.5 simplex-noise: 2.4.0 + '@guidepup/guidepup@0.24.0': + dependencies: + regedit: 5.1.2 + semver: 7.6.3 + shelljs: 0.8.5 + transitivePeerDependencies: + - supports-color + + '@guidepup/playwright@0.14.2(@guidepup/guidepup@0.24.0)(@playwright/test@1.56.1)': + dependencies: + '@guidepup/guidepup': 0.24.0 + '@playwright/test': 1.56.1 + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.6': @@ -3217,6 +3346,10 @@ snapshots: '@parcel/watcher-win32-ia32': 2.5.0 '@parcel/watcher-win32-x64': 2.5.0 + '@playwright/test@1.56.1': + dependencies: + playwright: 1.56.1 + '@rollup/pluginutils@5.1.3(rollup@4.27.4)': dependencies: '@types/estree': 1.0.6 @@ -3682,6 +3815,8 @@ snapshots: cookie@0.7.2: {} + core-util-is@1.0.3: {} + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -4179,6 +4314,11 @@ snapshots: combined-stream: 1.0.8 mime-types: 2.1.35 + fs.realpath@1.0.0: {} + + fsevents@2.3.2: + optional: true + fsevents@2.3.3: optional: true @@ -4213,6 +4353,15 @@ snapshots: dependencies: is-glob: 4.0.3 + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + globals@14.0.0: {} gopd@1.2.0: {} @@ -4384,6 +4533,8 @@ snapshots: dependencies: safer-buffer: 2.1.2 + if-async@3.7.4: {} + ignore@5.3.2: {} import-fresh@3.3.0: @@ -4395,12 +4546,21 @@ snapshots: imurmurhash@0.1.4: {} + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + inline-style-parser@0.1.1: {} inline-style-parser@0.2.4: {} internmap@2.0.3: {} + interpret@1.4.0: {} + iron-webcrypto@1.2.1: {} is-alphabetical@2.0.1: {} @@ -4417,6 +4577,10 @@ snapshots: dependencies: binary-extensions: 2.3.0 + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + is-decimal@2.0.1: {} is-docker@3.0.0: {} @@ -4455,6 +4619,8 @@ snapshots: dependencies: system-architecture: 0.1.0 + isarray@0.0.1: {} + isexe@2.0.0: {} jiti@2.4.2: {} @@ -5090,6 +5256,10 @@ snapshots: ohash@1.1.4: {} + once@1.4.0: + dependencies: + wrappy: 1.0.2 + onetime@6.0.0: dependencies: mimic-fn: 4.0.0 @@ -5174,10 +5344,14 @@ snapshots: path-exists@4.0.0: {} + path-is-absolute@1.0.1: {} + path-key@3.1.1: {} path-key@4.0.0: {} + path-parse@1.0.7: {} + pathe@1.1.2: {} picocolors@1.1.1: {} @@ -5200,6 +5374,14 @@ snapshots: mlly: 1.7.3 pathe: 1.1.2 + playwright-core@1.56.1: {} + + playwright@1.56.1: + dependencies: + playwright-core: 1.56.1 + optionalDependencies: + fsevents: 2.3.2 + postcss@8.4.49: dependencies: nanoid: 3.3.8 @@ -5247,10 +5429,21 @@ snapshots: dependencies: seedrandom: 3.0.5 + readable-stream@1.0.34: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 0.0.1 + string_decoder: 0.10.31 + readdirp@3.6.0: dependencies: picomatch: 2.3.1 + rechoir@0.6.2: + dependencies: + resolve: 1.22.11 + recma-build-jsx@1.0.0: dependencies: '@types/estree': 1.0.6 @@ -5281,6 +5474,15 @@ snapshots: unified: 11.0.5 vfile: 6.0.3 + regedit@5.1.2: + dependencies: + debug: 4.3.7 + if-async: 3.7.4 + stream-slicer: 0.0.6 + through2: 0.6.5 + transitivePeerDependencies: + - supports-color + regex-recursion@4.3.0: dependencies: regex-utilities: 2.3.0 @@ -5374,6 +5576,12 @@ snapshots: resolve-from@4.0.0: {} + resolve@1.22.11: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + restore-cursor@5.1.0: dependencies: onetime: 7.0.0 @@ -5479,6 +5687,12 @@ snapshots: shebang-regex@3.0.0: {} + shelljs@0.8.5: + dependencies: + glob: 7.2.3 + interpret: 1.4.0 + rechoir: 0.6.2 + shiki@1.23.1: dependencies: '@shikijs/core': 1.23.1 @@ -5547,6 +5761,8 @@ snapshots: std-env@3.8.0: {} + stream-slicer@0.0.6: {} + string-argv@0.3.2: {} string-width@4.2.3: @@ -5561,6 +5777,8 @@ snapshots: get-east-asian-width: 1.3.0 strip-ansi: 7.1.0 + string_decoder@0.10.31: {} + stringify-entities@4.0.4: dependencies: character-entities-html4: 2.1.0 @@ -5592,8 +5810,15 @@ snapshots: dependencies: has-flag: 4.0.0 + supports-preserve-symlinks-flag@1.0.0: {} + system-architecture@0.1.0: {} + through2@0.6.5: + dependencies: + readable-stream: 1.0.34 + xtend: 4.0.2 + tinyexec@0.3.1: {} to-regex-range@5.0.1: @@ -5771,6 +5996,10 @@ snapshots: string-width: 7.2.0 strip-ansi: 7.1.0 + wrappy@1.0.2: {} + + xtend@4.0.2: {} + xxhash-wasm@1.1.0: {} yaml@2.5.1: {}