Skip to content

Commit 465f7cc

Browse files
authored
test(copyrepobutton): add error resilience coverage (JhaSourav07#3024)
## Description Fixes JhaSourav07#2808 Added error resilience test coverage for `app/components/CopyRepoButton.tsx`. ### Tests Added * Verifies the component renders successfully during initial mount. * Ensures the component does not crash when clipboard operations fail. * Confirms the original button label remains visible after clipboard failures. * Verifies the icon remains rendered during error scenarios. * Ensures repeated failed copy attempts do not crash the component. ## Pillar * [ ] 🎨 Pillar 1 — New Theme Design * [ ] 📐 Pillar 2 — Geometric SVG Improvement * [ ] 🕐 Pillar 3 — Timezone Logic Optimization * [x] 🛠️ Other (Bug fix, refactoring, docs) ## Visual Preview N/A (Test-only changes) ## Checklist before requesting a review: * [x] I have read the `CONTRIBUTING.md` file. * [x] I have tested these changes locally. * [ ] I have run `npm run format` and `npm run lint` locally and resolved all errors. * [x] My commits follow the Conventional Commits format. * [ ] I have updated `README.md` if I added a new theme or URL parameter. (Not applicable) * [x] I have starred the repo. * [x] I have made sure that I have only one commit to merge in this PR. * [ ] The SVG output matches the CommitPulse "premium quality" aesthetic standard. (Not applicable) * [ ] (Recommended) I joined the CommitPulse Discord community.
2 parents a403fa5 + aa75e22 commit 465f7cc

1 file changed

Lines changed: 88 additions & 0 deletions

File tree

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
2+
import { describe, expect, it, vi, beforeEach } from 'vitest';
3+
4+
import CopyRepoButton from './CopyRepoButton';
5+
6+
vi.mock('lucide-react', () => ({
7+
Copy: () => <svg data-testid="copy-icon" />,
8+
}));
9+
10+
describe('CopyRepoButton error resilience', () => {
11+
beforeEach(() => {
12+
vi.restoreAllMocks();
13+
});
14+
15+
it('renders successfully during initial mount', () => {
16+
render(<CopyRepoButton />);
17+
18+
expect(screen.getByRole('button', { name: /copy url/i })).toBeDefined();
19+
});
20+
21+
it('does not crash when clipboard write rejects', async () => {
22+
Object.assign(navigator, {
23+
clipboard: {
24+
writeText: vi.fn().mockRejectedValue(new Error('Clipboard failed')),
25+
},
26+
});
27+
28+
render(<CopyRepoButton />);
29+
30+
fireEvent.click(screen.getByRole('button'));
31+
32+
await waitFor(() => {
33+
expect(screen.getByRole('button')).toBeDefined();
34+
});
35+
});
36+
37+
it('keeps original label visible after clipboard failure', async () => {
38+
Object.assign(navigator, {
39+
clipboard: {
40+
writeText: vi.fn().mockRejectedValue(new Error('Clipboard failed')),
41+
},
42+
});
43+
44+
render(<CopyRepoButton />);
45+
46+
fireEvent.click(screen.getByRole('button'));
47+
48+
await waitFor(() => {
49+
expect(screen.getByText(/copy url/i)).toBeDefined();
50+
});
51+
});
52+
53+
it('renders icon even when copy action fails', async () => {
54+
Object.assign(navigator, {
55+
clipboard: {
56+
writeText: vi.fn().mockRejectedValue(new Error('Clipboard failed')),
57+
},
58+
});
59+
60+
render(<CopyRepoButton />);
61+
62+
fireEvent.click(screen.getByRole('button'));
63+
64+
await waitFor(() => {
65+
expect(screen.getByTestId('copy-icon')).toBeDefined();
66+
});
67+
});
68+
69+
it('allows repeated failed copy attempts without crashing', async () => {
70+
Object.assign(navigator, {
71+
clipboard: {
72+
writeText: vi.fn().mockRejectedValue(new Error('Clipboard failed')),
73+
},
74+
});
75+
76+
render(<CopyRepoButton />);
77+
78+
const button = screen.getByRole('button');
79+
80+
fireEvent.click(button);
81+
fireEvent.click(button);
82+
fireEvent.click(button);
83+
84+
await waitFor(() => {
85+
expect(screen.getByRole('button')).toBeDefined();
86+
});
87+
});
88+
});

0 commit comments

Comments
 (0)