Files
portal/app/tests/Feature/Admin/AdminDashboardRefreshBalancesTest.php
T
Дмитрий e13130e3d7 fix(админка): снят сторож xfetch — он врал зелёным, а сам сервис нам больше не нужен
Сторож пинговал https://xf4.ru/fetch и считал сервис живым по любому ответу
меньше 500. А GET туда ВСЕГДА отдаёт 405 (ручка только на POST). Поэтому
03.08.2026, когда у xf4 отвалился браузерный движок и «Поиск клиентов» весь
день собирал по нулям, админка всё это время показывала «xfetch жив».
Сторож проверял, что дом стоит, а не что внутри кто-то есть.

Сам xf4 из поиска убран (перешли на свою рендер-виртуалку), сторожить нечего.

- реестр ExternalBalanceRefresher: 15 ключей -> 14, класс сторожа удалён;
- KNOWN_SERVICE_KEYS и ссылка «пополнить» для xfetch убраны из дашборда;
- карточка «Поиск клиентов» теперь служба + Keyso (рендерщик виден отдельной
  плиткой «Свой рендер»).

XfetchClient автоподбора НЕ тронут — это другой слой, и он уже деградирует
в пустоту без ключа (XFETCH_* убраны из боевого .env ещё в июле).

Тесты: Pest 35 зелёных, Vitest 22 зелёных, Larastan 0 ошибок.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-03 13:22:03 +03:00

84 lines
3.7 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
use App\Services\External\BalanceReading;
use App\Services\External\DadataBalanceProvider;
use App\Services\External\ExternalBalanceRefresher;
use App\Services\External\SupplierBalanceProvider;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Mail;
use Tests\Concerns\SharesSupplierPdo;
uses(DatabaseTransactions::class, SharesSupplierPdo::class); // рефрешер пишет через pgsql_supplier
beforeEach(function () {
Mail::fake();
DB::connection('pgsql_supplier')->table('external_service_balances')->delete();
ExternalBalanceRefresher::useLivenessProbes([]); // без сетевых проб
app()->instance(DadataBalanceProvider::class, fakeProvider('dadata', BalanceReading::ok('dadata', 4500, 'RUB', null)));
app()->instance(SupplierBalanceProvider::class, fakeProvider('supplier', BalanceReading::ok('supplier', 99000, 'RUB', null)));
});
afterEach(fn () => ExternalBalanceRefresher::resetLivenessProbes());
it('POST без service обновляет лёгкие, но НЕ тяжёлый supplier', function () {
$this->postJson('/api/admin/dashboard/balances/refresh', [])->assertOk();
$keys = DB::connection('pgsql_supplier')->table('external_service_balances')->pluck('service_key');
expect($keys)->toContain('dadata');
expect($keys)->not->toContain('supplier');
});
it('POST с service=dadata обновляет один сервис и возвращает список', function () {
$this->postJson('/api/admin/dashboard/balances/refresh', ['service' => 'dadata'])
->assertOk()
->assertJsonStructure(['light', 'services' => [['service_key', 'light', 'ok', 'checked_at']]]);
});
it('неизвестный service → 422', function () {
$this->postJson('/api/admin/dashboard/balances/refresh', ['service' => 'jivosite'])
->assertStatus(422);
});
it('supplier занят замком → 409, второй робот не стартует', function () {
Cache::lock('external-refresh:supplier', 60)->get(); // занять замок
$this->postJson('/api/admin/dashboard/balances/refresh', ['service' => 'supplier'])
->assertStatus(409);
});
it('POST с services[] обновляет группу «Поиск клиентов» разом', function () {
Http::fake(['*' => Http::response('ok', 200)]); // живость проб — без сети
ExternalBalanceRefresher::resetLivenessProbes(); // реальные пробы, но HTTP фейкнут
$this->postJson('/api/admin/dashboard/balances/refresh', [
'services' => ['sales_finder', 'keyso'],
])
->assertOk()
->assertJsonStructure(['light', 'services' => [['service_key', 'light', 'ok', 'checked_at']]]);
$keys = DB::connection('pgsql_supplier')->table('external_service_balances')->pluck('service_key');
foreach (['sales_finder', 'keyso'] as $k) {
expect($keys)->toContain($k);
}
});
it('неизвестный ключ в services[] → 422', function () {
$this->postJson('/api/admin/dashboard/balances/refresh', ['services' => ['keyso', 'нет-такого']])
->assertStatus(422);
});
it('снятый сторож xfetch в services[] тоже неизвестен → 422', function () {
$this->postJson('/api/admin/dashboard/balances/refresh', ['services' => ['xfetch']])
->assertStatus(422);
});
it('тяжёлый supplier в services[] → 422 (обновляется отдельной кнопкой)', function () {
$this->postJson('/api/admin/dashboard/balances/refresh', ['services' => ['keyso', 'supplier']])
->assertStatus(422);
});