Files
spoon/apps/next/tests/component/dashboard-loading.test.tsx
T

73 lines
2.1 KiB
TypeScript

import { cleanup, render, screen } from '@testing-library/react';
import { afterEach, describe, expect, it, vi } from 'vitest';
import DashboardPage from '../../src/app/(app)/dashboard/page';
const { mockUseQuery } = vi.hoisted(() => ({
mockUseQuery: vi.fn(),
}));
vi.mock('convex/react', () => ({
useConvexAuth: () => ({ isAuthenticated: false }),
useMutation: vi.fn(),
useQuery: mockUseQuery,
}));
vi.mock('next/navigation', () => ({
useParams: vi.fn(),
useRouter: () => ({ push: vi.fn(), replace: vi.fn() }),
useSearchParams: () => new URLSearchParams(),
}));
describe('dashboard loading vs empty state', () => {
afterEach(() => {
cleanup();
mockUseQuery.mockReset();
});
it('shows skeletons while queries are loading (undefined)', () => {
mockUseQuery.mockReturnValue(undefined);
render(<DashboardPage />);
expect(screen.getAllByTestId('list-skeleton').length).toBeGreaterThan(0);
expect(screen.queryByText('No Spoons yet')).not.toBeInTheDocument();
});
it('shows empty states once loaded with no data ([])', () => {
mockUseQuery.mockReturnValue([]);
render(<DashboardPage />);
expect(screen.queryByTestId('list-skeleton')).not.toBeInTheDocument();
expect(screen.getByText('No Spoons yet')).toBeInTheDocument();
});
it('renders data once loaded with items', () => {
mockUseQuery.mockImplementation((_query, args) => {
// spoons list has an empty args object ({}); recent syncRuns/threads pass limits.
if (args && 'limit' in args) return [];
return [
{
_id: 'spoon-1',
name: 'useSend',
upstreamOwner: 'acme',
upstreamRepo: 'app',
status: 'active',
syncCadence: 'daily',
effectiveUpstreamAheadBy: 0,
rawUpstreamAheadBy: 0,
forkAheadBy: 0,
ignoredUpstreamCount: 0,
},
];
});
render(<DashboardPage />);
expect(screen.getByText('useSend')).toBeInTheDocument();
expect(screen.queryByTestId('list-skeleton')).not.toBeInTheDocument();
expect(screen.queryByText('No Spoons yet')).not.toBeInTheDocument();
});
});