fix e2e tests

This commit is contained in:
Erza Bytyci
2026-05-15 11:17:22 +00:00
parent 12ab149903
commit 707edeca18
17 changed files with 90 additions and 58 deletions
+2 -2
View File
@@ -13,7 +13,7 @@ module.exports = defineConfig({
reporter: "html",
use: {
baseURL: "http://localhost:3000/gradesa",
baseURL: "http://localhost:3000/gradesa/",
trace: "on-first-retry",
screenshot: "only-on-failure",
},
@@ -35,7 +35,7 @@ module.exports = defineConfig({
webServer: {
command: "npm run dev",
url: "http://localhost:3000/gradesa",
url: "http://localhost:3000/gradesa/",
reuseExistingServer: !process.env.CI,
stdout: "pipe",
stderr: "pipe",
+4 -4
View File
@@ -3,7 +3,7 @@ const { elementExists } = require("./utils/helpers");
test.describe("Advanced Interactions", () => {
test("should display grammar content", async ({ page }) => {
await page.goto("/grammar/themes", { waitUntil: "domcontentloaded" });
await page.goto("grammar/themes", { waitUntil: "domcontentloaded" });
await expect(page.locator("main")).toBeVisible();
const headings = await page.locator("h1, h2, h3").all();
@@ -21,10 +21,10 @@ test.describe("Advanced Interactions", () => {
);
test.setTimeout(60000);
await page.goto("/pages/resources/1", { waitUntil: "domcontentloaded" });
await page.goto("pages/resources/1", { waitUntil: "domcontentloaded" });
const chapter1Url = page.url();
await page.goto("/pages/resources/2", { waitUntil: "domcontentloaded" });
await page.goto("pages/resources/2", { waitUntil: "domcontentloaded" });
expect(page.url()).not.toEqual(chapter1Url);
});
@@ -32,7 +32,7 @@ test.describe("Advanced Interactions", () => {
test("should have interactive UI elements", async ({ page }) => {
test.setTimeout(60000);
await page.goto("/pages/resources", {
await page.goto("pages/resources", {
waitUntil: "domcontentloaded",
timeout: 60000,
});
+2 -2
View File
@@ -2,14 +2,14 @@ const { test, expect } = require("@playwright/test");
test.describe("Authentication", () => {
test("should navigate to login page", async ({ page }) => {
await page.goto("/auth/login");
await page.goto("auth/login");
await expect(page).toHaveURL(/.*auth\/login/);
await page.screenshot({ path: "tests/e2e/screenshots/login-page.png" });
await expect(page.locator("form")).toBeVisible();
});
test("should navigate to register page", async ({ page }) => {
await page.goto("/auth/register");
await page.goto("auth/register");
await expect(page).toHaveURL(/.*auth\/register/);
await page.screenshot({ path: "tests/e2e/screenshots/register-page.png" });
await expect(page.locator("form")).toBeVisible();
@@ -1,7 +1,7 @@
const { test, expect } = require("@playwright/test");
async function gotoClickExerciseList(page) {
await page.goto("/grammar/exercises/click", {
await page.goto("grammar/exercises/click", {
waitUntil: "domcontentloaded",
timeout: 60000,
});
@@ -22,7 +22,6 @@ test.describe("Klick-Übungen", () => {
const currentUrl = page.url();
if (isOnLogin(currentUrl)) {
await expect(page).toHaveURL(/\/auth\/login\?redirect=/);
await expect(page.locator("form")).toBeVisible();
return;
}
+2 -2
View File
@@ -3,7 +3,7 @@ const { test, expect } = require("@playwright/test");
test.describe("Component Interactions", () => {
test("should display chapter navigation", async ({ page }) => {
test.setTimeout(60000);
await page.goto("/pages/resources", {
await page.goto("pages/resources", {
waitUntil: "domcontentloaded",
timeout: 60000,
});
@@ -14,7 +14,7 @@ test.describe("Component Interactions", () => {
test("should load resource content", async ({ page }) => {
test.setTimeout(60000);
await page.goto("/pages/resources/1", {
await page.goto("pages/resources/1", {
waitUntil: "domcontentloaded",
timeout: 60000,
});
@@ -1,7 +1,7 @@
const { test, expect } = require("@playwright/test");
async function gotoDndMatchList(page) {
await page.goto("/grammar/exercises/dnd-match", {
await page.goto("grammar/exercises/dnd-match", {
waitUntil: "domcontentloaded",
timeout: 60000,
});
@@ -24,7 +24,6 @@ test.describe("Zuordnungs-Übungen", () => {
const currentUrl = page.url();
if (isOnLogin(currentUrl)) {
await expect(page).toHaveURL(/\/auth\/login\?redirect=/);
await expect(page.locator("form")).toBeVisible();
return;
}
@@ -1,7 +1,7 @@
const { test, expect } = require("@playwright/test");
async function gotoDragdropExerciseList(page) {
await page.goto("/grammar/exercises/dragdrop", {
await page.goto("grammar/exercises/dragdrop", {
waitUntil: "domcontentloaded",
timeout: 60000,
});
@@ -22,7 +22,6 @@ test.describe("Sortieren/Gruppieren-Übungen", () => {
const currentUrl = page.url();
if (isOnLogin(currentUrl)) {
await expect(page).toHaveURL(/\/auth\/login\?redirect=/);
await expect(page.locator("form")).toBeVisible();
return;
}
+1 -4
View File
@@ -1,7 +1,7 @@
const { test, expect } = require("@playwright/test");
async function gotoFillInTheGapList(page) {
await page.goto("/grammar/exercises/fillinthegap", {
await page.goto("grammar/exercises/fillinthegap", {
waitUntil: "domcontentloaded",
timeout: 60000,
});
@@ -20,7 +20,6 @@ test.describe("Lückentext-Übungen", () => {
const currentUrl = page.url();
if (isOnLogin(currentUrl)) {
await expect(page).toHaveURL(/\/auth\/login\?redirect=/);
await expect(page.locator("form")).toBeVisible();
return;
}
@@ -36,7 +35,6 @@ test.describe("Lückentext-Übungen", () => {
const currentUrl = page.url();
if (isOnLogin(currentUrl)) {
await expect(page).toHaveURL(/\/auth\/login\?redirect=/);
await expect(page.locator("form")).toBeVisible();
return;
}
@@ -53,7 +51,6 @@ test.describe("Lückentext-Übungen", () => {
const currentUrl = page.url();
if (isOnLogin(currentUrl)) {
await expect(page).toHaveURL(/\/auth\/login\?redirect=/);
await expect(page.locator("form")).toBeVisible();
return;
}
+7 -2
View File
@@ -2,7 +2,12 @@ const { test, expect } = require("@playwright/test");
test.describe("Form Interactions", () => {
test("should navigate to register page", async ({ page }) => {
await page.goto("/auth/register");
test.setTimeout(60000);
await page.goto("auth/register", {
waitUntil: "domcontentloaded",
timeout: 60000,
});
await expect(page).toHaveURL(/.*register/);
await page.screenshot({ path: "tests/e2e/screenshots/register-page.png" });
await expect(page.locator("form")).toBeVisible();
@@ -11,7 +16,7 @@ test.describe("Form Interactions", () => {
test.skip("form submission - to be implemented after analyzing actual form structure", async ({
page,
}) => {
await page.goto("/auth/register");
await page.goto("auth/register");
await expect(page).toHaveURL(/.*register/);
});
});
+39 -17
View File
@@ -19,7 +19,7 @@ async function gotoWithRetry(page, url, options, retries = 1) {
}
async function getFirstAlphabeticalGrammarHref(page) {
await gotoWithRetry(page, "/grammar/alphabetical", {
await gotoWithRetry(page, "grammar/alphabetical", {
waitUntil: "domcontentloaded",
timeout: 60000,
});
@@ -38,15 +38,21 @@ async function getFirstAlphabeticalGrammarHref(page) {
test.describe("Grammar Pages", () => {
test("should load the grammar overview page", async ({ page }) => {
await page.goto("/grammar");
await expect(page).toHaveURL(/.*\/grammar$/);
test.setTimeout(60000);
await gotoWithRetry(page, "grammar", {
waitUntil: "domcontentloaded",
timeout: 60000,
});
await expect(page).toHaveURL(/\/grammar\/?$/);
await expect(page.getByRole("main").first()).toBeVisible();
});
test("should render topics-view grammar page directly", async ({ page }) => {
test.setTimeout(60000);
await page.goto("/grammar/themes/adjektivdeklination?view=topics", {
await page.goto("grammar/themes/adjektivdeklination?view=topics", {
waitUntil: "domcontentloaded",
timeout: 60000,
});
@@ -77,7 +83,7 @@ test.describe("Grammar Pages", () => {
}) => {
test.setTimeout(60000);
await page.goto("/grammar/themes/e2e-placeholder-page?view=topics", {
await page.goto("grammar/themes/e2e-placeholder-page?view=topics", {
waitUntil: "domcontentloaded",
timeout: 60000,
});
@@ -90,11 +96,26 @@ test.describe("Grammar Pages", () => {
test("should keep topics view when using next navigation", async ({
page,
}) => {
await page.goto("/grammar/themes/adjektivdeklination?view=topics");
test.setTimeout(60000);
await gotoWithRetry(
page,
"grammar/themes/adjektivdeklination?view=topics",
{
waitUntil: "domcontentloaded",
timeout: 60000,
}
);
const weiterButton = page.getByRole("link", { name: "Weiter" });
await expect(weiterButton).toBeVisible();
await weiterButton.click();
const nextHref = await weiterButton.getAttribute("href");
expect(nextHref).toBeTruthy();
await gotoWithRetry(page, nextHref, {
waitUntil: "domcontentloaded",
timeout: 60000,
});
await expect(page).toHaveURL(/view=topics/);
});
@@ -113,20 +134,21 @@ test.describe("Grammar Pages", () => {
const weiterButton = page.getByRole("link", { name: "Weiter" });
if (await weiterButton.isVisible()) {
await expect(weiterButton).toHaveAttribute("href", /view=alphabetical/);
await Promise.all([
page.waitForURL(/view=alphabetical/, {
timeout: 60000,
}),
weiterButton.click(),
]);
const nextHref = await weiterButton.getAttribute("href");
expect(nextHref).toBeTruthy();
await gotoWithRetry(page, nextHref, {
waitUntil: "domcontentloaded",
timeout: 60000,
});
await expect(page).toHaveURL(/view=alphabetical/);
}
});
test("should not show Ohne Thema in topics overview", async ({ page }) => {
await page.goto("/grammar/themes");
await page.goto("grammar/themes");
await expect(
page.getByRole("heading", { name: /Ohne Thema/i })
).toHaveCount(0);
await expect(page.locator("main")).not.toContainText(/Ohne Thema/i);
});
});
+1 -1
View File
@@ -2,7 +2,7 @@ const { test, expect } = require("@playwright/test");
test.describe("Home page", () => {
test("should display the home page correctly", async ({ page }) => {
await page.goto("/");
await page.goto("");
await expect(page).toHaveTitle(/Gradesa/i);
await expect(page.locator("main")).toBeVisible();
});
+4 -4
View File
@@ -2,13 +2,13 @@ const { test, expect } = require("@playwright/test");
test.describe("Learning Page", () => {
test("should load the learning page", async ({ page }) => {
await page.goto("/learning");
await page.goto("learning");
await expect(page).toHaveURL(/.*learning/);
await expect(page.getByRole("main").first()).toBeVisible();
});
test("should show language toggle options", async ({ page }) => {
await page.goto("/learning", { waitUntil: "domcontentloaded" });
await page.goto("learning", { waitUntil: "domcontentloaded" });
await expect(
page.getByRole("group", { name: "Choose language" })
@@ -18,7 +18,7 @@ test.describe("Learning Page", () => {
});
test("should switch language selection", async ({ page }) => {
await page.goto("/learning");
await page.goto("learning");
const englishButton = page.getByRole("button", { name: "English" });
const deutschButton = page.getByRole("button", { name: "Deutsch" });
@@ -43,7 +43,7 @@ test.describe("Learning Page", () => {
});
test("should show learning form when data is loaded", async ({ page }) => {
await page.goto("/learning", { waitUntil: "domcontentloaded" });
await page.goto("learning", { waitUntil: "domcontentloaded" });
const formContainer = page.locator(
'.LearningForm, [data-test="learning-form"]'
+3 -3
View File
@@ -4,7 +4,7 @@ test.describe("Navigation", () => {
test("should navigate to grammar communication page", async ({ page }) => {
test.setTimeout(60000);
await page.goto("/grammar/communications", {
await page.goto("grammar/communications", {
waitUntil: "domcontentloaded",
timeout: 60000,
});
@@ -15,7 +15,7 @@ test.describe("Navigation", () => {
test("should navigate to learning resources page", async ({ page }) => {
test.setTimeout(60000);
await page.goto("/pages/resources", {
await page.goto("pages/resources", {
waitUntil: "domcontentloaded",
timeout: 60000,
});
@@ -26,7 +26,7 @@ test.describe("Navigation", () => {
test("should navigate to a specific chapter", async ({ page }) => {
test.setTimeout(60000);
await page.goto("/pages/resources/1", {
await page.goto("pages/resources/1", {
waitUntil: "domcontentloaded",
timeout: 60000,
});
+9 -2
View File
@@ -3,7 +3,9 @@ const { elementExists } = require("./utils/helpers");
test.describe("Page Structure Analysis", () => {
test("analyze homepage structure", async ({ page }) => {
await page.goto("/");
test.setTimeout(60000);
await page.goto("", { waitUntil: "domcontentloaded", timeout: 60000 });
await page.screenshot({ path: "tests/e2e/screenshots/homepage.png" });
console.log("Page title:", await page.title());
@@ -32,7 +34,12 @@ test.describe("Page Structure Analysis", () => {
});
test("analyze learning page structure", async ({ page }) => {
await page.goto("/learning");
test.setTimeout(60000);
await page.goto("learning", {
waitUntil: "domcontentloaded",
timeout: 60000,
});
await page.screenshot({ path: "tests/e2e/screenshots/learning.png" });
console.log("Page title:", await page.title());
@@ -4,7 +4,7 @@ test.describe("Resources Detail Pages", () => {
test("should display chapter content", async ({ page }) => {
test.setTimeout(60000);
await page.goto("/pages/resources/1", { waitUntil: "domcontentloaded" });
await page.goto("pages/resources/1", { waitUntil: "domcontentloaded" });
await expect(page).toHaveURL(/.*pages\/resources\/1/);
await expect(page.getByRole("main").first()).toBeVisible();
@@ -15,7 +15,7 @@ test.describe("Resources Detail Pages", () => {
test("should navigate between chapters", async ({ page }) => {
test.setTimeout(90000);
await page.goto("/pages/resources/1", {
await page.goto("pages/resources/1", {
waitUntil: "domcontentloaded",
timeout: 60000,
});
@@ -23,7 +23,7 @@ test.describe("Resources Detail Pages", () => {
const nextLink = page.getByRole("link", { name: /^Weiter$/ }).last();
await expect(nextLink).toBeVisible();
await expect(nextLink).toHaveAttribute("href", "/pages/resources/2");
await expect(nextLink).toHaveAttribute("href", /\/pages\/resources\/2$/);
const href = await nextLink.getAttribute("href");
await expect(href).toBeTruthy();
@@ -39,7 +39,7 @@ test.describe("Resources Detail Pages", () => {
}) => {
test.setTimeout(60000);
await page.goto("/pages/resources/1", { waitUntil: "domcontentloaded" });
await page.goto("pages/resources/1", { waitUntil: "domcontentloaded" });
const resourcesLink = page.getByRole("link", {
name: "Effektiv online lernen",
@@ -61,7 +61,7 @@ test.describe("Resources Detail Pages", () => {
}) => {
test.setTimeout(60000);
await page.goto("/pages/resources/1", { waitUntil: "domcontentloaded" });
await page.goto("pages/resources/1", { waitUntil: "domcontentloaded" });
const paragraphs = page.locator("p");
await expect(paragraphs.first()).toBeVisible();
+3 -3
View File
@@ -2,19 +2,19 @@ const { test, expect } = require("@playwright/test");
test.describe("User Management", () => {
test("users page route responds", async ({ page }) => {
await page.goto("/admin/users");
await page.goto("admin/users");
await expect(page).toHaveURL(/\/(admin\/users|$)/);
});
test("users page contains a button when accessible", async ({ page }) => {
await page.goto("/admin/users");
await page.goto("admin/users");
const buttons = page.getByRole("button");
await expect(buttons.first()).toBeVisible();
});
test("users page or redirect renders successfully", async ({ page }) => {
await page.goto("/admin/users");
await page.goto("admin/users");
await expect(page.locator("body")).toBeVisible();
});
});
+5 -1
View File
@@ -30,12 +30,16 @@ const unauthRequired = ["/auth/login", "/auth/register"];
*/
export async function middleware(request) {
const { pathname } = request.nextUrl;
const basePath = (process.env.NEXT_PUBLIC_BASE_PATH || "/gradesa").replace(
/\/$/,
""
);
const sessionCookie = request.cookies.get(AUTH_COOKIE_NAME);
const hasCookie = !!sessionCookie && sessionCookie.value !== "";
// Redirect logged-out users trying to access protected paths
if (!hasCookie && authRequired.some((path) => pathname.startsWith(path))) {
const loginUrl = new URL("/auth/login", request.url);
const loginUrl = new URL(`${basePath}/auth/login`, request.url);
loginUrl.searchParams.set("redirect", pathname); // Add the original path as a query parameter
return NextResponse.redirect(loginUrl);
}