getJson('/api/admin/sms/tariffs'); $r->assertStatus(200); $tariffs = $r->json('tariffs'); expect($tariffs)->toHaveCount(5); expect(collect($tariffs)->pluck('min_qty')->all())->toBe([1, 100, 250, 500, 1000]); expect($tariffs[0]['price_rub'])->toBe('9.00'); expect($r->json('settings.name_fee_rub_per_operator'))->toBe('2500.00'); expect($r->json('settings.name_debt_grace_days'))->toBe(29); }); test('PUT /api/admin/sms/tariffs заменяет весь набор ступеней', function () { $r = $this->putJson('/api/admin/sms/tariffs', [ 'rows' => [ ['min_qty' => 1, 'price_rub' => '10.00'], ['min_qty' => 500, 'price_rub' => '7.50'], ], ]); $r->assertStatus(200); expect(ClientSmsTariff::count())->toBe(2); $rows = ClientSmsTariff::orderBy('min_qty')->get(); expect($rows[0]->min_qty)->toBe(1); expect($rows[0]->price_rub)->toBe('10.00'); expect($rows[1]->min_qty)->toBe(500); expect($rows[1]->price_rub)->toBe('7.50'); $responseTariffs = $r->json('tariffs'); expect($responseTariffs)->toHaveCount(2); expect(collect($responseTariffs)->pluck('min_qty')->all())->toBe([1, 500]); }); test('PUT /api/admin/sms/settings обновляет singleton настроек', function () { $r = $this->putJson('/api/admin/sms/settings', [ 'name_fee_rub_per_operator' => '3000.00', 'name_debt_grace_days' => 14, ]); $r->assertStatus(200); expect($r->json('name_fee_rub_per_operator'))->toBe('3000.00'); expect($r->json('name_debt_grace_days'))->toBe(14); $settings = ClientSmsSettings::first(); expect($settings->name_fee_rub_per_operator)->toBe('3000.00'); expect($settings->name_debt_grace_days)->toBe(14); }); test('PUT /api/admin/sms/tariffs с некорректной ступенью → 422', function () { $r = $this->putJson('/api/admin/sms/tariffs', [ 'rows' => [ ['min_qty' => 0, 'price_rub' => '10.00'], ], ]); $r->assertStatus(422); $r2 = $this->putJson('/api/admin/sms/tariffs', [ 'rows' => [ ['min_qty' => 1, 'price_rub' => '0.00'], ], ]); $r2->assertStatus(422); // Исходные 5 ступеней не тронуты. expect(ClientSmsTariff::count())->toBe(5); }); /** * Строка листа 4.3: срок, после которого рассылка считается зависшей, правит * владелец — без выпуска новой версии. Значение живёт в тех же общих настройках, * что и границы окна отправки. */ test('4.3 — владелец меняет срок «рассылка зависла», и он сохраняется', function () { $r = $this->putJson('/api/admin/sms/settings', [ 'name_fee_rub_per_operator' => '2500.00', 'name_debt_grace_days' => 29, 'stuck_after_minutes' => 120, ]); $r->assertStatus(200); expect($r->json('stuck_after_minutes'))->toBe(120); expect(ClientSmsSettings::first()->stuck_after_minutes)->toBe(120); }); test('4.3 — GET отдаёт срок «рассылка зависла» вместе с остальными настройками', function () { $r = $this->getJson('/api/admin/sms/tariffs'); $r->assertStatus(200); expect($r->json('settings.stuck_after_minutes'))->toBe(60); }); test('4.3 — слишком короткий срок админка не принимает: сторож срывал бы живые рассылки', function () { $base = ['name_fee_rub_per_operator' => '2500.00', 'name_debt_grace_days' => 29]; $this->putJson('/api/admin/sms/settings', $base + ['stuck_after_minutes' => 0]) ->assertStatus(422) ->assertJsonValidationErrors('stuck_after_minutes'); $this->putJson('/api/admin/sms/settings', $base + ['stuck_after_minutes' => 4]) ->assertStatus(422); // Срок не тронут. expect(ClientSmsSettings::first()->stuck_after_minutes)->toBe(60); }); test('4.3 — срок дольше суток админка не принимает: деньги висели бы замороженными', function () { $r = $this->putJson('/api/admin/sms/settings', [ 'name_fee_rub_per_operator' => '2500.00', 'name_debt_grace_days' => 29, 'stuck_after_minutes' => 1441, ]); $r->assertStatus(422); expect(ClientSmsSettings::first()->stuck_after_minutes)->toBe(60); }); /** * Строка листа 4.6: потолок загрузки базы правит владелец (журнал В-161) — * число, которое никто не может поменять, хуже отсутствующего (мой вывод В-84). */ test('4.6 — владелец меняет потолок загрузки базы, и он сохраняется', function () { $r = $this->putJson('/api/admin/sms/settings', [ 'name_fee_rub_per_operator' => '2500.00', 'name_debt_grace_days' => 29, 'max_upload_phones' => 30000, ]); $r->assertStatus(200); expect($r->json('max_upload_phones'))->toBe(30000); expect(ClientSmsSettings::first()->max_upload_phones)->toBe(30000); }); test('4.6 — GET отдаёт потолок загрузки вместе с остальными настройками', function () { $r = $this->getJson('/api/admin/sms/tariffs'); $r->assertStatus(200); expect($r->json('settings.max_upload_phones'))->toBe(50000); }); test('4.6 — потолок вне границ админка не принимает', function () { $base = ['name_fee_rub_per_operator' => '2500.00', 'name_debt_grace_days' => 29]; // Слишком мало: обычную базу пришлось бы резать на десяток файлов. $this->putJson('/api/admin/sms/settings', $base + ['max_upload_phones' => 100]) ->assertStatus(422) ->assertJsonValidationErrors('max_upload_phones'); // Слишком много: файл читается в память целиком. $this->putJson('/api/admin/sms/settings', $base + ['max_upload_phones' => 100001]) ->assertStatus(422); // Потолок не тронут. expect(ClientSmsSettings::first()->max_upload_phones)->toBe(50000); }); test('4.3 — кто присылает только настройки имени, продолжает работать', function () { // Контракт адреса менять права не имеем: срок необязателен, как и границы окна. $r = $this->putJson('/api/admin/sms/settings', [ 'name_fee_rub_per_operator' => '3000.00', 'name_debt_grace_days' => 20, ]); $r->assertStatus(200); expect(ClientSmsSettings::first()->stuck_after_minutes)->toBe(60); });