'srv-key-test', 'services.captcha.yandex_validate_url' => 'https://smartcaptcha.cloud.yandex.ru/validate', ]); }); test('пустой токен → false без обращения к Yandex', function () { Http::fake(); expect((new YandexSmartCaptchaVerifier)->verify(null))->toBeFalse(); expect((new YandexSmartCaptchaVerifier)->verify(''))->toBeFalse(); Http::assertNothingSent(); }); test('Yandex status=ok → true', function () { Http::fake(['smartcaptcha.cloud.yandex.ru/*' => Http::response(['status' => 'ok'], 200)]); expect((new YandexSmartCaptchaVerifier)->verify('tok', '203.0.113.7'))->toBeTrue(); }); test('Yandex status=failed → false', function () { Http::fake(['smartcaptcha.cloud.yandex.ru/*' => Http::response(['status' => 'failed'], 200)]); expect((new YandexSmartCaptchaVerifier)->verify('tok'))->toBeFalse(); }); test('Yandex 500 → fail-open true', function () { Http::fake(['smartcaptcha.cloud.yandex.ru/*' => Http::response('err', 500)]); expect((new YandexSmartCaptchaVerifier)->verify('tok'))->toBeTrue(); }); test('Yandex connection error → fail-open true', function () { Http::fake(function () { throw new ConnectionException('timeout'); }); expect((new YandexSmartCaptchaVerifier)->verify('tok'))->toBeTrue(); }); test('запрос несёт secret+token+ip', function () { Http::fake(['smartcaptcha.cloud.yandex.ru/*' => Http::response(['status' => 'ok'], 200)]); (new YandexSmartCaptchaVerifier)->verify('tok-abc', '198.51.100.9'); Http::assertSent(function (Request $r) { return $r['secret'] === 'srv-key-test' && $r['token'] === 'tok-abc' && $r['ip'] === '198.51.100.9'; }); }); test('биндинг по driver: yandex → Yandex-класс, null → Null-класс', function () { config(['services.captcha.driver' => 'yandex']); expect(app(CaptchaVerifier::class))->toBeInstanceOf(YandexSmartCaptchaVerifier::class); config(['services.captcha.driver' => 'null']); expect(app(CaptchaVerifier::class))->toBeInstanceOf(NullCaptchaVerifier::class); });