Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions src/components/error/ErrorFallback.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* Uses paint daube icons for brand consistency.
*/

import { Alert, Pressable, View } from 'react-native';
import { Alert, Linking, Pressable, View } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { ErrorIcon } from '@/components/icons';
import { Container, VStack } from '@/components/layout';
Expand Down Expand Up @@ -37,8 +37,18 @@ export function ErrorFallback({
if (onReportIssue) {
onReportIssue();
} else {
// TODO: Implement proper issue reporting (e.g., open GitHub issues URL)
Alert.alert('Report Issue', 'Issue reporting will be available in a future update.');
const issueTitle = encodeURIComponent(
`[Bug] Error Report: ${error?.name || 'Unknown Error'}`
);
const issueBody = encodeURIComponent(
`**Error Details**\nMessage: ${error?.message || 'No message'}\n\n**Component Stack**\n\`\`\`\n${componentStack || 'No stack trace'}\n\`\`\``
);
const url = `https://github.com/agentic-dev-library/thumbcode/issues/new?title=${issueTitle}&body=${issueBody}`;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To improve maintainability and reusability, it's better to avoid hardcoding the GitHub repository URL. Consider extracting it into a constant, preferably at the module level. This makes it easier to find and update if the repository URL changes.

Please define GITHUB_ISSUES_URL at the module level, for example:

const GITHUB_ISSUES_URL = 'https://github.com/agentic-dev-library/thumbcode/issues/new';
Suggested change
const url = `https://github.com/agentic-dev-library/thumbcode/issues/new?title=${issueTitle}&body=${issueBody}`;
const url = `${GITHUB_ISSUES_URL}?title=${issueTitle}&body=${issueBody}`;


Linking.openURL(url).catch((err) => {
console.error('Failed to open issue URL:', err);
Alert.alert('Report Issue', 'Could not open GitHub issues page.');
});
}
};

Expand All @@ -58,7 +68,13 @@ export function ErrorFallback({
</View>

{/* Error Title */}
<Text size="xl" weight="bold" className="text-white text-center font-display">
<Text
size="xl"
weight="bold"
className="text-white text-center font-display"
testID="error-title"
accessibilityRole="header"
>
{title}
</Text>

Expand Down Expand Up @@ -96,7 +112,7 @@ export function ErrorFallback({
)}

{/* Secondary Action */}
<Pressable className="py-2" onPress={handleReportIssue}>
<Pressable className="py-2" onPress={handleReportIssue} testID="report-issue-button">
<Text size="sm" className="text-teal-500">
Report Issue
</Text>
Comment on lines +115 to 118
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Read the ErrorFallback component to understand the full context
cat -n src/components/error/ErrorFallback.tsx

Repository: agentic-dev-library/thumbcode

Length of output: 5870


🏁 Script executed:

# Check for other accessibility patterns in the codebase for consistency
rg -t tsx -t ts "accessibilityRole|accessibilityLabel|accessibilityHint" --max-count 10 -A 2

Repository: agentic-dev-library/thumbcode

Length of output: 100


🏁 Script executed:

# Search for other Pressable components with accessibility attributes
rg "Pressable" -A 3 src/components/ | grep -A 2 "accessibility"

Repository: agentic-dev-library/thumbcode

Length of output: 1234


🏁 Script executed:

# Check if there are any existing button or pressable components with accessibility patterns
fd "\.tsx$" src/components | xargs grep -l "accessibilityRole.*button"

Repository: agentic-dev-library/thumbcode

Length of output: 461


🏁 Script executed:

# Look at a specific example to understand the pattern better
cat -n src/components/feedback/Modal.tsx | head -50 | tail -30

Repository: agentic-dev-library/thumbcode

Length of output: 876


🏁 Script executed:

# Check the exact format used in one of the files with good accessibility patterns
rg -B 2 -A 5 'accessibilityRole="button"' src/components/chat/ThreadList.tsx | head -20

Repository: agentic-dev-library/thumbcode

Length of output: 908


Add accessibility attributes to the "Report Issue" button.

Interactive elements should expose roles and labels for screen readers. The codebase uses a consistent pattern with accessibilityRole, accessibilityLabel, and accessibilityHint (see ThreadList.tsx, Modal.tsx for examples).

♿ Suggested accessibility props
-          <Pressable className="py-2" onPress={handleReportIssue} testID="report-issue-button">
+          <Pressable
+            className="py-2"
+            onPress={handleReportIssue}
+            testID="report-issue-button"
+            accessibilityRole="button"
+            accessibilityLabel="Report issue"
+            accessibilityHint="Opens the GitHub issue form in your browser"
+          >
🤖 Prompt for AI Agents
In `@src/components/error/ErrorFallback.tsx` around lines 115 - 118, The Pressable
used for the Report Issue action (Pressable with testID "report-issue-button"
and onPress handler handleReportIssue) is missing accessibility props; update
that Pressable to include accessibilityRole="button", a clear accessibilityLabel
(e.g., "Report issue"), and an accessibilityHint that describes the action
(e.g., "Opens the issue reporting form"), matching the pattern used in
ThreadList.tsx/Modal.tsx so screen readers can identify and describe the
control.

Expand Down
14 changes: 14 additions & 0 deletions src/components/error/__tests__/ErrorFallback.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { render } from '@testing-library/react-native';
import { ErrorFallback } from '../ErrorFallback';

// Mock Linking
jest.mock('react-native/Libraries/Linking/Linking', () => ({
openURL: jest.fn(),
}));

describe('ErrorFallback', () => {
it('renders without crashing', () => {
render(<ErrorFallback error={new Error('Test error')} componentStack="Test stack" />);
// Note: detailed UI element queries are skipped due to test environment issues with jest-expo/react-native-web
});
Comment on lines +10 to +13
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current smoke test is a good start. However, it can be improved to assert that the component renders correctly by checking for an element. More importantly, a new test should be added to simulate a press on the 'Report Issue' button and verify that Linking.openURL is called with the correct URL. This ensures the main feature of this PR is tested.

Note: You will need to add import { fireEvent } from '@testing-library/react-native'; and import { Linking } from 'react-native'; for the suggestion to work.

  it('renders without crashing and displays title', () => {
    const { getByTestId } = render(
      <ErrorFallback error={new Error('Test error')} componentStack="Test stack" />
    );
    expect(getByTestId('error-title')).toBeTruthy();
  });

  it('opens GitHub issue URL when "Report Issue" is pressed', () => {
    const error = new Error('Test error message');
    error.name = 'TestErrorName';
    const componentStack = 'Test component stack';
    const { getByTestId } = render(
      <ErrorFallback error={error} componentStack={componentStack} />
    );

    fireEvent.press(getByTestId('report-issue-button'));

    const issueTitle = encodeURIComponent(`[Bug] Error Report: ${error.name}`);
    const issueBody = encodeURIComponent(
      `**Error Details**\nMessage: ${error.message}\n\n**Component Stack**\n\`\`\`\n${componentStack}\n\`\`\``
    );
    const expectedUrl = `https://github.com/agentic-dev-library/thumbcode/issues/new?title=${issueTitle}&body=${issueBody}`;

    expect(Linking.openURL).toHaveBeenCalledWith(expectedUrl);
  });

});
Loading