Skip to content

Commit 166b681

Browse files
committed
chore(test): update and merge test files
Signed-off-by: xbabalov <t.babalova.17@gmail.com>
1 parent 53f8308 commit 166b681

3 files changed

Lines changed: 248 additions & 0 deletions

File tree

.github/workflows/pr-check.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,8 @@ jobs:
149149
runs-on: ubuntu-24.04
150150
env:
151151
SKIP_INSTALLATION: true
152+
DVLPR_USERNAME: ${{ secrets.DVLPR_USERNAME }}
153+
DVLPR_PASSWORD: ${{ secrets.DVLPR_PASSWORD }}
152154
steps:
153155
- uses: actions/checkout@v4
154156
with:

tests/src/developer-sandbox.spec.ts

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,17 @@ import {
2323
ExtensionCardPage,
2424
RunnerOptions,
2525
test,
26+
ResourceConnectionCardPage,
27+
startChromium,
28+
findPageWithTitleInBrowser,
29+
ConfirmInputValue,
30+
KubeContextPage,
31+
performBrowserLogin,
2632
} from '@podman-desktop/tests-playwright';
2733
import { DeveloperSandboxPage } from './model/pages/developer-sandbox-page';
34+
import { CreateResourcePage } from './model/pages/create-resource-page';
35+
import type { Browser, BrowserContext, Page } from '@playwright/test';
36+
import path, { join } from 'node:path';
2837

2938
let extensionInstalled = false;
3039
let extensionCard: ExtensionCardPage;
@@ -37,6 +46,11 @@ const activeExtensionStatus = 'ACTIVE';
3746
const disabledExtensionStatus = 'DISABLED';
3847
const activeConnectionStatus = 'RUNNING';
3948
const skipInstallation = process.env.SKIP_INSTALLATION === 'true';
49+
let browserOutputPath: string;
50+
let loginCommand = '';
51+
const resourceCardLabel = 'redhat.sandbox';
52+
const contextName = 'dev-sandbox-context-3';
53+
const chromePort = '9222';
4054

4155
test.use({
4256
runnerOptions: new RunnerOptions({ customFolder: 'sandbox-tests-pd', autoUpdate: false, autoCheckUpdates: false }),
@@ -45,6 +59,8 @@ test.beforeAll(async ({ runner, page, welcomePage }) => {
4559
runner.setVideoAndTraceName('sandbox-e2e');
4660
await welcomePage.handleWelcomePage(true);
4761
extensionCard = new ExtensionCardPage(page, extensionLabelName, extensionLabel);
62+
browserOutputPath = test.info().project.outputDir;
63+
console.log(`Saving browser test artifacts to: '${browserOutputPath}'`);
4864
});
4965

5066
test.afterAll(async ({ runner }) => {
@@ -140,6 +156,161 @@ test.describe.serial('Red Hat Developer Sandbox extension verification', () => {
140156
});
141157
});
142158

159+
test.describe.serial('Developer Sandbox cluster verification', async () => {
160+
test.describe.serial('Fetch login command via browser', async () => {
161+
let chromiumPage: Page | undefined;
162+
let browser: Browser | undefined;
163+
let context: BrowserContext | undefined;
164+
165+
test.afterAll(async () => {
166+
if (browser) {
167+
console.log('Stopping tracing and closing browser...');
168+
await context?.tracing.stop({ path: join(path.join(browserOutputPath), 'traces', 'browser-sandbox-trace.zip') });
169+
if (chromiumPage) {
170+
await chromiumPage.close();
171+
}
172+
await browser.close();
173+
}
174+
});
175+
176+
test('Open Developer Sandbox page in browser', async ({ navigationBar, page }) => {
177+
test.setTimeout(120_000);
178+
//get sandbox url
179+
const settingsBar = await navigationBar.openSettings();
180+
await settingsBar.resourcesTab.click();
181+
const resourcesPage = new ResourcesPage(page);
182+
playExpect(await resourcesPage.resourceCardIsVisible(resourceCardLabel)).toBeTruthy();
183+
await resourcesPage.goToCreateNewResourcePage(resourceCardLabel);
184+
const createResourcePage = new CreateResourcePage(page);
185+
await createResourcePage.logIntoSandboxButton.click();
186+
const websiteDialog = createResourcePage.content.getByRole('dialog', { name: 'Open External Website' });
187+
await playExpect(websiteDialog).toBeVisible();
188+
const sandboxUrl = await websiteDialog.getByLabel('Dialog Details').textContent();
189+
const cancelDialogButton = websiteDialog.getByRole('button', { name: 'Cancel' });
190+
await cancelDialogButton.click();
191+
192+
//open the website
193+
if (sandboxUrl) {
194+
browser = await startChromium(chromePort, path.join(browserOutputPath));
195+
context = await browser.newContext();
196+
await context.tracing.start({ screenshots: true, snapshots: true, sources: true });
197+
const newPage = await context.newPage();
198+
await newPage.goto(sandboxUrl);
199+
await newPage.waitForURL(/developers.redhat.com/);
200+
chromiumPage = newPage;
201+
if (browser) {
202+
await findPageWithTitleInBrowser(browser, 'Developer Sandbox | Red Hat Developer');
203+
}
204+
console.log(`Found page with title: ${await chromiumPage?.title()}`);
205+
} else {
206+
throw new Error('Did not find Developer Sandbox page');
207+
}
208+
});
209+
test('Log into Red Hat Sandbox', async () => {
210+
//go to login page
211+
playExpect(chromiumPage).toBeDefined();
212+
if (!chromiumPage) {
213+
throw new Error('Chromium browser page was not initialized');
214+
}
215+
await chromiumPage.bringToFront();
216+
console.log(`Switched to Chrome tab with title: ${await chromiumPage.title()}`);
217+
const startSandboxButton = chromiumPage.getByRole('button', { name: 'Start your sandbox for free' });
218+
await playExpect(startSandboxButton).toBeVisible();
219+
await startSandboxButton.click();
220+
221+
//log in, same tab
222+
const usernameAction: ConfirmInputValue = {
223+
inputLocator: chromiumPage.getByRole('textbox', { name: 'username' }),
224+
inputValue: process.env.DVLPR_USERNAME ?? 'unknown',
225+
confirmLocator: chromiumPage.getByRole('button', { name: 'Next' }),
226+
};
227+
const passwordAction: ConfirmInputValue = {
228+
inputLocator: chromiumPage.getByRole('textbox', { name: 'password' }),
229+
inputValue: process.env.DVLPR_PASSWORD ?? 'unknown',
230+
confirmLocator: chromiumPage.getByRole('button', { name: 'Log in' }),
231+
};
232+
const usernameBox = chromiumPage.getByRole('textbox', { name: 'Red Hat login' });
233+
await playExpect(usernameBox).toBeVisible({ timeout: 5_000 });
234+
await usernameBox.focus();
235+
236+
//after login redirect twice to sandbox.redhat.com, same tab
237+
await performBrowserLogin(chromiumPage, /Log In/, usernameAction, passwordAction, async (chromiumPage) => {
238+
playExpect(chromiumPage).toBeDefined();
239+
if (!chromiumPage) {
240+
throw new Error('Chromium browser page was not initialized');
241+
}
242+
playExpect(await chromiumPage.title()).toBe('Developer Sandbox | Developer Sandbox');
243+
await chromiumPage.screenshot({ path: join(path.join(browserOutputPath), 'screenshots', 'after_login_in_browser.png'), type: 'png', fullPage: true });
244+
});
245+
});
246+
test('Fetch the login command', async () => {
247+
//open "try it" openshift
248+
playExpect(chromiumPage).toBeDefined();
249+
if (!chromiumPage) {
250+
throw new Error('Chromium browser page was not initialized');
251+
}
252+
await chromiumPage.bringToFront();
253+
const openshiftBoxLabel = chromiumPage.getByAltText('Openshift', { exact: true });
254+
await playExpect(openshiftBoxLabel).toBeVisible();
255+
const openshiftBox = openshiftBoxLabel.locator('..').locator('..').locator('..');
256+
const tryItButton = openshiftBox.getByRole('button', { name: 'Try it' });
257+
await playExpect(tryItButton).toBeVisible();
258+
await tryItButton.click();
259+
260+
//new tab, log in through the Openshift auth page (sometimes might need reload)
261+
await loginThroughOpenshiftServicePage(browser!, chromiumPage);
262+
263+
//same tab, get login command from the Console Openshift page
264+
const userDropdownMenuButton = chromiumPage.getByRole('button', { name: 'User menu' });
265+
await playExpect(userDropdownMenuButton).toBeVisible({ timeout: 50_000 });
266+
await userDropdownMenuButton.click();
267+
const copyLoginCommandButton = chromiumPage.getByText('Copy login command');
268+
await playExpect(copyLoginCommandButton).toBeVisible();
269+
await copyLoginCommandButton.click();
270+
271+
//new tab, find command (sandbox login might need reload)
272+
await loginThroughOpenshiftServicePage(browser!, chromiumPage);
273+
274+
const displayTokenButton = chromiumPage.getByRole('button', { name: 'Display Token' });
275+
await playExpect(displayTokenButton).toBeVisible();
276+
await displayTokenButton.click();
277+
const commandElement = chromiumPage.getByText('oc login').locator('..');
278+
await playExpect(commandElement).toBeVisible();
279+
loginCommand = await commandElement.innerText();
280+
});
281+
});
282+
283+
test('Create Sandbox cluster', async ({ page }) => {
284+
await page.bringToFront();
285+
const createResourcePage = new CreateResourcePage(page);
286+
await createResourcePage.createResource(loginCommand, contextName);
287+
});
288+
289+
test('Verify Sandbox cluster and context', async ({ page, navigationBar }) => {
290+
const sandboxClusterCard = new ResourceConnectionCardPage(page, resourceCardLabel, contextName);
291+
playExpect(await sandboxClusterCard.doesResourceElementExist()).toBeTruthy();
292+
await playExpect(sandboxClusterCard.resourceElementConnectionStatus).toHaveText('RUNNING');
293+
294+
const settingsBar = await navigationBar.openSettings();
295+
await settingsBar.kubernetesTab.click();
296+
const kubeContextPage = new KubeContextPage(page);
297+
playExpect(await kubeContextPage.pageIsEmpty()).not.toBeTruthy();
298+
playExpect(await kubeContextPage.isContextReachable(contextName)).toBeTruthy();
299+
playExpect(await kubeContextPage.isContextDefault(contextName)).not.toBeTruthy();
300+
});
301+
302+
test('Delete remote cluster context', async ({ page, navigationBar }) => {
303+
const kubeContextPage = new KubeContextPage(page);
304+
await kubeContextPage.deleteContext(contextName);
305+
playExpect(await kubeContextPage.pageIsEmpty()).toBeTruthy();
306+
307+
const settingsBar = await navigationBar.openSettings();
308+
await settingsBar.resourcesTab.click();
309+
const sandboxClusterCard = new ResourceConnectionCardPage(page, resourceCardLabel, contextName);
310+
playExpect(await sandboxClusterCard.doesResourceElementExist()).not.toBeTruthy();
311+
});
312+
});
313+
143314
test('Extension can be removed', async ({ navigationBar }) => {
144315
await removeExtension(navigationBar);
145316
});
@@ -184,3 +355,14 @@ async function checkSandboxInDashboard(navigationBar: NavigationBar, isInstalled
184355
await playExpect(sandboxProviderCard).toBeHidden();
185356
}
186357
}
358+
359+
async function loginThroughOpenshiftServicePage(browser: Browser, chromiumPage: Page) {
360+
let loginSandboxPage = await findPageWithTitleInBrowser(browser!, 'Login - Red Hat OpenShift Service on AWS');
361+
if (!loginSandboxPage) {
362+
throw new Error('Sandbox service login browser page was not initialized');
363+
}
364+
await loginSandboxPage.bringToFront();
365+
const loginWithSandboxButton = chromiumPage.getByRole('button', { name: 'Log in with DevSandbox' });
366+
await playExpect(loginWithSandboxButton).toBeVisible();
367+
await loginWithSandboxButton.click();
368+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/**********************************************************************
2+
* Copyright (C) 2024 Red Hat, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
***********************************************************************/
18+
19+
import type { Page, Locator } from '@playwright/test';
20+
import { BasePage, ResourcesPage, expect as playExpect } from '@podman-desktop/tests-playwright';;
21+
22+
export class CreateResourcePage extends BasePage {
23+
readonly heading: Locator;
24+
readonly content: Locator;
25+
readonly logIntoSandboxButton: Locator;
26+
readonly contextName: Locator;
27+
readonly setAsCurrentContext: Locator;
28+
readonly loginCommand: Locator;
29+
readonly closeButton: Locator;
30+
readonly createButton: Locator;
31+
32+
constructor(page: Page) {
33+
super(page);
34+
this.heading = this.page.getByRole('heading', { name: 'Create Developer Sandbox' });
35+
this.content = this.page.getByRole('region', { name: 'Tab Content' });
36+
this.logIntoSandboxButton = this.page.getByRole('button', { name: 'Log into Developer Sandbox' });
37+
this.contextName = this.page.getByRole('textbox', { name: 'Context name' });
38+
this.setAsCurrentContext = this.page.getByRole('checkbox', { name: 'Set as current context' });
39+
this.loginCommand = this.page.getByRole('textbox', { name: 'Login command from Developer Console' });
40+
this.closeButton = this.page.getByRole('button', { name: 'Close page' });
41+
this.createButton = this.page.getByRole('button', { name: 'Create' });
42+
}
43+
44+
async createResource(loginCommandValue: string, contextNameValue?: string, setAsCurrentContextValue = false): Promise<ResourcesPage> {
45+
await this.loginCommand.fill(loginCommandValue);
46+
47+
if (contextNameValue) {
48+
await this.contextName.fill(contextNameValue);
49+
}
50+
51+
if (setAsCurrentContextValue !== (await this.setAsCurrentContext.isChecked())) {
52+
await this.setAsCurrentContext.locator('..').click();
53+
playExpect(await this.setAsCurrentContext.isChecked()).toBe(setAsCurrentContextValue);
54+
}
55+
56+
const successMessage = this.page.getByText('Successful operation');
57+
const goToResourcesButton = this.page.getByRole('button', { name: 'Go back to resources' });
58+
await playExpect(successMessage).toBeVisible();
59+
await playExpect(goToResourcesButton).toBeVisible();
60+
61+
await goToResourcesButton.click();
62+
return new ResourcesPage(this.page);
63+
}
64+
}

0 commit comments

Comments
 (0)