import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { render, screen, waitFor } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { EmailVerificationBanner } from '../EmailVerificationBanner' import { useAuthStore } from '@/store/authStore' import { authApi } from '@/api/auth' import type { User } from '@/types' vi.mock('@/api/auth', () => ({ authApi: { getVerificationStatus: vi.fn(), sendVerificationEmail: vi.fn(), }, })) vi.mock('@/lib/toast', () => ({ toast: { success: vi.fn(), error: vi.fn(), }, })) function makeUser(overrides: Partial = {}): User { return { id: 'user-1', email: 'test@example.com', name: 'Test User', role: 'engineer', is_super_admin: false, is_active: true, must_change_password: false, account_id: 'acct-1', account_role: 'engineer', team_id: null, created_at: '2026-05-01T00:00:00Z', last_login: null, phone: null, job_title: null, timezone: 'UTC', avatar_url: null, email_verified_at: null, ...overrides, } } const FROZEN_NOW = new Date('2026-05-06T00:00:00Z') describe('EmailVerificationBanner', () => { beforeEach(() => { vi.useFakeTimers({ shouldAdvanceTime: true }) vi.setSystemTime(FROZEN_NOW) useAuthStore.setState({ user: null, token: null, isAuthenticated: false }) vi.mocked(authApi.getVerificationStatus).mockResolvedValue({ enabled: true, }) vi.mocked(authApi.sendVerificationEmail).mockResolvedValue(undefined) }) afterEach(() => { vi.useRealTimers() vi.clearAllMocks() }) it('hides past grace day-7+', async () => { // Created 8 days before frozen now -> elapsed=8, > grace=6. useAuthStore.setState({ user: makeUser({ created_at: '2026-04-28T00:00:00Z' }), }) const { container } = render() // Wait long enough for any pending verification-status fetch to resolve. await waitFor(() => { expect(authApi.getVerificationStatus).toHaveBeenCalled() }) expect( screen.queryByTestId('email-verification-banner'), ).not.toBeInTheDocument() expect(container.firstChild).toBeNull() }) it('renders within the grace window', async () => { // Created 1 day before frozen now -> elapsed=1, within grace. useAuthStore.setState({ user: makeUser({ created_at: '2026-05-05T00:00:00Z' }), }) render() await waitFor(() => { expect( screen.getByTestId('email-verification-banner'), ).toBeInTheDocument() }) }) it('resend triggers API call', async () => { useAuthStore.setState({ user: makeUser({ created_at: '2026-05-05T00:00:00Z' }), }) render() await waitFor(() => { expect( screen.getByTestId('email-verification-banner'), ).toBeInTheDocument() }) const user = userEvent.setup({ advanceTimers: vi.advanceTimersByTime }) await user.click(screen.getByTestId('banner-resend-button')) await waitFor(() => { expect(authApi.sendVerificationEmail).toHaveBeenCalledTimes(1) }) }) })