parser = new ResearcherParser; }); it('разбирает чистый JSON в имена + тип', function () { $raw = '[{"name":"CarMoney","type":"федеральная"},{"name":"Ваш инвестор","type":"региональная"}]'; $out = $this->parser->parse($raw); expect($out)->toHaveCount(2) ->and($out[0]['name'])->toBe('CarMoney') ->and($out[0]['type'])->toBe('федеральная') ->and($out[1]['name'])->toBe('Ваш инвестор'); }); it('вытаскивает JSON из markdown-обёртки и текста вокруг', function () { $raw = "Вот названия:\n```json\n".'[{"name":"Финео","type":"федеральная"}]'."\n```\nГотово."; $out = $this->parser->parse($raw); expect($out)->toHaveCount(1)->and($out[0]['name'])->toBe('Финео'); }); it('пропускает элемент без имени; тип может отсутствовать', function () { $raw = '[{"name":"","type":"региональная"},{"name":"Голд Авто Инвест"}]'; $out = $this->parser->parse($raw); expect($out)->toHaveCount(1) ->and($out[0]['name'])->toBe('Голд Авто Инвест') ->and($out[0]['type'])->toBeNull(); }); it('модель даёт ТОЛЬКО имя и тип — сайт/карточку парсер НЕ вытаскивает (их найдёт EXA)', function () { // Даже если модель по инерции положит site/card — парсер их игнорирует: якорь ищет EXA. $raw = '[{"name":"CarMoney","type":"федеральная","site":"carmoney.ru","card":"https://2gis.ru/firm/999"}]'; $out = $this->parser->parse($raw); expect($out)->toHaveCount(1) ->and($out[0]['name'])->toBe('CarMoney') ->and($out[0]['type'])->toBe('федеральная') ->and(array_keys($out[0]))->toBe(['name', 'type']); // никаких site/card }); it('пустой массив и мусор дают []', function () { expect($this->parser->parse('[]'))->toBe([]) ->and($this->parser->parse('извините, ничего'))->toBe([]) ->and($this->parser->parse(''))->toBe([]); });