Skip to content

Conversation

@mrrajan
Copy link
Contributor

@mrrajan mrrajan commented Oct 1, 2025

Added Test scenarios for manual validation.
Please note the placeholders will be updated during validation.

Summary by Sourcery

Add end-to-end SBOM scanning test scenarios and supporting helpers and page objects

New Features:

  • Introduce SbomScanPage page object and associated BDD step definitions for SBOM scan flows
  • Add scan-sbom.feature files with comprehensive scenarios for SBOM upload, error handling, report generation, filtering, sorting, pagination, and download actions
  • Implement reusable helpers verifyDownload, clickAndVerifyDownload, and verifyCommaDelimitedValues for download verification and list comparisons

Enhancements:

  • Dynamically set Content-Type header based on file extension in API global setup
  • Refine ToolbarTable helper to improve sorting clicks and download-trigger interactions
  • Extend ADVISORY_FILES constant list with additional test artifacts

Tests:

  • Add extensive UI and API test scenarios for SBOM scanning under e2e tests

@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Oct 1, 2025

Reviewer's Guide

This PR extends the SBOM scanning test suite by adding end-to-end BDD feature files and step definitions, introducing reusable download and CSV validation helpers, refactoring global API setup for dynamic content types, improving the ToolbarTable helper, expanding test asset constants, and creating a dedicated SbomScanPage page object for streamlined interactions.

File-Level Changes

Change Details Files
Introduce download and CSV helpers in UI tests
  • Add verifyDownload to save and confirm download success
  • Add clickAndVerifyDownload to wrap click-triggered downloads
  • Add verifyCommaDelimitedValues for validating CSV-like lists
e2e/tests/ui/pages/Helpers.ts
Expand advisory file constants for test assets
  • Add multiple GHSA- and RHSA-prefixed advisory filenames
  • Insert additional CVE entries to the constants list
e2e/tests/common/constants.ts
Refactor API global setup to set Content-Type dynamically
  • Compute contentType based on file extension (.bz2 vs .json)
  • Apply dynamic Content-Type header in SBOM and advisory uploads
e2e/tests/api/dependencies/global.setup.ts
Enhance ToolbarTable helper for better sorting and waiting
  • Click column headers by name and wait for table content
  • Fix row index increment logic when finding non-empty cells
e2e/tests/ui/helpers/ToolbarTable.ts
Add BDD feature files and step definitions for SBOM scanning
  • Create scan-sbom.feature with end-to-end scenarios
  • Update sbom-explorer.feature for parameterized sorting tests
  • Implement scan-sbom.step.ts with Given/When/Then steps
e2e/tests/ui/features/scan-sbom.feature
e2e/tests/ui/features/@sbom-scan/scan-sbom.feature
e2e/tests/ui/features/@sbom-explorer/sbom-explorer.feature
e2e/tests/ui/features/@sbom-scan/scan-sbom.step.ts
Introduce SbomScanPage page object for scan interactions
  • Encapsulate upload, navigation, and error handling methods
  • Provide helpers for verifying headers, filters, tooltips, and actions
  • Add getVulnerabilityRow for locating table rows by ID
e2e/tests/ui/pages/sbom-scan/SbomScanPage.ts

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes - here's some feedback:

  • This feature file is very large and repetitive; consider splitting it into smaller, focused feature files (e.g., unsupported formats, filtering, actions) to improve maintainability.
  • Several scenarios share identical steps that could be consolidated into a Background or refactored using Scenario Outline to reduce duplication.
  • Scenario names are duplicated (e.g., 'Verify Generate Vulnerability Report Screen') and should be made unique to avoid confusion when running tests.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- This feature file is very large and repetitive; consider splitting it into smaller, focused feature files (e.g., unsupported formats, filtering, actions) to improve maintainability.
- Several scenarios share identical steps that could be consolidated into a Background or refactored using Scenario Outline to reduce duplication.
- Scenario names are duplicated (e.g., 'Verify Generate Vulnerability Report Screen') and should be made unique to avoid confusion when running tests.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@codecov
Copy link

codecov bot commented Oct 1, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 61.59%. Comparing base (4153180) to head (aae73a9).
⚠️ Report is 5 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #772      +/-   ##
==========================================
+ Coverage   57.76%   61.59%   +3.82%     
==========================================
  Files         163      170       +7     
  Lines        2872     3080     +208     
  Branches      654      698      +44     
==========================================
+ Hits         1659     1897     +238     
+ Misses        976      927      -49     
- Partials      237      256      +19     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@mrrajan mrrajan force-pushed the scan_sbom_feature branch from 9041436 to 8dda8ec Compare October 9, 2025 15:39
@mrrajan mrrajan marked this pull request as draft October 9, 2025 15:40
@mrrajan mrrajan marked this pull request as ready for review October 9, 2025 15:44
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes - here's some feedback:

  • Please remove the stray console.log("debug cellText:", result) in the step definitions to avoid leftover debug output in your tests.
  • The verifyDownload helper’s extension check isn’t actually asserting the result—add a proper expect(...).toBeTruthy() or toMatch(...) so failures are caught.
  • These feature files are extremely large with a lot of repeated scenarios and placeholders—consider splitting them into smaller, logical pieces or consolidating outlines to keep them maintainable.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Please remove the stray console.log("debug cellText:", result) in the step definitions to avoid leftover debug output in your tests.
- The verifyDownload helper’s extension check isn’t actually asserting the result—add a proper expect(...).toBeTruthy() or toMatch(...) so failures are caught.
- These feature files are extremely large with a lot of repeated scenarios and placeholders—consider splitting them into smaller, logical pieces or consolidating outlines to keep them maintainable.

## Individual Comments

### Comment 1
<location> `e2e/tests/ui/features/@sbom-scan/scan-sbom.step.ts:61` </location>
<code_context>
+  },
+);
+
+When("User Clicks on Browse files Button", async ({ page }) => {
+  await page.getByRole("button", { name: "Browse Files" }).click();
+});
</code_context>

<issue_to_address>
**suggestion (testing):** No test for drag-and-drop file upload interaction.

Please add a test that simulates drag-and-drop file upload and checks the resulting UI and processing.

Suggested implementation:

```typescript
When("User Clicks on Browse files Button", async ({ page }) => {
  await page.getByRole("button", { name: "Browse Files" }).click();
});

When("User drags and drops a file onto the upload area", async ({ page }) => {
  // Locate the drop area (adjust selector as needed)
  const dropArea = await page.locator('[data-testid="file-drop-area"]');
  // Simulate drag-and-drop file upload
  await dropArea.setInputFiles('tests/fixtures/sample-sbom.json');
});

Then("The uploaded file should appear in the file list and start processing", async ({ page }) => {
  // Check that the file appears in the UI
  await expect(page.getByText("sample-sbom.json")).toBeVisible();
  // Check for processing indicator (adjust selector/text as needed)
  await expect(page.getByTestId("processing-indicator")).toBeVisible();
});

```

- Ensure that the selector `[data-testid="file-drop-area"]` matches your actual drop area. Adjust as needed.
- Place a sample SBOM file at `tests/fixtures/sample-sbom.json` or update the path to match your test fixture location.
- Adjust `"processing-indicator"` and other selectors/texts to match your application's UI.
- If your file list or processing indicator uses different test IDs or text, update the assertions accordingly.
</issue_to_address>

### Comment 2
<location> `e2e/tests/ui/features/@sbom-scan/scan-sbom.step.ts:380-391` </location>
<code_context>
    if (column === "Qualifiers") {
      // Use the reusable helper for comma-delimited values
      await verifyCommaDelimitedValues(cell, expected, "xpath=//td/span");
    } else {
      // For other columns, check if expected is empty string (for empty columns)
      if (expected === "") {
        const cellText = await cell.textContent();
        await expect(cellText?.trim() || "").toBe("");
      } else {
        await expect(cell).toContainText(expected);
      }
    }

</code_context>

<issue_to_address>
**suggestion (code-quality):** Merge else clause's nested if statement into `else if` ([`merge-else-if`](https://docs.sourcery.ai/Reference/Rules-and-In-Line-Suggestions/TypeScript/Default-Rules/merge-else-if))

```suggestion
    if (column === "Qualifiers") {
          // Use the reusable helper for comma-delimited values
          await verifyCommaDelimitedValues(cell, expected, "xpath=//td/span");
        }
    else if (expected === "") {
            const cellText = await cell.textContent();
            await expect(cellText?.trim() || "").toBe("");
          }
    else {
            await expect(cell).toContainText(expected);
          }

```

<br/><details><summary>Explanation</summary>Flattening if statements nested within else clauses generates code that is
easier to read and expand upon.
</details>
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@mrrajan mrrajan marked this pull request as draft October 9, 2025 16:23
@mrrajan mrrajan marked this pull request as ready for review October 10, 2025 10:42
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes - here's some feedback:

  • Replace fixed waitForTimeout calls with explicit waits for specific element conditions to improve stability and avoid flakiness.
  • Consolidate or remove duplicate scan-sbom.feature files and overlapping scenarios to reduce redundancy and simplify maintenance.
  • Update SbomScanPage methods like errorVulnerabilitiesHeading/body to use await expect(...).toBeVisible() so failures are properly reported.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Replace fixed waitForTimeout calls with explicit waits for specific element conditions to improve stability and avoid flakiness.
- Consolidate or remove duplicate scan-sbom.feature files and overlapping scenarios to reduce redundancy and simplify maintenance.
- Update SbomScanPage methods like errorVulnerabilitiesHeading/body to use await expect(...).toBeVisible() so failures are properly reported.

## Individual Comments

### Comment 1
<location> `e2e/tests/ui/pages/sbom-scan/SbomScanPage.ts:36-37` </location>
<code_context>
+    return this._page.getByRole("button", { name: "Actions" });
+  }
+
+  async errorVulnerabilitiesHeading(header: string) {
+    this._page.getByRole("heading", { name: header }).isVisible();
+  }
+
</code_context>

<issue_to_address>
**issue (bug_risk):** Missing await in errorVulnerabilitiesHeading and errorVulnerabilitiesBody.

Please add 'await' before isVisible() in both methods to ensure correct test behavior.
</issue_to_address>

### Comment 2
<location> `e2e/tests/ui/features/@sbom-scan/scan-sbom.step.ts:361-370` </location>
<code_context>
      if (column === "Qualifiers") {
        await verifyCommaDelimitedValues(cell, expected, "xpath=//span");
      } else {
        if (expected === "") {
          const cellText = await cell.textContent();
          await expect(cellText?.trim() || "").toBe("");
        } else {
          await expect(cell).toContainText(expected);
        }
      }

</code_context>

<issue_to_address>
**suggestion (code-quality):** Merge else clause's nested if statement into `else if` ([`merge-else-if`](https://docs.sourcery.ai/Reference/Rules-and-In-Line-Suggestions/TypeScript/Default-Rules/merge-else-if))

```suggestion
      if (column === "Qualifiers") {
              await verifyCommaDelimitedValues(cell, expected, "xpath=//span");
            }
      else if (expected === "") {
                const cellText = await cell.textContent();
                await expect(cellText?.trim() || "").toBe("");
              }
      else {
                await expect(cell).toContainText(expected);
              }

```

<br/><details><summary>Explanation</summary>Flattening if statements nested within else clauses generates code that is
easier to read and expand upon.
</details>
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines 36 to 37
async errorVulnerabilitiesHeading(header: string) {
this._page.getByRole("heading", { name: header }).isVisible();
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (bug_risk): Missing await in errorVulnerabilitiesHeading and errorVulnerabilitiesBody.

Please add 'await' before isVisible() in both methods to ensure correct test behavior.

Copy link
Collaborator

@carlosthe19916 carlosthe19916 left a comment

Choose a reason for hiding this comment

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

  • Aren't ui/features/scan-sbom.feature and ui/features/@sbom-scan/scan-sbom.feature the same? Shouldn't we delete ui/features/scan-sbom.feature from this PR?

I gave a quick look and I added comments to each section. Given that the tests are failing a second review will be needed once CI is green.

@mrrajan
Copy link
Contributor Author

mrrajan commented Oct 13, 2025

Thanks for the review @carlosthe19916 I have refactored the code - Please review and let me know.
Regarding the feature file, I have removed the implemented ones and just kept the other as place holder. Once they are implemented, will remove the file.

@mrrajan mrrajan force-pushed the scan_sbom_feature branch 2 times, most recently from ea832bc to 2edfac3 Compare October 17, 2025 09:33
Copy link
Collaborator

@carlosthe19916 carlosthe19916 left a comment

Choose a reason for hiding this comment

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

@mrrajan sorry for my delayed review

  • Please remove the comments // here
  • Also address the minor suggestion on the PackageDetailsPage file.

Copy link
Collaborator

@carlosthe19916 carlosthe19916 left a comment

Choose a reason for hiding this comment

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

@mrrajan LGTM, thanks. I am approving this PR

  • Before your merge the PR please address the minor comments below and push the merge button
  • It would be good to backport the changes to the release branch, so please backport it too.

Name: "keycloak-core",
Version: "18.0.6.redhat-00001",
});
await expect(await tableRow.count()).toBeGreaterThan(0);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Remove the first await because it has no effect.

Suggested change
await expect(await tableRow.count()).toBeGreaterThan(0);
expect(await tableRow.count()).toBeGreaterThan(0);

I believe the IDE should help to find those things.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

count() returns a promise - so await is necessary

Name: "keycloak-core",
Version: "18.0.6.redhat-00001",
});
await expect(await tableRow.count()).toBeGreaterThan(0);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same as above, let;s remove the first await

Suggested change
await expect(await tableRow.count()).toBeGreaterThan(0);
expect(await tableRow.count()).toBeGreaterThan(0);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

count() returns a promise - so await is necessary

Copy link
Collaborator

Choose a reason for hiding this comment

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

Current code:

await expect(await tableRow.count()).toBeGreaterThan(0);
  • The current code has 2 await. The first await has not effect. The second one does.
  • As you pointed out count() returns a promise, therefore the second await does apply correctly. But the first one does not.

Copy link
Collaborator

Choose a reason for hiding this comment

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

If we leave the current code it won't break anything. I suggested to remove the first await just in the spirit of having clean code and not get confused if in the future we review the code again... as mentioned before I think any standard IDE should be able to warn us about this kind of things.

image

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah! I see. Thanks! I will have this change part of my next PR.

Comment on lines 120 to 127
await expect
.soft(
missing.length === 0,
missing.length > 0
? `Missing expected values: ${missing.join(", ")}. Actual values: [${actualValues.join(", ")}]`
: "Values did not match expected pattern",
)
.toBeTruthy();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same here. Remove await as it has no effect. That is a synchronous operation so await makes no sense.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@mrrajan
Copy link
Contributor Author

mrrajan commented Oct 29, 2025

Thanks carlos - I have committed couple of changes and added comments on couple.

@mrrajan mrrajan added the backport release/0.4.z This PR should be backported to release/0.4.z branch. label Oct 29, 2025
@mrrajan mrrajan added this pull request to the merge queue Oct 29, 2025
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Oct 29, 2025
@mrrajan mrrajan added this pull request to the merge queue Oct 29, 2025
Merged via the queue into guacsec:main with commit 52fdc56 Oct 29, 2025
11 of 13 checks passed
github-actions bot pushed a commit that referenced this pull request Oct 29, 2025
Signed-off-by: mrrajan <[email protected].>
(cherry picked from commit 52fdc56)
@trustify-ci-bot
Copy link
Contributor

Successfully created backport PR for release/0.4.z:

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

Labels

backport release/0.4.z This PR should be backported to release/0.4.z branch.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants