Files
portal/app/tests/Feature/ClientTg/AdminTgApiTest.php
T

110 lines
5.2 KiB
PHP
Raw Normal View History

<?php
declare(strict_types=1);
use App\Models\ClientTg\Campaign;
use App\Models\ClientTg\Tariff;
use Illuminate\Foundation\Testing\DatabaseTransactions;
/**
* SaaS-admin «Клиентская Telegram-реклама» — себестоимость показа (client_tg_tariffs).
* Гейт группы — saas-admin,admin-db (crm_admin_user); admin-db переключает соединение
* на pgsql_admin, а SharesAdminPdo (глобально в Pest.php) отдаёт ему ту же PDO-сессию,
* что у default (видимость засеянной схемы).
*
* 🔴 Форма таблицы изменилась 02.08.2026 (миграция client_tg_cena_po_media): было пять
* ступеней по объёму, стало три строки по видам медиа. У МТС скидки за объём НЕТ —
* цена плоская и зависит только от медиа (прайс кабинета, стр. 13).
*
* Здесь правится ЗАКУПОЧНАЯ цена (что платим мы), а не цена клиента: клиент платит
* её × наценку config client_tg.markup.
*
* Сидировано миграцией: none/0.480, image/0.720, video/0.816 — с НДС.
*/
uses(DatabaseTransactions::class);
test('GET /api/admin/telegram/tariffs возвращает три вида медиа', function () {
$r = $this->getJson('/api/admin/telegram/tariffs');
$r->assertStatus(200);
$tariffs = $r->json('tariffs');
expect($tariffs)->toHaveCount(3);
expect(collect($tariffs)->pluck('media_kind')->all())
->toBe([Campaign::MEDIA_NONE, Campaign::MEDIA_IMAGE, Campaign::MEDIA_VIDEO]);
expect($tariffs[0]['price_rub'])->toBe('0.480');
expect($tariffs[2]['price_rub'])->toBe('0.816');
});
test('PUT /api/admin/telegram/tariffs заменяет себестоимость всех трёх видов', function () {
$r = $this->putJson('/api/admin/telegram/tariffs', [
'rows' => [
['media_kind' => Campaign::MEDIA_NONE, 'price_rub' => '0.500'],
['media_kind' => Campaign::MEDIA_IMAGE, 'price_rub' => '0.750'],
['media_kind' => Campaign::MEDIA_VIDEO, 'price_rub' => '0.900'],
],
]);
$r->assertStatus(200);
expect(Tariff::count())->toBe(3)
->and(Tariff::where('media_kind', Campaign::MEDIA_NONE)->first()->price_rub)->toBe('0.500')
->and(Tariff::where('media_kind', Campaign::MEDIA_VIDEO)->first()->price_rub)->toBe('0.900');
expect(collect($r->json('tariffs'))->pluck('media_kind')->all())
->toBe([Campaign::MEDIA_NONE, Campaign::MEDIA_IMAGE, Campaign::MEDIA_VIDEO]);
});
test('PUT /api/admin/telegram/tariffs с нулевой ценой → 422', function () {
$this->putJson('/api/admin/telegram/tariffs', [
'rows' => [
['media_kind' => Campaign::MEDIA_NONE, 'price_rub' => '0.000'],
['media_kind' => Campaign::MEDIA_IMAGE, 'price_rub' => '0.750'],
['media_kind' => Campaign::MEDIA_VIDEO, 'price_rub' => '0.900'],
],
])->assertStatus(422);
// Исходные строки не тронуты.
expect(Tariff::count())->toBe(3)
->and(Tariff::where('media_kind', Campaign::MEDIA_NONE)->first()->price_rub)->toBe('0.480');
});
/**
* 🔴 Главное, что охраняет эта ручка. Прежняя принимала произвольный список ступеней:
* владелец мог сохранить сетку без нужной строки, и расчёт упал бы уже в бою — в момент
* списания денег с клиента. Теперь набор строго три вида, каждый ровно один раз.
*/
test('PUT /api/admin/telegram/tariffs без одного вида медиа → 422, старое сохранено', function () {
$this->putJson('/api/admin/telegram/tariffs', [
'rows' => [
['media_kind' => Campaign::MEDIA_NONE, 'price_rub' => '0.500'],
['media_kind' => Campaign::MEDIA_IMAGE, 'price_rub' => '0.750'],
],
])->assertStatus(422);
expect(Tariff::count())->toBe(3)
->and(Tariff::where('media_kind', Campaign::MEDIA_NONE)->first()->price_rub)->toBe('0.480');
});
test('PUT /api/admin/telegram/tariffs с задвоенным видом → 422', function () {
$this->putJson('/api/admin/telegram/tariffs', [
'rows' => [
['media_kind' => Campaign::MEDIA_NONE, 'price_rub' => '0.500'],
['media_kind' => Campaign::MEDIA_NONE, 'price_rub' => '0.600'],
['media_kind' => Campaign::MEDIA_VIDEO, 'price_rub' => '0.900'],
],
])->assertStatus(422);
expect(Tariff::count())->toBe(3);
});
test('PUT /api/admin/telegram/tariffs с выдуманным видом медиа → 422', function () {
$this->putJson('/api/admin/telegram/tariffs', [
'rows' => [
['media_kind' => 'gif', 'price_rub' => '0.500'],
['media_kind' => Campaign::MEDIA_IMAGE, 'price_rub' => '0.750'],
['media_kind' => Campaign::MEDIA_VIDEO, 'price_rub' => '0.900'],
],
])->assertStatus(422);
expect(Tariff::count())->toBe(3);
});