Conversation
Add a Cryptographic Bill of Materials tab to the SBOM detail page, surfacing per-SBOM cryptographic assets with a filterable, paginated table showing asset name, type, primitive, OID, policy status, and properties columns. - Add useFetchCryptoBySbom query hook filtering by sbom_id - Create CbomBySbom tab content component following existing patterns - Register CBOM tab in sbom-details alongside info/packages/vulns/models - Add unit tests for table rendering, empty state, and column display Implements TC-5854 Assisted-by: Claude Code
Reviewer's GuideAdds a CBOM tab to SBOM Explorer details, backed by a new SBOM-filtered crypto query and a tested table that supports search, pagination, policy/status rendering, and empty-state handling. Sequence diagram for loading SBOM-scoped CBOM assetssequenceDiagram
participant User
participant SbomDetails
participant CbomBySbom
participant useFetchCryptoBySbom
participant CryptoAPI
User->>SbomDetails: Select CBOM tab
SbomDetails->>CbomBySbom: Render sbomId
CbomBySbom->>useFetchCryptoBySbom: useFetchCryptoBySbom(sbomId, params)
useFetchCryptoBySbom->>CryptoAPI: GET /api/v3/crypto/algorithm?q=sbom_id=sbomId
CryptoAPI-->>useFetchCryptoBySbom: CryptoAlgorithm items and total
useFetchCryptoBySbom-->>CbomBySbom: data, total, isFetching, fetchError
CbomBySbom-->>User: Render filterable paginated CBOM table
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="client/src/app/pages/sbom-details/cbom-by-sbom.test.tsx" line_range="103-109" />
<code_context>
+ });
+
+ /** Verifies that the empty state message is shown when no crypto assets exist. */
+ it("shows empty state when SBOM has no crypto assets", () => {
+ mockData = [];
+ renderComponent();
+
+ expect(
+ screen.getByText("No cryptographic assets found for this SBOM."),
+ ).toBeInTheDocument();
+ mockData = mockCryptoAssets;
+ });
+
</code_context>
<issue_to_address>
**nitpick (testing):** The empty-state test mutates module-level `mockData` and restores it only after the assertion; if rendering or the assertion throws, later tests retain the empty dataset and fail or silently test the wrong state.
**Triggers:** When the empty-state assertion fails or the test exits before the manual restoration.
**Suggested fix:** Reset `mockData` in an `afterEach`/`finally` block instead of relying on an inline restoration.
```suggestion
mockData = [];
try {
renderComponent();
expect(
screen.getByText("No cryptographic assets found for this SBOM."),
).toBeInTheDocument();
} finally {
mockData = mockCryptoAssets;
}
```
</issue_to_address>Sourcery assessment
Approved.
| mockData = []; | ||
| renderComponent(); | ||
|
|
||
| expect( | ||
| screen.getByText("No cryptographic assets found for this SBOM."), | ||
| ).toBeInTheDocument(); | ||
| mockData = mockCryptoAssets; |
There was a problem hiding this comment.
nitpick (testing): The empty-state test mutates module-level mockData and restores it only after the assertion; if rendering or the assertion throws, later tests retain the empty dataset and fail or silently test the wrong state.
Triggers: When the empty-state assertion fails or the test exits before the manual restoration.
Suggested fix: Reset mockData in an afterEach/finally block instead of relying on an inline restoration.
| mockData = []; | |
| renderComponent(); | |
| expect( | |
| screen.getByText("No cryptographic assets found for this SBOM."), | |
| ).toBeInTheDocument(); | |
| mockData = mockCryptoAssets; | |
| mockData = []; | |
| try { | |
| renderComponent(); | |
| expect( | |
| screen.getByText("No cryptographic assets found for this SBOM."), | |
| ).toBeInTheDocument(); | |
| } finally { | |
| mockData = mockCryptoAssets; | |
| } |
|
Closing — implementation was based on the wrong mock-up. Will re-implement with the correct design. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1247 +/- ##
==========================================
+ Coverage 56.81% 56.97% +0.15%
==========================================
Files 261 262 +1
Lines 5859 5892 +33
Branches 1830 1840 +10
==========================================
+ Hits 3329 3357 +28
- Misses 2284 2286 +2
- Partials 246 249 +3
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Summary
useFetchCryptoBySbomquery hook that filtersGET /v3/crypto/algorithmbysbom_idCbomBySbomcomponent renders a filterable, paginated table with columns: Asset Name, Type, Primitive, OID, Policy Status, PropertiesImplements TC-5854
Note: This PR depends on the cryptography backend API from trustify#2619.
Test plan
npm run test— all 122 tests passnpm run lint— no errors or warnings🤖 Generated with Claude Code
Summary by Sourcery
Add cryptographic asset visibility to SBOM details through a filterable, paginated CBOM tab.
New Features:
Enhancements:
Tests: