From 2a3d7bcad9b5617bcfa00092f3adc6de43bfb7ef Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Tue, 1 Jul 2025 11:27:59 +0200
Subject: [PATCH 01/14] 4565: Added playwright github action
---
.github/workflows/pr.yaml | 28 ++++++++++++++++++++++++++++
CHANGELOG.md | 1 +
2 files changed, 29 insertions(+)
diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml
index 87882f18..f54def6a 100644
--- a/.github/workflows/pr.yaml
+++ b/.github/workflows/pr.yaml
@@ -263,3 +263,31 @@ jobs:
- name: Check for changes in specifications (json)
run: git diff --diff-filter=ACMRT --exit-code public/api-spec-v2.json
+
+ frontend-build-and-test:
+ name: Playwright
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup network
+ run: docker network create frontend
+
+ - name: Run playwright
+ env:
+ CI: 'true'
+ run: |
+ docker compose run --rm node npm install
+ docker compose run --rm node npm run install
+ docker compose run --rm playwright npx playwright install --with-deps
+ docker compose run --rm playwright npx playwright test --retries 3
+
+ - uses: actions/upload-artifact@v4
+ if: always()
+ with:
+ name: playwright-report
+ path: playwright-report/
+ retention-days: 30
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 91ad6d86..3e9902fb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file.
* Added ADRs 008 and 009.
* Cleaned up Github Actions workflows.
* Updated PHP dependencies.
+* Added Playwright github action.
### NB! Prior to 3.x the project was split into separate repositories
From 8afd022f32550ecd7f8027a78af60f93131f3f21 Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Tue, 1 Jul 2025 11:31:31 +0200
Subject: [PATCH 02/14] 4565: Fixed npm run build
---
.github/workflows/pr.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml
index f54def6a..04155328 100644
--- a/.github/workflows/pr.yaml
+++ b/.github/workflows/pr.yaml
@@ -281,7 +281,7 @@ jobs:
CI: 'true'
run: |
docker compose run --rm node npm install
- docker compose run --rm node npm run install
+ docker compose run --rm node npm run build
docker compose run --rm playwright npx playwright install --with-deps
docker compose run --rm playwright npx playwright test --retries 3
From b3e99c8b49dc83e4211dbf4bab47a3e9d5b95ac9 Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Wed, 2 Jul 2025 17:50:51 +0200
Subject: [PATCH 03/14] 4565: Fixed playwright github setup. Added test readme.
Changed to @vitejs/plugin-react-oxc
---
.github/workflows/composer.yaml | 3 +-
.github/workflows/pr.yaml | 1 -
docker-compose.override.yml | 6 +-
docs/test.md | 45 ++++++
package-lock.json | 270 +++-----------------------------
package.json | 4 +-
playwright.config.ts | 6 +-
vite.config.js | 9 +-
8 files changed, 81 insertions(+), 263 deletions(-)
create mode 100644 docs/test.md
diff --git a/.github/workflows/composer.yaml b/.github/workflows/composer.yaml
index 1bdcc571..6e60167b 100644
--- a/.github/workflows/composer.yaml
+++ b/.github/workflows/composer.yaml
@@ -65,5 +65,4 @@ jobs:
- uses: actions/checkout@v4
- run: |
docker network create frontend
- docker compose run --rm phpfpm composer install
- docker compose run --rm phpfpm composer audit
+ docker compose run --rm phpfpm composer audit --locked
diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml
index 04155328..3e498363 100644
--- a/.github/workflows/pr.yaml
+++ b/.github/workflows/pr.yaml
@@ -282,7 +282,6 @@ jobs:
run: |
docker compose run --rm node npm install
docker compose run --rm node npm run build
- docker compose run --rm playwright npx playwright install --with-deps
docker compose run --rm playwright npx playwright test --retries 3
- uses: actions/upload-artifact@v4
diff --git a/docker-compose.override.yml b/docker-compose.override.yml
index a831755c..e4b15ad3 100644
--- a/docker-compose.override.yml
+++ b/docker-compose.override.yml
@@ -1,8 +1,4 @@
services:
- phpfpm:
- environment:
- - PHP_MEMORY_LIMIT=512M
-
nginx:
labels:
# HTTPS config - uncomment to enable redirect from :80 to :443
@@ -30,7 +26,7 @@ services:
playwright:
# https://playwright.dev/docs/docker
# This Playwright version should match the one in `package.json`.
- image: mcr.microsoft.com/playwright:v1.52.0
+ image: mcr.microsoft.com/playwright:v1.53.2-noble
networks:
- app
depends_on:
diff --git a/docs/test.md b/docs/test.md
new file mode 100644
index 00000000..1fb947d9
--- /dev/null
+++ b/docs/test.md
@@ -0,0 +1,45 @@
+# Test
+
+## Playwright
+
+To test the React apps we use playwright.
+
+### Updating Playwright
+
+It is important that the versions of the playwright container and the library imported in package.json align.
+
+See the `docker-compose.override.yml` playwright entry and the version imported in package.json.
+
+### Dev mode
+
+To run tests locally, there are a few options.
+
+To run from the developer machine:
+
+```shell
+BASE_URL="https://display.local.itkdev.dk" npx playwright test template
+```
+
+In interactive mode:
+
+```shell
+BASE_URL="https://display.local.itkdev.dk" npx playwright test template --ui
+```
+
+### Prod mode
+
+Another option is to run the tests on the built javascript assets through the playwright container.
+This is the option that runs in Github Actions.
+
+```shell
+# Stop the node container, to avoid Vite build dev assets.
+docker compose stop node
+
+# Build the assets
+docker compose run --rm node npm run build
+
+# Run the test
+docker compose run --rm playwright npx playwright test
+
+# To return to vite dev mode, restart the node container.
+```
diff --git a/package-lock.json b/package-lock.json
index 74f6a777..5a6cc0d9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -57,10 +57,10 @@
"ulid": "^2.3.0"
},
"devDependencies": {
- "@playwright/test": "^1.52.0",
+ "@playwright/test": "1.53.2",
"@reduxjs/toolkit": "^1.6.1",
"@vitejs/plugin-react": "^4.6.0",
- "@vitejs/plugin-react-swc": "^3.10.2",
+ "@vitejs/plugin-react-oxc": "^0.2.3",
"sass": "^1.88.9",
"typescript": "^4.4.2",
"vite": "npm:rolldown-vite@^7.0.3",
@@ -1721,13 +1721,13 @@
}
},
"node_modules/@playwright/test": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.52.0.tgz",
- "integrity": "sha512-uh6W7sb55hl7D6vsAeA+V2p5JnlAqzhqFyF0VcJkKZXkgnFcVG9PziERRHQfPLfNGx1C292a4JqbWzhR8L4R1g==",
+ "version": "1.53.2",
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.53.2.tgz",
+ "integrity": "sha512-tEB2U5z74ebBeyfGNZ3Jfg29AnW+5HlWhvHtb/Mqco9pFdZU1ZLNdVb2UtB5CvmiilNr2ZfVH/qMmAROG/XTzw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "playwright": "1.52.0"
+ "playwright": "1.53.2"
},
"bin": {
"playwright": "cli.js"
@@ -2614,232 +2614,6 @@
"@svgr/core": "*"
}
},
- "node_modules/@swc/core": {
- "version": "1.12.7",
- "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.12.7.tgz",
- "integrity": "sha512-bcpllEihyUSnqp0UtXTvXc19CT4wp3tGWLENhWnjr4B5iEOkzqMu+xHGz1FI5IBatjfqOQb29tgIfv6IL05QaA==",
- "dev": true,
- "hasInstallScript": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@swc/counter": "^0.1.3",
- "@swc/types": "^0.1.23"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/swc"
- },
- "optionalDependencies": {
- "@swc/core-darwin-arm64": "1.12.7",
- "@swc/core-darwin-x64": "1.12.7",
- "@swc/core-linux-arm-gnueabihf": "1.12.7",
- "@swc/core-linux-arm64-gnu": "1.12.7",
- "@swc/core-linux-arm64-musl": "1.12.7",
- "@swc/core-linux-x64-gnu": "1.12.7",
- "@swc/core-linux-x64-musl": "1.12.7",
- "@swc/core-win32-arm64-msvc": "1.12.7",
- "@swc/core-win32-ia32-msvc": "1.12.7",
- "@swc/core-win32-x64-msvc": "1.12.7"
- },
- "peerDependencies": {
- "@swc/helpers": ">=0.5.17"
- },
- "peerDependenciesMeta": {
- "@swc/helpers": {
- "optional": true
- }
- }
- },
- "node_modules/@swc/core-darwin-arm64": {
- "version": "1.12.7",
- "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.12.7.tgz",
- "integrity": "sha512-w6BBT0hBRS56yS+LbReVym0h+iB7/PpCddqrn1ha94ra4rZ4R/A91A/rkv+LnQlPqU/+fhqdlXtCJU9mrhCBtA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "Apache-2.0 AND MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@swc/core-darwin-x64": {
- "version": "1.12.7",
- "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.12.7.tgz",
- "integrity": "sha512-jN6LhFfGOpm4DY2mXPgwH4aa9GLOwublwMVFFZ/bGnHYYCRitLZs9+JWBbyWs7MyGcA246Ew+EREx36KVEAxjA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "Apache-2.0 AND MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@swc/core-linux-arm-gnueabihf": {
- "version": "1.12.7",
- "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.12.7.tgz",
- "integrity": "sha512-rHn8XXi7G2StEtZRAeJ6c7nhJPDnqsHXmeNrAaYwk8Tvpa6ZYG2nT9E1OQNXj1/dfbSFTjdiA8M8ZvGYBlpBoA==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@swc/core-linux-arm64-gnu": {
- "version": "1.12.7",
- "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.12.7.tgz",
- "integrity": "sha512-N15hKizSSh+hkZ2x3TDVrxq0TDcbvDbkQJi2ZrLb9fK+NdFUV/x+XF16ZDPlbxtrGXl1CT7VD439SNaMN9F7qw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "Apache-2.0 AND MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@swc/core-linux-arm64-musl": {
- "version": "1.12.7",
- "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.12.7.tgz",
- "integrity": "sha512-jxyINtBezpxd3eIUDiDXv7UQ87YWlPsM9KumOwJk09FkFSO4oYxV2RT+Wu+Nt5tVWue4N0MdXT/p7SQsDEk4YA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "Apache-2.0 AND MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@swc/core-linux-x64-gnu": {
- "version": "1.12.7",
- "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.12.7.tgz",
- "integrity": "sha512-PR4tPVwU1BQBfFDk2XfzXxsEIjF3x/bOV1BzZpYvrlkU0TKUDbR4t2wzvsYwD/coW7/yoQmlL70/qnuPtTp1Zw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "Apache-2.0 AND MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@swc/core-linux-x64-musl": {
- "version": "1.12.7",
- "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.12.7.tgz",
- "integrity": "sha512-zy7JWfQtQItgMfUjSbbcS3DZqQUn2d9VuV0LSGpJxtTXwgzhRpF1S2Sj7cU9hGpbM27Y8RJ4DeFb3qbAufjbrw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "Apache-2.0 AND MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@swc/core-win32-arm64-msvc": {
- "version": "1.12.7",
- "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.12.7.tgz",
- "integrity": "sha512-52PeF0tyX04ZFD8nibNhy/GjMFOZWTEWPmIB3wpD1vIJ1po+smtBnEdRRll5WIXITKoiND8AeHlBNBPqcsdcwA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "Apache-2.0 AND MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@swc/core-win32-ia32-msvc": {
- "version": "1.12.7",
- "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.12.7.tgz",
- "integrity": "sha512-WzQwkNMuhB1qQShT9uUgz/mX2j7NIEPExEtzvGsBT7TlZ9j1kGZ8NJcZH/fwOFcSJL4W7DnkL7nAhx6DBlSPaA==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "Apache-2.0 AND MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@swc/core-win32-x64-msvc": {
- "version": "1.12.7",
- "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.12.7.tgz",
- "integrity": "sha512-R52ivBi2lgjl+Bd3XCPum0YfgbZq/W1AUExITysddP9ErsNSwnreYyNB3exEijiazWGcqHEas2ChiuMOP7NYrA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "Apache-2.0 AND MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@swc/counter": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
- "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==",
- "dev": true,
- "license": "Apache-2.0"
- },
- "node_modules/@swc/types": {
- "version": "0.1.23",
- "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.23.tgz",
- "integrity": "sha512-u1iIVZV9Q0jxY+yM2vw/hZGDNudsN85bBpTqzAQ9rzkxW9D+e3aEM4Han+ow518gSewkXgjmEK0BD79ZcNVgPw==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@swc/counter": "^0.1.3"
- }
- },
"node_modules/@tybys/wasm-util": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz",
@@ -3054,21 +2828,23 @@
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0"
}
},
- "node_modules/@vitejs/plugin-react-swc": {
- "version": "3.10.2",
- "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.10.2.tgz",
- "integrity": "sha512-xD3Rdvrt5LgANug7WekBn1KhcvLn1H3jNBfJRL3reeOIua/WnZOEV5qi5qIBq5T8R0jUDmRtxuvk4bPhzGHDWw==",
+ "node_modules/@vitejs/plugin-react-oxc": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-oxc/-/plugin-react-oxc-0.2.3.tgz",
+ "integrity": "sha512-ONriHoEGQv+ITmeJQsHIpx7u1ms8Z68oIo3AdKCoaBTvZtF+AfDVviQ3tKgCTnIbz9NW8V2Rd/Q+5zjzpsht1g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@rolldown/pluginutils": "1.0.0-beta.11",
- "@swc/core": "^1.11.31"
+ "@rolldown/pluginutils": "1.0.0-beta.11"
+ },
+ "engines": {
+ "node": ">=20.0.0"
},
"peerDependencies": {
- "vite": "^4 || ^5 || ^6 || ^7.0.0-beta.0"
+ "vite": "^6.3.0 || ^7.0.0-beta.0"
}
},
- "node_modules/@vitejs/plugin-react-swc/node_modules/@rolldown/pluginutils": {
+ "node_modules/@vitejs/plugin-react-oxc/node_modules/@rolldown/pluginutils": {
"version": "1.0.0-beta.11",
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.11.tgz",
"integrity": "sha512-L/gAA/hyCSuzTF1ftlzUSI/IKr2POHsv1Dd78GfqkR83KMNuswWD61JxGV2L7nRwBBBSDr6R1gCkdTmoN7W4ag==",
@@ -5356,13 +5132,13 @@
"license": "MIT"
},
"node_modules/playwright": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.52.0.tgz",
- "integrity": "sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==",
+ "version": "1.53.2",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.53.2.tgz",
+ "integrity": "sha512-6K/qQxVFuVQhRQhFsVZ9fGeatxirtrpPgxzBYWyZLEXJzqYwuL4fuNmfOfD5et1tJE4GScKyPNeLhZeRwuTU3A==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "playwright-core": "1.52.0"
+ "playwright-core": "1.53.2"
},
"bin": {
"playwright": "cli.js"
@@ -5375,9 +5151,9 @@
}
},
"node_modules/playwright-core": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.52.0.tgz",
- "integrity": "sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==",
+ "version": "1.53.2",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.53.2.tgz",
+ "integrity": "sha512-ox/OytMy+2w1jcYEYlOo1Hhp8hZkLCximMTUTMBXjGUA1KoFfiSZ+DU+3a739jsPY0yoKH2TFy9S2fsJas8yAw==",
"dev": true,
"license": "Apache-2.0",
"bin": {
diff --git a/package.json b/package.json
index 4102d20f..0573d5d2 100644
--- a/package.json
+++ b/package.json
@@ -8,9 +8,9 @@
"build": "vite build"
},
"devDependencies": {
- "@playwright/test": "^1.52.0",
+ "@playwright/test": "1.53.2",
"@vitejs/plugin-react": "^4.6.0",
- "@vitejs/plugin-react-swc": "^3.10.2",
+ "@vitejs/plugin-react-oxc": "^0.2.3",
"@reduxjs/toolkit": "^1.6.1",
"sass": "^1.88.9",
"typescript": "^4.4.2",
diff --git a/playwright.config.ts b/playwright.config.ts
index dde1c703..0a2463bb 100644
--- a/playwright.config.ts
+++ b/playwright.config.ts
@@ -6,6 +6,8 @@ import { defineConfig, devices } from '@playwright/test';
*/
// require('dotenv').config();
+const BASE_URL = process.env.BASE_URL ?? 'http://nginx:8080';
+
/**
* See https://playwright.dev/docs/test-configuration.
*/
@@ -26,9 +28,7 @@ export default defineConfig({
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
// Docker baseurl
- baseURL: 'http://nginx:8080/',
- // for testing locally
- // baseURL: 'https://display.local.itkdev.dk/',
+ baseURL: BASE_URL,
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
diff --git a/vite.config.js b/vite.config.js
index 1a956033..f4d5ef62 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -1,6 +1,6 @@
import {defineConfig} from "vite";
import symfonyPlugin from "vite-plugin-symfony";
-import react from "@vitejs/plugin-react-swc";
+import react from "@vitejs/plugin-react-oxc";
import svgr from "vite-plugin-svgr";
export default defineConfig(({command}) => {
@@ -13,6 +13,9 @@ export default defineConfig(({command}) => {
},
}
},
+ experimental: {
+ enableNativePlugin: true,
+ },
plugins: [
react(),
symfonyPlugin(),
@@ -21,7 +24,6 @@ export default defineConfig(({command}) => {
svgrOptions: {exportType: "default", ref: true, svgo: false, titleProp: true},
include: "**/*.svg",
}),
-
],
build: {
outDir: "./public/build",
@@ -45,7 +47,8 @@ export default defineConfig(({command}) => {
host: "display.local.itkdev.dk",
protocol: "wss",
clientPort: 443,
- }
+ },
+ cors: true,
},
}
});
From 2413ff0e45928e68ff3391ed85613f0cf66e37bb Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Thu, 3 Jul 2025 11:09:12 +0200
Subject: [PATCH 04/14] 4565: Changed to a traeficless setup
---
.docker/templates/default.conf.template | 11 -----------
.github/workflows/pr.yaml | 4 ++--
docker-compose.override.yml | 9 +++------
public/error.html | 8 ++++++++
vite.config.js | 9 +--------
5 files changed, 14 insertions(+), 27 deletions(-)
create mode 100644 public/error.html
diff --git a/.docker/templates/default.conf.template b/.docker/templates/default.conf.template
index 991a5294..61c4e648 100644
--- a/.docker/templates/default.conf.template
+++ b/.docker/templates/default.conf.template
@@ -37,17 +37,6 @@ server {
internal;
}
- location /vite {
- proxy_set_header X-Forwarded-For $remote_addr;
- proxy_set_header Host $http_host;
- proxy_pass http://node:3000;
- proxy_http_version 1.1;
-
- # Enable WebSocket support for HMR
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection "upgrade";
- }
-
location ~ \.php$ {
return 404;
}
diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml
index 3e498363..19923150 100644
--- a/.github/workflows/pr.yaml
+++ b/.github/workflows/pr.yaml
@@ -278,11 +278,11 @@ jobs:
- name: Run playwright
env:
- CI: 'true'
+ CI: "true"
run: |
docker compose run --rm node npm install
docker compose run --rm node npm run build
- docker compose run --rm playwright npx playwright test --retries 3
+ docker compose run --rm playwright npx playwright test
- uses: actions/upload-artifact@v4
if: always()
diff --git a/docker-compose.override.yml b/docker-compose.override.yml
index e4b15ad3..211eb08a 100644
--- a/docker-compose.override.yml
+++ b/docker-compose.override.yml
@@ -1,10 +1,4 @@
services:
- nginx:
- labels:
- # HTTPS config - uncomment to enable redirect from :80 to :443
- - "traefik.http.routers.${COMPOSE_PROJECT_NAME}.middlewares=redirect-to-https"
- - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
-
redis:
image: "redis:6"
networks:
@@ -15,8 +9,11 @@ services:
node:
image: node:24
command: npm run dev
+ ports:
+ - "5173:5173"
networks:
- app
+ - frontend
working_dir: /app
environment:
- NODE_ENV=development
diff --git a/public/error.html b/public/error.html
new file mode 100644
index 00000000..895c5106
--- /dev/null
+++ b/public/error.html
@@ -0,0 +1,8 @@
+
+
+ Error
+
+
+ Error
+
+
diff --git a/vite.config.js b/vite.config.js
index f4d5ef62..4886cdc6 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -5,7 +5,7 @@ import svgr from "vite-plugin-svgr";
export default defineConfig(({command}) => {
return {
- base: command === 'serve' ? '/vite' : '/build',
+ base: "/build",
css: {
preprocessorOptions: {
scss: {
@@ -40,14 +40,7 @@ export default defineConfig(({command}) => {
},
},
server: {
- strictPort: true,
- port: 3000,
host: "0.0.0.0",
- hmr: {
- host: "display.local.itkdev.dk",
- protocol: "wss",
- clientPort: 443,
- },
cors: true,
},
}
From 8389d8a0298e4653128f5ad723fc4837e4fe6f6b Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Thu, 3 Jul 2025 11:23:11 +0200
Subject: [PATCH 05/14] 4565: Added composer install
---
.github/workflows/pr.yaml | 3 +++
public/error.html | 8 --------
2 files changed, 3 insertions(+), 8 deletions(-)
delete mode 100644 public/error.html
diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml
index 19923150..4693d1b3 100644
--- a/.github/workflows/pr.yaml
+++ b/.github/workflows/pr.yaml
@@ -276,6 +276,9 @@ jobs:
- name: Setup network
run: docker network create frontend
+ - name: Composer install
+ run: docker compose run --rm phpfpm composer install
+
- name: Run playwright
env:
CI: "true"
diff --git a/public/error.html b/public/error.html
deleted file mode 100644
index 895c5106..00000000
--- a/public/error.html
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
- Error
-
-
- Error
-
-
From 0d29dcaea3e3322185f1fe9fd9837c99c199354e Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Thu, 3 Jul 2025 12:15:57 +0200
Subject: [PATCH 06/14] 4565: Split pr.yaml into more files
---
.github/workflows/apispec.yaml | 50 ++++
.github/workflows/composer_install.yaml | 40 ++++
.github/workflows/doctrine.yaml | 57 +++++
.github/workflows/phpunit.yaml | 59 +++++
.github/workflows/playwright.yaml | 41 ++++
.github/workflows/pr.yaml | 295 ------------------------
.github/workflows/psalm.yaml | 39 ++++
.github/workflows/rector.yaml | 39 ++++
8 files changed, 325 insertions(+), 295 deletions(-)
create mode 100644 .github/workflows/apispec.yaml
create mode 100644 .github/workflows/composer_install.yaml
create mode 100644 .github/workflows/doctrine.yaml
create mode 100644 .github/workflows/phpunit.yaml
create mode 100644 .github/workflows/playwright.yaml
delete mode 100644 .github/workflows/pr.yaml
create mode 100644 .github/workflows/psalm.yaml
create mode 100644 .github/workflows/rector.yaml
diff --git a/.github/workflows/apispec.yaml b/.github/workflows/apispec.yaml
new file mode 100644
index 00000000..81de9fed
--- /dev/null
+++ b/.github/workflows/apispec.yaml
@@ -0,0 +1,50 @@
+on: pull_request
+
+name: Api Spec
+
+jobs:
+ apispec:
+ runs-on: ubuntu-latest
+ name: API Specification validation
+ strategy:
+ fail-fast: false
+ matrix:
+ php: ["8.3"]
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 2
+
+ - name: Setup PHP, with composer and extensions
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php}}
+ extensions: apcu, ctype, iconv, imagick, json, redis, soap, xmlreader, zip
+ coverage: none
+
+ - name: Get composer cache directory
+ id: composer-cache
+ run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
+
+ - name: Cache composer dependencies
+ uses: actions/cache@v4
+ with:
+ path: ${{ steps.composer-cache.outputs.dir }}
+ key: ${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }}
+ restore-keys: ${{ matrix.php }}-composer-
+
+ - name: Install Dependencies
+ run: composer install -q --no-ansi --no-interaction --no-scripts --no-suggest --no-progress --prefer-dist
+
+ - name: Export specifications (yaml)
+ run: bin/console api:openapi:export --yaml --output=public/api-spec-v2.yaml --no-interaction
+
+ - name: Check for changes in specifications (yaml)
+ run: git diff --diff-filter=ACMRT --exit-code public/api-spec-v2.yaml
+
+ - name: Export specifications (json)
+ run: bin/console api:openapi:export --output=public/api-spec-v2.json --no-interaction
+
+ - name: Check for changes in specifications (json)
+ run: git diff --diff-filter=ACMRT --exit-code public/api-spec-v2.json
diff --git a/.github/workflows/composer_install.yaml b/.github/workflows/composer_install.yaml
new file mode 100644
index 00000000..7954e2a0
--- /dev/null
+++ b/.github/workflows/composer_install.yaml
@@ -0,0 +1,40 @@
+on: pull_request
+
+name: PHP install
+
+jobs:
+ test-composer-install:
+ runs-on: ubuntu-latest
+ env:
+ COMPOSER_ALLOW_SUPERUSER: 1
+ strategy:
+ fail-fast: false
+ matrix:
+ php: ["8.3"]
+ name: Composer install in prod mode (PHP ${{ matrix.php}})
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup PHP, with composer and extensions
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php}}
+ extensions: apcu, ctype, iconv, imagick, json, redis, soap, xmlreader, zip
+ coverage: none
+
+ - name: Get composer cache directory
+ id: composer-cache
+ run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
+
+ - name: Cache composer dependencies
+ uses: actions/cache@v4
+ with:
+ path: ${{ steps.composer-cache.outputs.dir }}
+ key: ${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }}
+ restore-keys: ${{ matrix.php }}-composer-
+
+ - name: "[prod] Composer install with exported .env variables"
+ run: |
+ set -a && source .env && set +a
+ APP_ENV=prod composer install --no-dev -o
diff --git a/.github/workflows/doctrine.yaml b/.github/workflows/doctrine.yaml
new file mode 100644
index 00000000..411acc50
--- /dev/null
+++ b/.github/workflows/doctrine.yaml
@@ -0,0 +1,57 @@
+on: pull_request
+
+name: Doctrine
+
+jobs:
+ validate-doctrine-shema:
+ runs-on: ubuntu-latest
+ env:
+ DATABASE_URL: mysql://db:db@127.0.0.1:3306/db?serverVersion=mariadb-10.5.13
+ strategy:
+ fail-fast: false
+ matrix:
+ php: ["8.3"]
+ name: Validate Schema (PHP ${{ matrix.php}})
+ services:
+ mariadb:
+ image: mariadb:10.5.13
+ env:
+ MYSQL_USER: db
+ MYSQL_PASSWORD: db
+ MYSQL_DATABASE: db
+ MYSQL_ROOT_PASSWORD: db
+ ports:
+ - 3306:3306
+ options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup PHP, with composer and extensions
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php}}
+ extensions: apcu, ctype, iconv, imagick, json, redis, soap, xmlreader, zip
+ coverage: none
+
+ - name: Get composer cache directory
+ id: composer-cache
+ run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
+
+ - name: Cache composer dependencies
+ uses: actions/cache@v4
+ with:
+ path: ${{ steps.composer-cache.outputs.dir }}
+ key: ${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }}
+ restore-keys: ${{ matrix.php }}-composer-
+
+ - name: "Composer install with exported .env variables"
+ run: |
+ set -a && source .env && set +a
+ APP_ENV=prod composer install --no-dev -o
+
+ - name: Run Doctrine Migrations
+ run: APP_ENV=prod php bin/console doctrine:migrations:migrate --no-interaction
+
+ - name: Validate Doctrine schema
+ run: APP_ENV=prod php bin/console doctrine:schema:validate
diff --git a/.github/workflows/phpunit.yaml b/.github/workflows/phpunit.yaml
new file mode 100644
index 00000000..2a2e5488
--- /dev/null
+++ b/.github/workflows/phpunit.yaml
@@ -0,0 +1,59 @@
+on: pull_request
+
+name: Test
+
+jobs:
+ phpunit:
+ runs-on: ubuntu-latest
+ services:
+ mariadb:
+ image: mariadb:lts
+ ports:
+ - 3306
+ env:
+ MYSQL_USER: db
+ MYSQL_PASSWORD: db
+ MYSQL_DATABASE: db_test
+ MYSQL_ROOT_PASSWORD: password
+ # https://mariadb.org/mariadb-server-docker-official-images-healthcheck-without-mysqladmin/
+ options: >-
+ --health-cmd="healthcheck.sh --connect --innodb_initialized"
+ --health-interval=5s
+ --health-timeout=2s
+ --health-retries=3
+ strategy:
+ fail-fast: false
+ matrix:
+ php: ["8.3"]
+ name: PHP Unit tests (PHP ${{ matrix.php }})
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup PHP, with composer and extensions
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php}}
+ extensions: apcu, ctype, iconv, imagick, json, redis, soap, xmlreader, zip
+ coverage: none
+
+ - name: Get composer cache directory
+ id: composer-cache
+ run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
+
+ - name: Cache composer dependencies
+ uses: actions/cache@v4
+ with:
+ path: ${{ steps.composer-cache.outputs.dir }}
+ key: ${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }}
+ restore-keys: ${{ matrix.php }}-composer-
+
+ - name: Install Dependencies
+ run: composer install -q --no-ansi --no-interaction --no-scripts --no-suggest --no-progress --prefer-dist
+
+ - name: PHP Unit - Test setup
+ env:
+ PORT: ${{ job.services.mariadb.ports[3306] }}
+ run: |
+ DATABASE_URL="mysql://db:db@127.0.0.1:$PORT/db_test" composer run test-setup
+ DATABASE_URL="mysql://db:db@127.0.0.1:$PORT/db_test" composer run test
diff --git a/.github/workflows/playwright.yaml b/.github/workflows/playwright.yaml
new file mode 100644
index 00000000..7d2802df
--- /dev/null
+++ b/.github/workflows/playwright.yaml
@@ -0,0 +1,41 @@
+on: pull_request
+
+name: Test
+
+env:
+ COMPOSE_USER: root
+
+jobs:
+ frontend-build-and-test:
+ name: Playwright
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: true
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup network
+ run: docker network create frontend
+
+ - name: Composer install
+ run: |
+ docker compose run --rm phpfpm composer install
+
+ - name: Build assets
+ run: |
+ docker compose run --rm node npm install
+ docker compose run --rm node npm run build
+
+ - name: Run playwright
+ env:
+ CI: "true"
+ run: |
+ docker compose run --rm playwright npx playwright test
+
+ - uses: actions/upload-artifact@v4
+ if: always()
+ with:
+ name: playwright-report
+ path: playwright-report/
+ retention-days: 30
diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml
deleted file mode 100644
index 4693d1b3..00000000
--- a/.github/workflows/pr.yaml
+++ /dev/null
@@ -1,295 +0,0 @@
-on: pull_request
-name: Pull Request Review
-jobs:
- test-composer-install:
- runs-on: ubuntu-latest
- env:
- COMPOSER_ALLOW_SUPERUSER: 1
- strategy:
- fail-fast: false
- matrix:
- php: ["8.3"]
- name: Validate composer (PHP ${{ matrix.php}})
- steps:
- - name: Checkout
- uses: actions/checkout@v4
-
- - name: Setup PHP, with composer and extensions
- uses: shivammathur/setup-php@v2
- with:
- php-version: ${{ matrix.php}}
- extensions: apcu, ctype, iconv, imagick, json, redis, soap, xmlreader, zip
- coverage: none
-
- - name: Get composer cache directory
- id: composer-cache
- run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
-
- - name: Cache composer dependencies
- uses: actions/cache@v4
- with:
- path: ${{ steps.composer-cache.outputs.dir }}
- key: ${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }}
- restore-keys: ${{ matrix.php }}-composer-
-
- - name: "[prod] Composer install with exported .env variables"
- run: |
- set -a && source .env && set +a
- APP_ENV=prod composer install --no-dev -o
-
- validate-doctrine-shema:
- runs-on: ubuntu-latest
- env:
- DATABASE_URL: mysql://db:db@127.0.0.1:3306/db?serverVersion=mariadb-10.5.13
- strategy:
- fail-fast: false
- matrix:
- php: ["8.3"]
- name: Validate Doctrine Schema (PHP ${{ matrix.php}})
- services:
- mariadb:
- image: mariadb:10.5.13
- env:
- MYSQL_USER: db
- MYSQL_PASSWORD: db
- MYSQL_DATABASE: db
- MYSQL_ROOT_PASSWORD: db
- ports:
- - 3306:3306
- options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
- steps:
- - name: Checkout
- uses: actions/checkout@v4
-
- - name: Setup PHP, with composer and extensions
- uses: shivammathur/setup-php@v2
- with:
- php-version: ${{ matrix.php}}
- extensions: apcu, ctype, iconv, imagick, json, redis, soap, xmlreader, zip
- coverage: none
-
- - name: Get composer cache directory
- id: composer-cache
- run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
-
- - name: Cache composer dependencies
- uses: actions/cache@v4
- with:
- path: ${{ steps.composer-cache.outputs.dir }}
- key: ${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }}
- restore-keys: ${{ matrix.php }}-composer-
-
- - name: "Composer install with exported .env variables"
- run: |
- set -a && source .env && set +a
- APP_ENV=prod composer install --no-dev -o
-
- - name: Run Doctrine Migrations
- run: APP_ENV=prod php bin/console doctrine:migrations:migrate --no-interaction
-
- - name: Validate Doctrine schema
- run: APP_ENV=prod php bin/console doctrine:schema:validate
-
- psalm:
- runs-on: ubuntu-latest
- strategy:
- fail-fast: false
- matrix:
- php: ["8.3"]
- name: Psalm (PHP ${{ matrix.php }})
- steps:
- - name: Checkout
- uses: actions/checkout@v4
-
- - name: Setup PHP, with composer and extensions
- uses: shivammathur/setup-php@v2
- with:
- php-version: ${{ matrix.php}}
- extensions: apcu, ctype, iconv, imagick, json, redis, soap, xmlreader, zip
- coverage: none
-
- - name: Get composer cache directory
- id: composer-cache
- run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
-
- - name: Cache composer dependencies
- uses: actions/cache@v4
- with:
- path: ${{ steps.composer-cache.outputs.dir }}
- key: ${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }}
- restore-keys: ${{ matrix.php }}-composer-
-
- - name: Install Dependencies
- run: composer install -q --no-ansi --no-interaction --no-scripts --no-suggest --no-progress --prefer-dist
-
- - name: Psalm
- run: phpdbg -qrr ./vendor/bin/psalm
-
- rector:
- runs-on: ubuntu-latest
- strategy:
- fail-fast: false
- matrix:
- php: ["8.3"]
- name: Rector (PHP ${{ matrix.php }})
- steps:
- - name: Checkout
- uses: actions/checkout@v4
-
- - name: Setup PHP, with composer and extensions
- uses: shivammathur/setup-php@v2
- with:
- php-version: ${{ matrix.php}}
- extensions: apcu, ctype, iconv, imagick, json, redis, soap, xmlreader, zip
- coverage: none
-
- - name: Get composer cache directory
- id: composer-cache
- run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
-
- - name: Cache composer dependencies
- uses: actions/cache@v4
- with:
- path: ${{ steps.composer-cache.outputs.dir }}
- key: ${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }}
- restore-keys: ${{ matrix.php }}-composer-
-
- - name: Install Dependencies
- run: composer install -q --no-ansi --no-interaction --no-scripts --no-suggest --no-progress --prefer-dist
-
- - name: Rector
- run: phpdbg -qrr ./vendor/bin/rector --dry-run
-
- phpunit:
- runs-on: ubuntu-latest
- services:
- mariadb:
- image: mariadb:lts
- ports:
- - 3306
- env:
- MYSQL_USER: db
- MYSQL_PASSWORD: db
- MYSQL_DATABASE: db_test
- MYSQL_ROOT_PASSWORD: password
- # https://mariadb.org/mariadb-server-docker-official-images-healthcheck-without-mysqladmin/
- options: >-
- --health-cmd="healthcheck.sh --connect --innodb_initialized"
- --health-interval=5s
- --health-timeout=2s
- --health-retries=3
- strategy:
- fail-fast: false
- matrix:
- php: ["8.3"]
- name: PHP Unit tests (PHP ${{ matrix.php }})
- steps:
- - name: Checkout
- uses: actions/checkout@v4
-
- - name: Setup PHP, with composer and extensions
- uses: shivammathur/setup-php@v2
- with:
- php-version: ${{ matrix.php}}
- extensions: apcu, ctype, iconv, imagick, json, redis, soap, xmlreader, zip
- coverage: none
-
- - name: Get composer cache directory
- id: composer-cache
- run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
-
- - name: Cache composer dependencies
- uses: actions/cache@v4
- with:
- path: ${{ steps.composer-cache.outputs.dir }}
- key: ${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }}
- restore-keys: ${{ matrix.php }}-composer-
-
- - name: Install Dependencies
- run: composer install -q --no-ansi --no-interaction --no-scripts --no-suggest --no-progress --prefer-dist
-
- - name: PHP Unit - Test setup
- env:
- PORT: ${{ job.services.mariadb.ports[3306] }}
- run: DATABASE_URL="mysql://db:db@127.0.0.1:$PORT/db_test" composer run test-setup
-
- - name: PHP Unit - Test
- env:
- PORT: ${{ job.services.mariadb.ports[3306] }}
- run: DATABASE_URL="mysql://db:db@127.0.0.1:$PORT/db_test" composer run test
-
- apispec:
- runs-on: ubuntu-latest
- name: API Specification validation
- strategy:
- fail-fast: false
- matrix:
- php: ["8.3"]
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- with:
- fetch-depth: 2
-
- - name: Setup PHP, with composer and extensions
- uses: shivammathur/setup-php@v2
- with:
- php-version: ${{ matrix.php}}
- extensions: apcu, ctype, iconv, imagick, json, redis, soap, xmlreader, zip
- coverage: none
-
- - name: Get composer cache directory
- id: composer-cache
- run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
-
- - name: Cache composer dependencies
- uses: actions/cache@v4
- with:
- path: ${{ steps.composer-cache.outputs.dir }}
- key: ${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }}
- restore-keys: ${{ matrix.php }}-composer-
-
- - name: Install Dependencies
- run: composer install -q --no-ansi --no-interaction --no-scripts --no-suggest --no-progress --prefer-dist
-
- - name: Export specifications (yaml)
- run: bin/console api:openapi:export --yaml --output=public/api-spec-v2.yaml --no-interaction
-
- - name: Check for changes in specifications (yaml)
- run: git diff --diff-filter=ACMRT --exit-code public/api-spec-v2.yaml
-
- - name: Export specifications (json)
- run: bin/console api:openapi:export --output=public/api-spec-v2.json --no-interaction
-
- - name: Check for changes in specifications (json)
- run: git diff --diff-filter=ACMRT --exit-code public/api-spec-v2.json
-
- frontend-build-and-test:
- name: Playwright
- runs-on: ubuntu-latest
- strategy:
- fail-fast: false
- steps:
- - name: Checkout
- uses: actions/checkout@v4
-
- - name: Setup network
- run: docker network create frontend
-
- - name: Composer install
- run: docker compose run --rm phpfpm composer install
-
- - name: Run playwright
- env:
- CI: "true"
- run: |
- docker compose run --rm node npm install
- docker compose run --rm node npm run build
- docker compose run --rm playwright npx playwright test
-
- - uses: actions/upload-artifact@v4
- if: always()
- with:
- name: playwright-report
- path: playwright-report/
- retention-days: 30
diff --git a/.github/workflows/psalm.yaml b/.github/workflows/psalm.yaml
new file mode 100644
index 00000000..6cbb222c
--- /dev/null
+++ b/.github/workflows/psalm.yaml
@@ -0,0 +1,39 @@
+on: pull_request
+
+name: Psalm
+
+jobs:
+ psalm:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ php: ["8.3"]
+ name: Psalm (PHP ${{ matrix.php }})
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup PHP, with composer and extensions
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php}}
+ extensions: apcu, ctype, iconv, imagick, json, redis, soap, xmlreader, zip
+ coverage: none
+
+ - name: Get composer cache directory
+ id: composer-cache
+ run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
+
+ - name: Cache composer dependencies
+ uses: actions/cache@v4
+ with:
+ path: ${{ steps.composer-cache.outputs.dir }}
+ key: ${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }}
+ restore-keys: ${{ matrix.php }}-composer-
+
+ - name: Install Dependencies
+ run: composer install -q --no-ansi --no-interaction --no-scripts --no-suggest --no-progress --prefer-dist
+
+ - name: Psalm
+ run: phpdbg -qrr ./vendor/bin/psalm
diff --git a/.github/workflows/rector.yaml b/.github/workflows/rector.yaml
new file mode 100644
index 00000000..aa482e70
--- /dev/null
+++ b/.github/workflows/rector.yaml
@@ -0,0 +1,39 @@
+on: pull_request
+
+name: Rector
+
+jobs:
+ rector:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ php: ["8.3"]
+ name: Rector (PHP ${{ matrix.php }})
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup PHP, with composer and extensions
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php}}
+ extensions: apcu, ctype, iconv, imagick, json, redis, soap, xmlreader, zip
+ coverage: none
+
+ - name: Get composer cache directory
+ id: composer-cache
+ run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
+
+ - name: Cache composer dependencies
+ uses: actions/cache@v4
+ with:
+ path: ${{ steps.composer-cache.outputs.dir }}
+ key: ${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }}
+ restore-keys: ${{ matrix.php }}-composer-
+
+ - name: Install Dependencies
+ run: composer install -q --no-ansi --no-interaction --no-scripts --no-suggest --no-progress --prefer-dist
+
+ - name: Rector
+ run: phpdbg -qrr ./vendor/bin/rector --dry-run
From 8dd2101399152a4aa3abbe454a9533cad2bff82d Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Thu, 3 Jul 2025 12:29:12 +0200
Subject: [PATCH 07/14] 4565: Set COMPOSE_USER
---
.github/workflows/composer.yaml | 2 +-
.github/workflows/composer_install.yaml | 2 +-
.github/workflows/php.yaml | 2 +-
.github/workflows/playwright.yaml | 2 +-
.github/workflows/twig.yaml | 2 +-
5 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/.github/workflows/composer.yaml b/.github/workflows/composer.yaml
index 6e60167b..b93b0d81 100644
--- a/.github/workflows/composer.yaml
+++ b/.github/workflows/composer.yaml
@@ -26,7 +26,7 @@
name: Composer
env:
- COMPOSE_USER: root
+ COMPOSE_USER: runner
on:
pull_request:
diff --git a/.github/workflows/composer_install.yaml b/.github/workflows/composer_install.yaml
index 7954e2a0..569a71b3 100644
--- a/.github/workflows/composer_install.yaml
+++ b/.github/workflows/composer_install.yaml
@@ -1,6 +1,6 @@
on: pull_request
-name: PHP install
+name: Composer install
jobs:
test-composer-install:
diff --git a/.github/workflows/php.yaml b/.github/workflows/php.yaml
index 60fb70eb..ee967977 100644
--- a/.github/workflows/php.yaml
+++ b/.github/workflows/php.yaml
@@ -34,7 +34,7 @@
name: Symfony PHP
env:
- COMPOSE_USER: root
+ COMPOSE_USER: runner
on:
pull_request:
diff --git a/.github/workflows/playwright.yaml b/.github/workflows/playwright.yaml
index 7d2802df..0f67fe03 100644
--- a/.github/workflows/playwright.yaml
+++ b/.github/workflows/playwright.yaml
@@ -3,7 +3,7 @@ on: pull_request
name: Test
env:
- COMPOSE_USER: root
+ COMPOSE_USER: runner
jobs:
frontend-build-and-test:
diff --git a/.github/workflows/twig.yaml b/.github/workflows/twig.yaml
index 9b0e3431..9dc424b4 100644
--- a/.github/workflows/twig.yaml
+++ b/.github/workflows/twig.yaml
@@ -24,7 +24,7 @@
name: Twig
env:
- COMPOSE_USER: root
+ COMPOSE_USER: runner
on:
pull_request:
From c6cce532e3734f07b5d2671e4e673cc0b0328ab7 Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Thu, 3 Jul 2025 12:41:35 +0200
Subject: [PATCH 08/14] 4565: Changed playwright container
---
.github/workflows/playwright.yaml | 1 +
docker-compose.override.yml | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/playwright.yaml b/.github/workflows/playwright.yaml
index 0f67fe03..02550e4e 100644
--- a/.github/workflows/playwright.yaml
+++ b/.github/workflows/playwright.yaml
@@ -31,6 +31,7 @@ jobs:
env:
CI: "true"
run: |
+ docker compose run --rm playwright npx playwright install --with-deps
docker compose run --rm playwright npx playwright test
- uses: actions/upload-artifact@v4
diff --git a/docker-compose.override.yml b/docker-compose.override.yml
index 211eb08a..323243a2 100644
--- a/docker-compose.override.yml
+++ b/docker-compose.override.yml
@@ -23,7 +23,7 @@ services:
playwright:
# https://playwright.dev/docs/docker
# This Playwright version should match the one in `package.json`.
- image: mcr.microsoft.com/playwright:v1.53.2-noble
+ image: mcr.microsoft.com/playwright:v1.53.2
networks:
- app
depends_on:
From b92d561a1651ce55fc2c56b779955966c670631c Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Thu, 3 Jul 2025 13:17:21 +0200
Subject: [PATCH 09/14] 4565: Added default login methods to .env
---
.env | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.env b/.env
index e25463ff..3d119537 100644
--- a/.env
+++ b/.env
@@ -115,7 +115,7 @@ TRACK_SCREEN_INFO_UPDATE_INTERVAL_SECONDS=300
ADMIN_REJSEPLANEN_APIKEY=
ADMIN_SHOW_SCREEN_STATUS=false
ADMIN_TOUCH_BUTTON_REGIONS=false
-ADMIN_LOGIN_METHODS="[]"
+ADMIN_LOGIN_METHODS='"[{"type":"username-password","enabled":true,"provider":"username-password","label":""}]'"'
ADMIN_ENHANCED_PREVIEW=false
###< Admin configuration ###
From 73ecbd50e4b63f3ffc9e96d1eef51bbc5733e6ee Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Thu, 3 Jul 2025 13:18:40 +0200
Subject: [PATCH 10/14] 4565: Removed typos
---
.env | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.env b/.env
index 3d119537..ab0e35b3 100644
--- a/.env
+++ b/.env
@@ -115,7 +115,7 @@ TRACK_SCREEN_INFO_UPDATE_INTERVAL_SECONDS=300
ADMIN_REJSEPLANEN_APIKEY=
ADMIN_SHOW_SCREEN_STATUS=false
ADMIN_TOUCH_BUTTON_REGIONS=false
-ADMIN_LOGIN_METHODS='"[{"type":"username-password","enabled":true,"provider":"username-password","label":""}]'"'
+ADMIN_LOGIN_METHODS='[{"type":"username-password","enabled":true,"provider":"username-password","label":""}]'
ADMIN_ENHANCED_PREVIEW=false
###< Admin configuration ###
From 32ec83d3777876e9ee657a9c18c71125cb6b1166 Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Thu, 3 Jul 2025 18:19:29 +0200
Subject: [PATCH 11/14] 4565: Fixed issues with tests
---
assets/tests/admin/admin-app.spec.js | 3 +-
assets/tests/admin/admin-campaign.spec.js | 5 +-
assets/tests/admin/admin-feed-sources.spec.js | 3 +-
assets/tests/admin/admin-media.spec.js | 1 +
assets/tests/admin/admin-playlist.spec.js | 1 +
.../tests/admin/admin-screen-groups.spec.js | 1 +
assets/tests/admin/admin-screens.spec.js | 60 +++++++------------
assets/tests/admin/admin-shared-list.spec.js | 1 +
assets/tests/admin/admin-slides.spec.js | 1 +
assets/tests/admin/admin-theme.spec.js | 1 +
assets/tests/admin/admin-top-bar.spec.js | 1 +
config/routes.yaml | 2 +-
12 files changed, 34 insertions(+), 46 deletions(-)
diff --git a/assets/tests/admin/admin-app.spec.js b/assets/tests/admin/admin-app.spec.js
index 32bceda7..bf99dcce 100644
--- a/assets/tests/admin/admin-app.spec.js
+++ b/assets/tests/admin/admin-app.spec.js
@@ -2,7 +2,7 @@ import { test, expect } from "@playwright/test";
test("Basic app runs", async ({ page }) => {
await page.goto(
- "/admin/slide/list?published=all&page=1&order=asc&sort=title",
+ "/admin/slide/list",
);
await page.route("**/slides*", async (route) => {
@@ -31,6 +31,7 @@ test("Basic app runs", async ({ page }) => {
};
await route.fulfill({ json });
});
+
await page.route("**/token", async (route) => {
const json = {
token: "1",
diff --git a/assets/tests/admin/admin-campaign.spec.js b/assets/tests/admin/admin-campaign.spec.js
index f607a6ba..d66978ad 100644
--- a/assets/tests/admin/admin-campaign.spec.js
+++ b/assets/tests/admin/admin-campaign.spec.js
@@ -40,6 +40,7 @@ test.describe("Campaign pages work", () => {
await page.getByLabel("Email").fill("johndoe@example.com");
await page.getByLabel("Kodeord").fill("password");
await page.locator("#login").click();
+ await expect(page.locator('h1').getByText("Opret ny kampagne")).toBeVisible();
});
test("It loads create campaign page", async ({ page }) => {
@@ -340,10 +341,8 @@ test.describe("Campaign pages work", () => {
// Remove slide
await page
- .locator("#slides-section")
- .locator("tbody")
.locator(".remove-from-list")
- .click();
+ .click({ force: true });
await expect(
page.locator("#slides-section").locator("tbody"),
).not.toBeVisible();
diff --git a/assets/tests/admin/admin-feed-sources.spec.js b/assets/tests/admin/admin-feed-sources.spec.js
index d8539cc2..8db54a96 100644
--- a/assets/tests/admin/admin-feed-sources.spec.js
+++ b/assets/tests/admin/admin-feed-sources.spec.js
@@ -186,7 +186,7 @@ const feedSourcesJson = {
],
};
-test.describe("fest", () => {
+test.describe("feed sources", () => {
test.beforeEach(async ({ page }) => {
await page.goto("/admin/feed-sources/list");
await page.route("**/feed-sources*", async (route) => {
@@ -215,6 +215,7 @@ test.describe("fest", () => {
await page.getByLabel("Email").fill("admin@example.com");
await page.getByLabel("Kodeord").fill("password");
await page.locator("#login").click();
+ await expect(page.locator('h1').getByText("Datakilder")).toBeVisible();
});
test("It loads create datakilde page", async ({ page }) => {
diff --git a/assets/tests/admin/admin-media.spec.js b/assets/tests/admin/admin-media.spec.js
index 06c932d6..d421a5b4 100644
--- a/assets/tests/admin/admin-media.spec.js
+++ b/assets/tests/admin/admin-media.spec.js
@@ -84,6 +84,7 @@ test.describe("media list tests", () => {
await page.getByLabel("Email").fill("johndoe@example.com");
await page.getByLabel("Kodeord").fill("password");
await page.locator("#login").click();
+ await expect(page.locator('h1').getByText("Medier")).toBeVisible();
});
test("It loads media list", async ({ page }) => {
diff --git a/assets/tests/admin/admin-playlist.spec.js b/assets/tests/admin/admin-playlist.spec.js
index 21807e4c..34ed86a2 100644
--- a/assets/tests/admin/admin-playlist.spec.js
+++ b/assets/tests/admin/admin-playlist.spec.js
@@ -36,6 +36,7 @@ test.describe("Playlist create tests", () => {
await page.getByLabel("Email").fill("johndoe@example.com");
await page.getByLabel("Kodeord").fill("password");
await page.locator("#login").click();
+ await expect(page.locator('h1').getByText("Opret ny spilleliste")).toBeVisible();
});
test("It loads create playlist page", async ({ page }) => {
diff --git a/assets/tests/admin/admin-screen-groups.spec.js b/assets/tests/admin/admin-screen-groups.spec.js
index d4c2d07e..720dcf61 100644
--- a/assets/tests/admin/admin-screen-groups.spec.js
+++ b/assets/tests/admin/admin-screen-groups.spec.js
@@ -27,6 +27,7 @@ test.describe("Create group page works", () => {
await page.getByLabel("Email").fill("johndoe@example.com");
await page.getByLabel("Kodeord").fill("password");
await page.locator("#login").click();
+ await expect(page.locator('h1').getByText("Opret ny gruppe")).toBeVisible();
});
test("It loads create group page", async ({ page }) => {
diff --git a/assets/tests/admin/admin-screens.spec.js b/assets/tests/admin/admin-screens.spec.js
index d61292b7..e11eee13 100644
--- a/assets/tests/admin/admin-screens.spec.js
+++ b/assets/tests/admin/admin-screens.spec.js
@@ -1,7 +1,7 @@
import { test, expect } from "@playwright/test";
test.describe("Screen list tests", () => {
- test.beforeEach(async ({ page }) => {
+ test("Test list", async ({ page }) => {
await page.goto("/admin/screen/list");
await page.route("**/token", async (route) => {
const json = {
@@ -25,6 +25,7 @@ test.describe("Screen list tests", () => {
await page.route("**/screens*", async (route) => {
const json = {
"@id": "/v2/screens",
+ "hydra:totalItems": 2,
"hydra:member": [
{
"@type": "Screen",
@@ -70,53 +71,32 @@ test.describe("Screen list tests", () => {
},
],
};
-
await route.fulfill({ json });
});
+ await page.route("**/campaigns*", async (route) => {
+ await route.fulfill({ json: {
+ "hydra:member": [],
+ "hydra:totalItems": 0,
+ }
+ });
+ });
+ await page.route("**/screen-groups*", async (route) => {
+ await route.fulfill({ json: {
+ "hydra:member": [],
+ "hydra:totalItems": 0,
+ }
+ });
+ });
+
await expect(page).toHaveTitle(/OS2Display Admin/);
await page.getByLabel("Email").fill("johndoe@example.com");
await page.getByLabel("Kodeord").fill("password");
await page.locator("#login").click();
- });
- test("It loads screens list", async ({ page }) => {
- await page.getByText("Skærme");
+ await expect(page.locator('h1').getByText("Skærme")).toBeVisible();
await expect(page.locator("table").locator("tbody")).not.toBeEmpty();
- await expect(page.locator("tbody").locator("tr td")).toHaveCount(14);
- });
-
- test("It goes to screen edit", async ({ page }) => {
- await page.route("**/screens/*", async (route) => {
- const json = {
- "@id": "/v2/screens/00APXK73HQ11PM0X3P12EG14DZ",
- title: "Ab eos dolorum minima inventore.",
- description:
- "Non inventore ab vitae. Voluptatem assumenda aliquam sunt nulla sint corrupti et. Nihil consectetur facere cum modi aliquid. Non aut voluptas voluptas laudantium.",
- size: "42",
- created: "1981-09-01T17:22:18+02:00",
- modified: "2021-12-09T12:01:33+01:00",
- modifiedBy: "",
- createdBy: "",
- layout: "/v2/layouts/009S1H8VER00GK086N0M1J16K9",
- location:
- "Natus aut est eveniet deleniti nihil voluptatum. Accusamus similique adipisci at qui molestiae quia nihil eligendi. Delectus repellendus ut asperiores ut debitis.",
- regions: [],
- inScreenGroups: "/v2/screens/00APXK73HQ11PM0X3P12EG14DZ/groups",
- dimensions: {
- width: 1920,
- height: 1200,
- },
- };
-
- await route.fulfill({ json });
- });
- await expect(page.locator("#screenTitle")).not.toBeVisible();
- await page.locator("tbody").locator("#edit_button").nth(0).click();
- await expect(page.locator("#screenTitle")).toBeVisible();
- });
-
- test("The correct amount of column headers loaded", async ({ page }) => {
- await expect(page.locator("thead").locator("th")).toHaveCount(7);
+ await expect(page.locator("tbody").locator("tr td")).toHaveCount(16);
+ await expect(page.locator("thead").locator("th")).toHaveCount(8);
});
});
diff --git a/assets/tests/admin/admin-shared-list.spec.js b/assets/tests/admin/admin-shared-list.spec.js
index b85f18db..76ee7133 100644
--- a/assets/tests/admin/admin-shared-list.spec.js
+++ b/assets/tests/admin/admin-shared-list.spec.js
@@ -82,6 +82,7 @@ test.describe("Shared list tests", () => {
await page.getByLabel("Email").fill("johndoe@example.com");
await page.getByLabel("Kodeord").fill("password");
await page.locator("#login").click();
+ await expect(page.locator('h1').getByText("Delte spillelister")).toBeVisible();
});
test("It loads shared playlist list", async ({ page }) => {
diff --git a/assets/tests/admin/admin-slides.spec.js b/assets/tests/admin/admin-slides.spec.js
index 529f6757..519415e4 100644
--- a/assets/tests/admin/admin-slides.spec.js
+++ b/assets/tests/admin/admin-slides.spec.js
@@ -119,6 +119,7 @@ test.describe("Create slide page works", () => {
await page.getByLabel("Email").fill("johndoe@example.com");
await page.getByLabel("Kodeord").fill("password");
await page.locator("#login").click();
+ await expect(page.locator('h1').getByText("Opret nyt slide")).toBeVisible();
});
test("It loads create slide page", async ({ page }) => {
diff --git a/assets/tests/admin/admin-theme.spec.js b/assets/tests/admin/admin-theme.spec.js
index ab3dd1d6..e5bf1ae9 100644
--- a/assets/tests/admin/admin-theme.spec.js
+++ b/assets/tests/admin/admin-theme.spec.js
@@ -302,6 +302,7 @@ test.describe("Theme pages work", () => {
await page.getByLabel("Email").fill("johndoe@example.com");
await page.getByLabel("Kodeord").fill("password");
await page.locator("#login").click();
+ await expect(page.locator('h1').getByText("Temaer")).toBeVisible();
});
test("It loads create theme page", async ({ page }) => {
diff --git a/assets/tests/admin/admin-top-bar.spec.js b/assets/tests/admin/admin-top-bar.spec.js
index ef754dd6..e9a336a0 100644
--- a/assets/tests/admin/admin-top-bar.spec.js
+++ b/assets/tests/admin/admin-top-bar.spec.js
@@ -33,6 +33,7 @@ test.describe("Nav items loads", () => {
await page.getByLabel("Email").fill("johndoe@example.com");
await page.getByLabel("Kodeord").fill("password");
await page.locator("#login").click();
+ await expect(page.locator('h1').getByText("Opret ny skærm")).toBeVisible();
});
test("It loads", async ({ page }) => {
diff --git a/config/routes.yaml b/config/routes.yaml
index 505235fa..f1185ed4 100644
--- a/config/routes.yaml
+++ b/config/routes.yaml
@@ -34,7 +34,7 @@ client:
# https://symfony.com/doc/current/routing.html#slash-characters-in-route-parameters
subroutes: '.*'
methods: ['GET']
- controller: App\Controller\Client\ClientController'
+ controller: App\Controller\Client\ClientController
when@dev:
templates:
From 118e965d2d0252b3c72d77c74f39aa8c8293fd98 Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Thu, 3 Jul 2025 18:21:06 +0200
Subject: [PATCH 12/14] 4565: Applied coding standards
---
assets/tests/admin/admin-app.spec.js | 4 +---
assets/tests/admin/admin-campaign.spec.js | 8 ++++----
assets/tests/admin/admin-feed-sources.spec.js | 2 +-
assets/tests/admin/admin-media.spec.js | 2 +-
assets/tests/admin/admin-playlist.spec.js | 4 +++-
assets/tests/admin/admin-screen-groups.spec.js | 2 +-
assets/tests/admin/admin-screens.spec.js | 12 +++++++-----
assets/tests/admin/admin-shared-list.spec.js | 4 +++-
assets/tests/admin/admin-slides.spec.js | 2 +-
assets/tests/admin/admin-theme.spec.js | 2 +-
assets/tests/admin/admin-top-bar.spec.js | 2 +-
11 files changed, 24 insertions(+), 20 deletions(-)
diff --git a/assets/tests/admin/admin-app.spec.js b/assets/tests/admin/admin-app.spec.js
index bf99dcce..134316dc 100644
--- a/assets/tests/admin/admin-app.spec.js
+++ b/assets/tests/admin/admin-app.spec.js
@@ -1,9 +1,7 @@
import { test, expect } from "@playwright/test";
test("Basic app runs", async ({ page }) => {
- await page.goto(
- "/admin/slide/list",
- );
+ await page.goto("/admin/slide/list");
await page.route("**/slides*", async (route) => {
const json = {
diff --git a/assets/tests/admin/admin-campaign.spec.js b/assets/tests/admin/admin-campaign.spec.js
index d66978ad..563bbbcb 100644
--- a/assets/tests/admin/admin-campaign.spec.js
+++ b/assets/tests/admin/admin-campaign.spec.js
@@ -40,7 +40,9 @@ test.describe("Campaign pages work", () => {
await page.getByLabel("Email").fill("johndoe@example.com");
await page.getByLabel("Kodeord").fill("password");
await page.locator("#login").click();
- await expect(page.locator('h1').getByText("Opret ny kampagne")).toBeVisible();
+ await expect(
+ page.locator("h1").getByText("Opret ny kampagne"),
+ ).toBeVisible();
});
test("It loads create campaign page", async ({ page }) => {
@@ -340,9 +342,7 @@ test.describe("Campaign pages work", () => {
).toHaveCount(6);
// Remove slide
- await page
- .locator(".remove-from-list")
- .click({ force: true });
+ await page.locator(".remove-from-list").click({ force: true });
await expect(
page.locator("#slides-section").locator("tbody"),
).not.toBeVisible();
diff --git a/assets/tests/admin/admin-feed-sources.spec.js b/assets/tests/admin/admin-feed-sources.spec.js
index 8db54a96..5547f4d7 100644
--- a/assets/tests/admin/admin-feed-sources.spec.js
+++ b/assets/tests/admin/admin-feed-sources.spec.js
@@ -215,7 +215,7 @@ test.describe("feed sources", () => {
await page.getByLabel("Email").fill("admin@example.com");
await page.getByLabel("Kodeord").fill("password");
await page.locator("#login").click();
- await expect(page.locator('h1').getByText("Datakilder")).toBeVisible();
+ await expect(page.locator("h1").getByText("Datakilder")).toBeVisible();
});
test("It loads create datakilde page", async ({ page }) => {
diff --git a/assets/tests/admin/admin-media.spec.js b/assets/tests/admin/admin-media.spec.js
index d421a5b4..312a18b7 100644
--- a/assets/tests/admin/admin-media.spec.js
+++ b/assets/tests/admin/admin-media.spec.js
@@ -84,7 +84,7 @@ test.describe("media list tests", () => {
await page.getByLabel("Email").fill("johndoe@example.com");
await page.getByLabel("Kodeord").fill("password");
await page.locator("#login").click();
- await expect(page.locator('h1').getByText("Medier")).toBeVisible();
+ await expect(page.locator("h1").getByText("Medier")).toBeVisible();
});
test("It loads media list", async ({ page }) => {
diff --git a/assets/tests/admin/admin-playlist.spec.js b/assets/tests/admin/admin-playlist.spec.js
index 34ed86a2..add7f5c1 100644
--- a/assets/tests/admin/admin-playlist.spec.js
+++ b/assets/tests/admin/admin-playlist.spec.js
@@ -36,7 +36,9 @@ test.describe("Playlist create tests", () => {
await page.getByLabel("Email").fill("johndoe@example.com");
await page.getByLabel("Kodeord").fill("password");
await page.locator("#login").click();
- await expect(page.locator('h1').getByText("Opret ny spilleliste")).toBeVisible();
+ await expect(
+ page.locator("h1").getByText("Opret ny spilleliste"),
+ ).toBeVisible();
});
test("It loads create playlist page", async ({ page }) => {
diff --git a/assets/tests/admin/admin-screen-groups.spec.js b/assets/tests/admin/admin-screen-groups.spec.js
index 720dcf61..fc5c047c 100644
--- a/assets/tests/admin/admin-screen-groups.spec.js
+++ b/assets/tests/admin/admin-screen-groups.spec.js
@@ -27,7 +27,7 @@ test.describe("Create group page works", () => {
await page.getByLabel("Email").fill("johndoe@example.com");
await page.getByLabel("Kodeord").fill("password");
await page.locator("#login").click();
- await expect(page.locator('h1').getByText("Opret ny gruppe")).toBeVisible();
+ await expect(page.locator("h1").getByText("Opret ny gruppe")).toBeVisible();
});
test("It loads create group page", async ({ page }) => {
diff --git a/assets/tests/admin/admin-screens.spec.js b/assets/tests/admin/admin-screens.spec.js
index e11eee13..e7821d98 100644
--- a/assets/tests/admin/admin-screens.spec.js
+++ b/assets/tests/admin/admin-screens.spec.js
@@ -74,17 +74,19 @@ test.describe("Screen list tests", () => {
await route.fulfill({ json });
});
await page.route("**/campaigns*", async (route) => {
- await route.fulfill({ json: {
+ await route.fulfill({
+ json: {
"hydra:member": [],
"hydra:totalItems": 0,
- }
+ },
});
});
await page.route("**/screen-groups*", async (route) => {
- await route.fulfill({ json: {
+ await route.fulfill({
+ json: {
"hydra:member": [],
"hydra:totalItems": 0,
- }
+ },
});
});
@@ -93,7 +95,7 @@ test.describe("Screen list tests", () => {
await page.getByLabel("Kodeord").fill("password");
await page.locator("#login").click();
- await expect(page.locator('h1').getByText("Skærme")).toBeVisible();
+ await expect(page.locator("h1").getByText("Skærme")).toBeVisible();
await expect(page.locator("table").locator("tbody")).not.toBeEmpty();
await expect(page.locator("tbody").locator("tr td")).toHaveCount(16);
await expect(page.locator("thead").locator("th")).toHaveCount(8);
diff --git a/assets/tests/admin/admin-shared-list.spec.js b/assets/tests/admin/admin-shared-list.spec.js
index 76ee7133..94adf5bf 100644
--- a/assets/tests/admin/admin-shared-list.spec.js
+++ b/assets/tests/admin/admin-shared-list.spec.js
@@ -82,7 +82,9 @@ test.describe("Shared list tests", () => {
await page.getByLabel("Email").fill("johndoe@example.com");
await page.getByLabel("Kodeord").fill("password");
await page.locator("#login").click();
- await expect(page.locator('h1').getByText("Delte spillelister")).toBeVisible();
+ await expect(
+ page.locator("h1").getByText("Delte spillelister"),
+ ).toBeVisible();
});
test("It loads shared playlist list", async ({ page }) => {
diff --git a/assets/tests/admin/admin-slides.spec.js b/assets/tests/admin/admin-slides.spec.js
index 519415e4..c44060e2 100644
--- a/assets/tests/admin/admin-slides.spec.js
+++ b/assets/tests/admin/admin-slides.spec.js
@@ -119,7 +119,7 @@ test.describe("Create slide page works", () => {
await page.getByLabel("Email").fill("johndoe@example.com");
await page.getByLabel("Kodeord").fill("password");
await page.locator("#login").click();
- await expect(page.locator('h1').getByText("Opret nyt slide")).toBeVisible();
+ await expect(page.locator("h1").getByText("Opret nyt slide")).toBeVisible();
});
test("It loads create slide page", async ({ page }) => {
diff --git a/assets/tests/admin/admin-theme.spec.js b/assets/tests/admin/admin-theme.spec.js
index e5bf1ae9..640d5fc2 100644
--- a/assets/tests/admin/admin-theme.spec.js
+++ b/assets/tests/admin/admin-theme.spec.js
@@ -302,7 +302,7 @@ test.describe("Theme pages work", () => {
await page.getByLabel("Email").fill("johndoe@example.com");
await page.getByLabel("Kodeord").fill("password");
await page.locator("#login").click();
- await expect(page.locator('h1').getByText("Temaer")).toBeVisible();
+ await expect(page.locator("h1").getByText("Temaer")).toBeVisible();
});
test("It loads create theme page", async ({ page }) => {
diff --git a/assets/tests/admin/admin-top-bar.spec.js b/assets/tests/admin/admin-top-bar.spec.js
index e9a336a0..2111aa95 100644
--- a/assets/tests/admin/admin-top-bar.spec.js
+++ b/assets/tests/admin/admin-top-bar.spec.js
@@ -33,7 +33,7 @@ test.describe("Nav items loads", () => {
await page.getByLabel("Email").fill("johndoe@example.com");
await page.getByLabel("Kodeord").fill("password");
await page.locator("#login").click();
- await expect(page.locator('h1').getByText("Opret ny skærm")).toBeVisible();
+ await expect(page.locator("h1").getByText("Opret ny skærm")).toBeVisible();
});
test("It loads", async ({ page }) => {
From a551ed6eb182e3c43fac66527411520a1597f28d Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Thu, 3 Jul 2025 20:19:00 +0200
Subject: [PATCH 13/14] 4565: Added retries to playwright action
---
.github/workflows/playwright.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/playwright.yaml b/.github/workflows/playwright.yaml
index 02550e4e..68395203 100644
--- a/.github/workflows/playwright.yaml
+++ b/.github/workflows/playwright.yaml
@@ -32,7 +32,7 @@ jobs:
CI: "true"
run: |
docker compose run --rm playwright npx playwright install --with-deps
- docker compose run --rm playwright npx playwright test
+ docker compose run --rm playwright npx playwright test --retries 3
- uses: actions/upload-artifact@v4
if: always()
From f4bfc386018612456b547acad0b6522cb8df478d Mon Sep 17 00:00:00 2001
From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com>
Date: Fri, 4 Jul 2025 10:31:44 +0200
Subject: [PATCH 14/14] 4565: Removed retry
---
.github/workflows/playwright.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/playwright.yaml b/.github/workflows/playwright.yaml
index 68395203..02550e4e 100644
--- a/.github/workflows/playwright.yaml
+++ b/.github/workflows/playwright.yaml
@@ -32,7 +32,7 @@ jobs:
CI: "true"
run: |
docker compose run --rm playwright npx playwright install --with-deps
- docker compose run --rm playwright npx playwright test --retries 3
+ docker compose run --rm playwright npx playwright test
- uses: actions/upload-artifact@v4
if: always()