diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 0000000..3b632cd --- /dev/null +++ b/.github/workflows/playwright.yml @@ -0,0 +1,27 @@ +name: End-to-end Tests +on: + push: + branches: [main, develop] + pull_request: + branches: [main, develop] +jobs: + test: + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: '14.x' + - 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@v2 + if: always() + with: + name: playwright-report + path: playwright-report/ + retention-days: 5 diff --git a/.gitignore b/.gitignore index e8206f8..722af60 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,7 @@ yarn-error.log* yarn.lock #eslint -.eslintrc.json \ No newline at end of file +.eslintrc.json +/test-results/ +/playwright-report/ +/playwright/.cache/ diff --git a/e2e-tests/default.spec.js b/e2e-tests/default.spec.js new file mode 100644 index 0000000..0cba989 --- /dev/null +++ b/e2e-tests/default.spec.js @@ -0,0 +1,13 @@ +// @ts-check +const { test, expect } = require('@playwright/test'); + +test.beforeEach(async ({ page }) => { + await page.goto('http://localhost:3000'); + }); + +test.describe('Basic test', () => { + test('should show the title', async ({ page }) => { + const title = page.locator('title'); + await expect(title).toHaveText('React Devs Kenya'); + }); +}); \ No newline at end of file diff --git a/package.json b/package.json index e8d00cb..492c012 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "dev": "next dev", "build": "next build", "start": "next start", - "lint": "next lint" + "lint": "next lint", + "test": "playwright test" }, "dependencies": { "next": "12.1.6", @@ -14,10 +15,11 @@ "react-dom": "18.1.0" }, "devDependencies": { - "autoprefixer": "^10.4.7", + "@playwright/test": "1.22.2", + "autoprefixer": "10.4.7", "eslint": "8.17.0", "eslint-config-next": "12.1.6", - "postcss": "^8.4.14", - "tailwindcss": "^3.1.2" + "postcss": "8.4.14", + "tailwindcss": "3.1.2" } } diff --git a/playwright.config.js b/playwright.config.js new file mode 100644 index 0000000..8adb706 --- /dev/null +++ b/playwright.config.js @@ -0,0 +1,116 @@ +// @ts-check +const { devices } = require('@playwright/test'); + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + + +/** + * @see https://playwright.dev/docs/test-configuration + * @type {import('@playwright/test').PlaywrightTestConfig} + */ +const config = { + testDir: './e2e-tests', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* 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: { + /* 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:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + /* Run the dev server and wait for it to be fully up before running the tests */ + webServer: { + command: 'npm run dev', + port: 3000, + timeout: 120 * 1000, + reuseExistingServer: !process.env.CI, + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'], + }, + }, + + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'], + }, + }, + + { + name: 'webkit', + use: { + ...devices['Desktop Safari'], + }, + }, + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + // webServer: { + // command: 'npm run start', + // port: 3000, + // }, +}; + +module.exports = config;