- 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
94 lines
4.3 KiB
JavaScript
94 lines
4.3 KiB
JavaScript
// Tests/frontend_tests.mjs
|
||
// Тесты доступности страниц frontend — запускаются через: node Tests/frontend_tests.mjs
|
||
// Требует: запущенный Vite dev server (npm run dev в frontend/)
|
||
|
||
const BASE = 'http://localhost:3000';
|
||
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');
|
||
}
|
||
|
||
// ─── Группа 1: Доступность страниц ─────────────────────────────────────────
|
||
console.log('\n🔍 Группа 1: Доступность страниц (HTTP 200)');
|
||
|
||
const pages = [
|
||
{ url: '/', name: 'Главная страница' },
|
||
{ url: '/login', name: 'Страница входа' },
|
||
{ url: '/about', name: 'О компании' },
|
||
{ url: '/delivery', name: 'Доставка' },
|
||
{ url: '/nonexistent-page', name: '404 страница (возвращает HTML)' },
|
||
];
|
||
|
||
for (const page of pages) {
|
||
await test(`GET ${page.url} — ${page.name}`, async () => {
|
||
const res = await fetch(`${BASE}${page.url}`);
|
||
assert(res.status === 200, `Ожидался 200, получен ${res.status}`);
|
||
const text = await res.text();
|
||
assert(text.includes('<div id="root">'), 'HTML не содержит корневой элемент React');
|
||
});
|
||
}
|
||
|
||
// ─── Группа 2: Контент страниц ──────────────────────────────────────────────
|
||
console.log('\n🔍 Группа 2: Корректность HTML');
|
||
|
||
await test('Главная страница содержит тег title', async () => {
|
||
const res = await fetch(`${BASE}/`);
|
||
const text = await res.text();
|
||
assert(text.includes('<title>'), 'Нет тега <title>');
|
||
assert(text.includes('Nutshell'), 'Title не содержит "Nutshell"');
|
||
});
|
||
|
||
await test('Страница загружает шрифт Inter из Google Fonts', async () => {
|
||
const res = await fetch(`${BASE}/`);
|
||
const text = await res.text();
|
||
assert(text.includes('fonts.googleapis.com'), 'Нет ссылки на Google Fonts');
|
||
assert(text.includes('Inter'), 'Шрифт Inter не подключён');
|
||
});
|
||
|
||
await test('Логотип PNG доступен', async () => {
|
||
const res = await fetch(`${BASE}/logo-white.png`);
|
||
assert(res.status === 200, `Ожидался 200 для logo-white.png, получен ${res.status}`);
|
||
const ct = res.headers.get('content-type') || '';
|
||
assert(ct.includes('image/png') || ct.includes('image/'), `Неверный content-type: ${ct}`);
|
||
});
|
||
|
||
await test('Чёрный логотип PNG доступен', async () => {
|
||
const res = await fetch(`${BASE}/logo-black.png`);
|
||
assert(res.status === 200, `Ожидался 200 для logo-black.png, получен ${res.status}`);
|
||
});
|
||
|
||
// ─── Группа 3: Proxy к API ──────────────────────────────────────────────────
|
||
console.log('\n🔍 Группа 3: Proxy /api → backend :3001');
|
||
|
||
await test('Vite proxy /api/health работает', async () => {
|
||
const res = await fetch(`${BASE}/api/health`);
|
||
assert(res.status === 200, `Ожидался 200 через proxy, получен ${res.status}`);
|
||
const data = await res.json();
|
||
assert(data.success === true, 'success !== true через proxy');
|
||
assert(data.data.status === 'ok', `status !== 'ok' через proxy`);
|
||
});
|
||
|
||
// ─── Итог ──────────────────────────────────────────────────────────────────
|
||
console.log(`\n${'─'.repeat(50)}`);
|
||
console.log(`Итог: ${passed} прошло, ${failed} провалено`);
|
||
if (failed > 0) {
|
||
console.log('⚠️ Есть проваленные тесты');
|
||
process.exit(1);
|
||
} else {
|
||
console.log('✅ Все тесты прошли успешно');
|
||
}
|