diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 0000000..467190b --- /dev/null +++ b/.github/workflows/playwright.yml @@ -0,0 +1,27 @@ +name: Playwright Tests +on: + push: + branches: [ main, master ] + pull_request: + branches: [ main, master ] +jobs: + test: + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: lts/* + - name: Install dependencies + run: npm ci + - name: Install Playwright Browsers + run: npx playwright install --with-deps + - name: Run Playwright tests + run: npx playwright test + - uses: actions/upload-artifact@v4 + if: always() + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 diff --git a/.gitignore b/.gitignore index 6b74716..c84e54a 100644 --- a/.gitignore +++ b/.gitignore @@ -29,4 +29,9 @@ yarn-error.log* *storybook.log test-report.xml -eslint-results.sarif \ No newline at end of file +eslint-results.sarif +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ +storageState.json diff --git a/.prettierignore b/.prettierignore index 85ee54d..7870359 100644 --- a/.prettierignore +++ b/.prettierignore @@ -13,4 +13,6 @@ !config/**/*.js !config/**/*.ts -!scripts/**/*.js \ No newline at end of file +!scripts/**/*.js + +!tests/**/*.ts \ No newline at end of file diff --git a/.storybook/main.ts b/.storybook/main.ts index aaa1848..6fcbe2b 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -13,7 +13,6 @@ const config: StorybookConfig = { stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], addons: [ getAbsolutePath('@storybook/addon-webpack5-compiler-swc'), - getAbsolutePath('@storybook/addon-onboarding'), getAbsolutePath('@storybook/addon-links'), getAbsolutePath('@storybook/addon-essentials'), getAbsolutePath('@chromatic-com/storybook'), diff --git a/package.json b/package.json index 75168eb..8429d70 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,8 @@ ":generate:theme:clean": "rimraf ./build/lib", ":generate:theme": "npm-run-all :generate:theme:build :generate:theme:clean", "storybook": "storybook dev -p 6006", - "build-storybook": "storybook build" + "build-storybook": "storybook build", + "test:storybook": "npx playwright test --ui" }, "dependencies": { "@babel/core": "^7.23.3", @@ -124,10 +125,10 @@ "@babel/runtime": "^7.24.4", "@chromatic-com/storybook": "^1.3.2", "@emotion/jest": "^11.11.0", + "@playwright/test": "^1.43.1", "@storybook/addon-essentials": "^8.0.8", "@storybook/addon-interactions": "^8.0.8", "@storybook/addon-links": "^8.0.8", - "@storybook/addon-onboarding": "^8.0.8", "@storybook/addon-themes": "^8.0.8", "@storybook/addon-webpack5-compiler-swc": "^1.0.2", "@storybook/blocks": "^8.0.8", diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..ae3007e --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,77 @@ +import { defineConfig, devices } from '@playwright/test'; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + globalSetup: require.resolve('./tests/global-setup'), + testDir: './tests', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:6006/', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + testIdAttribute: 'data-test-id', + }, + expect: { + toHaveScreenshot: { maxDiffPixels: 100 }, + }, + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + + { + name: 'Microsoft Edge', + use: { + channel: 'msedge', + }, + }, + + { + name: 'Google Chrome', + use: { + channel: 'chrome', + }, + }, + ], + + outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + command: 'npm run storybook', + url: 'http://127.0.0.1:6006', + reuseExistingServer: !process.env.CI, + }, +}); diff --git a/tests/components.spec.ts b/tests/components.spec.ts new file mode 100644 index 0000000..aee5f61 --- /dev/null +++ b/tests/components.spec.ts @@ -0,0 +1,34 @@ +import { test, expect } from '@playwright/test' + +const components = [ + { name: 'Alert' }, + { name: 'CaPool' }, + { name: 'CodeEditor' }, + { name: 'Editor' }, + { name: 'Headline' }, + { name: 'Link' }, + { name: 'StatusPill' }, + { name: 'StatusTag' }, + { name: 'Swiper' }, + { name: 'Tabs' }, + { name: 'Tag' }, + { name: 'TileExpand' }, + { name: 'TileToggle' }, + { name: 'Tooltip' }, + { name: 'VersionMark' }, +] + +components.forEach((component) => { + test(`${component.name}`, async ({ page }) => { + await page.goto(`http://localhost:6006/?path=/story/example-${component.name.toLowerCase()}--default`) + + await page.click("button[aria-label='Shortcuts']") + await page.click('a#list-item-F') + + // secure interval for animations + await page.waitForTimeout(5000) + await page.locator('#storybook-preview-iframe').focus() + + await expect(page).toHaveScreenshot({ fullPage: true, omitBackground: true }) + }) +}) diff --git a/tests/components.spec.ts-snapshots/Alert-1-Google-Chrome-darwin.png b/tests/components.spec.ts-snapshots/Alert-1-Google-Chrome-darwin.png new file mode 100644 index 0000000..b3165f2 Binary files /dev/null and b/tests/components.spec.ts-snapshots/Alert-1-Google-Chrome-darwin.png differ diff --git a/tests/components.spec.ts-snapshots/Alert-1-chromium-darwin.png b/tests/components.spec.ts-snapshots/Alert-1-chromium-darwin.png new file mode 100644 index 0000000..0b9197b Binary files /dev/null and b/tests/components.spec.ts-snapshots/Alert-1-chromium-darwin.png differ diff --git a/tests/components.spec.ts-snapshots/CaPool-1-Google-Chrome-darwin.png b/tests/components.spec.ts-snapshots/CaPool-1-Google-Chrome-darwin.png new file mode 100644 index 0000000..b3165f2 Binary files /dev/null and b/tests/components.spec.ts-snapshots/CaPool-1-Google-Chrome-darwin.png differ diff --git a/tests/components.spec.ts-snapshots/CaPool-1-chromium-darwin.png b/tests/components.spec.ts-snapshots/CaPool-1-chromium-darwin.png new file mode 100644 index 0000000..b3165f2 Binary files /dev/null and b/tests/components.spec.ts-snapshots/CaPool-1-chromium-darwin.png differ diff --git a/tests/components.spec.ts-snapshots/CodeEditor-1-chromium-darwin.png b/tests/components.spec.ts-snapshots/CodeEditor-1-chromium-darwin.png new file mode 100644 index 0000000..0b9197b Binary files /dev/null and b/tests/components.spec.ts-snapshots/CodeEditor-1-chromium-darwin.png differ diff --git a/tests/components.spec.ts-snapshots/Editor-1-chromium-darwin.png b/tests/components.spec.ts-snapshots/Editor-1-chromium-darwin.png new file mode 100644 index 0000000..0b9197b Binary files /dev/null and b/tests/components.spec.ts-snapshots/Editor-1-chromium-darwin.png differ diff --git a/tests/components.spec.ts-snapshots/Headline-1-chromium-darwin.png b/tests/components.spec.ts-snapshots/Headline-1-chromium-darwin.png new file mode 100644 index 0000000..0b9197b Binary files /dev/null and b/tests/components.spec.ts-snapshots/Headline-1-chromium-darwin.png differ diff --git a/tests/components.spec.ts-snapshots/Link-1-chromium-darwin.png b/tests/components.spec.ts-snapshots/Link-1-chromium-darwin.png new file mode 100644 index 0000000..0b9197b Binary files /dev/null and b/tests/components.spec.ts-snapshots/Link-1-chromium-darwin.png differ diff --git a/tests/components.spec.ts-snapshots/StatusPill-1-chromium-darwin.png b/tests/components.spec.ts-snapshots/StatusPill-1-chromium-darwin.png new file mode 100644 index 0000000..b3165f2 Binary files /dev/null and b/tests/components.spec.ts-snapshots/StatusPill-1-chromium-darwin.png differ diff --git a/tests/components.spec.ts-snapshots/StatusTag-1-chromium-darwin.png b/tests/components.spec.ts-snapshots/StatusTag-1-chromium-darwin.png new file mode 100644 index 0000000..0b9197b Binary files /dev/null and b/tests/components.spec.ts-snapshots/StatusTag-1-chromium-darwin.png differ diff --git a/tests/components.spec.ts-snapshots/Swiper-1-chromium-darwin.png b/tests/components.spec.ts-snapshots/Swiper-1-chromium-darwin.png new file mode 100644 index 0000000..3c44bf2 Binary files /dev/null and b/tests/components.spec.ts-snapshots/Swiper-1-chromium-darwin.png differ diff --git a/tests/components.spec.ts-snapshots/Tabs-1-chromium-darwin.png b/tests/components.spec.ts-snapshots/Tabs-1-chromium-darwin.png new file mode 100644 index 0000000..b3165f2 Binary files /dev/null and b/tests/components.spec.ts-snapshots/Tabs-1-chromium-darwin.png differ diff --git a/tests/components.spec.ts-snapshots/Tag-1-chromium-darwin.png b/tests/components.spec.ts-snapshots/Tag-1-chromium-darwin.png new file mode 100644 index 0000000..0b9197b Binary files /dev/null and b/tests/components.spec.ts-snapshots/Tag-1-chromium-darwin.png differ diff --git a/tests/components.spec.ts-snapshots/TileExpand-1-chromium-darwin.png b/tests/components.spec.ts-snapshots/TileExpand-1-chromium-darwin.png new file mode 100644 index 0000000..d4953be Binary files /dev/null and b/tests/components.spec.ts-snapshots/TileExpand-1-chromium-darwin.png differ diff --git a/tests/components.spec.ts-snapshots/TileToggle-1-chromium-darwin.png b/tests/components.spec.ts-snapshots/TileToggle-1-chromium-darwin.png new file mode 100644 index 0000000..c7bae8b Binary files /dev/null and b/tests/components.spec.ts-snapshots/TileToggle-1-chromium-darwin.png differ diff --git a/tests/components.spec.ts-snapshots/Tooltip-1-chromium-darwin.png b/tests/components.spec.ts-snapshots/Tooltip-1-chromium-darwin.png new file mode 100644 index 0000000..b3165f2 Binary files /dev/null and b/tests/components.spec.ts-snapshots/Tooltip-1-chromium-darwin.png differ diff --git a/tests/components.spec.ts-snapshots/VersionMark-1-chromium-darwin.png b/tests/components.spec.ts-snapshots/VersionMark-1-chromium-darwin.png new file mode 100644 index 0000000..b3165f2 Binary files /dev/null and b/tests/components.spec.ts-snapshots/VersionMark-1-chromium-darwin.png differ diff --git a/tests/global-setup.ts b/tests/global-setup.ts new file mode 100644 index 0000000..40105eb --- /dev/null +++ b/tests/global-setup.ts @@ -0,0 +1,14 @@ +import { chromium, expect } from '@playwright/test' + +async function globalSetup() { + const browser = await chromium.launch() + const page = await browser.newPage() + + const response = await page.request.get('http://localhost:6006/') + await expect(response).toBeOK() + + await page.context().storageState({ path: 'storageState.json' }) + await browser.close() +} + +export default globalSetup