ExternalBalanceRefresher::resetLivenessProbes()); function stubBalanceProvidersOk(): void { app()->instance(DadataBalanceProvider::class, fakeProvider('dadata', BalanceReading::ok('dadata', 9000, 'RUB', 100))); app()->instance(SupplierBalanceProvider::class, fakeProvider('supplier', BalanceReading::ok('supplier', 90000, 'RUB', null))); app()->instance(YandexCloudBalanceProvider::class, fakeProvider('yandex_cloud', BalanceReading::ok('yandex_cloud', 90000, 'RUB', 100))); // captcha — единственная проба, которую эти тесты подменяют через useLivenessProbes(); // остальные пробы (yookassa/self_render/sales_finder) идут в реальные классы без Http::fake(). // self_render по умолчанию не настроен (grey, без сети). sales_finder же по умолчанию // смотрит на боевой домен (config/services.php) — обнуляем его здесь, иначе тест бьёт // по сети и красный ответ ломает ожидание «письмо не ушло». config()->set('services.sales_finder.base_url', ''); } it('шлёт одно письмо, когда сервис впервые покраснел', function () { Mail::fake(); stubBalanceProvidersOk(); ExternalBalanceRefresher::useLivenessProbes([ fakeProbe('captcha', LivenessReading::down('captcha', 'HTTP 500')), ]); (new RefreshExternalBalancesJob)->handle(app(ExternalBalanceRefresher::class)); Mail::assertSent(ExternalServiceDownMail::class, 1); }); it('не шлёт письмо, если сервис уже был красным (без спама)', function () { Mail::fake(); stubBalanceProvidersOk(); // Предзаливаем строку: captcha уже красный. DB::connection('pgsql_supplier')->table('external_service_balances')->updateOrInsert( ['service_key' => 'captcha'], ['light' => 'red', 'ok' => true, 'currency' => 'RUB', 'checked_at' => now(), 'updated_at' => now()], ); ExternalBalanceRefresher::useLivenessProbes([ fakeProbe('captcha', LivenessReading::down('captcha', 'HTTP 500')), ]); (new RefreshExternalBalancesJob)->handle(app(ExternalBalanceRefresher::class)); Mail::assertNothingSent(); }); it('не шлёт письмо, когда всё зелёное', function () { Mail::fake(); stubBalanceProvidersOk(); ExternalBalanceRefresher::useLivenessProbes([ fakeProbe('captcha', LivenessReading::alive('captcha', 'ок')), ]); (new RefreshExternalBalancesJob)->handle(app(ExternalBalanceRefresher::class)); Mail::assertNothingSent(); });