pelagia-portal/App/tests/e2e/admin-bordered-buttons.spec.ts
2026-05-18 23:18:58 +05:30

128 lines
4.6 KiB
TypeScript

/**
* User stories covered: Feature 10 — Admin bordered buttons
* - On /admin/vendors, Edit and Delete buttons have visible borders (not plain text links)
* - Same checks apply to /admin/users, /admin/vessels, /admin/accounts, /admin/products
*
* The fix replaced text-link style buttons with bordered buttons. We check that action
* buttons in admin tables do NOT have link-only styling (no underline-only appearance)
* and DO have a border or background CSS class.
*
* Selector strategy: Admin action buttons are rendered by EditVendorButton, ConfirmDeleteButton.
* We look for <button> or <a> elements in the last table column that have class attributes
* containing "border" — this is the key indicator of the style fix.
*
* Created: 2026-05-17
*/
import { test, expect } from "@playwright/test";
import { login, USERS } from "./helpers/login";
/** Assert that action buttons in the last column of an admin table have border classes. */
async function assertBorderedButtons(
page: import("@playwright/test").Page,
url: string
): Promise<void> {
await page.goto(url);
await page.waitForLoadState("networkidle");
// Find all action cells in the last column of the table body
// The admin pages use a consistent table layout where the last <td> holds action buttons
const actionCells = page.locator("table tbody tr td:last-child");
const cellCount = await actionCells.count();
if (cellCount === 0) {
console.log(` No table rows found on ${url} — skipping button check`);
return;
}
// Get all buttons/links within the action cells
const actionButtons = actionCells.locator("button, a");
const btnCount = await actionButtons.count();
if (btnCount === 0) {
console.log(` No action buttons found on ${url}`);
return;
}
// Verify at least one button has border-related class (not a plain text link)
let foundBorderedButton = false;
for (let i = 0; i < Math.min(btnCount, 10); i++) {
const cls = (await actionButtons.nth(i).getAttribute("class")) ?? "";
if (
cls.includes("border") ||
cls.includes("bg-") ||
cls.includes("btn") ||
cls.includes("rounded")
) {
foundBorderedButton = true;
break;
}
}
expect(foundBorderedButton).toBeTruthy();
console.log(`✓ Bordered/styled action buttons found on ${url}`);
}
test.describe("Feature 10 — Admin bordered buttons", () => {
test("US-10a: /admin/vendors action buttons have border classes", async ({
page,
}) => {
await login(page, USERS.ADMIN);
await assertBorderedButtons(page, "/admin/vendors");
});
test("US-10a: /admin/users action buttons have border classes", async ({
page,
}) => {
await login(page, USERS.ADMIN);
await assertBorderedButtons(page, "/admin/users");
});
test("US-10a: /admin/vessels action buttons have border classes", async ({
page,
}) => {
await login(page, USERS.ADMIN);
await assertBorderedButtons(page, "/admin/vessels");
});
test("US-10a: /admin/accounts action buttons have border classes", async ({
page,
}) => {
await login(page, USERS.ADMIN);
await assertBorderedButtons(page, "/admin/accounts");
});
test("US-10a: /admin/products action buttons have border classes", async ({
page,
}) => {
await login(page, USERS.ADMIN);
await assertBorderedButtons(page, "/admin/products");
});
test("US-10a: /admin/vendors Edit button is visually distinct from plain text", async ({
page,
}) => {
await login(page, USERS.ADMIN);
await page.goto("/admin/vendors");
await page.waitForLoadState("networkidle");
// The EditVendorButton renders as a <button> with some visual styling
// After the fix it should have border or background — not just text color
const editBtns = page.locator("table tbody tr td:last-child button").first();
if (await editBtns.isVisible()) {
const cls = (await editBtns.getAttribute("class")) ?? "";
// Must NOT be an unstyled anchor-look-alike; must have border or bg
const hasVisualStyle =
cls.includes("border") || cls.includes("bg-") || cls.includes("rounded");
expect(hasVisualStyle).toBeTruthy();
console.log(`✓ Edit button class: ${cls.slice(0, 80)}...`);
} else {
// Vendors table might use <span> wrapping both buttons
const spanBtn = page.locator("table tbody tr td:last-child span button").first();
const spanCls = (await spanBtn.getAttribute("class")) ?? "";
expect(
spanCls.includes("border") || spanCls.includes("bg-") || spanCls.includes("rounded")
).toBeTruthy();
console.log(`✓ Vendor edit button has visual styling`);
}
});
});