Skip to content

Commit 59555d5

Browse files
committed
Script to delete SBOM and Advisory from UI
Signed-off-by: mrrajan <86094767+mrrajan@users.noreply.github.com.>
1 parent ba9140a commit 59555d5

File tree

10 files changed

+130
-29
lines changed

10 files changed

+130
-29
lines changed

.github/chatmodes/playwright-tester.chatmode.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ mode: 'agent'
3737
- Automatically run test with:
3838
```bash
3939
cd $PROJECT_ROOT/e2e
40-
npx playwright test --project='bdd' --trace on -g "scenario name here" --headed
40+
npx playwright test --project='bdd' --trace on -g "scenario name here"
4141
```
4242
- In case of test failures, the above command launched HTML server to host the test output Press `Ctrl+C` to stop the server
4343

2.05 KB
Binary file not shown.
1.47 KB
Binary file not shown.
12.4 KB
Binary file not shown.
186 KB
Binary file not shown.

e2e/tests/ui/features/@advisory-explorer/advisory-explorer.feature

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,25 @@ Scenario: Display vulnerabilities tied to a single advisory
7070
Examples:
7171
| advisoryName | vulnerabilityID | advisoryType |
7272
| CVE-2023-3223 | CVE-2023-3223 | csaf |
73+
74+
Scenario: Delete an advisory from the Advisory Explorer page
75+
Given User visits Advisory details Page of "<advisoryID>"
76+
When User Clicks on Actions button and Selects Delete option from the drop down
77+
When User select Delete button from the Permanently delete Advisory model window
78+
Then The Advisory deleted message is displayed
79+
And Application Navigates to Advisory list page
80+
And The "<advisoryID>" should not be present on Advisory list page as it is deleted
81+
Examples:
82+
| advisoryID |
83+
| CVE-2025-22130 |
84+
85+
Scenario: Delete an advisory from the Advisory List Page
86+
Given User searches for "<advisoryID>" in the dedicated search bar
87+
When User Selects Delete option from the toggle option from Advisory List Page
88+
When User select Delete button from the Permanently delete Advisory model window
89+
Then The Advisory deleted message is displayed
90+
And Application Navigates to Advisory list page
91+
And The "<advisoryID>" should not be present on Advisory list page as it is deleted
92+
Examples:
93+
| advisoryID |
94+
| CVE-2023-1906 |

e2e/tests/ui/features/@advisory-explorer/advisory-explorer.step.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ import { createBdd } from "playwright-bdd";
22
import { expect } from "playwright/test";
33
import { ToolbarTable } from "../../helpers/ToolbarTable";
44
import { SearchPage } from "../../helpers/SearchPage";
5+
import { AdvisoryListPage } from "../../pages/advisory-list/AdvisoryListPage";
56
import { test } from "../../fixtures";
7+
import { ConfirmDialog } from "../../helpers/ConfirmDialog";
8+
import { DetailsPage } from "../../helpers/DetailsPage";
69

710
export const { Given, When, Then } = createBdd(test);
811

@@ -157,3 +160,60 @@ Then(
157160
).toBeVisible();
158161
},
159162
);
163+
164+
When(
165+
"User Selects Delete option from the toggle option from Advisory List Page",
166+
async ({ page }) => {
167+
const firstRow = page.locator("table tbody tr").first();
168+
const kebabToggle = firstRow.getByRole("button", { name: "Kebab toggle" });
169+
await kebabToggle.click();
170+
await page.getByRole("menuitem", { name: "Delete" }).click();
171+
},
172+
);
173+
174+
When(
175+
"User Clicks on Actions button and Selects Delete option from the drop down",
176+
async ({ page }) => {
177+
const details = new DetailsPage(page);
178+
await details.clickOnPageAction("Delete");
179+
},
180+
);
181+
182+
When(
183+
"User select Delete button from the Permanently delete Advisory model window",
184+
async ({ page }) => {
185+
const dialog = await ConfirmDialog.build(page);
186+
await dialog.verifyTitle("Permanently delete");
187+
await dialog.clickConfirm();
188+
},
189+
);
190+
191+
Then(
192+
"The {string} should not be present on Advisory list page as it is deleted",
193+
async ({ page }, advisoryID: string) => {
194+
const list = await AdvisoryListPage.build(page);
195+
const toolbar = await list.getToolbar();
196+
const table = await list.getTable();
197+
198+
await toolbar.applyFilter({ "Filter text": advisoryID });
199+
await table.waitUntilDataIsLoaded();
200+
await expect(
201+
page.locator(
202+
"table[aria-label='advisory-table'] tbody[aria-label='Table empty']",
203+
),
204+
).toBeVisible();
205+
},
206+
);
207+
208+
Then("Application Navigates to Advisory list page", async ({ page }) => {
209+
await expect(
210+
page.getByRole("heading", { level: 1, name: "Advisories" }),
211+
).toBeVisible();
212+
});
213+
214+
Then("The Advisory deleted message is displayed", async ({ page }) => {
215+
const alertHeading = page.getByRole("heading", { level: 4 }).filter({
216+
hasText: /The Advisory .+ was deleted/,
217+
});
218+
await expect(alertHeading).toBeVisible({ timeout: 10000 });
219+
});

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

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,7 @@ Feature: SBOM Explorer - View SBOM details
119119
When User visits SBOM details Page of "<sbomName>"
120120
When User selects the Tab "Vulnerabilities"
121121
Then Table column "Description" is not sortable
122-
Then Sorting of "Id, Affected dependencies, Published, Updated" Columns Works
123-
#Then Sorting of "CVSS" Columns works
124-
# Bug: https://issues.redhat.com/browse/TC-2598
122+
Then Sorting of "Id, CVSS, Affected dependencies, Published, Updated" Columns Works
125123
Examples:
126124
| sbomName |
127125
| quarkus-bom |
@@ -135,13 +133,25 @@ Feature: SBOM Explorer - View SBOM details
135133
| sbomName | Labels |
136134
| ubi9-minimal-container | RANDOM_LABELS |
137135

138-
Scenario Outline: Delete SBOM
136+
Scenario Outline: Delete SBOM from SBOM Explorer Page
139137
Given An ingested SBOM "<sbomName>" is available
140138
When User visits SBOM details Page of "<sbomName>"
141139
When User Clicks on Actions button and Selects Delete option from the drop down
142140
When User select Delete button from the Permanently delete SBOM model window
143-
Then Application Navigates to SBOM list page
141+
Then The SBOM deleted message is displayed
142+
And Application Navigates to SBOM list page
144143
And The "<sbomName>" should not be present on SBOM list page as it is deleted
145144
Examples:
146145
| sbomName |
147-
| curl |
146+
| MRG-M-3.0.0 |
147+
148+
Scenario Outline: Delete SBOM from SBOM List Page
149+
Given An ingested SBOM "<sbomName>" is available
150+
When User Selects Delete option from the toggle option from SBOM List Page
151+
When User select Delete button from the Permanently delete SBOM model window
152+
Then The SBOM deleted message is displayed
153+
And Application Navigates to SBOM list page
154+
And The "<sbomName>" should not be present on SBOM list page as it is deleted
155+
Examples:
156+
| sbomName |
157+
| rhn_satellite |

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

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,6 @@ Then(
222222
},
223223
);
224224

225-
226225
When(
227226
"User Clicks on Actions button and Selects Delete option from the drop down",
228227
async ({ page }) => {
@@ -234,38 +233,48 @@ When(
234233
When(
235234
"User select Delete button from the Permanently delete SBOM model window",
236235
async ({ page }) => {
237-
const confirm = await ConfirmDialog.build(page);
238-
await confirm.verifyTitle("Permanently delete SBOM?");
239-
await confirm.clickConfirm();
236+
const dialog = await ConfirmDialog.build(page);
237+
await dialog.verifyTitle("Permanently delete");
238+
await dialog.clickConfirm();
240239
},
241240
);
242241

243-
Then(
244-
"Application Navigates to SBOM list page",
242+
When(
243+
"User Selects Delete option from the toggle option from SBOM List Page",
245244
async ({ page }) => {
246-
// Wait for navigation to list view where toolbar and table are present
247-
const list = await SbomListPage.build(page);
248-
await list.getToolbar();
249-
await list.getTable();
250-
await expect(page.getByRole("heading")).toContainText("SBOMs");
245+
const firstRow = page.locator("table tbody tr").first();
246+
const kebabToggle = firstRow.getByRole("button", { name: "Kebab toggle" });
247+
await kebabToggle.click();
248+
await page.getByRole("menuitem", { name: "Delete" }).click();
251249
},
252250
);
253251

252+
Then("Application Navigates to SBOM list page", async ({ page }) => {
253+
await expect(
254+
page.getByRole("heading", { level: 1, name: "SBOMs" }),
255+
).toBeVisible();
256+
});
257+
254258
Then(
255259
"The {string} should not be present on SBOM list page as it is deleted",
256-
async ({ page }, sbomName) => {
260+
async ({ page }, sbomName: string) => {
257261
const list = await SbomListPage.build(page);
258262
const toolbar = await list.getToolbar();
259263
const table = await list.getTable();
260-
261-
await toolbar.applyTextFilter("Filter text", sbomName);
264+
await toolbar.applyFilter({ "Filter text": sbomName });
262265
await table.waitUntilDataIsLoaded();
263-
264-
// Expect table to be empty after filtering for deleted sbom
265266
await expect(
266-
page.locator(`table[aria-label='sbom-table'] tbody[aria-label='Table empty']`),
267+
page.locator(
268+
"table[aria-label='sbom-table'] tbody[aria-label='Table empty']",
269+
),
267270
).toBeVisible();
268271
},
269272
);
270273

271-
274+
Then("The SBOM deleted message is displayed", async ({ page }) => {
275+
// PatternFly toast alerts render the title as a heading inside AlertGroup
276+
const alertHeading = page.getByRole("heading", { level: 4 }).filter({
277+
hasText: /The SBOM .+ was deleted/,
278+
});
279+
await expect(alertHeading).toBeVisible({ timeout: 10000 });
280+
});

e2e/tests/ui/helpers/ConfirmDialog.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@ export class ConfirmDialog {
88
}
99

1010
static async build(page: Page) {
11-
const dialog = page.locator("#confirm-dialog");
11+
const dialog = page.getByRole("dialog", { name: "Confirm dialog" });
1212
await expect(dialog).toBeVisible();
13-
await expect(page.getByRole("dialog", { name: "Confirm dialog" })).toBeVisible();
1413
return new ConfirmDialog(page);
1514
}
1615

1716
async verifyTitle(title: string) {
18-
await expect(this._page.locator("#confirm-dialog")).toContainText(title);
17+
const dialog = this._page.getByRole("dialog", { name: "Confirm dialog" });
18+
await expect(dialog).toContainText(title);
1919
}
2020

2121
async clickConfirm() {
22-
const confirmBtn = this._page.locator("#confirm-dialog-button");
22+
const confirmBtn = this._page.getByRole("button", { name: "confirm" });
2323
await expect(confirmBtn).toBeVisible();
2424
await expect(confirmBtn).toBeEnabled();
2525
await confirmBtn.click();

0 commit comments

Comments
 (0)