fix(ui): update ui e2e tests (#14619)

Signed-off-by: ebuildy <tdecaux@petalmd.com>
This commit is contained in:
Thomas Decaux
2024-11-28 18:52:20 +01:00
committed by GitHub
parent fc6105b2bd
commit e31aebe14c
9 changed files with 78 additions and 25 deletions

View File

@@ -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
#

View File

@@ -1,4 +1,4 @@
require('dotenv').config({path: __dirname + '/.env'});
require('dotenv').config({path: __dirname + '/../.env'});
export default class Configuration {
// Test specific
@@ -6,6 +6,9 @@ export default class Configuration {
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 : '';

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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:
@@ -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"]'
);
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
/**

View File

@@ -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();

View File

@@ -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.
@@ -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) {