siesta-lite
Version:
Stress-free JavaScript unit testing and functional testing tool, works in NodeJS and browsers
382 lines (269 loc) • 12.7 kB
JavaScript
/*
Siesta 5.6.1
Copyright(c) 2009-2022 Bryntum AB
https://bryntum.com/contact
https://bryntum.com/products/siesta/license
*/
Role('Siesta.Launcher.Dispatcher.Reporter', {
requires : [
'forEachAssertion'
],
does : [
Siesta.Util.Role.CanFormatStrings,
Siesta.Util.Role.CanParseOs,
Siesta.Util.Role.CanParseBrowser,
Siesta.Launcher.Role.CanPrintWithLauncher,
Siesta.Launcher.Dispatcher.Reporter.JSON,
Siesta.Launcher.Dispatcher.Reporter.JUnit
],
has : {
stringificationCache : Joose.I.Object
},
methods : {
onTestSuiteStart : function (userAgent, platform) {
this.printTestSuiteHeader(userAgent, platform)
},
onTestSuiteEnd : function () {
this.printTestSuiteSummaryMessage()
},
onPageInactivityTimeout : function (elId, inactivityTimeout) {
var message = "Inactivity timeout " + inactivityTimeout + 'ms has been exceeded'
if (elId) {
var el = this.getElementById(elId)
message += ' during test: ' + el.descId + ', restarting'
}
this.warn(message)
},
onCanNotRunElement : function (el) {
this.warn("Can not reach the end of the test: " + el.descId + ", test is marked as failed")
this.printTestResult(el)
},
printTestSuiteHeader : function (userAgent, platform) {
var browserInfo = this.parseBrowser(userAgent)
var agentString = typeof process != 'undefined' ? ", agent: " : ", browser: "
this.print(
"Launching test suite, OS: " + this.parseOS(platform) + agentString + browserInfo.name + " " + browserInfo.version
)
},
printTestSuiteSummaryMessage : function () {
this.print(this.getAutomatedSummaryMessage())
},
stringifyAssertion : function (info) {
var type = info.type
if (!type) throw new Error("Can't strigify assertion : " + JSON.stringify(info))
var instance = this.stringificationCache[ type ]
if (!instance) {
instance = this.stringificationCache[ type ] = new (Joose.S.strToClass(type))({})
}
// other properties will always present in the assertion info so no need to cleanup them
Joose.A.each([ 'isTodo', 'isWaitFor', 'isException', 'sourceLine', 'name', 'annotation', 'exceptionType' ], function (name) {
instance[ name ] = null
})
Joose.O.extend(instance, info)
return instance.toString()
},
getFormattedAssertionText : function (text, assertion, parentTests, printState, noColor) {
var launcher = this.launcher
// 4.0.x compatibility, early exit
if (this.options[ 'flat-output' ]) return launcher.prepareText(text, false, 0, noColor)
var output = ''
var printedParents = printState.printedParents || []
var printing = false
for (var indent = 1; indent < parentTests.length; indent++) {
if (printing || parentTests[ indent ] != printedParents[ indent ]) {
printing = true
output += launcher.prepareText(
this.styled(parentTests[ indent ].name, 'bold'),
true,
indent - 1,
noColor
)
}
}
printState.printedParents = parentTests
output += launcher.prepareText(text, false, parentTests.length - 1, noColor)
return output
},
// printAssertionText : function (text, assertion, parentTests, printState) {
// var printMethod = assertion.type == 'Siesta.Result.Diagnostic' && assertion.isWarning ? 'warn' : 'print'
//
// if (this.options[ 'flat-output' ])
// // 4.0.x compatibility
// this[ printMethod ](text)
// else {
// var printedParents = printState.printedParents || []
//
// var printing = false
//
// for (var indent = 1; indent < parentTests.length; indent++) {
// if (printing || parentTests[ indent ] != printedParents[ indent ]) {
// printing = true
//
// this.print(this.styled(parentTests[ indent ].name, 'bold'), indent - 1)
// }
// }
//
// printState.printedParents = parentTests
//
// this[ printMethod ](text, parentTests.length - 1)
// }
// },
getAssertionText : function (assertion) {
var text = this.stringifyAssertion(assertion)
if (assertion.type == 'Siesta.Result.Assertion') {
if (assertion.isException && !assertion.isTodo) {
text = this.style().bold(this.style().red(text))
} else if (assertion.isTodo) {
text = this.styled(text, assertion.passed ? 'magenta' : 'yellow')
} else {
text = this.styled(text, assertion.passed ? 'green' : 'red')
}
}
if (assertion.type == 'Siesta.Result.Diagnostic') {
if (assertion.isWarning)
text = this.styled('[WARN] ', 'red') + text
else
text = this.styled(text, 'bold')
}
return text
},
needToShowAssertion : function (assertion) {
if (this.options.verbose) return true
var needToShow = false
if (assertion.type == 'Siesta.Result.Assertion') {
if (assertion.isException && !assertion.isTodo) {
needToShow = true
} else if (assertion.isTodo) {
if (assertion.passed && !assertion.isWaitFor) needToShow = true
} else {
if (!assertion.passed) needToShow = true
}
}
if (assertion.type == 'Siesta.Result.Diagnostic') {
if (assertion.isWarning)
needToShow = true
}
return needToShow
},
printAssertionInfo : function (assertion, parentTests, printState) {
printState = printState || {}
if (this.needToShowAssertion(assertion)) {
var text = this.getAssertionText(assertion)
this.print(this.getFormattedAssertionText(text, assertion, parentTests, printState, false))
}
},
printTestResult: function (el, isAfterReRun, streamAssertions) {
var testResult = el.result
// in case of "streamAssertions" header has been already printed
if (!streamAssertions) this.printTestHeader(testResult)
// in case of "streamAssertions" body has been already printed unless "ERROR" is present
if (!streamAssertions || testResult.ERROR) this.printTestBody(testResult)
// footer should be printed always
this.printTestFooter(testResult, isAfterReRun)
el.resultPrinted = true
},
printTestHeader : function (testResult) {
},
printTestBody : function (testResult) {
if (!testResult.ERROR) {
this.printSubTestResult(testResult)
}
},
printSubTestResult : function (testResult, parentTests, printState) {
parentTests = parentTests || []
printState = printState || {}
parentTests.push(testResult)
for (var i = 0; i < testResult.assertions.length; i++) {
var assertion = testResult.assertions[ i ]
if (assertion.type == 'Siesta.Result.Assertion' || assertion.type == 'Siesta.Result.Diagnostic')
this.printAssertionInfo(assertion, parentTests, printState)
if (assertion.type == 'Siesta.Result.SubTest') {
this.printSubTestResult(assertion, parentTests.slice(), printState)
}
}
},
printStreamedUpdate : function (update, printState) {
if (update.type == 'Siesta.Result.Assertion' || update.type == 'Siesta.Result.Diagnostic') {
var parentTests = []
var parent = this.getParentOfStreamedUpdate(update)
while (parent) {
parentTests.unshift(parent)
parent = this.getParentOfStreamedUpdate(parent)
}
this.printAssertionInfo(update, parentTests, printState)
}
},
printTestFooter : function (testResult, isAfterReRun) {
var isPassed = testResult.passed
this.print(
'['
+ (
isPassed
?
this.styled(Siesta.Resource('Siesta.Role.ConsoleReporter', 'passText'), isAfterReRun ? 'yellow' : 'green')
:
this.styled(Siesta.Resource('Siesta.Role.ConsoleReporter', 'failText'), 'red')
)
+ '] ' + testResult.url + (isPassed ? '' : '\n')
)
},
getAutomatedSummaryMessage : function () {
var testCases = this.getAllResults()
var testsTotal = testCases.length
var testsFailed = 0
var assertionsTotal = 0
var assertionsFailed = 0
var todoPassed = 0
var todoFailed = 0
var timeTotal = (this.endDate || new Date) - this.startDate
var durationStr = timeTotal + 'ms'
if (timeTotal >= 1000) {
timeTotal = timeTotal / 1000
durationStr = timeTotal + 's'
if (timeTotal >= 60) {
durationStr = Math.floor(timeTotal / 60) + 'm ' + Math.floor(timeTotal % 60) + 's'
timeTotal = timeTotal / 60
if (timeTotal >= 60) {
durationStr = Math.floor(timeTotal / 60) + 'h ' + Math.floor(timeTotal % 60) + 'm'
}
}
}
for (i = 0; i < testCases.length; i++) {
var testInfo = testCases[ i ]
if (testInfo.ERROR) {
testsFailed++
} else {
if (!testInfo.passed) testsFailed++
this.forEachAssertion(testInfo, function (assertion) {
if (assertion.isTodo) {
assertion.passed ? todoPassed++ : todoFailed++
} else {
assertionsTotal++
if (!assertion.passed) assertionsFailed++
}
})
}
}
return this.formatString([
'{assertionsPassed} passed, {assertionsFailed} failed assertions took {!timeTotal} to complete'
].join('\n'), {
testsFailed : testsFailed,
testsPassed : testsTotal - testsFailed,
testsTotal : testsTotal,
timeTotal : durationStr,
assertionsTotal : assertionsTotal,
assertionsPassed : assertionsTotal - assertionsFailed,
assertionsFailed : assertionsFailed,
todoPassed : todoPassed,
todoFailed : todoFailed
})
},
generateReport : function (options) {
// a string?
if (Object(options) !== options) options = { format : options || 'json' }
var methodName = 'generate' + Joose.S.uppercaseFirst(options.format) + 'Report'
if (!this[ methodName ]) throw "Can't generate report - missing the `" + methodName + "` method"
return this[ methodName ](options)
}
}
})