# 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 ``` Error: expect(locator).toBeVisible() failed Locator: getByRole('tab', { name: 'Github Actions' }) Expected: visible Timeout: 10000ms Error: element(s) not found Call log: - Expect "toBeVisible" with timeout 10000ms - waiting for getByRole('tab', { name: 'Github Actions' }) ``` # Page snapshot ```yaml - generic [ref=e2]: - generic [ref=e3]: - navigation [ref=e5]: - generic [ref=e6]: - link "Home" [ref=e8] [cursor=pointer]: - /url: / - img [ref=e9] - generic [ref=e18]: - img [ref=e20] - combobox "Search..." [ref=e22] - generic "Self-service" [ref=e25]: - link "Self-service" [ref=e26] [cursor=pointer]: - /url: /create - img [ref=e28] - button "Your starred items" [ref=e31] [cursor=pointer]: - img [ref=e32] - button "Application launcher" [ref=e35] [cursor=pointer]: - img [ref=e36] - button "Help" [ref=e39] [cursor=pointer]: - img [ref=e40] - separator [ref=e42] - button "Admin" [ref=e44] [cursor=pointer]: - generic [ref=e45]: - img [ref=e46] - paragraph [ref=e49]: Admin - img [ref=e50] - generic [ref=e53]: - navigation "sidebar nav": - generic [ref=e55]: - generic [ref=e58]: - link "Home" [ref=e60] [cursor=pointer]: - /url: / - img [ref=e64] - generic [ref=e66]: Home - link "Catalog" [ref=e68] [cursor=pointer]: - /url: /catalog - img [ref=e72] - generic [ref=e74]: Catalog - link "APIs" [ref=e76] [cursor=pointer]: - /url: /api-docs - img [ref=e80] - generic [ref=e82]: APIs - link "Learning Paths" [ref=e84] [cursor=pointer]: - /url: /learning-paths - img [ref=e88] - generic [ref=e90]: Learning Paths - separator [ref=e91] - link "Docs" [ref=e94] [cursor=pointer]: - /url: /docs - img [ref=e98] - generic [ref=e100]: Docs - generic [ref=e101]: - separator [ref=e102] - button "Administration" [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 "e2e-tests-go-wrydbkfk Add to favorites" [level=1] [ref=e119]: - generic [ref=e120]: - generic "component:default/e2e-tests-go-wrydbkfk | service | Secure Supply Chain Example for Go Runtime http based application with advanced continuous integration pipeline covering building, CVE scanning, security scanning, signatures, attestations, SLSA provenance and SBOM along with Gitops-based continuous deployment." [ref=e122]: e2e-tests-go-wrydbkfk - button "Add to favorites" [ref=e123] [cursor=pointer]: - img [ref=e126] - generic [ref=e128]: - generic [ref=e130]: - paragraph [ref=e131]: Owner - paragraph [ref=e132]: - link "user:guest" [ref=e133] [cursor=pointer]: - /url: /catalog/default/user/guest - generic "user:default/guest" [ref=e134]: - img [ref=e136] - text: user:guest - generic [ref=e139]: - paragraph [ref=e140]: Lifecycle - paragraph [ref=e141]: experimental - button "more" [ref=e142] [cursor=pointer]: - img [ref=e144] - tablist "tabs" [ref=e150]: - tab "Overview" [ref=e151] [cursor=pointer] - tab "Topology" [ref=e152] [cursor=pointer] - tab "CI" [selected] [ref=e153] [cursor=pointer] - tab "CD" [ref=e154] [cursor=pointer] - tab "Kubernetes" [ref=e155] [cursor=pointer] - tab "Image Registry" [ref=e156] [cursor=pointer] - tab "API" [ref=e157] [cursor=pointer] - tab "Dependencies" [ref=e158] [cursor=pointer] - tab "Docs" [ref=e159] [cursor=pointer] - article [ref=e161]: - generic [ref=e162]: - generic [ref=e165]: - generic [ref=e166]: - 'heading "Gitlab Pipelines: e2e-tests-go-wrydbkfk" [level=2] [ref=e168]' - generic [ref=e170]: - img [ref=e172] - textbox "Search" [ref=e174]: - /placeholder: Filter - generic [ref=e175]: - button "Clear Search" [disabled]: - generic: - img - table [ref=e180]: - rowgroup [ref=e181]: - row "Pipeline ID Status Branch Web URL Created At Duration" [ref=e182]: - columnheader "Pipeline ID" [ref=e183]: - button "Pipeline ID" [ref=e184] [cursor=pointer]: - button "Pipeline ID" [ref=e185] - img [ref=e186] - columnheader "Status" [ref=e188]: - button "Status" [ref=e189] [cursor=pointer]: - button "Status" [ref=e190] - img [ref=e191] - columnheader "Branch" [ref=e193]: - button "Branch" [ref=e194] [cursor=pointer]: - button "Branch" [ref=e195] - img [ref=e196] - columnheader "Web URL" [ref=e198]: - button "Web URL" [ref=e199] [cursor=pointer]: - button "Web URL" [ref=e200] - img [ref=e201] - columnheader "Created At" [ref=e203]: - button "Created At" [ref=e204] [cursor=pointer]: - button "Created At" [ref=e205] - img [ref=e206] - columnheader "Duration" [ref=e208]: - button "Duration" [ref=e209] [cursor=pointer]: - button "Duration" [ref=e210] - img [ref=e211] - rowgroup [ref=e213]: - row "2471306568 success main https://gitlab.com/rhtap-qe/e2e-tests-go-wrydbkfk/-/pipelines/2471306568 14 minutes ago 3m 53s" [ref=e214]: - cell "2471306568" [ref=e215] - cell "success" [ref=e216]: - generic [ref=e217]: - img [ref=e219] - generic [ref=e221]: success - cell "main" [ref=e222] - cell "https://gitlab.com/rhtap-qe/e2e-tests-go-wrydbkfk/-/pipelines/2471306568" [ref=e223]: - link "https://gitlab.com/rhtap-qe/e2e-tests-go-wrydbkfk/-/pipelines/2471306568" [ref=e224] [cursor=pointer]: - /url: https://gitlab.com/rhtap-qe/e2e-tests-go-wrydbkfk/-/pipelines/2471306568 - cell "14 minutes ago" [ref=e225] - cell "3m 53s" [ref=e226] - row "2471296079 success test-branch-1776856696641 https://gitlab.com/rhtap-qe/e2e-tests-go-wrydbkfk/-/pipelines/2471296079 19 minutes ago 4m 18s" [ref=e227]: - cell "2471296079" [ref=e228] - cell "success" [ref=e229]: - generic [ref=e230]: - img [ref=e232] - generic [ref=e234]: success - cell "test-branch-1776856696641" [ref=e235] - cell "https://gitlab.com/rhtap-qe/e2e-tests-go-wrydbkfk/-/pipelines/2471296079" [ref=e236]: - link "https://gitlab.com/rhtap-qe/e2e-tests-go-wrydbkfk/-/pipelines/2471296079" [ref=e237] [cursor=pointer]: - /url: https://gitlab.com/rhtap-qe/e2e-tests-go-wrydbkfk/-/pipelines/2471296079 - cell "19 minutes ago" [ref=e238] - cell "4m 18s" [ref=e239] - row "2471295305 canceled main https://gitlab.com/rhtap-qe/e2e-tests-go-wrydbkfk/-/pipelines/2471295305 19 minutes ago 17s" [ref=e240]: - cell "2471295305" [ref=e241] - cell "canceled" [ref=e242]: - generic [ref=e243]: - img [ref=e245] - generic [ref=e247]: canceled - cell "main" [ref=e248] - cell "https://gitlab.com/rhtap-qe/e2e-tests-go-wrydbkfk/-/pipelines/2471295305" [ref=e249]: - link "https://gitlab.com/rhtap-qe/e2e-tests-go-wrydbkfk/-/pipelines/2471295305" [ref=e250] [cursor=pointer]: - /url: https://gitlab.com/rhtap-qe/e2e-tests-go-wrydbkfk/-/pipelines/2471295305 - cell "19 minutes ago" [ref=e251] - cell "17s" [ref=e252] - row [ref=e253] - row [ref=e254] - row [ref=e255] - table [ref=e256]: - rowgroup [ref=e257]: - row "5 rows First Page Previous Page 1-3 of 3 Next Page Last Page" [ref=e258]: - cell "5 rows First Page Previous Page 1-3 of 3 Next Page Last Page" [ref=e259]: - generic [ref=e260]: - generic [ref=e261]: - 'button "Rows per page: 5 rows" [ref=e262] [cursor=pointer]': - generic [ref=e263]: 5 rows - textbox: "5" - img - generic [ref=e264]: - generic "First Page" [ref=e265]: - button "First Page" [disabled]: - generic: - img - generic "Previous Page" [ref=e266]: - button "Previous Page" [disabled]: - generic: - img - generic [ref=e267]: 1-3 of 3 - generic "Next Page" [ref=e268]: - button "Next Page" [disabled]: - generic: - img - generic "Last Page" [ref=e269]: - button "Last Page" [disabled]: - generic: - img - generic [ref=e273]: - heading "Security Information" [level=4] [ref=e276] - generic [ref=e278]: - tablist "Multi CI" [ref=e281]: - tab "Gitlab CI" [selected] [ref=e282] [cursor=pointer]: - generic [ref=e283]: Gitlab CI - generic [ref=e287]: - generic [ref=e288]: - generic [ref=e291]: - generic [ref=e293]: - img [ref=e295] - button "Name" [ref=e297] [cursor=pointer] - textbox: Name - img - generic "search" [ref=e299]: - img [ref=e301] - textbox "Search by name" [ref=e303] - generic [ref=e305]: - generic "rows per page" [ref=e306]: - button "1 - 3 of 3" [ref=e307] [cursor=pointer] - textbox: "5" - img - button "first page" [disabled]: - generic: - img - button "previous page" [disabled]: - generic: - img - generic "page number" [ref=e308]: - generic [ref=e309]: - textbox [ref=e310]: "1" - group - paragraph [ref=e311]: of 1 - button "next page" [disabled]: - generic: - img - button "last page" [disabled]: - generic: - img - table [ref=e313]: - rowgroup [ref=e314]: - row "Pipeline Run ID Type Critical Important Moderate Low SBOM Actions" [ref=e315]: - columnheader "Pipeline Run ID" [ref=e316] - columnheader "Type" [ref=e317] - columnheader "Critical" [ref=e318] - columnheader "Important" [ref=e319] - columnheader "Moderate" [ref=e320] - columnheader "Low" [ref=e321] - columnheader "SBOM" [ref=e322] - columnheader "Actions" [ref=e323] - rowgroup [ref=e324]: - row "2471306568 Build Critical Important Moderate Low Link to SBOM View Logs View Scan Results" [ref=e325]: - cell "2471306568" [ref=e326]: - paragraph [ref=e327]: "2471306568" - cell "Build" [ref=e328]: - paragraph [ref=e329]: Build - cell "Critical" [ref=e330]: - generic "Critical" [ref=e331]: - img [ref=e332] - text: "0" - cell "Important" [ref=e334]: - generic "Important" [ref=e335]: - img [ref=e336] - text: "2" - cell "Moderate" [ref=e339]: - generic "Moderate" [ref=e340]: - img [ref=e341] - text: "2" - cell "Low" [ref=e343]: - generic "Low" [ref=e344]: - img [ref=e345] - text: "13" - cell "Link to SBOM" [ref=e348]: - generic "Link to SBOM" [ref=e349]: - button [ref=e350] [cursor=pointer]: - img [ref=e352] - cell "View Logs View Scan Results" [ref=e354]: - generic [ref=e355]: - generic "View Logs" [ref=e356]: - button [ref=e357] [cursor=pointer]: - img [ref=e359] - generic "View Scan Results" [ref=e361]: - button [ref=e362] [cursor=pointer]: - img [ref=e364] - row "2471296079 Build Critical Important Moderate Low Link to SBOM View Logs View Scan Results" [ref=e366]: - cell "2471296079" [ref=e367]: - paragraph [ref=e368]: "2471296079" - cell "Build" [ref=e369]: - paragraph [ref=e370]: Build - cell "Critical" [ref=e371]: - generic "Critical" [ref=e372]: - img [ref=e373] - text: "0" - cell "Important" [ref=e375]: - generic "Important" [ref=e376]: - img [ref=e377] - text: "2" - cell "Moderate" [ref=e380]: - generic "Moderate" [ref=e381]: - img [ref=e382] - text: "2" - cell "Low" [ref=e384]: - generic "Low" [ref=e385]: - img [ref=e386] - text: "13" - cell "Link to SBOM" [ref=e389]: - generic "Link to SBOM" [ref=e390]: - button [ref=e391] [cursor=pointer]: - img [ref=e393] - cell "View Logs View Scan Results" [ref=e395]: - generic [ref=e396]: - generic "View Logs" [ref=e397]: - button [ref=e398] [cursor=pointer]: - img [ref=e400] - generic "View Scan Results" [ref=e402]: - button [ref=e403] [cursor=pointer]: - img [ref=e405] - row "2471295305 Build Critical Important Moderate Low Link to SBOM Logs are not available for this run Scan Results are not available for this run" [ref=e407]: - cell "2471295305" [ref=e408]: - paragraph [ref=e409]: "2471295305" - cell "Build" [ref=e410]: - paragraph [ref=e411]: Build - cell "Critical" [ref=e412]: - generic "Critical" [ref=e413]: - paragraph [ref=e414]: N/A - cell "Important" [ref=e415]: - generic "Important" [ref=e416]: - paragraph [ref=e417]: N/A - cell "Moderate" [ref=e418]: - generic "Moderate" [ref=e419]: - paragraph [ref=e420]: N/A - cell "Low" [ref=e421]: - generic "Low" [ref=e422]: - paragraph [ref=e423]: N/A - cell "Link to SBOM" [ref=e424]: - generic "Link to SBOM" [ref=e425]: - button [disabled]: - generic: - img - cell "Logs are not available for this run Scan Results are not available for this run" [ref=e426]: - generic [ref=e427]: - generic "Logs are not available for this run" [ref=e428]: - button [disabled]: - generic: - img - generic "Scan Results are not available for this run" [ref=e429]: - button [disabled]: - generic: - img - alert [ref=e430]: - generic [ref=e431]: Need help? Visit the Quick Start Guide by clicking on this (?) icon in the header! - button "close" [ref=e433] [cursor=pointer]: - img [ref=e434] ``` # Test source ```ts 1 | import { escapeRegex } from '../../../utils/util'; 2 | import { CiPo } from '../../page-objects/ciPo'; 3 | import { CommonPO } from '../../page-objects/commonPo'; 4 | import { CIPlugin } from './ciPlugin'; 5 | import { expect, Locator, Page } from '@playwright/test'; 6 | 7 | export class BaseCIPlugin implements CIPlugin { 8 | protected name: string; 9 | protected imageUrlRegex: RegExp; 10 | 11 | constructor(name: string, registryOrg: string) { 12 | this.name = name; 13 | this.imageUrlRegex = new RegExp(`^${escapeRegex(registryOrg)}/`, 'i'); 14 | } 15 | 16 | public async checkCIHeading(page: Page): Promise { 17 | // For GitHub Actions, the name appears as a tab in Security Information, not a heading 18 | const heading = page.getByRole('heading', { name: this.name }); 19 | const tab = page.getByRole('tab', { name: this.name }); 20 | 21 | // Check if either heading or tab is visible 22 | const headingVisible = await heading.isVisible().catch(() => false); 23 | const tabVisible = await tab.isVisible().catch(() => false); 24 | 25 | if (!headingVisible && !tabVisible) { 26 | // Fallback: check for "Github Actions" tab (different casing) 27 | const tabAlt = page.getByRole('tab', { name: 'Github Actions' }); > 28 | await expect(tabAlt).toBeVisible({ timeout: 10000 }); | ^ Error: expect(locator).toBeVisible() failed 29 | } 30 | } 31 | 32 | protected async checkViewOutputPopup(page: Page, row: Locator): Promise { 33 | const viewOutputButton = row.getByTestId(CommonPO.viewOutputIconTestId); 34 | await viewOutputButton.click(); 35 | 36 | const dialog = page.getByRole('dialog'); 37 | await expect(dialog).toBeVisible(); 38 | 39 | // Check results table 40 | const resultsTable = dialog.getByTestId(CiPo.resultsTableTestId); 41 | await expect(resultsTable).toBeVisible(); 42 | 43 | // Check column headers 44 | for (const column of CiPo.resultsTableColumns) { 45 | await expect(resultsTable.getByRole('columnheader', { name: column })).toBeVisible(); 46 | } 47 | 48 | // Check expected rows exist 49 | for (const rowName of CiPo.resultsTableRows) { 50 | await expect(resultsTable.getByRole('gridcell', { name: rowName, exact: true })).toBeVisible(); 51 | } 52 | 53 | // Check IMAGE_URL contains component name 54 | const imageUrlRow = resultsTable.getByRole('row').filter({ hasText: CiPo.imageUrlRow }); 55 | await expect(imageUrlRow).toContainText(this.name); 56 | 57 | // Check CHAINS-GIT_URL has a link 58 | const gitUrlRow = resultsTable.getByRole('row').filter({ hasText: CiPo.chainsGitUrlRow }); 59 | await expect(gitUrlRow.getByRole('link')).toBeVisible(); 60 | 61 | const closeButton = dialog.getByTestId(CommonPO.closeIconTestId); 62 | await closeButton.click(); 63 | } 64 | 65 | // eslint-disable-next-line no-unused-vars 66 | public async checkImageRegistryLinks(_page: Page): Promise { 67 | } 68 | 69 | // eslint-disable-next-line no-unused-vars 70 | public async checkActions(_page: Page): Promise { 71 | } 72 | 73 | // eslint-disable-next-line no-unused-vars 74 | public async checkPipelineRunsTable(_page: Page): Promise { 75 | } 76 | 77 | public async checkSecurityInformation(page: Page): Promise { 78 | // Security Information viewer may not be present for all CI providers 79 | const heading = page.getByRole('heading', { name: CiPo.securityInformationHeading }); 80 | const isVisible = await heading.isVisible().catch(() => false); 81 | if (!isVisible) { 82 | return; 83 | } 84 | 85 | // Scope column header checks to the security table 86 | const securityTable = page.getByRole('table').filter({ has: page.getByRole('columnheader', { name: CiPo.securityTableColumns[0] }) }); 87 | for (const column of CiPo.securityTableColumns) { 88 | await expect(securityTable.getByRole('columnheader', { name: column })).toBeVisible(); 89 | } 90 | } 91 | } 92 | ```