amanpay / web /src /components /FederatedStatusCard.test.tsx
MHamdan's picture
CI deploy d3d1cf1
0f4d9ea verified
Raw
History Blame Contribute Delete
2.96 kB
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(<I18nProvider initial="en"><FederatedStatusCard detailed={detailed} /></I18nProvider>)
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)
})
})