diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 7cf992f09..720fc3ee0 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -1,4 +1,4 @@ -name: Node.js CI +name: E2E Tests permissions: contents: write packages: write @@ -6,7 +6,7 @@ on: push: branches: [main] pull_request: - branches: [main] + branches: [main, staging] workflow_dispatch: inputs: debug_enabled: @@ -15,13 +15,14 @@ on: required: false default: false jobs: - test: + e2e-tests: if: github.actor != 'renovate[bot]' timeout-minutes: 60 env: CI: true ESLINT_USE_FLAT_CONFIG: true SUPABASE_URL: http://localhost:54321 + VITE_PORT: 5173 VITE_BASE_URL: http://localhost:5173 VITE_RECOVERY_AUTH_REDIRECT_URL: http://localhost:5173/profile/reset-password VITE_SUPABASE_URL: http://localhost:54321 diff --git a/.github/workflows/linting-and-unit-tests.yml b/.github/workflows/linting-and-unit-tests.yml index 1575db6f4..15c776ea4 100644 --- a/.github/workflows/linting-and-unit-tests.yml +++ b/.github/workflows/linting-and-unit-tests.yml @@ -8,7 +8,7 @@ on: pull_request: branches: [main, staging] jobs: - test: + lint-and-unit-tests: runs-on: ubuntu-latest steps: - name: Checkout code ⬇️ diff --git a/.gitignore b/.gitignore index b859edc36..667eef843 100644 --- a/.gitignore +++ b/.gitignore @@ -25,7 +25,7 @@ dist-ssr *.njsproj *.sln *.sw? -/test-results/ +**/test-results/ /playwright-report/ /blob-report/ /playwright/.cache/ diff --git a/package.json b/package.json index e0fbd03eb..c995b240b 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,8 @@ "prettier:ci": "prettier --check .", "preview": "vite preview", "test": "npm run test:unit && npm run test:e2e", - "test:unit": "vitest run", - "test:e2e": "playwright test" + "test:unit": "vitest run --config ./tests/unit/vitest.config.ts", + "test:e2e": "playwright test --config=tests/e2e/playwright.config.ts" }, "dependencies": { "@supabase/supabase-js": "2.43.1", diff --git a/src/tests/e2e/auth/_setup.test.ts b/tests/e2e/_setup.test.ts similarity index 96% rename from src/tests/e2e/auth/_setup.test.ts rename to tests/e2e/_setup.test.ts index 614d3f8b3..0bfa6b6bf 100644 --- a/src/tests/e2e/auth/_setup.test.ts +++ b/tests/e2e/_setup.test.ts @@ -1,6 +1,5 @@ import { expect, test } from "@playwright/test"; import { - baseUrl, defaultEmail, defaultInbucketEmailUsername, defaultPassword, @@ -13,7 +12,6 @@ import { test.describe("Setup", () => { test("should check if all environment/default variables are set", () => { - expect(baseUrl).toBeDefined(); expect(supabaseApiUrl).not.toBe(""); expect(supabaseAnonKey).not.toBe(""); expect(inbucketUrl).not.toBe(""); diff --git a/src/tests/e2e/auth/edit-user.test.ts b/tests/e2e/auth/edit-user.test.ts similarity index 83% rename from src/tests/e2e/auth/edit-user.test.ts rename to tests/e2e/auth/edit-user.test.ts index 848f0170d..5a945a7d6 100644 --- a/src/tests/e2e/auth/edit-user.test.ts +++ b/tests/e2e/auth/edit-user.test.ts @@ -5,7 +5,6 @@ import { registerThenLoginWithDefaultAccount, } from "./utils.ts"; import { - baseUrl, changedEmail, changedInbucketEmailUsername, defaultEmail, @@ -14,12 +13,12 @@ import { defaultUsername, inbucketUrl, supabaseClient, -} from "./constants.ts"; +} from "../constants.ts"; test.describe("Edit user", () => { test.describe("Edit Username", () => { - test.beforeEach(async ({ page }) => { - await registerThenLoginWithDefaultAccount(page); + test.beforeEach(async ({ page, isMobile }) => { + await registerThenLoginWithDefaultAccount({ page, isMobile }); }); test.afterEach(async () => { @@ -27,7 +26,7 @@ test.describe("Edit user", () => { }); test("should be able to edit username", async ({ page }) => { - await page.goto(`${baseUrl}/profile`); + await page.goto(`/profile`); await page .locator("div") @@ -47,8 +46,8 @@ test.describe("Edit user", () => { }); test.describe("Edit Email", () => { - test.beforeEach(async ({ page }) => { - await registerThenLoginWithDefaultAccount(page); + test.beforeEach(async ({ page, isMobile }) => { + await registerThenLoginWithDefaultAccount({ page, isMobile }); }); test.afterEach(async () => { @@ -56,7 +55,7 @@ test.describe("Edit user", () => { }); test("should be able to edit e-mail", async ({ page }) => { - await page.goto(`${baseUrl}/profile`); + await page.goto(`/profile`); await page .locator("div") @@ -87,8 +86,8 @@ test.describe("Edit user", () => { }); test.describe("Edit password", () => { - test.beforeEach(async ({ page }) => { - await registerThenLoginWithDefaultAccount(page); + test.beforeEach(async ({ page, isMobile }) => { + await registerThenLoginWithDefaultAccount({ page, isMobile }); }); test.afterEach(async () => { @@ -96,7 +95,7 @@ test.describe("Edit user", () => { }); test("should be able to edit password", async ({ page }) => { - await page.goto(`${baseUrl}/profile`); + await page.goto(`/profile`); await page.getByRole("button", { name: "Passwort ändern" }).click(); await page.getByRole("button", { name: "OK" }).click(); @@ -114,12 +113,12 @@ test.describe("Edit user", () => { }); test.describe("Delete account", () => { - test.beforeEach(async ({ page }) => { - await registerThenLoginWithDefaultAccount(page); + test.beforeEach(async ({ page, isMobile }) => { + await registerThenLoginWithDefaultAccount({ page, isMobile }); }); test("should be able to delete account", async ({ page }) => { - await page.goto(`${baseUrl}/profile`); + await page.goto(`/profile`); await page.getByRole("button", { name: "Account löschen" }).click(); await page.getByRole("button", { name: "Löschen", exact: true }).click(); diff --git a/src/tests/e2e/auth/forgot-password.test.ts b/tests/e2e/auth/forgot-password.test.ts similarity index 88% rename from src/tests/e2e/auth/forgot-password.test.ts rename to tests/e2e/auth/forgot-password.test.ts index a58a0dfbf..c8dbf90a0 100644 --- a/src/tests/e2e/auth/forgot-password.test.ts +++ b/tests/e2e/auth/forgot-password.test.ts @@ -5,24 +5,23 @@ import { registerThenLogoutWithDefaultAccount, } from "./utils"; import { - baseUrl, defaultEmail, defaultInbucketEmailUsername, defaultPassword, inbucketUrl, -} from "./constants"; +} from "../constants"; test.describe("Forgot password", () => { test.describe("Happy Case", () => { - test.beforeEach(async ({ page }) => { - await registerThenLogoutWithDefaultAccount(page); + test.beforeEach(async ({ page, isMobile }) => { + await registerThenLogoutWithDefaultAccount({ page, isMobile }); }); test.afterEach(async () => { await deleteDefaultAccount(); }); test("should be able to reset password via e-mail", async ({ page }) => { - await page.goto(`${baseUrl}/profile`); + await page.goto(`/profile`); await page.getByRole("link", { name: "Passwort vergessen?" }).click(); await page.getByLabel("E-Mail").click(); await page.getByLabel("E-Mail").fill(defaultEmail); @@ -59,7 +58,7 @@ test.describe("Forgot password", () => { test("should not be able to reset password with empty email", async ({ page, }) => { - await page.goto(`${baseUrl}/profile`); + await page.goto(`/profile`); await page.getByRole("link", { name: "Passwort vergessen?" }).click(); await page.getByLabel("E-Mail").click(); @@ -72,7 +71,7 @@ test.describe("Forgot password", () => { test("should not be able to reset password with invalid email format", async ({ page, }) => { - await page.goto(`${baseUrl}/profile`); + await page.goto(`/profile`); await page.getByRole("link", { name: "Passwort vergessen?" }).click(); await page.getByLabel("E-Mail").click(); @@ -84,9 +83,8 @@ test.describe("Forgot password", () => { test('should not be able to reset password by going on "profile/reset-password" directly', async ({ page, }) => { - await page.goto(`${baseUrl}/profile/reset-password`); + await page.goto(`/profile/reset-password`); - await page.goto("http://localhost:5173/profile/reset-password"); await expect( page.getByText("Einen Moment Geduld bitte..."), ).toBeVisible(); @@ -100,7 +98,7 @@ test.describe("Forgot password", () => { page.getByText("Hinweis: Diese Seite kann nur"), ).toBeVisible(); await page.getByRole("button", { name: "Zurück zur Startseite" }).click(); - await expect(page).toHaveURL(new RegExp(`${baseUrl}/map.*`)); + await expect(page).toHaveURL(new RegExp(`/map.*`)); }); }); @@ -112,7 +110,7 @@ test.describe("Forgot password", () => { const browserContext = await browser.newContext(); const page = await browserContext.newPage(); - await page.goto(`${baseUrl}/profile`); + await page.goto(`/profile`); await page.getByRole("link", { name: "Passwort vergessen?" }).click(); await page.getByLabel("E-Mail").click(); @@ -129,8 +127,8 @@ test.describe("Forgot password", () => { }); test.describe("Reset password page", () => { - test.beforeEach(async ({ page }) => { - await registerThenLogoutWithDefaultAccount(page); + test.beforeEach(async ({ page, isMobile }) => { + await registerThenLogoutWithDefaultAccount({ page, isMobile }); }); test.afterEach(async () => { await deleteDefaultAccount(); @@ -142,7 +140,7 @@ test.describe("Forgot password", () => { const browserContext = await browser.newContext(); const page = await browserContext.newPage(); - await page.goto(`${baseUrl}/profile`); + await page.goto(`/profile`); await page.getByRole("link", { name: "Passwort vergessen?" }).click(); await page.getByLabel("E-Mail").click(); await page.getByLabel("E-Mail").fill(defaultEmail); diff --git a/src/tests/e2e/auth/login.test.ts b/tests/e2e/auth/login.test.ts similarity index 89% rename from src/tests/e2e/auth/login.test.ts rename to tests/e2e/auth/login.test.ts index 7a37b3ff2..232228c97 100644 --- a/src/tests/e2e/auth/login.test.ts +++ b/tests/e2e/auth/login.test.ts @@ -3,19 +3,19 @@ import { deleteDefaultAccount, registerThenLogoutWithDefaultAccount, } from "./utils"; -import { baseUrl, defaultEmail, defaultPassword } from "./constants"; +import { defaultEmail, defaultPassword } from "../constants"; test.describe("Login", () => { test.describe("Happy Case", () => { - test.beforeEach(async ({ page }) => { - await registerThenLogoutWithDefaultAccount(page); + test.beforeEach(async ({ page, isMobile }) => { + await registerThenLogoutWithDefaultAccount({ page, isMobile }); }); test.afterEach(async () => { await deleteDefaultAccount(); }); test("should be able to log-in then log-out", async ({ page }) => { - await page.goto(`${baseUrl}/map`); + await page.goto(`/map`); // Go to profile await page.getByRole("link", { name: "Profil" }).click(); @@ -39,7 +39,7 @@ test.describe("Login", () => { test.describe("Client-Side Validation", () => { test("should not be able to log-in with empty email", async ({ page }) => { - await page.goto(`${baseUrl}/profile`); + await page.goto(`/profile`); await page.getByLabel("E-Mail").click(); await page.getByLabel("E-Mail").fill(" "); @@ -54,7 +54,7 @@ test.describe("Login", () => { test("should not be able to log-in with invalid email format", async ({ page, }) => { - await page.goto(`${baseUrl}/profile`); + await page.goto(`/profile`); await page.getByLabel("E-Mail").click(); await page.getByLabel("E-Mail").fill("invalid-email"); @@ -68,7 +68,7 @@ test.describe("Login", () => { test("should not be able to log-in with empty password", async ({ page, }) => { - await page.goto(`${baseUrl}/profile`); + await page.goto(`/profile`); await page.getByLabel("E-Mail").click(); await page.getByLabel("E-Mail").fill("invalid-email"); @@ -85,7 +85,7 @@ test.describe("Login", () => { test("should not be able to log-in with wrong email/password credentials", async ({ page, }) => { - await page.goto(`${baseUrl}/profile`); + await page.goto(`/profile`); await page.getByLabel("E-Mail").click(); await page.getByLabel("E-Mail").fill("email-with-no-account@example.com"); @@ -108,7 +108,7 @@ test.describe("Login", () => { const browserContext = await browser.newContext(); const page = await browserContext.newPage(); - await page.goto(`${baseUrl}/profile`); + await page.goto(`/profile`); await page.getByLabel("E-Mail").click(); await page.getByLabel("E-Mail").fill(defaultEmail); diff --git a/src/tests/e2e/auth/register.test.ts b/tests/e2e/auth/register.test.ts similarity index 92% rename from src/tests/e2e/auth/register.test.ts rename to tests/e2e/auth/register.test.ts index 1c48d50df..84889ba2e 100644 --- a/src/tests/e2e/auth/register.test.ts +++ b/tests/e2e/auth/register.test.ts @@ -1,13 +1,12 @@ /* eslint-disable max-lines */ import { expect, test } from "@playwright/test"; import { - baseUrl, defaultEmail, defaultInbucketEmailUsername, defaultPassword, defaultUsername, inbucketUrl, -} from "./constants"; +} from "../constants"; import { deleteDefaultAccount, registerThenLogoutWithDefaultAccount, @@ -19,8 +18,11 @@ test.describe("Register", () => { await deleteDefaultAccount(); }); - test("should be able to register then logout", async ({ page }) => { - await page.goto(`${baseUrl}/profile`); + test("should be able to register then logout", async ({ + page, + isMobile, + }) => { + await page.goto(`/profile`); await page.getByRole("link", { name: "Registriere Dich" }).click(); await page.getByLabel("E-Mail").click(); @@ -50,7 +52,13 @@ test.describe("Register", () => { .click(); // close splash screen - await page.locator("#splash-action-button").click(); + if (isMobile) { + await page.getByTestId("splash-close-button").nth(0).click(); + } + + if (!isMobile) { + await page.getByTestId("splash-close-button").nth(1).click(); + } await page.getByRole("link", { name: "Profil" }).click(); await expect( @@ -68,7 +76,7 @@ test.describe("Register", () => { test("should not be able to register with empty e-mail", async ({ page, }) => { - await page.goto(`${baseUrl}/profile`); + await page.goto(`/profile`); await page.getByRole("link", { name: "Registriere Dich" }).click(); await page.getByLabel("E-Mail").click(); @@ -82,7 +90,7 @@ test.describe("Register", () => { test("should not be able to register with invalid e-mail format", async ({ page, }) => { - await page.goto(`${baseUrl}/profile`); + await page.goto(`/profile`); await page.getByRole("link", { name: "Registriere Dich" }).click(); await page.getByLabel("E-Mail").click(); @@ -93,7 +101,7 @@ test.describe("Register", () => { test("should not be able to register with empty username", async ({ page, }) => { - await page.goto(`${baseUrl}/profile`); + await page.goto(`/profile`); await page.getByRole("link", { name: "Registriere Dich" }).click(); await page.getByLabel("Benutzername").fill(" "); @@ -105,7 +113,7 @@ test.describe("Register", () => { test("should not be able to register with invalid username format", async ({ page, }) => { - await page.goto(`${baseUrl}/profile`); + await page.goto(`/profile`); await page.getByRole("link", { name: "Registriere Dich" }).click(); await page.getByLabel("Benutzername").fill("a"); // too short @@ -139,7 +147,7 @@ test.describe("Register", () => { test("should not be able to register with empty password", async ({ page, }) => { - await page.goto(`${baseUrl}/profile`); + await page.goto(`/profile`); await page.getByRole("link", { name: "Registriere Dich" }).click(); await page.getByLabel("Passwort").fill(" "); @@ -151,7 +159,7 @@ test.describe("Register", () => { test("should not be able to register with invalid password format", async ({ page, }) => { - await page.goto(`${baseUrl}/profile`); + await page.goto(`/profile`); await page.getByRole("link", { name: "Registriere Dich" }).click(); await page.getByLabel("Passwort").fill("a1Q!"); // too short @@ -188,8 +196,8 @@ test.describe("Register", () => { }); test.describe("Server-Side Validation", () => { - test.beforeEach(async ({ page }) => { - await registerThenLogoutWithDefaultAccount(page); + test.beforeEach(async ({ page, isMobile }) => { + await registerThenLogoutWithDefaultAccount({ page, isMobile }); }); test.afterEach(async () => { @@ -199,7 +207,7 @@ test.describe("Register", () => { test("should not be able to register with already registered e-mail", async ({ page, }) => { - await page.goto(`${baseUrl}/profile`); + await page.goto(`/profile`); await page.getByRole("link", { name: "Registriere Dich" }).click(); await page.getByLabel("E-Mail").click(); @@ -216,7 +224,7 @@ test.describe("Register", () => { test("should not be able to register with already registered username", async ({ page, }) => { - await page.goto(`${baseUrl}/profile`); + await page.goto(`/profile`); await page.getByRole("link", { name: "Registriere Dich" }).click(); await page.getByLabel("E-Mail").click(); @@ -239,7 +247,7 @@ test.describe("Register", () => { const browserContext = await browser.newContext(); const page = await browserContext.newPage(); - await page.goto(`${baseUrl}/profile`); + await page.goto(`/profile`); await page.getByRole("link", { name: "Registriere Dich" }).click(); await page.getByLabel("E-Mail").click(); diff --git a/tests/e2e/base/base.test.ts b/tests/e2e/base/base.test.ts new file mode 100644 index 000000000..0f540cc4b --- /dev/null +++ b/tests/e2e/base/base.test.ts @@ -0,0 +1,18 @@ +import { expect, test } from "@playwright/test"; + +test.describe("Is Alive", () => { + test.describe("Happy Case", () => { + test("should be able to open the /map", async ({ page, isMobile }) => { + await page.goto(`/map`); + await expect(page.getByText("Die Berliner Stadtbäume")).toBeVisible(); + + if (isMobile) { + await page.getByTestId("splash-close-button").nth(0).click(); + } + + if (!isMobile) { + await page.getByTestId("splash-close-button").nth(1).click(); + } + }); + }); +}); diff --git a/src/tests/e2e/auth/constants.ts b/tests/e2e/constants.ts similarity index 93% rename from src/tests/e2e/auth/constants.ts rename to tests/e2e/constants.ts index 9d6579c61..d9ec5b19e 100644 --- a/src/tests/e2e/auth/constants.ts +++ b/tests/e2e/constants.ts @@ -1,7 +1,6 @@ import { createClient } from "@supabase/supabase-js"; import "dotenv/config"; -export const baseUrl = process.env.VITE_BASE_URL; export const supabaseApiUrl = process.env.VITE_SUPABASE_URL ?? ""; export const supabaseAnonKey = process.env.VITE_SUPABASE_ANON_KEY ?? ""; export const inbucketUrl = process.env.TEST_SUPABASE_INBUCKET_URL ?? ""; diff --git a/playwright.config.ts b/tests/e2e/playwright.config.ts similarity index 78% rename from playwright.config.ts rename to tests/e2e/playwright.config.ts index e8191d7dd..be4ce03a1 100644 --- a/playwright.config.ts +++ b/tests/e2e/playwright.config.ts @@ -1,17 +1,13 @@ import { defineConfig, devices } from "@playwright/test"; -/** - * Read environment variables from file. - * https://github.com/motdotla/dotenv - */ -// require('dotenv').config(); +const port = process.env.VITE_PORT ? parseInt(process.env.VITE_PORT) : 5173; /** * See https://playwright.dev/docs/test-configuration. */ // eslint-disable-next-line @technologiestiftung/no-default-export export default defineConfig({ - testDir: "./src/tests/e2e", + testDir: "./", /* Run tests in files in parallel */ fullyParallel: true, /* Fail the build on CI if you accidentally left test.only in the source code. */ @@ -21,16 +17,19 @@ export default defineConfig({ /* Opt out of parallel tests on CI. */ workers: 1, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: "list", + reporter: [ + ["list"], + ["html", { open: "never", outputFolder: "./test-results" }], + ], /* 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: process.env.VITE_BASE_URL, /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: "retain-on-failure", + trace: "on-first-retry", }, - timeout: 60000, + timeout: 30000, /* Configure projects for major browsers */ projects: [ @@ -72,8 +71,16 @@ export default defineConfig({ /* Run your local dev server before starting the tests */ webServer: { - command: "npm run dev", + command: getCommand(), url: process.env.VITE_BASE_URL, reuseExistingServer: !process.env.CI, }, }); + +function getCommand() { + if (process.env.CI) { + return `npm run preview -- --port ${port}`; + } + + return `VITE_PW_TEST=true npm run build && npm run preview -- --port ${port}`; +} diff --git a/src/tests/e2e/auth/tree-detail.test.ts b/tests/e2e/tree-details/tree-detail.test.ts similarity index 62% rename from src/tests/e2e/auth/tree-detail.test.ts rename to tests/e2e/tree-details/tree-detail.test.ts index fab8a96e7..28e4a326e 100644 --- a/src/tests/e2e/auth/tree-detail.test.ts +++ b/tests/e2e/tree-details/tree-detail.test.ts @@ -1,23 +1,25 @@ import { expect, test } from "@playwright/test"; -import { baseUrl } from "./constants"; -import { useIsInVegetationPeriod } from "../../../utils/use-is-in-vegetation-period"; +import { useIsInVegetationPeriod } from "../../../src/utils/use-is-in-vegetation-period"; const isInVegetationPeriod = useIsInVegetationPeriod(); test.describe("Tree detail view", () => { - test.fixme( - !!process.env.CI, - "This feature needs the API to run in the CI, which currently is not set-up as vercel:dev needs credentials", - ); - - test("should show tree info for baby tree", async ({ page }) => { - await page.goto(`${baseUrl}/map?treeId=_23002dc7a1`); + test("should show tree info for baby tree", async ({ page, isMobile }) => { + await page.goto(`/map?&treeId=00008100:002faeaf`); // close splash screen - await page.locator("#splash-action-button").click(); + if (isMobile) { + await page.getByTestId("splash-close-button").nth(0).click(); + } + + if (!isMobile) { + await page.getByTestId("splash-close-button").nth(1).click(); + } - await expect(page.getByText("Bauminformationen")).toBeVisible(); - await expect(page.getByText("Zier-Feld-Ahorn 'Red Shine'")).toBeVisible(); + await expect( + page.getByText("Bauminformationen", { exact: true }), + ).toBeVisible(); + await expect(page.getByText("Resista Ulme 'Rebona'")).toBeVisible(); await expect( page.getByText( "Dieser Baum wird bereits vom Bezirksamt versorgt und muss nicht gegossen werden.", @@ -34,22 +36,24 @@ test.describe("Tree detail view", () => { await expect(page.getByTestId("water-tree-button")).not.toBeVisible(); await page.getByRole("button", { name: "Baumsteckbrief" }).click(); - await expect(page.getByText("Die Gattung der Ahorne")).toBeVisible(); + await expect(page.getByText("Der Anteil der Ulmen (Ulmus)")).toBeVisible(); await page.getByRole("button", { name: "Baumsteckbrief" }).click(); - await expect(page.getByText("Die Gattung der Ahorne")).not.toBeVisible(); + await expect( + page.getByText("Der Anteil der Ulmen (Ulmus)"), + ).not.toBeVisible(); // Check for exact age await expect(page.getByText("Standalter")).toBeVisible(); const calculatedAge = await page.getByTestId("age").textContent(); expect(calculatedAge).toBe( - // At the year of writing this test, the tree was 2 years old. + // At the year of writing this test, the tree was 1 year old. // Every year, the tree gets one year older, as we all do - time is merciless. - (2 + new Date().getFullYear() - 2024).toString(), + (1 + new Date().getFullYear() - 2024).toString(), ); if (isInVegetationPeriod) { await expect( - page.getByText("Vom Bezirksamt versorgt", { exact: true }), + page.getByText("Bereits vom Bezirksamt versorgt", { exact: true }), ).toBeVisible(); await expect(page.getByTestId("water-progress-circle")).toBeVisible(); } diff --git a/src/tests/unit/baby-tree-water-needs-special-district.test.ts b/tests/unit/baby-tree-water-needs-special-district.test.ts similarity index 93% rename from src/tests/unit/baby-tree-water-needs-special-district.test.ts rename to tests/unit/baby-tree-water-needs-special-district.test.ts index ff08084e2..c3230a0d5 100644 --- a/src/tests/unit/baby-tree-water-needs-special-district.test.ts +++ b/tests/unit/baby-tree-water-needs-special-district.test.ts @@ -1,10 +1,10 @@ import { expect, test } from "vitest"; -import { useTreeAgeClassification } from "../../components/tree-detail/hooks/use-tree-age-classification"; -import { useTreeWaterNeedsData } from "../../components/tree-detail/hooks/use-tree-water-needs-data"; +import { useTreeAgeClassification } from "../../src/components/tree-detail/hooks/use-tree-age-classification"; +import { useTreeWaterNeedsData } from "../../src/components/tree-detail/hooks/use-tree-water-needs-data"; import { TreeAgeClassification, TreeCoreData, -} from "../../components/tree-detail/tree-types"; +} from "../../src/components/tree-detail/tree-types"; test("should calculate correct water needs for baby tree in special district", () => { const treeData: TreeCoreData = { diff --git a/src/tests/unit/baby-tree-water-needs.test.ts b/tests/unit/baby-tree-water-needs.test.ts similarity index 93% rename from src/tests/unit/baby-tree-water-needs.test.ts rename to tests/unit/baby-tree-water-needs.test.ts index 129e3eda3..c5bb080b4 100644 --- a/src/tests/unit/baby-tree-water-needs.test.ts +++ b/tests/unit/baby-tree-water-needs.test.ts @@ -1,11 +1,11 @@ import { expect, test } from "vitest"; -import { useTreeAgeClassification } from "../../components/tree-detail/hooks/use-tree-age-classification"; -import { useTreeWaterNeedsData } from "../../components/tree-detail/hooks/use-tree-water-needs-data"; +import { useTreeAgeClassification } from "../../src/components/tree-detail/hooks/use-tree-age-classification"; +import { useTreeWaterNeedsData } from "../../src/components/tree-detail/hooks/use-tree-water-needs-data"; import { TreeAgeClassification, TreeCoreData, TreeWateringData, -} from "../../components/tree-detail/tree-types"; +} from "../../src/components/tree-detail/tree-types"; test("should calculate correct water needs for baby tree", () => { const waterings: TreeWateringData[] = [ diff --git a/src/tests/unit/junior-tree-water-needs.test.ts b/tests/unit/junior-tree-water-needs.test.ts similarity index 94% rename from src/tests/unit/junior-tree-water-needs.test.ts rename to tests/unit/junior-tree-water-needs.test.ts index 0c9d783aa..a9a935acf 100644 --- a/src/tests/unit/junior-tree-water-needs.test.ts +++ b/tests/unit/junior-tree-water-needs.test.ts @@ -1,11 +1,11 @@ import { expect, test } from "vitest"; -import { useTreeAgeClassification } from "../../components/tree-detail/hooks/use-tree-age-classification"; -import { useTreeWaterNeedsData } from "../../components/tree-detail/hooks/use-tree-water-needs-data"; +import { useTreeAgeClassification } from "../../src/components/tree-detail/hooks/use-tree-age-classification"; +import { useTreeWaterNeedsData } from "../../src/components/tree-detail/hooks/use-tree-water-needs-data"; import { TreeAgeClassification, TreeCoreData, TreeWateringData, -} from "../../components/tree-detail/tree-types"; +} from "../../src/components/tree-detail/tree-types"; test("should calculate correct water needs for junior tree", () => { const waterings: TreeWateringData[] = [ diff --git a/src/tests/unit/senior-tree-water-needs-special-district.test.ts b/tests/unit/senior-tree-water-needs-special-district.test.ts similarity index 93% rename from src/tests/unit/senior-tree-water-needs-special-district.test.ts rename to tests/unit/senior-tree-water-needs-special-district.test.ts index a0038310e..ef1826bda 100644 --- a/src/tests/unit/senior-tree-water-needs-special-district.test.ts +++ b/tests/unit/senior-tree-water-needs-special-district.test.ts @@ -1,10 +1,10 @@ import { expect, test } from "vitest"; -import { useTreeAgeClassification } from "../../components/tree-detail/hooks/use-tree-age-classification"; -import { useTreeWaterNeedsData } from "../../components/tree-detail/hooks/use-tree-water-needs-data"; +import { useTreeAgeClassification } from "../../src/components/tree-detail/hooks/use-tree-age-classification"; +import { useTreeWaterNeedsData } from "../../src/components/tree-detail/hooks/use-tree-water-needs-data"; import { TreeAgeClassification, TreeCoreData, -} from "../../components/tree-detail/tree-types"; +} from "../../src/components/tree-detail/tree-types"; test("should calculate correct water needs for senior tree in special district", () => { const treeData: TreeCoreData = { diff --git a/src/tests/unit/senior-tree-water-needs.test.ts b/tests/unit/senior-tree-water-needs.test.ts similarity index 93% rename from src/tests/unit/senior-tree-water-needs.test.ts rename to tests/unit/senior-tree-water-needs.test.ts index 1bb555fd6..8fba90895 100644 --- a/src/tests/unit/senior-tree-water-needs.test.ts +++ b/tests/unit/senior-tree-water-needs.test.ts @@ -1,11 +1,11 @@ import { expect, test } from "vitest"; -import { useTreeAgeClassification } from "../../components/tree-detail/hooks/use-tree-age-classification"; -import { useTreeWaterNeedsData } from "../../components/tree-detail/hooks/use-tree-water-needs-data"; +import { useTreeAgeClassification } from "../../src/components/tree-detail/hooks/use-tree-age-classification"; +import { useTreeWaterNeedsData } from "../../src/components/tree-detail/hooks/use-tree-water-needs-data"; import { TreeAgeClassification, TreeCoreData, TreeWateringData, -} from "../../components/tree-detail/tree-types"; +} from "../../src/components/tree-detail/tree-types"; test("should calculate correct water needs for senior tree", () => { const waterings: TreeWateringData[] = [ diff --git a/src/tests/unit/unknown-tree-water-needs.test.ts b/tests/unit/unknown-tree-water-needs.test.ts similarity index 93% rename from src/tests/unit/unknown-tree-water-needs.test.ts rename to tests/unit/unknown-tree-water-needs.test.ts index c715e71c9..c69ae2e54 100644 --- a/src/tests/unit/unknown-tree-water-needs.test.ts +++ b/tests/unit/unknown-tree-water-needs.test.ts @@ -1,11 +1,11 @@ import { expect, test } from "vitest"; -import { useTreeAgeClassification } from "../../components/tree-detail/hooks/use-tree-age-classification"; -import { useTreeWaterNeedsData } from "../../components/tree-detail/hooks/use-tree-water-needs-data"; +import { useTreeAgeClassification } from "../../src/components/tree-detail/hooks/use-tree-age-classification"; +import { useTreeWaterNeedsData } from "../../src/components/tree-detail/hooks/use-tree-water-needs-data"; import { TreeAgeClassification, TreeCoreData, TreeWateringData, -} from "../../components/tree-detail/tree-types"; +} from "../../src/components/tree-detail/tree-types"; test("should calculate correct water needs for senior tree", () => { const waterings: TreeWateringData[] = [ diff --git a/tests/unit/vitest.config.ts b/tests/unit/vitest.config.ts new file mode 100644 index 000000000..02a2ef6fa --- /dev/null +++ b/tests/unit/vitest.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from "vitest/config"; + +// eslint-disable-next-line @technologiestiftung/no-default-export +export default defineConfig({ + test: { + include: ["./tests/unit/**/*.test.ts"], + }, +}); diff --git a/vitest.config.ts b/vitest.config.ts deleted file mode 100644 index 24974964f..000000000 --- a/vitest.config.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { defineConfig } from "vitest/config"; - -export default defineConfig({ - test: { - include: ["src/tests/unit/**/*.test.ts"], - }, -});