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 aef72d0..dcf9800 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,6 @@ coverage test-results/ playwright-report/ +blob-report/ +e2e/.cache/ + diff --git a/e2e/login.spec.ts b/e2e/login.spec.ts new file mode 100644 index 0000000..b5d1b9e --- /dev/null +++ b/e2e/login.spec.ts @@ -0,0 +1,52 @@ +import { test, expect } from '@playwright/test' + +test('visits the app login page and login', async ({ page }) => { + // Navigate to the target page + await page.goto('/') + + // Check for the presence of "Hi there! 👋" + const hiThereText = page.locator('div.text-h5') + await expect(hiThereText).toHaveText('Hi there! 👋') + + // Check for the presence of the logo + const logo = page.locator('img.logo') + await expect(logo).toBeVisible() + + // Check for the presence of the "HangTime" text + const hangTimeText = page.locator('h2.text-h4') + await expect(hangTimeText).toHaveText('HangTime') + + // Check for the "Hangboard Training App" subtitle + const subtitleText = page.locator('h1.text-subtitle-2') + await expect(subtitleText).toHaveText('Hangboard Training App') + + // Check for the presence of the login buttons + const facebookButton = page.locator('button:has-text("Sign in with Facebook")') + const googleButton = page.locator('button:has-text("Sign in with Google")') + const appleButton = page.locator('button:has-text("Sign in with Apple")') + await expect(facebookButton).toBeVisible() + await expect(googleButton).toBeVisible() + await expect(appleButton).toBeVisible() + + // Check for the presence of the email input field + const emailInput = page.getByLabel('E-mail', { exact: true }) + await expect(emailInput).toBeVisible() + + // Check for the presence of the password input field + const passwordInput = page.getByLabel('Password', { exact: true }) + await expect(passwordInput).toBeVisible() + + // Check for the presence of the login button + const loginButton = page.getByRole('button', { name: 'Login' }) + await expect(loginButton).toBeVisible() + await expect(loginButton).toBeEnabled() + + // Perform login with dummy account + await emailInput.fill('mail@stevie-ray.nl') + await passwordInput.fill('8Ty>g{Q"F!#4') + await loginButton.click() + + // Check if login was successful + const workoutTab = page.getByText('My Workouts') + await expect(workoutTab).toBeVisible() +}) diff --git a/e2e/vue.spec.ts b/e2e/vue.spec.ts deleted file mode 100644 index 3e5a3d0..0000000 --- a/e2e/vue.spec.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { test, expect } from '@playwright/test'; - -// See here how to get started: -// https://playwright.dev/docs/intro -test('visits the app root url', async ({ page }) => { - await page.goto('/'); - await expect(page.locator('div.greetings > h1')).toHaveText('You did it!'); -}) diff --git a/playwright.config.ts b/playwright.config.ts index 92075cc..edb2da3 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -1,4 +1,3 @@ -import process from 'node:process' import { defineConfig, devices } from '@playwright/test' /** @@ -19,8 +18,10 @@ export default defineConfig({ * Maximum time expect() should wait for the condition to be met. * For example in `await expect(locator).toHaveText();` */ - timeout: 5000 + timeout: 5 * 1000 }, + /* Run tests in files in parallel */ + fullyParallel: true, /* Fail the build on CI if you accidentally left test.only in the source code. */ forbidOnly: !!process.env.CI, /* Retry on CI only */ @@ -33,8 +34,9 @@ export default defineConfig({ use: { /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: 'http://localhost:5173', + baseURL: 'http://localhost:3000', /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ trace: 'on-first-retry', @@ -47,49 +49,37 @@ export default defineConfig({ projects: [ { name: 'chromium', - use: { - ...devices['Desktop Chrome'] - } - }, - { - name: 'firefox', - use: { - ...devices['Desktop Firefox'] - } - }, - { - name: 'webkit', - use: { - ...devices['Desktop Safari'] - } + use: { ...devices['Desktop Chrome'] } } + // { + // name: 'firefox', + // use: { ...devices['Desktop Firefox'] } + // }, + + // { + // name: 'webkit', + // use: { ...devices['Desktop Safari'] } + // } + /* Test against mobile viewports. */ // { // name: 'Mobile Chrome', - // use: { - // ...devices['Pixel 5'], - // }, + // use: { ...devices['Pixel 5'] }, // }, // { // name: 'Mobile Safari', - // use: { - // ...devices['iPhone 12'], - // }, + // use: { ...devices['iPhone 12'] }, // }, /* Test against branded browsers. */ // { // name: 'Microsoft Edge', - // use: { - // channel: 'msedge', - // }, + // use: { ...devices['Desktop Edge'], channel: 'msedge' }, // }, // { // name: 'Google Chrome', - // use: { - // channel: 'chrome', - // }, + // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, // }, ], @@ -103,8 +93,8 @@ export default defineConfig({ * Use the preview server on CI for more realistic testing. * Playwright will re-use the local server if there is already a dev-server running. */ - command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', - port: 5173, + command: process.env.CI ? 'vite preview --port 3000' : 'vite dev', + port: 3000, reuseExistingServer: !process.env.CI } }) diff --git a/vite.config.ts b/vite.config.ts index 6f01955..9bd0973 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -20,10 +20,10 @@ export default defineConfig({ }), // https://github.com/vuetifyjs/vuetify-loader/tree/master/packages/vite-plugin vuetify({ - autoImport: true, - styles: { - configFile: 'src/plugins/vuetify/settings.scss' - } + autoImport: true + // styles: { + // configFile: 'src/plugins/vuetify/settings.scss' + // } }), VitePWA({ registerType: 'autoUpdate',