- Backend: Express + TypeORM + PostgreSQL, JWT + OTP auth - Frontend: React + Vite + Tailwind, 4 pages (Home/Login/Orders/404) - Docker Compose: PostgreSQL 15 on port 5434 - Tests: 16 tests passing (API + Frontend) - ai_state: rules.md, INSTRUCTIONS.md, session tasks - Examples: brand book PDF, logos, page mockups
108 lines
4.8 KiB
JavaScript
108 lines
4.8 KiB
JavaScript
// Tests/api_tests.mjs
|
||
// Тесты backend API — запускаются через: node Tests/api_tests.mjs
|
||
// Требует: запущенный backend (npm run dev в backend/) и PostgreSQL
|
||
|
||
const API = 'http://localhost:3001/api';
|
||
let passed = 0;
|
||
let failed = 0;
|
||
|
||
async function test(name, fn) {
|
||
try {
|
||
await fn();
|
||
console.log(` ✅ PASS: ${name}`);
|
||
passed++;
|
||
} catch (err) {
|
||
console.log(` ❌ FAIL: ${name}`);
|
||
console.log(` ${err.message}`);
|
||
failed++;
|
||
}
|
||
}
|
||
|
||
function assert(condition, message) {
|
||
if (!condition) throw new Error(message || 'Assertion failed');
|
||
}
|
||
|
||
async function fetchJSON(url, options = {}) {
|
||
const res = await fetch(url, {
|
||
headers: { 'Content-Type': 'application/json', ...options.headers },
|
||
...options,
|
||
body: options.body ? JSON.stringify(options.body) : undefined,
|
||
});
|
||
const data = await res.json();
|
||
return { status: res.status, data };
|
||
}
|
||
|
||
// ─── Группа 1: Health Check ────────────────────────────────────────────────
|
||
console.log('\n🔍 Группа 1: Health Check');
|
||
|
||
await test('GET /api/health возвращает 200', async () => {
|
||
const { status, data } = await fetchJSON(`${API}/health`);
|
||
assert(status === 200, `Ожидался 200, получен ${status}`);
|
||
assert(data.success === true, 'success !== true');
|
||
assert(data.data.status === 'ok', `status !== 'ok'`);
|
||
});
|
||
|
||
// ─── Группа 2: Auth — request-otp ──────────────────────────────────────────
|
||
console.log('\n🔍 Группа 2: Auth — request-otp');
|
||
|
||
// Уникальный номер на каждый запуск — обходим rate-limit (5 минут)
|
||
const testPhone = `+7900${Date.now().toString().slice(-7)}`;
|
||
|
||
await test('POST /api/auth/request-otp с телефоном возвращает success', async () => {
|
||
const { status, data } = await fetchJSON(`${API}/auth/request-otp`, {
|
||
method: 'POST',
|
||
body: { phone: testPhone },
|
||
});
|
||
assert(status === 200, `Ожидался 200, получен ${status}`);
|
||
assert(data.success === true, `success=false, errors: ${JSON.stringify(data.errors)}`);
|
||
});
|
||
|
||
await test('POST /api/auth/request-otp без телефона возвращает 400', async () => {
|
||
const { status, data } = await fetchJSON(`${API}/auth/request-otp`, {
|
||
method: 'POST',
|
||
body: {},
|
||
});
|
||
assert(status === 400, `Ожидался 400, получен ${status}`);
|
||
assert(data.success === false, 'success должен быть false для невалидных данных');
|
||
});
|
||
|
||
// ─── Группа 3: Auth — verify-otp ───────────────────────────────────────────
|
||
console.log('\n🔍 Группа 3: Auth — verify-otp');
|
||
|
||
await test('POST /api/auth/verify-otp с неверным кодом возвращает ошибку', async () => {
|
||
const { status, data } = await fetchJSON(`${API}/auth/verify-otp`, {
|
||
method: 'POST',
|
||
body: { phone: testPhone, otp: '000000' },
|
||
});
|
||
// Неверный код: сервер должен вернуть 400 или 200 с success=false
|
||
assert(data.success === false, `Ожидался success=false для неверного OTP`);
|
||
});
|
||
|
||
await test('POST /api/auth/verify-otp без otp возвращает 400', async () => {
|
||
const { status, data } = await fetchJSON(`${API}/auth/verify-otp`, {
|
||
method: 'POST',
|
||
body: { phone: testPhone },
|
||
});
|
||
assert(status === 400, `Ожидался 400, получен ${status}`);
|
||
});
|
||
|
||
// ─── Группа 4: Защищённые маршруты ─────────────────────────────────────────
|
||
console.log('\n🔍 Группа 4: Защищённые маршруты (без токена)');
|
||
|
||
await test('Запрос к несуществующему API маршруту возвращает 404', async () => {
|
||
const res = await fetch(`${API}/nonexistent`);
|
||
assert(res.status === 404, `Ожидался 404, получен ${res.status}`);
|
||
const data = await res.json();
|
||
assert(data.success === false, 'success должен быть false для 404');
|
||
});
|
||
|
||
// ─── Итог ──────────────────────────────────────────────────────────────────
|
||
console.log(`\n${'─'.repeat(50)}`);
|
||
console.log(`Итог: ${passed} прошло, ${failed} провалено`);
|
||
if (failed > 0) {
|
||
console.log('⚠️ Есть проваленные тесты');
|
||
process.exit(1);
|
||
} else {
|
||
console.log('✅ Все тесты прошли успешно');
|
||
}
|