Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ui): update ui e2e tests #14619

Merged
merged 2 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
9 changes: 9 additions & 0 deletions ui-test/.env
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ IS_HEADLESS=true
# URL of the ArgoCD UI to test against
ARGOCD_URL=http://localhost:4000
#
# argocd app definition namespace
ARGOCD_NAMESPACE=argocd-e2e
#
# argocd credentials (if any)
#ARGOCD_AUTH_USERNAME=admin
#
# argocd credentials (if any)
#ARGOCD_AUTH_PASSWORD=password
#
# Git repository where applications reside
GIT_REPO=https://github.com/argoproj/argocd-example-apps
#
Expand Down
5 changes: 4 additions & 1 deletion ui-test/src/Configuration.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
require('dotenv').config({path: __dirname + '/.env'});
require('dotenv').config({path: __dirname + '/../.env'});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we run the scripts defined in the package.json, the .env file gets copied over to the out folder and so it will be in current directory. But this will work too.


export default class Configuration {
// Test specific
public static readonly ENABLE_CONSOLE_LOG: string | undefined = process.env.ENABLE_CONSOLE_LOG;
public static readonly TEST_TIMEOUT: string | undefined = process.env.TEST_TIMEOUT;
// ArgoCD UI specific. These are for single application-based tests, so one can quickly create an app based on the environment variables
public static readonly ARGOCD_URL: string = process.env.ARGOCD_URL ? process.env.ARGOCD_URL : '';
public static readonly ARGOCD_NAMESPACE: string = process.env.ARGOCD_NAMESPACE || 'argocd';
public static readonly ARGOCD_AUTH_USERNAME: string = process.env.ARGOCD_AUTH_USERNAME || '';
public static readonly ARGOCD_AUTH_PASSWORD: string = process.env.ARGOCD_AUTH_PASSWORD || '';
public static readonly APP_NAME: string = process.env.APP_NAME ? process.env.APP_NAME : '';
public static readonly APP_PROJECT: string = process.env.APP_PROJECT ? process.env.APP_PROJECT : '';
public static readonly GIT_REPO: string = process.env.GIT_REPO ? process.env.GIT_REPO : '';
Expand Down
2 changes: 1 addition & 1 deletion ui-test/src/Constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const TEST_TIMEOUT: number = 60000;
export const TEST_SLIDING_PANEL_TIMEOUT: number = 6000;
export const TEST_SLIDING_PANEL_TIMEOUT: number = 10000;
export const TEST_IS_NOT_VISIBLE_TIMEOUT: number = 5000;
export const ENABLE_CONSOLE_LOG: boolean = true;
2 changes: 1 addition & 1 deletion ui-test/src/UiTestUtilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export default class UiTestUtilities {
timeout = parseInt(Configuration.TEST_TIMEOUT, 10);
}
const element = await driver.wait(until.elementLocated(locator), timeout);
var isDisplayed = await element.isDisplayed();
const isDisplayed = await element.isDisplayed();
if (isDisplayed) {
await driver.wait(until.elementIsVisible(element), timeout);
}
Expand Down
31 changes: 13 additions & 18 deletions ui-test/src/applications-list/applications-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {Base} from '../base';
import {ApplicationCreatePanel} from '../application-create-panel/application-create-panel';
import {ApplicationsSyncPanel, SYNC_PANEL_SYNCHRONIZE_BUTTON} from '../applications-sync-panel/applications-sync-panel';
import {PopupManager} from '../popup/popup-manager';
import Configuration from '../Configuration';

const NEW_APP_BUTTON: By = By.xpath('.//button[@qe-id="applications-list-button-new-app"]');
// Uncomment to use:
Expand Down Expand Up @@ -155,45 +156,39 @@ export class ApplicationsList extends Base {

// Locators

// By.css('#app .applications-tiles .applications-list-" + appName + "'');
// By.css('#app .applications-tiles .applications-list-argocd_" + appName + "'');

private getApplicationTileSelector(appName: string): string {
return './/div[contains(@class,"qe-applications-list-' + Configuration.ARGOCD_NAMESPACE + '_' + appName + '")]';
}

private getApplicationTileLocator(appName: string): By {
return By.xpath('.//div[contains(@class,"qe-applications-list-"' + appName + ')');
return By.xpath(this.getApplicationTileSelector(appName));
}

private getSyncButtonLocatorForApp(appName: string): By {
return By.xpath('.//div[contains(@class, "qe-applications-list-' + appName + '")]//div[@class="row"]//ancestor::a[@qe-id="applications-tiles-button-sync"]');
return By.xpath(this.getApplicationTileSelector(appName) + '//div[@class="row"]//ancestor::a[@qe-id="applications-tiles-button-sync"]');
}

private getDeleteButtonLocatorForApp(appName: string): By {
return By.xpath('.//div[contains(@class, "qe-applications-list-' + appName + '")]//div[@class="row"]//ancestor::a[@qe-id="applications-tiles-button-delete"]');
return By.xpath(this.getApplicationTileSelector(appName) + '//div[@class="row"]//ancestor::a[@qe-id="applications-tiles-button-delete"]');
}

private getRefreshButtonLocatorForApp(appName: string): By {
return By.xpath('.//div[contains(@class, "qe-applications-list-' + appName + '")]//div[@class="row"]//ancestor::a[@qe-id="applications-tiles-button-refresh"]');
return By.xpath(this.getApplicationTileSelector(appName) + '//div[@class="row"]//ancestor::a[@qe-id="applications-tiles-button-refresh"]');
}

private getApplicationHealthTitle(appName: string): By {
return By.xpath(
'.//div[contains(@class, "qe-applications-list-' +
appName +
'")]//div[@class="row"]//div[@qe-id="applications-tiles-health-status"]//i[@qe-id="utils-health-status-title"]'
);
return By.xpath(this.getApplicationTileSelector(appName) + '//div[@class="row"]//div[@qe-id="applications-tiles-health-status"]//i[@qe-id="utils-health-status-title"]');
}

private getApplicationSyncTitle(appName: string): By {
return By.xpath(
'.//div[contains(@class, "qe-applications-list-' +
appName +
'")]//div[@class="row"]//div[@qe-id="applications-tiles-health-status"]//i[@qe-id="utils-sync-status-title"]'
);
return By.xpath(this.getApplicationTileSelector(appName) + '//div[@class="row"]//div[@qe-id="applications-tiles-health-status"]//i[@qe-id="utils-sync-status-title"]');
}

private getApplicationOperationsTitle(appName: string): By {
return By.xpath(
'.//div[contains(@class, "qe-applications-list-' +
appName +
'")]//div[@class="row"]//div[@qe-id="applications-tiles-health-status"]//i[@qe-id="utils-operations-status-title"]'
this.getApplicationTileSelector(appName) + '//div[@class="row"]//div[@qe-id="applications-tiles-health-status"]//i[@qe-id="utils-operations-status-title"]'
);
}
}
28 changes: 28 additions & 0 deletions ui-test/src/auth/login-page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {By, WebDriver} from 'selenium-webdriver';
import {Base} from '../base';
import Configuration from '../Configuration';
import UiTestUtilities from '../UiTestUtilities';

const LOGIN_FORM: By = By.css('#app .login__box form');
const LOGIN_FORM_INPUT: By = By.css('input.argo-field');
const LOGIN_FORM_BUTTON: By = By.css('button.argo-button');

export class AuthLoginPage extends Base {
public constructor(driver: WebDriver) {
super(driver);
}

/**
* Fill login form and submit it
*/
public async loginWithCredentials() {
const loginForm = await UiTestUtilities.findUiElement(this.driver, LOGIN_FORM);
const inputs = await loginForm.findElements(LOGIN_FORM_INPUT);
const submitButton = await loginForm.findElement(LOGIN_FORM_BUTTON);

await inputs[0].sendKeys(Configuration.ARGOCD_AUTH_USERNAME);
await inputs[1].sendKeys(Configuration.ARGOCD_AUTH_PASSWORD);

await submitButton.click();
}
}
15 changes: 11 additions & 4 deletions ui-test/src/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,25 @@ import {By, WebDriver} from 'selenium-webdriver';
import {ApplicationsList} from './applications-list/applications-list';
import UiTestUtilities from './UiTestUtilities';
import {Base} from './base';
import {AuthLoginPage} from './auth/login-page';

const NAVBAR_APPLICATIONS_BUTTON: By = By.css('#app .nav-bar .argo-icon-application');
const NAVBAR_SETTINGS_BUTTON: By = By.css('#app .nav-bar .argo-icon-settings');
const NAVBAR_USER_INFO_BUTTON: By = By.css('#app .nav-bar .fa-user-circle');
const NAVBAR_DOCS_BUTTON: By = By.css('#app .nav-bar .argo-icon-docs');
const NAVBAR_APPLICATIONS_BUTTON: By = By.css('#app .sidebar .argo-icon-application');
const NAVBAR_SETTINGS_BUTTON: By = By.css('#app .sidebar .argo-icon-settings');
const NAVBAR_USER_INFO_BUTTON: By = By.css('#app .sidebar .fa-user-circle');
const NAVBAR_DOCS_BUTTON: By = By.css('#app .sidebar .argo-icon-docs');

export class Navigation extends Base {
private applicationsList: ApplicationsList;
private authLoginPage: AuthLoginPage;

public constructor(driver: WebDriver) {
super(driver);
this.applicationsList = new ApplicationsList(this.driver);
this.authLoginPage = new AuthLoginPage(this.driver);
}

public getLoginPage(): AuthLoginPage {
return this.authLoginPage;
}

/**
Expand Down
4 changes: 4 additions & 0 deletions ui-test/src/test001.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ import {PopupManager} from './popup/popup-manager';
async function doTest() {
const navigation = await UiTestUtilities.init();
try {
if (Configuration.ARGOCD_AUTH_USERNAME !== '') {
await navigation.getLoginPage().loginWithCredentials();
}

const appsList: ApplicationsList = await navigation.clickApplicationsNavBarButton();
const applicationCreatePanel: ApplicationCreatePanel = await appsList.clickNewAppButton();

Expand Down
7 changes: 7 additions & 0 deletions ui-test/src/test002.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import UiTestUtilities from './UiTestUtilities';
import {trace} from 'console';
import {ApplicationsList} from './applications-list/applications-list';
import {ApplicationCreatePanel} from './application-create-panel/application-create-panel';
import Configuration from './Configuration';

/**
* Test to demo how to visit each page via the navigation bar on the left.
Expand All @@ -10,11 +11,17 @@ import {ApplicationCreatePanel} from './application-create-panel/application-cre
async function doTest() {
const navigation = await UiTestUtilities.init();
try {
if (Configuration.ARGOCD_AUTH_USERNAME !== '') {
await navigation.getLoginPage().loginWithCredentials();
}

await navigation.clickDocsNavBarButton();
await navigation.clickUserInfoNavBarButton();
await navigation.clickSettingsNavBarButton();
const appsList: ApplicationsList = await navigation.clickApplicationsNavBarButton();
const applicationCreatePanel: ApplicationCreatePanel = await appsList.clickNewAppButton();
// wait slide effect
await navigation.sleep(500);
await applicationCreatePanel.clickCancelButton();
await UiTestUtilities.log('Test passed');
} catch (e) {
Expand Down