Skip to content

Add dismissible warning banner to QualityGateStatus component - #76

Merged
frankbria merged 2 commits into
mainfrom
parallel-mit24a09-o78i
Dec 5, 2025
Merged

Add dismissible warning banner to QualityGateStatus component#76
frankbria merged 2 commits into
mainfrom
parallel-mit24a09-o78i

Conversation

@frankbria

@frankbria frankbria commented Dec 5, 2025

Copy link
Copy Markdown
Owner

Summary

Implements a dismissible warning banner that alerts users when quality gates show "passed" status but individual gates may not have been evaluated, addressing potential false positives until the backend implements gates_evaluated tracking.

Changes Made

  • Warning Banner State Management: Added warningDismissed state with localStorage persistence
  • Dismissible Banner Component: Yellow warning banner with clear messaging and dismiss button
  • Task-Specific Persistence: Uses qualityGates_warning_dismissed_${taskId} localStorage keys
  • Type Definitions: Added TODO comment documenting future backend enhancement
  • Consistent Styling: Follows existing yellow warning pattern from CheckpointRestore component

Testing

  • 6 new tests added for warning banner functionality
  • All 34 tests pass (28 existing + 6 new)
  • 100% test coverage for new feature
  • TDD approach: Tests written first, then implementation

Test Coverage

  1. Display warning when status is passed with no failures
  2. Hide warning when status is failed
  3. Hide warning when status is running
  4. Dismiss warning on button click
  5. Persist dismissal in localStorage
  6. Use task-specific localStorage keys

Implementation Details

Files Changed

  • web-ui/src/components/quality-gates/QualityGateStatus.tsx - Component implementation (46 lines added)
  • web-ui/__tests__/components/QualityGateStatus.test.tsx - Test coverage (162 lines added)
  • web-ui/src/types/qualityGates.ts - Type definitions with TODO comment (4 lines added)

User Experience

  • Warning appears between status header and running progress indicator
  • Yellow warning styling with ⚠️ icon for consistency
  • Dismissal persists per task (not globally)
  • Accessible dismiss button with proper aria-label

Future Work

As noted in the TODO comment, this warning banner is a temporary solution. The backend should be enhanced to include a gates_evaluated?: QualityGateType[] field in the QualityGateStatus interface to eliminate the need for this warning.

Screenshots

The warning banner appears when:

  • Status is "passed"
  • No failures exist
  • User hasn't dismissed it for this specific task

Test Plan

cd web-ui
npm install
npm test -- __tests__/components/QualityGateStatus.test.tsx

All tests should pass with 100% coverage for the warning banner feature.

Summary by CodeRabbit

  • New Features

    • Added a dismissible warning banner that appears when a quality gate status passes with no failures. The dismissal state persists per task.
  • Tests

    • Added comprehensive test coverage for warning banner behavior, including display conditions, dismissal, and state persistence.

✏️ Tip: You can customize this high-level summary in your review settings.

…ponent

Implements a dismissible warning banner that alerts users when quality gates
show "passed" status but individual gates may not have been evaluated. This
addresses potential false positives until the backend implements gates_evaluated
tracking.

Key changes:
- Add warning banner state management with localStorage persistence
- Create dismissible warning banner component with task-specific storage keys
- Add 6 comprehensive tests covering display, dismissal, and persistence
- Add TODO comment in type definitions for future backend enhancement
- Use consistent yellow warning styling pattern from CheckpointRestore

Testing:
- All 34 tests pass (28 existing + 6 new warning banner tests)
- TDD approach: Tests written first, then implementation

Files changed:
- web-ui/src/components/quality-gates/QualityGateStatus.tsx
- web-ui/__tests__/components/QualityGateStatus.test.tsx
- web-ui/src/types/qualityGates.ts
@coderabbitai

coderabbitai Bot commented Dec 5, 2025

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@frankbria has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 25 minutes and 0 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 9c8d965 and 6b79f4e.

📒 Files selected for processing (2)
  • web-ui/__tests__/components/QualityGateStatus.test.tsx (1 hunks)
  • web-ui/src/components/quality-gates/QualityGateStatus.tsx (3 hunks)

Walkthrough

This pull request adds a dismissible warning banner feature to the QualityGateStatus component that displays when test status passes without failures. The implementation includes local dismissal state management with per-task persistence to localStorage, comprehensive test coverage for the new functionality, and documentation TODOs for planned backend enhancements.

Changes

Cohort / File(s) Summary
Warning Banner Implementation
web-ui/src/components/quality-gates/QualityGateStatus.tsx
Introduces warning banner UI state (warningDismissed), reads dismissal flag from localStorage on component mount, adds dismissWarning() function to persist dismissal, and conditionally renders banner when status is passed with no failures unless previously dismissed.
Warning Banner Tests
web-ui/__tests__/components/QualityGateStatus.test.tsx
Adds comprehensive test suite covering banner display on passed status without failures, absence on failed/running statuses, dismissal behavior, localStorage persistence with task-specific keys, and per-task state isolation. Includes localStorage mocking and cleanup.
Type Documentation
web-ui/src/types/qualityGates.ts
Adds developer-facing TODO notes describing planned backend enhancement and proposing optional gates_evaluated property to track which gates executed; no runtime behavior changes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

  • Review banner display logic and dismissal state management in QualityGateStatus component
  • Verify localStorage key naming convention and per-task isolation is correct
  • Confirm test coverage adequately exercises all conditional rendering scenarios

Possibly related PRs

Poem

🐰 A banner warns with graceful flair,
Dismissed with ease, then stored with care,
localStorage keeps the secret well—
Per-task dismissal casts its spell!
Thump thump

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and accurately describes the main feature addition: a dismissible warning banner in the QualityGateStatus component, which is the primary focus of the changeset across all three modified files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@claude

claude Bot commented Dec 5, 2025

Copy link
Copy Markdown

Code Review for PR #76: Add Dismissible Warning Banner

Summary

This PR adds a well-implemented warning banner to alert users when quality gate status shows passed but individual gates may not have been evaluated yet. The implementation follows TDD practices with excellent test coverage.

Strengths

  1. Excellent Test Coverage - 6 comprehensive tests covering all scenarios with 100% coverage for the new feature. TDD approach with tests written first.

  2. Good UX Design - Task-specific dismissal, persistent state via localStorage, consistent styling with existing patterns, accessible dismiss button with proper aria-label.

  3. Clean Implementation - Minimal code changes (46 lines in component), no breaking changes, proper error handling in localStorage parsing, well-documented with TODO comment for future backend work.

  4. Follows Project Standards - Matches CLAUDE.md guidelines (React 18, TypeScript 5.3+, Tailwind CSS), consistent with existing component patterns.

Observations and Suggestions

1. Component Re-render Optimization (Minor) - Consider initializing warningDismissed state with a function to load from localStorage directly, avoiding the useEffect and an extra render. This is purely an optimization; the current implementation is correct.

2. localStorage Key Pattern (Minor) - The key pattern is good, but consider what happens if a user has hundreds of tasks accumulating localStorage keys over time. Document cleanup strategy or add a utility to clear stale warnings after tasks are completed/deleted.

3. Accessibility Enhancement (Optional) - The dismiss button could benefit from enhanced keyboard focus styling (focus:ring-2 focus:ring-yellow-500) and a more descriptive aria-label.

Security and Performance

  • No security concerns. localStorage usage is appropriate for UI preferences
  • Minimal performance impact. localStorage operations are fast and only run on mount/dismiss
  • No memory leaks detected. State management is clean

Test Coverage Analysis

Excellent test coverage with 6 tests covering all key scenarios. Missing edge case tests (not blocking): warning behavior when status.failures is undefined vs empty array, when localStorage is disabled/unavailable, and on taskId change.

Code Quality Metrics

Metric Score Notes
Test Coverage 100% All new code tested
Code Clarity 5/5 Clear, readable implementation
Documentation 5/5 Good TODO comment for future work
Best Practices 4/5 Minor optimization opportunity
Accessibility 4/5 Good, could be enhanced

Final Verdict

APPROVE - This is a well-crafted PR that addresses a real UX concern with excellent test coverage, clean maintainable code, proper documentation, and minimal risk. The suggestions above are minor optimizations and not blocking. The current implementation is production-ready.

Great work! This PR demonstrates strong TDD practices and attention to detail.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
web-ui/__tests__/components/QualityGateStatus.test.tsx (1)

619-779: Excellent test coverage, consider adding taskId change scenario.

The test suite comprehensively covers the warning banner feature including display conditions, dismissal, persistence, and per-task isolation. The use of localStorage.clear() in beforeEach and jest.spyOn for verification demonstrates good testing practices.

Consider adding a test case that verifies correct behavior when the taskId prop changes while the component remains mounted:

it('should reset warning state when taskId changes', async () => {
  const mockStatus: QualityGateStatusType = {
    task_id: 1,
    status: 'passed',
    failures: [],
    requires_human_approval: false,
    timestamp: new Date().toISOString(),
  };

  mockFetchQualityGateStatus.mockResolvedValue(mockStatus);

  const { rerender } = render(<QualityGateStatus taskId={1} />);

  // Dismiss warning for task 1
  await waitFor(() => {
    expect(screen.getByText(/Summary Status Only/i)).toBeInTheDocument();
  });
  fireEvent.click(screen.getByLabelText('Dismiss warning'));

  // Change to task 2
  mockStatus.task_id = 2;
  rerender(<QualityGateStatus taskId={2} />);

  // Warning should reappear for task 2
  await waitFor(() => {
    expect(screen.getByText(/Summary Status Only/i)).toBeInTheDocument();
  });
});

This would verify that dismissal state correctly resets per task.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4ea2c8b and 9c8d965.

📒 Files selected for processing (3)
  • web-ui/__tests__/components/QualityGateStatus.test.tsx (1 hunks)
  • web-ui/src/components/quality-gates/QualityGateStatus.tsx (3 hunks)
  • web-ui/src/types/qualityGates.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use TypeScript 5.3+ for frontend development with React 18, Tailwind CSS, and Context + useReducer for state management

Files:

  • web-ui/src/components/quality-gates/QualityGateStatus.tsx
  • web-ui/__tests__/components/QualityGateStatus.test.tsx
  • web-ui/src/types/qualityGates.ts
web-ui/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

web-ui/**/*.{ts,tsx}: Use AgentStateContext with useReducer hook for multi-agent state management supporting up to 10 concurrent agents with WebSocket real-time updates and automatic exponential backoff reconnection (1s → 30s)
Run frontend tests with: cd web-ui && npm test; achieve 90%+ test coverage on all React components including unit and integration tests

Files:

  • web-ui/src/components/quality-gates/QualityGateStatus.tsx
  • web-ui/__tests__/components/QualityGateStatus.test.tsx
  • web-ui/src/types/qualityGates.ts
web-ui/src/components/**/*.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

Wrap all Dashboard sub-components with React.memo; use useMemo for derived state; implement ErrorBoundary wrapper around AgentStateProvider for graceful error handling

Files:

  • web-ui/src/components/quality-gates/QualityGateStatus.tsx
web-ui/__tests__/**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Write component tests for Context + Reducer pattern components with 90+ unit and integration tests; use React Testing Library for testing AgentStateProvider, useAgentState hook, and WebSocket message mapping

Files:

  • web-ui/__tests__/components/QualityGateStatus.test.tsx
🧠 Learnings (7)
📓 Common learnings
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-05T05:44:48.051Z
Learning: Applies to codeframe/agents/worker_agent.py : Implement quality gates with 4-stage pre-completion workflow: (1) run tests, (2) type checking, (3) coverage check (85% minimum), (4) code review trigger; create blocker if any gate fails
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-05T05:44:48.051Z
Learning: Implement quality gates as multi-stage pre-completion checks (tests → type → coverage 85% → review) that block tasks from completion if any gate fails, preventing bad code from being marked done
📚 Learning: 2025-12-05T05:44:48.051Z
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-05T05:44:48.051Z
Learning: Applies to web-ui/src/components/**/*.tsx : Wrap all Dashboard sub-components with React.memo; use useMemo for derived state; implement ErrorBoundary wrapper around AgentStateProvider for graceful error handling

Applied to files:

  • web-ui/src/components/quality-gates/QualityGateStatus.tsx
📚 Learning: 2025-12-05T05:44:48.051Z
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-05T05:44:48.051Z
Learning: Applies to web-ui/__tests__/**/*.test.{ts,tsx} : Write component tests for Context + Reducer pattern components with 90+ unit and integration tests; use React Testing Library for testing AgentStateProvider, useAgentState hook, and WebSocket message mapping

Applied to files:

  • web-ui/__tests__/components/QualityGateStatus.test.tsx
📚 Learning: 2025-12-05T05:44:48.051Z
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-05T05:44:48.051Z
Learning: Applies to web-ui/**/*.{ts,tsx} : Run frontend tests with: cd web-ui && npm test; achieve 90%+ test coverage on all React components including unit and integration tests

Applied to files:

  • web-ui/__tests__/components/QualityGateStatus.test.tsx
📚 Learning: 2025-11-25T19:08:37.203Z
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-11-25T19:08:37.203Z
Learning: Applies to docs/web-ui/**/__tests__/**/*.test.{ts,tsx} : Create JavaScript test files colocated or in __tests__/ as *.test.ts

Applied to files:

  • web-ui/__tests__/components/QualityGateStatus.test.tsx
📚 Learning: 2025-12-05T05:44:48.051Z
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-05T05:44:48.051Z
Learning: Applies to codeframe/agents/worker_agent.py : Implement quality gates with 4-stage pre-completion workflow: (1) run tests, (2) type checking, (3) coverage check (85% minimum), (4) code review trigger; create blocker if any gate fails

Applied to files:

  • web-ui/src/types/qualityGates.ts
📚 Learning: 2025-12-05T05:44:48.051Z
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-05T05:44:48.051Z
Learning: Implement quality gates as multi-stage pre-completion checks (tests → type → coverage 85% → review) that block tasks from completion if any gate fails, preventing bad code from being marked done

Applied to files:

  • web-ui/src/types/qualityGates.ts
🧬 Code graph analysis (1)
web-ui/__tests__/components/QualityGateStatus.test.tsx (2)
web-ui/src/components/quality-gates/QualityGateStatus.tsx (1)
  • QualityGateStatus (34-299)
web-ui/src/types/qualityGates.ts (1)
  • QualityGateStatus (41-47)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Frontend Unit Tests
  • GitHub Check: Backend Unit Tests
  • GitHub Check: claude-review
🔇 Additional comments (3)
web-ui/src/types/qualityGates.ts (1)

36-39: LGTM! Clear documentation of planned enhancement.

The TODO comment clearly describes the planned backend field and explains how it will eliminate the need for the warning banner workaround. This provides helpful context for future work.

web-ui/src/components/quality-gates/QualityGateStatus.tsx (2)

77-82: LGTM! Dismissal logic correctly persists per-task state.

The dismiss handler properly updates both local state and localStorage using the task-specific key format. The implementation correctly pairs with the read logic.


205-227: LGTM! Warning banner implementation is solid.

The banner correctly:

  • Displays only when status is passed with no failures and hasn't been dismissed
  • Uses accessible markup with aria-label on the dismiss button
  • Follows existing yellow warning styling patterns
  • Provides clear messaging about the limitation

Comment thread web-ui/src/components/quality-gates/QualityGateStatus.tsx
The localStorage effect now properly resets warningDismissed to false when:
- taskId changes and no stored value exists (null from localStorage)
- JSON parsing fails (invalid stored value)

This ensures dismissal state is properly isolated per task. Without this fix,
dismissing the warning for task A would incorrectly hide the warning for
task B when switching between tasks.

Changes:
- Add else clause to reset state when localStorage.getItem returns null
- Update comment to clarify the reset behavior
- Add test verifying state reset when switching between tasks

Testing:
- All 35 tests pass (28 existing + 7 warning banner tests)
- New test confirms proper state isolation between tasks
@claude

claude Bot commented Dec 5, 2025

Copy link
Copy Markdown

Code Review - PR #76: Add dismissible warning banner to QualityGateStatus component

Summary

This PR implements a well-designed dismissible warning banner to address false positives in the quality gates UI. The implementation is clean, well-tested, and follows React best practices.


✅ Strengths

1. Excellent Test Coverage

  • 6 new comprehensive tests covering all scenarios (display, dismissal, persistence, task-specific keys)
  • 100% coverage of the new feature with TDD approach
  • Test quality is high with proper setup/teardown and edge case coverage
  • Test for task switching (lines 780-821) is particularly thorough

2. Clean Component Design

  • Properly separated concerns (state management, localStorage persistence, UI rendering)
  • Good use of React hooks (useEffect for localStorage initialization)
  • Consistent styling with existing codebase (yellow warning pattern from CheckpointRestore)
  • Accessible dismiss button with proper aria-label

3. User Experience

  • Task-specific persistence prevents global dismissal (good UX choice)
  • Warning appears in logical location (between status header and progress indicator)
  • Clear, concise messaging explaining the limitation
  • Non-intrusive but informative

4. Documentation

  • TODO comment in type definitions documents future backend enhancement
  • Clear PR description explaining the temporary nature of the solution
  • Good inline comments in tests

🔍 Potential Improvements

1. localStorage Error Handling (Minor)

Location: QualityGateStatus.tsx:64-78

The current implementation silently falls back to false on parse errors, which is fine. However, consider adding optional error logging for debugging in development mode.

Severity: Low - Current implementation is acceptable

2. Potential Memory Leak Prevention (Minor)

Location: QualityGateStatus.tsx:63-78

Consider extracting the localStorage logic into a custom hook like useLocalStorage for reusability and better cleanup. This would also make the component more testable and maintainable if this pattern is reused elsewhere.

Severity: Low - Current implementation works fine, but this would improve reusability

3. Type Safety Enhancement (Minor)

Location: QualityGateStatus.tsx:81-85

The dismissWarning function duplicates the storage key logic. Consider extracting it to a constant or helper function to maintain DRY principles.

Severity: Very Low - Code duplication is minimal

4. Accessibility Enhancement (Minor)

Location: QualityGateStatus.tsx:208-230

Consider adding role="alert" and aria-live="polite" to the warning banner for better screen reader support.

Severity: Low - Current implementation is accessible, but this would enhance it


🔒 Security Considerations

No security concerns identified

  • localStorage usage is appropriate for non-sensitive UI state
  • No XSS vulnerabilities (no dangerouslySetInnerHTML)
  • No injection risks
  • Task ID is properly scoped to prevent cross-task pollution

🚀 Performance Considerations

Performance looks good

  • localStorage reads are minimal (only on mount and taskId change)
  • No unnecessary re-renders (state updates are well-scoped)
  • Warning banner rendering is conditional and efficient
  • Consider: If this pattern is used extensively across the app, investigate if localStorage keys should be cleaned up periodically (not a concern for this PR)

📋 Code Quality

Follows Best Practices:

  • ✅ Consistent naming conventions (warningDismissed, dismissWarning)
  • ✅ Proper React patterns (functional components, hooks)
  • ✅ No prop drilling or unnecessary complexity
  • ✅ Clean separation of concerns

Adherence to Codebase Standards:

  • ✅ Matches existing component structure (CheckpointRestore pattern)
  • ✅ Consistent styling with Tailwind CSS
  • ✅ Follows TypeScript conventions
  • ✅ Test structure matches existing test patterns

🧪 Test Quality

Excellent test coverage with these scenarios:

  1. ✅ Display warning when passed with no failures
  2. ✅ Hide warning when failed
  3. ✅ Hide warning when running
  4. ✅ Dismiss warning on button click
  5. ✅ Persist dismissal in localStorage
  6. ✅ Task-specific localStorage keys
  7. ✅ Reset dismissal state when switching tasks

Particularly impressed with:


📝 Recommendations

Must Fix (None)

No blocking issues identified.

Should Consider (Optional)

  1. Extract localStorage logic to custom hook for reusability (if this pattern will be used elsewhere)
  2. Add role="alert" for enhanced accessibility
  3. Add development-mode logging for parse errors

Nice to Have

  1. Add a comment explaining why task-specific persistence was chosen over global dismissal
  2. Consider adding a "Don't show this again" tooltip on the dismiss button

✨ Final Assessment

Approval Status: ✅ APPROVED

This is a high-quality PR that addresses a real UX issue with:

  • Excellent test coverage (6 new tests, 100% feature coverage)
  • Clean, maintainable code following React best practices
  • No security or performance concerns
  • Proper documentation of temporary nature (TODO comment)
  • Good accessibility considerations

The implementation is production-ready. The optional improvements listed above are minor enhancements that could be addressed in future PRs if desired.

Great work! The TDD approach and attention to edge cases (task switching, localStorage key scoping) demonstrate strong engineering practices.


📊 Stats

  • Files Changed: 3
  • Additions: 258 lines
  • Deletions: 0 lines
  • Test Coverage: 100% (6/6 new tests passing)
  • Security Issues: 0
  • Performance Issues: 0
  • Blocking Issues: 0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant