diff --git a/tests/e2e/configs/mocharc.ts b/tests/e2e/configs/mocharc.ts index cbd793d69a1..bb9ef2ce867 100644 --- a/tests/e2e/configs/mocharc.ts +++ b/tests/e2e/configs/mocharc.ts @@ -21,8 +21,9 @@ module.exports = { timeout: MOCHA_CONSTANTS.MOCHA_DEFAULT_TIMEOUT, slow: 60000, reporter: 'mocha-multi-reporters', - reporterOptions: 'configFile=configs/reporters-config.json', + reporterOptions: 'configFile=configs/reporters.config.js', ui: 'tdd', + extension: ['js', 'cjs', 'mjs'], require: ['dist/specs/MochaHooks.js', 'ts-node/register'], bail: MOCHA_CONSTANTS.MOCHA_BAIL, 'full-trace': true, @@ -39,5 +40,6 @@ module.exports = { : MOCHA_CONSTANTS.MOCHA_USERSTORY ? [`dist/specs/**/${MOCHA_CONSTANTS.MOCHA_USERSTORY}.spec.js`, `dist/specs/${MOCHA_CONSTANTS.MOCHA_USERSTORY}.spec.js`] : ['dist/specs/**/**.spec.js', 'dist/specs/**.spec.js'], - retries: MOCHA_CONSTANTS.MOCHA_RETRIES + retries: MOCHA_CONSTANTS.MOCHA_RETRIES, + grep: MOCHA_CONSTANTS.MOCHA_GREP }; diff --git a/tests/e2e/configs/reporters-config.json b/tests/e2e/configs/reporters-config.json deleted file mode 100644 index 82a75b921dd..00000000000 --- a/tests/e2e/configs/reporters-config.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "reporterEnabled": "allure-mocha,dist/utils/CheReporter.js", - "allureMochaReporterOptions": { - "resultsDir": ".allure-results" - } -} diff --git a/tests/e2e/configs/reporters.config.js b/tests/e2e/configs/reporters.config.js new file mode 100644 index 00000000000..73f561544c8 --- /dev/null +++ b/tests/e2e/configs/reporters.config.js @@ -0,0 +1,51 @@ +/** ******************************************************************* + * copyright (c) 2023 Red Hat, Inc. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + **********************************************************************/ +const { REPORTER_CONSTANTS } = require('../constants/REPORTER_CONSTANTS'); +const { BASE_TEST_CONSTANTS } = require('../constants/BASE_TEST_CONSTANTS'); + +module.exports = { + reporterEnabled: REPORTER_CONSTANTS.REPORTERS_ENABLED(), + allureMochaReporterOptions: { + resultsDir: '.allure-results' + }, + reportportalAgentJsMochaReporterOptions: { + apiKey: REPORTER_CONSTANTS.RP_API_KEY, + endpoint: REPORTER_CONSTANTS.RP_ENDPOINT(), + project: REPORTER_CONSTANTS.RP_PROJECT(), + launch: `${REPORTER_CONSTANTS.RP_LAUNCH_NAME}`, + attributes: [ + { + key: 'build', + value: `${BASE_TEST_CONSTANTS.TESTING_APPLICATION_VERSION}` + }, + { + key: 'ocp version', + value: `${BASE_TEST_CONSTANTS.OCP_VERSION}` + }, + { + key: 'ocp infra', + value: `${BASE_TEST_CONSTANTS.OCP_INFRA}` + }, + { + key: 'application', + value: BASE_TEST_CONSTANTS.TESTING_APPLICATION_NAME() + }, + { + key: 'url', + value: BASE_TEST_CONSTANTS.TS_SELENIUM_BASE_URL + } + ], + rerun: REPORTER_CONSTANTS.RP_RERUN(), + rerunOf: REPORTER_CONSTANTS.RP_RERUN_UUID, + restClientConfig: { + timeout: 1200000 + } + } +}; diff --git a/tests/e2e/configs/sh-scripts/runFunctionalTests.sh b/tests/e2e/configs/sh-scripts/runFunctionalTests.sh index 29f527fb02f..576424978bb 100755 --- a/tests/e2e/configs/sh-scripts/runFunctionalTests.sh +++ b/tests/e2e/configs/sh-scripts/runFunctionalTests.sh @@ -3,8 +3,8 @@ validateParameters(){ # Validate required parameters - if [ -z "$OCP_VERSION" ] || [ -z "$ARCH_VERSION" ] || [ -z "$TS_SELENIUM_BASE_URL" ]; then - echo "The ARCH_VERSION, OCP_VERSION or TS_SELENIUM_BASE_URL is not set!"; + if [ -z "$OCP_VERSION" ] || [ -z "$OCP_INFRA" ] || [ -z "$TS_SELENIUM_BASE_URL" ]; then + echo "The OCP_INFRA, OCP_VERSION or TS_SELENIUM_BASE_URL is not set!"; echo "Please, set all required environment variable parameters" exit 1 fi @@ -17,14 +17,14 @@ validateParameters(){ launchAPITests() { export MOCHA_SUITE="APITest" echo "MOCHA_SUITE = ${MOCHA_SUITE}" - export RP_LAUNCH_NAME="API tests suite" + export RP_LAUNCH_NAME="API tests suite $TEST_ENVIRONMENT" echo "suites/$MOCHA_DIRECTORY/$MOCHA_SUITE" npm run driver-less-test } launchDynamicallyGeneratingAPITests() { export MOCHA_SUITE="DynamicallyGeneratingAPITest" - export RP_LAUNCH_NAME="Application inbuilt DevWorkspaces API tests suite" + export RP_LAUNCH_NAME="Application inbuilt DevWorkspaces API tests suite $TEST_ENVIRONMENT" echo "MOCHA_SUITE = ${MOCHA_SUITE}" echo "suites/$MOCHA_DIRECTORY/$MOCHA_SUITE" npm run delayed-test @@ -32,7 +32,7 @@ launchDynamicallyGeneratingAPITests() { launchUITests() { export MOCHA_SUITE="UITest" - export RP_LAUNCH_NAME="UI tests suite" + export RP_LAUNCH_NAME="UI tests suite $TEST_ENVIRONMENT" echo "MOCHA_SUITE = ${MOCHA_SUITE}" echo "suites/$MOCHA_DIRECTORY/$MOCHA_SUITE" npm run test @@ -59,7 +59,7 @@ initTestValues() { export MOCHA_DIRECTORY="online-ocp" fi - export TEST_ENVIRONMENT="$ARCH_VERSION $MOCHA_DIRECTORY $OCP_VERSION" + export TEST_ENVIRONMENT="$OCP_INFRA $MOCHA_DIRECTORY $OCP_VERSION" export DELETE_WORKSPACE_ON_FAILED_TEST=${DELETE_WORKSPACE_ON_FAILED_TEST:-'false'} export DELETE_SCREENCAST_IF_TEST_PASS=${DELETE_SCREENCAST_IF_TEST_PASS:-'true'} export NODE_TLS_REJECT_UNAUTHORIZED=${NODE_TLS_REJECT_UNAUTHORIZED:-'0'} diff --git a/tests/e2e/constants/BASE_TEST_CONSTANTS.ts b/tests/e2e/constants/BASE_TEST_CONSTANTS.ts index 886219f18a8..8ab1ceb4441 100644 --- a/tests/e2e/constants/BASE_TEST_CONSTANTS.ts +++ b/tests/e2e/constants/BASE_TEST_CONSTANTS.ts @@ -13,7 +13,7 @@ export enum Platform { } export const BASE_TEST_CONSTANTS: { - ARCH_VERSION: string; + OCP_INFRA: string; DELETE_WORKSPACE_ON_FAILED_TEST: boolean; IS_CLUSTER_DISCONNECTED: () => boolean; IS_PRODUCT_DOCUMENTATION_RELEASED: any; @@ -30,6 +30,7 @@ export const BASE_TEST_CONSTANTS: { TS_SELENIUM_PROJECT_ROOT_FILE_NAME: string; TS_SELENIUM_REQUEST_INTERCEPTOR: boolean; TS_SELENIUM_RESPONSE_INTERCEPTOR: boolean; + TESTING_APPLICATION_NAME: () => string; } = { /** * base URL of the application which should be checked @@ -37,9 +38,9 @@ export const BASE_TEST_CONSTANTS: { TS_SELENIUM_BASE_URL: !process.env.TS_SELENIUM_BASE_URL ? 'http://sample-url' : process.env.TS_SELENIUM_BASE_URL.replace(/\/$/, ''), /** - * system arch type + * ocp infra type, possible values "PSI", "AWS", "IBM Z", "IBM Power" */ - ARCH_VERSION: process.env.ARCH_VERSION || '', + OCP_INFRA: process.env.OCP_INFRA || '', /** * openShift version @@ -51,6 +52,17 @@ export const BASE_TEST_CONSTANTS: { */ TEST_ENVIRONMENT: process.env.TEST_ENVIRONMENT || '', + /** + * application name (DevSpaces or Che) + */ + TESTING_APPLICATION_NAME: (): string => { + return BASE_TEST_CONSTANTS.TS_SELENIUM_BASE_URL.includes('devspaces') + ? 'devspaces' + : BASE_TEST_CONSTANTS.TS_SELENIUM_BASE_URL.includes('che') + ? 'che' + : 'default'; + }, + /** * testing application version */ diff --git a/tests/e2e/constants/MOCHA_CONSTANTS.ts b/tests/e2e/constants/MOCHA_CONSTANTS.ts index 04a0fbc6c70..1fb05e96052 100644 --- a/tests/e2e/constants/MOCHA_CONSTANTS.ts +++ b/tests/e2e/constants/MOCHA_CONSTANTS.ts @@ -17,6 +17,7 @@ export const MOCHA_CONSTANTS: { MOCHA_USERSTORY: undefined | string; MOCHA_RETRIES: string | number; MOCHA_BAIL: boolean; + MOCHA_GREP: string | undefined; } = { MOCHA_DIRECTORY: process.env.MOCHA_DIRECTORY || undefined, @@ -26,9 +27,11 @@ export const MOCHA_CONSTANTS: { MOCHA_DELAYED_SUITE: process.env.MOCHA_DELAYED_SUITE === 'true', - MOCHA_DEFAULT_TIMEOUT: process.env.MOCHA_DEFAULT_TIMEOUT || 420000, + MOCHA_DEFAULT_TIMEOUT: Number(process.env.MOCHA_DEFAULT_TIMEOUT) || 420000, MOCHA_RETRIES: process.env.MOCHA_RETRIES || BASE_TEST_CONSTANTS.TEST_ENVIRONMENT === '' ? 0 : 2, - MOCHA_SUITE: process.env.MOCHA_SUITE || undefined + MOCHA_SUITE: process.env.MOCHA_SUITE || undefined, + + MOCHA_GREP: process.env.MOCHA_GREP || undefined }; diff --git a/tests/e2e/constants/REPORTER_CONSTANTS.ts b/tests/e2e/constants/REPORTER_CONSTANTS.ts index b9b566585a6..e662e1a124a 100644 --- a/tests/e2e/constants/REPORTER_CONSTANTS.ts +++ b/tests/e2e/constants/REPORTER_CONSTANTS.ts @@ -7,14 +7,29 @@ * * SPDX-License-Identifier: EPL-2.0 **********************************************************************/ +import { BASE_TEST_CONSTANTS } from './BASE_TEST_CONSTANTS'; +import { MOCHA_CONSTANTS } from './MOCHA_CONSTANTS'; + export const REPORTER_CONSTANTS: { + DELETE_SCREENCAST_IF_TEST_PASS: boolean; + RP_ENDPOINT(): string; + RP_IS_LOCAL_SERVER: boolean; + REPORTERS_ENABLED(): string; + RP_API_KEY: string; + RP_PROJECT(): string; + RP_RERUN(): boolean; + RP_RERUN_UUID: string | undefined; + RP_LAUNCH_NAME: string; + RP_USER: string; + RP_USE_PERSONAL: boolean; + SAVE_ALLURE_REPORT_DATA: boolean; + SAVE_RP_REPORT_DATA: boolean; TS_SELENIUM_DELAY_BETWEEN_SCREENSHOTS: number; - TS_SELENIUM_REPORT_FOLDER: string; TS_SELENIUM_EXECUTION_SCREENCAST: boolean; - TS_SELENIUM_PRINT_TIMEOUT_VARIABLES: string | boolean; TS_SELENIUM_LOAD_TEST_REPORT_FOLDER: string; TS_SELENIUM_LOG_LEVEL: string; - DELETE_SCREENCAST_IF_TEST_PASS: boolean; + TS_SELENIUM_PRINT_TIMEOUT_VARIABLES: string | boolean; + TS_SELENIUM_REPORT_FOLDER: string; } = { /** * path to folder with load tests execution report. @@ -44,10 +59,88 @@ export const REPORTER_CONSTANTS: { /** * log level settings, possible variants: 'INFO' (by default), 'DEBUG', 'TRACE'. */ - TS_SELENIUM_LOG_LEVEL: process.env.TS_SELENIUM_LOG_LEVEL || 'INFO', + TS_SELENIUM_LOG_LEVEL: process.env.TS_SELENIUM_LOG_LEVEL || 'TRACE', /** * print all timeout variables when tests launch, default to false */ - TS_SELENIUM_PRINT_TIMEOUT_VARIABLES: process.env.TS_SELENIUM_PRINT_TIMEOUT_VARIABLES || false + TS_SELENIUM_PRINT_TIMEOUT_VARIABLES: process.env.TS_SELENIUM_PRINT_TIMEOUT_VARIABLES === 'true', + + /** + * use local Allure reporter, default to false + */ + SAVE_ALLURE_REPORT_DATA: process.env.SAVE_ALLURE_REPORT_DATA === 'true', + + /** + * use ReportPortal reporter, default to false + */ + SAVE_RP_REPORT_DATA: process.env.SAVE_RP_REPORT_DATA === 'true', + + /** + * list of enabler reporters + */ + REPORTERS_ENABLED: (): string => { + let reporters: string = 'dist/utils/CheReporter.js'; + if (REPORTER_CONSTANTS.SAVE_ALLURE_REPORT_DATA) { + reporters += ',allure-mocha'; + } + if (REPORTER_CONSTANTS.SAVE_RP_REPORT_DATA) { + reporters += ',@reportportal/agent-js-mocha'; + } + return reporters; + }, + + /** + * reportPortal app key or user token + */ + RP_API_KEY: process.env.RP_API_KEY || '', + + /** + * user name on ReportPortal + */ + RP_USER: process.env.RP_USER || process.env.USER || process.env.BUILD_USER_ID || '', + + /** + * launch name to save report + */ + RP_LAUNCH_NAME: process.env.RP_LAUNCH_NAME || `Test run ${MOCHA_CONSTANTS.MOCHA_USERSTORY}`, + + /** + * launch name to save report + */ + RP_RERUN_UUID: process.env.RP_RERUN_UUID || undefined, + + /** + * is launch rerun + */ + RP_RERUN: (): boolean => !!REPORTER_CONSTANTS.RP_RERUN_UUID, + + /** + * is local or online server to use + */ + RP_IS_LOCAL_SERVER: process.env.RP_IS_LOCAL_SERVER !== 'false', + + /** + * url with endpoints where ReportPortal is + */ + RP_ENDPOINT: (): string => { + return process.env.RP_ENDPOINT || REPORTER_CONSTANTS.RP_IS_LOCAL_SERVER + ? 'http://localhost:8080/api/v1' + : 'https://reportportal-crw.apps.ocp-c1.prod.psi.redhat.com/api/v1'; + }, + + /** + * use personal project to save launch, if false launch will be send to devspaces or che project, true by default + */ + RP_USE_PERSONAL: process.env.RP_USE_PERSONAL !== 'false', + + /** + * project name to save launch + */ + RP_PROJECT: (): string => { + const project: string = REPORTER_CONSTANTS.RP_USE_PERSONAL + ? `${REPORTER_CONSTANTS.RP_USER}_personal` + : BASE_TEST_CONSTANTS.TESTING_APPLICATION_NAME(); + return process.env.RP_PROJECT || project; + } }; diff --git a/tests/e2e/constants/TIMEOUT_CONSTANTS.ts b/tests/e2e/constants/TIMEOUT_CONSTANTS.ts index a3af150a4ea..3c7d42552cc 100644 --- a/tests/e2e/constants/TIMEOUT_CONSTANTS.ts +++ b/tests/e2e/constants/TIMEOUT_CONSTANTS.ts @@ -8,25 +8,23 @@ * SPDX-License-Identifier: EPL-2.0 **********************************************************************/ export const TIMEOUT_CONSTANTS: { - TS_FIND_EXTENSION_TEST_TIMEOUT: number; - TS_SELENIUM_WORKSPACE_STATUS_POLLING: number; + TS_CLICK_DASHBOARD_ITEM_TIMEOUT: number; TS_COMMON_DASHBOARD_WAIT_TIMEOUT: number; - TS_EXPAND_PROJECT_TREE_ITEM_TIMEOUT: number; - TS_DIALOG_WINDOW_DEFAULT_TIMEOUT: number; + TS_COMMON_PLUGIN_TEST_TIMEOUT: number; TS_DASHBOARD_WORKSPACE_STOP_TIMEOUT: number; + TS_DIALOG_WINDOW_DEFAULT_TIMEOUT: number; + TS_EDITOR_TAB_INTERACTION_TIMEOUT: number; + TS_EXPAND_PROJECT_TREE_ITEM_TIMEOUT: number; + TS_FIND_EXTENSION_TEST_TIMEOUT: number; + TS_IDE_LOAD_TIMEOUT: number; TS_SELENIUM_CLICK_ON_VISIBLE_ITEM: number; TS_SELENIUM_DEFAULT_ATTEMPTS: number; - TS_SELENIUM_WORKSPACE_STATUS_ATTEMPTS: number; - TS_SELENIUM_WAIT_FOR_URL: number; TS_SELENIUM_DEFAULT_POLLING: number; - TS_IDE_LOAD_TIMEOUT: number; + TS_SELENIUM_LOAD_PAGE_TIMEOUT: number; + TS_SELENIUM_START_WORKSPACE_TIMEOUT: number; + TS_SELENIUM_WAIT_FOR_URL: number; TS_WAIT_LOADER_ABSENCE_TIMEOUT: number; TS_WAIT_LOADER_PRESENCE_TIMEOUT: number; - TS_SELENIUM_START_WORKSPACE_TIMEOUT: number; - TS_SELENIUM_LOAD_PAGE_TIMEOUT: number; - TS_CLICK_DASHBOARD_ITEM_TIMEOUT: number; - TS_COMMON_PLUGIN_TEST_TIMEOUT: number; - TS_EDITOR_TAB_INTERACTION_TIMEOUT: number; } = { /** * default amount of tries, "5" by default. @@ -45,16 +43,6 @@ export const TIMEOUT_CONSTANTS: { */ TS_SELENIUM_WAIT_FOR_URL: Number(process.env.TS_SELENIUM_WAIT_FOR_URL) || 10_000, - /** - * amount of tries for checking workspace status. - */ - TS_SELENIUM_WORKSPACE_STATUS_ATTEMPTS: Number(process.env.TS_SELENIUM_WORKSPACE_STATUS_ATTEMPTS) || 90, - - /** - * delay in milliseconds between checking workspace status tries. - */ - TS_SELENIUM_WORKSPACE_STATUS_POLLING: Number(process.env.TS_SELENIUM_WORKSPACE_STATUS_POLLING) || 10000, - /** * wait between workspace started and IDE ready to be used, "20 000" by default. */ diff --git a/tests/e2e/package-lock.json b/tests/e2e/package-lock.json index 853112e2c1b..553c8227f62 100644 --- a/tests/e2e/package-lock.json +++ b/tests/e2e/package-lock.json @@ -15,6 +15,7 @@ }, "devDependencies": { "@eclipse-che/che-devworkspace-generator": "next", + "@reportportal/agent-js-mocha": "^5.0.3", "@types/chai": "^4.3.4", "@types/clone-deep": "^4.0.1", "@types/mocha": "5.2.6", @@ -266,6 +267,24 @@ "node": ">=4" } }, + "node_modules/@babel/runtime": { + "version": "7.23.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.1.tgz", + "integrity": "sha512-hC2v6p8ZSI/W0HUzh3V8C5g+NwSKzKPtJwSpTjwl0o297GP9+ZLQSkdvHz46CM3LqyoXxq+5G9komY+eSqSO0g==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime/node_modules/regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==", + "dev": true + }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -512,6 +531,193 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/@reportportal/agent-js-mocha": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@reportportal/agent-js-mocha/-/agent-js-mocha-5.0.3.tgz", + "integrity": "sha512-QxR2yUJJ3cq0xOwQEa0/PqYZKbqV8j0JiT1rqku0VCYYhT0jvZARsz81IWjRuq6ZLZC2kQtAYIOwdEd6kd0pqA==", + "dev": true, + "dependencies": { + "@reportportal/client-javascript": "^5.0.12", + "mocha": "^10.2.0" + }, + "engines": { + "node": ">=10.x" + } + }, + "node_modules/@reportportal/agent-js-mocha/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@reportportal/agent-js-mocha/node_modules/minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@reportportal/agent-js-mocha/node_modules/mocha": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", + "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", + "dev": true, + "dependencies": { + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "nanoid": "3.3.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/@reportportal/agent-js-mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/@reportportal/agent-js-mocha/node_modules/nanoid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/@reportportal/agent-js-mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@reportportal/agent-js-mocha/node_modules/workerpool": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": true + }, + "node_modules/@reportportal/client-javascript": { + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/@reportportal/client-javascript/-/client-javascript-5.0.13.tgz", + "integrity": "sha512-HMW5i7PR90SnxTQwhWud7AaIuSzoiDL+m3XTWOtR35yliJIzNJca04HfM8W/J3afYdH6SrhUC4ItmEL654KTPw==", + "dev": true, + "dependencies": { + "axios": "^0.27.2", + "axios-retry": "^3.4.0", + "glob": "^7.2.3", + "ini": "^2.0.0", + "uniqid": "^5.4.0", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">=10.x" + } + }, + "node_modules/@reportportal/client-javascript/node_modules/axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "dev": true, + "dependencies": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, + "node_modules/@reportportal/client-javascript/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@reportportal/client-javascript/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@reportportal/client-javascript/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@testim/chrome-version": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.4.tgz", @@ -1148,6 +1354,16 @@ "follow-redirects": "^1.14.7" } }, + "node_modules/axios-retry": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-3.8.0.tgz", + "integrity": "sha512-CfIsQyWNc5/AE7x/UEReRUadiBmQeoBpSEC+4QyGLJMswTsP1tz0GW2YYPnE7w9+ESMef5zOgLDFpHynNyEZ1w==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.15.4", + "is-retry-allowed": "^2.2.0" + } + }, "node_modules/babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", @@ -3069,6 +3285,15 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/interpret": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", @@ -3275,6 +3500,18 @@ "node": ">=0.10.0" } }, + "node_modules/is-retry-allowed": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-2.2.0.tgz", + "integrity": "sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -5317,6 +5554,12 @@ "node": ">=4.2.0" } }, + "node_modules/uniqid": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/uniqid/-/uniqid-5.4.0.tgz", + "integrity": "sha512-38JRbJ4Fj94VmnC7G/J/5n5SC7Ab46OM5iNtSstB/ko3l1b5g7ALt4qzHFgGciFkyiRNtDXtLNb+VsxtMSE77A==", + "dev": true + }, "node_modules/universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", diff --git a/tests/e2e/package.json b/tests/e2e/package.json index 6deba53d638..8a09b24e9d7 100644 --- a/tests/e2e/package.json +++ b/tests/e2e/package.json @@ -22,12 +22,7 @@ "license": "ISC", "devDependencies": { "@eclipse-che/che-devworkspace-generator": "next", - "allure-decorators": "^2.4.0", - "allure-js-commons": "^2.4.0", - "allure-mocha": "^2.4.0", - "mocha-multi-reporters": "^1.5.1", - "allure-commandline": "^2.22.1", - "mocha-allure-reporter": "^1.4.0", + "@reportportal/agent-js-mocha": "^5.0.3", "@types/chai": "^4.3.4", "@types/clone-deep": "^4.0.1", "@types/mocha": "5.2.6", @@ -38,6 +33,10 @@ "@typescript-eslint/eslint-plugin": "^6.4.1", "@typescript-eslint/eslint-plugin-tslint": "^6.1.0", "@typescript-eslint/parser": "^6.1.0", + "allure-commandline": "^2.22.1", + "allure-decorators": "^2.4.0", + "allure-js-commons": "^2.4.0", + "allure-mocha": "^2.4.0", "axios": "^0.25.0", "chai": "^4.3.4", "chrome-har": "^0.13.2", @@ -48,9 +47,11 @@ "eslint-plugin-header": "^3.1.1", "eslint-plugin-jsdoc": "^46.5.0", "eslint-plugin-prettier": "^5.0.0", - "inversify-inject-decorators": "^3.1.0", "husky": "^8.0.3", + "inversify-inject-decorators": "^3.1.0", "mocha": "^9.1.3", + "mocha-allure-reporter": "^1.4.0", + "mocha-multi-reporters": "^1.5.1", "monaco-page-objects": "3.9.1", "prettier": "^3.0.2", "rimraf": "2.6.2", diff --git a/tests/e2e/specs/MochaHooks.ts b/tests/e2e/specs/MochaHooks.ts index 1e1677885d1..42a403628b1 100644 --- a/tests/e2e/specs/MochaHooks.ts +++ b/tests/e2e/specs/MochaHooks.ts @@ -25,9 +25,11 @@ import { CHROME_DRIVER_CONSTANTS } from '../constants/CHROME_DRIVER_CONSTANTS'; import { decorate, injectable, unmanaged } from 'inversify'; import { Main } from '@eclipse-che/che-devworkspace-generator/lib/main'; import { LocatorLoader } from 'monaco-page-objects/out/locators/loader'; +import { REPORTER_CONSTANTS } from '../constants/REPORTER_CONSTANTS'; const driverHelper: DriverHelper = e2eContainer.get(CLASSES.DriverHelper); let latestWorkspace: string = ''; +export let rpApi: any = undefined; export function registerRunningWorkspace(workspaceName: string): void { workspaceName !== '' ? Logger.debug(`with workspaceName:${workspaceName}`) : Logger.debug('delete workspace name'); @@ -37,6 +39,10 @@ export function registerRunningWorkspace(workspaceName: string): void { exports.mochaHooks = { beforeAll: [ + function initRPApi(): any { + rpApi = require('@reportportal/agent-js-mocha/lib/publicReportingAPI.js'); + }, + function decorateExternalClasses(): void { decorate(injectable(), Main); decorate(injectable(), LocatorLoader); @@ -69,15 +75,15 @@ exports.mochaHooks = { if (BASE_TEST_CONSTANTS.TS_DEBUG_MODE) { for (const [timeout, seconds] of Object.entries(TIMEOUT_CONSTANTS)) { Object.defineProperty(TIMEOUT_CONSTANTS, timeout, { - value: seconds * 100 + value: seconds * 2 }); } } } ], afterEach: [ - async function (this: Mocha.Context): Promise { - if (this.currentTest?.state === 'failed') { + async function saveAllureAttachments(this: Mocha.Context): Promise { + if (REPORTER_CONSTANTS.SAVE_ALLURE_REPORT_DATA && this.currentTest?.state === 'failed') { try { const screenshot: string = await driverHelper.getDriver().takeScreenshot(); allure.attachment('Screenshot', Buffer.from(screenshot, 'base64'), 'image/png'); @@ -86,6 +92,21 @@ exports.mochaHooks = { } } }, + async function saveReportportalAttachments(this: Mocha.Context): Promise { + if (REPORTER_CONSTANTS.SAVE_RP_REPORT_DATA && this.currentTest?.state === 'failed') { + try { + const screenshot: string = await driverHelper.getDriver().takeScreenshot(); + const attachment: { name: string; type: string; content: string } = { + name: 'screenshot.png', + type: 'image/png', + content: screenshot + }; + rpApi.error('Screenshot on fail: ', attachment); + } catch (e) { + rpApi.error('Could not attach the screenshot'); + } + } + }, // stop and remove running workspace function deleteWorkspaceOnFailedTest(this: Mocha.Context): void { if (this.currentTest?.state === 'failed') { @@ -103,8 +124,7 @@ exports.mochaHooks = { if (!BASE_TEST_CONSTANTS.TS_DEBUG_MODE && CHROME_DRIVER_CONSTANTS.TS_USE_WEB_DRIVER_FOR_TEST) { // ensure that fired events done await driverHelper.wait(5000); - await driverHelper.getDriver().quit(); - Logger.info('Chrome driver session stopped.'); + await driverHelper.quit(); } } ] diff --git a/tests/e2e/specs/SmokeTest.spec.ts b/tests/e2e/specs/SmokeTest.spec.ts index 7782843b357..4524f708585 100644 --- a/tests/e2e/specs/SmokeTest.spec.ts +++ b/tests/e2e/specs/SmokeTest.spec.ts @@ -20,7 +20,7 @@ import { BrowserTabsUtil } from '../utils/BrowserTabsUtil'; import { expect } from 'chai'; import { BASE_TEST_CONSTANTS } from '../constants/BASE_TEST_CONSTANTS'; -suite('The SmokeTest userstory', function (): void { +suite(`The SmokeTest userstory ${BASE_TEST_CONSTANTS.TEST_ENVIRONMENT}`, function (): void { const projectAndFileTests: ProjectAndFileTests = e2eContainer.get(CLASSES.ProjectAndFileTests); const workspaceHandlingTests: WorkspaceHandlingTests = e2eContainer.get(CLASSES.WorkspaceHandlingTests); const loginTests: LoginTests = e2eContainer.get(CLASSES.LoginTests); diff --git a/tests/e2e/specs/api/EmptyWorkspaceAPI.spec.ts b/tests/e2e/specs/api/EmptyWorkspaceAPI.spec.ts index a3ee0d27bce..7a508ec91e9 100644 --- a/tests/e2e/specs/api/EmptyWorkspaceAPI.spec.ts +++ b/tests/e2e/specs/api/EmptyWorkspaceAPI.spec.ts @@ -71,10 +71,6 @@ suite('Empty workspace API test', function (): void { BASE_TEST_CONSTANTS.TS_SELENIUM_PROJECT_ROOT_FILE_NAME ); }); - - suiteTeardown('Delete cloned project', function (): void { - containerTerminal.removeFolder(`${clonedProjectName}`); - }); }); suiteTeardown('Delete workspace', function (): void { diff --git a/tests/e2e/tests-library/LoginTests.ts b/tests/e2e/tests-library/LoginTests.ts index 0896c86129e..4bbc2fa6e4e 100644 --- a/tests/e2e/tests-library/LoginTests.ts +++ b/tests/e2e/tests-library/LoginTests.ts @@ -41,7 +41,10 @@ export class LoginTests { loginIntoOcpConsole(): void { test('Login into ocp console', async (): Promise => { - const openshiftConsoleUrl: string = BASE_TEST_CONSTANTS.TS_SELENIUM_BASE_URL.replace('devspaces', 'console-openshift-console'); + const openshiftConsoleUrl: string = BASE_TEST_CONSTANTS.TS_SELENIUM_BASE_URL.replace( + BASE_TEST_CONSTANTS.TESTING_APPLICATION_NAME(), + 'console-openshift-console' + ); await this.browserTabsUtil.navigateTo(openshiftConsoleUrl); await this.ocpLoginPage.login(); await this.browserTabsUtil.maximize(); diff --git a/tests/e2e/tsconfig.json b/tests/e2e/tsconfig.json index ece61f742c0..7357caec767 100644 --- a/tests/e2e/tsconfig.json +++ b/tests/e2e/tsconfig.json @@ -13,5 +13,5 @@ "noImplicitReturns": false, "sourceMap": true }, - "include": [".eslintrc.js", "**/*.ts", "**/**/*.ts"] + "include": [".eslintrc.js", "**/*.ts", "**/**/*.ts", "**/reporters.config.js"] } diff --git a/tests/e2e/utils/DevWorkspaceConfigurationHelper.ts b/tests/e2e/utils/DevWorkspaceConfigurationHelper.ts index 44e2539aee0..54d131eded4 100644 --- a/tests/e2e/utils/DevWorkspaceConfigurationHelper.ts +++ b/tests/e2e/utils/DevWorkspaceConfigurationHelper.ts @@ -56,6 +56,7 @@ export class DevWorkspaceConfigurationHelper { async generateDevfileContext(): Promise { Logger.debug(); + if (!this.params.projects) { this.params.projects = []; } @@ -71,6 +72,7 @@ export class DevWorkspaceConfigurationHelper { // write templates and then DevWorkspace in a single file getDevWorkspaceConfigurationYamlAsString(context: DevfileContext): string { Logger.debug(); + const allContentArray: any[] = context.devWorkspaceTemplates.map((template: V1alpha2DevWorkspaceTemplate): string => YAML.stringify(template) ); @@ -80,7 +82,7 @@ export class DevWorkspaceConfigurationHelper { } getDevWorkspaceConfigurationsAsYaml(allContentString: string): string { - Logger.debug(`${this.constructor.name}.${this.getDevWorkspaceConfigurationsAsYaml.name}`); + Logger.debug(); const content: any = {}; const contentArray: string[] = allContentString.split('---\n'); contentArray.forEach((e: any): void => { @@ -97,6 +99,7 @@ export class DevWorkspaceConfigurationHelper { return content; } patchDevWorkspaceConfigWithBuildContainerAttribute(devfileContextDevWorkspace: any): void { + Logger.debug(); devfileContextDevWorkspace.spec.template.attributes = YAML.parse(` controller.devfile.io/devworkspace-config: name: devworkspace-config diff --git a/tests/e2e/utils/DriverHelper.ts b/tests/e2e/utils/DriverHelper.ts index 95a1386fefa..f94a6796133 100644 --- a/tests/e2e/utils/DriverHelper.ts +++ b/tests/e2e/utils/DriverHelper.ts @@ -742,4 +742,10 @@ export class DriverHelper { await this.getDriver().navigate().to(url); } + + async quit(): Promise { + Logger.trace(); + + await this.getDriver().quit(); + } } diff --git a/tests/e2e/utils/KubernetesCommandLineToolsExecutor.ts b/tests/e2e/utils/KubernetesCommandLineToolsExecutor.ts index 94767a6870d..49046af21bc 100644 --- a/tests/e2e/utils/KubernetesCommandLineToolsExecutor.ts +++ b/tests/e2e/utils/KubernetesCommandLineToolsExecutor.ts @@ -46,14 +46,14 @@ export class KubernetesCommandLineToolsExecutor implements IKubernetesCommandLin } get namespace(): string | undefined { - this._namespace = - this._namespace !== undefined - ? this._namespace - : BASE_TEST_CONSTANTS.TS_SELENIUM_BASE_URL.includes('devspaces') - ? OAUTH_CONSTANTS.TS_SELENIUM_OCP_USERNAME + '-devspaces' - : BASE_TEST_CONSTANTS.TS_SELENIUM_BASE_URL.includes('che') - ? OAUTH_CONSTANTS.TS_SELENIUM_OCP_USERNAME + '-che' - : 'default'; + if (!this._namespace) { + const applicationName: string = BASE_TEST_CONSTANTS.TESTING_APPLICATION_NAME(); + if (applicationName === 'default') { + this._namespace = applicationName; + } else { + this._namespace = OAUTH_CONSTANTS.TS_SELENIUM_OCP_USERNAME + '-' + applicationName; + } + } return this._namespace; } diff --git a/tests/e2e/utils/Logger.ts b/tests/e2e/utils/Logger.ts index 68512f02b24..1431dadcf14 100644 --- a/tests/e2e/utils/Logger.ts +++ b/tests/e2e/utils/Logger.ts @@ -8,17 +8,23 @@ * SPDX-License-Identifier: EPL-2.0 **********************************************************************/ import { REPORTER_CONSTANTS } from '../constants/REPORTER_CONSTANTS'; +import { rpApi } from '../specs/MochaHooks'; -export abstract class Logger { +export class Logger { /** * uses for logging of fatal errors. * @param text log text * @param indentLevel log level */ + static error(text: string = '', indentLevel: number = 1): void { const callerInfo: string = this.getCallerInfo(); const logLevelSymbol: string = '[ERROR] '; - this.logText(indentLevel, logLevelSymbol, `${this.getFullMessage(callerInfo, text)}`); + const message: string = this.getFullMessage(callerInfo, text); + this.logText(indentLevel, logLevelSymbol, message); + if (this.sendLogMessageIntoReportPortal()) { + rpApi.error(message); + } } /** @@ -32,7 +38,11 @@ export abstract class Logger { } const callerInfo: string = this.getCallerInfo(); const logLevelSymbol: string = '[WARN] '; - this.logText(indentLevel, logLevelSymbol, `${this.getFullMessage(callerInfo, text)}`); + const message: string = this.getFullMessage(callerInfo, text); + this.logText(indentLevel, logLevelSymbol, message); + if (this.sendLogMessageIntoReportPortal()) { + rpApi.warn(message); + } } /** @@ -46,7 +56,11 @@ export abstract class Logger { } const callerInfo: string = this.getCallerInfo(); const logLevelSymbol: string = '• '; - this.logText(indentLevel, logLevelSymbol, `${this.getFullMessage(callerInfo, text)}`); + const message: string = this.getFullMessage(callerInfo, text); + this.logText(indentLevel, logLevelSymbol, message); + if (this.sendLogMessageIntoReportPortal()) { + rpApi.info(message); + } } /** @@ -64,7 +78,11 @@ export abstract class Logger { } const callerInfo: string = this.getCallerInfo(); const logLevelSymbol: string = '▼ '; - this.logText(indentLevel, logLevelSymbol, `${this.getFullMessage(callerInfo, text)}`); + const message: string = this.getFullMessage(callerInfo, text); + this.logText(indentLevel, logLevelSymbol, message); + if (this.sendLogMessageIntoReportPortal()) { + rpApi.debug(message); + } } /** @@ -84,13 +102,21 @@ export abstract class Logger { } const callerInfo: string = this.getCallerInfo(); const logLevelSymbol: string = '‣ '; - this.logText(indentLevel, logLevelSymbol, `${this.getFullMessage(callerInfo, text)}`); + const message: string = this.getFullMessage(callerInfo, text); + this.logText(indentLevel, logLevelSymbol, message); + if (this.sendLogMessageIntoReportPortal()) { + rpApi.trace(message); + } } private static getFullMessage(callerInfo: string, text: string): string { return `${callerInfo}${this.separator(text, callerInfo)}${text}`; } + private static separator(text: string, caller: string): string { + return text ? (caller ? ' - ' : '') : ''; + } + private static logText(messageIndentationLevel: number, logLevelSymbol: string, text: string): void { if (text) { // start group for every level @@ -107,14 +133,26 @@ export abstract class Logger { } } - private static getCallerInfo(): string { - const e: Error = new Error(); - const stack: string[] = e.stack ? e.stack.split('\n') : []; + private static getCallerInfo(i: number = 4): string { + const stack: string[] = this.getCallStackArray(); // " at functionName ( ..." => "functionName" - return stack[3].includes('. { + return acc || /MochaHooks|CheReporter/.test(e); + }, false); } }