Skip to content

Commit

Permalink
Add simple BrowserFormatter for nicer html results
Browse files Browse the repository at this point in the history
  • Loading branch information
adambeynon committed Oct 18, 2013
1 parent 78dffb9 commit acf1ac5
Show file tree
Hide file tree
Showing 4 changed files with 225 additions and 8 deletions.
3 changes: 2 additions & 1 deletion app/app.rb
Expand Up @@ -40,4 +40,5 @@
end
end

OpalRSpec::Runner.new.run
OpalRSpec::Runner.autorun

13 changes: 6 additions & 7 deletions opal/opal-rspec.rb
Expand Up @@ -3,22 +3,21 @@
require 'thread'

# production
# require 'opal-rspec/rspec'
require 'opal-rspec/rspec'
# development
require 'rspec-builder'
# require 'rspec-builder'

require 'opal-rspec/fixes'
require 'opal-rspec/text_formatter'
require 'opal-rspec/browser_formatter'
require 'opal-rspec/runner'

RSpec.configure do |config|

RSpec.configure do |config|
# For now, always use our custom formatter for results
config.formatter = OpalRSpec::TextFormatter
config.formatter = OpalRSpec::Runner.default_formatter

# Always support expect() and .should syntax (we should not do this really..)
config.expect_with :rspec do |c|
c.syntax = [:should, :expect]
end
config.expect_with(:rspec) { |c| c.syntax = [:should, :expect] }
end

190 changes: 190 additions & 0 deletions opal/opal-rspec/browser_formatter.rb
@@ -0,0 +1,190 @@
require 'opal-rspec/text_formatter'

module OpalRSpec
class BrowserFormatter < TextFormatter

def start(example_count)
super

@summary_element = Element.new(:p, class_name: 'summary', text: 'Runner...')
@groups_element = Element.new(:ul, class_name: 'example_groups')

target = Element.new(`document.body`)
target << @summary_element
target << @groups_element

styles = Element.new(:style, type: 'text/css', css_text: CSS)
styles.append_to_head
end

def example_group_started(example_group)
super

@example_group_failed = false
@group_element = Element.new(:li)

description = Element.new(:span, class_name: 'group_description', text: example_group.description)
@group_element << description

@example_list = Element.new(:ul, class_name: 'examples')
@group_element << @example_list

@groups_element << @group_element
end

def example_group_finished(example_group)
super

if @example_group_failed
@group_element.class_name = 'group failed'
else
@group_element.class_name = 'group passed'
end
end

def example_failed(example)
super

@example_group_failed = true

error = example.execution_result[:exception]
error_name = error.class.name.to_s
output = "#{short_padding}#{error_name}:\n"
error.message.to_s.split("\n").each { |line| output += "#{long_padding} #{line}\n" }

wrapper = Element.new(:li, class_name: 'example failed')

description = Element.new(:span, class_name: 'example_description', text: example.description)
wrapper << description

exception = Element.new(:pre, class_name: 'exception', text: output)
wrapper << exception

@example_list << wrapper
@example_list.style :display, 'list-item'
end

def example_passed(example)
super

wrapper = Element.new(:li, class_name: 'example passed')
description = Element.new(:span, class_name: 'example_description', text: example.description)

wrapper << description
@example_list << wrapper
end

def dump_summary(duration, example_count, failure_count, pending_count)
super

summary = "\n#{example_count} examples, #{failure_count} failures (time taken: #{duration})"
@summary_element.text = summary
end

class Element
attr_reader :native

def initialize(el, attrs={})
if String === el
@native = `document.createElement(el)`
else
@native = el
end

attrs.each { |name, val| __send__ "#{name}=", val }
end

def class_name=(name)
`#@native.className = #{name}`
end

def html=(html)
`#@native.innerHTML = #{html}`
end

def text=(text)
self.html = text.gsub(/</, '&lt').gsub(/>/, '&gt')
end

def type=(type)
`#@native.type = #{type}`
end

def append(child)
`#@native.appendChild(#{child.native})`
end

alias << append

def css_text=(text)
%x{
if (#@native.styleSheet) {
#@native.styleSheet.cssText = #{text};
}
else {
#@native.appendChild(document.createTextNode(#{text}));
}
}
end

def style(name, value)
`#@native.style[#{name}] = value`
end

def append_to_head
`document.getElementsByTagName('head')[0].appendChild(#@native)`
end
end

CSS = <<-CSS
body {
font-size: 14px;
font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
}
pre {
font-family: "Bitstream Vera Sans Mono", Monaco, "Lucida Console", monospace;
font-size: 12px;
color: #444444;
white-space: pre;
padding: 3px 0px 3px 12px;
margin: 0px 0px 8px;
background: #FAFAFA;
-webkit-box-shadow: rgba(0,0,0,0.07) 0 1px 2px inset;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
border: 1px solid #DDDDDD;
}
ul.example_groups {
list-style-type: none;
}
li.group.passed .group_description {
color: #597800;
font-weight: bold;
}
li.group.failed .group_description {
color: #FF000E;
font-weight: bold;
}
li.example.passed {
color: #597800;
}
li.example.failed {
color: #FF000E;
}
.examples {
list-style-type: none;
}
CSS
end
end

27 changes: 27 additions & 0 deletions opal/opal-rspec/runner.rb
@@ -1,5 +1,32 @@
module OpalRSpec
class Runner

class << self
def browser?
`typeof(document) !== "undefined"`
end

def phantom?
`typeof(phantom) !== 'undefined' || typeof(OPAL_SPEC_PHANTOM) !== 'undefined'`
end

def default_formatter
if phantom?
TextFormatter
else # browser
BrowserFormatter
end
end

def autorun
if browser?
`setTimeout(function() { #{Runner.new.run} }, 0)`
else # phantom
Runner.new.run
end
end
end

def initialize(options={}, configuration=RSpec::configuration, world=RSpec::world)
@options = options
@configuration = configuration
Expand Down

0 comments on commit acf1ac5

Please sign in to comment.