From 00e66df2d1576712585cc9813233bfbf4824ba8e Mon Sep 17 00:00:00 2001 From: Beppe Catanese Date: Tue, 28 Nov 2023 12:02:48 +0100 Subject: [PATCH] Add E2E testing --- .gitignore | 9 +++- e2e/package-lock.json | 105 ++++++++++++++++++++++++++++++++++++ e2e/package.json | 17 ++++++ e2e/playwright.config.js | 57 ++++++++++++++++++++ e2e/tests/dashboard.spec.js | 22 ++++++++ e2e/tests/home.spec.js | 39 ++++++++++++++ e2e/tests/utils.js | 8 +++ 7 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 e2e/package-lock.json create mode 100644 e2e/package.json create mode 100644 e2e/playwright.config.js create mode 100644 e2e/tests/dashboard.spec.js create mode 100644 e2e/tests/home.spec.js create mode 100644 e2e/tests/utils.js diff --git a/.gitignore b/.gitignore index 821803a..4826d4a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,14 @@ target .idea *.iml .DS_Store -node_modules + +.env +node_modules/ +test-results/ +playwright-report/ +blob-report/ +playwright/.cache/ + *.bat react-app/build diff --git a/e2e/package-lock.json b/e2e/package-lock.json new file mode 100644 index 0000000..b8ef96b --- /dev/null +++ b/e2e/package-lock.json @@ -0,0 +1,105 @@ +{ + "name": "e2e", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "e2e", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "dotenv": "^16.3.1" + }, + "devDependencies": { + "@playwright/test": "^1.40.0", + "@types/node": "^20.10.0" + } + }, + "node_modules/@playwright/test": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.40.0.tgz", + "integrity": "sha512-PdW+kn4eV99iP5gxWNSDQCbhMaDVej+RXL5xr6t04nbKLCBwYtA046t7ofoczHOm8u6c+45hpDKQVZqtqwkeQg==", + "dev": true, + "dependencies": { + "playwright": "1.40.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@types/node": { + "version": "20.10.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.0.tgz", + "integrity": "sha512-D0WfRmU9TQ8I9PFx9Yc+EBHw+vSpIub4IDvQivcp26PtPrdMGAq5SDcpXEo/epqa/DXotVpekHiLNTg3iaKXBQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, + "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/playwright": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.40.0.tgz", + "integrity": "sha512-gyHAgQjiDf1m34Xpwzaqb76KgfzYrhK7iih+2IzcOCoZWr/8ZqmdBw+t0RU85ZmfJMgtgAiNtBQ/KS2325INXw==", + "dev": true, + "dependencies": { + "playwright-core": "1.40.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.40.0.tgz", + "integrity": "sha512-fvKewVJpGeca8t0ipM56jkVSU6Eo0RmFvQ/MaCQNDYm+sdvKkMBBWTE1FdeMqIdumRaXXjZChWHvIzCGM/tA/Q==", + "dev": true, + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + } + } +} diff --git a/e2e/package.json b/e2e/package.json new file mode 100644 index 0000000..0e053e3 --- /dev/null +++ b/e2e/package.json @@ -0,0 +1,17 @@ +{ + "name": "e2e", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": {}, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@playwright/test": "^1.40.0", + "@types/node": "^20.10.0" + }, + "dependencies": { + "dotenv": "^16.3.1" + } +} diff --git a/e2e/playwright.config.js b/e2e/playwright.config.js new file mode 100644 index 0000000..08ec8cf --- /dev/null +++ b/e2e/playwright.config.js @@ -0,0 +1,57 @@ +// @ts-check +const { defineConfig, devices } = require('@playwright/test'); + +require('dotenv').config(); + +/** + * @see https://playwright.dev/docs/test-configuration + */ +module.exports = defineConfig({ + testDir: './tests', + + /* Maximum time one test can run for. */ + timeout: 1 * 60 * 1000, + + expect: { + + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + * + * note: waiting longer on CI + */ + timeout: process.env.CI ? 40 * 1000 : 5 * 1000 + }, + + /* 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 ? 1 : 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: process.env.URL || 'http://localhost:3000', + + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 40 * 1000, + + /* 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'] }, + }, + ], + +}); + diff --git a/e2e/tests/dashboard.spec.js b/e2e/tests/dashboard.spec.js new file mode 100644 index 0000000..5471ee7 --- /dev/null +++ b/e2e/tests/dashboard.spec.js @@ -0,0 +1,22 @@ +// @ts-check +const { test, expect } = require('@playwright/test'); +const utils = require('./utils'); + +test('Dashboard', async ({ page }) => { + await page.goto('/'); + await expect(page).toHaveTitle(/AfP MyPlatform/); + + await page.goto('/login'); + await expect(page.locator('text="Login"')).toBeVisible(); + // perform login + await page.fill('input[name="username"]', utils.USERNAME); + await page.fill('input[name="password"]', "123"); + await page.getByRole('button', { name: 'Submit' }).click(); + + await expect(page.locator('text="Dashboard"')).toBeVisible(); + await expect(page.locator('text="Status"')).toBeVisible(); + + await page.goto('/products'); + await expect(page.locator('text="My Products"')).toBeVisible(); +}); + diff --git a/e2e/tests/home.spec.js b/e2e/tests/home.spec.js new file mode 100644 index 0000000..14a774d --- /dev/null +++ b/e2e/tests/home.spec.js @@ -0,0 +1,39 @@ +// @ts-check +const { test, expect } = require('@playwright/test'); + +test('Homepage', async ({ page }) => { + await page.goto('/'); + await expect(page).toHaveTitle(/AfP MyPlatform/); +}); + +test('Goto Signup', async ({ page }) => { + await page.goto('/'); + await expect(page).toHaveTitle(/AfP MyPlatform/); + + await page.goto('/signup'); + await expect(page.locator('text="Create an account"')).toBeVisible(); +}); + +test('Goto Login', async ({ page }) => { + await page.goto('/'); + await expect(page).toHaveTitle(/AfP MyPlatform/); + + await page.goto('/login'); + await expect(page.locator('text="Login"')).toBeVisible(); +}); + +test('Invalid Login', async ({ page }) => { + await page.goto('/'); + await expect(page).toHaveTitle(/AfP MyPlatform/); + + await page.goto('/login'); + await expect(page.locator('text="Login"')).toBeVisible(); + + await page.fill('input[name="username"]', "Unknown"); + await page.fill('input[name="password"]', "123"); + await page.getByRole('button', { name: 'Submit' }).click(); + + await expect(page.locator('text="Invalid credentials"')).toBeVisible(); + +}); + diff --git a/e2e/tests/utils.js b/e2e/tests/utils.js new file mode 100644 index 0000000..63ef082 --- /dev/null +++ b/e2e/tests/utils.js @@ -0,0 +1,8 @@ +const dotenv = require('dotenv'); + +dotenv.config(); + +module.exports = { + // valid AccountHolder id + USERNAME: process.env.AFP_USERNAME, +}; \ No newline at end of file