import { describe, it, expect } from 'vitest'; import { mount } from '@vue/test-utils'; import { createPinia } from 'pinia'; import { createVuetify } from 'vuetify'; import SettingsView from '../../resources/js/views/SettingsView.vue'; describe('SettingsView.vue', () => { const factory = () => mount(SettingsView, { global: { plugins: [createPinia(), createVuetify()] }, }); it('монтируется и содержит заголовок «Настройки»', () => { const wrapper = factory(); expect(wrapper.find('h1').text()).toBe('Настройки'); }); it('содержит ровно 4 nav-tabs (placeholder-вкладки убраны, audit D6/D7)', () => { const wrapper = factory(); const items = wrapper.findAll('.tabs-rail .v-list-item'); expect(items.length).toBe(4); }); it('содержит все 4 названия рабочих вкладок', () => { const wrapper = factory(); const text = wrapper.text(); const labels = ['Профиль', 'Безопасность', 'API и Webhook', 'Уведомления']; labels.forEach((l) => expect(text).toContain(l)); }); it('не содержит placeholder-вкладок и текста «В разработке»', () => { const wrapper = factory(); const railText = wrapper.find('.tabs-rail').text(); ['Команда', 'Интеграции', 'Тихие часы'].forEach((l) => expect(railText).not.toContain(l)); expect(wrapper.text()).not.toContain('В разработке'); }); it('по умолчанию показывает вкладку «Профиль»', () => { const wrapper = factory(); const text = wrapper.text(); // ProfileTab содержит поля Имя / Фамилия (split из «Полное имя» в audit D1) и Тайм-зона. expect(text).toContain('Имя'); expect(text).toContain('Фамилия'); expect(text).toContain('Тайм-зона'); }); it('переключение на «Уведомления» показывает матрицу 8×3', async () => { const wrapper = factory(); const items = wrapper.findAll('.tabs-rail .v-list-item'); const notifItem = items.find((i) => i.text().includes('Уведомления')); await notifItem!.trigger('click'); await wrapper.vm.$nextTick(); const text = wrapper.text(); expect(text).toContain('События × каналы'); // 8 типов событий из schema users.notification_preferences. ['Новый лид', 'Напоминание', 'Низкий баланс', 'Нулевой баланс', 'Анонсы и промо'].forEach((e) => expect(text).toContain(e), ); }); it('переключение на «Безопасность» показывает 2FA и сессии', async () => { const wrapper = factory(); const items = wrapper.findAll('.tabs-rail .v-list-item'); const secItem = items.find((i) => i.text().includes('Безопасность')); await secItem!.trigger('click'); await wrapper.vm.$nextTick(); const text = wrapper.text(); expect(text).toContain('Двухфакторная авторизация'); expect(text).toContain('Активные сессии'); }); it('переключение на «API и Webhook» показывает API-ключ и signing secret', async () => { const wrapper = factory(); const items = wrapper.findAll('.tabs-rail .v-list-item'); const apiItem = items.find((i) => i.text().includes('API')); await apiItem!.trigger('click'); await wrapper.vm.$nextTick(); const text = wrapper.text(); expect(text).toContain('API-ключ'); expect(text).toContain('Signing secret'); expect(text).toContain('HMAC'); }); });