2026-02-06 23:01:30 -05:00

84 lines
2.7 KiB
TypeScript

// POST /api/test — Stream multi-layer QA test execution via SSE
import { NextRequest } from 'next/server';
import { runTests } from '@mcpengine/ai-pipeline/services/tester';
import { createSSEResponse } from '@mcpengine/ai-pipeline/streaming/sse';
import type { TestLayer } from '@mcpengine/ai-pipeline/types';
export const runtime = 'nodejs';
export const maxDuration = 180;
const VALID_LAYERS: TestLayer[] = [
'protocol', 'static', 'visual', 'functional', 'performance', 'security',
];
/**
* Load server code for a project.
* In production, this reads from DB / generated bundle storage.
*/
async function loadServerCode(projectId: string): Promise<string | null> {
// TODO: Replace with actual DB lookup
// Should return the concatenated server source code for testing
return null;
}
export async function POST(req: NextRequest) {
try {
const body = await req.json();
const { projectId, layers, serverCode } = body as {
projectId: string;
layers: TestLayer[];
serverCode?: string; // Allow inline for development
};
if (!projectId) {
return new Response(
JSON.stringify({ error: 'projectId is required' }),
{ status: 400, headers: { 'Content-Type': 'application/json' } }
);
}
if (!layers || !Array.isArray(layers) || layers.length === 0) {
return new Response(
JSON.stringify({ error: 'layers array is required and must not be empty' }),
{ status: 400, headers: { 'Content-Type': 'application/json' } }
);
}
// Validate layers
const invalidLayers = layers.filter((l) => !VALID_LAYERS.includes(l));
if (invalidLayers.length > 0) {
return new Response(
JSON.stringify({
error: `Invalid test layers: ${invalidLayers.join(', ')}. Valid: ${VALID_LAYERS.join(', ')}`,
}),
{ status: 400, headers: { 'Content-Type': 'application/json' } }
);
}
let resolvedCode: string;
if (serverCode) {
resolvedCode = serverCode;
} else {
const code = await loadServerCode(projectId);
if (!code) {
return new Response(
JSON.stringify({ error: `No server code found for project ${projectId}. Generate first.` }),
{ status: 404, headers: { 'Content-Type': 'application/json' } }
);
}
resolvedCode = code;
}
const generator = runTests(resolvedCode, layers);
return createSSEResponse(generator);
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
return new Response(
JSON.stringify({ error: `Internal error: ${message}` }),
{ status: 500, headers: { 'Content-Type': 'application/json' } }
);
}
}