Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions tests/src/sso-extension.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

import { SSOAuthenticationProviderCardPage } from './model/pages/sso-authentication-page';
import { SSOExtensionPage } from './model/pages/sso-extension-page';
import { findPageWithTitleInBrowser, getSSOUrlFromLogs, performBrowserLogin, startChromium } from './utility/auth-utils';
import { enableDebugCall, findPageWithTitleInBrowser, getSSOUrlFromLogs, performBrowserLogin, startChromium } from './utility/auth-utils';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
Expand Down Expand Up @@ -232,7 +232,7 @@
await chromiumPage.close();
});

test('User signed in status is propagated into Podman Desktop', async ({ page, navigationBar }) => {
test('User signed in status is propagated into Podman Desktop', async ({ page, navigationBar, runner }) => {

Check failure on line 235 in tests/src/sso-extension.spec.ts

View workflow job for this annotation

GitHub Actions / Test (ubuntu-24.04)

'runner' is defined but never used. Allowed unused args must match /^_/u
// activate Podman Desktop again
await page.bringToFront();
// verify the Signed in user
Expand All @@ -241,7 +241,9 @@
await playExpect(authPage.heading).toHaveText('Authentication');
// on linux we need to avoid issue with auth. providers store
// in case of need, refresh auth. providers store in troubleshooting
await page.screenshot({ path: join(...browserOutputPath, 'screenshots', 'back_pd_after_authentication.png'), type: 'png' });
await enableDebugCall(
async () => await page.screenshot({ path: join(...browserOutputPath, 'screenshots', 'back_pd_after_authentication.png'), type: 'png' }

Check warning on line 245 in tests/src/sso-extension.spec.ts

View workflow job for this annotation

GitHub Actions / Test (ubuntu-24.04)

Missing trailing comma

Check failure on line 245 in tests/src/sso-extension.spec.ts

View workflow job for this annotation

GitHub Actions / Test (ubuntu-24.04)

Promise returned in function argument where a void return was expected
));
if (await ssoProvider.signinButton.count() >= 0) {
console.log('SignIn Button still visible, we are hitting issue with linux');
const status = new StatusBar(page);
Expand Down
190 changes: 110 additions & 80 deletions tests/src/utility/auth-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,90 +22,120 @@
import { chromium, expect as playExpect } from '@playwright/test';
import { StatusBar, TroubleshootingPage } from '@podman-desktop/tests-playwright';

const enableDebug = process.env.BROWSER_DEBUG_ENABLED ?? false;

export async function findPageWithTitleInBrowser(browser: Browser, expectedTitle: string): Promise<Page|undefined> {
let chromePage: Page | undefined;

for (let i = 0; i < 10; i++) {
await new Promise(resolve => setTimeout(resolve, 1000));
const pages = browser.contexts().flatMap(context => context.pages());
const pagesTitles = await Promise.all(pages.map(async (page) => (
{ page, title: await page.title() }
)));

chromePage = pagesTitles.find(p => p.title.includes(expectedTitle))?.page;
if (chromePage) {
break;
}
}

if (!chromePage) {
console.error(`No page found with title: ${expectedTitle}`);
let chromePage: Page | undefined;

for (let i = 0; i < 10; i++) {
await new Promise(resolve => setTimeout(resolve, 1000));
const pages = browser.contexts().flatMap(context => context.pages());
const pagesTitles = await Promise.all(pages.map(async (page) => (
{ page, title: await page.title() }
)));

chromePage = pagesTitles.find(p => p.title.includes(expectedTitle))?.page;
if (chromePage) {
break;
}
return chromePage;
}

export async function performBrowserLogin(page: Page, username: string, pass: string, path: string): Promise<void> {
console.log(`Performing browser login...`);
await playExpect(page).toHaveTitle(/Log In/);
await playExpect(page.getByRole('heading', { name: 'Log in to your Red Hat' })).toBeVisible();
console.log(`We are on the login RH Login page...`);
const input = page.getByRole('textbox', { name: 'Red Hat login or email' });
await playExpect(input).toBeVisible();
await input.fill(username);
const nextButton = page.getByRole('button', { name: 'Next' });
await nextButton.click();
const passInput = page.getByRole('textbox', { name: 'Password' });
await playExpect(passInput).toBeVisible();
await passInput.fill(pass);
const loginButton = page.getByRole('button', { name: 'Log in' });
await playExpect(loginButton).toBeEnabled();
await loginButton.click();
const backButton = page.getByRole('button', { name: 'Go back to Podman Desktop' });
await playExpect(backButton).toBeEnabled();
await page.screenshot({ path: join(path, 'screenshots', 'after_login_in_browser.png'), type: 'png', fullPage: true });
console.log(`Logged in, go back...`);
await backButton.click();
await page.screenshot({ path: join(path, 'screenshots', 'after_clck_go_back.png'), type: 'png', fullPage: true });

if (!chromePage) {
console.error(`No page found with title: ${expectedTitle}`);
}
return chromePage;
}

export async function startChromium(port: string, tracesPath: string): Promise<Browser> {
console.log('Starting a web server on port 9222');
const browserLaunch = await chromium.launch({
headless: false,
args: [`--remote-debugging-port=${port}`],
tracesDir: tracesPath,
slowMo: 200,
});

// hard wait
await new Promise(resolve => setTimeout(resolve, 5_000));
// Connect to the same Chrome instance via CDP
// possible option is to use chromium.connectOverCDP(`http://localhost:${port}`);
if (!browserLaunch) {
throw new Error('Browser object was not initialized properly');
} else {
console.log(`Browser connected: ${browserLaunch.isConnected()}`);
}
return browserLaunch;
export async function performBrowserLogin(page: Page, username: string, pass: string, path: string): Promise<void> {
console.log(`Performing browser login...`);
await playExpect(page).toHaveTitle(/Log In/);
await playExpect(page.getByRole('heading', { name: 'Log in to your Red Hat' })).toBeVisible();
console.log(`We are on the login RH Login page...`);
await enableDebugCall( async () =>

Check failure on line 54 in tests/src/utility/auth-utils.ts

View workflow job for this annotation

GitHub Actions / Test (ubuntu-24.04)

Promise returned in function argument where a void return was expected
await page.screenshot({ path: join(path, 'screenshots', 'before_username_fill.png'), type: 'png', fullPage: true }

Check warning on line 55 in tests/src/utility/auth-utils.ts

View workflow job for this annotation

GitHub Actions / Test (ubuntu-24.04)

Missing trailing comma
));
const input = page.getByRole('textbox', { name: 'Red Hat login or email' });
await playExpect(input).toBeVisible();
await input.fill(username);
const nextButton = page.getByRole('button', { name: 'Next' });
await nextButton.click();
// after next is clicked, a wait is necessary
// we might get a page with providers to choose from
// button - Log in with company single sign-on OR
// button - Log in with Red Hat account
const buttonRHAccount = page.getByRole('button', { name: 'Log in with Red Hat account' });
// we might get to the password immediately
try {
await enableDebugCall( async () =>

Check failure on line 69 in tests/src/utility/auth-utils.ts

View workflow job for this annotation

GitHub Actions / Test (ubuntu-24.04)

Promise returned in function argument where a void return was expected
await page.screenshot({ path: join(path, 'screenshots', 'after_username_and_next.png'), type: 'png', fullPage: true }

Check warning on line 70 in tests/src/utility/auth-utils.ts

View workflow job for this annotation

GitHub Actions / Test (ubuntu-24.04)

Missing trailing comma
));
await playExpect(buttonRHAccount).toBeVisible({ timeout: 5000 });
await buttonRHAccount.click();
} catch (error: unknown) {
console.log(`Error: ${error}, while evaluating Log in with RH acc. button, continue...`);
}

export async function getSSOUrlFromLogs(page: Page, regex: RegExp): Promise<string | undefined> {
await new StatusBar(page).troubleshootingButton.click();
const troublePage = new TroubleshootingPage(page);
await playExpect(troublePage.heading).toBeVisible();
// open logs
await troublePage.openLogs();
const logList = troublePage.tabContent.getByRole('list');
await playExpect(logList).toBeVisible();
const ssoLine = logList.getByRole('listitem').filter( { hasText: /\[redhat-authentication\].*openid-connect.*/ });
await playExpect(ssoLine).toBeVisible();
await ssoLine.scrollIntoViewIfNeeded();
await playExpect(ssoLine).toContainText('sso.redhat.com');
const logText = await ssoLine.innerText();
console.log(`The whole log line with url to openid: ${logText}`);
// parse the url:
const parsedString = regex.exec(logText);
const urlMatch = parsedString ? parsedString[1] : undefined;
console.log(`Matched string: ${urlMatch}`);
return urlMatch;
await enableDebugCall(
async () => await page.screenshot({ path: join(path, 'screenshots', 'before_password_fill.png'), type: 'png', fullPage: true }

Check warning on line 78 in tests/src/utility/auth-utils.ts

View workflow job for this annotation

GitHub Actions / Test (ubuntu-24.04)

Missing trailing comma

Check failure on line 78 in tests/src/utility/auth-utils.ts

View workflow job for this annotation

GitHub Actions / Test (ubuntu-24.04)

Promise returned in function argument where a void return was expected
));
const passInput = page.getByRole('textbox', { name: 'Password' });
await playExpect(passInput).toBeVisible();
await passInput.fill(pass);
const loginButton = page.getByRole('button', { name: 'Log inx' });
await playExpect(loginButton).toBeEnabled();
await loginButton.click();
const backButton = page.getByRole('button', { name: 'Go back to Podman Desktop' });
await playExpect(backButton).toBeEnabled();
await enableDebugCall(
async () => await page.screenshot({ path: join(path, 'screenshots', 'after_login_in_browser.png'), type: 'png', fullPage: true }

Check warning on line 89 in tests/src/utility/auth-utils.ts

View workflow job for this annotation

GitHub Actions / Test (ubuntu-24.04)

Missing trailing comma

Check failure on line 89 in tests/src/utility/auth-utils.ts

View workflow job for this annotation

GitHub Actions / Test (ubuntu-24.04)

Promise returned in function argument where a void return was expected
));
console.log(`Logged in, go back...`);
await backButton.click();
}

export async function startChromium(port: string, tracesPath: string): Promise<Browser> {
console.log('Starting a web server on port 9222');
const browserLaunch = await chromium.launch({
headless: false,
args: [`--remote-debugging-port=${port}`],
tracesDir: tracesPath,
slowMo: 200,
});

// hard wait
await new Promise(resolve => setTimeout(resolve, 5_000));
// Connect to the same Chrome instance via CDP
// possible option is to use chromium.connectOverCDP(`http://localhost:${port}`);
if (!browserLaunch) {
throw new Error('Browser object was not initialized properly');
} else {
console.log(`Browser connected: ${browserLaunch.isConnected()}`);
}
return browserLaunch;
}

export async function getSSOUrlFromLogs(page: Page, regex: RegExp): Promise<string | undefined> {
await new StatusBar(page).troubleshootingButton.click();
const troublePage = new TroubleshootingPage(page);
await playExpect(troublePage.heading).toBeVisible();
// open logs
await troublePage.openLogs();
const logList = troublePage.tabContent.getByRole('list');
await playExpect(logList).toBeVisible();
const ssoLine = logList.getByRole('listitem').filter( { hasText: /\[redhat-authentication\].*openid-connect.*/ });
await playExpect(ssoLine).toBeVisible();
await ssoLine.scrollIntoViewIfNeeded();
await playExpect(ssoLine).toContainText('sso.redhat.com');
const logText = await ssoLine.innerText();
console.log(`The whole log line with url to openid: ${logText}`);
// parse the url:
const parsedString = regex.exec(logText);
const urlMatch = parsedString ? parsedString[1] : undefined;
console.log(`Matched string: ${urlMatch}`);
return urlMatch;
}

export async function enableDebugCall(callback: () => void): Promise<void> {
if (enableDebug) {
callback();
}
}
Loading