import { cleanup, render, screen } from '@testing-library/react'; import { getFunctionName } from 'convex/server'; import { afterEach, describe, expect, it, vi } from 'vitest'; import { api } from '@spoon/backend/convex/_generated/api.js'; import { GithubIntegrationPanel } from '../../src/components/integrations/github-integration-panel'; const { mockUseAction, mockUseQuery } = vi.hoisted(() => ({ mockUseAction: vi.fn(), mockUseQuery: vi.fn(), })); vi.mock('convex/react', () => ({ useAction: mockUseAction, useQuery: mockUseQuery, })); vi.mock('sonner', () => ({ toast: { error: vi.fn(), success: vi.fn(), }, })); type ConnectionStatus = 'active' | 'needs_reauth' | 'revoked'; const setup = (status: ConnectionStatus) => { mockUseAction.mockReturnValue(vi.fn()); const connectionName = getFunctionName(api.github.getConnection); const installUrlName = getFunctionName(api.github.getInstallUrl); mockUseQuery.mockImplementation((ref: Parameters[0]) => { const name = getFunctionName(ref); if (name === connectionName) { return { _id: 'connection-1', displayName: 'octocat', installationId: '12345', status, }; } if (name === installUrlName) { return 'https://github.com/apps/spoon/installations/new'; } return undefined; }); }; afterEach(() => { cleanup(); vi.clearAllMocks(); }); describe('GithubIntegrationPanel', () => { it('shows the reconnect warning when the connection needs re-authorization', () => { setup('needs_reauth'); render(); expect( screen.getByText(/GitHub access needs re-authorization/i), ).toBeInTheDocument(); expect( screen.getByRole('link', { name: /reconnect github app/i }), ).toBeInTheDocument(); }); it('shows the removed-installation warning when the connection is revoked', () => { setup('revoked'); render(); expect( screen.getByText(/GitHub App installation removed/i), ).toBeInTheDocument(); expect( screen.getByRole('link', { name: /reconnect github app/i }), ).toBeInTheDocument(); }); it('renders the normal connected state without a warning when active', () => { setup('active'); render(); expect(screen.getByText('octocat')).toBeInTheDocument(); expect( screen.queryByText(/needs re-authorization/i), ).not.toBeInTheDocument(); expect( screen.queryByRole('link', { name: /reconnect github app/i }), ).not.toBeInTheDocument(); }); });