'use strict'; /** * Integration: /api/client-errors — приём браузерных ошибок в error_log (level='client'). */ const { describe, it, before, after } = require('node:test'); const assert = require('node:assert/strict'); const { app, inject, getToken, db, cleanup } = require('./setup'); app.use('/api/client-errors', require('../src/routes/clientErrors')); after(() => cleanup()); describe('/api/client-errors', () => { let student; before(async () => { student = await getToken('student'); }); it('требует авторизацию (401)', async () => { const res = await inject('POST', '/api/client-errors', { message: 'x' }, null); assert.equal(res.status, 401); }); it('пустое сообщение → 400', async () => { const res = await inject('POST', '/api/client-errors', { message: ' ' }, student.token); assert.equal(res.status, 400); }); it('пишет ошибку в error_log с level=client', async () => { const res = await inject('POST', '/api/client-errors', { kind: 'error', message: 'TypeError: x is null', stack: 'at foo (app.js:10:5)', source: '/js/app.js', line: 10, col: 5, url: '/lab?sim=demo#x', }, student.token); assert.equal(res.status, 200); assert.equal(res.body.ok, true); const row = db.prepare( "SELECT * FROM error_log WHERE level='client' AND user_id=? ORDER BY id DESC LIMIT 1" ).get(student.userId); assert.ok(row, 'строка должна появиться'); assert.equal(row.message, 'TypeError: x is null'); assert.equal(row.route, '/lab?sim=demo#x'); assert.equal(row.method, 'error'); assert.match(row.stack, /app\.js:10:5/); }); it('unhandledrejection → method=rejection, stack из source при отсутствии stack', async () => { const res = await inject('POST', '/api/client-errors', { kind: 'unhandledrejection', message: 'boom', source: '/js/x.js', line: 3, col: 1, url: '/dashboard', }, student.token); assert.equal(res.status, 200); const row = db.prepare( "SELECT * FROM error_log WHERE level='client' AND message='boom' ORDER BY id DESC LIMIT 1" ).get(); assert.equal(row.method, 'rejection'); assert.match(row.stack, /x\.js:3:1/); }); it('длинные поля обрезаются (не падает)', async () => { const res = await inject('POST', '/api/client-errors', { message: 'M'.repeat(5000), stack: 'S'.repeat(20000), url: 'U'.repeat(2000), }, student.token); assert.equal(res.status, 200); const row = db.prepare("SELECT * FROM error_log WHERE level='client' ORDER BY id DESC LIMIT 1").get(); assert.ok(row.message.length <= 1000); assert.ok(row.stack.length <= 4000); assert.ok(row.route.length <= 400); }); });