From 17c79235dcdccbbe6c7fe28cd06cad25fe5df132 Mon Sep 17 00:00:00 2001 From: Osundwa Jeff Date: Fri, 15 Dec 2023 04:36:34 +0300 Subject: [PATCH] Playwright testing (#13) * Initial set up * Updated testing scripts * Update playwright version(1.40) * Updated testing scripts * Fixes on testing scripts --- playwright/ci-test/.envrc | 1 + playwright/ci-test/.gitignore | 8 ++ playwright/ci-test/README.md | 98 +++++++++++++++++++ playwright/ci-test/base-url.sh | 4 + playwright/ci-test/create-auth.sh | 35 +++++++ playwright/ci-test/nodesource-install.sh | 23 +++++ playwright/ci-test/package.json | 20 ++++ playwright/ci-test/playwright-path.sh | 83 ++++++++++++++++ playwright/ci-test/playwright.config.ts | 86 ++++++++++++++++ playwright/ci-test/record-test.sh | 44 +++++++++ playwright/ci-test/run-tests.sh | 14 +++ playwright/ci-test/shell.nix | 28 ++++++ playwright/ci-test/tests/auth.setup.ts | 38 +++++++ playwright/ci-test/tests/landingPage.spec.ts | 18 ++++ playwright/staging-tests/.envrc | 1 + playwright/staging-tests/.gitignore | 10 ++ playwright/staging-tests/README.md | 72 ++++++++++++++ playwright/staging-tests/base-url.sh | 4 + playwright/staging-tests/create-auth.sh | 35 +++++++ .../staging-tests/nodesource-install.sh | 23 +++++ playwright/staging-tests/package-lock.json | 91 +++++++++++++++++ playwright/staging-tests/package.json | 14 +++ playwright/staging-tests/playwright-path.sh | 83 ++++++++++++++++ playwright/staging-tests/playwright.config.js | 83 ++++++++++++++++ playwright/staging-tests/record-test.sh | 44 +++++++++ playwright/staging-tests/run-tests.sh | 14 +++ playwright/staging-tests/shell.nix | 28 ++++++ playwright/staging-tests/tests/test.spec.ts | 18 ++++ 28 files changed, 1020 insertions(+) create mode 100644 playwright/ci-test/.envrc create mode 100644 playwright/ci-test/.gitignore create mode 100644 playwright/ci-test/README.md create mode 100755 playwright/ci-test/base-url.sh create mode 100755 playwright/ci-test/create-auth.sh create mode 100755 playwright/ci-test/nodesource-install.sh create mode 100644 playwright/ci-test/package.json create mode 100755 playwright/ci-test/playwright-path.sh create mode 100644 playwright/ci-test/playwright.config.ts create mode 100755 playwright/ci-test/record-test.sh create mode 100755 playwright/ci-test/run-tests.sh create mode 100644 playwright/ci-test/shell.nix create mode 100644 playwright/ci-test/tests/auth.setup.ts create mode 100644 playwright/ci-test/tests/landingPage.spec.ts create mode 100644 playwright/staging-tests/.envrc create mode 100644 playwright/staging-tests/.gitignore create mode 100644 playwright/staging-tests/README.md create mode 100755 playwright/staging-tests/base-url.sh create mode 100755 playwright/staging-tests/create-auth.sh create mode 100755 playwright/staging-tests/nodesource-install.sh create mode 100644 playwright/staging-tests/package-lock.json create mode 100644 playwright/staging-tests/package.json create mode 100755 playwright/staging-tests/playwright-path.sh create mode 100644 playwright/staging-tests/playwright.config.js create mode 100755 playwright/staging-tests/record-test.sh create mode 100755 playwright/staging-tests/run-tests.sh create mode 100644 playwright/staging-tests/shell.nix create mode 100644 playwright/staging-tests/tests/test.spec.ts diff --git a/playwright/ci-test/.envrc b/playwright/ci-test/.envrc new file mode 100644 index 0000000..1d953f4 --- /dev/null +++ b/playwright/ci-test/.envrc @@ -0,0 +1 @@ +use nix diff --git a/playwright/ci-test/.gitignore b/playwright/ci-test/.gitignore new file mode 100644 index 0000000..e0258ff --- /dev/null +++ b/playwright/ci-test/.gitignore @@ -0,0 +1,8 @@ +node_modules/ +/test-results/ +/playwright-report/ +/playwright/.cache/ +states +package-lock.json +playwright-results +*auth.json \ No newline at end of file diff --git a/playwright/ci-test/README.md b/playwright/ci-test/README.md new file mode 100644 index 0000000..42a38f1 --- /dev/null +++ b/playwright/ci-test/README.md @@ -0,0 +1,98 @@ +# Validation Tests + +These tests are designed to run from GitHub action or CI. + +They are intended to verify basic functionality is working during the building of the application(Just before deployment to staging or production). + +## Essential reading: + +* [https://playwright.dev/](https://playwright.dev/) +* [https://playwright.dev/docs/ci-intro](https://playwright.dev/docs/ci-intro) +* [https://direnv.net/docs/installation.html](https://direnv.net/docs/installation.html) + +## Setting up your environment + +Before you can run, you need to set up your environment. + +Running these tests requires playwright set up on your local machine, as well as NodeJS. + +### NixOS + +If you are a NixOS user, you can set up direnv and then cd into this directory in your shell. + +When you do so the first time, you will be prompted to allow direnv which you can do using this command: + +```bash +direnv allow +``` + +>  This may take a while the first time as NixOS builds you a sandbox environment. + +### Non-NixOS + +For a non-NixOS user(Debian/Ubuntu) set up your environment by the following commands: + +```bash +npm install +``` + +To install playwright browsers with OS-level dependencies use: + +```bash +npx playwright install --with-deps chromium +``` + +**NOTE:** This only works with Debian/Ubuntu as they receive official support from playwright. It will also request your master password to install the dependencies. + +## Recording a test + +There is a bash helper script that will let you quickly create a new test: + +``` +Usage: ./record-test.sh TESTNAME +e.g. ./record-test.sh mytest +will write a new test to tests/mytest.spec.ts +Do not use spaces in your test name. +Test files MUST END in .spec.ts + +After recording your test, close the test browser. +You can then run your test by doing: +./run-tests.sh +``` + +>  The first time you record a test, it will store your session credentials in a file ending in ``auth.json``. This file should **NEVER** be committed to git / shared publicly. There is a gitignore rule to ensure this. + +## Running a test + +By default, this will run in `headless` mode just as it is in CI. + +```bash +./run-tests.sh +``` + +**NOTE:** To run it in `UI` mode, add the `--ui` tag to the script. + +```bash +$PLAYWRIGHT \ + test \ + --ui \ + --project chromium +``` + +## Adding a CI test + +To add tests for CI, use the recorded tests then modify it for CI. + +The tests can be modified to include time-outs, and waiting for events/actions etc. For more look go through [playwright's documentation](https://playwright.dev/docs/writing-tests). + +An example of a line-recorded test would look like: + +```typescript +await page.getByRole('img', { name: 'image' }).click(); +``` + +For the CI the line could be modified and turned into an assertion using `expect` to test if the specific element is visible. + +```typescript +await expect(page.getByRole('img', { name: 'image' })).toBeVisible(); +``` diff --git a/playwright/ci-test/base-url.sh b/playwright/ci-test/base-url.sh new file mode 100755 index 0000000..808ac7d --- /dev/null +++ b/playwright/ci-test/base-url.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +echo "Setting BASE_URL for test site" +BASE_URL=http://localhost:61100 diff --git a/playwright/ci-test/create-auth.sh b/playwright/ci-test/create-auth.sh new file mode 100755 index 0000000..386a047 --- /dev/null +++ b/playwright/ci-test/create-auth.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +source base-url.sh + +source playwright-path.sh + +echo "This script will write a new test to tests/deleteme.spec.ts" +echo "then delete it, leaving only the auth config." +echo "" +echo "When the playwright browser opens, log in to the site then exit." +echo "After recording your test, close the test browser." +echo "Recording auth token to auth.json" + +# File exists and write permission granted to user +# show prompt +echo "Continue? y/n" +read ANSWER +case $ANSWER in + [yY] ) echo "Writing auth.json" ;; + [nN] ) echo "Cancelled."; exit ;; +esac + +$PLAYWRIGHT \ + codegen \ + --target playwright-test \ + --save-storage=auth.json \ + -o tests/deleteme.spec.ts \ + $BASE_URL + +# We are only interested in auth.json +rm tests/deleteme.spec.ts + +echo "Auth file creation completed." +echo "You can then run your tests by doing e.g.:" +echo "playwright test --project chromium" diff --git a/playwright/ci-test/nodesource-install.sh b/playwright/ci-test/nodesource-install.sh new file mode 100755 index 0000000..eb2ef0f --- /dev/null +++ b/playwright/ci-test/nodesource-install.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +echo "NodeJS will be installed if not present" +echo "sudo password will be required" + +USES_APT=$(which apt | grep -w "apt" | wc -l) +USES_RPM=$(which rpm | grep -w "rpm" | wc -l) + +if [ $USES_APT -eq 1 ]; then + curl -SLO https://deb.nodesource.com/nsolid_setup_deb.sh + sudo chmod 500 nsolid_setup_deb.sh + sudo ./nsolid_setup_deb.sh 20 + sudo apt-get install nodejs -y + +elif [ $USES_RPM -eq 1 ]; then + curl -SLO https://rpm.nodesource.com/nsolid_setup_rpm.sh + sudo chmod 500 nsolid_setup_rpm.sh + sudo ./nsolid_setup_rpm.sh 20 + sudo yum install nodejs -y --setopt=nodesource-nodejs.module_hotfixes=1 +fi + +echo "Done" +echo "" diff --git a/playwright/ci-test/package.json b/playwright/ci-test/package.json new file mode 100644 index 0000000..b0c259c --- /dev/null +++ b/playwright/ci-test/package.json @@ -0,0 +1,20 @@ +{ + "name": "ci-test", + "version": "1.0.0", + "description": "", + "main": "index.js", + "directories": { + "test": "tests" + }, + "scripts": {}, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@playwright/test": "^1.39.0", + "@types/node": "^20.8.9" + }, + "dependencies": { + "playwright": "^1.39.0" + } +} diff --git a/playwright/ci-test/playwright-path.sh b/playwright/ci-test/playwright-path.sh new file mode 100755 index 0000000..41a24a0 --- /dev/null +++ b/playwright/ci-test/playwright-path.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash + +echo "This script will discover the path to your playwright install" +echo "If you are not in a NixOS environment and it is not installed," +echo "playwright will be installed." +echo "" +echo "At the end of calling this script , you should have a PLAYWRIGHT" +echo "" + +# Are we on nixos or a distro with Nix installed for packages +# Y + # Are we in direnv? + # Y: should all be set up + # N: run nix-shell +#N + # Are we in a deb based distro? + # Are we in an rpm based distro? + # Are we on macOS? + # Are we in windows? + +HAS_PLAYWRIGHT=$(which playwright 2> /dev/null | grep -v "which: no" | wc -l) +PLAYWRIGHT="playwright" +if [ $HAS_PLAYWRIGHT -eq 0 ]; then + PLAYWRIGHT="npx playwright" + + # check if OS is a deb based distro and uses apt + USES_APT=$(which apt 2> /dev/null | grep -w "apt" | wc -l) + # check if OS is an rpm-based distro + USES_RPM=$(which rpm | grep -w "rpm" | wc -l) + + if [ $USES_APT -eq 1 ]; then + # check if nodejs is installed + HAS_NODEJS=$(which node | grep -w "node" | wc -l) + + # if nodejs is present then + if [ $HAS_NODEJS -eq 0 ]; then + source nodesource-install.sh + fi + + # check if npm is present + HAS_NPM=$(which npm | grep -w "npm" | wc -l) + + if [ $HAS_NPM -eq 1 ]; then + NPM="npm" + PLAYWRIGHT_INSTALL=$($NPM ls --depth 1 playwright | grep -w "@playwright/test" | wc -l) + + if [ $PLAYWRIGHT_INSTALL -eq 0 ]; then + $NPM install -D @playwright/test@latest + $NPM ci + $PLAYWRIGHT install --with-deps chromium + fi + + fi + + elif [ $USES_RPM -eq 1 ]; then + + # check if nodejs is installed + HAS_NODEJS=$(which node | grep -w "node" | wc -l) + + # if nodejs is present then + if [ $HAS_NODEJS -eq 0 ]; then + source nodesource-install.sh + fi + + # check if npm is present + HAS_NPM=$(which npm | grep -w "npm" | wc -l) + + if [ $HAS_NPM -eq 1 ]; then + NPM="npm" + PLAYWRIGHT_INSTALL=$($NPM ls --depth 1 playwright | grep -w "@playwright/test" | wc -l) + + if [ $PLAYWRIGHT_INSTALL -eq 0 ]; then + $NPM install -D @playwright/test@latest + $NPM ci + $PLAYWRIGHT install + fi + + fi + fi +fi + +echo "Done." +echo "" diff --git a/playwright/ci-test/playwright.config.ts b/playwright/ci-test/playwright.config.ts new file mode 100644 index 0000000..f1f554f --- /dev/null +++ b/playwright/ci-test/playwright.config.ts @@ -0,0 +1,86 @@ + +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({ + testDir: './tests', + /* Run tests in files in parallel */ + timeout: 30 * 1000, + 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://127.0.0.1:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + baseURL: process.env.STAGING === '1' ? 'http://example.com' : 'http://localhost:61100/' + }, + + /* Configure projects for major browsers */ + projects: [ + { name: 'setup', testMatch: /.*\.setup\.ts/ }, + { + name: 'chromium', + use: { ...devices['Desktop Chrome'], + // Use prepared auth state. + storageState: 'auth.json', + }, + dependencies: ['setup'], + }, + // + // { + // 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, + // }, +}); diff --git a/playwright/ci-test/record-test.sh b/playwright/ci-test/record-test.sh new file mode 100755 index 0000000..6b4fb74 --- /dev/null +++ b/playwright/ci-test/record-test.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +source base-url.sh + +source playwright-path.sh + +if [ -z "$1" ] +then + echo "Usage: $0 TESTNAME" + echo "e.g. $0 mytest" + echo "will write a new test to tests/mytest.spec.ts" + echo "Do not use spaces in your test name." + echo "" + echo "After recording your test, close the test browser." + echo "You can then run your test by doing:" + echo "npx playwright test tests/mytest.spec.py" + exit +else + echo "Recording test to tests/${1}" +fi + +if [ -w "tests/${1}.spec.ts" ]; then + # File exists and write permission granted to user + # show prompt + echo "File tests/${1}.spec.ts exists. Overwrite? y/n" + read ANSWER + case $ANSWER in + [yY] ) echo "Writing recorded test to tests/${1}.spec.ts" ;; + [nN] ) echo "Cancelled."; exit ;; + esac +fi +TESTNAME=$1 + +$PLAYWRIGHT \ + codegen \ + --target playwright-test \ + --load-storage=auth.json \ + -o tests/$1.spec.ts \ + $BASE_URL + + +echo "Test recording completed." +echo "You can then run your test by doing:" +echo "./run-tests.sh" diff --git a/playwright/ci-test/run-tests.sh b/playwright/ci-test/run-tests.sh new file mode 100755 index 0000000..5ff10ab --- /dev/null +++ b/playwright/ci-test/run-tests.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +source playwright-path.sh + +echo "This script will run the tests defined in tests/" +echo "Before running the tests you need to create the auth config" +echo "" + +$PLAYWRIGHT \ + test \ + --ui \ + --project chromium + +echo "--done--" diff --git a/playwright/ci-test/shell.nix b/playwright/ci-test/shell.nix new file mode 100644 index 0000000..595c145 --- /dev/null +++ b/playwright/ci-test/shell.nix @@ -0,0 +1,28 @@ +let + # + # Note that I am using a snapshot from NixOS unstable here + # so that we can use a more bleeding edge version which includes the test --ui . + # If you want use a different version, go to nix packages search, and find the + # github hash of the version you want to be using, then replace in the URL below. + # + nixpkgs = builtins.fetchTarball "https://github.com/NixOS/nixpkgs/archive/4059c4f71b3a7339261c0183e365fd8016f24bdb.tar.gz"; + pkgs = import nixpkgs { config = { }; overlays = [ ]; }; +in +with pkgs; +mkShell { + buildInputs = [ + nodejs + playwright-test + # python311Packages.playwright + # python311Packages.pytest + ]; + + PLAYWRIGHT_BROWSERS_PATH="${pkgs.playwright-driver.browsers}"; + + shellHook = '' + # Remove playwright from node_modules, so it will be taken from playwright-test + rm node_modules/@playwright/ -R + export PLAYWRIGHT_BROWSERS_PATH=${pkgs.playwright-driver.browsers} + export PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS=true + ''; +} diff --git a/playwright/ci-test/tests/auth.setup.ts b/playwright/ci-test/tests/auth.setup.ts new file mode 100644 index 0000000..0f5ead4 --- /dev/null +++ b/playwright/ci-test/tests/auth.setup.ts @@ -0,0 +1,38 @@ +import { test as setup, expect } from '@playwright/test'; + +let url = '/'; + +let user_email = 'admin@example.com'; +let password = 'admin'; +const authFile = 'auth.json'; + + +setup.describe('login', () => { + + setup('login', async ({page}) => { + + await page.goto(url); + + const buttonSelector = 'LOGIN'; + + await page.waitForSelector(buttonSelector, {timeout: 2000}); + + const initialURL = page.url(); + + await page.click(buttonSelector); + + await page.waitForURL('**/login/'); + + await expect(page.getByRole('heading', { name: 'Login' })).toBeVisible(); + + await page.getByPlaceholder('E-mail address').fill(user_email); + + await page.getByPlaceholder('Password').fill(password); + + await page.getByRole('button', { name: 'LOGIN' }).click(); + + await page.context().storageState({ path: authFile }); + + }); + +}); diff --git a/playwright/ci-test/tests/landingPage.spec.ts b/playwright/ci-test/tests/landingPage.spec.ts new file mode 100644 index 0000000..83b3eb0 --- /dev/null +++ b/playwright/ci-test/tests/landingPage.spec.ts @@ -0,0 +1,18 @@ +import { test, expect } from '@playwright/test'; + +let url = '/'; + + +test.describe('navigation', () => { + test.beforeEach(async ({ page }) => { + // Go to the starting url before each test. + await page.goto(url); + }); + + test('has title', async ({ page }) => { + await page.waitForSelector('.landing-page-banner-text-header', { timeout: 2000 }); + await expect(page.locator('div.landing-page-banner-text-header')).toHaveText(); + }) + test('navigates', async ({page}) => { + }); +}); diff --git a/playwright/staging-tests/.envrc b/playwright/staging-tests/.envrc new file mode 100644 index 0000000..1d953f4 --- /dev/null +++ b/playwright/staging-tests/.envrc @@ -0,0 +1 @@ +use nix diff --git a/playwright/staging-tests/.gitignore b/playwright/staging-tests/.gitignore new file mode 100644 index 0000000..af81d4c --- /dev/null +++ b/playwright/staging-tests/.gitignore @@ -0,0 +1,10 @@ +node_modules/ +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ +*auth.json +.env +.direnv/ +/test-results/ +__pycache__ diff --git a/playwright/staging-tests/README.md b/playwright/staging-tests/README.md new file mode 100644 index 0000000..ac0de06 --- /dev/null +++ b/playwright/staging-tests/README.md @@ -0,0 +1,72 @@ +# Validation Tests + +These tests are designed to run from your local machine (i.e. not from a GitHub action or CI). +The are intended to verify basic functionality is working after a deployment is made to staging, and prior to deployment to production. + +## Essential reading: + +* https://playwright.dev/ +* https://direnv.net/docs/installation.html + +## Setting up your environment + +Before you can run or record tests, you need to set up your environment. + +Running these tests require playwright set up on your local machine, as well as NodeJS. + +**NixOS** + +If you are a NixOS user, you can set up direnv and then cd into this directory in your shell. + +When you do so the first time, you will be prompted to allow direnv which you can do using this command: + + +``` +direnv allow +``` + +>  This may take a while the first time as NixOS builds you a sandbox environment. + +**NON-NixOS** + +For a non-NixOS user(Debian/Ubuntu) set up your environment by the following commands: + +```bash +npm install +``` + +To install playwright browsers with OS-level dependencies use: + + +```bash +npm playwright install --with-deps chromium +``` + +**NOTE:** This only works with Debian/Ubuntu as they recieve official support from playwright. It will also request your master password to install the dependencies. + +## Recording a test + +There is a bash helper script that will let you quickly create a new test: + +``` +Usage: ./record-test.sh TESTNAME +e.g. ./record-test.sh mytest +will write a new test to tests/mytest.spec.ts +Do not use spaces in your test name. +Test files MUST END in .spec.ts + +After recording your test, close the test browser. +You can then run your test by doing: +./run-tests.sh +``` + + +>  The first time you record a test, it will store your session credentials in a file ending in ``auth.json``. This file should **NEVER** be committed to git / shared publicly. There is a gitignore rule to ensure this. + +## Running a test + + +``` +./run-tests.sh +``` + diff --git a/playwright/staging-tests/base-url.sh b/playwright/staging-tests/base-url.sh new file mode 100755 index 0000000..2b3082e --- /dev/null +++ b/playwright/staging-tests/base-url.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +echo "Setting BASE_URL for test site" +BASE_URL=https://example.com diff --git a/playwright/staging-tests/create-auth.sh b/playwright/staging-tests/create-auth.sh new file mode 100755 index 0000000..386a047 --- /dev/null +++ b/playwright/staging-tests/create-auth.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +source base-url.sh + +source playwright-path.sh + +echo "This script will write a new test to tests/deleteme.spec.ts" +echo "then delete it, leaving only the auth config." +echo "" +echo "When the playwright browser opens, log in to the site then exit." +echo "After recording your test, close the test browser." +echo "Recording auth token to auth.json" + +# File exists and write permission granted to user +# show prompt +echo "Continue? y/n" +read ANSWER +case $ANSWER in + [yY] ) echo "Writing auth.json" ;; + [nN] ) echo "Cancelled."; exit ;; +esac + +$PLAYWRIGHT \ + codegen \ + --target playwright-test \ + --save-storage=auth.json \ + -o tests/deleteme.spec.ts \ + $BASE_URL + +# We are only interested in auth.json +rm tests/deleteme.spec.ts + +echo "Auth file creation completed." +echo "You can then run your tests by doing e.g.:" +echo "playwright test --project chromium" diff --git a/playwright/staging-tests/nodesource-install.sh b/playwright/staging-tests/nodesource-install.sh new file mode 100755 index 0000000..eb2ef0f --- /dev/null +++ b/playwright/staging-tests/nodesource-install.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +echo "NodeJS will be installed if not present" +echo "sudo password will be required" + +USES_APT=$(which apt | grep -w "apt" | wc -l) +USES_RPM=$(which rpm | grep -w "rpm" | wc -l) + +if [ $USES_APT -eq 1 ]; then + curl -SLO https://deb.nodesource.com/nsolid_setup_deb.sh + sudo chmod 500 nsolid_setup_deb.sh + sudo ./nsolid_setup_deb.sh 20 + sudo apt-get install nodejs -y + +elif [ $USES_RPM -eq 1 ]; then + curl -SLO https://rpm.nodesource.com/nsolid_setup_rpm.sh + sudo chmod 500 nsolid_setup_rpm.sh + sudo ./nsolid_setup_rpm.sh 20 + sudo yum install nodejs -y --setopt=nodesource-nodejs.module_hotfixes=1 +fi + +echo "Done" +echo "" diff --git a/playwright/staging-tests/package-lock.json b/playwright/staging-tests/package-lock.json new file mode 100644 index 0000000..515588d --- /dev/null +++ b/playwright/staging-tests/package-lock.json @@ -0,0 +1,91 @@ +{ + "name": "staging-tests", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "staging-tests", + "version": "1.0.0", + "license": "ISC", + "devDependencies": { + "@playwright/test": "^1.40.1", + "@types/node": "^20.8.9" + } + }, + "node_modules/@playwright/test": { + "version": "1.40.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.40.1.tgz", + "integrity": "sha512-EaaawMTOeEItCRvfmkI9v6rBkF1svM8wjl/YPRrg2N2Wmp+4qJYkWtJsbew1szfKKDm6fPLy4YAanBhIlf9dWw==", + "dev": true, + "dependencies": { + "playwright": "1.40.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@types/node": { + "version": "20.9.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.2.tgz", + "integrity": "sha512-WHZXKFCEyIUJzAwh3NyyTHYSR35SevJ6mZ1nWwJafKtiQbqRTIKSRcw3Ma3acqgsent3RRDqeVwpHntMk+9irg==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "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.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.40.1.tgz", + "integrity": "sha512-2eHI7IioIpQ0bS1Ovg/HszsN/XKNwEG1kbzSDDmADpclKc7CyqkHw7Mg2JCz/bbCxg25QUPcjksoMW7JcIFQmw==", + "dev": true, + "dependencies": { + "playwright-core": "1.40.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.40.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.40.1.tgz", + "integrity": "sha512-+hkOycxPiV534c4HhpfX6yrlawqVUzITRKwHAmYfmsVreltEl6fAZJ3DPfLMOODw0H3s1Itd6MDCWmP1fl/QvQ==", + "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/playwright/staging-tests/package.json b/playwright/staging-tests/package.json new file mode 100644 index 0000000..a76e840 --- /dev/null +++ b/playwright/staging-tests/package.json @@ -0,0 +1,14 @@ +{ + "name": "staging-tests", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": {}, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@playwright/test": "^1.40.1", + "@types/node": "^20.8.9" + } +} diff --git a/playwright/staging-tests/playwright-path.sh b/playwright/staging-tests/playwright-path.sh new file mode 100755 index 0000000..41a24a0 --- /dev/null +++ b/playwright/staging-tests/playwright-path.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash + +echo "This script will discover the path to your playwright install" +echo "If you are not in a NixOS environment and it is not installed," +echo "playwright will be installed." +echo "" +echo "At the end of calling this script , you should have a PLAYWRIGHT" +echo "" + +# Are we on nixos or a distro with Nix installed for packages +# Y + # Are we in direnv? + # Y: should all be set up + # N: run nix-shell +#N + # Are we in a deb based distro? + # Are we in an rpm based distro? + # Are we on macOS? + # Are we in windows? + +HAS_PLAYWRIGHT=$(which playwright 2> /dev/null | grep -v "which: no" | wc -l) +PLAYWRIGHT="playwright" +if [ $HAS_PLAYWRIGHT -eq 0 ]; then + PLAYWRIGHT="npx playwright" + + # check if OS is a deb based distro and uses apt + USES_APT=$(which apt 2> /dev/null | grep -w "apt" | wc -l) + # check if OS is an rpm-based distro + USES_RPM=$(which rpm | grep -w "rpm" | wc -l) + + if [ $USES_APT -eq 1 ]; then + # check if nodejs is installed + HAS_NODEJS=$(which node | grep -w "node" | wc -l) + + # if nodejs is present then + if [ $HAS_NODEJS -eq 0 ]; then + source nodesource-install.sh + fi + + # check if npm is present + HAS_NPM=$(which npm | grep -w "npm" | wc -l) + + if [ $HAS_NPM -eq 1 ]; then + NPM="npm" + PLAYWRIGHT_INSTALL=$($NPM ls --depth 1 playwright | grep -w "@playwright/test" | wc -l) + + if [ $PLAYWRIGHT_INSTALL -eq 0 ]; then + $NPM install -D @playwright/test@latest + $NPM ci + $PLAYWRIGHT install --with-deps chromium + fi + + fi + + elif [ $USES_RPM -eq 1 ]; then + + # check if nodejs is installed + HAS_NODEJS=$(which node | grep -w "node" | wc -l) + + # if nodejs is present then + if [ $HAS_NODEJS -eq 0 ]; then + source nodesource-install.sh + fi + + # check if npm is present + HAS_NPM=$(which npm | grep -w "npm" | wc -l) + + if [ $HAS_NPM -eq 1 ]; then + NPM="npm" + PLAYWRIGHT_INSTALL=$($NPM ls --depth 1 playwright | grep -w "@playwright/test" | wc -l) + + if [ $PLAYWRIGHT_INSTALL -eq 0 ]; then + $NPM install -D @playwright/test@latest + $NPM ci + $PLAYWRIGHT install + fi + + fi + fi +fi + +echo "Done." +echo "" diff --git a/playwright/staging-tests/playwright.config.js b/playwright/staging-tests/playwright.config.js new file mode 100644 index 0000000..a09bb2c --- /dev/null +++ b/playwright/staging-tests/playwright.config.js @@ -0,0 +1,83 @@ +// @ts-check +const { defineConfig, devices } = require('@playwright/test'); + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * @see https://playwright.dev/docs/test-configuration + */ +module.exports = defineConfig({ + 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://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'], + // Use prepared auth state. + storageState: 'auth.json', + }, + // dependencies: ['setup'], + }, + + // { + // 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, + // }, +}); + diff --git a/playwright/staging-tests/record-test.sh b/playwright/staging-tests/record-test.sh new file mode 100755 index 0000000..6b4fb74 --- /dev/null +++ b/playwright/staging-tests/record-test.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +source base-url.sh + +source playwright-path.sh + +if [ -z "$1" ] +then + echo "Usage: $0 TESTNAME" + echo "e.g. $0 mytest" + echo "will write a new test to tests/mytest.spec.ts" + echo "Do not use spaces in your test name." + echo "" + echo "After recording your test, close the test browser." + echo "You can then run your test by doing:" + echo "npx playwright test tests/mytest.spec.py" + exit +else + echo "Recording test to tests/${1}" +fi + +if [ -w "tests/${1}.spec.ts" ]; then + # File exists and write permission granted to user + # show prompt + echo "File tests/${1}.spec.ts exists. Overwrite? y/n" + read ANSWER + case $ANSWER in + [yY] ) echo "Writing recorded test to tests/${1}.spec.ts" ;; + [nN] ) echo "Cancelled."; exit ;; + esac +fi +TESTNAME=$1 + +$PLAYWRIGHT \ + codegen \ + --target playwright-test \ + --load-storage=auth.json \ + -o tests/$1.spec.ts \ + $BASE_URL + + +echo "Test recording completed." +echo "You can then run your test by doing:" +echo "./run-tests.sh" diff --git a/playwright/staging-tests/run-tests.sh b/playwright/staging-tests/run-tests.sh new file mode 100755 index 0000000..5ff10ab --- /dev/null +++ b/playwright/staging-tests/run-tests.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +source playwright-path.sh + +echo "This script will run the tests defined in tests/" +echo "Before running the tests you need to create the auth config" +echo "" + +$PLAYWRIGHT \ + test \ + --ui \ + --project chromium + +echo "--done--" diff --git a/playwright/staging-tests/shell.nix b/playwright/staging-tests/shell.nix new file mode 100644 index 0000000..595c145 --- /dev/null +++ b/playwright/staging-tests/shell.nix @@ -0,0 +1,28 @@ +let + # + # Note that I am using a snapshot from NixOS unstable here + # so that we can use a more bleeding edge version which includes the test --ui . + # If you want use a different version, go to nix packages search, and find the + # github hash of the version you want to be using, then replace in the URL below. + # + nixpkgs = builtins.fetchTarball "https://github.com/NixOS/nixpkgs/archive/4059c4f71b3a7339261c0183e365fd8016f24bdb.tar.gz"; + pkgs = import nixpkgs { config = { }; overlays = [ ]; }; +in +with pkgs; +mkShell { + buildInputs = [ + nodejs + playwright-test + # python311Packages.playwright + # python311Packages.pytest + ]; + + PLAYWRIGHT_BROWSERS_PATH="${pkgs.playwright-driver.browsers}"; + + shellHook = '' + # Remove playwright from node_modules, so it will be taken from playwright-test + rm node_modules/@playwright/ -R + export PLAYWRIGHT_BROWSERS_PATH=${pkgs.playwright-driver.browsers} + export PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS=true + ''; +} diff --git a/playwright/staging-tests/tests/test.spec.ts b/playwright/staging-tests/tests/test.spec.ts new file mode 100644 index 0000000..623eb63 --- /dev/null +++ b/playwright/staging-tests/tests/test.spec.ts @@ -0,0 +1,18 @@ +import { test, expect } from '@playwright/test'; + +test.use({ + storageState: 'auth.json' +}); + +test('test', async ({ page }) => { + await page.goto('https://example.com/'); + await expect(page.getByRole('heading', { name: 'Example Domain' })).toBeVisible(); + await expect(page.getByText('This domain is for use in')).toBeVisible(); + await page.getByRole('heading', { name: 'Example Domain' }).click(); + await page.getByText('This domain is for use in').click(); + await page.getByRole('link', { name: 'More information...' }).click(); + await page.getByRole('heading', { name: 'Example Domains' }).click(); + await page.getByRole('link', { name: 'Homepage' }).click(); + await page.locator('h1').click(); + await page.getByText('The global coordination of').click(); +}); \ No newline at end of file