'', nodeRunner: function (string $script, string $url): ?array { throw new \RuntimeException('render timed out'); }, ); } it('site(): при падении рендера НЕ теряет номера, добытые curl', function () { $curl = fn (string $url): string => '8 8008 495'; // 8.8.8.8 — публичный IP: проходит isSafeUrl без DNS; сеть не трогаем (curl подменён). $site = fetcherWithFailingRender($curl)->site('https://8.8.8.8/'); expect($site->rawHtml)->toContain('tel:88007003767') ->and($site->rawHtml)->toContain('tel:84950110359') ->and($site->visiblePhones)->toBe([]); // рендер упал — видимых нет, но curl цел }); it('directory(): при падении рендера возвращает [] вместо исключения', function () { expect(fetcherWithFailingRender()->directory('https://8.8.8.8/'))->toBe([]); });