chore: remove portal from admin app — extracted to fiberops-portal (FIBEROPS-249)
- Delete app/(portal)/ route group (login, dashboard, invoices, tickets) - Delete lib/portal-api.ts and lib/portal-auth-store.ts - Remove Phase 9 portal tests (17–22) from business-flow E2E spec - Keep portalAccessEnabled in Client type and admin client profile view
This commit is contained in:
@@ -2,7 +2,7 @@ import { test, expect, Page } from '@playwright/test';
|
||||
|
||||
/**
|
||||
* FIBEROPS-248: Full business flow E2E
|
||||
* Simulates complete ISP business day — admin ops + subscriber portal
|
||||
* Simulates complete ISP business day — admin ops (tests 1–16)
|
||||
*
|
||||
* Seed data (pre-created via API):
|
||||
* Plan: Basic 25Mbps (₱999, POSTPAID)
|
||||
@@ -11,15 +11,14 @@ import { test, expect, Page } from '@playwright/test';
|
||||
* Invoice: INV-2026-000015
|
||||
* Ticket: "No internet connection"
|
||||
* Lead: Maria Reyes
|
||||
* Portal: ACC-000029 / Portal123!
|
||||
*
|
||||
* Note: Subscriber portal tests (17–22) live in the fiberops-portal repo.
|
||||
*/
|
||||
|
||||
const BASE = 'http://192.168.1.167:3002';
|
||||
const TENANT_SLUG = 'demo-isp';
|
||||
const ADMIN_EMAIL = 'admin@demo-isp.com';
|
||||
const ADMIN_PASSWORD = 'Admin123!';
|
||||
const PORTAL_ACCOUNT = 'ACC-000029';
|
||||
const PORTAL_PASSWORD = 'Portal123!';
|
||||
|
||||
async function adminLogin(page: Page) {
|
||||
await page.goto(`${BASE}/login`);
|
||||
@@ -281,108 +280,3 @@ test('16. Audit Log — page renders', async ({ page }) => {
|
||||
await expect(page.locator('body')).toBeVisible();
|
||||
});
|
||||
|
||||
// ─── Phase 9: Subscriber Portal ──────────────────────────────────────────────
|
||||
|
||||
test('17. Portal — login page renders with FiberOps branding', async ({ page }) => {
|
||||
await page.goto(`${BASE}/portal/login`);
|
||||
await page.waitForTimeout(2000);
|
||||
await expect(page.locator('text=FiberOps').first()).toBeVisible();
|
||||
await expect(page.locator('input[type="password"]')).toBeVisible();
|
||||
});
|
||||
|
||||
test('18. Portal — rejects wrong credentials', async ({ page }) => {
|
||||
await page.goto(`${BASE}/portal/login`);
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
await page.locator('input[placeholder*="demo-isp"], input').nth(0).fill(TENANT_SLUG);
|
||||
await page.locator('input[placeholder*="ACC"], input').nth(1).fill(PORTAL_ACCOUNT);
|
||||
await page.locator('input[type="password"]').fill('wrongpassword');
|
||||
await page.locator('button:has-text("Sign In")').click();
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
// Should stay on login, show error
|
||||
expect(page.url()).toContain('portal');
|
||||
await expect(page.locator('text=failed, text=invalid, text=error').first()).toBeVisible({ timeout: 5000 }).catch(() => {
|
||||
// Error may appear differently — just check no dashboard redirect
|
||||
expect(page.url()).not.toContain('dashboard');
|
||||
});
|
||||
});
|
||||
|
||||
test('19. Portal — login succeeds with correct credentials', async ({ page }) => {
|
||||
await page.goto(`${BASE}/portal/login`);
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
// 3 inputs: ISP Code, Account Number, Password
|
||||
const inputs = page.locator('input');
|
||||
await inputs.nth(0).fill(TENANT_SLUG);
|
||||
await inputs.nth(1).fill(PORTAL_ACCOUNT);
|
||||
await inputs.nth(2).fill(PORTAL_PASSWORD);
|
||||
await page.locator('button:has-text("Sign In")').click();
|
||||
|
||||
await expect(page).toHaveURL(/portal\/dashboard/, { timeout: 15000 });
|
||||
});
|
||||
|
||||
test('20. Portal dashboard — shows account info', async ({ page }) => {
|
||||
await page.goto(`${BASE}/portal/login`);
|
||||
await page.waitForTimeout(2000);
|
||||
const inputs = page.locator('input');
|
||||
await inputs.nth(0).fill(TENANT_SLUG);
|
||||
await inputs.nth(1).fill(PORTAL_ACCOUNT);
|
||||
await inputs.nth(2).fill(PORTAL_PASSWORD);
|
||||
await page.locator('button:has-text("Sign In")').click();
|
||||
await page.waitForURL(/portal\/dashboard/, { timeout: 15000 });
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
// Should show subscriber name or account
|
||||
await expect(page.locator('text=Juan, text=ACC-000029, text=Basic 25Mbps').first()).toBeVisible({ timeout: 8000 }).catch(() => {
|
||||
// At least the dashboard rendered
|
||||
expect(page.url()).toContain('dashboard');
|
||||
});
|
||||
});
|
||||
|
||||
test('21. Portal invoices — page loads while authenticated', async ({ page }) => {
|
||||
await page.goto(`${BASE}/portal/login`);
|
||||
await page.waitForTimeout(2000);
|
||||
const inputs = page.locator('input');
|
||||
await inputs.nth(0).fill(TENANT_SLUG);
|
||||
await inputs.nth(1).fill(PORTAL_ACCOUNT);
|
||||
await inputs.nth(2).fill(PORTAL_PASSWORD);
|
||||
await page.locator('button:has-text("Sign In")').click();
|
||||
await page.waitForURL(/portal\/dashboard/, { timeout: 15000 });
|
||||
|
||||
await page.goto(`${BASE}/portal/invoices`);
|
||||
await page.waitForTimeout(2000);
|
||||
// Should not redirect back to login
|
||||
expect(page.url()).not.toContain('/portal/login');
|
||||
await expect(page.locator('body')).toBeVisible();
|
||||
});
|
||||
|
||||
test('22. Portal tickets — page loads and can raise new ticket', async ({ page }) => {
|
||||
await page.goto(`${BASE}/portal/login`);
|
||||
await page.waitForTimeout(2000);
|
||||
const inputs = page.locator('input');
|
||||
await inputs.nth(0).fill(TENANT_SLUG);
|
||||
await inputs.nth(1).fill(PORTAL_ACCOUNT);
|
||||
await inputs.nth(2).fill(PORTAL_PASSWORD);
|
||||
await page.locator('button:has-text("Sign In")').click();
|
||||
await page.waitForURL(/portal\/dashboard/, { timeout: 15000 });
|
||||
|
||||
await page.goto(`${BASE}/portal/tickets`);
|
||||
await page.waitForTimeout(2000);
|
||||
expect(page.url()).not.toContain('/portal/login');
|
||||
|
||||
// Try raising a ticket
|
||||
const newBtn = page.locator('button:has-text("New"), button:has-text("Raise"), button:has-text("Create")').first();
|
||||
if (await newBtn.isVisible({ timeout: 3000 }).catch(() => false)) {
|
||||
await newBtn.click();
|
||||
await page.waitForTimeout(1000);
|
||||
const subjectField = page.getByLabel('Subject').first();
|
||||
if (await subjectField.isVisible({ timeout: 2000 }).catch(() => false)) {
|
||||
await subjectField.fill('Internet slow today');
|
||||
await page.locator('button:has-text("Submit"), button:has-text("Create"), button[type=submit]').last().click();
|
||||
await page.waitForTimeout(2000);
|
||||
}
|
||||
}
|
||||
|
||||
await expect(page.locator('body')).toBeVisible();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user