Initial commit: Full Crawl API implementation
Some checks failed
CI / Test (push) Has been cancelled
Deploy / Deploy to Staging (push) Has been cancelled
CI / Build & Push (push) Has been cancelled
Deploy / Deploy to Production (push) Has been cancelled

This commit is contained in:
2026-04-29 07:03:48 +00:00
commit 62994d4f3d
92 changed files with 6176 additions and 0 deletions

105
e2e/api.spec.ts Normal file
View File

@@ -0,0 +1,105 @@
import { test, expect } from '@playwright/test';
const API_URL = process.env.API_URL || 'http://localhost:3000';
test.describe('Crawl API E2E', () => {
let apiKey: string;
let token: string;
test.beforeAll(async ({ request }) => {
// Register test user
const register = await request.post(`${API_URL}/api/auth/register`, {
data: {
email: `e2e_${Date.now()}@test.com`,
password: 'testpassword123'
}
});
const registerData = await register.json();
token = registerData.token;
// Create API key
const key = await request.post(`${API_URL}/api/auth/api-keys`, {
headers: { 'x-auth-token': token },
data: { name: 'E2E Key' }
});
const keyData = await key.json();
apiKey = keyData.key;
});
test('POST /api/screenshot returns success', async ({ request }) => {
const res = await request.post(`${API_URL}/api/screenshot`, {
headers: {
'Content-Type': 'application/json',
'x-api-key': apiKey,
},
data: {
url: 'https://example.com',
options: { fullPage: true }
}
});
expect(res.status()).toBe(200);
const data = await res.json();
expect(data.success).toBe(true);
expect(data.data).toBeDefined();
expect(data.calls_remaining).toBeDefined();
});
test('POST /api/content returns HTML', async ({ request }) => {
const res = await request.post(`${API_URL}/api/content`, {
headers: {
'Content-Type': 'application/json',
'x-api-key': apiKey,
},
data: { url: 'https://example.com' }
});
expect(res.status()).toBe(200);
const data = await res.json();
expect(data.success).toBe(true);
expect(data.data.html).toContain('<html');
});
test('POST /api/json returns structured data', async ({ request }) => {
const res = await request.post(`${API_URL}/api/json`, {
headers: {
'Content-Type': 'application/json',
'x-api-key': apiKey,
},
data: { url: 'https://example.com' }
});
expect(res.status()).toBe(200);
const data = await res.json();
expect(data.success).toBe(true);
expect(data.data.title).toBeDefined();
});
test('GET /metrics returns Prometheus format', async ({ request }) => {
const res = await request.get(`${API_URL}/metrics`);
expect(res.status()).toBe(200);
const text = await res.text();
expect(text).toContain('api_requests_total');
});
test('POST /api/screenshot without API key returns 401', async ({ request }) => {
const res = await request.post(`${API_URL}/api/screenshot`, {
headers: { 'Content-Type': 'application/json' },
data: { url: 'https://example.com' }
});
expect(res.status()).toBe(401);
});
test('POST /api/screenshot with invalid URL returns 400', async ({ request }) => {
const res = await request.post(`${API_URL}/api/screenshot`, {
headers: {
'Content-Type': 'application/json',
'x-api-key': apiKey,
},
data: { url: 'not-a-valid-url' }
});
expect(res.status()).toBe(200);
const data = await res.json();
expect(data.success).toBe(false);
});
});

11
e2e/package.json Normal file
View File

@@ -0,0 +1,11 @@
{
"name": "crawlapi-e2e",
"version": "1.0.0",
"scripts": {
"test": "playwright test",
"test:ui": "playwright test --ui"
},
"devDependencies": {
"@playwright/test": "^1.49.0"
}
}

20
e2e/playwright.config.ts Normal file
View File

@@ -0,0 +1,20 @@
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: '.',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: 'html',
use: {
baseURL: process.env.API_URL || 'http://localhost:3000',
trace: 'on-first-retry',
},
projects: [
{
name: 'api',
testMatch: /.*\.spec\.ts/,
},
],
});