forked from argoproj/argo-cd
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: Add initial automated UI smoke tests (argoproj#4393) (argoproj#…
…4694) Signed-off-by: Keith Chong <[email protected]>
- Loading branch information
1 parent
c7738a0
commit 4a69cce
Showing
18 changed files
with
2,518 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# | ||
# Currently defined test environment variables. Uncomment and/or change as desired. | ||
# | ||
############################ | ||
# Test specific variables | ||
############################ | ||
# | ||
# Timeout to wait for an element to appear. The default is 60 sec. | ||
# TEST_TIMEOUT=60000 | ||
# | ||
# Run the tests in headless mode if true, non-headless mode if false | ||
IS_HEADLESS=true | ||
# | ||
# Turn on/off tracing to the console. The default is true. | ||
# ENABLE_CONSOLE_LOG=true | ||
# | ||
############################ | ||
# ArgoCD specific variables | ||
############################ | ||
# | ||
# URL of the ArgoCD UI to test against | ||
ARGOCD_URL=http://localhost:4000 | ||
# | ||
# Git repository where applications reside | ||
GIT_REPO=https://github.com/argoproj/argocd-example-apps | ||
# | ||
# The name to give the app in ArgoCD | ||
APP_NAME=myapp | ||
# | ||
# The project name | ||
APP_PROJECT=default | ||
# | ||
# The source path of the application in the repo | ||
SOURCE_REPO_PATH=helm-guestbook | ||
# | ||
# Destination cluster name | ||
DESTINATION_CLUSTER_NAME=in-cluster | ||
# | ||
# Destination namespace | ||
DESTINATION_NAMESPACE=default |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
.vscode/ | ||
.idea/ | ||
.DS_Store | ||
out/ | ||
node_modules/ | ||
.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"bracketSpacing": false, | ||
"jsxSingleQuote": true, | ||
"printWidth": 180, | ||
"singleQuote": true, | ||
"tabWidth": 4, | ||
"jsxBracketSameLine": true, | ||
"quoteProps": "consistent" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
{ | ||
"name": "ui-test", | ||
"version": "1.0.0", | ||
"description": "UI Testing", | ||
"main": "argocd-ui-test", | ||
"scripts": { | ||
"compile": "npx tsc", | ||
"test": "node out/test001.js", | ||
"pretest": "cp .env out/.env", | ||
"lint": "tslint -p ." | ||
}, | ||
"author": "Keith Chong", | ||
"license": "Apache-2.0", | ||
"dependencies": { | ||
"@types/selenium-webdriver": "^4.0.9", | ||
"assert": "^2.0.0", | ||
"chromedriver": "^86.0.0", | ||
"selenium-webdriver": "^4.0.0-alpha.7" | ||
}, | ||
"devDependencies": { | ||
"@types/mocha": "^8.0.3", | ||
"@types/node": "^14.14.2", | ||
"dotenv": "^8.2.0", | ||
"mocha": "^8.2.0", | ||
"prettier": "^1.18.2", | ||
"tslint": "^6.1.3", | ||
"tslint-config-prettier": "^1.18.0", | ||
"tslint-plugin-prettier": "^2.0.1", | ||
"typescript": "^4.0.3", | ||
"yarn": "^1.22.10" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
require('dotenv').config({path: __dirname + '/.env'}); | ||
|
||
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 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 : ''; | ||
public static readonly SOURCE_REPO_PATH: string = process.env.SOURCE_REPO_PATH ? process.env.SOURCE_REPO_PATH : ''; | ||
public static readonly DESTINATION_CLUSTER_NAME: string = process.env.DESTINATION_CLUSTER_NAME ? process.env.DESTINATION_CLUSTER_NAME : ''; | ||
public static readonly DESTINATION_NAMESPACE: string = process.env.DESTINATION_NAMESPACE ? process.env.DESTINATION_NAMESPACE : ''; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export const TEST_TIMEOUT: number = 60000; | ||
export const TEST_SLIDING_PANEL_TIMEOUT: number = 5000; | ||
export const TEST_IS_NOT_VISIBLE_TIMEOUT: number = 5000; | ||
export const ENABLE_CONSOLE_LOG: boolean = true; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
import Configuration from './Configuration'; | ||
import {Builder, By, until, WebDriver, WebElement} from 'selenium-webdriver'; | ||
import chrome from 'selenium-webdriver/chrome'; | ||
import * as Const from './Constants'; | ||
import {Navigation} from './navigation'; | ||
|
||
export default class UiTestUtilities { | ||
/** | ||
* Log a message to the console. | ||
* @param message | ||
*/ | ||
public static async log(message: string): Promise<void> { | ||
let doLog = Const.ENABLE_CONSOLE_LOG; | ||
// Config override | ||
if (Configuration.ENABLE_CONSOLE_LOG) { | ||
if (Configuration.ENABLE_CONSOLE_LOG === 'false') { | ||
doLog = false; | ||
} else { | ||
doLog = true; | ||
} | ||
} | ||
if (doLog) { | ||
// tslint:disable-next-line:no-console | ||
console.log(message); | ||
} | ||
} | ||
|
||
public static async logError(message: string): Promise<void> { | ||
let doLog = Const.ENABLE_CONSOLE_LOG; | ||
// Config override | ||
if (Configuration.ENABLE_CONSOLE_LOG) { | ||
if (Configuration.ENABLE_CONSOLE_LOG === 'false') { | ||
doLog = false; | ||
} else { | ||
doLog = true; | ||
} | ||
} | ||
if (doLog) { | ||
// tslint:disable-next-line:no-console | ||
console.error(message); | ||
} | ||
} | ||
|
||
/** | ||
* Set up the WebDriver. Initial steps for all tests. Returns the instance of Navigation with the WebDriver. | ||
* From there, navigate the UI. Test cases do no need to reference the instance of WebDriver since Component/Page-specific | ||
* API methods should be called instead. | ||
* | ||
*/ | ||
public static async init(): Promise<Navigation> { | ||
const options = new chrome.Options(); | ||
if (process.env.IS_HEADLESS) { | ||
options.addArguments('headless'); | ||
} | ||
options.addArguments('window-size=1400x1200'); | ||
const driver = await new Builder() | ||
.forBrowser('chrome') | ||
.setChromeOptions(options) | ||
.build(); | ||
|
||
UiTestUtilities.log('Environment variables are:'); | ||
UiTestUtilities.log(require('dotenv').config({path: __dirname + '/../.env'})); | ||
|
||
// Navigate to the ArgoCD URL | ||
await driver.get(Configuration.ARGOCD_URL); | ||
|
||
return new Navigation(driver); | ||
} | ||
|
||
/** | ||
* Locate the UI Element for the given locator, and wait until it is visible | ||
* | ||
* @param driver | ||
* @param locator | ||
*/ | ||
public static async findUiElement(driver: WebDriver, locator: By): Promise<WebElement> { | ||
try { | ||
let timeout = Const.TEST_TIMEOUT; | ||
if (Configuration.TEST_TIMEOUT) { | ||
timeout = parseInt(Configuration.TEST_TIMEOUT, 10); | ||
} | ||
const element = await driver.wait(until.elementLocated(locator), timeout); | ||
await driver.wait(until.elementIsVisible(element), timeout); | ||
return element; | ||
} catch (err) { | ||
throw err; | ||
} | ||
} | ||
|
||
/** | ||
* Similar to until.methods and used in driver.wait, this will wait until | ||
* the expected attribute is the same as the actual attribute on the element | ||
* | ||
* @param attr | ||
* @param attrValue | ||
*/ | ||
public static async untilAttributeIs(element: WebElement, attr: string, attrValue: string): Promise<boolean> { | ||
const actual = await element.getAttribute(attr); | ||
UiTestUtilities.log('Actual = ' + actual + ', expected = ' + attrValue + ', ' + (actual === attrValue)); | ||
return actual === attrValue; | ||
} | ||
|
||
/** | ||
* Similar to until.methods and used in driver.wait, this function will wait until | ||
* the element (eg. operation state) title attribute no longer is present | ||
* | ||
* @param element | ||
*/ | ||
public static async untilOperationStatusDisappears(element: WebElement): Promise<boolean> { | ||
try { | ||
const opState = await element.getAttribute('title'); | ||
UiTestUtilities.log('Operation State = ' + opState); | ||
return false; | ||
} catch (err) { | ||
UiTestUtilities.log('Status disappeared'); | ||
return true; | ||
} | ||
} | ||
|
||
/** | ||
* For clicking on elements if WebElement.click() doesn't work | ||
* | ||
* @param driver | ||
* @param element | ||
*/ | ||
public static async click(driver: WebDriver, element: WebElement): Promise<void> { | ||
try { | ||
// Execute synchronous script | ||
await driver.executeScript('arguments[0].click();', element); | ||
} catch (e) { | ||
throw e; | ||
} | ||
} | ||
} |
Oops, something went wrong.