/*********************************************************************
 * Copyright (c) 2019 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
 **********************************************************************/ import * as mocha from 'mocha' ; import { IDriver } from './IDriver' ; import { inversifyConfig } from '..' ; import { TYPES , CLASSES } from '..' ; import * as fs from 'fs' ; import * as rm from 'rimraf' ; import { TestConstants } from '../TestConstants' ; import { logging } from 'selenium-webdriver' ; import { DriverHelper } from '../utils/DriverHelper' ; import { ScreenCatcher } from '../utils/ScreenCatcher' ; import { ITestWorkspaceUtil } from '../utils/workspace/ITestWorkspaceUtil' ; import { PreferencesHandler , AskForConfirmationType , TerminalRendererType } from '../utils/PreferencesHandler' ; import { CheApiRequestHandler } from '../utils/requestHandlers/CheApiRequestHandler' ; import { TimeoutConstants } from '../TimeoutConstants' ; import { Logger } from '../utils/Logger' ; import { Sanitizer } from '../utils/Sanitizer' ; const e2eContainer = inversifyConfig . e2eContainer ; const driver = e2eContainer . get ( TYPES . Driver ) ; const driverHelper = e2eContainer . get ( CLASSES . DriverHelper ) ; const screenCatcher = e2eContainer . get ( CLASSES . ScreenCatcher ) ; const sanitizer = e2eContainer . get ( CLASSES . Sanitizer ) ; let methodIndex = 0 ; let deleteScreencast = true ; let testWorkspaceUtil = e2eContainer . get ( TYPES . WorkspaceUtil ) ; let preferencesHandler = e2eContainer . get ( CLASSES . PreferencesHandler ) ; class CheReporter extends mocha . reporters . Spec { private static latestWorkspace : string ; public static registerRunningWorkspace ( workspaceName ) { Logger . debug ( `CheReporter.registerRunningWorkspace {${ workspaceName }}` ) ; CheReporter . latestWorkspace = workspaceName ; } constructor ( runner , options ) { super ( runner , options ) ; runner . on ( 'start' , async ( test ) => { let launchInformation = `################## Launch Information ##################

      TS_SELENIUM_BASE_URL: ${ TestConstants . TS_SELENIUM_BASE_URL }
      TS_SELENIUM_HEADLESS: ${ TestConstants . TS_SELENIUM_HEADLESS }

      TS_SELENIUM_USERNAME: ${ TestConstants . TS_SELENIUM_USERNAME }
      TS_SELENIUM_PASSWORD: ${ TestConstants . TS_SELENIUM_PASSWORD }

      TS_SELENIUM_HAPPY_PATH_WORKSPACE_NAME: ${ TestConstants . TS_SELENIUM_HAPPY_PATH_WORKSPACE_NAME }
      TS_SELENIUM_DELAY_BETWEEN_SCREENSHOTS: ${ TestConstants . TS_SELENIUM_DELAY_BETWEEN_SCREENSHOTS }
      TS_SELENIUM_REPORT_FOLDER: ${ TestConstants . TS_SELENIUM_REPORT_FOLDER }
      TS_SELENIUM_EXECUTION_SCREENCAST: ${ TestConstants . TS_SELENIUM_EXECUTION_SCREENCAST }
      DELETE_SCREENCAST_IF_TEST_PASS: ${ TestConstants . DELETE_SCREENCAST_IF_TEST_PASS }
      TS_SELENIUM_REMOTE_DRIVER_URL: ${ TestConstants . TS_SELENIUM_REMOTE_DRIVER_URL }
      DELETE_WORKSPACE_ON_FAILED_TEST: ${ TestConstants . DELETE_WORKSPACE_ON_FAILED_TEST }
      TS_SELENIUM_LOG_LEVEL: ${ TestConstants . TS_SELENIUM_LOG_LEVEL }
      TS_SELENIUM_LAUNCH_FULLSCREEN: ${ TestConstants . TS_SELENIUM_LAUNCH_FULLSCREEN }
` ; if ( TestConstants . TS_SELENIUM_PRINT_TIMEOUT_VARIABLES ) { launchInformation += `\n      TS_SELENIUM_PRINT_TIMEOUT_VARIABLES is set to true: \n` ; Object . entries ( TimeoutConstants ) . forEach ( ( [ key , value ] ) => launchInformation += `\n         ${ key }: ${ value }` ) ; } else { launchInformation += `\n      to output timeout variables, set TS_SELENIUM_PRINT_TIMEOUT_VARIABLES to true` ; } launchInformation += `\n ######################################################## \n` ; console . log ( launchInformation ) ; rm . sync ( TestConstants . TS_SELENIUM_REPORT_FOLDER ) ; if ( TestConstants . TS_SELENIUM_REQUEST_INTERCEPTOR ) { CheApiRequestHandler . enableRequestInteceptor ( ) ; } if ( TestConstants . TS_SELENIUM_RESPONSE_INTERCEPTOR ) { CheApiRequestHandler . enableResponseInterceptor ( ) ; } await preferencesHandler . setConfirmExit ( AskForConfirmationType . never ) ; await preferencesHandler . setTerminalType ( TerminalRendererType . dom ) ; } ) ; runner . on ( 'test' , async function ( test ) { if ( ! TestConstants . TS_SELENIUM_EXECUTION_SCREENCAST ) { return ; } methodIndex = methodIndex + 1 ; const currentMethodIndex = methodIndex ; let iterationIndex = 1 ; while ( ! ( test . state === 'passed' || test . state === 'failed' ) ) { await screenCatcher . catchMethodScreen ( test . title , currentMethodIndex , iterationIndex ) ; iterationIndex = iterationIndex + 1 ; await driverHelper . wait ( TestConstants . TS_SELENIUM_DELAY_BETWEEN_SCREENSHOTS ) ; } } ) ; runner . on ( 'pass' , async ( test ) => { if ( TestConstants . TS_LOAD_TESTS ) { const loadTestReportFolder = TestConstants . TS_SELENIUM_LOAD_TEST_REPORT_FOLDER ; const loadTestFilePath = loadTestReportFolder + '/load-test-results.txt' ; const report = test . title + ': ' + test . duration + '\r' ; if ( ! fs . existsSync ( loadTestReportFolder ) ) { fs . mkdirSync ( loadTestReportFolder ) ; } fs . appendFileSync ( loadTestFilePath , report ) ; } } ) ; runner . on ( 'end' , async function ( test ) { await driver . get ( ) . sleep ( 5000 ) ; await driver . get ( ) . quit ( ) ; if ( deleteScreencast && TestConstants . DELETE_SCREENCAST_IF_TEST_PASS ) { rm . sync ( TestConstants . TS_SELENIUM_REPORT_FOLDER ) ; } } ) ; runner . on ( 'fail' , async function ( test ) { Logger . error ( `CheReporter runner.on.fail: ${ test . fullTitle ( ) } failed after ${ test . duration }ms` ) ; deleteScreencast = false ; Logger . trace ( `FullTitle:${ test . fullTitle ( ) }` ) ; const testFullTitle = sanitizer . sanitize ( test . fullTitle ( ) ) ; Logger . trace ( `FullTitleSanitized:${ testFullTitle }` ) ; Logger . trace ( `TestTitle:${ test . title }` ) ; const testTitle = sanitizer . sanitize ( test . title ) ; Logger . trace ( `TestTitleSanitized:${ testTitle }` ) ; const testReportDirPath = `${ TestConstants . TS_SELENIUM_REPORT_FOLDER }/${ testFullTitle }` ; const screenshotFileName = `${ testReportDirPath }/screenshot-${ testTitle }.png` ; const pageSourceFileName = `${ testReportDirPath }/pagesource-${ testTitle }.html` ; const browserLogsFileName = `${ testReportDirPath }/browserlogs-${ testTitle }.txt` ; const reportDirExists = fs . existsSync ( TestConstants . TS_SELENIUM_REPORT_FOLDER ) ; if ( ! reportDirExists ) { fs . mkdirSync ( TestConstants . TS_SELENIUM_REPORT_FOLDER ) ; } const testReportDirExists = fs . existsSync ( testReportDirPath ) ; if ( ! testReportDirExists ) { fs . mkdirSync ( testReportDirPath ) ; } const screenshot = await driver . get ( ) . takeScreenshot ( ) ; const screenshotStream = fs . createWriteStream ( screenshotFileName ) ; screenshotStream . write ( Buffer . from ( screenshot , 'base64' ) ) ; screenshotStream . end ( ) ; const pageSource = await driver . get ( ) . getPageSource ( ) ; const pageSourceStream = fs . createWriteStream ( pageSourceFileName ) ; pageSourceStream . write ( Buffer . from ( pageSource ) ) ; pageSourceStream . end ( ) ; const browserLogsEntries = await driverHelper . getDriver ( ) . manage ( ) . logs ( ) . get ( 'browser' ) ; let browserLogs = '' ; browserLogsEntries . forEach ( log => { browserLogs += `\"${ log . level }\" \"${ log . type }\" \"${ log . message }\"\n` ; } ) ; const browserLogsStream = fs . createWriteStream ( browserLogsFileName ) ; browserLogsStream . write ( Buffer . from ( browserLogs ) ) ; browserLogsStream . end ( ) ; if ( TestConstants . DELETE_WORKSPACE_ON_FAILED_TEST ) { Logger . warn ( 'Property DELETE_WORKSPACE_ON_FAILED_TEST se to true - trying to stop and delete running workspace.' ) ; await testWorkspaceUtil . cleanUpRunningWorkspace ( CheReporter . latestWorkspace ) ; } } ) ; } } export = CheReporter ;