Логин-страница уже в состоянии networkidle → waitForLoadState резолвился
мгновенно (до пост-логин редиректа), скрипт хватал PHPSESSID
неаутентифицированной логин-страницы. CSV-сверка 11:00 (19.05) упала
"load-reports returned non-array response" — портал отдал HTTP 200
+ HTML логин-страницы вместо JSON-массива отчётов.
После клика submit:
- waitForFunction опрашивает исчезновение #loginform-username из DOM
(переживает навигацию);
- guard exit 1, если форма осталась — отклонённый логин больше не
маскируется под «успех» (exit 0).
Verified: 2× RefreshSupplierSessionJob → валидная сессия (load-reports
JSON-массив из 39 отчётов); CsvReconcileJob id=7 status=ok.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
create/update/list через headless Chromium по образцу refresh-session.js.
Селекторы зафиксированы из recon-снапшота rt-add-project-form.yml (Task 1).
stdin/stdout JSON, exit codes 0/1/2/3/4 (success/auth/selector/timeout/input).
Фикстурный тест против локального HTML — без живого портала. Runner —
встроенный node:test (app/playwright не использует @playwright/test, только
playwright core); skipLogin режим открывает фикстуру напрямую.
Spec §4.3. Task 6 of 12. Node-тесты 2/2.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>