import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' import { render, screen } from '@testing-library/react' import { I18nProvider } from '../i18n' import { FederatedStatusCard } from './FederatedStatusCard' import * as ai from '../api/ai' vi.mock('../api/ai') const status: ai.FederatedStatus = { client_type: 'SYNTHETIC_SERVER_SIMULATION', real_device_training: 'NOT_IMPLEMENTED', native_local_only_training: 'NOT_IMPLEMENTED', real_user_data_used: false, federation: 'SIMULATED', secure_aggregation: 'DESIGN_ONLY', differential_privacy: 'SIMULATED', differential_privacy_detail: { differential_privacy: 'SIMULATED', budget_exhausted: true, candidate_privacy_eligibility: 'ineligible', cumulative_epsilon: 38.76, budget_epsilon: 8, production_privacy_guarantee: false, note: 'simulated only', }, automatic_model_promotion: false, affects_payment_authorization: false, candidate_status: 'candidate', candidate_promotable: false, disclaimer: 'Server-side simulation using synthetic clients; not real cross-device federated learning.', label: 'SIMULATED', aggregators: ['coordinate_median', 'fedavg', 'trimmed_mean'], } const renderCard = (detailed = false) => render() describe('FederatedStatusCard', () => { beforeEach(() => { vi.spyOn(ai, 'federatedStatus').mockResolvedValue(status) }) afterEach(() => vi.restoreAllMocks()) it('reports synthetic server simulation + design-only + not-implemented labels', async () => { renderCard() expect(await screen.findByTestId('fed-label-client_type')).toHaveTextContent('SYNTHETIC_SERVER_SIMULATION') expect(screen.getByTestId('fed-label-secure_aggregation')).toHaveTextContent('DESIGN_ONLY') expect(screen.getByTestId('fed-label-real_device_training')).toHaveTextContent('NOT_IMPLEMENTED') expect(screen.getByTestId('fed-label-native_local_only_training')).toHaveTextContent('NOT_IMPLEMENTED') }) it('surfaces the exhausted simulated DP budget as a warning', async () => { renderCard() expect(await screen.findByTestId('dp-exhausted')).toHaveTextContent(/budget is exhausted/i) expect(screen.getByTestId('dp-exhausted')).toHaveTextContent(/not a production privacy guarantee/i) }) it('never claims data stays on the device', async () => { const { container } = renderCard(true) await screen.findByTestId('federated-status') expect(container.textContent).not.toMatch(/stays (only )?on your (phone|device)/i) expect(container.textContent).not.toMatch(/never leaves your device/i) }) it('detailed mode states the candidate is not promotable and clients are synthetic', async () => { renderCard(true) expect(await screen.findByTestId('fed-not-promotable')).toHaveTextContent(/not promotable/i) expect(screen.getByTestId('fed-synthetic')).toHaveTextContent(/no real user data is used/i) }) })