From ff2a1ccf7fc9556af51d3e9dcca6e6dca7ac2a4a Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Mon, 2 Dec 2024 08:14:36 +0100 Subject: [PATCH 01/21] Restore execution of playwright tests --- .github/workflows/playwright.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 522514a..bdf273e 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -9,7 +9,6 @@ concurrency: cancel-in-progress: true jobs: test: - if: false timeout-minutes: 60 runs-on: ubuntu-latest container: From 0b9de712ffc18c65015ec2c0d86e29c2485f1fcf Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 1 Jun 2025 22:26:10 +0200 Subject: [PATCH 02/21] Restore basic Playwright tests --- playwright.config.ts | 5 ----- tests/guests.spec.ts | 10 ---------- 2 files changed, 15 deletions(-) diff --git a/playwright.config.ts b/playwright.config.ts index 16b2700..82aa0d4 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -43,11 +43,6 @@ export default defineConfig({ use: { ...devices['Desktop Firefox'] }, }, - { - name: 'webkit', - use: { ...devices['Desktop Safari'] }, - }, - /* Test against mobile viewports. */ // { // name: 'Mobile Chrome', diff --git a/tests/guests.spec.ts b/tests/guests.spec.ts index 8bf139c..e7a6138 100644 --- a/tests/guests.spec.ts +++ b/tests/guests.spec.ts @@ -75,16 +75,11 @@ test('should display the list of guests', async ({ page }) => { await expect(page.getByRole('row').nth(1).getByRole('cell', { name: 'Kristofer Rohan DVM' })).toBeVisible(); await expect(page.getByRole('row').nth(1).getByRole('cell', { name: 'Childhood friends' })).toBeVisible(); await expect(page.getByRole('row').nth(1).getByRole('cell', { name: 'Tentative' })).toBeVisible(); - await expect(page.getByRole('row').nth(1).getByRole('button', { name: 'Confirm' })).toBeVisible(); - await expect(page.getByRole('row').nth(1).getByRole('button', { name: 'Decline' })).toBeVisible(); await expect(page.getByRole('row').nth(2).getByRole('cell', { name: 'Olevia Quigley Jr.' })).toBeVisible(); await expect(page.getByRole('row').nth(2).getByRole('cell', { name: 'Work' })).toBeVisible(); await expect(page.getByRole('row').nth(2).getByRole('cell', { name: 'Invited' })).toBeVisible(); - await expect(page.getByRole('row').nth(2).getByRole('button', { name: 'Confirm' })).toBeVisible(); - await expect(page.getByRole('row').nth(2).getByRole('button', { name: 'Tentative' })).toBeVisible(); - await expect(page.getByRole('row').nth(2).getByRole('button', { name: 'Decline' })).toBeVisible(); }); test('should display the list of groups', async ({ page }) => { @@ -92,9 +87,4 @@ test('should display the list of groups', async ({ page }) => { await page.goto('/default/dashboard/guests'); await page.getByRole('tab', { name: 'Groups' }).click(); - - await expect(page.getByText('There are 2 elements in the list')).toBeVisible(); - - await expect(page.getByRole('row').nth(1).getByRole('cell', { name: "Pam's family" })).toBeVisible(); - await expect(page.getByRole('row').nth(2).getByRole('cell', { name: "Pam's work" })).toBeVisible(); }); \ No newline at end of file From 19232477fd51e9bac6b77c077c7e0253e43c20b5 Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 1 Jun 2025 22:50:41 +0200 Subject: [PATCH 03/21] Enhance guests tests --- tests/guests.spec.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/guests.spec.ts b/tests/guests.spec.ts index e7a6138..ca63543 100644 --- a/tests/guests.spec.ts +++ b/tests/guests.spec.ts @@ -67,19 +67,25 @@ test('should display the list of guests', async ({ page }) => { await page.goto('/default/dashboard/guests'); - await expect(page.getByRole('tab', { name: 'Groups' })).toBeVisible(); + await expect(page.getByRole('button', { name: 'Add new' })).toBeVisible(); + await expect(page.getByRole('tab', { name: 'Guests' })).toBeVisible(); + await expect(page.getByRole('tab', { name: 'Groups' })).toBeVisible(); + await expect(page.getByRole('tab', { name: 'Invitations' })).toBeVisible(); await expect(page.getByText('There are 2 elements in the list')).toBeVisible(); + await expect(page.getByRole('row')).toHaveCount(3); // 1 header row + 2 data rows await expect(page.getByRole('row').nth(1).getByRole('cell', { name: 'Kristofer Rohan DVM' })).toBeVisible(); await expect(page.getByRole('row').nth(1).getByRole('cell', { name: 'Childhood friends' })).toBeVisible(); await expect(page.getByRole('row').nth(1).getByRole('cell', { name: 'Tentative' })).toBeVisible(); + await expect(page.getByRole('row').nth(1).locator('svg')).toHaveCount(2); await expect(page.getByRole('row').nth(2).getByRole('cell', { name: 'Olevia Quigley Jr.' })).toBeVisible(); await expect(page.getByRole('row').nth(2).getByRole('cell', { name: 'Work' })).toBeVisible(); await expect(page.getByRole('row').nth(2).getByRole('cell', { name: 'Invited' })).toBeVisible(); + await expect(page.getByRole('row').nth(2).locator('svg')).toHaveCount(2); }); test('should display the list of groups', async ({ page }) => { From 0455fcd8da1586ec0b43531d0332392e25346fbd Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 1 Jun 2025 23:13:05 +0200 Subject: [PATCH 04/21] Enhance the specs for groups --- tests/guests.spec.ts | 67 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 14 deletions(-) diff --git a/tests/guests.spec.ts b/tests/guests.spec.ts index ca63543..81ddb12 100644 --- a/tests/guests.spec.ts +++ b/tests/guests.spec.ts @@ -34,27 +34,31 @@ const mockGroupsAPI = ({ page }: { page: Page }) => { "id": "ee44ffb9-1147-4842-a378-9eaeb0f0871a", "name": "Pam's family", "icon": "pi pi-users", - "parent_id": "cd9645e1-02c6-4fb9-bba6-1a960754b01c", + "parent_id": null, "color": "#ff0000", - "total": 3, - "considered": 2, - "invited": 1, - "confirmed": 0, - "declined": 0, - "tentative": 0 + "attendance": { + "total": 3, + "considered": 2, + "invited": 1, + "confirmed": 0, + "declined": 0, + "tentative": 0 + } }, { "id": "c8bda6ca-d8af-4bb8-b2bf-e6ec1c21b1e6", "name": "Pam's work", "icon": "pi pi-desktop", - "parent_id": "cd9645e1-02c6-4fb9-bba6-1a960754b01c", + "parent_id": null, "color": "#00ff00", - "total": 2, - "considered": 0, - "invited": 0, - "confirmed": 0, - "declined": 0, - "tentative": 2 + "attendance": { + "total": 2, + "considered": 0, + "invited": 0, + "confirmed": 0, + "declined": 0, + "tentative": 2 + } }, ]; @@ -93,4 +97,39 @@ test('should display the list of groups', async ({ page }) => { await page.goto('/default/dashboard/guests'); await page.getByRole('tab', { name: 'Groups' }).click(); + + await expect(page.getByRole('button', { name: 'Add new' })).toBeVisible(); + await expect(page.getByRole('button', { name: 'Reset affinities' })).toBeVisible(); + + await expect(page.getByRole('row')).toHaveCount(3); // 1 header row + 2 data rows + + await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(0)).toHaveText('Name'); + await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(1)).toHaveText('Color'); + await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(2)).toHaveText('Confirmed'); + await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(3)).toHaveText('Tentative'); + await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(4)).toHaveText('Pending'); + await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(5)).toHaveText('Declined'); + await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(6)).toHaveText('Considered'); + await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(7)).toHaveText('Total'); + await expect(page.getByRole('row').nth(0).getByRole('columnheader').nth(8)).toHaveText('Actions'); + + await expect(page.getByRole('row').nth(1).getByRole('cell').nth(0)).toContainText('Pam\'s family'); + await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('0'); + await expect(page.getByRole('row').nth(1).getByRole('cell').nth(3)).toHaveText('0'); + await expect(page.getByRole('row').nth(1).getByRole('cell').nth(4)).toHaveText('1'); + await expect(page.getByRole('row').nth(1).getByRole('cell').nth(5)).toHaveText('0'); + await expect(page.getByRole('row').nth(1).getByRole('cell').nth(6)).toHaveText('2'); + await expect(page.getByRole('row').nth(1).getByRole('cell').nth(7)).toHaveText('3'); + await expect(page.getByRole('row').nth(1).locator('svg:visible')).toHaveCount(3); + + + await expect(page.getByRole('row').nth(2).getByRole('cell').nth(0)).toContainText('Pam\'s work'); + await expect(page.getByRole('row').nth(2).getByRole('cell').nth(2)).toHaveText('0'); + await expect(page.getByRole('row').nth(2).getByRole('cell').nth(3)).toHaveText('2'); + await expect(page.getByRole('row').nth(2).getByRole('cell').nth(4)).toHaveText('0'); + await expect(page.getByRole('row').nth(2).getByRole('cell').nth(5)).toHaveText('0'); + await expect(page.getByRole('row').nth(2).getByRole('cell').nth(6)).toHaveText('0'); + await expect(page.getByRole('row').nth(2).getByRole('cell').nth(7)).toHaveText('2'); + await expect(page.getByRole('row').nth(2).locator('svg:visible')).toHaveCount(3); + }); \ No newline at end of file From e8551dd877f0fc8290fb693e06f76349091c72eb Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 1 Jun 2025 23:19:12 +0200 Subject: [PATCH 05/21] Upgrade playwright to the latest version --- package.json | 2 +- pnpm-lock.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index fdbc249..9233f01 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "zod": "^3.23.8" }, "devDependencies": { - "@playwright/test": "^1.46.0", + "@playwright/test": "^1.52.0", "@types/bcrypt": "^5.0.2", "@types/node": "22.15.29", "@types/react": "18.3.23", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4716f9a..318e086 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -64,7 +64,7 @@ importers: version: 3.25.45 devDependencies: '@playwright/test': - specifier: ^1.46.0 + specifier: ^1.52.0 version: 1.52.0 '@types/bcrypt': specifier: ^5.0.2 From 37488053776d94f96285f27d8b093359cd0035a1 Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 1 Jun 2025 23:46:25 +0200 Subject: [PATCH 06/21] WIP specs for guest creation --- tests/guests.spec.ts | 71 +++++++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 21 deletions(-) diff --git a/tests/guests.spec.ts b/tests/guests.spec.ts index 81ddb12..6fcd29b 100644 --- a/tests/guests.spec.ts +++ b/tests/guests.spec.ts @@ -1,29 +1,36 @@ import { test, expect, Page } from '@playwright/test' +import { mock } from 'node:test'; const mockGuestsAPI = ({ page }: { page: Page }) => { page.route('*/**/api/default/guests', async route => { - const json = [ - { - "id": "f4a09c28-40ea-4553-90a5-96935a59cac6", - "status": "tentative", - "name": "Kristofer Rohan DVM", - "group": { - "id": "2fcb8b22-6b07-4c34-92e3-a2535dbc5b14", - "name": "Childhood friends", - } - }, - { - "id": "bd585c40-0937-4cde-960a-bb23acfd6f18", - "status": "invited", - "name": "Olevia Quigley Jr.", - "group": { - "id": "da8edf26-3e1e-4cbb-b985-450c49fffe01", - "name": "Work", - } - }, - ]; + if (route.request().method() === 'GET') { + const json = [ + { + "id": "f4a09c28-40ea-4553-90a5-96935a59cac6", + "status": "tentative", + "name": "Kristofer Rohan DVM", + "group": { + "id": "2fcb8b22-6b07-4c34-92e3-a2535dbc5b14", + "name": "Childhood friends", + } + }, + { + "id": "bd585c40-0937-4cde-960a-bb23acfd6f18", + "status": "invited", + "name": "Olevia Quigley Jr.", + "group": { + "id": "da8edf26-3e1e-4cbb-b985-450c49fffe01", + "name": "Work", + } + }, + ]; - await route.fulfill({ json }) + await route.fulfill({ json }) + } else if (route.request().method() === 'POST') { + const json = {}; + + await route.fulfill({ json }); + } }) } @@ -92,6 +99,28 @@ test('should display the list of guests', async ({ page }) => { await expect(page.getByRole('row').nth(2).locator('svg')).toHaveCount(2); }); +test('should allow creating a new guest', async ({ page }) => { + await mockGuestsAPI({ page }); + await mockGroupsAPI({ page }); + + await page.goto('/default/dashboard/guests'); + await page.getByRole('button', { name: 'Add new' }).click(); + + await page.getByRole('dialog').getByLabel('Name').fill('John Snow'); + + await page.keyboard.press('Tab'); + await page.keyboard.press('ArrowDown'); + await page.keyboard.press('ArrowDown'); + await page.keyboard.press('Enter'); + + await page.keyboard.press('Tab'); + await page.keyboard.press('ArrowDown'); + await page.keyboard.press('ArrowDown'); + await page.keyboard.press('Enter'); + + await page.getByRole('dialog').getByRole('button', { name: 'Create' }).click(); +}); + test('should display the list of groups', async ({ page }) => { await mockGroupsAPI({ page }); From fed86088c375b0570b324cfc8bbca2115edb763b Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 8 Jun 2025 09:18:10 +0200 Subject: [PATCH 07/21] Use pnpm to build and run the service --- .github/workflows/playwright.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index bdf273e..f419958 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -21,10 +21,10 @@ jobs: - name: Install dependencies run: npm install -g pnpm && pnpm install - name: Build the service that will be tested - run: npm run build + run: pnpm run build - name: Install Playwright Browsers run: pnpm exec playwright install --with-deps - name: Run the service that will be tested - run: npm run start & + run: pnpm run start & - name: Run Playwright tests run: pnpm exec playwright test From 4455c0e6d44a14d7989503df656320044141d6c7 Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 8 Jun 2025 09:33:11 +0200 Subject: [PATCH 08/21] Run playwright tests in verbose mode --- .github/workflows/playwright.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index f419958..4b71f5a 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -27,4 +27,4 @@ jobs: - name: Run the service that will be tested run: pnpm run start & - name: Run Playwright tests - run: pnpm exec playwright test + run: DEBUG=pw:api pnpm exec playwright test From acdbee40bf9daa094dd9b3a4d3bc579eb4278c8a Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 8 Jun 2025 09:47:48 +0200 Subject: [PATCH 09/21] Wait for the service to be ready --- .github/workflows/playwright.yml | 2 + package.json | 3 +- pnpm-lock.yaml | 249 +++++++++++++++++++++++++++++++ 3 files changed, 253 insertions(+), 1 deletion(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 4b71f5a..87a6628 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -26,5 +26,7 @@ jobs: run: pnpm exec playwright install --with-deps - name: Run the service that will be tested run: pnpm run start & + - name: Wait for the service to be ready + run: npx wait-on http://127.0.0.1:3000 --timeout 30000 - name: Run Playwright tests run: DEBUG=pw:api pnpm exec playwright test diff --git a/package.json b/package.json index 9233f01..ef8eafb 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,8 @@ "@types/bcrypt": "^5.0.2", "@types/node": "22.15.29", "@types/react": "18.3.23", - "@types/react-dom": "18.3.7" + "@types/react-dom": "18.3.7", + "wait-on": "^8.0.3" }, "engines": { "node": ">=23.0.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 318e086..6253103 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -78,6 +78,9 @@ importers: '@types/react-dom': specifier: 18.3.7 version: 18.3.7(@types/react@18.3.23) + wait-on: + specifier: ^8.0.3 + version: 8.0.3 packages: @@ -254,6 +257,12 @@ packages: '@emotion/weak-memoize@0.4.0': resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==} + '@hapi/hoek@9.3.0': + resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} + + '@hapi/topo@5.1.0': + resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} + '@heroicons/react@2.2.0': resolution: {integrity: sha512-LMcepvRaS9LYHJGsF0zzmgKCUim/X3N/DQKc4jepAXJ7l8QxJ1PmxJzqplF2Z3FE4PqBAIGyJAQ/w4B5dsqbtQ==} peerDependencies: @@ -470,6 +479,15 @@ packages: engines: {node: '>=18'} hasBin: true + '@sideway/address@4.1.5': + resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==} + + '@sideway/formula@3.0.1': + resolution: {integrity: sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==} + + '@sideway/pinpoint@2.0.0': + resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==} + '@statsig/client-core@3.17.2': resolution: {integrity: sha512-7jq4H2SinknR4L51lzaI2VodGR6BfO5paRRPAKubqGIG35NjwQ0Z0MozPCuR94aL0SV+VvwMsys3zavtdLV9Ng==} @@ -553,6 +571,9 @@ packages: arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + autoprefixer@10.4.21: resolution: {integrity: sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==} engines: {node: ^10 || ^12 || >=14} @@ -560,6 +581,9 @@ packages: peerDependencies: postcss: ^8.1.0 + axios@1.9.0: + resolution: {integrity: sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==} + babel-plugin-macros@3.1.0: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} engines: {node: '>=10', npm: '>=6'} @@ -597,6 +621,10 @@ packages: resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} engines: {node: '>=10.16.0'} + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -641,6 +669,10 @@ packages: resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} engines: {node: '>=12.5.0'} + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} @@ -679,6 +711,10 @@ packages: supports-color: optional: true + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + delegates@1.0.0: resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} @@ -695,6 +731,10 @@ packages: dom-helpers@5.2.1: resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -710,6 +750,22 @@ packages: error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -735,10 +791,23 @@ packages: find-root@1.1.0: resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + foreground-child@3.1.1: resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} engines: {node: '>=14'} + form-data@4.0.3: + resolution: {integrity: sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==} + engines: {node: '>= 6'} + fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} @@ -767,6 +836,14 @@ packages: engines: {node: '>=10'} deprecated: This package is no longer supported. + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -788,6 +865,18 @@ packages: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + has-unicode@2.0.1: resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} @@ -853,6 +942,9 @@ packages: resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} hasBin: true + joi@17.13.3: + resolution: {integrity: sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==} + jose@6.0.10: resolution: {integrity: sha512-skIAxZqcMkOrSwjJvplIPYrlXGpxTPnro2/QWTDCxAdWQrSTV5/KqspMWmi5WAx5+ULswASJiZ0a+1B/Lxt9cw==} @@ -874,6 +966,9 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -886,6 +981,10 @@ packages: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -894,6 +993,14 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + mini-svg-data-uri@1.4.4: resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==} hasBin: true @@ -905,6 +1012,9 @@ packages: resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} engines: {node: '>=16 || 14 >=14.17'} + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + minipass@3.3.6: resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} engines: {node: '>=8'} @@ -1147,6 +1257,9 @@ packages: prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -1215,6 +1328,9 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + rxjs@7.8.2: + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} + safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} @@ -1380,6 +1496,11 @@ packages: resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} hasBin: true + wait-on@8.0.3: + resolution: {integrity: sha512-nQFqAFzZDeRxsu7S3C7LbuxslHhk+gnJZHyethuGKAn2IVleIbTB9I3vJSQiSR+DifUqmdzfPMoMPJfLqMF2vw==} + engines: {node: '>=12.0.0'} + hasBin: true + webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} @@ -1702,6 +1823,12 @@ snapshots: '@emotion/weak-memoize@0.4.0': {} + '@hapi/hoek@9.3.0': {} + + '@hapi/topo@5.1.0': + dependencies: + '@hapi/hoek': 9.3.0 + '@heroicons/react@2.2.0(react@19.0.0-rc-f38c22b244-20240704)': dependencies: react: 19.0.0-rc-f38c22b244-20240704 @@ -1872,6 +1999,14 @@ snapshots: dependencies: playwright: 1.52.0 + '@sideway/address@4.1.5': + dependencies: + '@hapi/hoek': 9.3.0 + + '@sideway/formula@3.0.1': {} + + '@sideway/pinpoint@2.0.0': {} + '@statsig/client-core@3.17.2': {} '@statsig/js-client@3.17.2': @@ -1948,6 +2083,8 @@ snapshots: arg@5.0.2: {} + asynckit@0.4.0: {} + autoprefixer@10.4.21(postcss@8.5.4): dependencies: browserslist: 4.24.4 @@ -1958,6 +2095,14 @@ snapshots: postcss: 8.5.4 postcss-value-parser: 4.2.0 + axios@1.9.0: + dependencies: + follow-redirects: 1.15.9 + form-data: 4.0.3 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + babel-plugin-macros@3.1.0: dependencies: '@babel/runtime': 7.27.0 @@ -2002,6 +2147,11 @@ snapshots: dependencies: streamsearch: 1.1.0 + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + callsites@3.1.0: {} camelcase-css@2.0.1: {} @@ -2046,6 +2196,10 @@ snapshots: color-string: 1.9.1 optional: true + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + commander@4.1.1: {} concat-map@0.0.1: {} @@ -2076,6 +2230,8 @@ snapshots: dependencies: ms: 2.1.2 + delayed-stream@1.0.0: {} + delegates@1.0.0: {} detect-libc@2.0.3: {} @@ -2089,6 +2245,12 @@ snapshots: '@babel/runtime': 7.27.0 csstype: 3.1.3 + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + eastasianwidth@0.2.0: {} electron-to-chromium@1.5.113: {} @@ -2101,6 +2263,21 @@ snapshots: dependencies: is-arrayish: 0.2.1 + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + escalade@3.2.0: {} escape-string-regexp@4.0.0: {} @@ -2125,11 +2302,21 @@ snapshots: find-root@1.1.0: {} + follow-redirects@1.15.9: {} + foreground-child@3.1.1: dependencies: cross-spawn: 7.0.3 signal-exit: 4.1.0 + form-data@4.0.3: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + fraction.js@4.3.7: {} fs-minipass@2.1.0: @@ -2158,6 +2345,24 @@ snapshots: strip-ansi: 6.0.1 wide-align: 1.1.5 + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -2185,6 +2390,14 @@ snapshots: globals@11.12.0: {} + gopd@1.2.0: {} + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + has-unicode@2.0.1: {} hasown@2.0.2: @@ -2247,6 +2460,14 @@ snapshots: jiti@1.21.6: {} + joi@17.13.3: + dependencies: + '@hapi/hoek': 9.3.0 + '@hapi/topo': 5.1.0 + '@sideway/address': 4.1.5 + '@sideway/formula': 3.0.1 + '@sideway/pinpoint': 2.0.0 + jose@6.0.10: {} js-tokens@4.0.0: {} @@ -2259,6 +2480,8 @@ snapshots: lines-and-columns@1.2.4: {} + lodash@4.17.21: {} + loose-envify@1.4.0: dependencies: js-tokens: 4.0.0 @@ -2269,6 +2492,8 @@ snapshots: dependencies: semver: 6.3.1 + math-intrinsics@1.1.0: {} + merge2@1.4.1: {} micromatch@4.0.8: @@ -2276,6 +2501,12 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + mini-svg-data-uri@1.4.4: {} minimatch@3.1.2: @@ -2286,6 +2517,8 @@ snapshots: dependencies: brace-expansion: 2.0.1 + minimist@1.2.8: {} + minipass@3.3.6: dependencies: yallist: 4.0.0 @@ -2484,6 +2717,8 @@ snapshots: object-assign: 4.1.1 react-is: 16.13.1 + proxy-from-env@1.1.0: {} + queue-microtask@1.2.3: {} raf-schd@4.0.3: {} @@ -2547,6 +2782,10 @@ snapshots: dependencies: queue-microtask: 1.2.3 + rxjs@7.8.2: + dependencies: + tslib: 2.8.1 + safe-buffer@5.2.1: {} scheduler@0.25.0-rc-f38c22b244-20240704: {} @@ -2730,6 +2969,16 @@ snapshots: uuid@11.1.0: {} + wait-on@8.0.3: + dependencies: + axios: 1.9.0 + joi: 17.13.3 + lodash: 4.17.21 + minimist: 1.2.8 + rxjs: 7.8.2 + transitivePeerDependencies: + - debug + webidl-conversions@3.0.1: {} whatwg-url@5.0.0: From d6f603d70c8a4c465ac4b4ab83c8ea85338103ca Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 8 Jun 2025 10:03:57 +0200 Subject: [PATCH 10/21] Run standalone node server instead of development build --- .github/workflows/playwright.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 87a6628..733fbc0 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -25,7 +25,7 @@ jobs: - name: Install Playwright Browsers run: pnpm exec playwright install --with-deps - name: Run the service that will be tested - run: pnpm run start & + run: node .next/standalone/server.js & - name: Wait for the service to be ready run: npx wait-on http://127.0.0.1:3000 --timeout 30000 - name: Run Playwright tests From 6490e585ee5a2d288409cba3a20dfe329d70956c Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 8 Jun 2025 10:27:13 +0200 Subject: [PATCH 11/21] Run the server in 127.0.0.1 host --- .github/workflows/playwright.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 733fbc0..bb82e41 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -25,7 +25,7 @@ jobs: - name: Install Playwright Browsers run: pnpm exec playwright install --with-deps - name: Run the service that will be tested - run: node .next/standalone/server.js & + run: HOST=127.0.0.1 node .next/standalone/server.js & - name: Wait for the service to be ready run: npx wait-on http://127.0.0.1:3000 --timeout 30000 - name: Run Playwright tests From 8b0cab93c9b9f6760182b06aecc3551320d688ff Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 8 Jun 2025 10:48:51 +0200 Subject: [PATCH 12/21] Fix environment variable name --- .github/workflows/playwright.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index bb82e41..f415e86 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -25,7 +25,7 @@ jobs: - name: Install Playwright Browsers run: pnpm exec playwright install --with-deps - name: Run the service that will be tested - run: HOST=127.0.0.1 node .next/standalone/server.js & + run: HOSTNAME=127.0.0.1 node .next/standalone/server.js & - name: Wait for the service to be ready run: npx wait-on http://127.0.0.1:3000 --timeout 30000 - name: Run Playwright tests From e0da10c0006d8f984771dbdc38508b69f902835e Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 8 Jun 2025 11:10:00 +0200 Subject: [PATCH 13/21] Try localhost --- .github/workflows/playwright.yml | 4 ++-- playwright.config.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index f415e86..9ae59b3 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -25,8 +25,8 @@ jobs: - name: Install Playwright Browsers run: pnpm exec playwright install --with-deps - name: Run the service that will be tested - run: HOSTNAME=127.0.0.1 node .next/standalone/server.js & + run: HOSTNAME=localhost node .next/standalone/server.js & - name: Wait for the service to be ready - run: npx wait-on http://127.0.0.1:3000 --timeout 30000 + run: npx wait-on http://localhost:3000 --timeout 30000 - name: Run Playwright tests run: DEBUG=pw:api pnpm exec playwright test diff --git a/playwright.config.ts b/playwright.config.ts index 82aa0d4..0748741 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -25,7 +25,7 @@ export default defineConfig({ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: 'http://127.0.0.1:3000', + baseURL: 'http://localhost:3000', /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ trace: 'on-first-retry', @@ -67,7 +67,7 @@ export default defineConfig({ /* Run your local dev server before starting the tests */ // webServer: { // command: 'npm run start', - // url: 'http://127.0.0.1:3000', + // url: 'http://localhost:3000', // reuseExistingServer: !process.env.CI, // }, }); From 85f918b397268adff48ff40b44d4da4a05c88872 Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 8 Jun 2025 11:42:59 +0200 Subject: [PATCH 14/21] Fix the waiting URL --- .github/workflows/playwright.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 9ae59b3..03151bb 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -27,6 +27,6 @@ jobs: - name: Run the service that will be tested run: HOSTNAME=localhost node .next/standalone/server.js & - name: Wait for the service to be ready - run: npx wait-on http://localhost:3000 --timeout 30000 + run: npx wait-on http://localhost:3000/default/dashboard/guests --timeout 30000 - name: Run Playwright tests run: DEBUG=pw:api pnpm exec playwright test From 01717b392c6a53c0165ed86843a3176422fa522d Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 8 Jun 2025 11:49:44 +0200 Subject: [PATCH 15/21] Revert "Try localhost" This reverts commit e0da10c0006d8f984771dbdc38508b69f902835e. --- .github/workflows/playwright.yml | 4 ++-- playwright.config.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 03151bb..91e5e10 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -25,8 +25,8 @@ jobs: - name: Install Playwright Browsers run: pnpm exec playwright install --with-deps - name: Run the service that will be tested - run: HOSTNAME=localhost node .next/standalone/server.js & + run: HOSTNAME=127.0.0.1 node .next/standalone/server.js & - name: Wait for the service to be ready - run: npx wait-on http://localhost:3000/default/dashboard/guests --timeout 30000 + run: npx wait-on http://127.0.0.1:3000/default/dashboard/guests --timeout 30000 - name: Run Playwright tests run: DEBUG=pw:api pnpm exec playwright test diff --git a/playwright.config.ts b/playwright.config.ts index 0748741..82aa0d4 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -25,7 +25,7 @@ export default defineConfig({ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: 'http://localhost:3000', + baseURL: 'http://127.0.0.1:3000', /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ trace: 'on-first-retry', @@ -67,7 +67,7 @@ export default defineConfig({ /* Run your local dev server before starting the tests */ // webServer: { // command: 'npm run start', - // url: 'http://localhost:3000', + // url: 'http://127.0.0.1:3000', // reuseExistingServer: !process.env.CI, // }, }); From 22a2cba3fec375fb3d49e397707748ab881caa74 Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 8 Jun 2025 12:19:01 +0200 Subject: [PATCH 16/21] Fix the path used for checking upstatus --- .github/workflows/playwright.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 91e5e10..2bbc580 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -27,6 +27,6 @@ jobs: - name: Run the service that will be tested run: HOSTNAME=127.0.0.1 node .next/standalone/server.js & - name: Wait for the service to be ready - run: npx wait-on http://127.0.0.1:3000/default/dashboard/guests --timeout 30000 + run: npx wait-on http://127.0.0.1:3000/default/ --timeout 30000 - name: Run Playwright tests run: DEBUG=pw:api pnpm exec playwright test From 2c3480f9807c887e800ee7dd8ca7c009adb24d94 Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 8 Jun 2025 12:33:44 +0200 Subject: [PATCH 17/21] Fix use of localstorage in server side --- app/[slug]/dashboard/guests/page.tsx | 7 +++++-- app/[slug]/page.tsx | 8 ++++---- app/ui/components/login-form.tsx | 5 ++++- app/ui/components/registration-form.tsx | 4 +++- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/app/[slug]/dashboard/guests/page.tsx b/app/[slug]/dashboard/guests/page.tsx index 7915188..40bb0cb 100644 --- a/app/[slug]/dashboard/guests/page.tsx +++ b/app/[slug]/dashboard/guests/page.tsx @@ -15,12 +15,15 @@ import SkeletonTable from '@/app/ui/guests/skeleton-row'; import GuestsTable from '@/app/ui/guests/table'; import { TabPanel, TabView } from 'primereact/tabview'; import { Toast } from 'primereact/toast'; -import { Suspense, useRef, useState } from 'react'; +import { Suspense, useEffect, useRef, useState } from 'react'; import InvitationsBoard from '@/app/ui/invitations/board'; import { Invitation, InvitationSerializer } from '@/app/lib/invitation'; export default function Page() { + const [slug, setSlug] = useState(null); + useEffect(() => { setSlug(getSlug()) }, []); + const toast = useRef(null); function refreshGuests() { @@ -45,7 +48,7 @@ export default function Page() { } function resetAffinities() { - fetch(`/api/${getSlug()}/groups/affinities/reset`, { + fetch(`/api/${slug}/groups/affinities/reset`, { method: 'POST', headers: { 'Accept': 'application/json', diff --git a/app/[slug]/page.tsx b/app/[slug]/page.tsx index f189a6a..a4d9a70 100644 --- a/app/[slug]/page.tsx +++ b/app/[slug]/page.tsx @@ -16,11 +16,11 @@ export default async function Page() { if (getCsrfToken() == 'unknown') { retrieveCSRFToken(); } - }, []); - if (typeof window !== 'undefined') { - localStorage.setItem('slug', await params.slug); - } + if (typeof window !== 'undefined') { + localStorage.setItem('slug', params.slug); + } + }, []); return (
diff --git a/app/ui/components/login-form.tsx b/app/ui/components/login-form.tsx index 7b808c2..4e3c8af 100644 --- a/app/ui/components/login-form.tsx +++ b/app/ui/components/login-form.tsx @@ -14,6 +14,9 @@ import { getSlug } from '@/app/lib/utils'; export default function LoginForm() { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); + + const [slug, setSlug] = useState(null); + useEffect(() => {setSlug(getSlug())}, []); const router = useRouter(); @@ -41,7 +44,7 @@ export default function LoginForm() { password: password, onLogin: (user) => { setCurrentUser(user); - router.push(`${getSlug()}/dashboard`) + router.push(`${slug}/dashboard`) } })}> Sign in diff --git a/app/ui/components/registration-form.tsx b/app/ui/components/registration-form.tsx index 3de63ea..da4745f 100644 --- a/app/ui/components/registration-form.tsx +++ b/app/ui/components/registration-form.tsx @@ -17,7 +17,9 @@ export default function RegistrationForm() { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [passwordConfirmation, setPasswordConfirmation] = useState(""); - const [slug, setSlug] = useState(getSlug()); + + const [slug, setSlug] = useState(null); + useEffect(() => { setSlug(getSlug()) }, []); const [captchaId, setCaptchaId] = useState(""); const [captchaUrl, setCaptchaUrl] = useState(""); From 7719929e4356ebadbf2e85d928449a5b343dfd6e Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 8 Jun 2025 12:42:46 +0200 Subject: [PATCH 18/21] Prevent slug from being null --- app/[slug]/dashboard/guests/page.tsx | 2 +- app/ui/components/login-form.tsx | 4 ++-- app/ui/components/registration-form.tsx | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/[slug]/dashboard/guests/page.tsx b/app/[slug]/dashboard/guests/page.tsx index 40bb0cb..0859d21 100644 --- a/app/[slug]/dashboard/guests/page.tsx +++ b/app/[slug]/dashboard/guests/page.tsx @@ -21,7 +21,7 @@ import { Invitation, InvitationSerializer } from '@/app/lib/invitation'; export default function Page() { - const [slug, setSlug] = useState(null); + const [slug, setSlug] = useState("default"); useEffect(() => { setSlug(getSlug()) }, []); const toast = useRef(null); diff --git a/app/ui/components/login-form.tsx b/app/ui/components/login-form.tsx index 4e3c8af..fd575b6 100644 --- a/app/ui/components/login-form.tsx +++ b/app/ui/components/login-form.tsx @@ -14,8 +14,8 @@ import { getSlug } from '@/app/lib/utils'; export default function LoginForm() { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); - - const [slug, setSlug] = useState(null); + + const [slug, setSlug] = useState("default"); useEffect(() => {setSlug(getSlug())}, []); const router = useRouter(); diff --git a/app/ui/components/registration-form.tsx b/app/ui/components/registration-form.tsx index da4745f..f6594c6 100644 --- a/app/ui/components/registration-form.tsx +++ b/app/ui/components/registration-form.tsx @@ -18,7 +18,7 @@ export default function RegistrationForm() { const [password, setPassword] = useState(""); const [passwordConfirmation, setPasswordConfirmation] = useState(""); - const [slug, setSlug] = useState(null); + const [slug, setSlug] = useState("default"); useEffect(() => { setSlug(getSlug()) }, []); const [captchaId, setCaptchaId] = useState(""); From 1c0570d1a8b4abafc5b4aec5be04354b4accd019 Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Sun, 8 Jun 2025 13:12:51 +0200 Subject: [PATCH 19/21] Fix additional use of localstorage in the server side --- app/[slug]/dashboard/guests/page.tsx | 19 ++++++++----------- app/ui/arrangements/arrangement.tsx | 1 - app/ui/dashboard/nav-links.tsx | 16 ++++++++++------ app/ui/dashboard/sidenav.tsx | 14 +++++++++++--- 4 files changed, 29 insertions(+), 21 deletions(-) diff --git a/app/[slug]/dashboard/guests/page.tsx b/app/[slug]/dashboard/guests/page.tsx index 0859d21..137cd10 100644 --- a/app/[slug]/dashboard/guests/page.tsx +++ b/app/[slug]/dashboard/guests/page.tsx @@ -22,28 +22,31 @@ import { Invitation, InvitationSerializer } from '@/app/lib/invitation'; export default function Page() { const [slug, setSlug] = useState("default"); - useEffect(() => { setSlug(getSlug()) }, []); + + useEffect(() => { + setSlug(getSlug()); + refreshGroups(); + refreshGuests(); + refreshInvitations(); + }, []); const toast = useRef(null); function refreshGuests() { new AbstractApi().getAll(new GuestSerializer(), (objects: Guest[]) => { setGuests(objects); - setGuestsLoaded(true); }); } function refreshGroups() { new AbstractApi().getAll(new GroupSerializer(), (objects: Group[]) => { setGroups(objects); - setGroupsLoaded(true); }); } function refreshInvitations() { new AbstractApi().getAll(new InvitationSerializer(), (objects: Invitation[]) => { setInvitations(objects); - setInvitationsLoaded(true); }); } @@ -75,23 +78,17 @@ export default function Page() { }); } - const [groupsLoaded, setGroupsLoaded] = useState(false); const [groups, setGroups] = useState>([]); const [groupBeingEdited, setGroupBeingEdited] = useState(undefined); const [groupAffinitiesBeingEditted, setGroupAffinitiesBeingEditted] = useState(undefined); - const [guestsLoaded, setGuestsLoaded] = useState(false); const [guests, setGuests] = useState>([]); const [guestBeingEdited, setGuestBeingEdited] = useState(undefined); - const [invitationsLoaded, setInvitationsLoaded] = useState(false); const [invitations, setInvitations] = useState>([]); - const [invitationBeingEdited, setInvitationBeingEdited] = useState(undefined); - !groupsLoaded && refreshGroups(); - !guestsLoaded && refreshGuests(); - !invitationsLoaded && refreshInvitations(); + return (
diff --git a/app/ui/arrangements/arrangement.tsx b/app/ui/arrangements/arrangement.tsx index d8bf0b1..d2ec567 100644 --- a/app/ui/arrangements/arrangement.tsx +++ b/app/ui/arrangements/arrangement.tsx @@ -5,7 +5,6 @@ import { AbstractApi } from '@/app/api/abstract-api'; import { TableArrangement } from '@/app/lib/definitions'; import { TableSimulation, TableSimulationSerializer } from '@/app/lib/tableSimulation'; -import { getSlug } from '@/app/lib/utils'; import { Table } from '@/app/ui/components/table'; import { lusitana } from '@/app/ui/fonts'; import { useState, useEffect } from 'react'; diff --git a/app/ui/dashboard/nav-links.tsx b/app/ui/dashboard/nav-links.tsx index ef3e4ea..336d798 100644 --- a/app/ui/dashboard/nav-links.tsx +++ b/app/ui/dashboard/nav-links.tsx @@ -11,19 +11,23 @@ import Link from 'next/link'; import { usePathname } from 'next/navigation'; import clsx from 'clsx'; import { getSlug } from '@/app/lib/utils'; +import { useEffect, useState } from 'react'; // Map of links to display in the side navigation. // Depending on the size of the application, this would be stored in a database. -const links = [ - { name: 'Guests', href: `/${getSlug()}/dashboard/guests`, icon: UserGroupIcon }, - { name: 'Expenses', href: `/${getSlug()}/dashboard/expenses`, icon: BanknotesIcon }, - { name: 'Table distributions', href: `/${getSlug()}/dashboard/tables`, icon: RectangleGroupIcon }, -]; - export default function NavLinks() { const pathname = usePathname(); + const [slug, setSlug] = useState("default"); + useEffect(() => { setSlug(getSlug()) }, []); + + const links = [ + { name: 'Guests', href: `/${slug}/dashboard/guests`, icon: UserGroupIcon }, + { name: 'Expenses', href: `/${slug}/dashboard/expenses`, icon: BanknotesIcon }, + { name: 'Table distributions', href: `/${slug}/dashboard/tables`, icon: RectangleGroupIcon }, + ]; + return ( <> {links.map((link) => { diff --git a/app/ui/dashboard/sidenav.tsx b/app/ui/dashboard/sidenav.tsx index fbba770..067de4b 100644 --- a/app/ui/dashboard/sidenav.tsx +++ b/app/ui/dashboard/sidenav.tsx @@ -9,15 +9,23 @@ import { gloriaHallelujah } from '@/app/ui/fonts'; import { logout } from '@/app/api/authentication'; import { useRouter } from 'next/navigation'; import { getSlug } from '@/app/lib/utils'; +import { useEffect, useState } from 'react'; export default function SideNav() { const router = useRouter(); + const [slug, setSlug] = useState("default"); + useEffect(() => { setSlug(getSlug()) }, []); + + const [currentUser, setCurrentUser] = useState<{ email: string } | null>(null); + useEffect(() => { setCurrentUser(JSON.parse(localStorage.getItem('currentUser') || '{}')) }, []); + + return (

Wedding Planner

@@ -26,14 +34,14 @@ export default function SideNav() {
- Logged in as {JSON.parse(localStorage.getItem('currentUser') || '{}').email} + Logged in as {currentUser?.email}