Skip to content

Commit 862f942

Browse files
committed
test(contributors): add loading empty fallback coverage
1 parent a48d605 commit 862f942

1 file changed

Lines changed: 87 additions & 0 deletions

File tree

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import { render, screen } from '@testing-library/react';
2+
import { describe, expect, it } from 'vitest';
3+
import Loading from './loading';
4+
5+
function hasClasses(element: Element | null, classes: string[]) {
6+
expect(element).not.toBeNull();
7+
8+
for (const className of classes) {
9+
expect(element!.classList.contains(className)).toBe(true);
10+
}
11+
}
12+
13+
describe('Contributors loading empty fallback', () => {
14+
it('renders safely without props or input data', () => {
15+
expect(() => render(<Loading />)).not.toThrow();
16+
});
17+
18+
it('shows a clear fallback loading state', () => {
19+
render(<Loading />);
20+
21+
expect(screen.getByRole('status')).toBeTruthy();
22+
expect(screen.getByText('Loading the collective...')).toBeTruthy();
23+
expect(screen.getByText('Fetching contributor data from GitHub')).toBeTruthy();
24+
});
25+
26+
it('keeps accessible fallback markers available', () => {
27+
render(<Loading />);
28+
29+
const status = screen.getByRole('status');
30+
31+
expect(status.getAttribute('aria-live')).toBe('polite');
32+
expect(status.children.length).toBeGreaterThanOrEqual(2);
33+
});
34+
35+
it('maintains default fallback layout styles', () => {
36+
render(<Loading />);
37+
38+
const status = screen.getByRole('status');
39+
const page = status.parentElement;
40+
41+
hasClasses(page, [
42+
'flex',
43+
'min-h-screen',
44+
'items-center',
45+
'justify-center',
46+
'bg-[#050505]',
47+
'text-white',
48+
]);
49+
50+
hasClasses(status, ['flex', 'flex-col', 'items-center', 'gap-6']);
51+
});
52+
53+
it('renders fallback spinner structure without hydration-sensitive content', () => {
54+
render(<Loading />);
55+
56+
const status = screen.getByRole('status');
57+
const spinnerWrapper = status.firstElementChild;
58+
const spinner = spinnerWrapper?.firstElementChild ?? null;
59+
const glowOverlay = spinnerWrapper?.children.item(1) ?? null;
60+
61+
hasClasses(spinnerWrapper, ['relative']);
62+
63+
hasClasses(spinner, [
64+
'h-16',
65+
'w-16',
66+
'animate-spin',
67+
'rounded-full',
68+
'border-2',
69+
'border-white/10',
70+
'border-t-cyan-400',
71+
]);
72+
73+
hasClasses(glowOverlay, [
74+
'absolute',
75+
'inset-0',
76+
'h-16',
77+
'w-16',
78+
'rounded-full',
79+
'bg-cyan-400/20',
80+
'blur-xl',
81+
'animate-pulse',
82+
]);
83+
84+
expect(status.classList.contains('overflow-hidden')).toBe(false);
85+
expect(status.classList.contains('text-transparent')).toBe(false);
86+
});
87+
});

0 commit comments

Comments
 (0)