# Instructions - Following Playwright test failed. - Explain why, be concise, respect Playwright best practices. - Provide a snippet of code with the fix, if possible. # Test info - Name: ui/component.test.ts >> Component UI Test Suite >> Verify CI >> verify CI provider on CI tab - Location: tests/ui/component.test.ts:83:5 # Error details ``` TimeoutError: Step timeout of 40000ms exceeded. ``` ``` Error: expect(locator).toBeVisible() failed Locator: getByText('STEP-SHOW-SBOM') Expected: visible Error: element(s) not found Call log: - Expect "toBeVisible" with timeout 60000ms - waiting for getByText('STEP-SHOW-SBOM') ``` # Page snapshot ```yaml - generic [ref=e1]: - generic [ref=e3]: - navigation [ref=e5]: - generic [ref=e6]: - link [ref=e8] [cursor=pointer]: - /url: / - img [ref=e9] - generic [ref=e18]: - img [ref=e20] - combobox [ref=e22] - link [ref=e26] [cursor=pointer]: - /url: /create - img [ref=e28] - button [ref=e31] [cursor=pointer]: - img [ref=e32] - button [ref=e35] [cursor=pointer]: - img [ref=e36] - button [ref=e39] [cursor=pointer]: - img [ref=e40] - separator [ref=e42] - button [ref=e44] [cursor=pointer]: - generic [ref=e45]: - img [ref=e46] - paragraph [ref=e49]: Admin - img [ref=e50] - generic [ref=e53]: - generic [ref=e55]: - generic [ref=e58]: - link [ref=e60] [cursor=pointer]: - /url: / - img [ref=e64] - generic [ref=e66]: Home - link [ref=e68] [cursor=pointer]: - /url: /catalog - img [ref=e72] - generic [ref=e74]: Catalog - link [ref=e76] [cursor=pointer]: - /url: /api-docs - img [ref=e80] - generic [ref=e82]: APIs - link [ref=e84] [cursor=pointer]: - /url: /learning-paths - img [ref=e88] - generic [ref=e90]: Learning Paths - separator [ref=e91] - link [ref=e94] [cursor=pointer]: - /url: /docs - img [ref=e98] - generic [ref=e100]: Docs - generic [ref=e101]: - separator [ref=e102] - button [ref=e103] [cursor=pointer]: - generic [ref=e104]: - img [ref=e108] - generic [ref=e111]: Administration - img [ref=e113] - main [ref=e115]: - generic [ref=e116]: - generic [ref=e117]: - paragraph [ref=e118]: component — service - heading [level=1] [ref=e119]: - generic [ref=e120]: - generic [ref=e122]: e2e-tests-go-kvwscftl - button [ref=e123] [cursor=pointer]: - img [ref=e126] - generic [ref=e128]: - generic [ref=e130]: - paragraph [ref=e131]: Owner - paragraph [ref=e132]: - link [ref=e133] [cursor=pointer]: - /url: /catalog/default/user/guest - generic [ref=e134]: - img [ref=e136] - text: user:guest - generic [ref=e139]: - paragraph [ref=e140]: Lifecycle - paragraph [ref=e141]: experimental - button [ref=e142] [cursor=pointer]: - img [ref=e144] - tablist [ref=e150]: - tab [ref=e151] [cursor=pointer]: Overview - tab [ref=e152] [cursor=pointer]: Topology - tab [selected] [ref=e153] [cursor=pointer]: CI - tab [ref=e154] [cursor=pointer]: CD - tab [ref=e155] [cursor=pointer]: Kubernetes - tab [ref=e156] [cursor=pointer]: API - tab [ref=e157] [cursor=pointer]: Dependencies - tab [ref=e158] [cursor=pointer]: Docs - article [ref=e160]: - generic [ref=e163]: - generic [ref=e167]: - generic [ref=e168]: - paragraph [ref=e169]: Cluster - generic [ref=e172]: - button [ref=e173] [cursor=pointer]: - paragraph [ref=e174]: rhdh-cluster - textbox: rhdh-cluster - img - generic [ref=e175]: - paragraph [ref=e176]: Status - generic [ref=e179]: - button [ref=e180] [cursor=pointer]: - paragraph [ref=e181]: All - textbox: All - img - generic [ref=e182]: - generic [ref=e183]: - button [disabled]: - generic: - img - button [ref=e185] [cursor=pointer]: - img [ref=e187] - separator [ref=e189] - generic [ref=e192]: - generic [ref=e193]: - heading [level=2] [ref=e194]: Pipeline Runs - generic [ref=e196]: - img [ref=e198] - textbox [ref=e200]: - /placeholder: Search - generic [ref=e201]: - button [disabled]: - generic: - img - table [ref=e202]: - rowgroup [ref=e203]: - row [ref=e204]: - columnheader [ref=e205] - columnheader [ref=e206]: - button [ref=e207] [cursor=pointer]: - text: NAME - img [ref=e208] - columnheader [ref=e210]: - button [ref=e211] [cursor=pointer]: - text: VULNERABILITIES - img [ref=e212] - columnheader [ref=e214]: - button [ref=e215] [cursor=pointer]: - text: STATUS - img [ref=e216] - columnheader [ref=e218]: - button [ref=e219] [cursor=pointer]: - text: TASK STATUS - img [ref=e220] - columnheader [ref=e222]: - button [ref=e223] [cursor=pointer]: - text: STARTED - img [ref=e224] - columnheader [ref=e226]: - button [ref=e227] [cursor=pointer]: - text: DURATION - img [ref=e228] - columnheader [ref=e230]: ACTIONS - rowgroup [ref=e231]: - row [ref=e232]: - cell [ref=e233]: - button [ref=e234] [cursor=pointer]: - img [ref=e236] - cell [ref=e238]: - generic [ref=e240]: - generic [ref=e242]: PLR - generic [ref=e243]: e2e-tests-go-kvwscftl-gitops-on-pull-request-78gsh - img [ref=e247] - cell [ref=e250]: - generic [ref=e251]: "-" - cell [ref=e252]: - paragraph [ref=e253]: - img [ref=e256] - generic [ref=e258]: Succeeded - cell [ref=e259] - cell [ref=e260]: - time [ref=e262]: 5/14/2026, 3:49:58 PM - cell [ref=e263]: 44 seconds - cell [ref=e264]: - generic [ref=e265]: - button [ref=e268] [cursor=pointer]: - img [ref=e270] - button [ref=e274] [cursor=pointer]: - img [ref=e276] - button [disabled] [ref=e280]: - img [ref=e282] - button [disabled] [ref=e286]: - img [ref=e288] - row [ref=e290]: - cell [ref=e291] - row [ref=e292]: - cell [ref=e293]: - button [ref=e294] [cursor=pointer]: - img [ref=e296] - cell [ref=e298]: - generic [ref=e300]: - generic [ref=e302]: PLR - generic [ref=e303]: e2e-tests-go-kvwscftl-gitops-on-pull-request-n44xv - img [ref=e307] - cell [ref=e310]: - generic [ref=e311]: "-" - cell [ref=e312]: - paragraph [ref=e313]: - img [ref=e316] - generic [ref=e318]: Succeeded - cell [ref=e319] - cell [ref=e320]: - time [ref=e322]: 5/14/2026, 3:48:01 PM - cell [ref=e323]: 46 seconds - cell [ref=e324]: - generic [ref=e325]: - button [ref=e328] [cursor=pointer]: - img [ref=e330] - button [ref=e334] [cursor=pointer]: - img [ref=e336] - button [disabled] [ref=e340]: - img [ref=e342] - button [disabled] [ref=e346]: - img [ref=e348] - row [ref=e350]: - cell [ref=e351] - row [ref=e352]: - cell [ref=e353]: - button [ref=e354] [cursor=pointer]: - img [ref=e356] - cell [ref=e358]: - generic [ref=e360]: - generic [ref=e362]: PLR - generic [ref=e363]: e2e-tests-go-kvwscftl-on-push-4gdjk - img [ref=e367] - cell [ref=e370]: - generic [ref=e371]: - generic [ref=e372]: - img [ref=e375] - generic [ref=e377]: "0" - generic [ref=e378]: - img [ref=e381] - generic [ref=e384]: "4" - generic [ref=e385]: - img [ref=e388] - generic [ref=e390]: "8" - generic [ref=e391]: - img [ref=e394] - generic [ref=e397]: "15" - cell [ref=e398]: - paragraph [ref=e399]: - img [ref=e402] - generic [ref=e404]: Succeeded - cell [ref=e405] - cell [ref=e406]: - time [ref=e408]: 5/14/2026, 3:45:15 PM - cell [ref=e409]: 1 minute 56 seconds - cell [ref=e410]: - generic [ref=e411]: - button [ref=e414] [cursor=pointer]: - img [ref=e416] - button [ref=e420] [cursor=pointer]: - img [ref=e422] - button [ref=e426] [cursor=pointer]: - img [ref=e428] - button [ref=e432] [cursor=pointer]: - img [ref=e434] - row [ref=e436]: - cell [ref=e437] - row [ref=e438]: - cell [ref=e439]: - button [ref=e440] [cursor=pointer]: - img [ref=e442] - cell [ref=e444]: - generic [ref=e446]: - generic [ref=e448]: PLR - generic [ref=e449]: e2e-tests-go-kvwscftl-on-pull-request-bh48g - img [ref=e453] - cell [ref=e456]: - generic [ref=e457]: - generic [ref=e458]: - img [ref=e461] - generic [ref=e463]: "0" - generic [ref=e464]: - img [ref=e467] - generic [ref=e470]: "4" - generic [ref=e471]: - img [ref=e474] - generic [ref=e476]: "8" - generic [ref=e477]: - img [ref=e480] - generic [ref=e483]: "15" - cell [ref=e484]: - paragraph [ref=e485]: - img [ref=e488] - generic [ref=e490]: Succeeded - cell [ref=e491] - cell [ref=e492]: - time [ref=e494]: 5/14/2026, 3:42:58 PM - cell [ref=e495]: 1 minute 53 seconds - cell [ref=e496]: - generic [ref=e497]: - button [ref=e500] [cursor=pointer]: - img [ref=e502] - button [ref=e506] [cursor=pointer]: - img [ref=e508] - button [ref=e512] [cursor=pointer]: - img [ref=e514] - button [ref=e518] [cursor=pointer]: - img [ref=e520] - row [ref=e522]: - cell [ref=e523] - row [ref=e524]: - cell [ref=e525]: - button [ref=e526] [cursor=pointer]: - img [ref=e528] - cell [ref=e530]: - generic [ref=e532]: - generic [ref=e534]: PLR - generic [ref=e535]: e2e-tests-go-kvwscftl-on-push-n9fgj - img [ref=e539] - cell [ref=e542]: - generic [ref=e543]: - generic [ref=e544]: - img [ref=e547] - generic [ref=e549]: "0" - generic [ref=e550]: - img [ref=e553] - generic [ref=e556]: "4" - generic [ref=e557]: - img [ref=e560] - generic [ref=e562]: "8" - generic [ref=e563]: - img [ref=e566] - generic [ref=e569]: "15" - cell [ref=e570]: - paragraph [ref=e571]: - img [ref=e574] - generic [ref=e576]: Succeeded - cell [ref=e577] - cell [ref=e578]: - time [ref=e580]: 5/14/2026, 3:42:01 PM - cell [ref=e581]: 2 minutes 13 seconds - cell [ref=e582]: - generic [ref=e583]: - button [ref=e586] [cursor=pointer]: - img [ref=e588] - button [ref=e592] [cursor=pointer]: - img [ref=e594] - button [ref=e598] [cursor=pointer]: - img [ref=e600] - button [ref=e604] [cursor=pointer]: - img [ref=e606] - row [ref=e608]: - cell [ref=e609] - row [ref=e610]: - cell [ref=e611]: - generic [ref=e612]: - generic [ref=e613]: - button [ref=e614] [cursor=pointer]: 5 rows - textbox: "5" - img - paragraph [ref=e615]: 1-5 of 5 - generic [ref=e616]: - button [disabled]: - generic: - img - button [disabled]: - generic: - img - dialog [ref=e619]: - generic "PipelineRun Logs" [ref=e620]: - heading "PLR e2e-tests-go-kvwscftl-on-push-4gdjk close" [level=2] [ref=e621]: - generic [ref=e622]: - generic [ref=e623]: - generic [ref=e625]: PLR - generic [ref=e626]: e2e-tests-go-kvwscftl-on-push-4gdjk - button "close" [ref=e627] [cursor=pointer]: - img [ref=e629] - generic [ref=e631]: - generic [ref=e632]: - button "Download" [ref=e634] [cursor=pointer]: - generic [ref=e635]: - img [ref=e636] - text: Download - button "Download all tasks logs" [ref=e639] [cursor=pointer]: - generic [ref=e640]: - img [ref=e641] - text: Download all tasks logs - generic [ref=e643]: - generic [ref=e647]: - button "clone-repository 16s" [ref=e649] [cursor=pointer]: - generic [ref=e650]: - img [ref=e653] - generic [ref=e657]: - heading "clone-repository" [level=6] [ref=e658] - generic [ref=e659]: 16s - button "build 1m 18s" [ref=e663] [cursor=pointer]: - generic [ref=e664]: - img [ref=e667] - generic [ref=e671]: - heading "build" [level=6] [ref=e672] - generic [ref=e673]: 1m 18s - button "deploy 7s" [ref=e677] [cursor=pointer]: - generic [ref=e678]: - img [ref=e681] - generic [ref=e685]: - heading "deploy" [level=6] [ref=e686] - generic [ref=e687]: 7s - button "scan 13s" [ref=e691] [cursor=pointer]: - generic [ref=e692]: - img [ref=e695] - generic [ref=e699]: - heading "scan" [level=6] [ref=e700] - generic [ref=e701]: 13s - button "deployment-check 8s" [ref=e705] [cursor=pointer]: - generic [ref=e706]: - img [ref=e709] - generic [ref=e713]: - heading "deployment-check" [level=6] [ref=e714] - generic [ref=e715]: 8s - button "summarize 7s" [ref=e719] [cursor=pointer]: - generic [ref=e720]: - img [ref=e723] - generic [ref=e727]: - heading "summarize" [level=6] [ref=e728] - generic [ref=e729]: 7s - button "show-sbom 7s" [ref=e733] [cursor=pointer]: - generic [ref=e734]: - img [ref=e737] - generic [ref=e741]: - heading "show-sbom" [level=6] [ref=e742] - generic [ref=e743]: 7s - generic [ref=e747]: - generic [ref=e748]: - button [ref=e749] [cursor=pointer]: - img [ref=e751] - paragraph [ref=e753]: 1/1 - button [ref=e754] [cursor=pointer]: - img [ref=e756] - textbox "Search" [active] [ref=e760]: STEP-SHOW-SBOM - button [ref=e761] [cursor=pointer]: - img [ref=e763] - generic [ref=e766]: - generic [ref=e767]: - row "7955" [ref=e768] [cursor=pointer] - generic [ref=e769]: "{" - generic [ref=e770]: - row "7956" [ref=e771] [cursor=pointer] - generic [ref=e772]: "\"ref\": \"pkg:rpm/redhat/libgcc@11.5.0-11.el9?arch=x86_64&distro=rhel-9.7&package-id=06e2c48d975ea1da&upstream=gcc-11.5.0-11.el9.src.rpm\"," - generic [ref=e773]: - row "7957" [ref=e774] [cursor=pointer] - generic [ref=e775]: "\"dependsOn\": [" - generic [ref=e776]: - row "7958" [ref=e777] [cursor=pointer] - generic [ref=e778]: "\"pkg:rpm/redhat/glibc@2.34-231.el9_7.10?arch=x86_64&distro=rhel-9.7&package-id=6cae8570f9132c10&upstream=glibc-2.34-231.el9_7.10.src.rpm\"" - generic [ref=e779]: - row "7959" [ref=e780] [cursor=pointer] - generic [ref=e781]: "]" - generic [ref=e782]: - row "7960" [ref=e783] [cursor=pointer] - generic [ref=e784]: "}," - generic [ref=e785]: - row "7961" [ref=e786] [cursor=pointer] - generic [ref=e787]: "{" - generic [ref=e788]: - row "7962" [ref=e789] [cursor=pointer] - generic [ref=e790]: "\"ref\": \"pkg:rpm/redhat/libselinux@3.6-3.el9?arch=x86_64&distro=rhel-9.7&package-id=ccc2461d41d72dde&upstream=libselinux-3.6-3.el9.src.rpm\"," - generic [ref=e791]: - row "7963" [ref=e792] [cursor=pointer] - generic [ref=e793]: "\"dependsOn\": [" - generic [ref=e794]: - row "7964" [ref=e795] [cursor=pointer] - generic [ref=e796]: "\"pkg:rpm/redhat/glibc@2.34-231.el9_7.10?arch=x86_64&distro=rhel-9.7&package-id=6cae8570f9132c10&upstream=glibc-2.34-231.el9_7.10.src.rpm\"," - generic [ref=e797]: - row "7965" [ref=e798] [cursor=pointer] - generic [ref=e799]: "\"pkg:rpm/redhat/libsepol@3.6-3.el9?arch=x86_64&distro=rhel-9.7&package-id=cecb06c03b371de6&upstream=libsepol-3.6-3.el9.src.rpm\"," - generic [ref=e800]: - row "7966" [ref=e801] [cursor=pointer] - generic [ref=e802]: "\"pkg:rpm/redhat/pcre2@10.40-6.el9?arch=x86_64&distro=rhel-9.7&package-id=d52857c4436af57f&upstream=pcre2-10.40-6.el9.src.rpm\"" - generic [ref=e803]: - row "7967" [ref=e804] [cursor=pointer] - generic [ref=e805]: "]" - generic [ref=e806]: - row "7968" [ref=e807] [cursor=pointer] - generic [ref=e808]: "}," - generic [ref=e809]: - row "7969" [ref=e810] [cursor=pointer] - generic [ref=e811]: "{" - generic [ref=e812]: - row "7970" [ref=e813] [cursor=pointer] - generic [ref=e814]: "\"ref\": \"pkg:rpm/redhat/libsepol@3.6-3.el9?arch=x86_64&distro=rhel-9.7&package-id=cecb06c03b371de6&upstream=libsepol-3.6-3.el9.src.rpm\"," - generic [ref=e815]: - row "7971" [ref=e816] [cursor=pointer] - generic [ref=e817]: "\"dependsOn\": [" - generic [ref=e818]: - row "7972" [ref=e819] [cursor=pointer] - generic [ref=e820]: "\"pkg:rpm/redhat/glibc@2.34-231.el9_7.10?arch=x86_64&distro=rhel-9.7&package-id=6cae8570f9132c10&upstream=glibc-2.34-231.el9_7.10.src.rpm\"" - generic [ref=e821]: - row "7973" [ref=e822] [cursor=pointer] - generic [ref=e823]: "]" - generic [ref=e824]: - row "7974" [ref=e825] [cursor=pointer] - generic [ref=e826]: "}," - generic [ref=e827]: - row "7975" [ref=e828] [cursor=pointer] - generic [ref=e829]: "{" - generic [ref=e830]: - row "7976" [ref=e831] [cursor=pointer] - generic [ref=e832]: "\"ref\": \"pkg:rpm/redhat/ncurses-libs@6.2-12.20210508.el9?arch=x86_64&distro=rhel-9.7&package-id=9dc1b34cdde2c695&upstream=ncurses-6.2-12.20210508.el9.src.rpm\"," - generic [ref=e833]: - row "7977" [ref=e834] [cursor=pointer] - generic [ref=e835]: "\"dependsOn\": [" - generic [ref=e836]: - row "7978" [ref=e837] [cursor=pointer] - generic [ref=e838]: "\"pkg:rpm/redhat/glibc@2.34-231.el9_7.10?arch=x86_64&distro=rhel-9.7&package-id=6cae8570f9132c10&upstream=glibc-2.34-231.el9_7.10.src.rpm\"," - generic [ref=e839]: - row "7979" [ref=e840] [cursor=pointer] - generic [ref=e841]: "\"pkg:rpm/redhat/ncurses-base@6.2-12.20210508.el9?arch=noarch&distro=rhel-9.7&package-id=cb11b32d6ce6627c&upstream=ncurses-6.2-12.20210508.el9.src.rpm\"" - generic [ref=e842]: - row "7980" [ref=e843] [cursor=pointer] - generic [ref=e844]: "]" - generic [ref=e845]: - row "7981" [ref=e846] [cursor=pointer] - generic [ref=e847]: "}," - generic [ref=e848]: - row "7982" [ref=e849] [cursor=pointer] - generic [ref=e850]: "{" - generic [ref=e851]: - row "7983" [ref=e852] [cursor=pointer] - generic [ref=e853]: "\"ref\": \"pkg:rpm/redhat/pcre2@10.40-6.el9?arch=x86_64&distro=rhel-9.7&package-id=d52857c4436af57f&upstream=pcre2-10.40-6.el9.src.rpm\"," - generic [ref=e854]: - row "7984" [ref=e855] [cursor=pointer] - generic [ref=e856]: "\"dependsOn\": [" - generic [ref=e857]: - row "7985" [ref=e858] [cursor=pointer] - generic [ref=e859]: "\"pkg:rpm/redhat/glibc@2.34-231.el9_7.10?arch=x86_64&distro=rhel-9.7&package-id=6cae8570f9132c10&upstream=glibc-2.34-231.el9_7.10.src.rpm\"," - generic [ref=e860]: - row "7986" [ref=e861] [cursor=pointer] - generic [ref=e862]: "\"pkg:rpm/redhat/pcre2-syntax@10.40-6.el9?arch=noarch&distro=rhel-9.7&package-id=79b3a388130aa9b9&upstream=pcre2-10.40-6.el9.src.rpm\"" - generic [ref=e863]: - row "7987" [ref=e864] [cursor=pointer] - generic [ref=e865]: "]" - generic [ref=e866]: - row "7988" [ref=e867] [cursor=pointer] - generic [ref=e868]: "}," - generic [ref=e869]: - row "7989" [ref=e870] [cursor=pointer] - generic [ref=e871]: "{" - generic [ref=e872]: - row "7990" [ref=e873] [cursor=pointer] - generic [ref=e874]: "\"ref\": \"pkg:rpm/redhat/setup@2.13.7-10.el9?arch=noarch&distro=rhel-9.7&package-id=5e411c4e4f6d3d56&upstream=setup-2.13.7-10.el9.src.rpm\"," - generic [ref=e875]: - row "7991" [ref=e876] [cursor=pointer] - generic [ref=e877]: "\"dependsOn\": [" - generic [ref=e878]: - row "7992" [ref=e879] [cursor=pointer] - generic [ref=e880]: "\"pkg:rpm/redhat/redhat-release@9.7-0.10.el9?arch=x86_64&distro=rhel-9.7&package-id=b68bfdee47c6f5da&upstream=redhat-release-9.7-0.10.el9.src.rpm\"" - generic [ref=e881]: - row "7993" [ref=e882] [cursor=pointer] - generic [ref=e883]: "]" - generic [ref=e884]: - row "7994" [ref=e885] [cursor=pointer] - generic [ref=e886]: "}" - generic [ref=e887]: - row "7995" [ref=e888] [cursor=pointer] - generic [ref=e889]: "]" - generic [ref=e890]: - row "7996" [ref=e891] [cursor=pointer] - generic [ref=e892]: "}" - generic [ref=e893]: - row "7997" [ref=e894] [cursor=pointer] - generic [ref=e895]: SBOM_EYECATCHER_END - row "7998" [ref=e897] [cursor=pointer] ``` # Test source ```ts 1 | import { expect, Page, Locator } from '@playwright/test'; 2 | import { BaseCIPlugin } from './baseCIPlugin'; 3 | import { TektonPO } from '../../page-objects/tektonPo'; 4 | import { CiPo } from '../../page-objects/ciPo'; 5 | import { CommonPO } from '../../page-objects/commonPo'; 6 | 7 | export class TektonPlugin extends BaseCIPlugin { 8 | constructor(name: string, registryOrg: string) { 9 | super(name, registryOrg); 10 | } 11 | 12 | private async checkActionButtons(onPushRow: Locator): Promise { 13 | for (const testId of [TektonPO.logsIconTestId, TektonPO.sbomIconTestId, TektonPO.viewOutputTestId]) { 14 | const button = onPushRow.getByTestId(testId); 15 | await expect(button).toBeVisible(); 16 | } 17 | } 18 | 19 | private async checkLogsPopup(page: Page, row: Locator): Promise { 20 | const logsButton = row.getByTestId(TektonPO.logsIconTestId); 21 | await logsButton.click(); 22 | 23 | const logsPopup = page.getByTitle(TektonPO.logsDialogTitle); 24 | await expect(logsPopup).toBeVisible(); 25 | 26 | for (const task of TektonPO.sourceTasks) { 27 | const button = page.getByRole('heading', { name: task, exact: true }); 28 | await expect(button).toBeVisible(); 29 | } 30 | 31 | const button = page.getByRole('heading', { name: TektonPO.sourceTasks[0] }); 32 | await button.click(); 33 | 34 | // Check the log is visible by looking for the word 'STEP' 35 | const span = page.getByText(TektonPO.logStepRegex).first(); 36 | await expect(span).toBeVisible(); 37 | 38 | // Close popup 39 | const closeButton = page.getByRole('dialog').getByTestId(CommonPO.closeIconTestId); 40 | await closeButton.click(); 41 | } 42 | 43 | async checkSBOMpopup(page: Page, row: Locator): Promise { 44 | const sbomButton = row.getByTestId(TektonPO.sbomIconTestId); 45 | await sbomButton.click(); 46 | 47 | const searchBox = page.getByRole('textbox', { name: TektonPO.searchBoxName }); 48 | await searchBox.fill(TektonPO.sbomStepName); 49 | 50 | const span = page.getByText(TektonPO.sbomStepName); > 51 | await expect(span).toBeVisible(); | ^ Error: expect(locator).toBeVisible() failed 52 | 53 | // Close popup 54 | const closeButton = page.getByRole('dialog').getByTestId(CommonPO.closeIconTestId); 55 | await closeButton.click(); 56 | } 57 | 58 | private async checkGraph(page: Page, row: Locator): Promise { 59 | const expandButton = row.getByRole('button', { name: TektonPO.expandButtonName }); 60 | const graph = page.locator(TektonPO.graphSelector); 61 | 62 | // Expand the row 63 | await expandButton.click(); 64 | 65 | // Check the graph is visible 66 | await expect(graph).toBeVisible(); 67 | 68 | // Fit to screen 69 | await page.getByRole('button', { name: TektonPO.fitToScreenButtonName }).click(); 70 | 71 | // Check all the tasks are visible 72 | for (const taskName of TektonPO.sourceTasks) { 73 | const task = page.locator(`g[data-test="task ${taskName}"]`); 74 | await expect(task).toBeVisible(); 75 | } 76 | 77 | // Check the graph buttons are visible 78 | for(const buttonName of [TektonPO.zoomInButtonName, TektonPO.zoomOutButtonName, TektonPO.fitToScreenButtonName, TektonPO.resetViewButtonName]) { 79 | const button = page.getByRole('button', { name: buttonName }); 80 | await expect(button).toBeVisible(); 81 | } 82 | 83 | // Collapse the row 84 | await expandButton.click(); 85 | 86 | await expect(graph).not.toBeVisible(); 87 | } 88 | 89 | async checkPipelineRunsTable(page: Page): Promise { 90 | // Wait for the Pipeline Runs section to be visible 91 | await expect(page.getByRole('heading', { name: /pipeline runs/i })).toBeVisible(); 92 | 93 | // Find the table and on-push row 94 | const table = page.locator('table').filter({ has: page.getByRole('columnheader', { name: 'NAME' }) }); 95 | const firstRow = table.locator('tbody tr').filter({ hasText: TektonPO.onPushRowRegex }).first(); 96 | await expect(firstRow).toBeVisible(); 97 | 98 | // 1. Shield icon next to name (look for shield icon with specific path, not the expand arrow) 99 | const shieldIcon = firstRow.locator('.signed-indicator svg'); 100 | await expect(shieldIcon).toBeVisible(); 101 | 102 | // 2. Vulnerabilities are shown (look for vulnerability severity levels) 103 | await expect(firstRow.getByRole('cell').filter({ hasText: TektonPO.vulnerabilitySeverityRegex }).first()).toBeVisible(); 104 | 105 | // 3. Status is Succeeded and has a tick 106 | await expect(firstRow).toContainText(CiPo.statusSucceededText); 107 | await expect(firstRow.locator(`[data-testid="${CiPo.statusOkTestId}"]`)).toBeVisible(); 108 | 109 | // 4. Started column has a date and time format (look for date pattern in any cell) 110 | await expect(firstRow.getByRole('cell').filter({ hasText: /\d{1,2}\/\d{1,2}\/\d{4}/ })).toBeVisible(); 111 | 112 | // 5. Task status has a visible bar (look for progress elements) 113 | // Skipping until https://redhat.atlassian.net/browse/SSCUI-82 is fixed 114 | //await expect(firstRow.locator('[role="progressbar"], [class*="bar"], [data-testid*="progress"]').first()).toBeVisible(); 115 | 116 | // 6. Duration is visible (e.g. `3 minutes 20 seconds`, `3 minutes`, or `45 seconds`) 117 | await expect(firstRow.getByRole('cell').filter({ hasText: TektonPO.durationRegex })).toBeVisible(); 118 | } 119 | 120 | async checkActions(page: Page): Promise { 121 | // Find the Pipeline Runs table specifically to avoid conflicts with other tables (e.g., ArgoCD) 122 | const pipelineRunsTable = page.locator('table').filter({ has: page.getByRole('columnheader', { name: 'NAME' }) }); 123 | 124 | // Scroll to the action column header within the Pipeline Runs table 125 | await pipelineRunsTable.getByRole('columnheader', { name: TektonPO.actionsColumnHeader, exact: true }).scrollIntoViewIfNeeded(); 126 | 127 | const onPushRow = pipelineRunsTable.locator('tr').filter({ hasText: TektonPO.onPushRowRegex }).first(); 128 | 129 | await this.checkActionButtons(onPushRow); 130 | await this.checkLogsPopup(page, onPushRow); 131 | await this.checkSBOMpopup(page, onPushRow); 132 | await this.checkViewOutputPopup(page, onPushRow); 133 | await this.checkGraph(page, onPushRow); 134 | } 135 | 136 | /** 137 | * Verifies that registry links in both Image Scan and Image Check tabs 138 | * are actual clickable links that lead to an external registry (outside Developer Hub). 139 | * 140 | * This method: 141 | * 1. Opens the "View Output" dialog for an on-push pipeline row 142 | * 2. Checks Image Scan tab - verifies the image link is a real link (not just text) 143 | * 3. Checks Image Check tab - verifies the image link is a real link (not just text) 144 | * 4. Confirms links open in new tabs and navigate outside Developer Hub 145 | * 146 | * @param page - Playwright Page object 147 | */ 148 | public async checkImageRegistryLinks(page: Page): Promise { 149 | // Find the Pipeline Runs table (same pattern as checkActions) 150 | const pipelineRunsTable = page.locator('table').filter({ has: page.getByRole('columnheader', { name: 'NAME' }) }); 151 | ```