opal-rspec-cj 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/.gitmodules +15 -0
- data/.travis.yml +13 -0
- data/.yardopts +5 -0
- data/CHANGELOG.md +25 -0
- data/Gemfile +8 -0
- data/README.md +147 -0
- data/Rakefile +26 -0
- data/config.ru +10 -0
- data/example/Gemfile +4 -0
- data/example/README.md +13 -0
- data/example/Rakefile +8 -0
- data/example/opal/user.rb +11 -0
- data/example/spec/user_spec.rb +15 -0
- data/lib/opal-rspec.rb +2 -0
- data/lib/opal/rspec.rb +20 -0
- data/lib/opal/rspec/rake_task.rb +63 -0
- data/lib/opal/rspec/version.rb +5 -0
- data/opal-rspec.gemspec +21 -0
- data/opal/opal-rspec.rb +1 -0
- data/opal/opal/rspec.rb +25 -0
- data/opal/opal/rspec/async.rb +289 -0
- data/opal/opal/rspec/browser_formatter.rb +188 -0
- data/opal/opal/rspec/fixes.rb +116 -0
- data/opal/opal/rspec/requires.rb +45 -0
- data/opal/opal/rspec/runner.rb +69 -0
- data/opal/opal/rspec/sprockets_runner.rb.erb +11 -0
- data/opal/opal/rspec/text_formatter.rb +74 -0
- data/spec/async_spec.rb +38 -0
- data/spec/example_spec.rb +163 -0
- data/spec/matchers_spec.rb +201 -0
- data/spec/mock_spec.rb +63 -0
- data/spec/named_subject_spec.rb +11 -0
- data/spec/should_syntax_spec.rb +17 -0
- data/vendor/spec_runner.js +50 -0
- data/vendor_lib/rspec-expectations.rb +1 -0
- data/vendor_lib/rspec.rb +3 -0
- data/vendor_lib/rspec/autorun.rb +2 -0
- data/vendor_lib/rspec/core.rb +203 -0
- data/vendor_lib/rspec/core/backport_random.rb +302 -0
- data/vendor_lib/rspec/core/backtrace_formatter.rb +65 -0
- data/vendor_lib/rspec/core/command_line.rb +36 -0
- data/vendor_lib/rspec/core/configuration.rb +1129 -0
- data/vendor_lib/rspec/core/configuration_options.rb +143 -0
- data/vendor_lib/rspec/core/drb_command_line.rb +26 -0
- data/vendor_lib/rspec/core/drb_options.rb +87 -0
- data/vendor_lib/rspec/core/dsl.rb +26 -0
- data/vendor_lib/rspec/core/example.rb +312 -0
- data/vendor_lib/rspec/core/example_group.rb +540 -0
- data/vendor_lib/rspec/core/filter_manager.rb +224 -0
- data/vendor_lib/rspec/core/flat_map.rb +17 -0
- data/vendor_lib/rspec/core/formatters.rb +54 -0
- data/vendor_lib/rspec/core/formatters/base_formatter.rb +291 -0
- data/vendor_lib/rspec/core/formatters/base_text_formatter.rb +307 -0
- data/vendor_lib/rspec/core/formatters/deprecation_formatter.rb +193 -0
- data/vendor_lib/rspec/core/formatters/documentation_formatter.rb +67 -0
- data/vendor_lib/rspec/core/formatters/helpers.rb +82 -0
- data/vendor_lib/rspec/core/formatters/html_formatter.rb +155 -0
- data/vendor_lib/rspec/core/formatters/html_printer.rb +408 -0
- data/vendor_lib/rspec/core/formatters/json_formatter.rb +99 -0
- data/vendor_lib/rspec/core/formatters/progress_formatter.rb +32 -0
- data/vendor_lib/rspec/core/formatters/snippet_extractor.rb +101 -0
- data/vendor_lib/rspec/core/hooks.rb +535 -0
- data/vendor_lib/rspec/core/memoized_helpers.rb +431 -0
- data/vendor_lib/rspec/core/metadata.rb +313 -0
- data/vendor_lib/rspec/core/mocking/with_absolutely_nothing.rb +11 -0
- data/vendor_lib/rspec/core/mocking/with_flexmock.rb +27 -0
- data/vendor_lib/rspec/core/mocking/with_mocha.rb +52 -0
- data/vendor_lib/rspec/core/mocking/with_rr.rb +27 -0
- data/vendor_lib/rspec/core/mocking/with_rspec.rb +27 -0
- data/vendor_lib/rspec/core/option_parser.rb +234 -0
- data/vendor_lib/rspec/core/ordering.rb +154 -0
- data/vendor_lib/rspec/core/pending.rb +110 -0
- data/vendor_lib/rspec/core/project_initializer.rb +88 -0
- data/vendor_lib/rspec/core/rake_task.rb +128 -0
- data/vendor_lib/rspec/core/reporter.rb +132 -0
- data/vendor_lib/rspec/core/ruby_project.rb +44 -0
- data/vendor_lib/rspec/core/runner.rb +97 -0
- data/vendor_lib/rspec/core/shared_context.rb +53 -0
- data/vendor_lib/rspec/core/shared_example_group.rb +146 -0
- data/vendor_lib/rspec/core/shared_example_group/collection.rb +27 -0
- data/vendor_lib/rspec/core/version.rb +7 -0
- data/vendor_lib/rspec/core/warnings.rb +22 -0
- data/vendor_lib/rspec/core/world.rb +131 -0
- data/vendor_lib/rspec/expectations.rb +75 -0
- data/vendor_lib/rspec/expectations/differ.rb +154 -0
- data/vendor_lib/rspec/expectations/errors.rb +9 -0
- data/vendor_lib/rspec/expectations/expectation_target.rb +87 -0
- data/vendor_lib/rspec/expectations/extensions.rb +1 -0
- data/vendor_lib/rspec/expectations/extensions/object.rb +29 -0
- data/vendor_lib/rspec/expectations/fail_with.rb +79 -0
- data/vendor_lib/rspec/expectations/handler.rb +68 -0
- data/vendor_lib/rspec/expectations/syntax.rb +182 -0
- data/vendor_lib/rspec/expectations/version.rb +8 -0
- data/vendor_lib/rspec/matchers.rb +633 -0
- data/vendor_lib/rspec/matchers/built_in.rb +39 -0
- data/vendor_lib/rspec/matchers/built_in/base_matcher.rb +68 -0
- data/vendor_lib/rspec/matchers/built_in/be.rb +213 -0
- data/vendor_lib/rspec/matchers/built_in/be_instance_of.rb +15 -0
- data/vendor_lib/rspec/matchers/built_in/be_kind_of.rb +11 -0
- data/vendor_lib/rspec/matchers/built_in/be_within.rb +55 -0
- data/vendor_lib/rspec/matchers/built_in/change.rb +141 -0
- data/vendor_lib/rspec/matchers/built_in/cover.rb +21 -0
- data/vendor_lib/rspec/matchers/built_in/eq.rb +22 -0
- data/vendor_lib/rspec/matchers/built_in/eql.rb +23 -0
- data/vendor_lib/rspec/matchers/built_in/equal.rb +48 -0
- data/vendor_lib/rspec/matchers/built_in/exist.rb +26 -0
- data/vendor_lib/rspec/matchers/built_in/has.rb +48 -0
- data/vendor_lib/rspec/matchers/built_in/include.rb +61 -0
- data/vendor_lib/rspec/matchers/built_in/match.rb +17 -0
- data/vendor_lib/rspec/matchers/built_in/match_array.rb +51 -0
- data/vendor_lib/rspec/matchers/built_in/raise_error.rb +154 -0
- data/vendor_lib/rspec/matchers/built_in/respond_to.rb +74 -0
- data/vendor_lib/rspec/matchers/built_in/satisfy.rb +30 -0
- data/vendor_lib/rspec/matchers/built_in/start_and_end_with.rb +48 -0
- data/vendor_lib/rspec/matchers/built_in/throw_symbol.rb +94 -0
- data/vendor_lib/rspec/matchers/built_in/yield.rb +297 -0
- data/vendor_lib/rspec/matchers/compatibility.rb +14 -0
- data/vendor_lib/rspec/matchers/configuration.rb +113 -0
- data/vendor_lib/rspec/matchers/dsl.rb +23 -0
- data/vendor_lib/rspec/matchers/generated_descriptions.rb +35 -0
- data/vendor_lib/rspec/matchers/matcher.rb +301 -0
- data/vendor_lib/rspec/matchers/method_missing.rb +12 -0
- data/vendor_lib/rspec/matchers/operator_matcher.rb +99 -0
- data/vendor_lib/rspec/matchers/pretty.rb +70 -0
- data/vendor_lib/rspec/matchers/test_unit_integration.rb +11 -0
- data/vendor_lib/rspec/mocks.rb +100 -0
- data/vendor_lib/rspec/mocks/any_instance/chain.rb +92 -0
- data/vendor_lib/rspec/mocks/any_instance/expectation_chain.rb +47 -0
- data/vendor_lib/rspec/mocks/any_instance/message_chains.rb +75 -0
- data/vendor_lib/rspec/mocks/any_instance/recorder.rb +200 -0
- data/vendor_lib/rspec/mocks/any_instance/stub_chain.rb +45 -0
- data/vendor_lib/rspec/mocks/any_instance/stub_chain_chain.rb +23 -0
- data/vendor_lib/rspec/mocks/argument_list_matcher.rb +104 -0
- data/vendor_lib/rspec/mocks/argument_matchers.rb +264 -0
- data/vendor_lib/rspec/mocks/arity_calculator.rb +66 -0
- data/vendor_lib/rspec/mocks/configuration.rb +111 -0
- data/vendor_lib/rspec/mocks/error_generator.rb +203 -0
- data/vendor_lib/rspec/mocks/errors.rb +12 -0
- data/vendor_lib/rspec/mocks/example_methods.rb +201 -0
- data/vendor_lib/rspec/mocks/extensions/marshal.rb +17 -0
- data/vendor_lib/rspec/mocks/framework.rb +36 -0
- data/vendor_lib/rspec/mocks/instance_method_stasher.rb +112 -0
- data/vendor_lib/rspec/mocks/matchers/have_received.rb +99 -0
- data/vendor_lib/rspec/mocks/matchers/receive.rb +112 -0
- data/vendor_lib/rspec/mocks/matchers/receive_messages.rb +72 -0
- data/vendor_lib/rspec/mocks/message_expectation.rb +643 -0
- data/vendor_lib/rspec/mocks/method_double.rb +209 -0
- data/vendor_lib/rspec/mocks/method_reference.rb +95 -0
- data/vendor_lib/rspec/mocks/mock.rb +7 -0
- data/vendor_lib/rspec/mocks/mutate_const.rb +406 -0
- data/vendor_lib/rspec/mocks/object_reference.rb +90 -0
- data/vendor_lib/rspec/mocks/order_group.rb +82 -0
- data/vendor_lib/rspec/mocks/proxy.rb +269 -0
- data/vendor_lib/rspec/mocks/proxy_for_nil.rb +37 -0
- data/vendor_lib/rspec/mocks/space.rb +95 -0
- data/vendor_lib/rspec/mocks/standalone.rb +3 -0
- data/vendor_lib/rspec/mocks/stub_chain.rb +51 -0
- data/vendor_lib/rspec/mocks/syntax.rb +374 -0
- data/vendor_lib/rspec/mocks/targets.rb +90 -0
- data/vendor_lib/rspec/mocks/test_double.rb +109 -0
- data/vendor_lib/rspec/mocks/verifying_double.rb +77 -0
- data/vendor_lib/rspec/mocks/verifying_message_expecation.rb +60 -0
- data/vendor_lib/rspec/mocks/verifying_proxy.rb +151 -0
- data/vendor_lib/rspec/mocks/version.rb +7 -0
- data/vendor_lib/rspec/support.rb +6 -0
- data/vendor_lib/rspec/support/caller_filter.rb +56 -0
- data/vendor_lib/rspec/support/spec.rb +14 -0
- data/vendor_lib/rspec/support/spec/deprecation_helpers.rb +29 -0
- data/vendor_lib/rspec/support/spec/in_sub_process.rb +40 -0
- data/vendor_lib/rspec/support/spec/stderr_splitter.rb +50 -0
- data/vendor_lib/rspec/support/version.rb +7 -0
- data/vendor_lib/rspec/support/warnings.rb +41 -0
- data/vendor_lib/rspec/version.rb +5 -0
- metadata +268 -0
data/opal/opal-rspec.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'opal/rspec'
|
data/opal/opal/rspec.rb
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
class MiniTest
|
|
2
|
+
class Unit; end
|
|
3
|
+
end
|
|
4
|
+
|
|
5
|
+
Test = MiniTest
|
|
6
|
+
|
|
7
|
+
require 'opal/rspec/requires'
|
|
8
|
+
require 'opal/rspec/fixes'
|
|
9
|
+
require 'opal/rspec/text_formatter'
|
|
10
|
+
require 'opal/rspec/browser_formatter'
|
|
11
|
+
require 'opal/rspec/runner'
|
|
12
|
+
require 'opal/rspec/async'
|
|
13
|
+
|
|
14
|
+
RSpec.configure do |config|
|
|
15
|
+
# For now, always use our custom formatter for results
|
|
16
|
+
config.formatter = Opal::RSpec::Runner.default_formatter
|
|
17
|
+
|
|
18
|
+
# Async helpers for specs
|
|
19
|
+
config.include Opal::RSpec::AsyncHelpers
|
|
20
|
+
|
|
21
|
+
# Always support expect() and .should syntax (we should not do this really..)
|
|
22
|
+
config.expect_with :rspec do |c|
|
|
23
|
+
c.syntax = [:should, :expect]
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
module Opal
|
|
2
|
+
module RSpec
|
|
3
|
+
# {AsyncHelpers} is automatically included in all example groups to add
|
|
4
|
+
# support for running specs async. Usually, rspec runners expect all
|
|
5
|
+
# examples to run synchronously, but this is not ideal in the case for
|
|
6
|
+
# Opal where a lot of underlying libraries expect the ability to run code
|
|
7
|
+
# in an asynchronous manner.
|
|
8
|
+
#
|
|
9
|
+
# This module defines an {AsyncHelpers::ClassMethods.async} method which
|
|
10
|
+
# can be used instead of `it` inside an example group, which marks the
|
|
11
|
+
# example as being async. This makes the runner wait for the example to
|
|
12
|
+
# complete.
|
|
13
|
+
#
|
|
14
|
+
# describe "Some examples" do
|
|
15
|
+
# it "normal example" do
|
|
16
|
+
# # normal test code
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# async "async example" do
|
|
20
|
+
# # this will wait until completion before moving on
|
|
21
|
+
# end
|
|
22
|
+
# end
|
|
23
|
+
#
|
|
24
|
+
# Marking an example as being async is only half the task. Examples will
|
|
25
|
+
# also have an instance {AsyncHelpers#async} method defined which is then
|
|
26
|
+
# used to complete the example. Any code run inside this block will run
|
|
27
|
+
# inside the context of the example.
|
|
28
|
+
#
|
|
29
|
+
# describe "HTTP requests" do
|
|
30
|
+
# async "might take a while" do
|
|
31
|
+
# HTTP.get("/url/to/get") do |res|
|
|
32
|
+
# async { expect(res).to be_ok }
|
|
33
|
+
# end
|
|
34
|
+
# end
|
|
35
|
+
# end
|
|
36
|
+
#
|
|
37
|
+
# As soon as `async` is run inside the block, the example completes. This
|
|
38
|
+
# means that only 1 `async` call is allowed. However, you can use `async`
|
|
39
|
+
# multiple times aslong as it is only called once:
|
|
40
|
+
#
|
|
41
|
+
# describe "HTTP requests" do
|
|
42
|
+
# async "should work" do
|
|
43
|
+
# HTTP.get("/users/1").then |res|
|
|
44
|
+
# async { expect(res).to be_ok }
|
|
45
|
+
# end.fail do
|
|
46
|
+
# async { raise "this should not be called" }
|
|
47
|
+
# end
|
|
48
|
+
# end
|
|
49
|
+
# end
|
|
50
|
+
#
|
|
51
|
+
# Here, a promise will either be accepted or rejected, so an `async` block
|
|
52
|
+
# can be used in each case as only 1 will be called.
|
|
53
|
+
#
|
|
54
|
+
# Another helper, {AsyncHelpers#delay} can also be used to run a block of
|
|
55
|
+
# code after a given time in seconds. This is useful to wait for animations
|
|
56
|
+
# or time restricted operations to occur.
|
|
57
|
+
module AsyncHelpers
|
|
58
|
+
module ClassMethods
|
|
59
|
+
# Define an async example method. This should be used instead of `it`
|
|
60
|
+
# to inform the spec runner that the example will need to wait for an
|
|
61
|
+
# {AsyncHelpers#async} method to complete the test. Any additional
|
|
62
|
+
# configuration options can be passed to this call, and they just get
|
|
63
|
+
# delegated to the underlying `#it` call.
|
|
64
|
+
#
|
|
65
|
+
# @example
|
|
66
|
+
# describe "Some tests" do
|
|
67
|
+
# async "should be async" do
|
|
68
|
+
# # ... async code
|
|
69
|
+
# end
|
|
70
|
+
#
|
|
71
|
+
# it "should work with normal tests" do
|
|
72
|
+
# expect(1).to eq(1)
|
|
73
|
+
# end
|
|
74
|
+
# end
|
|
75
|
+
#
|
|
76
|
+
# @param desc [String] description
|
|
77
|
+
def async(desc, *args, &block)
|
|
78
|
+
options = ::RSpec::Core::Metadata.build_hash_from(args)
|
|
79
|
+
Opal::RSpec::AsyncExample.register(self, desc, options, block)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def self.included(base)
|
|
84
|
+
base.extend ClassMethods
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Must be used with {ClassMethods#async} to finish the async action. If
|
|
88
|
+
# this is not called inside the body then the spec runner will time out
|
|
89
|
+
# or the error might give a false positive as it is not caught inside
|
|
90
|
+
# the current example.
|
|
91
|
+
#
|
|
92
|
+
# @example Complete expectation after HTTP request
|
|
93
|
+
# describe "HTTP calls" do
|
|
94
|
+
# async "complete eventually" do
|
|
95
|
+
# HTTP.get("/some_url") do |response|
|
|
96
|
+
# async { expect(response).to be_ok }
|
|
97
|
+
# end
|
|
98
|
+
# end
|
|
99
|
+
# end
|
|
100
|
+
#
|
|
101
|
+
def async(&block)
|
|
102
|
+
@example.continue_async(block)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Runs the given block after a given duration. You are still required to
|
|
106
|
+
# use a {#async} block inside the delayed callback. This helper can be
|
|
107
|
+
# used to simulate IO delays, or just to wait for animations/other
|
|
108
|
+
# behaviour to finish.
|
|
109
|
+
#
|
|
110
|
+
# The `duaration` should be given in seconds, i.e. `1` means 1 second, or
|
|
111
|
+
# 0.3 means 300ms. The given block is just run after the time delay.
|
|
112
|
+
#
|
|
113
|
+
# @example
|
|
114
|
+
# describe "Some interaction" do
|
|
115
|
+
# async "takes a while to complete" do
|
|
116
|
+
# task = start_long_task!
|
|
117
|
+
#
|
|
118
|
+
# delay(1) do
|
|
119
|
+
# async { expect(task).to be_completed }
|
|
120
|
+
# end
|
|
121
|
+
# end
|
|
122
|
+
# end
|
|
123
|
+
#
|
|
124
|
+
# @param duration [Integer, Float] time in seconds to wait
|
|
125
|
+
def delay(duration, &block)
|
|
126
|
+
`setTimeout(block, duration * 1000)`
|
|
127
|
+
self
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Use {#async} instead.
|
|
131
|
+
#
|
|
132
|
+
# @deprecated
|
|
133
|
+
def run_async(&block)
|
|
134
|
+
async(&block)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Use {#delay} instead.
|
|
138
|
+
#
|
|
139
|
+
# @deprecated
|
|
140
|
+
def set_timeout(*args, &block)
|
|
141
|
+
delay(*args, &block)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Runs all async examples from {AsyncExample.examples}.
|
|
146
|
+
class AsyncRunner
|
|
147
|
+
def initialize(runner, reporter, finish_block)
|
|
148
|
+
@runner = runner
|
|
149
|
+
@reporter = reporter
|
|
150
|
+
@finish_block = finish_block
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def run
|
|
154
|
+
@examples = AsyncExample.examples.clone
|
|
155
|
+
run_next_example
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def run_next_example
|
|
159
|
+
if @examples.empty?
|
|
160
|
+
finish
|
|
161
|
+
else
|
|
162
|
+
run_example @examples.pop
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def run_example(example)
|
|
167
|
+
example_group = example.example_group
|
|
168
|
+
|
|
169
|
+
@reporter.example_group_started example_group
|
|
170
|
+
instance = example_group.new
|
|
171
|
+
|
|
172
|
+
example.run(instance, @reporter) do
|
|
173
|
+
example_finished example
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def example_finished(example)
|
|
178
|
+
@reporter.example_group_finished example.example_group
|
|
179
|
+
run_next_example
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Called once all examples have finished. Just calls back to main
|
|
183
|
+
# runner to inform it
|
|
184
|
+
def finish
|
|
185
|
+
@finish_block.call
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# An {AsyncExample} is a subclass of regular example instances which adds
|
|
190
|
+
# support for running an example, and waiting for a non-sync outcome. All
|
|
191
|
+
# async examples in a set of spec files will get registered through
|
|
192
|
+
# {AsyncExample.register}, and added to the {AsyncExample.examples} array
|
|
193
|
+
# ready for the runner to run.
|
|
194
|
+
#
|
|
195
|
+
# You will not need to create new instances of this class directly, and
|
|
196
|
+
# should instead use {AsyncHelpers} to create async examples.
|
|
197
|
+
class AsyncExample < ::RSpec::Core::Example
|
|
198
|
+
include AsyncHelpers
|
|
199
|
+
|
|
200
|
+
# Register new async example.
|
|
201
|
+
#
|
|
202
|
+
# @see AsyncHelpers::ClassMethods.async
|
|
203
|
+
def self.register(*args)
|
|
204
|
+
examples << new(*args)
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# All async examples in specs.
|
|
208
|
+
#
|
|
209
|
+
# @return [Array<AsyncExample>]
|
|
210
|
+
def self.examples
|
|
211
|
+
@examples ||= []
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def run(example_group_instance, reporter, &after_run_block)
|
|
215
|
+
@example_group_instance = example_group_instance
|
|
216
|
+
@reporter = reporter
|
|
217
|
+
@after_run_block = after_run_block
|
|
218
|
+
@finished = false
|
|
219
|
+
|
|
220
|
+
should_wait = true
|
|
221
|
+
|
|
222
|
+
::RSpec.current_example = self
|
|
223
|
+
example_group_instance.instance_variable_set :@example, self
|
|
224
|
+
|
|
225
|
+
start(reporter)
|
|
226
|
+
|
|
227
|
+
begin
|
|
228
|
+
run_before_each
|
|
229
|
+
@example_group_instance.instance_exec(self, &@example_block)
|
|
230
|
+
rescue Exception => e
|
|
231
|
+
set_exception(e)
|
|
232
|
+
should_wait = false
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
if should_wait
|
|
236
|
+
delay options[:timeout] || 10 do
|
|
237
|
+
next if finished?
|
|
238
|
+
|
|
239
|
+
set_exception RuntimeError.new("timeout")
|
|
240
|
+
async_example_finished
|
|
241
|
+
end
|
|
242
|
+
else
|
|
243
|
+
async_example_finished
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def continue_async(block)
|
|
248
|
+
return if finished?
|
|
249
|
+
|
|
250
|
+
begin
|
|
251
|
+
block.call
|
|
252
|
+
rescue Exception => e
|
|
253
|
+
set_exception(e)
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
async_example_finished
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def finished?
|
|
260
|
+
@finished
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def async_example_finished
|
|
264
|
+
@finished = true
|
|
265
|
+
|
|
266
|
+
begin
|
|
267
|
+
run_after_each
|
|
268
|
+
rescue Exception => e
|
|
269
|
+
set_exception(e)
|
|
270
|
+
ensure
|
|
271
|
+
@example_group_instance.instance_variables.each do |ivar|
|
|
272
|
+
@example_group_instance.instance_variable_set(ivar, nil)
|
|
273
|
+
end
|
|
274
|
+
@example_group_instance = nil
|
|
275
|
+
|
|
276
|
+
begin
|
|
277
|
+
assign_generated_description
|
|
278
|
+
rescue Exception => e
|
|
279
|
+
set_exception(e, "while assigning the example description")
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
finish(@reporter)
|
|
284
|
+
::RSpec.current_example = nil
|
|
285
|
+
@after_run_block.call
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
end
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
require 'erb'
|
|
2
|
+
|
|
3
|
+
module Opal
|
|
4
|
+
module RSpec
|
|
5
|
+
class BrowserFormatter < ::RSpec::Core::Formatters::BaseFormatter
|
|
6
|
+
include ERB::Util
|
|
7
|
+
|
|
8
|
+
CSS_STYLES = ::RSpec::Core::Formatters::HtmlPrinter::GLOBAL_STYLES
|
|
9
|
+
|
|
10
|
+
def start(example_count)
|
|
11
|
+
super
|
|
12
|
+
target = Element.new(`document.body`)
|
|
13
|
+
target << Element.new(:div, html: REPORT_TEMPLATE)
|
|
14
|
+
@rspec_results = Element.id('rspec-results')
|
|
15
|
+
|
|
16
|
+
css_text = CSS_STYLES + "\n body { padding: 0; margin: 0 }"
|
|
17
|
+
styles = Element.new(:style, type: 'text/css', css_text: css_text)
|
|
18
|
+
styles.append_to_head
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def example_group_started(example_group)
|
|
22
|
+
super
|
|
23
|
+
|
|
24
|
+
@example_group_failed = false
|
|
25
|
+
parents = example_group.parent_groups.size
|
|
26
|
+
|
|
27
|
+
@rspec_group = Element.new(:div, class_name: "example_group passed")
|
|
28
|
+
@rspec_dl = Element.new(:dl)
|
|
29
|
+
@rspec_dt = Element.new(:dt, class_name: "passed", text: example_group.description)
|
|
30
|
+
@rspec_group << @rspec_dl
|
|
31
|
+
@rspec_dl << @rspec_dt
|
|
32
|
+
|
|
33
|
+
@rspec_dl.style 'margin-left', "#{(parents - 2) * 15}px"
|
|
34
|
+
|
|
35
|
+
@rspec_results << @rspec_group
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def example_group_finished(example_group)
|
|
39
|
+
super
|
|
40
|
+
|
|
41
|
+
if @example_group_failed
|
|
42
|
+
@rspec_group.class_name = "example_group failed"
|
|
43
|
+
@rspec_dt.class_name = "failed"
|
|
44
|
+
Element.id('rspec-header').class_name = 'failed'
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def example_failed(example)
|
|
49
|
+
super
|
|
50
|
+
duration = sprintf("%0.5f", example.execution_result[:run_time])
|
|
51
|
+
|
|
52
|
+
error = example.execution_result[:exception]
|
|
53
|
+
error_name = error.class.name.to_s
|
|
54
|
+
output = "#{short_padding}#{error_name}:\n"
|
|
55
|
+
error.message.to_s.split("\n").each { |line| output += "#{long_padding} #{line}\n" }
|
|
56
|
+
|
|
57
|
+
@example_group_failed = true
|
|
58
|
+
|
|
59
|
+
@rspec_dl << Element.new(:dd, class_name: "example failed", html: <<-HTML)
|
|
60
|
+
<span class="failed_spec_name">#{h example.description}</span>
|
|
61
|
+
<span class="duration">#{duration}s</span>
|
|
62
|
+
<div class="failure">
|
|
63
|
+
<div class="message"><pre>#{h output}</pre></div>
|
|
64
|
+
</div>
|
|
65
|
+
HTML
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def example_passed(example)
|
|
69
|
+
super
|
|
70
|
+
duration = sprintf("%0.5f", example.execution_result[:run_time])
|
|
71
|
+
|
|
72
|
+
@rspec_dl << Element.new(:dd, class_name: "example passed", html: <<-HTML)
|
|
73
|
+
<span class="passed_spec_name">#{h example.description}</span>
|
|
74
|
+
<span class="duration">#{duration}s</span>
|
|
75
|
+
HTML
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def dump_summary(duration, example_count, failure_count, pending_count)
|
|
79
|
+
super
|
|
80
|
+
|
|
81
|
+
totals = "#{example_count} examples, #{failure_count} failures"
|
|
82
|
+
Element.id('totals').html = totals
|
|
83
|
+
|
|
84
|
+
duration = "Finished in <strong>#{sprintf("%.5f", duration)} seconds</strong>"
|
|
85
|
+
Element.id('duration').html = duration
|
|
86
|
+
|
|
87
|
+
add_scripts
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def add_scripts
|
|
91
|
+
content = ::RSpec::Core::Formatters::HtmlPrinter::GLOBAL_SCRIPTS
|
|
92
|
+
`window.eval(#{content})`
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def short_padding
|
|
96
|
+
' '
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def long_padding
|
|
100
|
+
' '
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
class Element
|
|
104
|
+
attr_reader :native
|
|
105
|
+
|
|
106
|
+
def self.id(id)
|
|
107
|
+
new(`document.getElementById(id)`)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def initialize(el, attrs={})
|
|
111
|
+
if String === el
|
|
112
|
+
@native = `document.createElement(el)`
|
|
113
|
+
else
|
|
114
|
+
@native = el
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
attrs.each { |name, val| __send__ "#{name}=", val }
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def class_name=(name)
|
|
121
|
+
`#@native.className = #{name}`
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def html=(html)
|
|
125
|
+
`#@native.innerHTML = #{html}`
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def text=(text)
|
|
129
|
+
self.html = text.gsub(/</, '<').gsub(/>/, '>')
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def type=(type)
|
|
133
|
+
`#@native.type = #{type}`
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def append(child)
|
|
137
|
+
`#@native.appendChild(#{child.native})`
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
alias << append
|
|
141
|
+
|
|
142
|
+
def css_text=(text)
|
|
143
|
+
%x{
|
|
144
|
+
if (#@native.styleSheet) {
|
|
145
|
+
#@native.styleSheet.cssText = #{text};
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
#@native.appendChild(document.createTextNode(#{text}));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def style(name, value)
|
|
154
|
+
`#@native.style[#{name}] = value`
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def append_to_head
|
|
158
|
+
`document.getElementsByTagName('head')[0].appendChild(#@native)`
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
REPORT_TEMPLATE = <<-EOF
|
|
163
|
+
<div class="rspec-report">
|
|
164
|
+
|
|
165
|
+
<div id="rspec-header">
|
|
166
|
+
<div id="label">
|
|
167
|
+
<h1>RSpec Code Examples</h1>
|
|
168
|
+
</div>
|
|
169
|
+
|
|
170
|
+
<div id="display-filters">
|
|
171
|
+
<input id="passed_checkbox" name="passed_checkbox" type="checkbox" checked="checked" onchange="apply_filters()" value="1" /> <label for="passed_checkbox">Passed</label>
|
|
172
|
+
<input id="failed_checkbox" name="failed_checkbox" type="checkbox" checked="checked" onchange="apply_filters()" value="2" /> <label for="failed_checkbox">Failed</label>
|
|
173
|
+
<input id="pending_checkbox" name="pending_checkbox" type="checkbox" checked="checked" onchange="apply_filters()" value="3" /> <label for="pending_checkbox">Pending</label>
|
|
174
|
+
</div>
|
|
175
|
+
|
|
176
|
+
<div id="summary">
|
|
177
|
+
<p id="totals"> </p>
|
|
178
|
+
<p id="duration"> </p>
|
|
179
|
+
</div>
|
|
180
|
+
</div>
|
|
181
|
+
|
|
182
|
+
<div id="rspec-results" class="results">
|
|
183
|
+
</div>
|
|
184
|
+
</div>
|
|
185
|
+
EOF
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|