/** * Тест refresh-session.js — поведение при ОТКАЗЕ запуска браузера. * * FN-SESSION (приёмка 22.06.2026): на проде browserType.launch падал (не было * исполняемого файла headless-shell в кэше www-data). Из-за того, что * chromium.launch() стоял ВНЕ try/catch, отказ становился unhandled promise * rejection → Node выходил с кодом 1 + сырой стек в stderr — неотличимо от * честного «login rejected» (тоже exit 1). Этот тест фиксирует контракт: * отказ запуска браузера = exit 4 + структурированный JSON {error} в stderr. * * Runner: встроенный node:test (Node 18+). Запуск: `node --test refresh-session.test.js`. */ const { test } = require('node:test'); const assert = require('node:assert'); const { execFile } = require('node:child_process'); const path = require('node:path'); const SCRIPT = path.resolve(__dirname, 'refresh-session.js'); /** Спавнить refresh-session.js с заданным env, подать JSON на stdin, вернуть {code, stdout, stderr}. */ function runScript(input, extraEnv) { return new Promise((resolve, reject) => { const child = execFile( 'node', [SCRIPT], { timeout: 90_000, env: { ...process.env, ...extraEnv } }, (err, stdout, stderr) => { if (err && err.killed) return reject(new Error('Process killed / timed out')); resolve({ code: err ? err.code : 0, stdout: stdout.toString(), stderr: stderr.toString(), }); }, ); child.stdin.write(JSON.stringify(input)); child.stdin.end(); }); } test('отказ запуска браузера → чистый exit 4 + JSON {error} в stderr (не опасный exit 1)', async () => { // Форсируем отказ chromium.launch: указываем кэш браузеров в несуществующий // путь — Playwright не найдёт исполняемый файл (та же ошибка, что была на проде). const result = await runScript( { login: 'x', password: 'y', url: 'http://127.0.0.1:1/' }, { PLAYWRIGHT_BROWSERS_PATH: path.resolve(__dirname, '__nonexistent_browsers__') }, ); // Отказ запуска должен классифицироваться как exit 4 (другая ошибка), // а НЕ как exit 1 (login rejected) и не как unhandled-rejection exit 1. assert.strictEqual(result.code, 4, `Expected exit 4, got ${result.code}. stderr: ${result.stderr}`); // stderr должен быть валидным JSON с ключом error (а не сырым стеком Node). let parsed; try { parsed = JSON.parse(result.stderr.trim()); } catch (e) { assert.fail(`stderr не валидный JSON (сырой стек?): ${result.stderr}`); } assert.ok(typeof parsed.error === 'string' && parsed.error.length > 0, `expected {error}, got ${result.stderr}`); });