pulsar/spec/atom-reporter.coffee

229 lines
7.3 KiB
CoffeeScript
Raw Normal View History

2014-02-11 06:40:49 +04:00
path = require 'path'
_ = require 'underscore-plus'
{convertStackTrace} = require 'coffeestack'
2014-02-11 06:40:49 +04:00
{View, $, $$} = require '../src/space-pen-extensions'
sourceMaps = {}
2014-02-19 23:12:58 +04:00
formatStackTrace = (spec, message='', stackTrace) ->
return stackTrace unless stackTrace
jasminePattern = /^\s*at\s+.*\(?.*[/\\]jasmine(-[^/\\]*)?\.js:\d+:\d+\)?\s*$/
firstJasmineLinePattern = /^\s*at [/\\].*[/\\]jasmine(-[^/\\]*)?\.js:\d+:\d+\)?\s*$/
convertedLines = []
for line in stackTrace.split('\n')
convertedLines.push(line) unless jasminePattern.test(line)
break if firstJasmineLinePattern.test(line)
stackTrace = convertStackTrace(convertedLines.join('\n'), sourceMaps)
lines = stackTrace.split('\n')
# Remove first line of stack when it is the same as the error message
errorMatch = lines[0]?.match(/^Error: (.*)/)
lines.shift() if message.trim() is errorMatch?[1]?.trim()
for line, index in lines
2014-02-19 23:12:58 +04:00
# Remove prefix of lines matching: at [object Object].<anonymous> (path:1:2)
prefixMatch = line.match(/at \[object Object\]\.<anonymous> \(([^)]+)\)/)
2014-02-19 23:12:58 +04:00
line = "at #{prefixMatch[1]}" if prefixMatch
# Relativize locations to spec directory
lines[index] = line.replace("at #{spec.specDirectory}#{path.sep}", 'at ')
2014-02-11 05:52:42 +04:00
lines = lines.map (line) -> line.trim()
2014-02-19 23:07:02 +04:00
lines.join('\n').trim()
2013-02-12 06:00:42 +04:00
module.exports =
class AtomReporter extends View
@content: ->
2014-02-11 20:58:30 +04:00
@div class: 'spec-reporter', =>
2013-02-15 00:31:19 +04:00
@div outlet: "suites"
2014-02-11 06:31:56 +04:00
@div outlet: 'coreArea', class: 'symbol-area', =>
2014-02-11 05:09:14 +04:00
@div outlet: 'coreHeader', class: 'symbol-header'
@ul outlet: 'coreSummary', class: 'symbol-summary list-unstyled'
2014-02-11 06:31:56 +04:00
@div outlet: 'bundledArea', class: 'symbol-area', =>
2014-02-11 05:09:14 +04:00
@div outlet: 'bundledHeader', class: 'symbol-header'
@ul outlet: 'bundledSummary', class: 'symbol-summary list-unstyled'
2014-02-11 06:31:56 +04:00
@div outlet: 'userArea', class: 'symbol-area', =>
2014-02-11 05:09:14 +04:00
@div outlet: 'userHeader', class: 'symbol-header'
@ul outlet: 'userSummary', class: 'symbol-summary list-unstyled'
@div outlet: "status", class: 'status alert alert-info', =>
2013-02-12 06:00:42 +04:00
@div outlet: "time", class: 'time'
@div outlet: "specCount", class: 'spec-count'
@div outlet: "message", class: 'message'
@div outlet: "results", class: 'results'
startedAt: null
runningSpecCount: 0
completeSpecCount: 0
passedCount: 0
failedCount: 0
skippedCount: 0
totalSpecCount: 0
@timeoutId: 0
reportRunnerStarting: (runner) ->
2013-02-12 08:23:42 +04:00
@handleEvents()
2014-02-11 08:52:35 +04:00
@startedAt = Date.now()
2013-02-12 06:00:42 +04:00
specs = runner.specs()
@totalSpecCount = specs.length
@addSpecs(specs)
$(document.body).append this
reportRunnerResults: (runner) ->
@updateSpecCounts()
@status.addClass('alert-success').removeClass('alert-info') if @failedCount is 0
2014-02-11 21:23:12 +04:00
if @failedCount is 1
@message.text "#{@failedCount} failure"
2013-02-12 06:00:42 +04:00
else
2014-02-11 21:23:12 +04:00
@message.text "#{@failedCount} failures"
2013-02-12 06:00:42 +04:00
reportSuiteResults: (suite) ->
reportSpecResults: (spec) ->
@completeSpecCount++
2014-02-11 08:52:35 +04:00
spec.endedAt = Date.now()
2013-02-12 06:00:42 +04:00
@specComplete(spec)
@updateStatusView(spec)
reportSpecStarting: (spec) ->
@specStarted(spec)
2013-02-12 08:23:42 +04:00
handleEvents: ->
2013-02-15 00:31:19 +04:00
$(document).on "click", ".spec-toggle", ({currentTarget}) =>
2013-02-12 08:23:42 +04:00
element = $(currentTarget)
2013-02-15 00:31:19 +04:00
specFailures = element.parent().find('.spec-failures')
specFailures.toggle()
2014-02-11 07:01:04 +04:00
element.toggleClass('folded')
2013-02-12 08:23:42 +04:00
false
updateSpecCounts: ->
if @skippedCount
specCount = "#{@completeSpecCount - @skippedCount}/#{@totalSpecCount - @skippedCount} (#{@skippedCount} skipped)"
else
specCount = "#{@completeSpecCount}/#{@totalSpecCount}"
@specCount[0].textContent = specCount
2013-02-12 06:00:42 +04:00
updateStatusView: (spec) ->
if @failedCount > 0
@status.addClass('alert-danger').removeClass('alert-info')
@updateSpecCounts()
2013-02-12 06:00:42 +04:00
rootSuite = spec.suite
rootSuite = rootSuite.parentSuite while rootSuite.parentSuite
@message.text rootSuite.description
2014-02-11 08:52:35 +04:00
time = "#{Math.round((spec.endedAt - @startedAt) / 10)}"
2013-02-13 02:48:16 +04:00
time = "0#{time}" if time.length < 3
@time[0].textContent = "#{time[0...-2]}.#{time[-2..]}s"
2013-02-12 06:00:42 +04:00
addSpecs: (specs) ->
coreSpecs = 0
bundledPackageSpecs = 0
userPackageSpecs = 0
2013-02-12 06:00:42 +04:00
for spec in specs
symbol = $$ -> @li id: "spec-summary-#{spec.id}", class: "spec-summary pending"
switch spec.specType
when 'core'
coreSpecs++
@coreSummary.append symbol
when 'bundled'
bundledPackageSpecs++
@bundledSummary.append symbol
when 'user'
userPackageSpecs++
@userSummary.append symbol
if coreSpecs > 0
2014-02-11 06:31:45 +04:00
@coreHeader.text("Core Specs (#{coreSpecs})")
else
@coreArea.hide()
if bundledPackageSpecs > 0
2014-02-11 06:31:45 +04:00
@bundledHeader.text("Bundled Package Specs (#{bundledPackageSpecs})")
else
@bundledArea.hide()
if userPackageSpecs > 0
2014-02-11 06:40:49 +04:00
if coreSpecs is 0 and bundledPackageSpecs is 0
2014-02-11 07:12:54 +04:00
# Package specs being run, show a more descriptive label
{specDirectory} = specs[0]
packageFolderName = path.basename(path.dirname(specDirectory))
2014-02-11 06:40:49 +04:00
packageName = _.undasherize(_.uncamelcase(packageFolderName))
2014-02-11 07:10:54 +04:00
@userHeader.text("#{packageName} Specs")
2014-02-11 06:40:49 +04:00
else
@userHeader.text("User Package Specs (#{userPackageSpecs})")
else
@userArea.hide()
2013-02-12 06:00:42 +04:00
specStarted: (spec) ->
@runningSpecCount++
specComplete: (spec) ->
specSummaryElement = $("#spec-summary-#{spec.id}")
2013-02-12 06:00:42 +04:00
specSummaryElement.removeClass('pending')
2014-02-11 08:59:38 +04:00
specSummaryElement.setTooltip(title: spec.getFullName(), container: '.spec-reporter')
2013-02-12 06:00:42 +04:00
results = spec.results()
if results.skipped
specSummaryElement.addClass("skipped")
@skippedCount++
else if results.passed()
specSummaryElement.addClass("passed")
@passedCount++
else
specSummaryElement.addClass("failed")
specView = new SpecResultView(spec)
specView.attach()
@failedCount++
class SuiteResultView extends View
@content: ->
@div class: 'suite', =>
@div outlet: 'description', class: 'description'
initialize: (@suite) ->
@attr('id', "suite-view-#{@suite.id}")
2014-02-11 21:02:41 +04:00
@description.text(@suite.description)
2013-02-12 06:00:42 +04:00
attach: ->
(@parentSuiteView() or $('.results')).append this
parentSuiteView: ->
return unless @suite.parentSuite
if not suiteView = $("#suite-view-#{@suite.parentSuite.id}").view()
2013-02-12 06:00:42 +04:00
suiteView = new SuiteResultView(@suite.parentSuite)
suiteView.attach()
suiteView
class SpecResultView extends View
@content: ->
@div class: 'spec', =>
2014-02-11 07:01:04 +04:00
@div class: 'spec-toggle'
2013-02-12 06:00:42 +04:00
@div outlet: 'description', class: 'description'
2013-02-15 00:31:19 +04:00
@div outlet: 'specFailures', class: 'spec-failures'
2013-02-12 06:00:42 +04:00
initialize: (@spec) ->
@addClass("spec-view-#{@spec.id}")
2014-02-11 06:53:06 +04:00
description = @spec.description
description = "it #{description}" if description.indexOf('it ') isnt 0
@description.text(description)
2013-02-12 06:00:42 +04:00
for result in @spec.results().getItems() when not result.passed()
2014-02-19 23:12:58 +04:00
stackTrace = formatStackTrace(@spec, result.message, result.trace.stack)
2013-02-15 00:31:19 +04:00
@specFailures.append $$ ->
2014-02-11 05:09:14 +04:00
@div result.message, class: 'result-message fail'
2014-02-11 05:52:24 +04:00
@pre stackTrace, class: 'stack-trace padded' if stackTrace
2013-02-12 06:00:42 +04:00
attach: ->
@parentSuiteView().append this
parentSuiteView: ->
if not suiteView = $("#suite-view-#{@spec.suite.id}").view()
2013-02-12 06:00:42 +04:00
suiteView = new SuiteResultView(@spec.suite)
suiteView.attach()
suiteView