# 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 >> Test Image Registry >> test image registry - Location: tests/ui/component.test.ts:206:5 # Error details ``` Error: expect(received).toBeGreaterThan(expected) Expected: > 0 Received: 0 ``` # 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-rdhdffmj Add to favorites" [level=1] [ref=e119]: - generic [ref=e120]: - generic "component:default/e2e-tests-go-rdhdffmj | 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-rdhdffmj - 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" [ref=e153] [cursor=pointer] - tab "CD" [ref=e154] [cursor=pointer] - tab "Kubernetes" [ref=e155] [cursor=pointer] - tab "Image Registry" [selected] [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=e166]: - generic [ref=e167]: - 'heading "JFrog Artifactory repository: e2e-tests-go-rdhdffmj" [level=2] [ref=e169]' - generic [ref=e171]: - img [ref=e173] - textbox "Search" [active] [ref=e175]: - /placeholder: Filter - text: .att - button "Clear Search" [ref=e177] [cursor=pointer]: - img [ref=e179] - table [ref=e185]: - rowgroup [ref=e186]: - row "Version Repositories Manifest Modified Size" [ref=e187]: - columnheader "Version" [ref=e188]: - button "Version" [ref=e189] [cursor=pointer]: - button "Version" [ref=e190] - img [ref=e191] - columnheader "Repositories" [ref=e193]: - button "Repositories" [ref=e194] [cursor=pointer]: - button "Repositories" [ref=e195] - img [ref=e196] - columnheader "Manifest" [ref=e198]: - button "Manifest" [ref=e199] [cursor=pointer]: - button "Manifest" [ref=e200] - img [ref=e201] - columnheader "Modified" [ref=e203]: - button "Modified" [ref=e204] [cursor=pointer]: - button "Modified" [ref=e205] - img [ref=e206] - columnheader "Size" [ref=e208]: - button "Size" [ref=e209] [cursor=pointer]: - button "Size" [ref=e210] - img [ref=e211] - rowgroup [ref=e213]: - row "No data was added yet, learn how to add data. , Opens in a new window" [ref=e214]: - cell "No data was added yet, learn how to add data. , Opens in a new window" [ref=e215]: - generic [ref=e216]: - text: No data was added yet, - link "learn how to add data. , Opens in a new window" [ref=e217] [cursor=pointer]: - /url: https://backstage.io/ - text: learn how to add data. - generic [ref=e218]: ", Opens in a new window" - table [ref=e219]: - rowgroup [ref=e220]: - row "5 Rows First Page Previous Page 0-0 of 0 Next Page Last Page" [ref=e221]: - cell "5 Rows First Page Previous Page 0-0 of 0 Next Page Last Page" [ref=e222]: - generic [ref=e223]: - generic [ref=e224]: - 'button "Rows per page: 5 Rows" [ref=e225] [cursor=pointer]': - generic [ref=e226]: 5 Rows - textbox: "5" - img - generic [ref=e227]: - generic "First Page" [ref=e228]: - button "First Page" [disabled]: - generic: - img - generic "Previous Page" [ref=e229]: - button "Previous Page" [disabled]: - generic: - img - generic [ref=e230]: 0-0 of 0 - generic "Next Page" [ref=e231]: - button "Next Page" [disabled]: - generic: - img - generic "Last Page" [ref=e232]: - button "Last Page" [disabled]: - generic: - img - alert [ref=e233]: - generic [ref=e234]: Need help? Visit the Quick Start Guide by clicking on this (?) icon in the header! - button "close" [ref=e236] [cursor=pointer]: - img [ref=e237] ``` # Test source ```ts 1 | import { expect, Locator, Page } from '@playwright/test'; 2 | import { ImageRegistry } from '../../../rhtap/core/integration/registry/imageRegistry'; 3 | import { RegistryPlugin } from './registryPlugin'; 4 | import { RegistryPO } from '../../page-objects/registryPo'; 5 | 6 | /** 7 | * Base class for registry UI plugins containing common functionality 8 | * that can be shared across different registry plugins. 9 | */ 10 | export abstract class BaseRegistryPlugin implements RegistryPlugin { 11 | protected registry: ImageRegistry; 12 | 13 | constructor(registry: ImageRegistry) { 14 | this.registry = registry; 15 | } 16 | 17 | private async getTableRows(page: Page): Promise { 18 | return await page.locator('tr[index]').all(); 19 | } 20 | 21 | async checkSearchInputField(page: Page): Promise { 22 | const searchInput = page.getByRole('textbox', { name: RegistryPO.searchPlaceholder }); 23 | const clearButton = page.getByRole('button', { name: RegistryPO.clearSearchButtonLabel }); 24 | 25 | await expect(searchInput).toBeVisible(); 26 | await expect(clearButton).toBeVisible(); 27 | 28 | // Get all rows with indexes (relevant non-empty rows with index) 29 | const indexedRowsBefore = await this.getTableRows(page); 30 | const initialRowCount = indexedRowsBefore.length; 31 | 32 | await searchInput.fill('.att'); 33 | await page.waitForTimeout(100); 34 | await expect(clearButton).toBeEnabled(); 35 | 36 | // Get indexed rows after filtering 37 | const indexedRowsAfter = await this.getTableRows(page); > 38 | expect(indexedRowsAfter.length).toBeGreaterThan(0); | ^ Error: expect(received).toBeGreaterThan(expected) 39 | 40 | for (const row of indexedRowsAfter) { 41 | const rowText = await row.textContent(); 42 | expect(rowText).toContain('.att'); 43 | } 44 | 45 | // Click the clear search button 46 | await clearButton.click(); 47 | await page.waitForTimeout(100); 48 | 49 | // Verify all indexed rows return after clearing 50 | const indexedRowsAfterClear = await page.locator('tr[index]').all(); 51 | expect(indexedRowsAfterClear.length).toBe(initialRowCount); 52 | } 53 | 54 | async checkImageTableContent(page: Page): Promise { 55 | const rows = await this.getTableRows(page); 56 | expect(rows.length).toBeGreaterThan(0); 57 | } 58 | 59 | protected async checkTableColumnHeaders(page: Page, columnHeaders: string[]): Promise { 60 | for (const header of columnHeaders) { 61 | await expect(page.getByRole('columnheader', { name: header })).toBeVisible(); 62 | } 63 | } 64 | 65 | // Abstract methods that must be implemented by specific registry plugins 66 | // eslint-disable-next-line no-unused-vars 67 | abstract checkRepositoryHeading(page: Page): Promise; 68 | // eslint-disable-next-line no-unused-vars 69 | abstract checkRepositoryLink(page: Page): Promise; 70 | // eslint-disable-next-line no-unused-vars 71 | abstract checkTableColumns(page: Page): Promise; 72 | } 73 | ```