diff --git a/test/e2e/specs/status-page.spec.js b/test/e2e/specs/status-page.spec.js index 26fa0c8b8..60de8ef1a 100644 --- a/test/e2e/specs/status-page.spec.js +++ b/test/e2e/specs/status-page.spec.js @@ -1,7 +1,11 @@ import { expect, test } from "@playwright/test"; -import { login, screenshot } from "../util-test"; +import { login, restoreSqliteSnapshot, screenshot } from "../util-test"; test.describe("Status Page", () => { + test.beforeEach(async ({ page }) => { + await restoreSqliteSnapshot(page); + }); + test("create and edit", async ({ page }, testInfo) => { test.setTimeout(60000); // Keep the timeout increase for stability @@ -44,42 +48,16 @@ test.describe("Status Page", () => { await page.getByTestId("tag-name-input").fill(tagName); await page.getByTestId("tag-value-input").fill(tagValue); await page.getByTestId("tag-color-select").click(); // Vue-Multiselect component - - // DEBUG: Check for any overlays that could block the dropdown - const lostConnBanner = page.locator(".lost-connection"); - console.log("DEBUG: lost-connection banner visible:", await lostConnBanner.isVisible().catch(() => false)); - await screenshot(testInfo, page); - await page.getByTestId("tag-color-select").getByRole("option", { name: "Orange" }).click(); - // DEBUG: Check if color was selected - const colorText = await page - .getByTestId("tag-color-select") - .textContent() - .catch(() => "N/A"); - console.log("DEBUG: tag-color-select text after picking Orange:", colorText); - await screenshot(testInfo, page); - - // DEBUG: Check button state before clicking - const addAnotherBtn = page.getByRole("button", { name: "Add Another Tag" }); - const isDisabled = await addAnotherBtn.getAttribute("disabled"); - console.log("DEBUG: 'Add Another Tag' button disabled attr:", isDisabled); - await screenshot(testInfo, page); - // Add another tag instead of submitting directly - await addAnotherBtn.click(); + await page.getByRole("button", { name: "Add Another Tag" }).click(); // Add second tag await page.getByTestId("tag-name-input").fill(tagName2); await page.getByTestId("tag-value-input").fill(tagValue2); await page.getByTestId("tag-color-select").click(); await page.getByTestId("tag-color-select").getByRole("option", { name: "Blue" }).click(); - const colorText2 = await page - .getByTestId("tag-color-select") - .textContent() - .catch(() => "N/A"); - console.log("DEBUG: tag-color-select text after picking Blue:", colorText2); - await screenshot(testInfo, page); // Submit both tags await page.getByTestId("add-tags-final-button").click(); @@ -147,20 +125,14 @@ test.describe("Status Page", () => { await expect(page.getByTestId("monitor-name")).toHaveAttribute("href", monitorCustomUrl); - // TODO: no idea how to fix, after removed sqlite snapshot/restore feature - /* await expect(page.getByTestId("update-countdown-text")).toContainText("00:"); + await expect(page.getByTestId("update-countdown-text")).toContainText("00:"); const updateCountdown = Number( (await page.getByTestId("update-countdown-text").textContent()).match(/(\d+):(\d+)/)[2] ); expect(updateCountdown).toBeGreaterThanOrEqual(refreshInterval - 10); // cant be certain when the timer will start, so ensure it's within expected range - expect(updateCountdown).toBeLessThanOrEqual(refreshInterval);*/ + expect(updateCountdown).toBeLessThanOrEqual(refreshInterval); - // The status page navigates to public view after save - await page.waitForURL("/status/example"); - // Wait for the status page theme to be applied to body - await page.waitForFunction((expectedTheme) => document.body.classList.contains(expectedTheme), theme, { - timeout: 10000, - }); + await expect(page.locator("body")).toHaveClass(theme); // Add Google Analytics ID to head and verify await page.waitForFunction( @@ -200,13 +172,6 @@ test.describe("Status Page", () => { await screenshot(testInfo, page); - await page.waitForFunction( - (scriptUrl) => { - return document.head.innerHTML.includes(scriptUrl); - }, - umamiAnalyticsScriptUrl, - { timeout: 5000 } - ); expect(await page.locator("head").innerHTML()).toContain(umamiAnalyticsScriptUrl); expect(await page.locator("head").innerHTML()).toContain(umamiAnalyticsWebsiteId); @@ -343,11 +308,8 @@ test.describe("Status Page", () => { await page.getByTestId("save-button").click(); await expect(page.getByTestId("edit-sidebar")).toHaveCount(0); - // Navigate to dashboard or anywhere to ensure any server-side cache is stale - await page.waitForTimeout(1000); - // Fetch RSS feed again - should use custom RSS title - const rssResponseCustom = await page.request.get("/status/security-test/rss?_t=" + Date.now()); + const rssResponseCustom = await page.request.get("/status/security-test/rss"); expect(rssResponseCustom.status()).toBe(200); const rssContentCustom = await rssResponseCustom.text(); diff --git a/test/e2e/util-test.js b/test/e2e/util-test.js index de607eb26..9adead395 100644 --- a/test/e2e/util-test.js +++ b/test/e2e/util-test.js @@ -1,6 +1,7 @@ const fs = require("fs"); const path = require("path"); const dbPath = "./../../data/playwright-test/kuma.db"; +const serverUrl = require("../../config/playwright.config.js").url; /** * @param {TestInfo} testInfo Test info @@ -37,3 +38,24 @@ export async function login(page) { export function getSqliteDatabaseExists() { return fs.existsSync(path.resolve(__dirname, dbPath)); } + +/** + * Makes a request to the server to take a snapshot of the SQLite database. + * @param {Page|null} page Page + * @returns {Promise} Promise of response from snapshot request. + */ +export async function takeSqliteSnapshot(page = null) { + if (page) { + return page.goto("./_e2e/take-sqlite-snapshot"); + } else { + return fetch(`${serverUrl}/_e2e/take-sqlite-snapshot`); + } +} + +/** + * Makes a request to the server to restore the snapshot of the SQLite database. + * @returns {Promise} Promise of response from restoration request. + */ +export async function restoreSqliteSnapshot() { + return fetch(`${serverUrl}/_e2e/restore-sqlite-snapshot`); +}