import { expect, test, type BrowserContext, type Page } from '@playwright/test' import { authenticateAs, createAccessToken } from '@/e2e/fixtures/session' const authenticate = async (context: BrowserContext, page: Page, role: 'admin' | 'user', status: 'active' | 'pending' = 'active') => { if (status === 'active') { await authenticateAs(context, page, role) return } await context.addCookies([ { name: 'accessToken', value: createAccessToken(role), domain: '127.0.0.1', path: '/' }, { name: 'userRole', value: role, domain: '127.0.0.1', path: '/' }, { name: 'userStatus', value: status, domain: '127.0.0.1', path: '/' }, ]) } test('redirects a guest from a private consumer route to home with auth modal intent', async ({ page }) => { await page.route('**/api/v1/**', (route) => route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ success: true, data: { items: [], meta: {} } }), }) ) await page.goto('/chats') await expect(page).toHaveURL(/\/(\?|$)/) await expect(page).not.toHaveURL(/\/auth/) await expect(page.getByPlaceholder('مثال ۰۹۱۲۳۴۵۶۷۸۹')).toBeVisible() }) test('redirects a guest from an admin route to the admin auth page', async ({ page }) => { await page.goto('/dashboard') await expect(page).toHaveURL(/\/auth\?redirect=%2Fdashboard$/) // Auth mobile step has no page title — assert the OTP entry form instead. await expect(page.getByLabel('شماره موبایل')).toBeVisible() await expect(page.getByRole('button', { name: 'ادامه' })).toBeVisible() }) test('allows public discovery routes without a session', async ({ page }) => { await page.route('**/api/v1/**', (route) => route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ success: true, data: { items: [], meta: {} } }), }) ) const response = await page.goto('/') await expect(page).toHaveURL('http://127.0.0.1:3102/') await expect(page.locator('body')).toBeVisible() expect(response?.headers()['content-security-policy']).toContain("frame-ancestors 'none'") expect(response?.headers()['x-content-type-options']).toBe('nosniff') expect(response?.headers()['referrer-policy']).toBe('strict-origin-when-cross-origin') }) test('prevents a consumer from opening admin routes', async ({ context, page }) => { await authenticate(context, page, 'user') await page.goto('/dashboard') await expect(page).toHaveURL('http://127.0.0.1:3102/') }) test('ignores a forged userRole=admin cookie when the access JWT is a consumer', async ({ context, page }) => { const accessToken = createAccessToken('user') await context.addCookies([ { name: 'accessToken', value: accessToken, domain: '127.0.0.1', path: '/' }, { name: 'userRole', value: 'admin', domain: '127.0.0.1', path: '/' }, { name: 'userStatus', value: 'active', domain: '127.0.0.1', path: '/' }, ]) await page.addInitScript( ({ token }) => { localStorage.setItem( 'user', JSON.stringify({ accessToken: token, userId: 'user-id', role: 'user', sessionId: 'user-session', AccessTokenExpireTime: Date.now() + 3_600_000, refreshTokenExpireTime: Date.now() + 86_400_000, status: 'active', }) ) }, { token: accessToken } ) await page.route('**/api/v1/**', (route) => route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ success: true, data: { items: [], meta: {} } }), }) ) await page.goto('/dashboard') await expect(page).toHaveURL('http://127.0.0.1:3102/') }) test('redirects an admin away from the consumer shell', async ({ context, page }) => { await authenticate(context, page, 'admin') await page.goto('/') await expect(page).toHaveURL(/\/dashboard$/) }) test('forces pending consumers to complete profile in the auth modal', async ({ context, page }) => { const accessToken = createAccessToken('user') await context.addCookies([ { name: 'accessToken', value: accessToken, domain: '127.0.0.1', path: '/' }, { name: 'userRole', value: 'user', domain: '127.0.0.1', path: '/' }, { name: 'userStatus', value: 'pending', domain: '127.0.0.1', path: '/' }, ]) await page.addInitScript( ({ token }) => { localStorage.setItem( 'user', JSON.stringify({ accessToken: token, userId: 'user-id', role: 'user', sessionId: 'user-session', AccessTokenExpireTime: Date.now() + 3_600_000, refreshTokenExpireTime: Date.now() + 86_400_000, status: 'pending', }) ) }, { token: accessToken } ) await page.route('**/api/v1/**', (route) => route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ success: true, data: { items: [], meta: {} } }), }) ) await page.goto('/profile') await expect(page).toHaveURL(/\/profile$/) await expect(page.getByText('تکمیل اطلاعات پروفایل')).toBeVisible() })