'Тест Менеджер '.uniqid(), 'email' => 'salesauth-'.uniqid().'@test.local', 'password' => Hash::make($plain), 'role' => 'manager', 'is_active' => $active, ]); return [$user, $plain]; } // ─── login ─────────────────────────────────────────────────────────────────── test('login: верные данные активного пользователя → 200, token и user.role', function () { [$user, $plain] = makeSalesUserWithPassword(); $response = $this->postJson('/api/sales/auth/login', [ 'email' => $user->email, 'password' => $plain, ]); $response->assertOk(); expect($response->json('token'))->not->toBeNull()->not->toBe(''); expect($response->json('user.role'))->toBe('manager'); expect($response->json('user.email'))->toBe($user->email); }); test('login: неверный пароль → 422 с сообщением', function () { [$user] = makeSalesUserWithPassword(); $response = $this->postJson('/api/sales/auth/login', [ 'email' => $user->email, 'password' => 'wrong-password-xyz', ]); $response->assertStatus(422); expect($response->json('message'))->toBe('Неверный логин или пароль.'); }); test('login: несуществующий email → 422 с сообщением', function () { $response = $this->postJson('/api/sales/auth/login', [ 'email' => 'nonexistent-'.uniqid().'@test.local', 'password' => 'some-password', ]); $response->assertStatus(422); expect($response->json('message'))->toBe('Неверный логин или пароль.'); }); test('login: неактивный пользователь с верным паролем → 403', function () { [$user, $plain] = makeSalesUserWithPassword(active: false); $response = $this->postJson('/api/sales/auth/login', [ 'email' => $user->email, 'password' => $plain, ]); $response->assertStatus(403); expect($response->json('message'))->toBe('Аккаунт отключён, обратитесь к начальнику.'); }); // ─── me ────────────────────────────────────────────────────────────────────── test('me: запрос без токена → 401', function () { $this->getJson('/api/sales/auth/me') ->assertUnauthorized(); }); test('me: запрос с валидным Bearer-токеном → 200 с данными пользователя', function () { [$user, $plain] = makeSalesUserWithPassword(); // Получаем токен через логин. $loginResponse = $this->postJson('/api/sales/auth/login', [ 'email' => $user->email, 'password' => $plain, ]); $loginResponse->assertOk(); $token = $loginResponse->json('token'); // Запрашиваем /me с токеном. $meResponse = $this->withHeader('Authorization', 'Bearer '.$token) ->getJson('/api/sales/auth/me'); $meResponse->assertOk(); expect($meResponse->json('email'))->toBe($user->email); expect($meResponse->json('role'))->toBe('manager'); }); // ─── logout ────────────────────────────────────────────────────────────────── test('logout: выход инвалидирует токен, повторный /me → 401', function () { [$user, $plain] = makeSalesUserWithPassword(); // Создаём токен напрямую (без login endpoint) — стабильнее в тестах. // Проверка самого login-эндпоинта покрыта первым тестом выше. $plainToken = $user->createToken('sales')->plainTextToken; // Выход через endpoint. $logoutResponse = $this->withHeader('Authorization', 'Bearer '.$plainToken) ->postJson('/api/sales/auth/logout'); $logoutResponse->assertOk(); expect($logoutResponse->json('message'))->toBe('Вы вышли.'); // Сбрасываем кэш guard-инстансов в AuthManager (общий singleton в контейнере). // Без этого guard('sales') возвращает пользователя, кэшированного из предыдущего // logout-запроса, даже если токен уже удалён из БД. Auth::forgetGuards(); // Повторный /me с тем же токеном должен вернуть 401. $this->withHeader('Authorization', 'Bearer '.$plainToken) ->getJson('/api/sales/auth/me') ->assertUnauthorized(); });