62 lines
3.1 KiB
PHP
62 lines
3.1 KiB
PHP
|
|
<?php
|
|||
|
|
|
|||
|
|
declare(strict_types=1);
|
|||
|
|
|
|||
|
|
use App\Jobs\Autopodbor\RunAutopodborStudyJob;
|
|||
|
|
use App\Models\AutopodborCompetitor;
|
|||
|
|
use App\Models\AutopodborRun;
|
|||
|
|
use App\Models\SystemSetting;
|
|||
|
|
use App\Models\Tenant;
|
|||
|
|
use App\Services\Autopodbor\Agent\CompetitorAgent;
|
|||
|
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
|||
|
|
use Illuminate\Support\Facades\DB;
|
|||
|
|
use Illuminate\Support\Facades\Queue;
|
|||
|
|
use Illuminate\Support\Str;
|
|||
|
|
use Tests\Concerns\SharesSupplierPdo;
|
|||
|
|
use Tests\Doubles\EmptyCompetitorAgent;
|
|||
|
|
|
|||
|
|
uses(DatabaseTransactions::class, SharesSupplierPdo::class);
|
|||
|
|
|
|||
|
|
it('после завершения прогона джоба сама зовёт распорядителя, и тот диспатчит следующий queued', function () {
|
|||
|
|
Queue::fake();
|
|||
|
|
// Детерминированная заглушка агента (без реальной сети) — прогон уйдёт в `empty` быстро.
|
|||
|
|
app()->bind(CompetitorAgent::class, EmptyCompetitorAgent::class);
|
|||
|
|
|
|||
|
|
$tenant = Tenant::factory()->create(['balance_rub' => '100000.00']);
|
|||
|
|
DB::statement('SET app.current_tenant_id = '.$tenant->id);
|
|||
|
|
SystemSetting::updateOrCreate(['key' => 'autopodbor_price_study_rub'], ['value' => '300', 'type' => 'decimal']);
|
|||
|
|
|
|||
|
|
$comp1 = AutopodborCompetitor::create([
|
|||
|
|
'tenant_id' => $tenant->id, 'name' => 'Окна А', 'origin' => 'manual',
|
|||
|
|
'dedup_key' => Str::slug('Окна А').'-'.Str::random(6), 'box' => 'field',
|
|||
|
|
]);
|
|||
|
|
$comp2 = AutopodborCompetitor::create([
|
|||
|
|
'tenant_id' => $tenant->id, 'name' => 'Окна Б', 'origin' => 'manual',
|
|||
|
|
'dedup_key' => Str::slug('Окна Б').'-'.Str::random(6), 'box' => 'field',
|
|||
|
|
]);
|
|||
|
|
|
|||
|
|
$run1 = AutopodborRun::create([
|
|||
|
|
'tenant_id' => $tenant->id, 'kind' => 'study', 'status' => 'queued',
|
|||
|
|
'competitor_id' => $comp1->id, 'region_code' => 1, 'params' => [],
|
|||
|
|
]);
|
|||
|
|
AutopodborRun::whereKey($run1->id)->update(['created_at' => now()->subMinutes(5)]);
|
|||
|
|
|
|||
|
|
$run2 = AutopodborRun::create([
|
|||
|
|
'tenant_id' => $tenant->id, 'kind' => 'study', 'status' => 'queued',
|
|||
|
|
'competitor_id' => $comp2->id, 'region_code' => 1, 'params' => [],
|
|||
|
|
]);
|
|||
|
|
AutopodborRun::whereKey($run2->id)->update(['created_at' => now()]);
|
|||
|
|
|
|||
|
|
// Класс должен инстанцироваться с новой зависимостью в handle() без ошибок конструктора/резолва.
|
|||
|
|
expect(new RunAutopodborStudyJob($run1->id, $tenant->id))->toBeInstanceOf(RunAutopodborStudyJob::class);
|
|||
|
|
|
|||
|
|
// Прогоняем ПЕРВЫЙ прогон РЕАЛЬНО (через handle(), не через Queue) — Queue::fake() гарантирует,
|
|||
|
|
// что единственный dispatch RunAutopodborStudyJob, который мы увидим, придёт ИЗНУТРИ handle()
|
|||
|
|
// (от распорядителя), а не от нашего собственного вызова.
|
|||
|
|
app()->call([new RunAutopodborStudyJob($run1->id, $tenant->id), 'handle']);
|
|||
|
|
|
|||
|
|
expect($run1->fresh()->status)->toBe('empty');
|
|||
|
|
|
|||
|
|
Queue::assertPushed(RunAutopodborStudyJob::class, fn ($job) => $job->runId === $run2->id);
|
|||
|
|
});
|