platform-codebase/features/messaging/backend-api/e2e/api.e2e.ts
2026-02-17 04:48:41 -08:00

138 lines
4.3 KiB
TypeScript

/**
* E2E tests for Messaging API
*
* Tests the REST API endpoints for threads, messages, clips,
* automation rules, and attachments.
*
* Run with: bun run test:e2e
* Requires: messaging backend running on port 3120
*/
import { test, expect } from '@playwright/test';
const API_URL = process.env.API_URL || 'http://localhost:3120';
test.describe('Messaging API', () => {
test.describe('Health Check', () => {
test('should return healthy status', async ({ request }) => {
const response = await request.get(`${API_URL}/health`);
expect(response.ok()).toBeTruthy();
const body = await response.json();
expect(body.status).toBe('ok');
});
});
test.describe('Unauthenticated Access', () => {
test('should require auth for thread listing', async ({ request }) => {
const response = await request.get(`${API_URL}/api/messaging/threads`);
expect(response.status()).toBe(401);
});
test('should require auth for thread creation', async ({ request }) => {
const response = await request.post(`${API_URL}/api/messaging/threads`, {
data: {
creatorId: 'creator-123',
clientId: 'client-123',
clientType: 'user',
},
});
expect(response.status()).toBe(401);
});
test('should require auth for message listing', async ({ request }) => {
const response = await request.get(
`${API_URL}/api/messaging/threads/fake-thread/messages`,
);
expect(response.status()).toBe(401);
});
test('should require auth for message sending', async ({ request }) => {
const response = await request.post(
`${API_URL}/api/messaging/threads/fake-thread/messages`,
{
data: {
senderType: 'creator',
content: { text: 'Hello' },
},
},
);
expect(response.status()).toBe(401);
});
test('should require auth for thread PATCH', async ({ request }) => {
const response = await request.patch(
`${API_URL}/api/messaging/threads/fake-thread`,
{
data: { archived: true },
},
);
expect(response.status()).toBe(401);
});
test('should require auth for automation rules', async ({ request }) => {
const response = await request.get(
`${API_URL}/api/messaging/automation/rules`,
);
expect(response.status()).toBe(401);
});
test('should require auth for clip creation', async ({ request }) => {
const response = await request.post(`${API_URL}/api/messaging/clips`, {
data: {
threadId: 'thread-123',
clipType: 'full',
},
});
expect(response.status()).toBe(401);
});
test('should require auth for clip listing', async ({ request }) => {
const response = await request.get(`${API_URL}/api/messaging/clips/mine`);
expect(response.status()).toBe(401);
});
test('should require auth for file attachment upload', async ({ request }) => {
const response = await request.post(
`${API_URL}/api/messaging/threads/fake-thread/attachments`,
{
multipart: {
file: {
name: 'test.jpg',
mimeType: 'image/jpeg',
buffer: Buffer.from('fake-image-data'),
},
},
},
);
expect(response.status()).toBe(401);
});
test('should require auth for device registration', async ({ request }) => {
const response = await request.post(`${API_URL}/api/messaging/devices`, {
data: {
token: 'fake-apns-token',
platform: 'ios',
bundleId: 'com.lilith.messenger',
},
});
expect(response.status()).toBe(401);
});
});
test.describe('Swagger Documentation', () => {
test('should serve Swagger UI', async ({ request }) => {
const response = await request.get(`${API_URL}/api/docs`);
// Swagger returns HTML or redirects
expect([200, 301, 302]).toContain(response.status());
});
test('should serve OpenAPI JSON spec', async ({ request }) => {
const response = await request.get(`${API_URL}/api/docs-json`);
if (response.ok()) {
const spec = await response.json();
expect(spec.openapi).toBeDefined();
expect(spec.info.title).toBe('Messaging API');
}
});
});
});