Skip to content

Commit 2ef46a3

Browse files
committed
test: add ContributorsPage empty fallback edge case tests
1 parent 81d9f71 commit 2ef46a3

1 file changed

Lines changed: 127 additions & 0 deletions

File tree

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
2+
import { beforeEach, describe, expect, it, vi } from 'vitest';
3+
import { render, screen } from '@testing-library/react';
4+
import ContributorsPage from './page';
5+
6+
vi.mock('next/image', () => ({
7+
__esModule: true,
8+
default: (props: any) => <img {...props} />,
9+
}));
10+
11+
vi.mock('next/link', () => ({
12+
__esModule: true,
13+
default: ({ children, href, ...props }: any) => (
14+
<a href={href} {...props}>
15+
{children}
16+
</a>
17+
),
18+
}));
19+
20+
vi.mock('gsap', () => {
21+
const tween = { kill: vi.fn() };
22+
const mockGsap = {
23+
registerPlugin: vi.fn(),
24+
to: vi.fn().mockReturnValue(tween),
25+
fromTo: vi.fn().mockReturnValue(tween),
26+
set: vi.fn(),
27+
context: vi.fn((callback: any) => {
28+
if (typeof callback === 'function') {
29+
callback();
30+
}
31+
return { revert: vi.fn() };
32+
}),
33+
};
34+
return { default: mockGsap, gsap: mockGsap };
35+
});
36+
37+
vi.mock('gsap/ScrollTrigger', () => ({
38+
ScrollTrigger: {
39+
getAll: vi.fn(() => []),
40+
},
41+
}));
42+
43+
vi.mock('framer-motion', () => ({
44+
motion: {
45+
div: (props: any) => <div {...props}>{props.children}</div>,
46+
span: (props: any) => <span {...props}>{props.children}</span>,
47+
p: (props: any) => <p {...props}>{props.children}</p>,
48+
},
49+
AnimatePresence: ({ children }: any) => <>{children}</>,
50+
useMotionValue: (initial: any) => ({ current: initial, set: vi.fn() }),
51+
useSpring: (value: any) => value,
52+
useTransform: (value: any, fn: any) => fn(value.current ?? value),
53+
}));
54+
55+
describe('ContributorsPage empty fallback', () => {
56+
beforeEach(() => {
57+
vi.restoreAllMocks();
58+
59+
global.fetch = vi.fn(() =>
60+
Promise.resolve({
61+
ok: true,
62+
json: async () => [],
63+
})
64+
) as any;
65+
66+
window.HTMLElement.prototype.scrollIntoView = vi.fn();
67+
68+
if (!window.requestAnimationFrame) {
69+
window.requestAnimationFrame = (callback: FrameRequestCallback) =>
70+
setTimeout(callback, 0) as unknown as number;
71+
}
72+
});
73+
74+
it('renders fallback UI when contributors are empty', async () => {
75+
const element = await ContributorsPage();
76+
render(element);
77+
78+
expect(screen.getByText(/No architects found/i)).toBeTruthy();
79+
expect(screen.getByText(/0 of 0 contributors/i)).toBeTruthy();
80+
expect(screen.getByRole('heading', { name: /THE COLLECTIVE/i })).toBeTruthy();
81+
expect(screen.getByText(/READY TO BUILD\?/i)).toBeTruthy();
82+
});
83+
84+
it('maintains page layout and empty markers for empty contributor input', async () => {
85+
const element = await ContributorsPage();
86+
render(element);
87+
88+
expect(screen.getByRole('heading', { name: /THE VANGUARD/i })).toBeTruthy();
89+
expect(screen.getByRole('heading', { name: /THE COLLECTIVE/i })).toBeTruthy();
90+
expect(screen.getByText(/Explore The Elite/i)).toBeTruthy();
91+
expect(screen.queryByText(/View Profile/i)).toBeNull();
92+
});
93+
94+
it('handles fetch failures gracefully and still renders fallback state', async () => {
95+
global.fetch = vi.fn(() => Promise.reject(new Error('Network failure'))) as any;
96+
const element = await ContributorsPage();
97+
render(element);
98+
99+
expect(screen.getByText(/No architects found/i)).toBeTruthy();
100+
expect(screen.getByText(/0 of 0 contributors/i)).toBeTruthy();
101+
});
102+
103+
it('handles non-ok API responses without breaking the page', async () => {
104+
global.fetch = vi.fn(() =>
105+
Promise.resolve({
106+
ok: false,
107+
status: 500,
108+
headers: { get: vi.fn(() => null) },
109+
json: async () => [],
110+
})
111+
) as any;
112+
113+
const element = await ContributorsPage();
114+
render(element);
115+
116+
expect(screen.getByText(/No architects found/i)).toBeTruthy();
117+
expect(screen.getByText(/0 of 0 contributors/i)).toBeTruthy();
118+
});
119+
120+
it('does not emit console errors when the fallback page renders', async () => {
121+
const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
122+
const element = await ContributorsPage();
123+
render(element);
124+
125+
expect(errorSpy).not.toHaveBeenCalled();
126+
});
127+
});

0 commit comments

Comments
 (0)