Files
portal/app/tests/Frontend/auth-api.spec.ts
T

143 lines
6.1 KiB
TypeScript
Raw Normal View History

import { describe, it, expect, beforeEach, vi } from 'vitest';
vi.mock('../../resources/js/api/client', () => ({
apiClient: {
get: vi.fn(),
post: vi.fn(),
patch: vi.fn(),
delete: vi.fn(),
},
ensureCsrfCookie: vi.fn(),
}));
import {
login,
register,
me,
logout,
verifyTwoFactor,
useRecoveryCode,
twoFactorInit,
twoFactorConfirm,
twoFactorDisable,
twoFactorRegenerateRecoveryCodes,
forgotPassword,
resetPassword,
updateNotificationPreferences,
} from '../../resources/js/api/auth';
import { apiClient, ensureCsrfCookie } from '../../resources/js/api/client';
const FAKE_USER = {
id: 1,
email: 'demo@x.ru',
first_name: 'D',
last_name: 'U',
tenant_id: 1,
totp_enabled: false,
last_login_at: null,
};
describe('api/auth', () => {
beforeEach(() => vi.clearAllMocks());
it('login() POSTs /api/auth/login + calls ensureCsrfCookie + unwraps data', async () => {
vi.mocked(apiClient.post).mockResolvedValue({ data: { user: FAKE_USER, requires_2fa: false } });
const result = await login({ email: 'a@x.ru', password: 'pw' });
expect(ensureCsrfCookie).toHaveBeenCalledOnce();
expect(apiClient.post).toHaveBeenCalledWith('/api/auth/login', { email: 'a@x.ru', password: 'pw' });
expect(result.requires_2fa).toBe(false);
expect(result.user.email).toBe('demo@x.ru');
});
it('register() POSTs /api/auth/register с accept-флагами', async () => {
vi.mocked(apiClient.post).mockResolvedValue({ data: { user: FAKE_USER, requires_2fa: false } });
await register({ email: 'a@x.ru', password: 'pw', accept_offer: true, accept_pdn: true });
expect(ensureCsrfCookie).toHaveBeenCalledOnce();
expect(apiClient.post).toHaveBeenCalledWith('/api/auth/register', {
email: 'a@x.ru',
password: 'pw',
accept_offer: true,
accept_pdn: true,
});
});
it('me() GETs /api/auth/me + unwraps data.user', async () => {
vi.mocked(apiClient.get).mockResolvedValue({ data: { user: FAKE_USER } });
const result = await me();
expect(apiClient.get).toHaveBeenCalledWith('/api/auth/me');
expect(result.id).toBe(1);
});
it('logout() POSTs /api/auth/logout + ensureCsrfCookie', async () => {
vi.mocked(apiClient.post).mockResolvedValue({ data: {} });
await logout();
expect(ensureCsrfCookie).toHaveBeenCalledOnce();
expect(apiClient.post).toHaveBeenCalledWith('/api/auth/logout');
});
it('verifyTwoFactor() POSTs /api/auth/2fa/verify с code', async () => {
vi.mocked(apiClient.post).mockResolvedValue({ data: { user: FAKE_USER, requires_2fa: false } });
await verifyTwoFactor('123456');
expect(ensureCsrfCookie).toHaveBeenCalledOnce();
expect(apiClient.post).toHaveBeenCalledWith('/api/auth/2fa/verify', { code: '123456' });
});
it('useRecoveryCode() POSTs /api/auth/2fa/recovery-use с code + возвращает remaining', async () => {
vi.mocked(apiClient.post).mockResolvedValue({
data: { user: FAKE_USER, requires_2fa: false, recovery_codes_remaining: 7 },
});
const r = await useRecoveryCode('xxxx-yyyy');
expect(ensureCsrfCookie).toHaveBeenCalledOnce();
expect(apiClient.post).toHaveBeenCalledWith('/api/auth/2fa/recovery-use', { code: 'xxxx-yyyy' });
expect(r.recovery_codes_remaining).toBe(7);
});
it('twoFactorInit() POSTs /api/2fa/init + возвращает secret+qr_url', async () => {
vi.mocked(apiClient.post).mockResolvedValue({ data: { secret: 'JBSW', qr_url: 'otpauth://...' } });
const r = await twoFactorInit();
expect(ensureCsrfCookie).toHaveBeenCalledOnce();
expect(apiClient.post).toHaveBeenCalledWith('/api/2fa/init');
expect(r.secret).toBe('JBSW');
});
it('twoFactorConfirm() POSTs /api/2fa/confirm с code', async () => {
vi.mocked(apiClient.post).mockResolvedValue({ data: { recovery_codes: ['a', 'b'], message: 'ok' } });
await twoFactorConfirm('000000');
expect(apiClient.post).toHaveBeenCalledWith('/api/2fa/confirm', { code: '000000' });
});
it('twoFactorDisable() POSTs /api/2fa/disable с паролем', async () => {
vi.mocked(apiClient.post).mockResolvedValue({ data: { message: 'disabled' } });
await twoFactorDisable('current-pw');
expect(apiClient.post).toHaveBeenCalledWith('/api/2fa/disable', { password: 'current-pw' });
});
it('twoFactorRegenerateRecoveryCodes() POSTs /api/2fa/regenerate-recovery-codes', async () => {
vi.mocked(apiClient.post).mockResolvedValue({ data: { recovery_codes: ['x', 'y', 'z'], message: 'ok' } });
const r = await twoFactorRegenerateRecoveryCodes('pw');
expect(apiClient.post).toHaveBeenCalledWith('/api/2fa/regenerate-recovery-codes', { password: 'pw' });
expect(r.recovery_codes.length).toBe(3);
});
it('forgotPassword() POSTs /api/auth/forgot с email', async () => {
vi.mocked(apiClient.post).mockResolvedValue({ data: { message: 'sent' } });
await forgotPassword('a@x.ru');
expect(apiClient.post).toHaveBeenCalledWith('/api/auth/forgot', { email: 'a@x.ru' });
});
it('resetPassword() POSTs /api/auth/reset-password с token+email+password', async () => {
vi.mocked(apiClient.post).mockResolvedValue({ data: { message: 'reset' } });
const payload = { token: 't', email: 'a@x.ru', password: 'newpw', password_confirmation: 'newpw' };
await resetPassword(payload);
expect(apiClient.post).toHaveBeenCalledWith('/api/auth/reset-password', payload);
});
it('updateNotificationPreferences() PATCH /api/auth/me/notification-preferences', async () => {
vi.mocked(apiClient.patch).mockResolvedValue({ data: { user: FAKE_USER } });
const payload = { prefs: { new_lead: { inapp: true } }, sound_enabled: false };
await updateNotificationPreferences(payload);
expect(ensureCsrfCookie).toHaveBeenCalledOnce();
expect(apiClient.patch).toHaveBeenCalledWith('/api/auth/me/notification-preferences', payload);
});
});