Phase 4.1: Update E2E permissions tests for exchange
Update permissions.spec.ts to test new exchange routes: - Regular user: /exchange, /trades, /api/exchange/price - Admin user: /admin/trades, /api/admin/trades/upcoming - Updated all redirects and navigation tests - Updated API permission boundary tests
This commit is contained in:
parent
d6002b0cfc
commit
ab908c172e
1 changed files with 51 additions and 55 deletions
|
|
@ -4,8 +4,8 @@ import { test, expect, Page } from "@playwright/test";
|
|||
* Permission-based E2E tests
|
||||
*
|
||||
* These tests verify that:
|
||||
* 1. Regular users can access booking and appointments pages
|
||||
* 2. Admin users can access admin pages (invites, availability, appointments)
|
||||
* 1. Regular users can access exchange and trades pages
|
||||
* 2. Admin users can access admin pages (trades, invites, availability)
|
||||
* 3. Users are properly redirected based on their permissions
|
||||
* 4. API calls respect permission boundaries
|
||||
*/
|
||||
|
|
@ -64,44 +64,44 @@ test.describe("Regular User Access", () => {
|
|||
await loginUser(page, REGULAR_USER.email, REGULAR_USER.password);
|
||||
});
|
||||
|
||||
test("redirected from home to booking page", async ({ page }) => {
|
||||
test("redirected from home to exchange page", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
|
||||
// Should be redirected to booking page
|
||||
await expect(page).toHaveURL("/booking");
|
||||
// Should be redirected to exchange page
|
||||
await expect(page).toHaveURL("/exchange");
|
||||
});
|
||||
|
||||
test("can access booking page", async ({ page }) => {
|
||||
await page.goto("/booking");
|
||||
test("can access exchange page", async ({ page }) => {
|
||||
await page.goto("/exchange");
|
||||
|
||||
// Should stay on booking page
|
||||
await expect(page).toHaveURL("/booking");
|
||||
// Should stay on exchange page
|
||||
await expect(page).toHaveURL("/exchange");
|
||||
|
||||
// Should see booking UI
|
||||
await expect(page.getByText("Book an Appointment")).toBeVisible();
|
||||
// Should see exchange UI
|
||||
await expect(page.getByText("Exchange Bitcoin")).toBeVisible();
|
||||
});
|
||||
|
||||
test("can access appointments page", async ({ page }) => {
|
||||
await page.goto("/appointments");
|
||||
test("can access trades page", async ({ page }) => {
|
||||
await page.goto("/trades");
|
||||
|
||||
// Should stay on appointments page
|
||||
await expect(page).toHaveURL("/appointments");
|
||||
// Should stay on trades page
|
||||
await expect(page).toHaveURL("/trades");
|
||||
|
||||
// Should see appointments UI
|
||||
await expect(page.getByText("My Appointments")).toBeVisible();
|
||||
// Should see trades UI
|
||||
await expect(page.getByText("My Trades")).toBeVisible();
|
||||
});
|
||||
|
||||
test("navigation shows booking and appointments", async ({ page }) => {
|
||||
await page.goto("/appointments");
|
||||
test("navigation shows exchange and trades", async ({ page }) => {
|
||||
await page.goto("/trades");
|
||||
|
||||
// From appointments page, we can see the nav links
|
||||
// "Appointments" is the current page (shown as span, not link)
|
||||
// "Book" should be a link - use first() since there may be other booking links on page
|
||||
await expect(page.locator('a[href="/booking"]').first()).toBeVisible();
|
||||
// From trades page, we can see the nav links
|
||||
// "My Trades" is the current page (shown as span, not link)
|
||||
// "Exchange" should be a link
|
||||
await expect(page.locator('a[href="/exchange"]').first()).toBeVisible();
|
||||
|
||||
// Should NOT see admin links
|
||||
const availabilityLinks = page.locator('a[href="/admin/availability"]');
|
||||
await expect(availabilityLinks).toHaveCount(0);
|
||||
const adminTradesLinks = page.locator('a[href="/admin/trades"]');
|
||||
await expect(adminTradesLinks).toHaveCount(0);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -111,21 +111,21 @@ test.describe("Admin User Access", () => {
|
|||
await loginUser(page, ADMIN_USER.email, ADMIN_USER.password);
|
||||
});
|
||||
|
||||
test("redirected from home to admin appointments", async ({ page }) => {
|
||||
test("redirected from home to admin trades", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
|
||||
// Should be redirected to admin appointments page
|
||||
await expect(page).toHaveURL("/admin/appointments");
|
||||
// Should be redirected to admin trades page
|
||||
await expect(page).toHaveURL("/admin/trades");
|
||||
});
|
||||
|
||||
test("can access admin appointments page", async ({ page }) => {
|
||||
await page.goto("/admin/appointments");
|
||||
test("can access admin trades page", async ({ page }) => {
|
||||
await page.goto("/admin/trades");
|
||||
|
||||
// Should stay on admin appointments page
|
||||
await expect(page).toHaveURL("/admin/appointments");
|
||||
// Should stay on admin trades page
|
||||
await expect(page).toHaveURL("/admin/trades");
|
||||
|
||||
// Should see appointments UI (use heading for specificity)
|
||||
await expect(page.getByRole("heading", { name: "All Appointments" })).toBeVisible();
|
||||
// Should see trades UI (use heading for specificity)
|
||||
await expect(page.getByRole("heading", { name: "Trades" })).toBeVisible();
|
||||
});
|
||||
|
||||
test("can access admin availability page", async ({ page }) => {
|
||||
|
|
@ -139,16 +139,16 @@ test.describe("Admin User Access", () => {
|
|||
});
|
||||
|
||||
test("navigation shows admin links", async ({ page }) => {
|
||||
await page.goto("/admin/appointments");
|
||||
await page.goto("/admin/trades");
|
||||
|
||||
// Should see admin nav items (use locator for nav links)
|
||||
await expect(page.locator('a[href="/admin/invites"]')).toBeVisible();
|
||||
await expect(page.locator('a[href="/admin/availability"]')).toBeVisible();
|
||||
await expect(page.locator('a[href="/admin/appointments"]')).toHaveCount(0); // Current page, shown as text not link
|
||||
await expect(page.locator('a[href="/admin/trades"]')).toHaveCount(0); // Current page, shown as text not link
|
||||
|
||||
// Should NOT see regular user links
|
||||
const bookLinks = page.locator('a[href="/booking"]');
|
||||
await expect(bookLinks).toHaveCount(0);
|
||||
const exchangeLinks = page.locator('a[href="/exchange"]');
|
||||
await expect(exchangeLinks).toHaveCount(0);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -162,19 +162,19 @@ test.describe("Unauthenticated Access", () => {
|
|||
await expect(page).toHaveURL("/login");
|
||||
});
|
||||
|
||||
test("booking page redirects to login", async ({ page }) => {
|
||||
await page.goto("/booking");
|
||||
test("exchange page redirects to login", async ({ page }) => {
|
||||
await page.goto("/exchange");
|
||||
await expect(page).toHaveURL("/login");
|
||||
});
|
||||
|
||||
test("admin page redirects to login", async ({ page }) => {
|
||||
await page.goto("/admin/appointments");
|
||||
await page.goto("/admin/trades");
|
||||
await expect(page).toHaveURL("/login");
|
||||
});
|
||||
});
|
||||
|
||||
test.describe("Permission Boundary via API", () => {
|
||||
test("regular user API call to admin appointments returns 403", async ({ page, request }) => {
|
||||
test("regular user API call to admin trades returns 403", async ({ page, request }) => {
|
||||
// Login as regular user
|
||||
await clearAuth(page);
|
||||
await loginUser(page, REGULAR_USER.email, REGULAR_USER.password);
|
||||
|
|
@ -184,8 +184,8 @@ test.describe("Permission Boundary via API", () => {
|
|||
const authCookie = cookies.find((c) => c.name === "auth_token");
|
||||
|
||||
if (authCookie) {
|
||||
// Try to call admin appointments API directly
|
||||
const response = await request.get(`${API_URL}/api/admin/appointments`, {
|
||||
// Try to call admin trades API directly
|
||||
const response = await request.get(`${API_URL}/api/admin/trades/upcoming`, {
|
||||
headers: {
|
||||
Cookie: `auth_token=${authCookie.value}`,
|
||||
},
|
||||
|
|
@ -195,7 +195,7 @@ test.describe("Permission Boundary via API", () => {
|
|||
}
|
||||
});
|
||||
|
||||
test("admin user API call to booking slots returns 403", async ({ page, request }) => {
|
||||
test("admin user API call to exchange price returns 403", async ({ page, request }) => {
|
||||
// Login as admin
|
||||
await clearAuth(page);
|
||||
await loginUser(page, ADMIN_USER.email, ADMIN_USER.password);
|
||||
|
|
@ -205,12 +205,8 @@ test.describe("Permission Boundary via API", () => {
|
|||
const authCookie = cookies.find((c) => c.name === "auth_token");
|
||||
|
||||
if (authCookie) {
|
||||
// Try to call booking slots API directly (requires regular user permission)
|
||||
const tomorrow = new Date();
|
||||
tomorrow.setDate(tomorrow.getDate() + 1);
|
||||
const dateStr = tomorrow.toISOString().split("T")[0];
|
||||
|
||||
const response = await request.get(`${API_URL}/api/booking/slots?date=${dateStr}`, {
|
||||
// Try to call exchange price API directly (requires regular user permission)
|
||||
const response = await request.get(`${API_URL}/api/exchange/price`, {
|
||||
headers: {
|
||||
Cookie: `auth_token=${authCookie.value}`,
|
||||
},
|
||||
|
|
@ -226,14 +222,14 @@ test.describe("Session and Logout", () => {
|
|||
// Login
|
||||
await clearAuth(page);
|
||||
await loginUser(page, REGULAR_USER.email, REGULAR_USER.password);
|
||||
await expect(page).toHaveURL("/booking");
|
||||
await expect(page).toHaveURL("/exchange");
|
||||
|
||||
// Logout
|
||||
await page.click("text=Sign out");
|
||||
await expect(page).toHaveURL("/login");
|
||||
|
||||
// Try to access booking
|
||||
await page.goto("/booking");
|
||||
// Try to access exchange
|
||||
await page.goto("/exchange");
|
||||
await expect(page).toHaveURL("/login");
|
||||
});
|
||||
|
||||
|
|
@ -249,7 +245,7 @@ test.describe("Session and Logout", () => {
|
|||
]);
|
||||
|
||||
// Try to access protected page
|
||||
await page.goto("/booking");
|
||||
await page.goto("/exchange");
|
||||
|
||||
// Should be redirected to login
|
||||
await expect(page).toHaveURL("/login");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue