// FE-MOB-SETINT-001 onwards import { describe, it, expect, vi, beforeEach } from 'vitest'; import { render, screen } from '../../../helpers/render'; import { resetAllStores, seedStore } from '../../../helpers/store'; import { useAddonStore } from '../../../../src/store/addonStore'; import MSettingsIntegrations from '../../../../src/mobile/screens/settings/MSettingsIntegrations'; // The four sections are covered by their own suites — stub them so this file // only exercises the addon gating and the initial loadAddons call. vi.mock('../../../../src/mobile/screens/settings/MPhotoProvidersSection', () => ({ default: () =>
, })); vi.mock('../../../../src/mobile/screens/settings/MAirTrailConnectionSection', () => ({ default: () =>
, })); vi.mock('../../../../src/mobile/screens/settings/MLlmConnectionSection', () => ({ default: () =>
, })); vi.mock('../../../../src/mobile/screens/settings/MSettingsMcp', () => ({ default: () =>
, })); function seedAddons(ids: string[], loadAddons = vi.fn().mockResolvedValue(undefined)) { seedStore(useAddonStore, { addons: ids.map((id) => ({ id, name: id, type: 'integration', icon: '', enabled: true })), loaded: true, loadAddons, }); return loadAddons; } describe('MSettingsIntegrations', () => { beforeEach(() => { resetAllStores(); }); it('FE-MOB-SETINT-001: only the photo providers render when no integration addon is on', () => { seedAddons([]); render(); expect(screen.getByTestId('photo-providers')).toBeInTheDocument(); expect(screen.queryByTestId('airtrail')).not.toBeInTheDocument(); expect(screen.queryByTestId('llm')).not.toBeInTheDocument(); expect(screen.queryByTestId('mcp')).not.toBeInTheDocument(); }); it('FE-MOB-SETINT-002: the airtrail addon reveals the AirTrail connection section', () => { seedAddons(['airtrail']); render(); expect(screen.getByTestId('airtrail')).toBeInTheDocument(); expect(screen.queryByTestId('llm')).not.toBeInTheDocument(); }); it('FE-MOB-SETINT-003: the llm_parsing addon reveals the AI connection section', () => { seedAddons(['llm_parsing']); render(); expect(screen.getByTestId('llm')).toBeInTheDocument(); expect(screen.queryByTestId('airtrail')).not.toBeInTheDocument(); }); it('FE-MOB-SETINT-004: the mcp addon reveals the MCP configuration', () => { seedAddons(['mcp']); render(); expect(screen.getByTestId('mcp')).toBeInTheDocument(); }); it('FE-MOB-SETINT-005: all three sections render together when every addon is on', () => { seedAddons(['airtrail', 'llm_parsing', 'mcp']); render(); expect(screen.getByTestId('airtrail')).toBeInTheDocument(); expect(screen.getByTestId('llm')).toBeInTheDocument(); expect(screen.getByTestId('mcp')).toBeInTheDocument(); }); it('FE-MOB-SETINT-006: a disabled addon row does not unlock its section', () => { seedStore(useAddonStore, { addons: [{ id: 'mcp', name: 'MCP', type: 'integration', icon: '', enabled: false }], loaded: true, loadAddons: vi.fn().mockResolvedValue(undefined), }); render(); expect(screen.queryByTestId('mcp')).not.toBeInTheDocument(); }); it('FE-MOB-SETINT-007: the addon list is refreshed once on mount', () => { const loadAddons = seedAddons([]); const { rerender } = render(); rerender(); expect(loadAddons).toHaveBeenCalledTimes(1); }); });