UNPKG

siesta-lite

Version:

Stress-free JavaScript unit testing and functional testing tool, works in NodeJS and browsers

523 lines (379 loc) 17.4 kB
/* Siesta 5.6.1 Copyright(c) 2009-2022 Bryntum AB https://bryntum.com/contact https://bryntum.com/products/siesta/license */ Role('Siesta.Project.Browser.Automation', { does : [ Siesta.Util.Role.CanStyleOutput, Siesta.Util.Role.CanFormatStrings ], has : { outputLog : Joose.I.Array, currentTestTimeout : null, lastActivity : null, exitStatus : null, activeTestAutomationId : null, testResults : Joose.I.Array, streamAssertions : false, eventLog : Joose.I.Array, enableCodeCoverage : false, manuallyProcessCoverageResults : true, codeCoverageResults : Joose.I.Array }, override : { setup : function () { if (this.isAutomated) { this.autoLaunchTests = false this.forceDOMVisible = true if (this.speedRun !== false) { this.speedRun = true } this.forcedRunCore = 'sequential' this.transparentEx = false this.keepNLastResults = 0 this.waitForTimeout = this.waitForTimeout * 3 this.defaultTimeout = this.defaultTimeout * 3 this.isReadyTimeout = this.isReadyTimeout * 3 this.lastActivity = new Date() var me = this if (typeof window != 'undefined') window.onerror = function (message, url, lineNumber, col, error) { // ignore exit exception if (/__SIESTA_TEST_EXIT_EXCEPTION__/.test(message)) return me.warn("[ERROR] message : " + message) me.warn("[ERROR] url : " + url) me.warn("[ERROR] line : " + lineNumber) if (col) me.warn("[ERROR] col : " + col) if (error && error.stack) me.warn("[ERROR] stack : " + error.stack) } this.on('maxtimeoutchanged', function (event, timeout) { me.onTestMaxTimeoutChanged(event.source, timeout) }) this.on('focuslost', function (event) { me.onTestFocusLost(event.source) }) } this.SUPERARG(arguments) } }, after : { markMissingFile : function (desc) { this.warn(Siesta.Resource('Siesta.Role.ConsoleReporter', 'missingFileText').replace("{URL}", desc.url)) if (this.isAutomated) { this.lastActivity = new Date() var result = { automationElementId : desc.automationElementId, url : desc.url, ERROR : "Can't open test file: " + desc.url } if (this.streamAssertions) this.eventLog.push({ isResult : true, data : result }) else this.testResults.push(result) } }, onTestSuiteStart : function (descriptors, contenManager, launchState) { // if (this.isAutomated && this.initialContentManagerState) contenManager.setState(this.initialContentManagerState) }, onTestSuiteEnd : function (descriptors, contenManager, launchState) { if (this.isAutomated && !launchState.needToStop) this.exit() }, onTestStart : function (test) { if (this.isAutomated && this.isTestActionActual(test)) { this.currentTestTimeout = test.getMaximalTimeout() * 2 this.activeTestAutomationId = test.automationElementId this.lastActivity = new Date() if (this.streamAssertions) if (!test.parent) this.eventLog.push({ isUpdate : true, data : test.getResults().toJSON() }) } }, onTestEnd : function (test) { if (this.isAutomated && this.isTestActionActual(test)) { this.lastActivity = new Date() this.activeTestAutomationId = null if (this.streamAssertions) this.eventLog.push({ isResult : true, data : test.getResults().toJSON() }) else this.testResults.push(test.getResults().toJSON()) if (this.enableCodeCoverage && this.manuallyProcessCoverageResults) { var result = test.global.__coverage__ result && this.codeCoverageResults.push(result) } } }, onTestUpdate : function (test, result, parentResult) { if (this.isAutomated && this.isTestActionActual(test)) { this.lastActivity = new Date() if (this.streamAssertions) if (!(result.isWaitFor && !result.completed) && !(result instanceof Siesta.Result.Summary)) { this.eventLog.push({ isUpdate : true, data : result.toJSON() }) // in "breakOnFail" case the failed assertion will switch "launchState" to "needToStop" // and "isTestActionActual" will return false for any following updates/results, // so, adding total test result manually if (this.breakOnFail && ((result instanceof Siesta.Result.Assertion) && !result.isPassed())) this.eventLog.push({ isResult : true, data : test.getResults().toJSON() }) } } } }, methods : { isTestActionActual : function (test) { if (test.launchId != this.currentLaunchId) return false var launchState = this.launches[ this.currentLaunchId ] return launchState ? !launchState.needToStop : false }, onTestFocusLost : function (test) { if (this.isAutomated) { test.warn(Siesta.Resource('Siesta.Test.Browser').get('focusLostWarningLauncher', { url : test.url })) this.stopCurrentLaunch() this.exit('focus_lost') } }, onTestMaxTimeoutChanged : function (test, timeout) { if (this.isAutomated) this.currentTestTimeout = timeout * 2 }, filterDescriptors : function (includeTests, excludeTests, descriptors) { includeTests = includeTests ? new RegExp(includeTests) : null excludeTests = excludeTests ? new RegExp(excludeTests) : null var filtered = [] if (includeTests || excludeTests) { Joose.A.each(this.flattenDescriptors(descriptors || this.descriptors), function (desc) { if (includeTests && !includeTests.test(desc.url)) return if (excludeTests && excludeTests.test(desc.url)) return filtered.push(desc) }) } else filtered = this.flattenDescriptors(descriptors || this.descriptors) return filtered }, getLastActivity : function () { return this.lastActivity - 0 }, log : function (text) { if (this.isAutomated) { if (this.streamAssertions) this.eventLog.push({ isLog : true, data : text }) else this.outputLog.push(text) } }, exit : function (status) { this.exitStatus = status || 'all_processed' }, getAutomationState : function () { var launchState = this.launches[ this.currentLaunchId ] var state = { activeTestAutomationId : this.activeTestAutomationId, activityTimeout : this.currentTestTimeout, lastActivity : this.lastActivity - 0, testResults : this.flushTestResults(), log : this.flushLog(), exitStatus : this.exitStatus, commands : this.flushAutomationCommands && this.flushAutomationCommands(), // launchState is deleted upon launch completion notLaunched : launchState ? launchState.notLaunchedByAutomationId : {} } if (this.streamAssertions) { state.eventLog = this.flushEventLog() } if (this.enableCodeCoverage) { state.coverageResult = this.flushCoverageResults() } return state }, flushLog : function () { var outputLog = this.outputLog if (outputLog.length) { this.outputLog = [] return outputLog } }, flushCoverageResults : function () { var results = this.codeCoverageResults if (results.length) { this.codeCoverageResults = [] return results } }, flushTestResults : function () { var testResults = this.testResults if (testResults.length) { this.testResults = [] return testResults } }, flushEventLog : function () { var eventLog = this.eventLog if (eventLog.length) { this.eventLog = [] return eventLog } }, cascadeStructureLeafOnly : function (func, list) { var me = this Joose.A.each(list, function (desc) { if (desc.group) { me.cascadeStructureLeafOnly(func, desc.items) } else func(desc) }) }, getDescriptorStructure : function (desc, visibleById) { var me = this if (visibleById && desc.id != '__ROOT__' && !visibleById[ desc.id ]) return null if (desc.group) { var items = [] Joose.A.each(desc.items, function (desc) { var res = me.getDescriptorStructure(desc, visibleById) if (res) items.push(res) }) return { id : desc.id, group : desc.group || desc.title || desc.name, items : items } } else { return desc.id } }, getConfigInfo : function (includeTest, excludeTests, filterValue, projectConfig) { var me = this var visibleById // need to configure project first, because some command line options (like `simulation`) overrides // default project config and affect the result of this method if (projectConfig) this.configure(projectConfig) if (filterValue) { var filterer = new Siesta.Util.TreeStoreFilterer({ idProp : 'id', childNodesProp : 'items', parentNodeProp : 'parent', isLeaf : function (node) { return !node.group } }) var res = filterer.parseFilterValue(filterValue) var testFilterRegexps = res.testFilterRegexps var groupFilterRegexps = res.groupFilterRegexps var getTitle = function (node) { // do not consider a test suite title as a "root group", otherwise, for the suite title "Test suite" // the --filter="ui>" will match all top-level tests if (node == me) return '' else return node.group || node.title || node.name } visibleById = filterer.collectNodes({ id : '__ROOT__', group : '__ROOT__', items : this.descriptors }, { filter : function (node) { return filterer.checkCommonFilter(node, getTitle, testFilterRegexps, groupFilterRegexps) } }) } var structure = this.getDescriptorStructure( { id : '__ROOT__', group : '__ROOT__', items : this.descriptors }, visibleById ) var list if (filterValue) { list = [] this.cascadeStructureLeafOnly(function (id) { list.push(me.getDescById(id)) }, structure.items) } else list = this.descriptors var filteredFlattenList = this.filterDescriptors(includeTest, excludeTests, list) return { // system info VERSION : Siesta.meta.VERSION, title : this.title, structure : structure, descriptors : this.sortDescriptors(filteredFlattenList, 'sequential', true), // environment hostName : typeof location != 'undefined' ? location.host : require('os').hostname(), userAgent : typeof navigator != 'undefined' ? navigator.userAgent : 'NodeJS/' + process.version, platform : typeof navigator != 'undefined' ? navigator.platform : process.platform, hasNativeSimulation : this.hasDescriptorWithNativeEventsSimulation(filteredFlattenList), // options breakOnFail : this.breakOnFail, screenshotCompareConfig : this.screenshotCompareConfig } }, // chunk task - [ { descId : descId, automationElementId : elId }, ... ] launchAutomatedTests : function (task, options) { if (!this.setupDone) { this.on('setupdone', function () { this.launchAutomatedTests(task, options) }) return } if (options.projectConfig) this.configure(options.projectConfig) this.enableCodeCoverage = Boolean(options.enableCodeCoverage) this.streamAssertions = Boolean(options.streamAssertions) this.showCursor = Boolean(options.showCursor) if (options.pause != null) this.pauseBetweenTests = options.pause if (options.restartOnBlur != null) this.restartOnBlur = options.restartOnBlur var me = this var descriptors = Joose.A.map(task, function (el) { var desc = me.getScriptDescriptor(el.descId) desc.automationElementId = el.automationElementId return desc }) this.launch(descriptors) }, warn : function (text) { this.log({ text : text, isWarning : true }) if (typeof window != 'undefined') window.console && console.warn(text) if (this.viewport) { Ext.toast({ cls : 'tr-warn-toast', title : 'Warning', html : text.replace(/\n/g, '<br>'), align : 't', autoCloseDelay : 3000 }) } }, getExitCode : function () { return this.allPassed() ? 0 : 1 } } }) //eof Siesta.Project.Browser.Automation if (!Siesta.Project.NodeJS) Siesta.Project.Browser.meta.extend({ does : [ Siesta.Project.Browser.Automation, Siesta.Project.Browser.Automation.Selenium, Siesta.Project.Browser.Automation.Puppeteer ] }) else if (Siesta.Project.NodeJS) Siesta.Project.NodeJS.meta.extend({ does : [ Siesta.Project.Browser.Automation, Siesta.Project.Browser.Automation.NodeJS ] })