From 6316a4a3100817c3032669b77230736edc10e61f Mon Sep 17 00:00:00 2001 From: Vasilis Date: Mon, 12 Aug 2024 13:40:42 +0200 Subject: [PATCH 01/51] yaml file added --- .github/workflows/hello.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/workflows/hello.yml diff --git a/.github/workflows/hello.yml b/.github/workflows/hello.yml new file mode 100644 index 0000000000..940f67a8ab --- /dev/null +++ b/.github/workflows/hello.yml @@ -0,0 +1,14 @@ +name: Hello World! + +on: + push: + branches: + - main + +jobs: + hello_world_job: + runs-on: ubuntu-20.04 + steps: + - name: Say hello + run: | + echo "Hello World!" \ No newline at end of file From 7d1775fc11ea4fda8cb2b14e1941e31b7155c342 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Mon, 12 Aug 2024 13:48:54 +0200 Subject: [PATCH 02/51] yml file update with date directory --- .github/workflows/hello.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/hello.yml b/.github/workflows/hello.yml index 940f67a8ab..175ba479fc 100644 --- a/.github/workflows/hello.yml +++ b/.github/workflows/hello.yml @@ -11,4 +11,10 @@ jobs: steps: - name: Say hello run: | - echo "Hello World!" \ No newline at end of file + echo "Hello World!" + - name: Now it is + run: | + date -u + -name: Directory content + run: | + ls -l From 4685469c7dd5cde1150c618c7502cf6a6912baa5 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Mon, 12 Aug 2024 13:51:37 +0200 Subject: [PATCH 03/51] error fixed --- .github/workflows/hello.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/hello.yml b/.github/workflows/hello.yml index 175ba479fc..088937e855 100644 --- a/.github/workflows/hello.yml +++ b/.github/workflows/hello.yml @@ -15,6 +15,6 @@ jobs: - name: Now it is run: | date -u - -name: Directory content + - name: Directory content run: | ls -l From c3d3d31a701719f0882b77c33207e15ea1499adc Mon Sep 17 00:00:00 2001 From: Vasilis Date: Mon, 12 Aug 2024 13:57:47 +0200 Subject: [PATCH 04/51] pipeline.yml added --- .github/workflows/pipeline.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 .github/workflows/pipeline.yml diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml new file mode 100644 index 0000000000..e69de29bb2 From 9ce0167523ef76134157f6a81077fe07c486f480 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Mon, 12 Aug 2024 13:59:02 +0200 Subject: [PATCH 05/51] another try --- .github/workflows/pipeline.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index e69de29bb2..b96171004c 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -0,0 +1,19 @@ +name: Deployment pipeline + +on: + push: + branches: + - main + +jobs: + simple_deployment_pipeline: + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: '20' + - name: Install dependencies + run: npm install + - name: Check style + run: npm run eslint \ No newline at end of file From 0d2e7dfa35c8c574ef6c83b2a8d3d4f9cc4545cc Mon Sep 17 00:00:00 2001 From: Vasilis Date: Mon, 12 Aug 2024 14:08:36 +0200 Subject: [PATCH 06/51] corrected mistakes --- .eslintrc.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 8a182fff92..b843a8e767 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,4 +1,4 @@ -module.exports = { +export default { "env": { "browser": true, "es6": true, @@ -29,7 +29,8 @@ module.exports = { ], "quotes": [ "error", - "single" + "single", + "double" ], "semi": [ "error", From c9c1a8c2056833d56006739b5b7c8db93caf6ae4 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Mon, 12 Aug 2024 14:09:59 +0200 Subject: [PATCH 07/51] changed export default to module.exports --- .eslintrc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eslintrc.js b/.eslintrc.js index b843a8e767..a1fcc03e7b 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,4 +1,4 @@ -export default { +module.exports = { "env": { "browser": true, "es6": true, From c6bf40d1207757ff2205255646d08000f6b5e6ea Mon Sep 17 00:00:00 2001 From: Vasilis Date: Tue, 13 Aug 2024 09:00:56 +0200 Subject: [PATCH 08/51] changes in quotes --- .eslintrc.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index a1fcc03e7b..6670337984 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -29,8 +29,7 @@ module.exports = { ], "quotes": [ "error", - "single", - "double" + "double", ], "semi": [ "error", From bd8d7ffe32218192aac19deae176ad5189953ceb Mon Sep 17 00:00:00 2001 From: Vasilis Date: Tue, 13 Aug 2024 12:59:54 +0200 Subject: [PATCH 09/51] changes on the linter --- .eslintrc.js | 90 ++++++++++++++++++++++----------------------- app.js | 9 +++-- package.json | 2 +- src/App.jsx | 2 +- src/PokemonPage.jsx | 1 - 5 files changed, 51 insertions(+), 53 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 6670337984..ddde124efd 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,49 +1,47 @@ -module.exports = { - "env": { - "browser": true, - "es6": true, - "jest/globals": true - }, - "extends": [ - "eslint:recommended", - "plugin:react/recommended" - ], - "parserOptions": { - "ecmaFeatures": { - "jsx": true + module.exports = { + "env": { + "browser": true, + "es6": true, + "jest/globals": true }, - "ecmaVersion": 2018, - "sourceType": "module" - }, - "plugins": [ - "react", "jest" - ], - "rules": { - "indent": [ - "error", - 2 - ], - "linebreak-style": [ - "error", - "unix" - ], - "quotes": [ - "error", - "double", + "extends": [ + "eslint:recommended", + "plugin:react/recommended", ], - "semi": [ - "error", - "never" - ], - "eqeqeq": "error", - "no-trailing-spaces": "error", - "object-curly-spacing": [ - "error", "always" - ], - "arrow-spacing": [ - "error", { "before": true, "after": true } + "parserOptions": { + "ecmaFeatures": { + "jsx": true + }, + "ecmaVersion": 2018, + "sourceType": "module" + }, + "plugins": [ + "react", "jest" ], - "no-console": "error", - "react/prop-types": 0 - } -} + "rules": { + "indent": [ + "error", + 2 + ], + "linebreak-style": [ + "error", + "unix", + // "windows" + ], + "quotes": [1, "single"], + "semi": [ + "error", + "never" + ], + "eqeqeq": "error", + "no-trailing-spaces": "error", + "object-curly-spacing": [ + "error", "always" + ], + "arrow-spacing": [ + "error", { "before": true, "after": true } + ], + "no-console": "error", + "react/prop-types": 0 + } + } \ No newline at end of file diff --git a/app.js b/app.js index 0b172aece0..36919fc351 100644 --- a/app.js +++ b/app.js @@ -1,10 +1,11 @@ -const express = require("express"); -const app = express(); +import express from "express"; + +const app = express() // get the port from env variable -const PORT = process.env.PORT || 5000; +const PORT = process.env.PORT || 5000 -app.use(express.static("dist")); +app.use(express.static("dist")) app.listen(PORT, () => { console.log(`server started on port ${PORT}`); diff --git a/package.json b/package.json index d7c454f137..ca49cd170f 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "start": "webpack-dev-server --open --mode development", "start-prod": "node app.js", "test": "jest", - "eslint": "eslint './**/*.{js,jsx}'", + "lint": "eslint **/*.{js,jsx}", "build": "webpack --mode production" }, "repository": { diff --git a/src/App.jsx b/src/App.jsx index 6b7e7cbcb5..3097bf7f19 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,5 +1,5 @@ import React from 'react' -import { BrowserRouter as Router, Routes, Route, useMatch } from 'react-router-dom' +import { Routes, Route, useMatch } from 'react-router-dom' import { useApi } from './useApi' import LoadingSpinner from './LoadingSpinner' import ErrorMessage from './ErrorMessage' diff --git a/src/PokemonPage.jsx b/src/PokemonPage.jsx index a37849fb4d..04ec77e694 100644 --- a/src/PokemonPage.jsx +++ b/src/PokemonPage.jsx @@ -26,7 +26,6 @@ const PokemonPage = ({ previous, next }) => { const normalAbility = pokemon.abilities.find((ability) => !ability.is_hidden) const hiddenAbility = pokemon.abilities.find((ability) => ability.is_hidden === true) - console.log('hiddenAbility=', hiddenAbility) return ( <>
From de6e340962920099000f6537566d308157c26703 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Tue, 13 Aug 2024 13:00:25 +0200 Subject: [PATCH 10/51] changes on yaml file --- .github/workflows/pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index b96171004c..4dc7590231 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -16,4 +16,4 @@ jobs: - name: Install dependencies run: npm install - name: Check style - run: npm run eslint \ No newline at end of file + run: npm run lint \ No newline at end of file From 9bb2a00712fc774ff958a1473f2d04c906ce5216 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Tue, 13 Aug 2024 14:13:28 +0200 Subject: [PATCH 11/51] lint fixes --- .eslintrc.js | 91 ++++++++++++++++++++++++----------------------- app.js | 6 ++-- package-lock.json | 91 +++++++++++++++++++++++++++++++++++++++++++---- package.json | 3 ++ 4 files changed, 138 insertions(+), 53 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index ddde124efd..86b21f7e93 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,47 +1,50 @@ - module.exports = { - "env": { - "browser": true, - "es6": true, - "jest/globals": true +module.exports = { + "env": { + "browser": true, + "es6": true, + "jest/globals": true, + "node": true + }, + "extends": [ + "eslint:recommended", + "plugin:react/recommended" + ], + "parserOptions": { + "ecmaFeatures": { + "jsx": true }, - "extends": [ - "eslint:recommended", - "plugin:react/recommended", - ], - "parserOptions": { - "ecmaFeatures": { - "jsx": true - }, - "ecmaVersion": 2018, - "sourceType": "module" - }, - "plugins": [ - "react", "jest" - ], - "rules": { - "indent": [ - "error", + "ecmaVersion": 2018, + "sourceType": "module" + }, + "plugins": [ + "react", "jest" + ], + "rules": { + "indent": [ + 1, 2 ], - "linebreak-style": [ - "error", - "unix", - // "windows" - ], - "quotes": [1, "single"], - "semi": [ - "error", - "never" - ], - "eqeqeq": "error", - "no-trailing-spaces": "error", - "object-curly-spacing": [ - "error", "always" - ], - "arrow-spacing": [ - "error", { "before": true, "after": true } - ], - "no-console": "error", - "react/prop-types": 0 - } - } \ No newline at end of file + "linebreak-style": [ + 1, + "unix" + ], + "quotes": [ + 1, + "single" + ], + "semi": [ + "error", + "never" + ], + "eqeqeq": 1, + "no-trailing-spaces": 1, + "object-curly-spacing": [ + "error", "always" + ], + "arrow-spacing": [ + "error", { "before": true, "after": true } + ], + "no-console": "off", + "react/prop-types": 0 + } +} \ No newline at end of file diff --git a/app.js b/app.js index 36919fc351..effa6d37e3 100644 --- a/app.js +++ b/app.js @@ -1,4 +1,4 @@ -import express from "express"; +import express from "express" const app = express() @@ -8,5 +8,5 @@ const PORT = process.env.PORT || 5000 app.use(express.static("dist")) app.listen(PORT, () => { - console.log(`server started on port ${PORT}`); -}); + console.log(`server started on port ${PORT}`) +}) diff --git a/package-lock.json b/package-lock.json index 56b25007d0..7349dc8b81 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,8 +20,10 @@ "@babel/plugin-transform-runtime": "^7.23.7", "@babel/preset-env": "^7.23.7", "@babel/preset-react": "^7.23.3", + "@stylistic/eslint-plugin-js": "^2.6.2", "@testing-library/jest-dom": "^6.2.0", "@testing-library/react": "^14.1.2", + "babel-eslint": "^10.1.0", "babel-jest": "^29.7.0", "babel-loader": "^9.1.3", "css-loader": "^6.8.1", @@ -2917,6 +2919,53 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@stylistic/eslint-plugin-js": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-2.6.2.tgz", + "integrity": "sha512-wCr/kVctAPayMU3pcOI1MKR7MoKIh6VKZU89lPklAqtJoxT+Em6RueiiARbpznUYG5eg3LymiU+aMD+aIZXdqA==", + "dev": true, + "dependencies": { + "@types/eslint": "^9.6.0", + "acorn": "^8.12.1", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": ">=8.40.0" + } + }, + "node_modules/@stylistic/eslint-plugin-js/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@stylistic/eslint-plugin-js/node_modules/espree": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", + "dev": true, + "dependencies": { + "acorn": "^8.12.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@testing-library/dom": { "version": "9.3.3", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.3.tgz", @@ -3265,9 +3314,9 @@ } }, "node_modules/@types/eslint": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.1.tgz", - "integrity": "sha512-18PLWRzhy9glDQp3+wOgfLYRWlhgX0azxgJ63rdpoUHyrC9z0f5CkFburjQx4uD7ZCruw85ZtMt6K+L+R8fLJQ==", + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz", + "integrity": "sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==", "dev": true, "dependencies": { "@types/estree": "*", @@ -3954,9 +4003,9 @@ } }, "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -4323,6 +4372,36 @@ "proxy-from-env": "^1.1.0" } }, + "node_modules/babel-eslint": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", + "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", + "deprecated": "babel-eslint is now @babel/eslint-parser. This package will no longer receive updates.", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.0", + "@babel/traverse": "^7.7.0", + "@babel/types": "^7.7.0", + "eslint-visitor-keys": "^1.0.0", + "resolve": "^1.12.0" + }, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "eslint": ">= 4.12.1" + } + }, + "node_modules/babel-eslint/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", diff --git a/package.json b/package.json index ca49cd170f..9de2496492 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "1.0.0", "description": "Full Stack Open", "main": "src/index.js", + "type": "commonjs", "scripts": { "start": "webpack-dev-server --open --mode development", "start-prod": "node app.js", @@ -28,8 +29,10 @@ "@babel/plugin-transform-runtime": "^7.23.7", "@babel/preset-env": "^7.23.7", "@babel/preset-react": "^7.23.3", + "@stylistic/eslint-plugin-js": "^2.6.2", "@testing-library/jest-dom": "^6.2.0", "@testing-library/react": "^14.1.2", + "babel-eslint": "^10.1.0", "babel-jest": "^29.7.0", "babel-loader": "^9.1.3", "css-loader": "^6.8.1", From 4fc06eb860f490a0afd0008a596889c9811f3fa3 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Tue, 13 Aug 2024 14:19:12 +0200 Subject: [PATCH 12/51] yaml update --- .github/workflows/pipeline.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 4dc7590231..1c46134687 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -16,4 +16,8 @@ jobs: - name: Install dependencies run: npm install - name: Check style - run: npm run lint \ No newline at end of file + run: npm run lint + - name: Build + run: npm run build + - name: Run tests + run: npm test \ No newline at end of file From ef43059168440b21b3d64abcba501ad4e3e20d89 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Tue, 13 Aug 2024 14:22:13 +0200 Subject: [PATCH 13/51] package.json fixes --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 9de2496492..37ba1cbb65 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,6 @@ "version": "1.0.0", "description": "Full Stack Open", "main": "src/index.js", - "type": "commonjs", "scripts": { "start": "webpack-dev-server --open --mode development", "start-prod": "node app.js", From 68edbce51ed2f1a40173bb094369cebb2ea1dc79 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Tue, 13 Aug 2024 14:29:16 +0200 Subject: [PATCH 14/51] error fixed in PokemonPage --- src/PokemonPage.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PokemonPage.jsx b/src/PokemonPage.jsx index 04ec77e694..0a3f5e6190 100644 --- a/src/PokemonPage.jsx +++ b/src/PokemonPage.jsx @@ -31,7 +31,7 @@ const PokemonPage = ({ previous, next }) => {
{previous && Previous} Home - {next && Next} + {next && Next}
From 542f271a1f715b6bdd3b3584efbd50a140480a27 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Tue, 13 Aug 2024 15:41:44 +0200 Subject: [PATCH 15/51] playwirght tests added --- .github/workflows/pipeline.yml | 4 +- .gitignore | 6 +- package-lock.json | 78 ++++- package.json | 8 +- playwright.config.js | 85 +++++ tests-examples/demo-todo-app.spec.js | 449 +++++++++++++++++++++++++++ tests/example.spec.js | 19 ++ tests/frontpage.spec.js | 15 + 8 files changed, 657 insertions(+), 7 deletions(-) create mode 100644 playwright.config.js create mode 100644 tests-examples/demo-todo-app.spec.js create mode 100644 tests/example.spec.js create mode 100644 tests/frontpage.spec.js diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 1c46134687..2804313a9b 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -20,4 +20,6 @@ jobs: - name: Build run: npm run build - name: Run tests - run: npm test \ No newline at end of file + run: npm test + - name: Run playWright test + run: npm run test:e2e \ No newline at end of file diff --git a/.gitignore b/.gitignore index 763301fc00..86c7cc8b73 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ dist/ -node_modules/ \ No newline at end of file +node_modules/ +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/package-lock.json b/package-lock.json index 7349dc8b81..22238252fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,9 +20,11 @@ "@babel/plugin-transform-runtime": "^7.23.7", "@babel/preset-env": "^7.23.7", "@babel/preset-react": "^7.23.3", + "@playwright/test": "^1.46.0", "@stylistic/eslint-plugin-js": "^2.6.2", "@testing-library/jest-dom": "^6.2.0", "@testing-library/react": "^14.1.2", + "@types/node": "^22.2.0", "babel-eslint": "^10.1.0", "babel-jest": "^29.7.0", "babel-loader": "^9.1.3", @@ -2887,6 +2889,21 @@ "node": ">= 8" } }, + "node_modules/@playwright/test": { + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.46.0.tgz", + "integrity": "sha512-/QYft5VArOrGRP5pgkrfKksqsKA6CEFyGQ/gjNe6q0y4tZ1aaPfq4gIjudr1s3D+pXyrPRdsy4opKDrjBabE5w==", + "dev": true, + "dependencies": { + "playwright": "1.46.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@remix-run/router": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.14.1.tgz", @@ -3441,10 +3458,13 @@ "dev": true }, "node_modules/@types/node": { - "version": "13.13.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.4.tgz", - "integrity": "sha512-x26ur3dSXgv5AwKS0lNfbjpCakGIduWU1DU91Zz58ONRWrIKGunmZBNv4P7N+e27sJkiGDsw/3fT4AtsqQBrBA==", - "dev": true + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.2.0.tgz", + "integrity": "sha512-bm6EG6/pCpkxDf/0gDNDdtDILMOHgaQBVOJGdwsqClnxA3xL6jtMv76rLBc006RVMWbmaf0xbmom4Z/5o2nRkQ==", + "dev": true, + "dependencies": { + "undici-types": "~6.13.0" + } }, "node_modules/@types/node-forge": { "version": "1.3.11", @@ -11178,6 +11198,50 @@ "node": ">=8" } }, + "node_modules/playwright": { + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.46.0.tgz", + "integrity": "sha512-XYJ5WvfefWONh1uPAUAi0H2xXV5S3vrtcnXe6uAOgdGi3aSpqOSXX08IAjXW34xitfuOJsvXU5anXZxPSEQiJw==", + "dev": true, + "dependencies": { + "playwright-core": "1.46.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.46.0.tgz", + "integrity": "sha512-9Y/d5UIwuJk8t3+lhmMSAJyNP1BUC/DqP3cQJDQQL/oWqAiuPTLgy7Q5dzglmTLwcBRdetzgNM/gni7ckfTr6A==", + "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/postcss": { "version": "8.4.33", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", @@ -12936,6 +13000,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici-types": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", + "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==", + "dev": true + }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", diff --git a/package.json b/package.json index 37ba1cbb65..57cb219ef7 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "start": "webpack-dev-server --open --mode development", "start-prod": "node app.js", "test": "jest", + "test:e2e": "playwright test", "lint": "eslint **/*.{js,jsx}", "build": "webpack --mode production" }, @@ -28,9 +29,11 @@ "@babel/plugin-transform-runtime": "^7.23.7", "@babel/preset-env": "^7.23.7", "@babel/preset-react": "^7.23.3", + "@playwright/test": "^1.46.0", "@stylistic/eslint-plugin-js": "^2.6.2", "@testing-library/jest-dom": "^6.2.0", "@testing-library/react": "^14.1.2", + "@types/node": "^22.2.0", "babel-eslint": "^10.1.0", "babel-jest": "^29.7.0", "babel-loader": "^9.1.3", @@ -56,6 +59,9 @@ "react-router-dom": "^6.21.1" }, "jest": { - "testEnvironment": "jsdom" + "testEnvironment": "jsdom", + "testPathIgnorePatterns": [ + "e2e-tests" + ] } } diff --git a/playwright.config.js b/playwright.config.js new file mode 100644 index 0000000000..3a73f75305 --- /dev/null +++ b/playwright.config.js @@ -0,0 +1,85 @@ +// @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: './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. */ + webServer: { + command: 'npm run start', + url: 'http://localhost:8080/', + timeout: 120 * 1000, + reuseExistingServer: !process.env.CI, + }, + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:8080/', + + /* 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, + // }, +}); + diff --git a/tests-examples/demo-todo-app.spec.js b/tests-examples/demo-todo-app.spec.js new file mode 100644 index 0000000000..e2eb87ce1b --- /dev/null +++ b/tests-examples/demo-todo-app.spec.js @@ -0,0 +1,449 @@ +// @ts-check +const { test, expect } = require('@playwright/test'); + +test.beforeEach(async ({ page }) => { + await page.goto('https://demo.playwright.dev/todomvc'); +}); + +const TODO_ITEMS = [ + 'buy some cheese', + 'feed the cat', + 'book a doctors appointment' +]; + +test.describe('New Todo', () => { + test('should allow me to add todo items', async ({ page }) => { + // create a new todo locator + const newTodo = page.getByPlaceholder('What needs to be done?'); + + // Create 1st todo. + await newTodo.fill(TODO_ITEMS[0]); + await newTodo.press('Enter'); + + // Make sure the list only has one todo item. + await expect(page.getByTestId('todo-title')).toHaveText([ + TODO_ITEMS[0] + ]); + + // Create 2nd todo. + await newTodo.fill(TODO_ITEMS[1]); + await newTodo.press('Enter'); + + // Make sure the list now has two todo items. + await expect(page.getByTestId('todo-title')).toHaveText([ + TODO_ITEMS[0], + TODO_ITEMS[1] + ]); + + await checkNumberOfTodosInLocalStorage(page, 2); + }); + + test('should clear text input field when an item is added', async ({ page }) => { + // create a new todo locator + const newTodo = page.getByPlaceholder('What needs to be done?'); + + // Create one todo item. + await newTodo.fill(TODO_ITEMS[0]); + await newTodo.press('Enter'); + + // Check that input is empty. + await expect(newTodo).toBeEmpty(); + await checkNumberOfTodosInLocalStorage(page, 1); + }); + + test('should append new items to the bottom of the list', async ({ page }) => { + // Create 3 items. + await createDefaultTodos(page); + + // create a todo count locator + const todoCount = page.getByTestId('todo-count') + + // Check test using different methods. + await expect(page.getByText('3 items left')).toBeVisible(); + await expect(todoCount).toHaveText('3 items left'); + await expect(todoCount).toContainText('3'); + await expect(todoCount).toHaveText(/3/); + + // Check all items in one call. + await expect(page.getByTestId('todo-title')).toHaveText(TODO_ITEMS); + await checkNumberOfTodosInLocalStorage(page, 3); + }); +}); + +test.describe('Mark all as completed', () => { + test.beforeEach(async ({ page }) => { + await createDefaultTodos(page); + await checkNumberOfTodosInLocalStorage(page, 3); + }); + + test.afterEach(async ({ page }) => { + await checkNumberOfTodosInLocalStorage(page, 3); + }); + + test('should allow me to mark all items as completed', async ({ page }) => { + // Complete all todos. + await page.getByLabel('Mark all as complete').check(); + + // Ensure all todos have 'completed' class. + await expect(page.getByTestId('todo-item')).toHaveClass(['completed', 'completed', 'completed']); + await checkNumberOfCompletedTodosInLocalStorage(page, 3); + }); + + test('should allow me to clear the complete state of all items', async ({ page }) => { + const toggleAll = page.getByLabel('Mark all as complete'); + // Check and then immediately uncheck. + await toggleAll.check(); + await toggleAll.uncheck(); + + // Should be no completed classes. + await expect(page.getByTestId('todo-item')).toHaveClass(['', '', '']); + }); + + test('complete all checkbox should update state when items are completed / cleared', async ({ page }) => { + const toggleAll = page.getByLabel('Mark all as complete'); + await toggleAll.check(); + await expect(toggleAll).toBeChecked(); + await checkNumberOfCompletedTodosInLocalStorage(page, 3); + + // Uncheck first todo. + const firstTodo = page.getByTestId('todo-item').nth(0); + await firstTodo.getByRole('checkbox').uncheck(); + + // Reuse toggleAll locator and make sure its not checked. + await expect(toggleAll).not.toBeChecked(); + + await firstTodo.getByRole('checkbox').check(); + await checkNumberOfCompletedTodosInLocalStorage(page, 3); + + // Assert the toggle all is checked again. + await expect(toggleAll).toBeChecked(); + }); +}); + +test.describe('Item', () => { + + test('should allow me to mark items as complete', async ({ page }) => { + // create a new todo locator + const newTodo = page.getByPlaceholder('What needs to be done?'); + + // Create two items. + for (const item of TODO_ITEMS.slice(0, 2)) { + await newTodo.fill(item); + await newTodo.press('Enter'); + } + + // Check first item. + const firstTodo = page.getByTestId('todo-item').nth(0); + await firstTodo.getByRole('checkbox').check(); + await expect(firstTodo).toHaveClass('completed'); + + // Check second item. + const secondTodo = page.getByTestId('todo-item').nth(1); + await expect(secondTodo).not.toHaveClass('completed'); + await secondTodo.getByRole('checkbox').check(); + + // Assert completed class. + await expect(firstTodo).toHaveClass('completed'); + await expect(secondTodo).toHaveClass('completed'); + }); + + test('should allow me to un-mark items as complete', async ({ page }) => { + // create a new todo locator + const newTodo = page.getByPlaceholder('What needs to be done?'); + + // Create two items. + for (const item of TODO_ITEMS.slice(0, 2)) { + await newTodo.fill(item); + await newTodo.press('Enter'); + } + + const firstTodo = page.getByTestId('todo-item').nth(0); + const secondTodo = page.getByTestId('todo-item').nth(1); + const firstTodoCheckbox = firstTodo.getByRole('checkbox'); + + await firstTodoCheckbox.check(); + await expect(firstTodo).toHaveClass('completed'); + await expect(secondTodo).not.toHaveClass('completed'); + await checkNumberOfCompletedTodosInLocalStorage(page, 1); + + await firstTodoCheckbox.uncheck(); + await expect(firstTodo).not.toHaveClass('completed'); + await expect(secondTodo).not.toHaveClass('completed'); + await checkNumberOfCompletedTodosInLocalStorage(page, 0); + }); + + test('should allow me to edit an item', async ({ page }) => { + await createDefaultTodos(page); + + const todoItems = page.getByTestId('todo-item'); + const secondTodo = todoItems.nth(1); + await secondTodo.dblclick(); + await expect(secondTodo.getByRole('textbox', { name: 'Edit' })).toHaveValue(TODO_ITEMS[1]); + await secondTodo.getByRole('textbox', { name: 'Edit' }).fill('buy some sausages'); + await secondTodo.getByRole('textbox', { name: 'Edit' }).press('Enter'); + + // Explicitly assert the new text value. + await expect(todoItems).toHaveText([ + TODO_ITEMS[0], + 'buy some sausages', + TODO_ITEMS[2] + ]); + await checkTodosInLocalStorage(page, 'buy some sausages'); + }); +}); + +test.describe('Editing', () => { + test.beforeEach(async ({ page }) => { + await createDefaultTodos(page); + await checkNumberOfTodosInLocalStorage(page, 3); + }); + + test('should hide other controls when editing', async ({ page }) => { + const todoItem = page.getByTestId('todo-item').nth(1); + await todoItem.dblclick(); + await expect(todoItem.getByRole('checkbox')).not.toBeVisible(); + await expect(todoItem.locator('label', { + hasText: TODO_ITEMS[1], + })).not.toBeVisible(); + await checkNumberOfTodosInLocalStorage(page, 3); + }); + + test('should save edits on blur', async ({ page }) => { + const todoItems = page.getByTestId('todo-item'); + await todoItems.nth(1).dblclick(); + await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill('buy some sausages'); + await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).dispatchEvent('blur'); + + await expect(todoItems).toHaveText([ + TODO_ITEMS[0], + 'buy some sausages', + TODO_ITEMS[2], + ]); + await checkTodosInLocalStorage(page, 'buy some sausages'); + }); + + test('should trim entered text', async ({ page }) => { + const todoItems = page.getByTestId('todo-item'); + await todoItems.nth(1).dblclick(); + await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill(' buy some sausages '); + await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).press('Enter'); + + await expect(todoItems).toHaveText([ + TODO_ITEMS[0], + 'buy some sausages', + TODO_ITEMS[2], + ]); + await checkTodosInLocalStorage(page, 'buy some sausages'); + }); + + test('should remove the item if an empty text string was entered', async ({ page }) => { + const todoItems = page.getByTestId('todo-item'); + await todoItems.nth(1).dblclick(); + await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill(''); + await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).press('Enter'); + + await expect(todoItems).toHaveText([ + TODO_ITEMS[0], + TODO_ITEMS[2], + ]); + }); + + test('should cancel edits on escape', async ({ page }) => { + const todoItems = page.getByTestId('todo-item'); + await todoItems.nth(1).dblclick(); + await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill('buy some sausages'); + await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).press('Escape'); + await expect(todoItems).toHaveText(TODO_ITEMS); + }); +}); + +test.describe('Counter', () => { + test('should display the current number of todo items', async ({ page }) => { + // create a new todo locator + const newTodo = page.getByPlaceholder('What needs to be done?'); + + // create a todo count locator + const todoCount = page.getByTestId('todo-count') + + await newTodo.fill(TODO_ITEMS[0]); + await newTodo.press('Enter'); + await expect(todoCount).toContainText('1'); + + await newTodo.fill(TODO_ITEMS[1]); + await newTodo.press('Enter'); + await expect(todoCount).toContainText('2'); + + await checkNumberOfTodosInLocalStorage(page, 2); + }); +}); + +test.describe('Clear completed button', () => { + test.beforeEach(async ({ page }) => { + await createDefaultTodos(page); + }); + + test('should display the correct text', async ({ page }) => { + await page.locator('.todo-list li .toggle').first().check(); + await expect(page.getByRole('button', { name: 'Clear completed' })).toBeVisible(); + }); + + test('should remove completed items when clicked', async ({ page }) => { + const todoItems = page.getByTestId('todo-item'); + await todoItems.nth(1).getByRole('checkbox').check(); + await page.getByRole('button', { name: 'Clear completed' }).click(); + await expect(todoItems).toHaveCount(2); + await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[2]]); + }); + + test('should be hidden when there are no items that are completed', async ({ page }) => { + await page.locator('.todo-list li .toggle').first().check(); + await page.getByRole('button', { name: 'Clear completed' }).click(); + await expect(page.getByRole('button', { name: 'Clear completed' })).toBeHidden(); + }); +}); + +test.describe('Persistence', () => { + test('should persist its data', async ({ page }) => { + // create a new todo locator + const newTodo = page.getByPlaceholder('What needs to be done?'); + + for (const item of TODO_ITEMS.slice(0, 2)) { + await newTodo.fill(item); + await newTodo.press('Enter'); + } + + const todoItems = page.getByTestId('todo-item'); + const firstTodoCheck = todoItems.nth(0).getByRole('checkbox'); + await firstTodoCheck.check(); + await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[1]]); + await expect(firstTodoCheck).toBeChecked(); + await expect(todoItems).toHaveClass(['completed', '']); + + // Ensure there is 1 completed item. + await checkNumberOfCompletedTodosInLocalStorage(page, 1); + + // Now reload. + await page.reload(); + await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[1]]); + await expect(firstTodoCheck).toBeChecked(); + await expect(todoItems).toHaveClass(['completed', '']); + }); +}); + +test.describe('Routing', () => { + test.beforeEach(async ({ page }) => { + await createDefaultTodos(page); + // make sure the app had a chance to save updated todos in storage + // before navigating to a new view, otherwise the items can get lost :( + // in some frameworks like Durandal + await checkTodosInLocalStorage(page, TODO_ITEMS[0]); + }); + + test('should allow me to display active items', async ({ page }) => { + const todoItem = page.getByTestId('todo-item'); + await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check(); + + await checkNumberOfCompletedTodosInLocalStorage(page, 1); + await page.getByRole('link', { name: 'Active' }).click(); + await expect(todoItem).toHaveCount(2); + await expect(todoItem).toHaveText([TODO_ITEMS[0], TODO_ITEMS[2]]); + }); + + test('should respect the back button', async ({ page }) => { + const todoItem = page.getByTestId('todo-item'); + await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check(); + + await checkNumberOfCompletedTodosInLocalStorage(page, 1); + + await test.step('Showing all items', async () => { + await page.getByRole('link', { name: 'All' }).click(); + await expect(todoItem).toHaveCount(3); + }); + + await test.step('Showing active items', async () => { + await page.getByRole('link', { name: 'Active' }).click(); + }); + + await test.step('Showing completed items', async () => { + await page.getByRole('link', { name: 'Completed' }).click(); + }); + + await expect(todoItem).toHaveCount(1); + await page.goBack(); + await expect(todoItem).toHaveCount(2); + await page.goBack(); + await expect(todoItem).toHaveCount(3); + }); + + test('should allow me to display completed items', async ({ page }) => { + await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check(); + await checkNumberOfCompletedTodosInLocalStorage(page, 1); + await page.getByRole('link', { name: 'Completed' }).click(); + await expect(page.getByTestId('todo-item')).toHaveCount(1); + }); + + test('should allow me to display all items', async ({ page }) => { + await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check(); + await checkNumberOfCompletedTodosInLocalStorage(page, 1); + await page.getByRole('link', { name: 'Active' }).click(); + await page.getByRole('link', { name: 'Completed' }).click(); + await page.getByRole('link', { name: 'All' }).click(); + await expect(page.getByTestId('todo-item')).toHaveCount(3); + }); + + test('should highlight the currently applied filter', async ({ page }) => { + await expect(page.getByRole('link', { name: 'All' })).toHaveClass('selected'); + + //create locators for active and completed links + const activeLink = page.getByRole('link', { name: 'Active' }); + const completedLink = page.getByRole('link', { name: 'Completed' }); + await activeLink.click(); + + // Page change - active items. + await expect(activeLink).toHaveClass('selected'); + await completedLink.click(); + + // Page change - completed items. + await expect(completedLink).toHaveClass('selected'); + }); +}); + +async function createDefaultTodos(page) { + // create a new todo locator + const newTodo = page.getByPlaceholder('What needs to be done?'); + + for (const item of TODO_ITEMS) { + await newTodo.fill(item); + await newTodo.press('Enter'); + } +} + +/** + * @param {import('@playwright/test').Page} page + * @param {number} expected + */ + async function checkNumberOfTodosInLocalStorage(page, expected) { + return await page.waitForFunction(e => { + return JSON.parse(localStorage['react-todos']).length === e; + }, expected); +} + +/** + * @param {import('@playwright/test').Page} page + * @param {number} expected + */ + async function checkNumberOfCompletedTodosInLocalStorage(page, expected) { + return await page.waitForFunction(e => { + return JSON.parse(localStorage['react-todos']).filter(i => i.completed).length === e; + }, expected); +} + +/** + * @param {import('@playwright/test').Page} page + * @param {string} title + */ +async function checkTodosInLocalStorage(page, title) { + return await page.waitForFunction(t => { + return JSON.parse(localStorage['react-todos']).map(i => i.title).includes(t); + }, title); +} diff --git a/tests/example.spec.js b/tests/example.spec.js new file mode 100644 index 0000000000..40eddb861e --- /dev/null +++ b/tests/example.spec.js @@ -0,0 +1,19 @@ +// @ts-check +const { test, expect } = require('@playwright/test'); + +test('has title', async ({ page }) => { + await page.goto('https://playwright.dev/'); + + // Expect a title "to contain" a substring. + await expect(page).toHaveTitle(/Playwright/); +}); + +test('get started link', async ({ page }) => { + await page.goto('https://playwright.dev/'); + + // Click the get started link. + await page.getByRole('link', { name: 'Get started' }).click(); + + // Expects page to have a heading with the name of Installation. + await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible(); +}); diff --git a/tests/frontpage.spec.js b/tests/frontpage.spec.js new file mode 100644 index 0000000000..cf24e914ee --- /dev/null +++ b/tests/frontpage.spec.js @@ -0,0 +1,15 @@ +const { test, describe, expect, beforeEach } = require('@playwright/test') + +describe('Pokedex', () => { + test('front page can be opened', async ({ page }) => { + await page.goto('/') + await expect(page.getByText('ivysaur')).toBeVisible() + await expect(page.getByText('Pokémon and Pokémon character names are trademarks of Nintendo.')).toBeVisible() + }) + test('pokemon page can be navigated to', async ({ page }) => { + await page.goto('/') + await page.getByText('bulbasaur').click() + await page.getByText('next').click() + await expect(page.getByText('ivysaur')).toBeVisible() + }) +}) \ No newline at end of file From 548c80b52979ef138e729256e934523643601b94 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Tue, 13 Aug 2024 15:45:51 +0200 Subject: [PATCH 16/51] changes for linter --- playwright.config.js | 4 +- tests-examples/demo-todo-app.spec.js | 449 --------------------------- tests/example.spec.js | 16 +- tests/frontpage.spec.js | 2 +- 4 files changed, 11 insertions(+), 460 deletions(-) delete mode 100644 tests-examples/demo-todo-app.spec.js diff --git a/playwright.config.js b/playwright.config.js index 3a73f75305..368a1fb795 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -1,5 +1,5 @@ // @ts-check -const { defineConfig, devices } = require('@playwright/test'); +const { defineConfig, devices } = require('@playwright/test') /** * Read environment variables from file. @@ -81,5 +81,5 @@ module.exports = defineConfig({ // url: 'http://127.0.0.1:3000', // reuseExistingServer: !process.env.CI, // }, -}); +}) diff --git a/tests-examples/demo-todo-app.spec.js b/tests-examples/demo-todo-app.spec.js deleted file mode 100644 index e2eb87ce1b..0000000000 --- a/tests-examples/demo-todo-app.spec.js +++ /dev/null @@ -1,449 +0,0 @@ -// @ts-check -const { test, expect } = require('@playwright/test'); - -test.beforeEach(async ({ page }) => { - await page.goto('https://demo.playwright.dev/todomvc'); -}); - -const TODO_ITEMS = [ - 'buy some cheese', - 'feed the cat', - 'book a doctors appointment' -]; - -test.describe('New Todo', () => { - test('should allow me to add todo items', async ({ page }) => { - // create a new todo locator - const newTodo = page.getByPlaceholder('What needs to be done?'); - - // Create 1st todo. - await newTodo.fill(TODO_ITEMS[0]); - await newTodo.press('Enter'); - - // Make sure the list only has one todo item. - await expect(page.getByTestId('todo-title')).toHaveText([ - TODO_ITEMS[0] - ]); - - // Create 2nd todo. - await newTodo.fill(TODO_ITEMS[1]); - await newTodo.press('Enter'); - - // Make sure the list now has two todo items. - await expect(page.getByTestId('todo-title')).toHaveText([ - TODO_ITEMS[0], - TODO_ITEMS[1] - ]); - - await checkNumberOfTodosInLocalStorage(page, 2); - }); - - test('should clear text input field when an item is added', async ({ page }) => { - // create a new todo locator - const newTodo = page.getByPlaceholder('What needs to be done?'); - - // Create one todo item. - await newTodo.fill(TODO_ITEMS[0]); - await newTodo.press('Enter'); - - // Check that input is empty. - await expect(newTodo).toBeEmpty(); - await checkNumberOfTodosInLocalStorage(page, 1); - }); - - test('should append new items to the bottom of the list', async ({ page }) => { - // Create 3 items. - await createDefaultTodos(page); - - // create a todo count locator - const todoCount = page.getByTestId('todo-count') - - // Check test using different methods. - await expect(page.getByText('3 items left')).toBeVisible(); - await expect(todoCount).toHaveText('3 items left'); - await expect(todoCount).toContainText('3'); - await expect(todoCount).toHaveText(/3/); - - // Check all items in one call. - await expect(page.getByTestId('todo-title')).toHaveText(TODO_ITEMS); - await checkNumberOfTodosInLocalStorage(page, 3); - }); -}); - -test.describe('Mark all as completed', () => { - test.beforeEach(async ({ page }) => { - await createDefaultTodos(page); - await checkNumberOfTodosInLocalStorage(page, 3); - }); - - test.afterEach(async ({ page }) => { - await checkNumberOfTodosInLocalStorage(page, 3); - }); - - test('should allow me to mark all items as completed', async ({ page }) => { - // Complete all todos. - await page.getByLabel('Mark all as complete').check(); - - // Ensure all todos have 'completed' class. - await expect(page.getByTestId('todo-item')).toHaveClass(['completed', 'completed', 'completed']); - await checkNumberOfCompletedTodosInLocalStorage(page, 3); - }); - - test('should allow me to clear the complete state of all items', async ({ page }) => { - const toggleAll = page.getByLabel('Mark all as complete'); - // Check and then immediately uncheck. - await toggleAll.check(); - await toggleAll.uncheck(); - - // Should be no completed classes. - await expect(page.getByTestId('todo-item')).toHaveClass(['', '', '']); - }); - - test('complete all checkbox should update state when items are completed / cleared', async ({ page }) => { - const toggleAll = page.getByLabel('Mark all as complete'); - await toggleAll.check(); - await expect(toggleAll).toBeChecked(); - await checkNumberOfCompletedTodosInLocalStorage(page, 3); - - // Uncheck first todo. - const firstTodo = page.getByTestId('todo-item').nth(0); - await firstTodo.getByRole('checkbox').uncheck(); - - // Reuse toggleAll locator and make sure its not checked. - await expect(toggleAll).not.toBeChecked(); - - await firstTodo.getByRole('checkbox').check(); - await checkNumberOfCompletedTodosInLocalStorage(page, 3); - - // Assert the toggle all is checked again. - await expect(toggleAll).toBeChecked(); - }); -}); - -test.describe('Item', () => { - - test('should allow me to mark items as complete', async ({ page }) => { - // create a new todo locator - const newTodo = page.getByPlaceholder('What needs to be done?'); - - // Create two items. - for (const item of TODO_ITEMS.slice(0, 2)) { - await newTodo.fill(item); - await newTodo.press('Enter'); - } - - // Check first item. - const firstTodo = page.getByTestId('todo-item').nth(0); - await firstTodo.getByRole('checkbox').check(); - await expect(firstTodo).toHaveClass('completed'); - - // Check second item. - const secondTodo = page.getByTestId('todo-item').nth(1); - await expect(secondTodo).not.toHaveClass('completed'); - await secondTodo.getByRole('checkbox').check(); - - // Assert completed class. - await expect(firstTodo).toHaveClass('completed'); - await expect(secondTodo).toHaveClass('completed'); - }); - - test('should allow me to un-mark items as complete', async ({ page }) => { - // create a new todo locator - const newTodo = page.getByPlaceholder('What needs to be done?'); - - // Create two items. - for (const item of TODO_ITEMS.slice(0, 2)) { - await newTodo.fill(item); - await newTodo.press('Enter'); - } - - const firstTodo = page.getByTestId('todo-item').nth(0); - const secondTodo = page.getByTestId('todo-item').nth(1); - const firstTodoCheckbox = firstTodo.getByRole('checkbox'); - - await firstTodoCheckbox.check(); - await expect(firstTodo).toHaveClass('completed'); - await expect(secondTodo).not.toHaveClass('completed'); - await checkNumberOfCompletedTodosInLocalStorage(page, 1); - - await firstTodoCheckbox.uncheck(); - await expect(firstTodo).not.toHaveClass('completed'); - await expect(secondTodo).not.toHaveClass('completed'); - await checkNumberOfCompletedTodosInLocalStorage(page, 0); - }); - - test('should allow me to edit an item', async ({ page }) => { - await createDefaultTodos(page); - - const todoItems = page.getByTestId('todo-item'); - const secondTodo = todoItems.nth(1); - await secondTodo.dblclick(); - await expect(secondTodo.getByRole('textbox', { name: 'Edit' })).toHaveValue(TODO_ITEMS[1]); - await secondTodo.getByRole('textbox', { name: 'Edit' }).fill('buy some sausages'); - await secondTodo.getByRole('textbox', { name: 'Edit' }).press('Enter'); - - // Explicitly assert the new text value. - await expect(todoItems).toHaveText([ - TODO_ITEMS[0], - 'buy some sausages', - TODO_ITEMS[2] - ]); - await checkTodosInLocalStorage(page, 'buy some sausages'); - }); -}); - -test.describe('Editing', () => { - test.beforeEach(async ({ page }) => { - await createDefaultTodos(page); - await checkNumberOfTodosInLocalStorage(page, 3); - }); - - test('should hide other controls when editing', async ({ page }) => { - const todoItem = page.getByTestId('todo-item').nth(1); - await todoItem.dblclick(); - await expect(todoItem.getByRole('checkbox')).not.toBeVisible(); - await expect(todoItem.locator('label', { - hasText: TODO_ITEMS[1], - })).not.toBeVisible(); - await checkNumberOfTodosInLocalStorage(page, 3); - }); - - test('should save edits on blur', async ({ page }) => { - const todoItems = page.getByTestId('todo-item'); - await todoItems.nth(1).dblclick(); - await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill('buy some sausages'); - await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).dispatchEvent('blur'); - - await expect(todoItems).toHaveText([ - TODO_ITEMS[0], - 'buy some sausages', - TODO_ITEMS[2], - ]); - await checkTodosInLocalStorage(page, 'buy some sausages'); - }); - - test('should trim entered text', async ({ page }) => { - const todoItems = page.getByTestId('todo-item'); - await todoItems.nth(1).dblclick(); - await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill(' buy some sausages '); - await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).press('Enter'); - - await expect(todoItems).toHaveText([ - TODO_ITEMS[0], - 'buy some sausages', - TODO_ITEMS[2], - ]); - await checkTodosInLocalStorage(page, 'buy some sausages'); - }); - - test('should remove the item if an empty text string was entered', async ({ page }) => { - const todoItems = page.getByTestId('todo-item'); - await todoItems.nth(1).dblclick(); - await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill(''); - await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).press('Enter'); - - await expect(todoItems).toHaveText([ - TODO_ITEMS[0], - TODO_ITEMS[2], - ]); - }); - - test('should cancel edits on escape', async ({ page }) => { - const todoItems = page.getByTestId('todo-item'); - await todoItems.nth(1).dblclick(); - await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill('buy some sausages'); - await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).press('Escape'); - await expect(todoItems).toHaveText(TODO_ITEMS); - }); -}); - -test.describe('Counter', () => { - test('should display the current number of todo items', async ({ page }) => { - // create a new todo locator - const newTodo = page.getByPlaceholder('What needs to be done?'); - - // create a todo count locator - const todoCount = page.getByTestId('todo-count') - - await newTodo.fill(TODO_ITEMS[0]); - await newTodo.press('Enter'); - await expect(todoCount).toContainText('1'); - - await newTodo.fill(TODO_ITEMS[1]); - await newTodo.press('Enter'); - await expect(todoCount).toContainText('2'); - - await checkNumberOfTodosInLocalStorage(page, 2); - }); -}); - -test.describe('Clear completed button', () => { - test.beforeEach(async ({ page }) => { - await createDefaultTodos(page); - }); - - test('should display the correct text', async ({ page }) => { - await page.locator('.todo-list li .toggle').first().check(); - await expect(page.getByRole('button', { name: 'Clear completed' })).toBeVisible(); - }); - - test('should remove completed items when clicked', async ({ page }) => { - const todoItems = page.getByTestId('todo-item'); - await todoItems.nth(1).getByRole('checkbox').check(); - await page.getByRole('button', { name: 'Clear completed' }).click(); - await expect(todoItems).toHaveCount(2); - await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[2]]); - }); - - test('should be hidden when there are no items that are completed', async ({ page }) => { - await page.locator('.todo-list li .toggle').first().check(); - await page.getByRole('button', { name: 'Clear completed' }).click(); - await expect(page.getByRole('button', { name: 'Clear completed' })).toBeHidden(); - }); -}); - -test.describe('Persistence', () => { - test('should persist its data', async ({ page }) => { - // create a new todo locator - const newTodo = page.getByPlaceholder('What needs to be done?'); - - for (const item of TODO_ITEMS.slice(0, 2)) { - await newTodo.fill(item); - await newTodo.press('Enter'); - } - - const todoItems = page.getByTestId('todo-item'); - const firstTodoCheck = todoItems.nth(0).getByRole('checkbox'); - await firstTodoCheck.check(); - await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[1]]); - await expect(firstTodoCheck).toBeChecked(); - await expect(todoItems).toHaveClass(['completed', '']); - - // Ensure there is 1 completed item. - await checkNumberOfCompletedTodosInLocalStorage(page, 1); - - // Now reload. - await page.reload(); - await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[1]]); - await expect(firstTodoCheck).toBeChecked(); - await expect(todoItems).toHaveClass(['completed', '']); - }); -}); - -test.describe('Routing', () => { - test.beforeEach(async ({ page }) => { - await createDefaultTodos(page); - // make sure the app had a chance to save updated todos in storage - // before navigating to a new view, otherwise the items can get lost :( - // in some frameworks like Durandal - await checkTodosInLocalStorage(page, TODO_ITEMS[0]); - }); - - test('should allow me to display active items', async ({ page }) => { - const todoItem = page.getByTestId('todo-item'); - await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check(); - - await checkNumberOfCompletedTodosInLocalStorage(page, 1); - await page.getByRole('link', { name: 'Active' }).click(); - await expect(todoItem).toHaveCount(2); - await expect(todoItem).toHaveText([TODO_ITEMS[0], TODO_ITEMS[2]]); - }); - - test('should respect the back button', async ({ page }) => { - const todoItem = page.getByTestId('todo-item'); - await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check(); - - await checkNumberOfCompletedTodosInLocalStorage(page, 1); - - await test.step('Showing all items', async () => { - await page.getByRole('link', { name: 'All' }).click(); - await expect(todoItem).toHaveCount(3); - }); - - await test.step('Showing active items', async () => { - await page.getByRole('link', { name: 'Active' }).click(); - }); - - await test.step('Showing completed items', async () => { - await page.getByRole('link', { name: 'Completed' }).click(); - }); - - await expect(todoItem).toHaveCount(1); - await page.goBack(); - await expect(todoItem).toHaveCount(2); - await page.goBack(); - await expect(todoItem).toHaveCount(3); - }); - - test('should allow me to display completed items', async ({ page }) => { - await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check(); - await checkNumberOfCompletedTodosInLocalStorage(page, 1); - await page.getByRole('link', { name: 'Completed' }).click(); - await expect(page.getByTestId('todo-item')).toHaveCount(1); - }); - - test('should allow me to display all items', async ({ page }) => { - await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check(); - await checkNumberOfCompletedTodosInLocalStorage(page, 1); - await page.getByRole('link', { name: 'Active' }).click(); - await page.getByRole('link', { name: 'Completed' }).click(); - await page.getByRole('link', { name: 'All' }).click(); - await expect(page.getByTestId('todo-item')).toHaveCount(3); - }); - - test('should highlight the currently applied filter', async ({ page }) => { - await expect(page.getByRole('link', { name: 'All' })).toHaveClass('selected'); - - //create locators for active and completed links - const activeLink = page.getByRole('link', { name: 'Active' }); - const completedLink = page.getByRole('link', { name: 'Completed' }); - await activeLink.click(); - - // Page change - active items. - await expect(activeLink).toHaveClass('selected'); - await completedLink.click(); - - // Page change - completed items. - await expect(completedLink).toHaveClass('selected'); - }); -}); - -async function createDefaultTodos(page) { - // create a new todo locator - const newTodo = page.getByPlaceholder('What needs to be done?'); - - for (const item of TODO_ITEMS) { - await newTodo.fill(item); - await newTodo.press('Enter'); - } -} - -/** - * @param {import('@playwright/test').Page} page - * @param {number} expected - */ - async function checkNumberOfTodosInLocalStorage(page, expected) { - return await page.waitForFunction(e => { - return JSON.parse(localStorage['react-todos']).length === e; - }, expected); -} - -/** - * @param {import('@playwright/test').Page} page - * @param {number} expected - */ - async function checkNumberOfCompletedTodosInLocalStorage(page, expected) { - return await page.waitForFunction(e => { - return JSON.parse(localStorage['react-todos']).filter(i => i.completed).length === e; - }, expected); -} - -/** - * @param {import('@playwright/test').Page} page - * @param {string} title - */ -async function checkTodosInLocalStorage(page, title) { - return await page.waitForFunction(t => { - return JSON.parse(localStorage['react-todos']).map(i => i.title).includes(t); - }, title); -} diff --git a/tests/example.spec.js b/tests/example.spec.js index 40eddb861e..4c6ab4a69c 100644 --- a/tests/example.spec.js +++ b/tests/example.spec.js @@ -1,19 +1,19 @@ // @ts-check -const { test, expect } = require('@playwright/test'); +const { test, expect } = require('@playwright/test') test('has title', async ({ page }) => { - await page.goto('https://playwright.dev/'); + await page.goto('https://playwright.dev/') // Expect a title "to contain" a substring. - await expect(page).toHaveTitle(/Playwright/); -}); + await expect(page).toHaveTitle(/Playwright/) +}) test('get started link', async ({ page }) => { - await page.goto('https://playwright.dev/'); + await page.goto('https://playwright.dev/') // Click the get started link. - await page.getByRole('link', { name: 'Get started' }).click(); + await page.getByRole('link', { name: 'Get started' }).click() // Expects page to have a heading with the name of Installation. - await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible(); -}); + await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible() +}) diff --git a/tests/frontpage.spec.js b/tests/frontpage.spec.js index cf24e914ee..3363ad6954 100644 --- a/tests/frontpage.spec.js +++ b/tests/frontpage.spec.js @@ -1,4 +1,4 @@ -const { test, describe, expect, beforeEach } = require('@playwright/test') +const { test, describe, expect } = require('@playwright/test') describe('Pokedex', () => { test('front page can be opened', async ({ page }) => { From ff25aebf48bf9b6eb1c5e54c5db8af64a4db149a Mon Sep 17 00:00:00 2001 From: Vasilis Date: Tue, 13 Aug 2024 15:51:48 +0200 Subject: [PATCH 17/51] only playwright tests --- .github/workflows/pipeline.yml | 2 -- package.json | 1 - 2 files changed, 3 deletions(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 2804313a9b..3403b53257 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -19,7 +19,5 @@ jobs: run: npm run lint - name: Build run: npm run build - - name: Run tests - run: npm test - name: Run playWright test run: npm run test:e2e \ No newline at end of file diff --git a/package.json b/package.json index 57cb219ef7..32c911d0ab 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,6 @@ "scripts": { "start": "webpack-dev-server --open --mode development", "start-prod": "node app.js", - "test": "jest", "test:e2e": "playwright test", "lint": "eslint **/*.{js,jsx}", "build": "webpack --mode production" From 898a9c180978f3bb1f2dea543c69df50b47169e5 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Tue, 13 Aug 2024 15:56:13 +0200 Subject: [PATCH 18/51] only playwright tests --- .github/workflows/pipeline.yml | 2 +- .github/workflows/playwright.yml | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/playwright.yml diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 3403b53257..c0da75a60c 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -20,4 +20,4 @@ jobs: - name: Build run: npm run build - name: Run playWright test - run: npm run test:e2e \ No newline at end of file + run: npx playwright install && npm run test:e2e \ No newline at end of file diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 0000000000..467190be66 --- /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 From 3af131498eb2e5a3565ef435932074950d3236f5 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Tue, 13 Aug 2024 16:01:15 +0200 Subject: [PATCH 19/51] extra yaml file for playwright install --- .github/workflows/pipeline.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index c0da75a60c..cbe53abf7b 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -14,10 +14,10 @@ jobs: with: node-version: '20' - name: Install dependencies - run: npm install + run: npm install ci - name: Check style run: npm run lint - name: Build run: npm run build - name: Run playWright test - run: npx playwright install && npm run test:e2e \ No newline at end of file + run: npx playwright install --with-deps && npm run test:e2e \ No newline at end of file From e4e1fb7266a5f474e73366c4d28e674b0a331595 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Tue, 13 Aug 2024 16:40:46 +0200 Subject: [PATCH 20/51] build_step file added --- .github/workflows/pipeline.yml | 4 +++- app.js | 4 ++++ build_step.sh | 0 3 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 build_step.sh diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index cbe53abf7b..ed438dc638 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -20,4 +20,6 @@ jobs: - name: Build run: npm run build - name: Run playWright test - run: npx playwright install --with-deps && npm run test:e2e \ No newline at end of file + run: npx playwright install --with-deps && npm run test:e2e + - name: 'Change ownership build file' + run: chmod -v +x build_step.sh && ./build_step.sh \ No newline at end of file diff --git a/app.js b/app.js index effa6d37e3..4a482eb73b 100644 --- a/app.js +++ b/app.js @@ -10,3 +10,7 @@ app.use(express.static("dist")) app.listen(PORT, () => { console.log(`server started on port ${PORT}`) }) + +app.get('/version', (req, res) => { + res.send('1') // change this string to ensure a new version deployed +}) diff --git a/build_step.sh b/build_step.sh new file mode 100644 index 0000000000..e69de29bb2 From 010435f33905da8a9e59749a987e7c5d43d4b729 Mon Sep 17 00:00:00 2001 From: Vasilis <107199128+tomavasi@users.noreply.github.com> Date: Tue, 13 Aug 2024 16:43:50 +0200 Subject: [PATCH 21/51] Update build_step.sh --- build_step.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/build_step.sh b/build_step.sh index e69de29bb2..903f9c6c42 100644 --- a/build_step.sh +++ b/build_step.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +echo "Build script" + +# add the commands here + +npm install From abea2165380c98c919ad5706230a52e9afd272a1 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Tue, 13 Aug 2024 16:58:59 +0200 Subject: [PATCH 22/51] change ownership in yml --- .github/workflows/pipeline.yml | 2 +- build_step.sh | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index ed438dc638..6954108583 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -22,4 +22,4 @@ jobs: - name: Run playWright test run: npx playwright install --with-deps && npm run test:e2e - name: 'Change ownership build file' - run: chmod -v +x build_step.sh && ./build_step.sh \ No newline at end of file + run: chmod -v +x build_step.sh \ No newline at end of file diff --git a/build_step.sh b/build_step.sh index e69de29bb2..79bf8a4154 100644 --- a/build_step.sh +++ b/build_step.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +echo "Build script" + +# add the commands here + +npm install +npm build \ No newline at end of file From 4a406bcf8b7b497804db299de63b7d6c2a76a746 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Tue, 13 Aug 2024 17:17:56 +0200 Subject: [PATCH 23/51] render pipeline deploy --- .github/workflows/pipeline.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 6954108583..4ae665458a 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -22,4 +22,10 @@ jobs: - name: Run playWright test run: npx playwright install --with-deps && npm run test:e2e - name: 'Change ownership build file' - run: chmod -v +x build_step.sh \ No newline at end of file + run: chmod -v +x build_step.sh + - name: Deploy to production + uses: johnbeynon/render-deploy-action@v0.0.8 + with: + service-id: ${{ secrets.RENDER_SERVICE_ID }} + api-key: ${{ secrets.RENDER_API }} + wait-for-success: true \ No newline at end of file From 7fe8ef47ac61a45391ffc542bef37f3832d69523 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Tue, 13 Aug 2024 17:45:41 +0200 Subject: [PATCH 24/51] small change in pipeline --- build_step.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_step.sh b/build_step.sh index e989e77b4b..9c8be5b44e 100644 --- a/build_step.sh +++ b/build_step.sh @@ -5,4 +5,4 @@ echo "Build script" # add the commands here npm install -npm build +npm run build From 251456c327d75182781f4641d4b599d9f9cea17b Mon Sep 17 00:00:00 2001 From: Vasilis Date: Tue, 13 Aug 2024 17:52:26 +0200 Subject: [PATCH 25/51] change in app.js --- app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.js b/app.js index 4a482eb73b..3aaca7721d 100644 --- a/app.js +++ b/app.js @@ -1,4 +1,4 @@ -import express from "express" +const express = require("express") const app = express() From a366d273a773c95f048ebf4a51057e4fc8107060 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Tue, 13 Aug 2024 18:54:10 +0200 Subject: [PATCH 26/51] app health --- app.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app.js b/app.js index 3aaca7721d..9c28dea04c 100644 --- a/app.js +++ b/app.js @@ -14,3 +14,7 @@ app.listen(PORT, () => { app.get('/version', (req, res) => { res.send('1') // change this string to ensure a new version deployed }) + +app.get('/health', (req, res) => { + res.send('ok') +}) From b9c8e2aeebca54d1fe0be2eff43b37911c94b48d Mon Sep 17 00:00:00 2001 From: Vasilis <107199128+tomavasi@users.noreply.github.com> Date: Tue, 13 Aug 2024 18:59:45 +0200 Subject: [PATCH 27/51] Update app.js --- app.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app.js b/app.js index 9c28dea04c..02a1541dcb 100644 --- a/app.js +++ b/app.js @@ -16,5 +16,7 @@ app.get('/version', (req, res) => { }) app.get('/health', (req, res) => { + // eslint-disable-next-line no-constant-condition + if (true) throw('error... ') res.send('ok') }) From 40739e95f7cbdb86fd53066600404dd7663048ca Mon Sep 17 00:00:00 2001 From: Vasilis <107199128+tomavasi@users.noreply.github.com> Date: Tue, 13 Aug 2024 19:04:28 +0200 Subject: [PATCH 28/51] Update app.js --- app.js | 1 - 1 file changed, 1 deletion(-) diff --git a/app.js b/app.js index 02a1541dcb..be213b98d4 100644 --- a/app.js +++ b/app.js @@ -17,6 +17,5 @@ app.get('/version', (req, res) => { app.get('/health', (req, res) => { // eslint-disable-next-line no-constant-condition - if (true) throw('error... ') res.send('ok') }) From 47ed76773bed4e0a0fc96ef8c5ef48452375b4b6 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Tue, 13 Aug 2024 19:28:40 +0200 Subject: [PATCH 29/51] pipeline changes --- .github/workflows/pipeline.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 4ae665458a..c2528b8261 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -4,6 +4,9 @@ on: push: branches: - main + pull_request: + branches: [main] + types: [opened, synchronize] jobs: simple_deployment_pipeline: From 18bbd400ddf9e2700677f404295e1278a7f224e4 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Tue, 13 Aug 2024 20:13:26 +0200 Subject: [PATCH 30/51] deploy only in merge/push --- .github/workflows/pipeline.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index c2528b8261..28c50b061e 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -26,6 +26,7 @@ jobs: run: npx playwright install --with-deps && npm run test:e2e - name: 'Change ownership build file' run: chmod -v +x build_step.sh + if: ${{ github.event_name == 'push' }} - name: Deploy to production uses: johnbeynon/render-deploy-action@v0.0.8 with: From f53de32964ea6c786b742de5181cfd9af0d23104 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Tue, 13 Aug 2024 20:15:16 +0200 Subject: [PATCH 31/51] actions on secondary --- .github/workflows/pipeline.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 28c50b061e..264c1cfb8d 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -4,6 +4,7 @@ on: push: branches: - main + - secondary pull_request: branches: [main] types: [opened, synchronize] From 34a80d27f04522cf2d953d5b4a0daed084f28364 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Tue, 13 Aug 2024 20:21:59 +0200 Subject: [PATCH 32/51] changes on yml file --- .github/workflows/pipeline.yml | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 264c1cfb8d..9b1c68f310 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -4,30 +4,36 @@ on: push: branches: - main - - secondary + - sescondary pull_request: branches: [main] types: [opened, synchronize] jobs: - simple_deployment_pipeline: + build_and_test: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '20' - - name: Install dependencies - run: npm install ci + - name: Install dependencies + run: npm ci - name: Check style run: npm run lint - name: Build run: npm run build - name: Run playWright test run: npx playwright install --with-deps && npm run test:e2e + + deploy: + needs: build_and_test + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v4 - name: 'Change ownership build file' run: chmod -v +x build_step.sh - if: ${{ github.event_name == 'push' }} - name: Deploy to production uses: johnbeynon/render-deploy-action@v0.0.8 with: From cd18979673f916619d0ef125bbb36874cfb811ae Mon Sep 17 00:00:00 2001 From: Vasilis Date: Tue, 13 Aug 2024 20:27:28 +0200 Subject: [PATCH 33/51] small change pipeline --- .github/workflows/pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 9b1c68f310..74d6221ee0 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -4,7 +4,7 @@ on: push: branches: - main - - sescondary + - secondary pull_request: branches: [main] types: [opened, synchronize] From b0c93917934c5af19b3b981e0e73f9ca46041d6e Mon Sep 17 00:00:00 2001 From: Vasilis Date: Wed, 14 Aug 2024 11:18:34 +0200 Subject: [PATCH 34/51] versioning --- .github/workflows/pipeline.yml | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 74d6221ee0..c0829f3b37 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -6,8 +6,8 @@ on: - main - secondary pull_request: - branches: [main] - types: [opened, synchronize] + branches: [main, master] + types: [opened, synchronize, closed] jobs: build_and_test: @@ -39,4 +39,26 @@ jobs: with: service-id: ${{ secrets.RENDER_SERVICE_ID }} api-key: ${{ secrets.RENDER_API }} - wait-for-success: true \ No newline at end of file + wait-for-success: true + + versioning: + needs: deploy + if: github.event.pull_request.merged == true + runs-on: ubuntu-22.04 + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.merge_commit_sha }} + fetch-depth: '0' + + - name: Bump version and push tag + uses: anothrNick/github-tag-action@v1 # Don't use @master or @v1 unless you're happy to test the latest version + env: + GITHUB_TOKEN: ${{ secrets.TOKEN_GITHUB }} # if you don't want to set write permissions use a PAT token + DEFAULT_BUMP: 'patch' + WITH_V: true + PRERELEASE: true + + From 092d390dc4655e3e0a51272b4067bef819c9e346 Mon Sep 17 00:00:00 2001 From: Vasilis <107199128+tomavasi@users.noreply.github.com> Date: Wed, 14 Aug 2024 11:38:30 +0200 Subject: [PATCH 35/51] Update pipeline.yml --- .github/workflows/pipeline.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index c0829f3b37..33fcaba285 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -7,7 +7,10 @@ on: - secondary pull_request: branches: [main, master] - types: [opened, synchronize, closed] + types: + - opened + - synchronize + - closed jobs: build_and_test: @@ -44,15 +47,11 @@ jobs: versioning: needs: deploy if: github.event.pull_request.merged == true - runs-on: ubuntu-22.04 + runs-on: ubuntu-20.04 permissions: contents: write steps: - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.merge_commit_sha }} - fetch-depth: '0' - - name: Bump version and push tag uses: anothrNick/github-tag-action@v1 # Don't use @master or @v1 unless you're happy to test the latest version env: From b06593ec255d14f0875517c50db5d9c1e637d240 Mon Sep 17 00:00:00 2001 From: Vasilis <107199128+tomavasi@users.noreply.github.com> Date: Wed, 14 Aug 2024 11:44:19 +0200 Subject: [PATCH 36/51] Update2 pipeline.yml --- .github/workflows/pipeline.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 33fcaba285..8280177e4f 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -46,7 +46,7 @@ jobs: versioning: needs: deploy - if: github.event.pull_request.merged == true + if: github.event_name == 'push' && github.ref == 'refs/heads/main' runs-on: ubuntu-20.04 permissions: contents: write From 50744fc9ffeea16ae77e98a512a1204570ae4371 Mon Sep 17 00:00:00 2001 From: Vasilis <107199128+tomavasi@users.noreply.github.com> Date: Wed, 14 Aug 2024 12:12:48 +0200 Subject: [PATCH 37/51] Update and skip hello.yml --- .github/workflows/hello.yml | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/.github/workflows/hello.yml b/.github/workflows/hello.yml index 088937e855..1e09706b89 100644 --- a/.github/workflows/hello.yml +++ b/.github/workflows/hello.yml @@ -3,18 +3,22 @@ name: Hello World! on: push: branches: - - main + - secondary jobs: - hello_world_job: + a_test_job: runs-on: ubuntu-20.04 steps: - - name: Say hello - run: | - echo "Hello World!" - - name: Now it is - run: | - date -u - - name: Directory content - run: | - ls -l + - uses: actions/checkout@v4 + - name: github context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - name: commits + env: + COMMITS: ${{ toJson(github.event.commits) }} + run: echo "$COMMITS" + - name: commit messages + env: + COMMIT_MESSAGES: ${{ toJson(github.event.commits.*.message) }} + run: echo "$COMMIT_MESSAGES" From f401644385a9469e143bc8eb7e61bea55cc9b380 Mon Sep 17 00:00:00 2001 From: Vasilis <107199128+tomavasi@users.noreply.github.com> Date: Wed, 14 Aug 2024 12:15:46 +0200 Subject: [PATCH 38/51] Update and skip playwright.yml --- .github/workflows/playwright.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 467190be66..533886563d 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -1,9 +1,11 @@ name: Playwright Tests on: push: - branches: [ main, master ] + branches: + - secondary pull_request: - branches: [ main, master ] + branches: + - secondary jobs: test: timeout-minutes: 60 From 06cebd0577a248601bff9a01d6e9a879c01172c2 Mon Sep 17 00:00:00 2001 From: Vasilis <107199128+tomavasi@users.noreply.github.com> Date: Wed, 14 Aug 2024 12:17:42 +0200 Subject: [PATCH 39/51] Update and skip playwright.yml --- .github/workflows/playwright.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 467190be66..763407b3b6 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -1,9 +1,7 @@ name: Playwright Tests on: push: - branches: [ main, master ] - pull_request: - branches: [ main, master ] + branches: [ secondary ] jobs: test: timeout-minutes: 60 From 8f727e4c96ede2e68908837b2ad1651f3256946a Mon Sep 17 00:00:00 2001 From: Vasilis Date: Wed, 14 Aug 2024 12:18:37 +0200 Subject: [PATCH 40/51] some changes --- .github/workflows/pipeline.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index c0829f3b37..33fcaba285 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -7,7 +7,10 @@ on: - secondary pull_request: branches: [main, master] - types: [opened, synchronize, closed] + types: + - opened + - synchronize + - closed jobs: build_and_test: @@ -44,15 +47,11 @@ jobs: versioning: needs: deploy if: github.event.pull_request.merged == true - runs-on: ubuntu-22.04 + runs-on: ubuntu-20.04 permissions: contents: write steps: - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.merge_commit_sha }} - fetch-depth: '0' - - name: Bump version and push tag uses: anothrNick/github-tag-action@v1 # Don't use @master or @v1 unless you're happy to test the latest version env: From 3801a82cdc5b9a3c2e850e5aadd9ecf6a9c37b8f Mon Sep 17 00:00:00 2001 From: Vasilis <107199128+tomavasi@users.noreply.github.com> Date: Wed, 14 Aug 2024 12:25:26 +0200 Subject: [PATCH 41/51] Update hello.yml --- .github/workflows/hello.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/hello.yml b/.github/workflows/hello.yml index 1e09706b89..5a56cacc44 100644 --- a/.github/workflows/hello.yml +++ b/.github/workflows/hello.yml @@ -4,10 +4,13 @@ on: push: branches: - secondary - +env: + COMMITS: ${{ (github.event.commits) }} + CONDITION: ${{ constains("$COMMITS", 'skip') }} jobs: a_test_job: runs-on: ubuntu-20.04 + if: ${{ github.env.CONDITION == 'true' }} steps: - uses: actions/checkout@v4 - name: github context @@ -15,9 +18,7 @@ jobs: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - name: commits - env: - COMMITS: ${{ toJson(github.event.commits) }} - run: echo "$COMMITS" + run: echo "something" - name: commit messages env: COMMIT_MESSAGES: ${{ toJson(github.event.commits.*.message) }} From 3d15e8f35b0f7cb995d79728cd0dcf3959ab35a7 Mon Sep 17 00:00:00 2001 From: Vasilis <107199128+tomavasi@users.noreply.github.com> Date: Wed, 14 Aug 2024 12:25:57 +0200 Subject: [PATCH 42/51] Update hello.yml --- .github/workflows/hello.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/hello.yml b/.github/workflows/hello.yml index 5a56cacc44..b32f73ea7b 100644 --- a/.github/workflows/hello.yml +++ b/.github/workflows/hello.yml @@ -6,7 +6,7 @@ on: - secondary env: COMMITS: ${{ (github.event.commits) }} - CONDITION: ${{ constains("$COMMITS", 'skip') }} + CONDITION: ${{ conntains("$COMMITS", 'skip') }} jobs: a_test_job: runs-on: ubuntu-20.04 From 2652db73294911ed995b15db67c1740d2e99ca63 Mon Sep 17 00:00:00 2001 From: Vasilis <107199128+tomavasi@users.noreply.github.com> Date: Wed, 14 Aug 2024 12:26:17 +0200 Subject: [PATCH 43/51] Update hello.yml --- .github/workflows/hello.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/hello.yml b/.github/workflows/hello.yml index b32f73ea7b..61e79fbf2b 100644 --- a/.github/workflows/hello.yml +++ b/.github/workflows/hello.yml @@ -6,7 +6,7 @@ on: - secondary env: COMMITS: ${{ (github.event.commits) }} - CONDITION: ${{ conntains("$COMMITS", 'skip') }} + CONDITION: ${{ contains("$COMMITS", 'skip') }} jobs: a_test_job: runs-on: ubuntu-20.04 From 9a24e805968235a224781ecdd7fe4b2ce000178b Mon Sep 17 00:00:00 2001 From: Vasilis <107199128+tomavasi@users.noreply.github.com> Date: Wed, 14 Aug 2024 12:27:31 +0200 Subject: [PATCH 44/51] Update hello.yml --- .github/workflows/hello.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/hello.yml b/.github/workflows/hello.yml index 61e79fbf2b..0f55da52bb 100644 --- a/.github/workflows/hello.yml +++ b/.github/workflows/hello.yml @@ -6,7 +6,7 @@ on: - secondary env: COMMITS: ${{ (github.event.commits) }} - CONDITION: ${{ contains("$COMMITS", 'skip') }} + CONDITION: ${{ contains(env.COMMITS, 'skip') }} jobs: a_test_job: runs-on: ubuntu-20.04 From cb65e5629a7aa76b2a1194649eede4c744b12a38 Mon Sep 17 00:00:00 2001 From: Vasilis <107199128+tomavasi@users.noreply.github.com> Date: Wed, 14 Aug 2024 12:28:06 +0200 Subject: [PATCH 45/51] Update hello.yml --- .github/workflows/hello.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/hello.yml b/.github/workflows/hello.yml index 0f55da52bb..036d72b45b 100644 --- a/.github/workflows/hello.yml +++ b/.github/workflows/hello.yml @@ -6,7 +6,7 @@ on: - secondary env: COMMITS: ${{ (github.event.commits) }} - CONDITION: ${{ contains(env.COMMITS, 'skip') }} + CONDITION: ${{ contains(COMMITS, 'skip') }} jobs: a_test_job: runs-on: ubuntu-20.04 From 85470139aaec452adab9f7224425db5dbfbf554f Mon Sep 17 00:00:00 2001 From: Vasilis <107199128+tomavasi@users.noreply.github.com> Date: Wed, 14 Aug 2024 12:29:24 +0200 Subject: [PATCH 46/51] Update hello.yml --- .github/workflows/hello.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/hello.yml b/.github/workflows/hello.yml index 036d72b45b..a7f20e4293 100644 --- a/.github/workflows/hello.yml +++ b/.github/workflows/hello.yml @@ -5,8 +5,7 @@ on: branches: - secondary env: - COMMITS: ${{ (github.event.commits) }} - CONDITION: ${{ contains(COMMITS, 'skip') }} + CONDITION: ${{ contains(github.event.commits, 'skip') }} jobs: a_test_job: runs-on: ubuntu-20.04 From 023ed2d33d8625abda7a6ad0eca0dc0005d105d3 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Wed, 14 Aug 2024 12:33:54 +0200 Subject: [PATCH 47/51] skip deployement and tagging --- .github/workflows/pipeline.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 8280177e4f..59d7692ba7 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -11,6 +11,8 @@ on: - opened - synchronize - closed +env: + CONDITION: ${{ contains(github.event.commits, 'skip') }} jobs: build_and_test: @@ -31,7 +33,7 @@ jobs: deploy: needs: build_and_test - if: github.event_name == 'push' && github.ref == 'refs/heads/main' + if: github.event_name == 'push' && github.ref == 'refs/heads/main' && ${{ github.env.CONDITION == 'false' }} runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v4 @@ -46,7 +48,7 @@ jobs: versioning: needs: deploy - if: github.event_name == 'push' && github.ref == 'refs/heads/main' + if: github.event_name == 'push' && github.ref == 'refs/heads/main' && ${{ github.env.CONDITION == 'false' }} runs-on: ubuntu-20.04 permissions: contents: write From 8701c624fd334b09a7663f163a1a051bb89fdb9d Mon Sep 17 00:00:00 2001 From: Vasilis Date: Wed, 14 Aug 2024 12:51:25 +0200 Subject: [PATCH 48/51] skip all --- .github/workflows/pipeline.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 59d7692ba7..71cdf0bcff 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -33,7 +33,7 @@ jobs: deploy: needs: build_and_test - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && ${{ github.env.CONDITION == 'false' }} + if: github.event_name == 'push' && github.ref == 'refs/heads/main' && !contains(github.event.head_commit.message, 'skip') runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v4 @@ -48,7 +48,7 @@ jobs: versioning: needs: deploy - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && ${{ github.env.CONDITION == 'false' }} + if: github.event_name == 'push' && github.ref == 'refs/heads/main' && !contains(github.event.head_commit.message, 'skip') runs-on: ubuntu-20.04 permissions: contents: write From 9cc0d18f9e803fc603d72bad26467918b39f3ec3 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Wed, 14 Aug 2024 13:03:41 +0200 Subject: [PATCH 49/51] [skip] --- .github/workflows/hello.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/hello.yml b/.github/workflows/hello.yml index a7f20e4293..b236a58bff 100644 --- a/.github/workflows/hello.yml +++ b/.github/workflows/hello.yml @@ -4,12 +4,12 @@ on: push: branches: - secondary + - main env: CONDITION: ${{ contains(github.event.commits, 'skip') }} jobs: a_test_job: runs-on: ubuntu-20.04 - if: ${{ github.env.CONDITION == 'true' }} steps: - uses: actions/checkout@v4 - name: github context From 5090cdb5373a05a99020a566f78e36da0606a17d Mon Sep 17 00:00:00 2001 From: Vasilis Date: Wed, 14 Aug 2024 14:46:28 +0200 Subject: [PATCH 50/51] testing webhooks --- .github/workflows/pipeline.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 71cdf0bcff..8a7921edc3 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -30,6 +30,19 @@ jobs: run: npm run build - name: Run playWright test run: npx playwright install --with-deps && npm run test:e2e + + notify: + needs: build_and_test + runs-on: ubuntu-20.04 + steps: + - name: Build Success + uses: rjstone/discord-webhook-notify@v1 + if: success() + with: + severity: info + details: Test webook Succeeded! + webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} + deploy: needs: build_and_test @@ -61,5 +74,7 @@ jobs: DEFAULT_BUMP: 'patch' WITH_V: true PRERELEASE: true + + From 42b6264e8ac7e3cb953ef0f47c24e48256fdade1 Mon Sep 17 00:00:00 2001 From: Vasilis Date: Wed, 14 Aug 2024 17:27:07 +0200 Subject: [PATCH 51/51] health check added #skip --- .github/workflows/healthCheck.yml | 18 ++++++++++++++++++ .github/workflows/hello.yml | 24 ------------------------ .github/workflows/pipeline.yml | 30 +++++++++++++++++++----------- .github/workflows/playwright.yml | 25 ------------------------- 4 files changed, 37 insertions(+), 60 deletions(-) create mode 100644 .github/workflows/healthCheck.yml delete mode 100644 .github/workflows/hello.yml delete mode 100644 .github/workflows/playwright.yml diff --git a/.github/workflows/healthCheck.yml b/.github/workflows/healthCheck.yml new file mode 100644 index 0000000000..05980e940e --- /dev/null +++ b/.github/workflows/healthCheck.yml @@ -0,0 +1,18 @@ +name: Health check + +on: + schedule: + - cron: '0 0 * * *' + +jobs: + check-health: + runs-on: ubuntu-20.04 + steps: + - name: Check the deployed service URL + uses: jtalk/url-health-check-action@v4 + with: + url: https://full-stack-open-pokedex-cvtb.onrender.com/health + follow-redirect: false + max-attempts: 3 + retry-delay: 5s + retry-all: false \ No newline at end of file diff --git a/.github/workflows/hello.yml b/.github/workflows/hello.yml deleted file mode 100644 index b236a58bff..0000000000 --- a/.github/workflows/hello.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Hello World! - -on: - push: - branches: - - secondary - - main -env: - CONDITION: ${{ contains(github.event.commits, 'skip') }} -jobs: - a_test_job: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v4 - - name: github context - env: - GITHUB_CONTEXT: ${{ toJson(github) }} - run: echo "$GITHUB_CONTEXT" - - name: commits - run: echo "something" - - name: commit messages - env: - COMMIT_MESSAGES: ${{ toJson(github.event.commits.*.message) }} - run: echo "$COMMIT_MESSAGES" diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 8a7921edc3..2a4bda6f94 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -4,15 +4,11 @@ on: push: branches: - main - - secondary pull_request: branches: [main, master] types: - opened - synchronize - - closed -env: - CONDITION: ${{ contains(github.event.commits, 'skip') }} jobs: build_and_test: @@ -31,22 +27,22 @@ jobs: - name: Run playWright test run: npx playwright install --with-deps && npm run test:e2e - notify: + notify-build: needs: build_and_test runs-on: ubuntu-20.04 steps: - name: Build Success uses: rjstone/discord-webhook-notify@v1 - if: success() + if: failure() with: - severity: info + severity: warn details: Test webook Succeeded! webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} deploy: needs: build_and_test - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && !contains(github.event.head_commit.message, 'skip') + if: ${{ github.event_name == 'push' && !contains(join(github.event.commits.*.message, ' '), '#skip') }} runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v4 @@ -58,19 +54,31 @@ jobs: service-id: ${{ secrets.RENDER_SERVICE_ID }} api-key: ${{ secrets.RENDER_API }} wait-for-success: true + + notify-deploy: + needs: deploy + runs-on: ubuntu-20.04 + steps: + - name: Deployment Success + uses: rjstone/discord-webhook-notify@v1 + if: success() + with: + severity: info + details: Deplyoment successful! + webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} versioning: needs: deploy - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && !contains(github.event.head_commit.message, 'skip') + if: ${{ github.event_name == 'push' && !contains(join(github.event.commits.*.message, ' '), '#skip') }} runs-on: ubuntu-20.04 permissions: contents: write steps: - uses: actions/checkout@v4 - name: Bump version and push tag - uses: anothrNick/github-tag-action@v1 # Don't use @master or @v1 unless you're happy to test the latest version + uses: anothrNick/github-tag-action@v1 env: - GITHUB_TOKEN: ${{ secrets.TOKEN_GITHUB }} # if you don't want to set write permissions use a PAT token + GITHUB_TOKEN: ${{ secrets.TOKEN_GITHUB }} DEFAULT_BUMP: 'patch' WITH_V: true PRERELEASE: true diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml deleted file mode 100644 index 763407b3b6..0000000000 --- a/.github/workflows/playwright.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Playwright Tests -on: - push: - branches: [ secondary ] -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