1616 * SPDX-License-Identifier: Apache-2.0
1717 ***********************************************************************/
1818
19- import type { NavigationBar } from '@podman-desktop/tests-playwright' ;
19+ import * as path from 'node:path' ;
20+ import { fileURLToPath } from 'node:url' ;
21+
22+ import type { Browser , Locator , Page } from '@playwright/test' ;
23+ import type { ConfirmInputValue } from '@podman-desktop/tests-playwright' ;
2024import {
25+ AuthenticationPage ,
2126 expect as playExpect ,
27+ findPageWithTitleInBrowser ,
28+ getEntryFromLogs ,
29+ NavigationBar ,
30+ performBrowserLogin ,
31+ ResourceConnectionCardPage ,
32+ ResourceElementActions ,
33+ ResourceElementState ,
34+ ResourcesPage ,
2235 RunnerOptions ,
36+ startChromium ,
2337 test ,
2438 waitForPodmanMachineStartup ,
39+ waitUntil ,
2540} from '@podman-desktop/tests-playwright' ;
2641
2742const extensionName = 'rhel-vms' ;
@@ -31,6 +46,17 @@ let extensionInstalled = false;
3146const skipInstallation = process . env . SKIP_INSTALLATION ;
3247const extensionURL = process . env . OCI_IMAGE ?? 'ghcr.io/redhat-developer/podman-desktop-rhel-ext:next' ;
3348
49+ const __filename = fileURLToPath ( import . meta. url ) ;
50+ const __dirname = path . dirname ( __filename ) ;
51+ const browserOutputPath = [ __dirname , '..' , 'output' , 'browser' ] ;
52+
53+ const expectedAuthPageTitle = 'Log In' ;
54+ const regex = new RegExp ( / ( ( h t t p | h t t p s ) : \/ \/ .* $ ) / ) ;
55+ let signInButton : Locator ;
56+ let browser : Browser ;
57+ let chromiumPage : Page ;
58+ const chromePort = '9222' ;
59+
3460test . use ( {
3561 runnerOptions : new RunnerOptions ( {
3662 customFolder : 'rhel-e2e-tests' ,
@@ -51,29 +77,146 @@ test.afterAll(async ({ runner }) => {
5177} ) ;
5278
5379test . describe . serial ( 'RHEL Extension E2E Tests' , ( ) => {
54- test . describe . configure ( { retries : 1 } ) ;
55- test ( 'Go to settings and check if extension is already installed' , async ( { navigationBar } ) => {
56- const extensionsPage = await navigationBar . openExtensions ( ) ;
57- if ( await extensionsPage . extensionIsInstalled ( extensionLabel ) ) extensionInstalled = true ;
80+ test . describe . serial ( 'Authentication Extension' , ( ) => {
81+ test ( 'Go to settings and check if extension is already installed' , async ( { navigationBar } ) => {
82+ const extensionsPage = await navigationBar . openExtensions ( ) ;
83+ if ( await extensionsPage . extensionIsInstalled ( extensionLabel ) ) extensionInstalled = true ;
84+ } ) ;
85+
86+ test ( 'Uninstalled previous version of rhel extension' , async ( { navigationBar } ) => {
87+ test . skip ( ! extensionInstalled || ! ! skipInstallation ) ;
88+ test . setTimeout ( 120_000 ) ;
89+ console . log ( 'Extension found already installed, trying to remove!' ) ;
90+ await ensureRhelExtensionIsRemoved ( navigationBar ) ;
91+ } ) ;
92+
93+ test ( 'Install extension through Extension page' , async ( { navigationBar } ) => {
94+ test . skip ( ! ! skipInstallation ) ;
95+ test . setTimeout ( 200_000 ) ;
96+
97+ const extensionsPage = await navigationBar . openExtensions ( ) ;
98+ await extensionsPage . installExtensionFromOCIImage ( extensionURL ) ;
99+
100+ await playExpect
101+ . poll ( async ( ) => await extensionsPage . extensionIsInstalled ( extensionLabel ) , { timeout : 30_000 } )
102+ . toBeTruthy ( ) ;
103+ } ) ;
58104 } ) ;
59105
60- test ( 'Uninstalled previous version of rhel extension' , async ( { navigationBar } ) => {
61- test . skip ( ! extensionInstalled || ! ! skipInstallation ) ;
62- test . setTimeout ( 120_000 ) ;
63- console . log ( 'Extension found already installed, trying to remove!' ) ;
64- await ensureRhelExtensionIsRemoved ( navigationBar ) ;
106+ test . describe . serial ( 'Red Hat Authentication extension installation' , ( ) => {
107+ test ( 'SSO provider is available in Authentication Page' , async ( { page, navigationBar } ) => {
108+ const settingsBar = await navigationBar . openSettings ( ) ;
109+ await settingsBar . openTabPage ( AuthenticationPage ) ;
110+
111+ const authPage = new AuthenticationPage ( page ) ;
112+ await playExpect ( authPage . heading ) . toBeVisible ( { timeout : 10_000 } ) ;
113+
114+ signInButton = page . getByRole ( 'button' , { name : 'Sign in' } ) ;
115+ await playExpect ( signInButton ) . toBeVisible ( ) ;
116+ } ) ;
117+
118+ test ( 'Can open authentication page in browser' , async ( { navigationBar, page } ) => {
119+ test . setTimeout ( 120_000 ) ;
120+ const settingsBar = await navigationBar . openSettings ( ) ;
121+ await settingsBar . openTabPage ( AuthenticationPage ) ;
122+ const authPage = new AuthenticationPage ( page ) ;
123+ await playExpect ( authPage . heading ) . toBeVisible ( { timeout : 10_000 } ) ;
124+
125+ // start up chrome instance and return browser object
126+ browser = await startChromium ( chromePort , path . join ( ...browserOutputPath ) ) ;
127+
128+ // open the link from PD
129+ await page . bringToFront ( ) ;
130+
131+ await playExpect ( signInButton ) . toBeEnabled ( { timeout : 10_000 } ) ;
132+ await signInButton . click ( ) ;
133+
134+ await page . waitForTimeout ( 5_000 ) ;
135+
136+ const urlMatch = await getEntryFromLogs ( page , / \. * o p e n i d - c o n n e c t .* / , regex , 'sso.redhat.com' ) ;
137+ if ( urlMatch ) {
138+ const context = await browser . newContext ( ) ;
139+ const newPage = await context . newPage ( ) ;
140+ await newPage . goto ( urlMatch ) ;
141+ await newPage . waitForURL ( / s s o .r e d h a t .c o m / ) ;
142+ chromiumPage = newPage ;
143+ const page = await findPageWithTitleInBrowser ( browser , expectedAuthPageTitle ) ;
144+ console . log ( `Found page with title: ${ await page ?. title ( ) } ` ) ;
145+ } else {
146+ throw new Error ( 'Did not find Initial SSO Login Page' ) ;
147+ }
148+ } ) ;
149+
150+ test ( 'User can authenticate via browser' , async ( ) => {
151+ // Activate the browser window and perform login
152+ playExpect ( chromiumPage ) . toBeDefined ( ) ;
153+ if ( ! chromiumPage ) {
154+ throw new Error ( 'Chromium browser page was not initialized' ) ;
155+ }
156+ await chromiumPage . bringToFront ( ) ;
157+ console . log ( `Switched to Chrome tab with title: ${ await chromiumPage . title ( ) } ` ) ;
158+ const usernameAction : ConfirmInputValue = {
159+ inputLocator : chromiumPage . getByRole ( 'textbox' , { name : 'Red Hat login or email' } ) ,
160+ inputValue : process . env . DVLPR_USERNAME ?? 'unknown' ,
161+ confirmLocator : chromiumPage . getByRole ( 'button' , { name : 'Next' } ) ,
162+ } ;
163+ const passwordAction : ConfirmInputValue = {
164+ inputLocator : chromiumPage . getByRole ( 'textbox' , { name : 'Password' } ) ,
165+ inputValue : process . env . DVLPR_PASSWORD ?? 'unknown' ,
166+ confirmLocator : chromiumPage . getByRole ( 'button' , { name : 'Log in' } ) ,
167+ } ;
168+ await performBrowserLogin ( chromiumPage , / L o g I n / , usernameAction , passwordAction , async chromiumPage => {
169+ const backButton = chromiumPage . getByRole ( 'button' , { name : 'Go back to Podman Desktop' } ) ;
170+ await playExpect ( backButton ) . toBeEnabled ( ) ;
171+ await backButton . click ( ) ;
172+ } ) ;
173+ await chromiumPage . close ( ) ;
174+ } ) ;
65175 } ) ;
66176
67- test ( 'Install extension through Extension page' , async ( { navigationBar } ) => {
68- test . skip ( ! ! skipInstallation ) ;
69- test . setTimeout ( 200_000 ) ;
177+ test . describe . serial ( 'RHEL VMs Extension' , ( ) => {
178+ test ( 'Create RHEL VM' , async ( { page } ) => {
179+ test . setTimeout ( 310_000 ) ;
180+ await createRhelVM ( page , 300_000 ) ;
181+
182+ const resourcesPage = new ResourcesPage ( page ) ;
183+ await playExpect ( resourcesPage . heading ) . toBeVisible ( { timeout : 10_000 } ) ;
184+
185+ const machineCard = new ResourceConnectionCardPage ( page , 'macadam' , 'rhel' ) ;
186+ await playExpect . poll ( async ( ) => machineCard . doesResourceElementExist ( ) , { timeout : 30_000 } ) . toBeTruthy ( ) ;
187+ playExpect ( await machineCard . resourceElementConnectionStatus . innerText ( ) ) . toContain ( ResourceElementState . Off ) ;
188+ } ) ;
189+
190+ test ( 'Start RHEL VM' , async ( { page } ) => {
191+ test . setTimeout ( 70_000 ) ;
192+ const machineCard = new ResourceConnectionCardPage ( page , 'macadam' , 'rhel' ) ;
193+ await machineCard . performConnectionAction ( ResourceElementActions . Start ) ;
194+
195+ await waitUntil (
196+ async ( ) =>
197+ ( await machineCard . resourceElementConnectionStatus . innerText ( ) ) . includes ( ResourceElementState . Running ) ,
198+ { timeout : 60_000 , sendError : true } ,
199+ ) ;
200+ } ) ;
201+
202+ test ( 'Stop RHEL VM' , async ( { page } ) => {
203+ test . setTimeout ( 70_000 ) ;
204+ const machineCard = new ResourceConnectionCardPage ( page , 'macadam' , 'rhel' ) ;
205+ await machineCard . performConnectionAction ( ResourceElementActions . Stop ) ;
206+
207+ await waitUntil (
208+ async ( ) => ( await machineCard . resourceElementConnectionStatus . innerText ( ) ) . includes ( ResourceElementState . Off ) ,
209+ { timeout : 30_000 , sendError : true } ,
210+ ) ;
211+ } ) ;
70212
71- const extensionsPage = await navigationBar . openExtensions ( ) ;
72- await extensionsPage . installExtensionFromOCIImage ( extensionURL ) ;
213+ test ( 'Remove RHEL VM' , async ( { page } ) => {
214+ test . setTimeout ( 70_000 ) ;
215+ const machineCard = new ResourceConnectionCardPage ( page , 'macadam' , 'rhel' ) ;
216+ await machineCard . performConnectionAction ( ResourceElementActions . Delete ) ;
73217
74- await playExpect
75- . poll ( async ( ) => await extensionsPage . extensionIsInstalled ( extensionLabel ) , { timeout : 30_000 } )
76- . toBeTruthy ( ) ;
218+ await playExpect . poll ( async ( ) => machineCard . doesResourceElementExist ( ) , { timeout : 30_000 } ) . toBeFalsy ( ) ;
219+ } ) ;
77220 } ) ;
78221
79222 test ( 'Remove RHEL extension through Settings' , async ( { navigationBar } ) => {
@@ -99,3 +242,28 @@ async function ensureRhelExtensionIsRemoved(navigationBar: NavigationBar): Promi
99242 . poll ( async ( ) => await extensionsPage . extensionIsInstalled ( extensionLabel ) , { timeout : 30_000 } )
100243 . toBeFalsy ( ) ;
101244}
245+
246+ async function createRhelVM ( page : Page , timeout = 120_000 ) : Promise < void > {
247+ const navigationBar = new NavigationBar ( page ) ;
248+ const rhelResourceCard = new ResourceConnectionCardPage ( page , 'macadam' ) ;
249+
250+ const settingsPage = await navigationBar . openSettings ( ) ;
251+ const resourcesPage = await settingsPage . openTabPage ( ResourcesPage ) ;
252+ await playExpect ( resourcesPage . heading ) . toBeVisible ( { timeout : 10_000 } ) ;
253+ await playExpect . poll ( async ( ) => resourcesPage . resourceCardIsVisible ( 'macadam' ) ) . toBeTruthy ( ) ;
254+ await playExpect ( rhelResourceCard . createButton ) . toBeVisible ( ) ;
255+
256+ await rhelResourceCard . createButton . click ( ) ;
257+
258+ const rhelVMNameInput = page . getByLabel ( 'Machine Name' , { exact : true } ) ;
259+ await playExpect ( rhelVMNameInput ) . toBeVisible ( { timeout : 10_000 } ) ;
260+ await playExpect ( rhelVMNameInput ) . toHaveValue ( 'rhel' ) ;
261+
262+ const createRhelVMButton = page . getByRole ( 'button' , { name : 'Create' , exact : true } ) ;
263+ await playExpect ( createRhelVMButton ) . toBeEnabled ( { timeout : 10_000 } ) ;
264+ await createRhelVMButton . click ( ) ;
265+
266+ const goBackButton = page . getByRole ( 'button' , { name : 'Go back to resources' } ) ;
267+ await playExpect ( goBackButton ) . toBeEnabled ( { timeout : timeout } ) ;
268+ await goBackButton . click ( ) ;
269+ }
0 commit comments