From c688964593a14fd5b5b20e7c05da68c75029e1b1 Mon Sep 17 00:00:00 2001 From: youneshenniwrites Date: Fri, 12 Sep 2025 16:16:39 +0100 Subject: [PATCH 1/2] generate client --- scripts/generate-client.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/generate-client.sh diff --git a/scripts/generate-client.sh b/scripts/generate-client.sh old mode 100644 new mode 100755 From ebc7e585f89bf97f787bca0b89cb3654cbd78d59 Mon Sep 17 00:00:00 2001 From: youneshenniwrites Date: Fri, 12 Sep 2025 18:12:34 +0100 Subject: [PATCH 2/2] add dashboard tests --- docker-compose.override.yml | 21 ++++---- frontend/tests/dashboard.spec.ts | 84 ++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 11 deletions(-) create mode 100644 frontend/tests/dashboard.spec.ts diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 0751abe901..25ac547f5d 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -1,5 +1,4 @@ services: - # Local services are available on their ports, but also available on: # http://api.localhost.tiangolo.com: backend # http://dashboard.localhost.tiangolo.com: frontend @@ -67,16 +66,16 @@ services: - run - --reload - "app/main.py" - develop: - watch: - - path: ./backend - action: sync - target: /app - ignore: - - ./backend/.venv - - .venv - - path: ./backend/pyproject.toml - action: rebuild + # develop: + # watch: + # - path: ./backend + # action: sync + # target: /app + # ignore: + # - ./backend/.venv + # - .venv + # - path: ./backend/pyproject.toml + # action: rebuild # TODO: remove once coverage is done locally volumes: - ./backend/htmlcov:/app/htmlcov diff --git a/frontend/tests/dashboard.spec.ts b/frontend/tests/dashboard.spec.ts new file mode 100644 index 0000000000..6cc1f20826 --- /dev/null +++ b/frontend/tests/dashboard.spec.ts @@ -0,0 +1,84 @@ +import { expect, test } from "@playwright/test"; +import { randomEmail, randomPassword } from "./utils/random"; +import { signUpNewUser, logInUser, logOutUser } from "./utils/user"; + +test.describe("Dashboard page", () => { + test("is visible after login", async ({ page }) => { + const email = randomEmail(); + const password = randomPassword(); + + // Sign up a new user + await signUpNewUser(page, "Playwright Dashboard Test", email, password); + + // Log in with the new user + await logInUser(page, email, password); + + // Navigate to dashboard (root path) + await page.goto("/"); + // Debug: take screenshot if fails + try { + await expect( + page.getByText("Welcome back, nice to see you again!") + ).toBeVisible({ timeout: 10000 }); + } catch (e) { + await page.screenshot({ + path: "dashboard-visible-after-login-fail.png", + fullPage: true, + }); + throw e; + } + // Check for greeting (user's name or email) + await expect(page.getByText(/^Hi, /)).toBeVisible({ timeout: 10000 }); + // Check for at least one button (UI loaded) + const buttons = await page.getByRole("button").all(); + expect(buttons.length).toBeGreaterThan(0); + }); + + test("redirects to login when not authenticated", async ({ page }) => { + await page.goto("/"); + // Wait for redirect to /login + await page.waitForURL("/login", { timeout: 10000 }); + // Debug: take screenshot if fails + try { + await expect(page.getByPlaceholder("Email")).toBeVisible({ + timeout: 10000, + }); + await expect( + page.getByPlaceholder("Password", { exact: true }) + ).toBeVisible({ timeout: 10000 }); + } catch (e) { + await page.screenshot({ + path: "dashboard-redirect-login-fail.png", + fullPage: true, + }); + throw e; + } + }); + + test("user can log out from dashboard", async ({ page }) => { + const email = randomEmail(); + const password = randomPassword(); + + // Sign up and log in + await signUpNewUser(page, "Playwright Logout Test", email, password); + await logInUser(page, email, password); + + // Log out + await logOutUser(page); + // Debug: take screenshot if fails + try { + await expect(page.getByPlaceholder("Email")).toBeVisible({ + timeout: 10000, + }); + await expect( + page.getByPlaceholder("Password", { exact: true }) + ).toBeVisible({ timeout: 10000 }); + } catch (e) { + await page.screenshot({ + path: "dashboard-logout-login-fail.png", + fullPage: true, + }); + throw e; + } + }); +});