108 lines
5.9 KiB
Markdown
108 lines
5.9 KiB
Markdown
|
|
# Implementation Plan: CVE Tooltip Hover
|
|||
|
|
|
|||
|
|
## Overview
|
|||
|
|
|
|||
|
|
Implement a hover tooltip for CVE badges in the Reporting Page findings table. The feature spans a backend endpoint (`GET /api/cves/:cveId/tooltip`) and a frontend `CveTooltip` portal component with in-memory caching and 300ms hover delay. Tasks are ordered backend-first, then frontend component, then integration, with property tests alongside each layer.
|
|||
|
|
|
|||
|
|
## Tasks
|
|||
|
|
|
|||
|
|
- [x] 1. Add backend tooltip endpoint
|
|||
|
|
- [x] 1.1 Add `GET /api/cves/:cveId/tooltip` route inline in `backend/server.js`
|
|||
|
|
- Place it alongside existing CVE endpoints (after `/api/cves/:cveId/vendors`)
|
|||
|
|
- Validate `:cveId` against existing `CVE_ID_PATTERN`; return 400 for invalid format
|
|||
|
|
- Query: `SELECT cve_id, description, severity FROM cves WHERE cve_id = ? LIMIT 1`
|
|||
|
|
- If no row: return `{ exists: false }` with status 200
|
|||
|
|
- If row found: truncate `description` to 300 chars + "…" if needed, return `{ exists: true, cve_id, description, severity }`
|
|||
|
|
- Protect with `requireAuth(db)` middleware
|
|||
|
|
- _Requirements: 1.1, 1.2, 1.3, 1.4, 1.5_
|
|||
|
|
|
|||
|
|
- [ ]* 1.2 Write property test for tooltip endpoint data correctness
|
|||
|
|
- **Property 1: Tooltip endpoint returns correct data for existing CVEs**
|
|||
|
|
- Install `fast-check` as dev dependency in `frontend/` (shared test runner)
|
|||
|
|
- Generate random CVE records with description lengths 0–1000 and all 4 severity levels
|
|||
|
|
- Verify response shape, truncation at 300 chars, and prefix preservation
|
|||
|
|
- **Validates: Requirements 1.1, 1.3, 1.5**
|
|||
|
|
|
|||
|
|
- [ ]* 1.3 Write property test for description truncation
|
|||
|
|
- **Property 2: Description truncation preserves content and enforces length**
|
|||
|
|
- Extract truncation logic into a testable pure function
|
|||
|
|
- Generate random strings of length 0–2000, verify length invariant and prefix match
|
|||
|
|
- **Validates: Requirements 1.5**
|
|||
|
|
|
|||
|
|
- [x] 2. Checkpoint — Verify backend endpoint
|
|||
|
|
- Ensure all tests pass, ask the user if questions arise.
|
|||
|
|
|
|||
|
|
- [x] 3. Create CveTooltip frontend component
|
|||
|
|
- [x] 3.1 Create `frontend/src/components/CveTooltip.js`
|
|||
|
|
- Portal-rendered component using `ReactDOM.createPortal` to `document.body`
|
|||
|
|
- Props: `cveId` (string|null), `anchorRect` (DOMRect|null), `cache` (useRef Map)
|
|||
|
|
- Internal state: `data`, `loading`
|
|||
|
|
- On `cveId` change: check cache → if miss, fetch from `/api/cves/:cveId/tooltip` with AbortController
|
|||
|
|
- If cached `exists: false` or fetch returns `exists: false`, render nothing
|
|||
|
|
- Show loading spinner (Loader from lucide-react) while fetching
|
|||
|
|
- Display: CVE ID in monospace, severity badge with design system colors, description text
|
|||
|
|
- Max-width 320px, dark theme gradient background, accent border, directional arrow
|
|||
|
|
- Position above anchor by default; flip below if insufficient viewport space above
|
|||
|
|
- Do not cache transient errors (network failures)
|
|||
|
|
- _Requirements: 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 3.1, 3.2, 3.3, 3.4, 3.5_
|
|||
|
|
|
|||
|
|
- [ ]* 3.2 Write property test for tooltip positioning logic
|
|||
|
|
- **Property 3: Tooltip positioning flips based on available viewport space**
|
|||
|
|
- Extract positioning calculation into a pure function
|
|||
|
|
- Generate random anchorRect.top (0–2000), tooltip height (50–200), viewport height (400–1200)
|
|||
|
|
- Verify tooltip never overflows top or bottom of viewport
|
|||
|
|
- **Validates: Requirements 3.1, 3.2**
|
|||
|
|
|
|||
|
|
- [ ]* 3.3 Write unit tests for CveTooltip component
|
|||
|
|
- Test loading state renders spinner
|
|||
|
|
- Test `exists: false` renders nothing
|
|||
|
|
- Test severity badge uses correct color per level
|
|||
|
|
- Test max-width constraint
|
|||
|
|
- Test directional arrow element is present
|
|||
|
|
- _Requirements: 2.4, 2.5, 2.6, 3.3, 3.5_
|
|||
|
|
|
|||
|
|
- [x] 4. Checkpoint — Verify CveTooltip component
|
|||
|
|
- Ensure all tests pass, ask the user if questions arise.
|
|||
|
|
|
|||
|
|
- [x] 5. Integrate tooltip into ReportingPage
|
|||
|
|
- [x] 5.1 Add hover state and cache ref to ReportingPage
|
|||
|
|
- Add state: `tooltipCveId` (string|null), `tooltipAnchorRect` (DOMRect|null)
|
|||
|
|
- Add `useRef(new Map())` for tooltip cache
|
|||
|
|
- Add `useRef` for hover delay timer
|
|||
|
|
- Clear cache when findings data is re-synced (inside existing sync callback)
|
|||
|
|
- _Requirements: 4.1, 4.4, 5.1_
|
|||
|
|
|
|||
|
|
- [x] 5.2 Add mouseenter/mouseleave handlers to CVE badge spans
|
|||
|
|
- In the `renderCell` function for the `'cves'` column case, wrap each CVE badge `<span>` with `onMouseEnter` and `onMouseLeave`
|
|||
|
|
- `onMouseEnter`: start 300ms setTimeout; on fire, set `tooltipCveId` and `tooltipAnchorRect` from `getBoundingClientRect()`
|
|||
|
|
- `onMouseLeave`: clear timeout, set `tooltipCveId` to null
|
|||
|
|
- _Requirements: 2.1, 2.2, 5.1, 5.2_
|
|||
|
|
|
|||
|
|
- [x] 5.3 Render CveTooltip instance in ReportingPage
|
|||
|
|
- Add single `<CveTooltip>` at the bottom of the ReportingPage return, passing `tooltipCveId`, `tooltipAnchorRect`, and cache ref
|
|||
|
|
- _Requirements: 2.1, 4.2, 4.3_
|
|||
|
|
|
|||
|
|
- [ ]* 5.4 Write property test for cache round-trip behavior
|
|||
|
|
- **Property 4: Cache round-trip — fetch then cache-hit avoids network call**
|
|||
|
|
- Generate random CVE IDs and response payloads, store in Map, verify lookups return identical objects
|
|||
|
|
- **Validates: Requirements 4.1, 4.2**
|
|||
|
|
|
|||
|
|
- [ ]* 5.5 Write unit tests for hover delay and cache integration
|
|||
|
|
- Test tooltip appears after 300ms delay (use fake timers)
|
|||
|
|
- Test tooltip cancelled if mouseout before 300ms
|
|||
|
|
- Test cached `exists: false` suppresses tooltip and API call
|
|||
|
|
- Test cache cleared on data sync/refresh
|
|||
|
|
- _Requirements: 4.3, 4.4, 5.1, 5.2_
|
|||
|
|
|
|||
|
|
- [x] 6. Final checkpoint — Ensure all tests pass
|
|||
|
|
- Ensure all tests pass, ask the user if questions arise.
|
|||
|
|
|
|||
|
|
## Notes
|
|||
|
|
|
|||
|
|
- Tasks marked with `*` are optional and can be skipped for faster MVP
|
|||
|
|
- Each task references specific requirements for traceability
|
|||
|
|
- Checkpoints ensure incremental validation
|
|||
|
|
- Property tests validate universal correctness properties from the design document
|
|||
|
|
- Unit tests validate specific examples and edge cases
|
|||
|
|
- The project uses plain JavaScript (no TypeScript), fast-check for PBT, and react-scripts test (Jest)
|