diff --git a/.gitignore b/.gitignore index 47f34732..b9ee1fe0 100644 --- a/.gitignore +++ b/.gitignore @@ -35,10 +35,5 @@ build/ /frontend/dist/* !/frontend/dist/.gitkeep -# Playwright files -/frontend/test-results/ -/frontend/playwright-report/ -/frontend/playwright/.cache/ - default.nix Dockerfile.dev diff --git a/frontend/package.json b/frontend/package.json index 7e8beb3b..165123a2 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -14,8 +14,7 @@ "typecheck": "vue-tsc -p ./tsconfig.tsc.json --noEmit", "lint": "eslint src/", "lint:fix": "eslint --fix src/", - "format": "prettier --write .", - "test": "playwright test" + "format": "prettier --write ." }, "dependencies": { "@chenfengyuan/vue-number-input": "^2.0.1", @@ -50,7 +49,6 @@ }, "devDependencies": { "@intlify/unplugin-vue-i18n": "^11.0.1", - "@playwright/test": "^1.54.1", "@tsconfig/node24": "^24.0.2", "@types/lodash-es": "^4.17.12", "@types/node": "^24.10.1", diff --git a/frontend/playwright.config.ts b/frontend/playwright.config.ts deleted file mode 100644 index af335a17..00000000 --- a/frontend/playwright.config.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { defineConfig, devices } from "@playwright/test"; - -/** - * Read environment variables from file. - * https://github.com/motdotla/dotenv - */ -// require('dotenv').config(); - -/** - * See https://playwright.dev/docs/test-configuration. - */ -export default defineConfig({ - testDir: "./tests", - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: process.env.CI ? 2 : 0, - /* Opt out of parallel tests on CI. */ - workers: process.env.CI ? 1 : undefined, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: "html", - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: "http://127.0.0.1:5173", - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: "on-first-retry", - - /* Set default locale to English (US) */ - locale: "en-US", - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: "chromium", - use: { ...devices["Desktop Chrome"] }, - }, - - { - name: "firefox", - use: { ...devices["Desktop Firefox"] }, - }, - - // { - // name: "webkit", - // use: { ...devices["Desktop Safari"] }, - // }, - - /* Test against mobile viewports. */ - // { - // name: 'Mobile Chrome', - // use: { ...devices['Pixel 5'] }, - // }, - // { - // name: 'Mobile Safari', - // use: { ...devices['iPhone 12'] }, - // }, - - /* Test against branded browsers. */ - // { - // name: 'Microsoft Edge', - // use: { ...devices['Desktop Edge'], channel: 'msedge' }, - // }, - // { - // name: 'Google Chrome', - // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, - // }, - ], - - /* Run your local dev server before starting the tests */ - webServer: { - command: "npm run dev", - url: "http://127.0.0.1:5173", - reuseExistingServer: !process.env.CI, - }, -}); diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 7e1ed07d..ff8fa515 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -99,9 +99,6 @@ importers: '@intlify/unplugin-vue-i18n': specifier: ^11.0.1 version: 11.0.1(@vue/compiler-dom@3.5.24)(eslint@9.39.1)(rollup@4.52.5)(typescript@5.6.3)(vue-i18n@11.1.12(vue@3.5.24(typescript@5.6.3)))(vue@3.5.24(typescript@5.6.3)) - '@playwright/test': - specifier: ^1.54.1 - version: 1.56.1 '@tsconfig/node24': specifier: ^24.0.2 version: 24.0.2 @@ -965,11 +962,6 @@ packages: resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@playwright/test@1.56.1': - resolution: {integrity: sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==} - engines: {node: '>=18'} - hasBin: true - '@rolldown/pluginutils@1.0.0-beta.29': resolution: {integrity: sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q==} @@ -1774,11 +1766,6 @@ packages: fraction.js@5.3.4: resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==} - fsevents@2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -2124,16 +2111,6 @@ packages: resolution: {integrity: sha512-afRERtHn54AlwaF2/+LFszyAANTCggGilmcmILUzEjvs3XgFZT+xE6+QWQcAGmu4xajy+Xtj7acLOPdx5/eXWQ==} hasBin: true - playwright-core@1.56.1: - resolution: {integrity: sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==} - engines: {node: '>=18'} - hasBin: true - - playwright@1.56.1: - resolution: {integrity: sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==} - engines: {node: '>=18'} - hasBin: true - postcss-selector-parser@6.1.2: resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} engines: {node: '>=4'} @@ -3442,10 +3419,6 @@ snapshots: '@pkgr/core@0.2.9': {} - '@playwright/test@1.56.1': - dependencies: - playwright: 1.56.1 - '@rolldown/pluginutils@1.0.0-beta.29': {} '@rollup/pluginutils@5.3.0(rollup@4.52.5)': @@ -4333,9 +4306,6 @@ snapshots: fraction.js@5.3.4: {} - fsevents@2.3.2: - optional: true - fsevents@2.3.3: optional: true @@ -4629,14 +4599,6 @@ snapshots: dependencies: '@babel/runtime': 7.28.4 - playwright-core@1.56.1: {} - - playwright@1.56.1: - dependencies: - playwright-core: 1.56.1 - optionalDependencies: - fsevents: 2.3.2 - postcss-selector-parser@6.1.2: dependencies: cssesc: 3.0.0 diff --git a/frontend/test-results/.last-run.json b/frontend/test-results/.last-run.json new file mode 100644 index 00000000..544c11fb --- /dev/null +++ b/frontend/test-results/.last-run.json @@ -0,0 +1,4 @@ +{ + "status": "failed", + "failedTests": [] +} diff --git a/frontend/tests-examples/demo-todo-app.spec.ts b/frontend/tests-examples/demo-todo-app.spec.ts deleted file mode 100644 index c06e8461..00000000 --- a/frontend/tests-examples/demo-todo-app.spec.ts +++ /dev/null @@ -1,489 +0,0 @@ -import { test, expect, type Page } from "@playwright/test"; - -test.beforeEach(async ({ page }) => { - await page.goto("https://demo.playwright.dev/todomvc"); -}); - -const TODO_ITEMS = [ - "buy some cheese", - "feed the cat", - "book a doctors appointment", -]; - -test.describe("New Todo", () => { - test("should allow me to add todo items", async ({ page }) => { - // create a new todo locator - const newTodo = page.getByPlaceholder("What needs to be done?"); - - // Create 1st todo. - await newTodo.fill(TODO_ITEMS[0]); - await newTodo.press("Enter"); - - // Make sure the list only has one todo item. - await expect(page.getByTestId("todo-title")).toHaveText([TODO_ITEMS[0]]); - - // Create 2nd todo. - await newTodo.fill(TODO_ITEMS[1]); - await newTodo.press("Enter"); - - // Make sure the list now has two todo items. - await expect(page.getByTestId("todo-title")).toHaveText([ - TODO_ITEMS[0], - TODO_ITEMS[1], - ]); - - await checkNumberOfTodosInLocalStorage(page, 2); - }); - - test("should clear text input field when an item is added", async ({ - page, - }) => { - // create a new todo locator - const newTodo = page.getByPlaceholder("What needs to be done?"); - - // Create one todo item. - await newTodo.fill(TODO_ITEMS[0]); - await newTodo.press("Enter"); - - // Check that input is empty. - await expect(newTodo).toBeEmpty(); - await checkNumberOfTodosInLocalStorage(page, 1); - }); - - test("should append new items to the bottom of the list", async ({ - page, - }) => { - // Create 3 items. - await createDefaultTodos(page); - - // create a todo count locator - const todoCount = page.getByTestId("todo-count"); - - // Check test using different methods. - await expect(page.getByText("3 items left")).toBeVisible(); - await expect(todoCount).toHaveText("3 items left"); - await expect(todoCount).toContainText("3"); - await expect(todoCount).toHaveText(/3/); - - // Check all items in one call. - await expect(page.getByTestId("todo-title")).toHaveText(TODO_ITEMS); - await checkNumberOfTodosInLocalStorage(page, 3); - }); -}); - -test.describe("Mark all as completed", () => { - test.beforeEach(async ({ page }) => { - await createDefaultTodos(page); - await checkNumberOfTodosInLocalStorage(page, 3); - }); - - test.afterEach(async ({ page }) => { - await checkNumberOfTodosInLocalStorage(page, 3); - }); - - test("should allow me to mark all items as completed", async ({ page }) => { - // Complete all todos. - await page.getByLabel("Mark all as complete").check(); - - // Ensure all todos have 'completed' class. - await expect(page.getByTestId("todo-item")).toHaveClass([ - "completed", - "completed", - "completed", - ]); - await checkNumberOfCompletedTodosInLocalStorage(page, 3); - }); - - test("should allow me to clear the complete state of all items", async ({ - page, - }) => { - const toggleAll = page.getByLabel("Mark all as complete"); - // Check and then immediately uncheck. - await toggleAll.check(); - await toggleAll.uncheck(); - - // Should be no completed classes. - await expect(page.getByTestId("todo-item")).toHaveClass(["", "", ""]); - }); - - test("complete all checkbox should update state when items are completed / cleared", async ({ - page, - }) => { - const toggleAll = page.getByLabel("Mark all as complete"); - await toggleAll.check(); - await expect(toggleAll).toBeChecked(); - await checkNumberOfCompletedTodosInLocalStorage(page, 3); - - // Uncheck first todo. - const firstTodo = page.getByTestId("todo-item").nth(0); - await firstTodo.getByRole("checkbox").uncheck(); - - // Reuse toggleAll locator and make sure its not checked. - await expect(toggleAll).not.toBeChecked(); - - await firstTodo.getByRole("checkbox").check(); - await checkNumberOfCompletedTodosInLocalStorage(page, 3); - - // Assert the toggle all is checked again. - await expect(toggleAll).toBeChecked(); - }); -}); - -test.describe("Item", () => { - test("should allow me to mark items as complete", async ({ page }) => { - // create a new todo locator - const newTodo = page.getByPlaceholder("What needs to be done?"); - - // Create two items. - for (const item of TODO_ITEMS.slice(0, 2)) { - await newTodo.fill(item); - await newTodo.press("Enter"); - } - - // Check first item. - const firstTodo = page.getByTestId("todo-item").nth(0); - await firstTodo.getByRole("checkbox").check(); - await expect(firstTodo).toHaveClass("completed"); - - // Check second item. - const secondTodo = page.getByTestId("todo-item").nth(1); - await expect(secondTodo).not.toHaveClass("completed"); - await secondTodo.getByRole("checkbox").check(); - - // Assert completed class. - await expect(firstTodo).toHaveClass("completed"); - await expect(secondTodo).toHaveClass("completed"); - }); - - test("should allow me to un-mark items as complete", async ({ page }) => { - // create a new todo locator - const newTodo = page.getByPlaceholder("What needs to be done?"); - - // Create two items. - for (const item of TODO_ITEMS.slice(0, 2)) { - await newTodo.fill(item); - await newTodo.press("Enter"); - } - - const firstTodo = page.getByTestId("todo-item").nth(0); - const secondTodo = page.getByTestId("todo-item").nth(1); - const firstTodoCheckbox = firstTodo.getByRole("checkbox"); - - await firstTodoCheckbox.check(); - await expect(firstTodo).toHaveClass("completed"); - await expect(secondTodo).not.toHaveClass("completed"); - await checkNumberOfCompletedTodosInLocalStorage(page, 1); - - await firstTodoCheckbox.uncheck(); - await expect(firstTodo).not.toHaveClass("completed"); - await expect(secondTodo).not.toHaveClass("completed"); - await checkNumberOfCompletedTodosInLocalStorage(page, 0); - }); - - test("should allow me to edit an item", async ({ page }) => { - await createDefaultTodos(page); - - const todoItems = page.getByTestId("todo-item"); - const secondTodo = todoItems.nth(1); - await secondTodo.dblclick(); - await expect(secondTodo.getByRole("textbox", { name: "Edit" })).toHaveValue( - TODO_ITEMS[1] - ); - await secondTodo - .getByRole("textbox", { name: "Edit" }) - .fill("buy some sausages"); - await secondTodo.getByRole("textbox", { name: "Edit" }).press("Enter"); - - // Explicitly assert the new text value. - await expect(todoItems).toHaveText([ - TODO_ITEMS[0], - "buy some sausages", - TODO_ITEMS[2], - ]); - await checkTodosInLocalStorage(page, "buy some sausages"); - }); -}); - -test.describe("Editing", () => { - test.beforeEach(async ({ page }) => { - await createDefaultTodos(page); - await checkNumberOfTodosInLocalStorage(page, 3); - }); - - test("should hide other controls when editing", async ({ page }) => { - const todoItem = page.getByTestId("todo-item").nth(1); - await todoItem.dblclick(); - await expect(todoItem.getByRole("checkbox")).not.toBeVisible(); - await expect( - todoItem.locator("label", { - hasText: TODO_ITEMS[1], - }) - ).not.toBeVisible(); - await checkNumberOfTodosInLocalStorage(page, 3); - }); - - test("should save edits on blur", async ({ page }) => { - const todoItems = page.getByTestId("todo-item"); - await todoItems.nth(1).dblclick(); - await todoItems - .nth(1) - .getByRole("textbox", { name: "Edit" }) - .fill("buy some sausages"); - await todoItems - .nth(1) - .getByRole("textbox", { name: "Edit" }) - .dispatchEvent("blur"); - - await expect(todoItems).toHaveText([ - TODO_ITEMS[0], - "buy some sausages", - TODO_ITEMS[2], - ]); - await checkTodosInLocalStorage(page, "buy some sausages"); - }); - - test("should trim entered text", async ({ page }) => { - const todoItems = page.getByTestId("todo-item"); - await todoItems.nth(1).dblclick(); - await todoItems - .nth(1) - .getByRole("textbox", { name: "Edit" }) - .fill(" buy some sausages "); - await todoItems - .nth(1) - .getByRole("textbox", { name: "Edit" }) - .press("Enter"); - - await expect(todoItems).toHaveText([ - TODO_ITEMS[0], - "buy some sausages", - TODO_ITEMS[2], - ]); - await checkTodosInLocalStorage(page, "buy some sausages"); - }); - - test("should remove the item if an empty text string was entered", async ({ - page, - }) => { - const todoItems = page.getByTestId("todo-item"); - await todoItems.nth(1).dblclick(); - await todoItems.nth(1).getByRole("textbox", { name: "Edit" }).fill(""); - await todoItems - .nth(1) - .getByRole("textbox", { name: "Edit" }) - .press("Enter"); - - await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[2]]); - }); - - test("should cancel edits on escape", async ({ page }) => { - const todoItems = page.getByTestId("todo-item"); - await todoItems.nth(1).dblclick(); - await todoItems - .nth(1) - .getByRole("textbox", { name: "Edit" }) - .fill("buy some sausages"); - await todoItems - .nth(1) - .getByRole("textbox", { name: "Edit" }) - .press("Escape"); - await expect(todoItems).toHaveText(TODO_ITEMS); - }); -}); - -test.describe("Counter", () => { - test("should display the current number of todo items", async ({ page }) => { - // create a new todo locator - const newTodo = page.getByPlaceholder("What needs to be done?"); - - // create a todo count locator - const todoCount = page.getByTestId("todo-count"); - - await newTodo.fill(TODO_ITEMS[0]); - await newTodo.press("Enter"); - - await expect(todoCount).toContainText("1"); - - await newTodo.fill(TODO_ITEMS[1]); - await newTodo.press("Enter"); - await expect(todoCount).toContainText("2"); - - await checkNumberOfTodosInLocalStorage(page, 2); - }); -}); - -test.describe("Clear completed button", () => { - test.beforeEach(async ({ page }) => { - await createDefaultTodos(page); - }); - - test("should display the correct text", async ({ page }) => { - await page.locator(".todo-list li .toggle").first().check(); - await expect( - page.getByRole("button", { name: "Clear completed" }) - ).toBeVisible(); - }); - - test("should remove completed items when clicked", async ({ page }) => { - const todoItems = page.getByTestId("todo-item"); - await todoItems.nth(1).getByRole("checkbox").check(); - await page.getByRole("button", { name: "Clear completed" }).click(); - await expect(todoItems).toHaveCount(2); - await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[2]]); - }); - - test("should be hidden when there are no items that are completed", async ({ - page, - }) => { - await page.locator(".todo-list li .toggle").first().check(); - await page.getByRole("button", { name: "Clear completed" }).click(); - await expect( - page.getByRole("button", { name: "Clear completed" }) - ).toBeHidden(); - }); -}); - -test.describe("Persistence", () => { - test("should persist its data", async ({ page }) => { - // create a new todo locator - const newTodo = page.getByPlaceholder("What needs to be done?"); - - for (const item of TODO_ITEMS.slice(0, 2)) { - await newTodo.fill(item); - await newTodo.press("Enter"); - } - - const todoItems = page.getByTestId("todo-item"); - const firstTodoCheck = todoItems.nth(0).getByRole("checkbox"); - await firstTodoCheck.check(); - await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[1]]); - await expect(firstTodoCheck).toBeChecked(); - await expect(todoItems).toHaveClass(["completed", ""]); - - // Ensure there is 1 completed item. - await checkNumberOfCompletedTodosInLocalStorage(page, 1); - - // Now reload. - await page.reload(); - await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[1]]); - await expect(firstTodoCheck).toBeChecked(); - await expect(todoItems).toHaveClass(["completed", ""]); - }); -}); - -test.describe("Routing", () => { - test.beforeEach(async ({ page }) => { - await createDefaultTodos(page); - // make sure the app had a chance to save updated todos in storage - // before navigating to a new view, otherwise the items can get lost :( - // in some frameworks like Durandal - await checkTodosInLocalStorage(page, TODO_ITEMS[0]); - }); - - test("should allow me to display active items", async ({ page }) => { - const todoItem = page.getByTestId("todo-item"); - await page.getByTestId("todo-item").nth(1).getByRole("checkbox").check(); - - await checkNumberOfCompletedTodosInLocalStorage(page, 1); - await page.getByRole("link", { name: "Active" }).click(); - await expect(todoItem).toHaveCount(2); - await expect(todoItem).toHaveText([TODO_ITEMS[0], TODO_ITEMS[2]]); - }); - - test("should respect the back button", async ({ page }) => { - const todoItem = page.getByTestId("todo-item"); - await page.getByTestId("todo-item").nth(1).getByRole("checkbox").check(); - - await checkNumberOfCompletedTodosInLocalStorage(page, 1); - - await test.step("Showing all items", async () => { - await page.getByRole("link", { name: "All" }).click(); - await expect(todoItem).toHaveCount(3); - }); - - await test.step("Showing active items", async () => { - await page.getByRole("link", { name: "Active" }).click(); - }); - - await test.step("Showing completed items", async () => { - await page.getByRole("link", { name: "Completed" }).click(); - }); - - await expect(todoItem).toHaveCount(1); - await page.goBack(); - await expect(todoItem).toHaveCount(2); - await page.goBack(); - await expect(todoItem).toHaveCount(3); - }); - - test("should allow me to display completed items", async ({ page }) => { - await page.getByTestId("todo-item").nth(1).getByRole("checkbox").check(); - await checkNumberOfCompletedTodosInLocalStorage(page, 1); - await page.getByRole("link", { name: "Completed" }).click(); - await expect(page.getByTestId("todo-item")).toHaveCount(1); - }); - - test("should allow me to display all items", async ({ page }) => { - await page.getByTestId("todo-item").nth(1).getByRole("checkbox").check(); - await checkNumberOfCompletedTodosInLocalStorage(page, 1); - await page.getByRole("link", { name: "Active" }).click(); - await page.getByRole("link", { name: "Completed" }).click(); - await page.getByRole("link", { name: "All" }).click(); - await expect(page.getByTestId("todo-item")).toHaveCount(3); - }); - - test("should highlight the currently applied filter", async ({ page }) => { - await expect(page.getByRole("link", { name: "All" })).toHaveClass( - "selected" - ); - - //create locators for active and completed links - const activeLink = page.getByRole("link", { name: "Active" }); - const completedLink = page.getByRole("link", { name: "Completed" }); - await activeLink.click(); - - // Page change - active items. - await expect(activeLink).toHaveClass("selected"); - await completedLink.click(); - - // Page change - completed items. - await expect(completedLink).toHaveClass("selected"); - }); -}); - -async function createDefaultTodos(page: Page) { - // create a new todo locator - const newTodo = page.getByPlaceholder("What needs to be done?"); - - for (const item of TODO_ITEMS) { - await newTodo.fill(item); - await newTodo.press("Enter"); - } -} - -async function checkNumberOfTodosInLocalStorage(page: Page, expected: number) { - return await page.waitForFunction((e) => { - return JSON.parse(localStorage["react-todos"]).length === e; - }, expected); -} - -async function checkNumberOfCompletedTodosInLocalStorage( - page: Page, - expected: number -) { - return await page.waitForFunction((e) => { - return ( - JSON.parse(localStorage["react-todos"]).filter( - (todo: any) => todo.completed - ).length === e - ); - }, expected); -} - -async function checkTodosInLocalStorage(page: Page, title: string) { - return await page.waitForFunction((t) => { - return JSON.parse(localStorage["react-todos"]) - .map((todo: any) => todo.title) - .includes(t); - }, title); -} diff --git a/frontend/tests/auth.spec.ts b/frontend/tests/auth.spec.ts deleted file mode 100644 index 4273bcee..00000000 --- a/frontend/tests/auth.spec.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { test, expect } from "./fixtures/auth"; - -test("redirect to login", async ({ page }) => { - await page.goto("/"); - await expect(page).toHaveURL(/\/login/); - - await page.goto("/files/"); - await expect(page).toHaveURL(/\/login\?redirect=\/files\//); -}); - -test("login and logout", async ({ authPage, page, context }) => { - await authPage.goto(); - await expect(page).toHaveTitle(/Login - File Browser$/); - - await authPage.loginAs("fake", "fake"); - await expect(authPage.wrongCredentials).toBeVisible(); - - await authPage.loginAs(); - await expect(authPage.wrongCredentials).toBeHidden(); - // await page.waitForURL("**/files/", { timeout: 5000 }); - await expect(page).toHaveTitle(/.*Files - File Browser$/); - - let cookies = await context.cookies(); - expect(cookies.find((c) => c.name == "auth")?.value).toBeDefined(); - - await authPage.logout(); - // await page.waitForURL("**/login", { timeout: 5000 }); - await expect(page).toHaveTitle(/Login - File Browser$/); - - cookies = await context.cookies(); - expect(cookies.find((c) => c.name == "auth")?.value).toBeUndefined(); -}); diff --git a/frontend/tests/fixtures/auth.ts b/frontend/tests/fixtures/auth.ts deleted file mode 100644 index ad1b015e..00000000 --- a/frontend/tests/fixtures/auth.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { - type Page, - type Locator, - test as base, - expect, -} from "@playwright/test"; - -export class AuthPage { - public readonly wrongCredentials: Locator; - - constructor(public readonly page: Page) { - this.wrongCredentials = this.page.locator("div.wrong"); - } - - async goto() { - await this.page.goto("/login"); - } - - async loginAs(username = "admin", password = "admin") { - await this.page.getByPlaceholder("Username").fill(username); - await this.page.getByPlaceholder("Password").fill(password); - await this.page.getByRole("button", { name: "Login" }).click(); - } - - async logout() { - await this.page.getByRole("button", { name: "Logout" }).click(); - } -} - -const test = base.extend<{ authPage: AuthPage }>({ - authPage: async ({ page }, use) => { - const authPage = new AuthPage(page); - await authPage.goto(); - await authPage.loginAs(); - await use(authPage); - // await authPage.logout(); - }, -}); - -export { test, expect }; diff --git a/frontend/tests/fixtures/settings.ts b/frontend/tests/fixtures/settings.ts deleted file mode 100644 index aa0027c9..00000000 --- a/frontend/tests/fixtures/settings.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { - type Locator, - type Page, - test as base, - expect, -} from "@playwright/test"; -import { AuthPage } from "./auth"; - -type SettingsType = "profile" | "shares" | "global" | "users"; - -export class SettingsPage { - public readonly hideDotfiles: Locator; // checkbox - public readonly singleClick: Locator; // checkbox - public readonly dateFormat: Locator; // checkbox - private readonly languages: Locator; // selection - private readonly submitProfile: Locator; // submit - private readonly submitPassword: Locator; // submit - - constructor(public readonly page: Page) { - this.hideDotfiles = this.page.locator('input[name="hideDotfiles"]'); - this.singleClick = this.page.locator('input[name="singleClick"]'); - this.dateFormat = this.page.locator('input[name="dateFormat"]'); - this.languages = this.page.locator('select[name="selectLanguage"]'); - this.submitProfile = this.page.locator('input[name="submitProfile"]'); - this.submitPassword = this.page.locator('input[name="submitPassword"]'); - } - - async goto(type: SettingsType = "profile") { - await this.page.goto(`/settings/${type}`); - } - - async setLanguage(locale: string = "en") { - await this.languages.selectOption(locale); - } - - async saveProfile() { - await this.submitProfile.click(); - } - - async savePassword() { - await this.submitPassword.click(); - } -} - -const test = base.extend<{ settingsPage: SettingsPage }>({ - page: async ({ page }, use) => { - // Sign in with our account. - const authPage = new AuthPage(page); - await authPage.goto(); - await authPage.loginAs(); - await expect(page).toHaveTitle(/.*Files - File Browser$/); - // Use signed-in page in the test. - await use(page); - }, - settingsPage: async ({ page }, use) => { - const settingsPage = new SettingsPage(page); - await use(settingsPage); - }, -}); - -export { test, expect }; diff --git a/frontend/tests/fixtures/toast.ts b/frontend/tests/fixtures/toast.ts deleted file mode 100644 index 4b5ebbf5..00000000 --- a/frontend/tests/fixtures/toast.ts +++ /dev/null @@ -1,20 +0,0 @@ -//classes: Vue-Toastification__toast Vue-Toastification__toast--success bottom-center -import { type Page, type Locator, expect } from "@playwright/test"; - -export class Toast { - private readonly success: Locator; - private readonly error: Locator; - - constructor(public readonly page: Page) { - this.success = this.page.locator("div.Vue-Toastification__toast--success"); - this.error = this.page.locator("div.Vue-Toastification__toast--error"); - } - - async isSuccess() { - await expect(this.success).toBeVisible(); - } - - async isError() { - await expect(this.error).toBeVisible(); - } -} diff --git a/frontend/tests/settings.spec.ts b/frontend/tests/settings.spec.ts deleted file mode 100644 index c8726e42..00000000 --- a/frontend/tests/settings.spec.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { test, expect } from "./fixtures/settings"; -import { Toast } from "./fixtures/toast"; - -// test.describe("profile settings", () => { -test("settings button", async ({ page }) => { - const button = page.getByLabel("Settings", { exact: true }); - await expect(button).toBeVisible(); - await button.click(); - await expect(page).toHaveTitle(/^Profile Settings/); - await expect( - page.getByRole("heading", { name: "Profile Settings" }) - ).toBeVisible(); -}); - -test("set locale", async ({ settingsPage, page }) => { - const toast = new Toast(page); - - await settingsPage.goto("profile"); - await expect(page).toHaveTitle(/^Profile Settings/); - // await settingsPage.saveProfile(); - // await toast.isSuccess(); - // await expect( - // page.getByText("Settings updated!", { exact: true }) - // ).toBeVisible(); - - await settingsPage.setLanguage("hu"); - await settingsPage.saveProfile(); - await toast.isSuccess(); - await expect( - page.getByText("Beállítások frissítve!", { exact: true }) - ).toBeVisible(); - await expect( - page.getByRole("heading", { name: "Profilbeállítások" }) - ).toBeVisible(); - - await settingsPage.setLanguage("en"); - await settingsPage.saveProfile(); - await toast.isSuccess(); - await expect( - page.getByText("Settings updated!", { exact: true }) - ).toBeVisible(); - await expect( - page.getByRole("heading", { name: "Profile Settings" }) - ).toBeVisible(); -}); -// }); diff --git a/frontend/tsconfig.node.json b/frontend/tsconfig.node.json index d5aadf04..29e91674 100644 --- a/frontend/tsconfig.node.json +++ b/frontend/tsconfig.node.json @@ -4,8 +4,7 @@ "vite.config.*", "vitest.config.*", "cypress.config.*", - "nightwatch.conf.*", - "playwright.config.*" + "nightwatch.conf.*" ], "compilerOptions": { "composite": true,