2026-02-07 10:23:29 -04:00
|
|
|
import { test, expect, Page } from '@playwright/test';
|
|
|
|
|
|
|
|
|
|
// Helper functions
|
|
|
|
|
async function loginAsCitizen(page: Page) {
|
|
|
|
|
await page.goto('/auth/login');
|
2026-02-08 18:44:05 -04:00
|
|
|
await page.getByLabel('Email').fill('rajesh.naik@example.com');
|
2026-02-07 10:23:29 -04:00
|
|
|
await page.getByLabel('Password').fill('Citizen@123');
|
|
|
|
|
await page.getByRole('button', { name: 'Sign In' }).click();
|
|
|
|
|
await page.waitForURL('**/dashboard**', { timeout: 10000 });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function loginAsAdmin(page: Page) {
|
|
|
|
|
await page.goto('/auth/login');
|
|
|
|
|
await page.getByLabel('Email').fill('admin@goa.gov.in');
|
|
|
|
|
await page.getByLabel('Password').fill('Admin@123');
|
|
|
|
|
await page.getByRole('button', { name: 'Sign In' }).click();
|
|
|
|
|
await page.waitForURL('**/admin**', { timeout: 10000 });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function loginAsDepartment(page: Page) {
|
|
|
|
|
await page.goto('/auth/login');
|
|
|
|
|
await page.getByLabel('Email').fill('fire@goa.gov.in');
|
|
|
|
|
await page.getByLabel('Password').fill('Fire@123');
|
|
|
|
|
await page.getByRole('button', { name: 'Sign In' }).click();
|
|
|
|
|
await page.waitForURL('**/dashboard**', { timeout: 10000 });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test.describe('Citizen Dashboard', () => {
|
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
|
|
|
await loginAsCitizen(page);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('should display citizen dashboard after login', async ({ page }) => {
|
|
|
|
|
await expect(page).toHaveURL(/.*dashboard.*/);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('should show welcome message or user info', async ({ page }) => {
|
|
|
|
|
// Dashboard should display something indicating the user is logged in
|
|
|
|
|
const hasUserInfo = await page.locator('text=citizen').first().isVisible().catch(() => false) ||
|
|
|
|
|
await page.locator('text=Dashboard').first().isVisible().catch(() => false) ||
|
|
|
|
|
await page.locator('text=Welcome').first().isVisible().catch(() => false);
|
|
|
|
|
|
|
|
|
|
expect(hasUserInfo).toBe(true);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('should have navigation menu', async ({ page }) => {
|
|
|
|
|
// Should have some navigation elements
|
|
|
|
|
const hasNav = await page.locator('nav, [role="navigation"], .sidebar, .nav-menu').first().isVisible().catch(() => false) ||
|
|
|
|
|
await page.locator('mat-sidenav, mat-toolbar').first().isVisible().catch(() => false);
|
|
|
|
|
|
|
|
|
|
expect(hasNav).toBe(true);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('should have link to requests', async ({ page }) => {
|
|
|
|
|
// Should be able to navigate to requests
|
|
|
|
|
const requestsLink = page.locator('a[href*="request"]').first();
|
|
|
|
|
|
|
|
|
|
if (await requestsLink.isVisible().catch(() => false)) {
|
|
|
|
|
await requestsLink.click();
|
|
|
|
|
await page.waitForURL('**/requests**', { timeout: 5000 }).catch(() => {});
|
|
|
|
|
} else {
|
|
|
|
|
// Try alternative navigation
|
|
|
|
|
await page.goto('/requests');
|
|
|
|
|
await expect(page).toHaveURL(/.*requests.*/);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test.describe('Department Dashboard', () => {
|
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
|
|
|
await loginAsDepartment(page);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('should display department dashboard after login', async ({ page }) => {
|
|
|
|
|
await expect(page).toHaveURL(/.*dashboard.*/);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('should show department-specific content', async ({ page }) => {
|
|
|
|
|
// Department dashboard may show pending approvals or assigned requests
|
|
|
|
|
const hasDepartmentContent =
|
|
|
|
|
(await page.locator('text=Pending').first().isVisible().catch(() => false)) ||
|
|
|
|
|
(await page.locator('text=Approval').first().isVisible().catch(() => false)) ||
|
|
|
|
|
(await page.locator('text=Review').first().isVisible().catch(() => false)) ||
|
|
|
|
|
(await page.locator('text=Dashboard').first().isVisible().catch(() => false));
|
|
|
|
|
|
|
|
|
|
expect(hasDepartmentContent).toBe(true);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test.describe('Admin Dashboard', () => {
|
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
|
|
|
await loginAsAdmin(page);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('should display admin dashboard after login', async ({ page }) => {
|
|
|
|
|
await expect(page).toHaveURL(/.*admin.*/);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('should show admin menu items', async ({ page }) => {
|
|
|
|
|
// Admin should see admin-specific navigation
|
|
|
|
|
const hasAdminItems =
|
|
|
|
|
(await page.locator('text=Admin').first().isVisible().catch(() => false)) ||
|
|
|
|
|
(await page.locator('text=Users').first().isVisible().catch(() => false)) ||
|
|
|
|
|
(await page.locator('text=Departments').first().isVisible().catch(() => false)) ||
|
|
|
|
|
(await page.locator('text=Workflow').first().isVisible().catch(() => false)) ||
|
|
|
|
|
(await page.locator('text=Settings').first().isVisible().catch(() => false));
|
|
|
|
|
|
|
|
|
|
expect(hasAdminItems).toBe(true);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('should have access to departments management', async ({ page }) => {
|
|
|
|
|
// Navigate to departments if link exists
|
|
|
|
|
const deptLink = page.locator('a[href*="department"]').first();
|
|
|
|
|
|
|
|
|
|
if (await deptLink.isVisible().catch(() => false)) {
|
|
|
|
|
await deptLink.click();
|
|
|
|
|
await page.waitForTimeout(2000);
|
|
|
|
|
} else {
|
|
|
|
|
// Navigate directly
|
|
|
|
|
await page.goto('/admin/departments');
|
|
|
|
|
await page.waitForTimeout(1000);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('should have access to workflows management', async ({ page }) => {
|
|
|
|
|
// Navigate to workflows if link exists
|
|
|
|
|
const workflowLink = page.locator('a[href*="workflow"]').first();
|
|
|
|
|
|
|
|
|
|
if (await workflowLink.isVisible().catch(() => false)) {
|
|
|
|
|
await workflowLink.click();
|
|
|
|
|
await page.waitForTimeout(2000);
|
|
|
|
|
} else {
|
|
|
|
|
// Navigate directly
|
|
|
|
|
await page.goto('/admin/workflows');
|
|
|
|
|
await page.waitForTimeout(1000);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test.describe('Navigation', () => {
|
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
|
|
|
await loginAsCitizen(page);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('should navigate between pages', async ({ page }) => {
|
|
|
|
|
// Go to dashboard
|
|
|
|
|
await page.goto('/dashboard');
|
|
|
|
|
await expect(page).toHaveURL(/.*dashboard.*/);
|
|
|
|
|
|
|
|
|
|
// Navigate to requests
|
|
|
|
|
await page.goto('/requests');
|
|
|
|
|
await page.waitForTimeout(1000);
|
|
|
|
|
await expect(page).toHaveURL(/.*requests.*/);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('should handle logout', async ({ page }) => {
|
|
|
|
|
// Find and click logout button/link
|
|
|
|
|
const logoutBtn = page.locator('button:has-text("Logout"), a:has-text("Logout"), [aria-label="Logout"], mat-icon:has-text("logout")').first();
|
|
|
|
|
|
|
|
|
|
if (await logoutBtn.isVisible()) {
|
|
|
|
|
await logoutBtn.click();
|
|
|
|
|
await page.waitForTimeout(2000);
|
|
|
|
|
|
|
|
|
|
// Should be redirected to login or home
|
|
|
|
|
const currentUrl = page.url();
|
|
|
|
|
expect(currentUrl).toMatch(/\/(auth|login|$)/);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test.describe('Responsive Design', () => {
|
|
|
|
|
test('should display correctly on mobile viewport', async ({ page }) => {
|
|
|
|
|
await page.setViewportSize({ width: 375, height: 667 });
|
|
|
|
|
await loginAsCitizen(page);
|
|
|
|
|
|
|
|
|
|
// Page should still be usable
|
|
|
|
|
await expect(page).toHaveURL(/.*dashboard.*/);
|
|
|
|
|
|
|
|
|
|
// Mobile menu toggle might be present
|
|
|
|
|
const mobileMenu = page.locator('[aria-label="Menu"]').first();
|
|
|
|
|
|
|
|
|
|
if (await mobileMenu.isVisible().catch(() => false)) {
|
|
|
|
|
await mobileMenu.click();
|
|
|
|
|
await page.waitForTimeout(500);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('should display correctly on tablet viewport', async ({ page }) => {
|
|
|
|
|
await page.setViewportSize({ width: 768, height: 1024 });
|
|
|
|
|
await loginAsCitizen(page);
|
|
|
|
|
|
|
|
|
|
await expect(page).toHaveURL(/.*dashboard.*/);
|
|
|
|
|
});
|
|
|
|
|
});
|