diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index d96df75..044aa0d 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -14,15 +14,17 @@ jobs: with: node-version: '20' # - uses: superfly/flyctl-actions/setup-flyctl@master - - name: Install dependencies for frontend - working-directory: ./frontend + - name: Install dependencies run: npm ci + - name: Install dependencies for frontend + run: npm run install:frontend - name: Check style for frontend - working-directory: ./frontend - run: npm run lint + run: npm run lint:frontend - name: Build for frontend - working-directory: ./frontend - run: npm run build + run: npm run build:frontend - name: Test for frontend - working-directory: ./frontend - run: npm run test + run: npm run test:frontend + - name: Install Playwright Browsers + run: npx playwright install --with-deps + - name: e2e tests + run: npm run test:e2e diff --git a/.gitignore b/.gitignore index 5de245c..4c19665 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,8 @@ yarn-error.log* # OS generated files .DS_Store -Thumbs.db \ No newline at end of file +Thumbs.db +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/e2e-tests/homepage.spec.js b/e2e-tests/homepage.spec.js new file mode 100644 index 0000000..80ad24f --- /dev/null +++ b/e2e-tests/homepage.spec.js @@ -0,0 +1,8 @@ +// @ts-check +const { test, expect } = require('@playwright/test'); + +test('has anecdotes title', async ({ page }) => { + await page.goto(''); + + await expect(page.getByText('Anecdotes')).toBeVisible(); +}); diff --git a/package-lock.json b/package-lock.json index 5fa7181..c29472c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,9 +14,35 @@ "uuid": "^10.0.0" }, "devDependencies": { + "@playwright/test": "^1.47.1", + "@types/node": "^22.5.5", "nodemon": "^3.1.4" } }, + "node_modules/@playwright/test": { + "version": "1.47.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.1.tgz", + "integrity": "sha512-dbWpcNQZ5nj16m+A5UNScYx7HX5trIy7g4phrcitn+Nk83S32EBX/CLU4hiF4RGKX/yRc93AAqtfaXB7JWBd4Q==", + "dev": true, + "dependencies": { + "playwright": "1.47.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@types/node": { + "version": "22.5.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.5.tgz", + "integrity": "sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==", + "dev": true, + "dependencies": { + "undici-types": "~6.19.2" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -779,6 +805,50 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/playwright": { + "version": "1.47.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.1.tgz", + "integrity": "sha512-SUEKi6947IqYbKxRiqnbUobVZY4bF1uu+ZnZNJX9DfU1tlf2UhWfvVjLf01pQx9URsOr18bFVUKXmanYWhbfkw==", + "dev": true, + "dependencies": { + "playwright-core": "1.47.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.47.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.1.tgz", + "integrity": "sha512-i1iyJdLftqtt51mEk6AhYFaAJCDx0xQ/O5NU8EKaWFgMjItPVma542Nh/Aq8aLCjIJSzjaiEQGW/nyqLkGF1OQ==", + "dev": true, + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -1048,6 +1118,12 @@ "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", "dev": true }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", diff --git a/package.json b/package.json index 77bc434..15ca60e 100644 --- a/package.json +++ b/package.json @@ -6,9 +6,11 @@ "start": "node src/app.js", "dev": "nodemon src/app.js", "start:frontend": "cd frontend && npm run dev", - "install:frontend": "cd frontend && npm install", + "install:frontend": "cd frontend && npm ci", + "lint:frontend": "cd frontend && npm run lint", "build:frontend": "cd frontend && npm run build", - "test:frontend": "cd frontend && npm test" + "test:frontend": "cd frontend && npm test", + "test:e2e": "playwright test" }, "keywords": [], "author": "", @@ -20,6 +22,8 @@ "uuid": "^10.0.0" }, "devDependencies": { + "@playwright/test": "^1.47.1", + "@types/node": "^22.5.5", "nodemon": "^3.1.4" } } diff --git a/playwright.config.js b/playwright.config.js new file mode 100644 index 0000000..54fc8aa --- /dev/null +++ b/playwright.config.js @@ -0,0 +1,84 @@ +// @ts-check +const { defineConfig, devices } = require('@playwright/test'); + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config({ path: path.resolve(__dirname, '.env') }); + +/** + * @see https://playwright.dev/docs/test-configuration + */ +module.exports = defineConfig({ + testDir: './e2e-tests', + /* Run tests in files in parallel */ + fullyParallel: false, + /* 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', + webServer: { + command: 'npm run start', + url: 'http://127.0.0.1:3000', + timeout: 120 * 1000, + reuseExistingServer: !process.env.CI, + }, + /* 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://127.0.0.1:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + /* 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: { ...devices['Desktop Edge'], channel: 'msedge' }, + // }, + // { + // name: 'Google Chrome', + // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, + // }, + ], + + /* Run your local dev server before starting the tests */ + // webServer: { + // command: 'npm run start', + // url: 'http://127.0.0.1:3000', + // reuseExistingServer: !process.env.CI, + // }, +});