Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
74 lines
2.9 KiB
JavaScript
74 lines
2.9 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
|
|
const BASE = process.env.TEST_BASE_URL || 'http://127.0.0.1:3010';
|
|
const SESSION = process.env.TEST_SESSION_COOKIE || '';
|
|
const CSRF = process.env.TEST_CSRF_TOKEN || '';
|
|
const TEST_ARTICLE_SLUG = process.env.TEST_ARTICLE_SLUG || 'agentic-ai-production-2026';
|
|
const REQUIRE_SERVER = process.env.TEST_REQUIRE_SERVER === '1';
|
|
|
|
async function serverAvailable() {
|
|
try {
|
|
const res = await fetch(`${BASE}/api/health`, { signal: AbortSignal.timeout(1500) });
|
|
return res.status < 500;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
const HAS_SERVER = await serverAvailable();
|
|
if (!HAS_SERVER && REQUIRE_SERVER) {
|
|
throw new Error(`TEST_REQUIRE_SERVER=1 but no backend is reachable at ${BASE}`);
|
|
}
|
|
const SERVER_SKIP = HAS_SERVER ? false : `no backend reachable at ${BASE}`;
|
|
|
|
async function request(path, options = {}) {
|
|
const headers = {
|
|
'content-type': 'application/json',
|
|
...(SESSION ? { cookie: SESSION } : {}),
|
|
...(CSRF ? { 'x-csrf-token': CSRF } : {}),
|
|
...(options.headers || {}),
|
|
};
|
|
return fetch(`${BASE}${path}`, { ...options, headers });
|
|
}
|
|
|
|
test('auth rejects invalid credentials without leaking internals', { skip: SERVER_SKIP }, async () => {
|
|
const res = await request('/api/v1/auth/login', {
|
|
method: 'POST',
|
|
body: JSON.stringify({ identifier: 'nobody@example.invalid', password: 'wrong', captchaId: 'invalid', userSolution: '0000' }),
|
|
});
|
|
assert.ok([400, 401, 429].includes(res.status));
|
|
const body = await res.json().catch(() => ({}));
|
|
assert.ok(body.error || body.message);
|
|
});
|
|
|
|
test('public article and comments endpoints are reachable', { skip: SERVER_SKIP }, async () => {
|
|
const articleRes = await request(`/api/v1/articles/${TEST_ARTICLE_SLUG}`);
|
|
assert.equal(articleRes.status, 200);
|
|
const articleBody = await articleRes.json();
|
|
assert.ok(articleBody.article?.id);
|
|
|
|
const commentsRes = await request(`/api/v1/articles/${TEST_ARTICLE_SLUG}/comments`);
|
|
assert.equal(commentsRes.status, 200);
|
|
const commentsBody = await commentsRes.json();
|
|
assert.ok(Array.isArray(commentsBody.items));
|
|
});
|
|
|
|
test('authenticated comment flow works when TEST_SESSION_COOKIE and TEST_CSRF_TOKEN are set', { skip: SERVER_SKIP || !SESSION || !CSRF }, async () => {
|
|
const res = await request(`/api/v1/articles/${TEST_ARTICLE_SLUG}/comments`, {
|
|
method: 'POST',
|
|
body: JSON.stringify({ body: `Phase 10 smoke ${Date.now()}` }),
|
|
});
|
|
assert.equal(res.status, 200);
|
|
const body = await res.json();
|
|
assert.ok(body.comment?.id);
|
|
});
|
|
|
|
test('authenticated article publish workflow is protected and callable when configured', { skip: SERVER_SKIP || !SESSION || !CSRF || !process.env.TEST_PUBLISH_ARTICLE_ID }, async () => {
|
|
const res = await request(`/api/v1/admin/articles/${encodeURIComponent(process.env.TEST_PUBLISH_ARTICLE_ID)}/publish`, {
|
|
method: 'POST',
|
|
body: JSON.stringify({}),
|
|
});
|
|
assert.ok([200, 403, 404].includes(res.status));
|
|
});
|