110 lines
4.8 KiB
PHP
110 lines
4.8 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
use App\Jobs\ClientTg\RunTelegramCampaignJob;
|
||
|
|
use App\Models\ClientTg\Campaign;
|
||
|
|
use App\Models\ClientTg\RobotJob;
|
||
|
|
use App\Models\Tenant;
|
||
|
|
use App\Models\User;
|
||
|
|
use App\Services\ClientTg\TelegramAudienceService;
|
||
|
|
use App\Services\ClientTg\TelegramRobotRunner;
|
||
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||
|
|
use Illuminate\Support\Facades\Queue;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* «Заголовок объявления» — находка приёмки глазами 31.07.2026.
|
||
|
|
*
|
||
|
|
* 🔴 Кабинет МТС показывает ОБЯЗАТЕЛЬНОЕ поле «Заголовок объявления» (до 40 знаков),
|
||
|
|
* когда рекламируется САЙТ, а не телеграм-канал. Робот про него не знал: «Продолжить»
|
||
|
|
* не срабатывало, кампания вставала на шаге «Объявление» с невнятной причиной, а в
|
||
|
|
* бою деньги к этому моменту уже списаны. Проверено живьём на кампаниях 2234454
|
||
|
|
* (ссылка на сайт — встала) и 2234462 (ссылка на канал — дошла до подтверждения).
|
||
|
|
*
|
||
|
|
* Поэтому портал обязан спросить заголовок ЗАРАНЕЕ — на создании черновика, до денег.
|
||
|
|
*/
|
||
|
|
uses(RefreshDatabase::class);
|
||
|
|
|
||
|
|
beforeEach(function () {
|
||
|
|
$this->tenant = Tenant::factory()->create();
|
||
|
|
$this->user = User::factory()->create(['tenant_id' => $this->tenant->id]);
|
||
|
|
$this->actingAs($this->user);
|
||
|
|
});
|
||
|
|
|
||
|
|
/** @return array<string, mixed> */
|
||
|
|
function tgHeadlinePayload(array $overrides = []): array
|
||
|
|
{
|
||
|
|
return array_merge([
|
||
|
|
'ad_text' => 'Приходите к нам',
|
||
|
|
'ad_link' => 'https://t.me/example_channel',
|
||
|
|
'audience_kind' => 'list',
|
||
|
|
'budget_cap_rub' => '1000.00',
|
||
|
|
'phones' => ['79990000001', '79990000002'],
|
||
|
|
], $overrides);
|
||
|
|
}
|
||
|
|
|
||
|
|
it('реклама САЙТА без заголовка — не создаём кампанию', function () {
|
||
|
|
$response = $this->postJson('/api/telegram/campaigns', tgHeadlinePayload([
|
||
|
|
'ad_link' => 'https://liderra.ru',
|
||
|
|
]));
|
||
|
|
|
||
|
|
$response->assertStatus(422)->assertJsonValidationErrors('ad_headline');
|
||
|
|
expect(Campaign::count())->toBe(0);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('реклама САЙТА с заголовком — кампания создаётся, заголовок сохранён', function () {
|
||
|
|
$response = $this->postJson('/api/telegram/campaigns', tgHeadlinePayload([
|
||
|
|
'ad_link' => 'https://liderra.ru',
|
||
|
|
'ad_headline' => 'Лидерра — заявки для бизнеса',
|
||
|
|
]));
|
||
|
|
|
||
|
|
$response->assertCreated();
|
||
|
|
expect(Campaign::first()->ad_headline)->toBe('Лидерра — заявки для бизнеса');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('реклама телеграм-канала — заголовок не нужен', function () {
|
||
|
|
$response = $this->postJson('/api/telegram/campaigns', tgHeadlinePayload());
|
||
|
|
|
||
|
|
$response->assertCreated();
|
||
|
|
expect(Campaign::first()->ad_headline)->toBeNull();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('заголовок длиннее 40 знаков не принимается — кабинет режет молча', function () {
|
||
|
|
$response = $this->postJson('/api/telegram/campaigns', tgHeadlinePayload([
|
||
|
|
'ad_link' => 'https://liderra.ru',
|
||
|
|
'ad_headline' => str_repeat('я', 41),
|
||
|
|
]));
|
||
|
|
|
||
|
|
$response->assertStatus(422)->assertJsonValidationErrors('ad_headline');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('ссылка на бота t.me тоже считается телеграмом — заголовок не требуем', function () {
|
||
|
|
$response = $this->postJson('/api/telegram/campaigns', tgHeadlinePayload([
|
||
|
|
'ad_link' => 'https://t.me/liderra_bot?start=1',
|
||
|
|
]));
|
||
|
|
|
||
|
|
$response->assertCreated();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('заголовок доезжает до задания робота', function () {
|
||
|
|
config(['client_tg.robot.transport' => 'poll', 'client_tg.sandbox' => true]);
|
||
|
|
Queue::fake();
|
||
|
|
|
||
|
|
$this->postJson('/api/telegram/campaigns', tgHeadlinePayload([
|
||
|
|
'ad_link' => 'https://liderra.ru',
|
||
|
|
'ad_headline' => 'Лидерра',
|
||
|
|
]))->assertCreated();
|
||
|
|
|
||
|
|
$campaign = Campaign::first();
|
||
|
|
$this->postJson("/api/telegram/campaigns/{$campaign->id}/launch")->assertOk();
|
||
|
|
|
||
|
|
// Джоб в очереди подделан — выполняем его тело руками, как это делают
|
||
|
|
// соседние тесты канала: важно, что в задании робота есть заголовок.
|
||
|
|
(new RunTelegramCampaignJob($campaign->id, $this->tenant->id))->handle(
|
||
|
|
app(TelegramAudienceService::class),
|
||
|
|
app(TelegramRobotRunner::class),
|
||
|
|
);
|
||
|
|
|
||
|
|
expect(RobotJob::first()->payload['adHeadline'])->toBe('Лидерра');
|
||
|
|
});
|