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

Commit e094eac

Browse files
committed
Add UI Tests for SBOM Upload
Adds feature file and step implementation for testing of page for Uploading SBOM. TC-2340
1 parent 5bb94fd commit e094eac

10 files changed

+359
-0
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"spdxVersion": "SPDX-2.3",
3+
"dataLicense": "CC0-1.0",
4+
"SPDXID": "SPDXRef-SBOM-Upload-001",
5+
"name": "test-upload-001",
6+
"documentNamespace": "trustify-tests",
7+
"creationInfo": {
8+
"creators": ["trustify-tests contributors"],
9+
"created": "2025-04-29T12:34:56Z"
10+
},
11+
"packages": [
12+
{
13+
"name": "test-upload-package-001",
14+
"SPDXID": "SPDXRef-Package-test-upload-001",
15+
"versionInfo": "0.0.1",
16+
"downloadLocation": "NOASSERTION",
17+
"sourceInfo": "written by hand",
18+
"licenseConcluded": "NONE",
19+
"licenseDeclared": "NOASSERTION",
20+
"copyrightText": "NOASSERTION",
21+
"externalRefs": [
22+
{
23+
"referenceCategory": "PACKAGE_MANAGER",
24+
"referenceLocator": "pkg:trustify-tests/upload/tt-upload@0.0.1?fakeQuali=fier",
25+
"referenceType": "purl"
26+
}
27+
]
28+
}
29+
],
30+
"relationships": [
31+
{
32+
"spdxElementId": "SPDXRef-SBOM-Upload-001",
33+
"relatedSpdxElement": "SPDXRef-Package-test-upload-001",
34+
"relationshipType": "DESCRIBES"
35+
}
36+
]
37+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"spdxVersion": "SPDX-2.3",
3+
"dataLicense": "CC0-1.0",
4+
"SPDXID": "SPDXRef-SBOM-Upload-002",
5+
"name": "test-upload-002",
6+
"documentNamespace": "trustify-tests",
7+
"creationInfo": {
8+
"creators": ["trustify-tests contributors"],
9+
"created": "2025-04-29T12:34:56Z"
10+
},
11+
"packages": [
12+
{
13+
"name": "test-upload-package-002",
14+
"SPDXID": "SPDXRef-Package-test-upload-002",
15+
"versionInfo": "0.0.2",
16+
"downloadLocation": "NOASSERTION",
17+
"sourceInfo": "written by hand",
18+
"licenseConcluded": "NONE",
19+
"licenseDeclared": "NOASSERTION",
20+
"copyrightText": "NOASSERTION",
21+
"externalRefs": [
22+
{
23+
"referenceCategory": "PACKAGE_MANAGER",
24+
"referenceLocator": "pkg:trustify-tests/upload/tt-upload@0.0.2?fakeQuali=fier",
25+
"referenceType": "purl"
26+
}
27+
]
28+
}
29+
],
30+
"relationships": [
31+
{
32+
"spdxElementId": "SPDXRef-SBOM-Upload-002",
33+
"relatedSpdxElement": "SPDXRef-Package-test-upload-002",
34+
"relationshipType": "DESCRIBES"
35+
}
36+
]
37+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"spdxVersion": "SPDX-2.3",
3+
"dataLicense": "CC0-1.0",
4+
"SPDXID": "SPDXRef-SBOM-Upload-003",
5+
"name": "test-upload-003",
6+
"documentNamespace": "trustify-tests",
7+
"creationInfo": {
8+
"creators": ["trustify-tests contributors"],
9+
"created": "2025-04-29T12:34:56Z"
10+
},
11+
"packages": [
12+
{
13+
"name": "test-upload-package-003",
14+
"SPDXID": "SPDXRef-Package-test-upload-003",
15+
"versionInfo": "0.0.3",
16+
"downloadLocation": "NOASSERTION",
17+
"sourceInfo": "written by hand",
18+
"licenseConcluded": "NONE",
19+
"licenseDeclared": "NOASSERTION",
20+
"copyrightText": "NOASSERTION",
21+
"externalRefs": [
22+
{
23+
"referenceCategory": "PACKAGE_MANAGER",
24+
"referenceLocator": "pkg:trustify-tests/upload/tt-upload@0.0.3?fakeQuali=fier",
25+
"referenceType": "purl"
26+
}
27+
]
28+
}
29+
],
30+
"relationships": [
31+
{
32+
"spdxElementId": "SPDXRef-SBOM-Upload-003",
33+
"relatedSpdxElement": "SPDXRef-Package-test-upload-003",
34+
"relationshipType": "DESCRIBES"
35+
}
36+
]
37+
}
541 Bytes
Binary file not shown.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"bomFormat": "CycloneDX",
3+
"specVersion": "1.3",
4+
"serialNumber": "urn:uuid:00000000-1111-2222-4444-555500000004",
5+
"version": 1,
6+
"metadata": {
7+
"timestamp": "2023-02-27T23:15:50-08:00",
8+
"tools": [
9+
{
10+
"vendor": "trustify-tests",
11+
"name": "contributors",
12+
"version": "1"
13+
}
14+
],
15+
"component": {
16+
"bom-ref": "0040000000000001",
17+
"type": "container",
18+
"name": "test-upload-container-004",
19+
"version": "0.0.4",
20+
"purl": "pkg:trustify-tests/upload/tt-upload-cont@0.0.4"
21+
}
22+
},
23+
"components": [
24+
{
25+
"bom-ref": "0040000000000002",
26+
"type": "application",
27+
"name": "test-upload-package-004",
28+
"version": "0.0.4",
29+
"cpe": "cpe:2.3:a:trustify-tests/upload:tt-upload:0.0.4:*:*:*:*:*:*:*",
30+
"purl": "pkg:trustify-tests/upload/tt-upload@0.0.4"
31+
}
32+
]
33+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"bomFormat": "CycloneDX",
3+
"specVersion": "1.3",
4+
"serialNumber": "urn:uuid:00000000-1111-2222-4444-555500000005",
5+
"version": 1,
6+
"metadata": {
7+
"timestamp": "2023-02-27T23:15:50-08:00",
8+
"tools": [
9+
{
10+
"vendor": "trustify-tests",
11+
"name": "contributors",
12+
"version": "1"
13+
}
14+
],
15+
"component": {
16+
"bom-ref": "0050000000000001",
17+
"type": "container",
18+
"name": "test-upload-container-005",
19+
"version": "0.0.5",
20+
"purl": "pkg:trustify-tests/upload/tt-upload-cont@0.0.5"
21+
}
22+
},
23+
"components": [
24+
{
25+
"bom-ref": "0050000000000002",
26+
"type": "application",
27+
"name": "test-upload-package-005",
28+
"version": "0.0.5",
29+
"cpe": "cpe:2.3:a:trustify-tests/upload:tt-upload:0.0.5:*:*:*:*:*:*:*",
30+
"purl": "pkg:trustify-tests/upload/tt-upload@0.0.5"
31+
}
32+
]
33+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"bomFormat": "CycloneDX",
3+
"specVersion": "1.3",
4+
"serialNumber": "urn:uuid:00000000-1111-2222-4444-555500000006",
5+
"version": 1,
6+
"metadata": {
7+
"timestamp": "2023-02-27T23:15:50-08:00",
8+
"tools": [
9+
{
10+
"vendor": "trustify-tests",
11+
"name": "contributors",
12+
"version": "1"
13+
}
14+
],
15+
"component": {
16+
"bom-ref": "0060000000000001",
17+
"type": "container",
18+
"name": "test-upload-container-006",
19+
"version": "0.0.6",
20+
"purl": "pkg:trustify-tests/upload/tt-upload-cont@0.0.6"
21+
}
22+
},
23+
"components": [
24+
{
25+
"bom-ref": "0060000000000002",
26+
"type": "application",
27+
"name": "test-upload-package-006",
28+
"version": "0.0.6",
29+
"cpe": "cpe:2.3:a:trustify-tests/upload:tt-upload:0.0.6:*:*:*:*:*:*:*",
30+
"purl": "pkg:trustify-tests/upload/tt-upload@0.0.6"
31+
}
32+
]
33+
}
406 Bytes
Binary file not shown.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
Feature: Upload SBOM
2+
3+
Background:
4+
Given User is authenticated
5+
6+
Scenario Outline: Verify Upload SBOM page content
7+
When User visits Upload page
8+
Then SBOM upload tab is selected
9+
And Drag and drop instructions are visible
10+
And Upload button is present
11+
And Accepted file types are described
12+
13+
Scenario Outline: Upload single SBOM
14+
Given User visits Upload page
15+
When User uploads "single SBOM"
16+
Then Total uploaded count is shown for "single SBOM"
17+
And Results of uploading "single SBOM" are visible
18+
19+
Scenario Outline: Upload multiple SBOMs
20+
Given User visits Upload page
21+
When User uploads "multiple SBOMs"
22+
Then Total uploaded count is shown for "multiple SBOMs"
23+
And Results of uploading "multiple SBOMs" are visible
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import fs from "fs";
2+
import path from "path";
3+
import { expect, test } from "@playwright/test";
4+
import { createBdd } from "playwright-bdd";
5+
6+
export const { Given, When, Then, Step } = createBdd();
7+
8+
const MENU_UPLOAD = "Upload";
9+
const HEADER_UPLOAD = "Upload";
10+
const BUTTON_UPLOAD = "Upload";
11+
const TAB_SBOM = "SBOM";
12+
const DRAG_INSTRUCTIONS = "Drag and drop files here or";
13+
const ACCEPTED_TYPES_DESC = "Accepted file types:";
14+
15+
const TIMEOUT_PAGELOAD_IMPORT = 2_000;
16+
const TIMEOUT_UPLOAD_DONE = 90_000;
17+
18+
const SBOM_SET = {
19+
"single SBOM": ["test-upload-001.spdx.json"],
20+
"multiple SBOMs": [
21+
"test-upload-002.spdx.json",
22+
"test-upload-003.spdx.json.bz2",
23+
"test-upload-004.cdx.json",
24+
"test-upload-005.cdx.json",
25+
"test-upload-006.cdx.json.bz2",
26+
],
27+
};
28+
29+
const visitUploadPage = async ({ page }) => {
30+
await page.goto("/importers"); // dont care which page here, importers is lot faster than Dashboard
31+
await page.getByRole("link", { name: MENU_UPLOAD }).click();
32+
33+
const header = page.locator(`xpath=(//h1[text()="${HEADER_UPLOAD}"])`);
34+
await header.waitFor({ state: "visible", timeout: TIMEOUT_PAGELOAD_IMPORT });
35+
};
36+
Step("User visits Upload page", visitUploadPage);
37+
38+
function assetsPath(files: string[]): string[] {
39+
return files.map((e) => path.join(__dirname, "assets", e));
40+
}
41+
42+
// PAGE CONTENT
43+
44+
Then("SBOM upload tab is selected", async ({ page }) => {
45+
await expect(page.getByRole("tab", { name: TAB_SBOM })).toHaveAttribute(
46+
"aria-selected",
47+
"true"
48+
);
49+
});
50+
51+
Then("Drag and drop instructions are visible", async ({ page }) => {
52+
await expect(
53+
page.getByLabel("SBOM").getByText(DRAG_INSTRUCTIONS)
54+
).toBeVisible();
55+
});
56+
57+
Then("Upload button is present", async ({ page }) => {
58+
await expect(page.getByRole("button", { name: "Upload" })).toBeVisible();
59+
});
60+
61+
Then("Accepted file types are described", async ({ page }) => {
62+
expect(page.getByLabel("SBOM").getByText(ACCEPTED_TYPES_DESC)).toBeVisible();
63+
});
64+
65+
// FILE UPLOAD
66+
67+
When("User uploads {string}", async ({ page }, data_set_key) => {
68+
const files = assetsPath(SBOM_SET[data_set_key]);
69+
70+
const fileChooserPromise = page.waitForEvent("filechooser");
71+
await page.getByRole("button", { name: BUTTON_UPLOAD, exact: true }).click();
72+
const fileChooser = await fileChooserPromise;
73+
74+
await fileChooser.setFiles(files);
75+
});
76+
77+
// FILE UPLOAD RESULTS
78+
79+
Then(
80+
"Total uploaded count is shown for {string}",
81+
async ({ page }, data_set_key) => {
82+
test.setTimeout(TIMEOUT_UPLOAD_DONE);
83+
const count = SBOM_SET[data_set_key].length;
84+
85+
await expect(
86+
page.locator(
87+
"#upload-sbom-tab-content .pf-v6-c-multiple-file-upload__status-progress"
88+
)
89+
).toContainText(`${count} of ${count} files uploaded`, {
90+
timeout: TIMEOUT_UPLOAD_DONE,
91+
});
92+
}
93+
);
94+
95+
Then(
96+
"Results of uploading {string} are visible",
97+
async ({ page }, data_set_key) => {
98+
const individual_results = page.locator(
99+
".pf-v6-c-expandable-section__content .pf-v6-c-multiple-file-upload__status-item"
100+
);
101+
102+
// expect correct count of individual result entries
103+
await expect(individual_results).toHaveCount(SBOM_SET[data_set_key].length);
104+
105+
// now upload itself may take a while so increase overall test timeout
106+
test.setTimeout(TIMEOUT_UPLOAD_DONE);
107+
108+
// expect name of each sbom to be in the list of results
109+
await expect(
110+
individual_results.locator(
111+
".pf-v6-c-multiple-file-upload__status-item-progress-text"
112+
)
113+
).toContainText(SBOM_SET[data_set_key], {
114+
timeout: TIMEOUT_UPLOAD_DONE,
115+
});
116+
117+
// expect result for each sbom to be present and have 100% state
118+
await expect(
119+
individual_results.locator(
120+
".pf-v6-c-progress__status .pf-v6-c-progress__measure"
121+
)
122+
).toContainText(new Array(SBOM_SET[data_set_key].length).fill("100%"), {
123+
timeout: TIMEOUT_UPLOAD_DONE,
124+
});
125+
}
126+
);

0 commit comments

Comments
 (0)