base.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. 'use strict'
  2. const util = require('util')
  3. const constants = require('../constants')
  4. const helper = require('../helper')
  5. const BaseReporter = function (formatError, reportSlow, useColors, browserConsoleLogOptions, adapter) {
  6. this.adapters = [adapter || process.stdout.write.bind(process.stdout)]
  7. this.USE_COLORS = false
  8. this.EXCLUSIVELY_USE_COLORS = undefined
  9. this.LOG_SINGLE_BROWSER = '%s: %s\n'
  10. this.LOG_MULTI_BROWSER = '%s %s: %s\n'
  11. this.SPEC_FAILURE = '%s %s FAILED' + '\n'
  12. this.SPEC_SLOW = '%s SLOW %s: %s\n'
  13. this.ERROR = '%s ERROR\n'
  14. this.FINISHED_ERROR = ' ERROR'
  15. this.FINISHED_SUCCESS = ' SUCCESS'
  16. this.FINISHED_DISCONNECTED = ' DISCONNECTED'
  17. this.X_FAILED = ' (%d FAILED)'
  18. this.TOTAL_SUCCESS = 'TOTAL: %d SUCCESS\n'
  19. this.TOTAL_FAILED = 'TOTAL: %d FAILED, %d SUCCESS\n'
  20. this.onRunStart = () => {
  21. this._browsers = []
  22. }
  23. this.onBrowserStart = (browser) => {
  24. this._browsers.push(browser)
  25. }
  26. this.renderBrowser = (browser) => {
  27. const results = browser.lastResult
  28. const totalExecuted = results.success + results.failed
  29. let msg = `${browser}: Executed ${totalExecuted} of ${results.total}`
  30. if (results.failed) {
  31. msg += util.format(this.X_FAILED, results.failed)
  32. }
  33. if (results.skipped) {
  34. msg += ` (skipped ${results.skipped})`
  35. }
  36. if (browser.isConnected) {
  37. if (results.disconnected) {
  38. msg += this.FINISHED_DISCONNECTED
  39. } else if (results.error) {
  40. msg += this.FINISHED_ERROR
  41. } else if (!results.failed) {
  42. msg += this.FINISHED_SUCCESS
  43. }
  44. msg += ` (${helper.formatTimeInterval(results.totalTime)} / ${helper.formatTimeInterval(results.netTime)})`
  45. }
  46. return msg
  47. }
  48. this.write = function () {
  49. const msg = util.format.apply(null, Array.prototype.slice.call(arguments))
  50. this.adapters.forEach((adapter) => {
  51. if (!helper.isDefined(adapter.colors)) {
  52. adapter.colors = useColors
  53. }
  54. if (!helper.isDefined(this.EXCLUSIVELY_USE_COLORS) || adapter.colors === this.EXCLUSIVELY_USE_COLORS) {
  55. return adapter(msg)
  56. }
  57. })
  58. }
  59. this.writeCommonMsg = function () {
  60. this.write.apply(this, arguments)
  61. }
  62. this.onBrowserError = (browser, error) => {
  63. this.writeCommonMsg(util.format(this.ERROR, browser) + formatError(error, ' '))
  64. }
  65. this.onBrowserLog = (browser, log, type) => {
  66. if (!browserConsoleLogOptions || !browserConsoleLogOptions.terminal) return
  67. type = type.toUpperCase()
  68. if (browserConsoleLogOptions.level) {
  69. const logPriority = constants.LOG_PRIORITIES.indexOf(browserConsoleLogOptions.level.toUpperCase())
  70. if (constants.LOG_PRIORITIES.indexOf(type) > logPriority) return
  71. }
  72. if (!helper.isString(log)) {
  73. // TODO(vojta): change util to new syntax (config object)
  74. log = util.inspect(log, false, undefined, this.USE_COLORS)
  75. }
  76. if (this._browsers && this._browsers.length === 1) {
  77. this.writeCommonMsg(util.format(this.LOG_SINGLE_BROWSER, type, log))
  78. } else {
  79. this.writeCommonMsg(util.format(this.LOG_MULTI_BROWSER, browser, type, log))
  80. }
  81. }
  82. this.onSpecComplete = (browser, result) => {
  83. if (result.skipped) {
  84. this.specSkipped(browser, result)
  85. } else if (result.success) {
  86. this.specSuccess(browser, result)
  87. } else {
  88. this.specFailure(browser, result)
  89. }
  90. if (reportSlow && result.time > reportSlow) {
  91. const specName = result.suite.join(' ') + ' ' + result.description
  92. const time = helper.formatTimeInterval(result.time)
  93. this.writeCommonMsg(util.format(this.SPEC_SLOW, browser, time, specName))
  94. }
  95. }
  96. this.specSuccess = () => {
  97. }
  98. this.specSkipped = () => {
  99. }
  100. this.specFailure = (browser, result) => {
  101. const specName = result.suite.join(' ') + ' ' + result.description
  102. let msg = util.format(this.SPEC_FAILURE, browser, specName)
  103. result.log.forEach((log) => {
  104. msg += formatError(log, '\t')
  105. })
  106. this.writeCommonMsg(msg)
  107. }
  108. this.onRunComplete = (browsers, results) => {
  109. if (browsers.length >= 1 && !results.error && !results.disconnected) {
  110. if (!results.failed) {
  111. this.write(this.TOTAL_SUCCESS, results.success)
  112. } else {
  113. this.write(this.TOTAL_FAILED, results.failed, results.success)
  114. }
  115. }
  116. }
  117. }
  118. BaseReporter.decoratorFactory = function (formatError, reportSlow, useColors, browserConsoleLogOptions) {
  119. return function (self) {
  120. BaseReporter.call(self, formatError, reportSlow, useColors, browserConsoleLogOptions)
  121. }
  122. }
  123. BaseReporter.decoratorFactory.$inject = [
  124. 'formatError',
  125. 'config.reportSlowerThan',
  126. 'config.colors',
  127. 'config.browserConsoleLogOptions'
  128. ]
  129. // PUBLISH
  130. module.exports = BaseReporter