# 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: setup/auth.setup.ts >> authenticate - Location: tests/setup/auth.setup.ts:24:6 # Error details ``` TimeoutError: locator.waitFor: Timeout 10000ms exceeded. Call log: - waiting for getByRole('heading', { name: 'Welcome back!' }) to be visible ``` # Page snapshot ```yaml - generic [ref=e2]: - alert [ref=e4]: - img [ref=e6] - generic [ref=e8]: "Login failed; caused by Error: Failed to sign-in, unable to resolve user identity. Please verify that your catalog contains the expected User entities that would match your configured sign-in resolver." - button [ref=e10] [cursor=pointer]: - img [ref=e12] - main [ref=e14]: - heading "Red Hat Developer Hub" [level=1] [ref=e17] - article [ref=e18]: - heading "Select a sign-in method" [level=2] [ref=e21] - list [ref=e22]: - listitem [ref=e23]: - generic [ref=e24]: - generic [ref=e27]: OIDC - separator [ref=e28] - paragraph [ref=e30]: Sign in using OIDC - button "Sign In" [active] [ref=e32] [cursor=pointer]: - generic [ref=e33]: Sign In ``` # Test source ```ts 1 | import { KubeClient } from '../../src/api/ocp/kubeClient'; 2 | import { Git, GitType } from '../../src/rhtap/core/integration/git'; 3 | import { OidcUi } from '../../src/ui/plugins/auth/oidcUi'; 4 | import { GithubUiPlugin } from '../../src/ui/plugins/git/githubUi'; 5 | import { getDeveloperHubConfig } from '../../src/utils/util'; 6 | import { test as setup, BrowserContext } from '@playwright/test'; 7 | 8 | const authFile = 'playwright/.auth/user.json'; 9 | 10 | 11 | async function updateGitHubGrantedScope(context: BrowserContext): Promise { 12 | const cookies = await context.cookies(); 13 | const scopeCookie = cookies.find(c => c.name === 'github-granted-scope'); 14 | 15 | if (scopeCookie) { 16 | await context.addCookies([{ 17 | ...scopeCookie, 18 | value: 'read%3Auser%20repo%20read%3Aorg' 19 | }]); 20 | console.log('Updated github-granted-scope cookie to include repo and read:org'); 21 | } 22 | } 23 | 24 | setup('authenticate', async ({ page }) => { 25 | console.log('Setting up authentication for UI tests'); 26 | 27 | // Use KubeClient to get the developer hub URL 28 | const kubeClient = new KubeClient(); 29 | const routeHostname = await kubeClient.getOpenshiftRoute('backstage-developer-hub', 'tssc-dh'); 30 | const developerHubUrl = `https://${routeHostname}`; 31 | await page.goto(developerHubUrl); 32 | 33 | // Get the sign in page from the Developer Hub config 34 | const config = await getDeveloperHubConfig(); 35 | const signInPage = config.signInPage; 36 | 37 | // Create GitHubUiPlugin for login (pass empty object as Git since it's not used for login) 38 | switch (signInPage) { 39 | case 'oidc': 40 | { const oidcUI = new OidcUi(); 41 | await oidcUI.login(page); 42 | break; } 43 | case GitType.GITHUB: 44 | { const githubUI = new GithubUiPlugin({} as Git); 45 | await githubUI.login(page); 46 | // Update the granted scope cookie to include repo and read:org to omit the Github login page in Github UI plugin 47 | await updateGitHubGrantedScope(page.context()); 48 | break; } 49 | default: 50 | setup.skip(true, `Unsupported sign in page: ${String(signInPage)}`); 51 | return; 52 | } 53 | 54 | // Wait for successful login - check for welcome message > 55 | await page.getByRole('heading', { name: 'Welcome back!' }).waitFor({ | ^ TimeoutError: locator.waitFor: Timeout 10000ms exceeded. 56 | state: 'visible', 57 | timeout: 10000, 58 | }); 59 | 60 | // Save signed-in state to 'authFile' 61 | await page.context().storageState({ path: authFile }); 62 | 63 | console.log('Authentication setup completed successfully'); 64 | }); 65 | ```