Files
portal/app/tests/Frontend/ProfileTab.spec.ts
T

109 lines
4.0 KiB
TypeScript
Raw Normal View History

import { describe, it, expect, beforeEach, vi } from 'vitest';
import { mount } from '@vue/test-utils';
import { createPinia, setActivePinia } from 'pinia';
import { createVuetify } from 'vuetify';
vi.mock('../../resources/js/api/auth', () => ({
updateProfile: vi.fn(),
}));
vi.mock('../../resources/js/api/client', () => ({
apiClient: {},
ensureCsrfCookie: vi.fn(),
extractValidationErrors: vi.fn(() => null),
extractErrorMessage: vi.fn((_e, fallback) => fallback ?? 'Произошла ошибка.'),
extractRateLimitRetry: vi.fn(() => null),
}));
import * as authApi from '../../resources/js/api/auth';
import ProfileTab from '../../resources/js/views/settings/ProfileTab.vue';
import { useAuthStore } from '../../resources/js/stores/auth';
import type { AuthUser } from '../../resources/js/api/auth';
const vuetify = createVuetify();
const mockUser: AuthUser = {
id: 1,
email: 'ivan@example.ru',
first_name: 'Иван',
last_name: 'Петров',
phone: '+7 916 000-00-00',
timezone: 'Europe/Moscow',
tenant_id: 1,
totp_enabled: false,
last_login_at: null,
};
const factory = (user: AuthUser | null = mockUser) => {
setActivePinia(createPinia());
const auth = useAuthStore();
auth.user = user;
return mount(ProfileTab, { global: { plugins: [vuetify] } });
};
describe('ProfileTab.vue', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('подставляет имя/фамилию/телефон/тайм-зону из auth-store', () => {
const wrapper = factory();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const vm = wrapper.vm as any;
expect(vm.firstName).toBe('Иван');
expect(vm.lastName).toBe('Петров');
expect(vm.phone).toBe('+7 916 000-00-00');
expect(vm.timezone).toBe('Europe/Moscow');
});
it('save() вызывает updateProfile с payload и показывает успех', async () => {
(authApi.updateProfile as ReturnType<typeof vi.fn>).mockResolvedValue({
...mockUser,
first_name: 'Пётр',
});
const wrapper = factory();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const vm = wrapper.vm as any;
vm.firstName = 'Пётр';
await vm.save();
expect(authApi.updateProfile).toHaveBeenCalledWith({
first_name: 'Пётр',
last_name: 'Петров',
phone: '+7 916 000-00-00',
timezone: 'Europe/Moscow',
});
expect(vm.saveSuccess).toBe(true);
expect(vm.saveError).toBe(null);
});
it('save() с пустым phone отправляет null', async () => {
(authApi.updateProfile as ReturnType<typeof vi.fn>).mockResolvedValue(mockUser);
const wrapper = factory();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const vm = wrapper.vm as any;
vm.phone = ' ';
await vm.save();
expect(authApi.updateProfile).toHaveBeenCalledWith(expect.objectContaining({ phone: null }));
});
it('save() показывает ошибку при reject', async () => {
(authApi.updateProfile as ReturnType<typeof vi.fn>).mockRejectedValue(new Error('boom'));
const wrapper = factory();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const vm = wrapper.vm as any;
await vm.save();
expect(vm.saveError).toBe('Не удалось сохранить профиль.');
expect(vm.saveSuccess).toBe(false);
expect(vm.saving).toBe(false);
});
it('resetForm() возвращает поля к значениям из store', async () => {
const wrapper = factory();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const vm = wrapper.vm as any;
vm.firstName = 'Изменено';
vm.resetForm();
expect(vm.firstName).toBe('Иван');
});
});