Files
portal/app/tests/Feature/Advertising/SyncCampaignAudienceJobTest.php
T

142 lines
5.2 KiB
PHP
Raw Normal View History

<?php
declare(strict_types=1);
use App\Jobs\SyncCampaignAudienceJob;
use App\Models\AdCampaign;
use App\Models\Tenant;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Tests\Concerns\SharesSupplierPdo;
// Джоб намеренно обходит running/pending-кампании ВСЕХ тенантов — без изоляции
// между кейсами кампания из одного теста осталась бы видна следующему (проверка
// "пустая аудитория ⇒ ни одного обращения" иначе ловила бы чужой сегмент).
uses(RefreshDatabase::class);
// Джоб перечисляет кампании через pgsql_supplier (BYPASSRLS) — без share PDO
// вставленные в тест-транзакции кампании (default pgsql-соединение) не видны
// второму соединению до commit'а.
uses(SharesSupplierPdo::class);
it('replace-заливает аудиторию активной кампании в Яндекс.Аудитории', function () {
config([
'services.yandex_direct.enabled' => true,
'services.yandex_audience.token' => 'AUDTOKEN',
]);
Http::fake(['*/modify_data*' => Http::response(['ok' => true], 200)]);
$tenant = Tenant::factory()->create();
// T3: свой список считается только в mode=manual (auto его игнорирует).
$campaign = AdCampaign::create([
'tenant_id' => $tenant->id,
'name' => 'Кампания ночной заливки',
'status' => AdCampaign::STATUS_RUNNING,
'yandex_segment_id' => 900001,
'weekly_budget_rub' => '500.00',
'mode' => AdCampaign::MODE_MANUAL,
'audience_days' => 10,
'use_uploaded_list' => true,
]);
DB::table('ad_campaign_phones')->insert([
'tenant_id' => $tenant->id,
'campaign_id' => $campaign->id,
'phone' => '79990000001',
'expires_at' => now()->addDays(5),
'created_at' => now(),
'updated_at' => now(),
]);
app(SyncCampaignAudienceJob::class)->handle();
Http::assertSent(function ($request) {
return str_contains($request->url(), 'modify_data')
&& str_contains($request->url(), 'replace');
});
});
it('рубильник выключен — ни одного обращения к Яндексу', function () {
config([
'services.yandex_direct.enabled' => false,
'services.yandex_audience.token' => 'AUDTOKEN',
]);
Http::fake(['*/modify_data*' => Http::response(['ok' => true], 200)]);
$tenant = Tenant::factory()->create();
$campaign = AdCampaign::create([
'tenant_id' => $tenant->id,
'name' => 'Кампания при выключенном рубильнике',
'status' => AdCampaign::STATUS_RUNNING,
'yandex_segment_id' => 900002,
'weekly_budget_rub' => '500.00',
'audience_days' => 10,
'use_uploaded_list' => true,
]);
DB::table('ad_campaign_phones')->insert([
'tenant_id' => $tenant->id,
'campaign_id' => $campaign->id,
'phone' => '79990000002',
'expires_at' => now()->addDays(5),
'created_at' => now(),
'updated_at' => now(),
]);
app(SyncCampaignAudienceJob::class)->handle();
Http::assertNothingSent();
});
it('пустая аудитория кампании — пропускает без обращения к Яндексу', function () {
config([
'services.yandex_direct.enabled' => true,
'services.yandex_audience.token' => 'AUDTOKEN',
]);
Http::fake(['*/modify_data*' => Http::response(['ok' => true], 200)]);
$tenant = Tenant::factory()->create();
AdCampaign::create([
'tenant_id' => $tenant->id,
'name' => 'Кампания без аудитории',
'status' => AdCampaign::STATUS_RUNNING,
'yandex_segment_id' => 900003,
'weekly_budget_rub' => '500.00',
'audience_days' => 10,
'use_uploaded_list' => false,
]);
app(SyncCampaignAudienceJob::class)->handle();
Http::assertNothingSent();
});
it('кампания без сегмента Яндекса — пропускает', function () {
config([
'services.yandex_direct.enabled' => true,
'services.yandex_audience.token' => 'AUDTOKEN',
]);
Http::fake(['*/modify_data*' => Http::response(['ok' => true], 200)]);
$tenant = Tenant::factory()->create();
$campaign = AdCampaign::create([
'tenant_id' => $tenant->id,
'name' => 'Кампания без сегмента',
'status' => AdCampaign::STATUS_RUNNING,
'weekly_budget_rub' => '500.00',
'audience_days' => 10,
'use_uploaded_list' => true,
]);
DB::table('ad_campaign_phones')->insert([
'tenant_id' => $tenant->id,
'campaign_id' => $campaign->id,
'phone' => '79990000004',
'expires_at' => now()->addDays(5),
'created_at' => now(),
'updated_at' => now(),
]);
app(SyncCampaignAudienceJob::class)->handle();
Http::assertNothingSent();
});