'Начальник '.uniqid(), 'email' => 'perhead'.uniqid().'@sales.local', 'password' => bcrypt('secret'), 'role' => 'head', 'is_active' => true, ]); } /** * Все GET-точки, которые принимают период. Начальник видит все, * поэтому одним пользователем покрываем и менеджерские, и boss-only. * * @return list */ function per_endpoints(): array { return [ '/api/sales/clients', '/api/sales/dashboard/overview', '/api/sales/income', '/api/sales/managers/performance', '/api/sales/payouts/remaining', '/api/sales/tariffs', ]; } it('произвольный период без дат отвечает 422, а не падает', function () { $head = per_head(); foreach (per_endpoints() as $url) { $this->actingAs($head, 'sales') ->getJson($url.'?period=custom') ->assertStatus(422) ->assertJsonValidationErrors('period'); } }); it('произвольный период с одной датой отвечает 422', function () { $head = per_head(); foreach (per_endpoints() as $url) { $this->actingAs($head, 'sales') ->getJson($url.'?period=custom&from=2026-07-01') ->assertStatus(422) ->assertJsonValidationErrors('period'); } }); it('перевёрнутый произвольный период отвечает 422', function () { $head = per_head(); foreach (per_endpoints() as $url) { $this->actingAs($head, 'sales') ->getJson($url.'?period=custom&from=2026-07-10&to=2026-07-01') ->assertStatus(422) ->assertJsonValidationErrors('period'); } }); it('новые периоды календаря принимаются на всех экранах', function () { $head = per_head(); foreach (per_endpoints() as $url) { foreach (['today', 'yesterday', 'd7', 'd30'] as $kind) { $this->actingAs($head, 'sales') ->getJson($url.'?period='.$kind) ->assertOk(); } } });