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('содержит ровно 8 nav-tabs', () => { const wrapper = factory(); const items = wrapper.findAll('.tabs-rail .v-list-item'); expect(items.length).toBe(8); }); it('содержит все 8 названий вкладок', () => { const wrapper = factory(); const text = wrapper.text(); const labels = [ 'Профиль', 'Безопасность', 'Проекты', 'Команда', 'API и Webhook', 'Интеграции', 'Тихие часы', 'Уведомления', ]; labels.forEach((l) => expect(text).toContain(l)); }); it('по умолчанию показывает вкладку «Профиль»', () => { const wrapper = factory(); const text = wrapper.text(); // ProfileTab содержит «Полное имя» и поле email. expect(text).toContain('Полное имя'); expect(text).toContain('Тайм-зона'); }); it('placeholder-вкладки показывают «В разработке»', async () => { const wrapper = factory(); // Кликаем по «Проекты» — placeholder-вкладка. const items = wrapper.findAll('.tabs-rail .v-list-item'); const projectsItem = items.find((i) => i.text().includes('Проекты')); expect(projectsItem).toBeDefined(); await projectsItem!.trigger('click'); await wrapper.vm.$nextTick(); expect(wrapper.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'); }); });