Skip to content
This repository was archived by the owner on Sep 11, 2025. It is now read-only.

Commit 388de1e

Browse files
author
Rajan Ravi
committed
BDD and xpath updates
Signed-off-by: Rajan Ravi <rravi@rravi-thinkpadp1gen4i.bengluru.csb>
1 parent 54e25de commit 388de1e

File tree

3 files changed

+65
-49
lines changed

3 files changed

+65
-49
lines changed

tests/ui/features/@sbom-explorer/sbom-explorer.feature

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ Feature: SBOM Explorer - View SBOM details
33
Given User is authenticated
44

55
Scenario Outline: View SBOM Overview
6-
Given User visits SBOM details Page of "<sbomName>"
6+
Given An ingested "<sbomType>" SBOM "<sbomName>" is available
7+
When User visits SBOM details Page of "<sbomName>"
78
Then The page title is "<sbomName>"
89
And Tab "Info" is visible
910
And Tab "Packages" is visible
@@ -15,7 +16,8 @@ Feature: SBOM Explorer - View SBOM details
1516
| quarkus-bom |
1617

1718
Scenario Outline: View SBOM Info (Metadata)
18-
Given User visits SBOM details Page of "<sbomName>"
19+
Given An ingested "<sbomType>" SBOM "<sbomName>" is available
20+
When User visits SBOM details Page of "<sbomName>"
1921
Then Tab "Info" is selected
2022
Then "SBOM's name" is visible
2123
And "SBOM's namespace" is visible
@@ -26,18 +28,19 @@ Feature: SBOM Explorer - View SBOM details
2628
Examples:
2729
| sbomName |
2830
| quarkus-bom |
29-
31+
3032
Scenario Outline: Downloading SBOM file
31-
Given User visits SBOM details Page of "<sbomName>"
33+
Given An ingested "<sbomType>" SBOM "<sbomName>" is available
34+
When User visits SBOM details Page of "<sbomName>"
3235
Then "Download SBOM" action is invoked and downloaded filename is "<expectedSbomFilename>"
3336
Then "Download License Report" action is invoked and downloaded filename is "<expectedLicenseFilename>"
3437

3538
Examples:
3639
| sbomName | expectedSbomFilename | expectedLicenseFilename |
3740
| quarkus-bom | quarkus-bom.json | quarkus-bom_licenses.tar.gz |
38-
41+
3942
Scenario Outline: View list of SBOM Packages
40-
Given An ingested <sbomType> SBOM <sbomName> is available
43+
Given An ingested "<sbomType>" SBOM "<sbomName>" is available
4144
When User visits SBOM details Page of "<sbomName>"
4245
When User selects the Tab "Packages"
4346
# confirms its visible for all tabs
@@ -56,11 +59,11 @@ Feature: SBOM Explorer - View SBOM details
5659
Then The Package table total results is greather than 1
5760

5861
Examples:
59-
| sbomName | packageName |
60-
| quarkus-bom | jdom |
61-
62+
| sbomType | sbomName | packageName |
63+
| SPDX | quarkus-bom | jdom |
64+
@only
6265
Scenario Outline: View <sbomType> SBOM Vulnerabilities
63-
Given An ingested "<sbomType>" SBOM "<sbomName>" containing Vulnerabilities is available
66+
Given An ingested "<sbomType>" SBOM "<sbomName>" containing Vulnerabilities
6467
When User visits SBOM details Page of "<sbomName>"
6568
When User selects the Tab "Vulnerabilities"
6669
When User Clicks on Vulnerabilities Tab Action
@@ -70,9 +73,8 @@ Feature: SBOM Explorer - View SBOM details
7073
Then SBOM Name "<sbomName>" should be visible inside the tab
7174
Then SBOM Version should be visible inside the tab
7275
Then SBOM Creation date should be visible inside the tab
73-
Then List of related Vulnerabilities should be sorted by CVSS in descending order
76+
# Then List of related Vulnerabilities should be sorted by "CVSS" in descending order
7477

7578
Examples:
7679
| sbomType | sbomName |
77-
| CycloneDX | fedora |
7880
| SPDX | quarkus-bom |

tests/ui/features/@sbom-explorer/sbom-explorer.step.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const VULN_TABLE_NAME = "Vulnerability table";
1111

1212
Given(
1313
"An ingested {string} SBOM {string} is available",
14-
async ({ page }, sbomName) => {
14+
async ({ page }, _sbomType, sbomName) => {
1515
const searchPage = new SearchPage(page);
1616
searchPage.dedicatedSearch("SBOMs", sbomName);
1717
}
@@ -84,11 +84,11 @@ Then(
8484

8585
Given(
8686
"An ingested {string} SBOM {string} containing Vulnerabilities",
87-
async ({ page }, sbomName) => {
87+
async ({ page }, _sbomType, sbomName) => {
8888
const searchPage = new SearchPage(page);
89-
searchPage.dedicatedSearch("SBOMs", sbomName);
89+
await searchPage.dedicatedSearch("SBOMs", sbomName);
9090
const element = await page.locator(
91-
"xpath=(//tr[contains(.,{sbomName})]/td[@data-label='Vulnerabilities']/div)[1]"
91+
`xpath=(//tr[contains(.,'${sbomName}')]/td[@data-label='Vulnerabilities']/div)[1]`
9292
);
9393
await expect(element, "SBOM have no vulnerabilities").toHaveText(
9494
/^(?!0$).+/
@@ -108,32 +108,32 @@ Then("Vulnerability Popup menu appears with message", async ({ page }) => {
108108
Then(
109109
"Vulnerability Risk Profile circle should be visible",
110110
async ({ page }) => {
111-
await page.locator("//div[contains(@class, 'chart')]").isVisible();
111+
await page.locator(`xpath=//div[contains(@class, 'chart')]`).isVisible();
112112
}
113113
);
114114

115115
Then(
116116
"Vulnerability Risk Profile shows summary of vulnerabilities",
117117
async ({ page }) => {
118118
const detailsPage = new DetailsPage(page);
119-
detailsPage.verifyVulnerabilityPanelcount();
119+
await detailsPage.verifyVulnerabilityPanelcount();
120120
}
121121
);
122122

123123
Then(
124124
"SBOM Name {string} should be visible inside the tab",
125125
async ({ page }, sbomName) => {
126126
const panelSbomName = await page.locator(
127-
"xpath=//section[@id='refVulnerabilitiesSection']//dt[contains(.,'Name')]/following-sibling::dd"
127+
`xpath=//section[@id='refVulnerabilitiesSection']//dt[contains(.,'Name')]/following-sibling::dd`
128128
);
129129
await panelSbomName.isVisible();
130-
await expect(sbomName).toHaveText(await panelSbomName.innerText());
130+
await expect(await panelSbomName.textContent()).toEqual(sbomName);
131131
}
132132
);
133133

134134
Then("SBOM Version should be visible inside the tab", async ({ page }) => {
135135
const panelSBOMVersion = await page.locator(
136-
"xpath=//section[@id='refVulnerabilitiesSection']//dt[contains(.,'Version')]/following-sibling::dd"
136+
`xpath=//section[@id='refVulnerabilitiesSection']//dt[contains(.,'Version')]/following-sibling::dd`
137137
);
138138
await panelSBOMVersion.isVisible();
139139
});
@@ -142,7 +142,7 @@ Then(
142142
"SBOM Creation date should be visible inside the tab",
143143
async ({ page }) => {
144144
const panelSBOMVersion = await page.locator(
145-
"xpath=//section[@id='refVulnerabilitiesSection']//dt[contains(.,'Creation date')]/following-sibling::dd"
145+
`xpath=//section[@id='refVulnerabilitiesSection']//dt[contains(.,'Creation date')]/following-sibling::dd`
146146
);
147147
await panelSBOMVersion.isVisible();
148148
}
@@ -152,6 +152,6 @@ Then(
152152
"List of related Vulnerabilities should be sorted by {string} in descending order",
153153
async ({ page }, columnName) => {
154154
const toolbarTable = new ToolbarTable(page, VULN_TABLE_NAME);
155-
toolbarTable.verifyTableIsSortedBy(columnName, false);
155+
await toolbarTable.verifyTableIsSortedBy(columnName, false);
156156
}
157157
);

tests/ui/helpers/DetailsPage.ts

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ export class DetailsPage {
1313

1414
async selectTab(tabName: string) {
1515
const tab = this.page.locator("button[role='tab']", { hasText: tabName });
16-
expect(tab).toBeVisible();
17-
tab.click();
16+
await expect(tab).toBeVisible();
17+
await tab.click();
1818
}
1919

2020
async clickOnPageAction(actionName: string) {
@@ -41,36 +41,36 @@ export class DetailsPage {
4141
await expect(this.page.getByRole("tab", { name: tabName })).toHaveCount(0);
4242
}
4343

44+
//Wait for Loading Spinner to detach from the DOM
4445
async waitForData() {
45-
await expect(this.page.getByLabel("Contents")).toHaveCount(0, {
46-
timeout: 5000,
47-
});
46+
const spinner = this.page.getByLabel("Contents");
47+
await spinner.waitFor({ state: "detached" });
4848
}
4949

50+
//Verifies the Page loads with data
5051
async verifyDataAvailable() {
51-
const rows = await this.page
52-
.locator("xpath=//div[(.='No data available to be shown here.')]")
53-
.count();
54-
await expect(rows, "No data available - Verify the data load").toEqual(0);
52+
await expect(
53+
this.page.locator(
54+
`xpath=//div[(.='No data available to be shown here.')]`
55+
)
56+
).toHaveCount(0);
5557
}
5658

59+
//Verifies the Vulnerability counts from summary to table
5760
async verifyVulnerabilityPanelcount() {
58-
const pieVulnSevLabel =
59-
"xpath=//*[name()='svg']/*[name()='g']//*[name()='tspan']";
60-
const totalVuln =
61-
"xpath=//*[name()='svg']/*[name()='text']//*[name()='tspan'][1]";
61+
const pieVulnSevLabel = `xpath=//*[name()='svg']/*[name()='g']//*[name()='tspan']`;
62+
const totalVuln = `xpath=//*[name()='svg']/*[name()='text']//*[name()='tspan'][1]`;
6263

6364
const panelVulnSev = await this.getCountFromLabels(pieVulnSevLabel, ":");
6465
const sumPanelVulnSev = Object.values(panelVulnSev).reduce(
6566
(sum, value) => sum + value,
6667
0
6768
);
68-
const totalVulnPanel = await this.page.locator(totalVuln).innerText();
69+
const totalVulnPanel = await this.page.locator(totalVuln).textContent();
6970
const tableVulnSev = await this.getCVSSCountFromVulnTable();
7071
var mismatch = false;
71-
7272
await expect(
73-
parseInt(totalVulnPanel, 10),
73+
parseInt(totalVulnPanel!, 10),
7474
"Total Vulnerabilities count {totalVuln} mismatches with sum of individual {sumOfVulnSev}"
7575
).toEqual(sumPanelVulnSev);
7676

@@ -82,18 +82,25 @@ export class DetailsPage {
8282
}
8383
}
8484
}
85-
await expect(mismatch, "Panel count mismatches to table count");
85+
await expect(mismatch, "Panel count mismatches to table count").not.toBe(
86+
true
87+
);
8688
}
8789

90+
/**
91+
* Get all the Elements matching to the @param labelLocator and retrieves the textContext of each element
92+
* Splits the text with @param delimiter
93+
* @returns the mutable object { [key: 0th_element ]: 1st_element }
94+
*/
8895
async getCountFromLabels(
8996
labelLocator: string,
9097
delimiter: string
9198
): Promise<{ [key: string]: number }> {
9299
const elements = await this.page.locator(labelLocator).all();
93100
const vulnLabelCount = {};
94101
for (const element of elements) {
95-
const innerText = await element.innerText();
96-
const labelArr = await innerText?.split(delimiter);
102+
const innerText = await element.textContent();
103+
const labelArr = await innerText!.split(delimiter);
97104
vulnLabelCount[labelArr[0].trim().toString()] = parseInt(
98105
labelArr[1].trim(),
99106
10
@@ -102,6 +109,11 @@ export class DetailsPage {
102109
return vulnLabelCount;
103110
}
104111

112+
/**
113+
* Retrieves the CVSS value from each row of Vulnerability table
114+
* @returns Count of each CVSS type in { [key: severity ]: count }
115+
*/
116+
105117
async getCVSSCountFromVulnTable(): Promise<{ [key: string]: number }> {
106118
var nextPage = true;
107119
const counts = {
@@ -113,19 +125,21 @@ export class DetailsPage {
113125
Critical: 0,
114126
};
115127
const nextButton = await this.page.locator(
116-
"xpath=(//section[@id='refVulnerabilitiesSection']//button[@data-action='next'])[1]"
128+
`xpath=(//section[@id='refVulnerabilitiesSection']//button[@data-action='next'])[1]`
117129
);
118130

119-
await this.page
120-
.getByLabel("Vulnerabilities within the")
121-
.locator("#pagination-id-top-toggle")
122-
.click();
123-
await this.page.getByRole("menuitem", { name: "100 per page" }).click();
131+
const noOfRows = await this.page.locator(
132+
`xpath=//section[@id="refVulnerabilitiesSection"]//button[@id="pagination-id-top-toggle"]`
133+
);
134+
if (await noOfRows.isEnabled()) {
135+
noOfRows.click();
136+
await this.page.getByRole("menuitem", { name: "100 per page" }).click();
137+
}
124138

125139
while (nextPage) {
126140
const cvssLocator = await this.page
127141
.locator(
128-
"xpath=//table[@aria-label='Vulnerability table']//td[@data-label='CVSS']"
142+
`xpath=//table[@aria-label='Vulnerability table']//td[@data-label='CVSS']`
129143
)
130144
.all();
131145
for (const cvss of cvssLocator) {

0 commit comments

Comments
 (0)