Expand Playwright E2E test coverage from 17 to 86 tests covering: - Listings CRUD (create, search, filter, detail, status update) - Search (text search, geo search, validation, Typesense fallback) - Payments (create, list transactions, auth guards) - Subscriptions (plans, create, quota, billing, usage metering) - Admin authorization guards (all endpoints reject non-admin users) Co-Authored-By: Paperclip <noreply@paperclip.ing>
153 lines
4.8 KiB
TypeScript
153 lines
4.8 KiB
TypeScript
import { test, expect, registerUser } from '../fixtures';
|
|
|
|
/**
|
|
* Admin API E2E tests.
|
|
*
|
|
* These tests verify that admin endpoints enforce proper authorization.
|
|
* Full admin workflow tests require a seeded admin user with password
|
|
* (see prisma/seed.ts — admin phone: 0900000001).
|
|
*/
|
|
test.describe('Admin API — Authorization', () => {
|
|
let regularToken: string;
|
|
|
|
test.beforeAll(async ({ request }) => {
|
|
const { accessToken } = await registerUser(request);
|
|
regularToken = accessToken;
|
|
});
|
|
|
|
test.describe('GET /admin/moderation — Moderation queue', () => {
|
|
test('rejects unauthenticated request', async ({ request }) => {
|
|
const res = await request.get('/admin/moderation');
|
|
|
|
expect(res.status()).toBe(401);
|
|
});
|
|
|
|
test('rejects non-admin user', async ({ request }) => {
|
|
const res = await request.get('/admin/moderation', {
|
|
headers: { Authorization: `Bearer ${regularToken}` },
|
|
});
|
|
|
|
expect(res.status()).toBe(403);
|
|
});
|
|
});
|
|
|
|
test.describe('POST /admin/moderation/approve — Approve listing', () => {
|
|
test('rejects unauthenticated request', async ({ request }) => {
|
|
const res = await request.post('/admin/moderation/approve', {
|
|
data: { listingId: 'test-id' },
|
|
});
|
|
|
|
expect(res.status()).toBe(401);
|
|
});
|
|
|
|
test('rejects non-admin user', async ({ request }) => {
|
|
const res = await request.post('/admin/moderation/approve', {
|
|
data: { listingId: 'test-id' },
|
|
headers: { Authorization: `Bearer ${regularToken}` },
|
|
});
|
|
|
|
expect(res.status()).toBe(403);
|
|
});
|
|
});
|
|
|
|
test.describe('POST /admin/moderation/reject — Reject listing', () => {
|
|
test('rejects unauthenticated request', async ({ request }) => {
|
|
const res = await request.post('/admin/moderation/reject', {
|
|
data: { listingId: 'test-id', reason: 'E2E test rejection reason' },
|
|
});
|
|
|
|
expect(res.status()).toBe(401);
|
|
});
|
|
|
|
test('rejects non-admin user', async ({ request }) => {
|
|
const res = await request.post('/admin/moderation/reject', {
|
|
data: { listingId: 'test-id', reason: 'E2E test rejection reason' },
|
|
headers: { Authorization: `Bearer ${regularToken}` },
|
|
});
|
|
|
|
expect(res.status()).toBe(403);
|
|
});
|
|
});
|
|
|
|
test.describe('POST /admin/users/ban — Ban user', () => {
|
|
test('rejects unauthenticated request', async ({ request }) => {
|
|
const res = await request.post('/admin/users/ban', {
|
|
data: { userId: 'test-id', reason: 'E2E test ban reason text' },
|
|
});
|
|
|
|
expect(res.status()).toBe(401);
|
|
});
|
|
|
|
test('rejects non-admin user', async ({ request }) => {
|
|
const res = await request.post('/admin/users/ban', {
|
|
data: { userId: 'test-id', reason: 'E2E test ban reason text' },
|
|
headers: { Authorization: `Bearer ${regularToken}` },
|
|
});
|
|
|
|
expect(res.status()).toBe(403);
|
|
});
|
|
});
|
|
|
|
test.describe('POST /admin/subscriptions/adjust — Adjust subscription', () => {
|
|
test('rejects unauthenticated request', async ({ request }) => {
|
|
const res = await request.post('/admin/subscriptions/adjust', {
|
|
data: {
|
|
userId: 'test-id',
|
|
newPlanTier: 'AGENT_PRO',
|
|
reason: 'E2E test subscription adjustment',
|
|
},
|
|
});
|
|
|
|
expect(res.status()).toBe(401);
|
|
});
|
|
|
|
test('rejects non-admin user', async ({ request }) => {
|
|
const res = await request.post('/admin/subscriptions/adjust', {
|
|
data: {
|
|
userId: 'test-id',
|
|
newPlanTier: 'AGENT_PRO',
|
|
reason: 'E2E test subscription adjustment',
|
|
},
|
|
headers: { Authorization: `Bearer ${regularToken}` },
|
|
});
|
|
|
|
expect(res.status()).toBe(403);
|
|
});
|
|
});
|
|
|
|
test.describe('GET /admin/dashboard — Dashboard stats', () => {
|
|
test('rejects unauthenticated request', async ({ request }) => {
|
|
const res = await request.get('/admin/dashboard');
|
|
|
|
expect(res.status()).toBe(401);
|
|
});
|
|
|
|
test('rejects non-admin user', async ({ request }) => {
|
|
const res = await request.get('/admin/dashboard', {
|
|
headers: { Authorization: `Bearer ${regularToken}` },
|
|
});
|
|
|
|
expect(res.status()).toBe(403);
|
|
});
|
|
});
|
|
|
|
test.describe('GET /admin/revenue — Revenue stats', () => {
|
|
test('rejects unauthenticated request', async ({ request }) => {
|
|
const res = await request.get('/admin/revenue', {
|
|
params: { startDate: '2026-01-01', endDate: '2026-12-31' },
|
|
});
|
|
|
|
expect(res.status()).toBe(401);
|
|
});
|
|
|
|
test('rejects non-admin user', async ({ request }) => {
|
|
const res = await request.get('/admin/revenue', {
|
|
params: { startDate: '2026-01-01', endDate: '2026-12-31' },
|
|
headers: { Authorization: `Bearer ${regularToken}` },
|
|
});
|
|
|
|
expect(res.status()).toBe(403);
|
|
});
|
|
});
|
|
});
|