Files
teknav-bak/app/backend/tests/phase10-smoke.test.mjs
arsam 66569baea5 Import tests: app/backend/tests/phase10-smoke.test.mjs
Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
2026-09-18 23:20:49 +03:30

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));
});