opal-rspec 0.5.0.beta3 → 0.5.0
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 +4 -4
- data/.travis.yml +17 -2
- data/CHANGELOG.md +4 -2
- data/README.md +38 -26
- data/Rakefile +14 -1
- data/config.ru +10 -7
- data/lib/opal/rspec/cached_environment.rb +3 -1
- data/lib/opal/rspec/post_rack_locator.rb +1 -1
- data/lib/opal/rspec/pre_rack_locator.rb +13 -49
- data/lib/opal/rspec/rake_task.rb +4 -9
- data/lib/opal/rspec/sprockets_environment.rb +5 -3
- data/lib/opal/rspec/version.rb +1 -1
- data/opal/opal/rspec/formatter/element.rb +14 -2
- data/opal/opal/rspec/formatter/html_printer.rb +14 -2
- data/spec/mri/unit/opal/rspec/cached_environment_spec.rb +16 -34
- data/spec/mri/unit/opal/rspec/rake_task_spec.rb +21 -5
- data/spec/mri/unit/opal/rspec/sprockets_environment_spec.rb +21 -60
- data/spec/rspec/core/core_spec_loader.rb +4 -0
- data/spec/rspec/expectations/expectation_spec_loader.rb +4 -0
- data/spec/rspec/mocks/filter/bugs/any_instance.rb +3 -3
- data/spec/rspec/mocks/mocks_spec_loader.rb +4 -0
- data/spec/rspec/opal_rspec_spec_loader.rb +20 -10
- data/spec/rspec/support/support_spec_loader.rb +4 -0
- data/vendor/spec_runner.js +2 -2
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1da9042a8eae6f23afb1f989cd88ac73bb16bf2b
|
4
|
+
data.tar.gz: 199ade21ce80c64e09f5123ecadd37d156c7cde9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 07fd2261509f2ac82c45866d6acbce58db865a75e08fb04ae48ab8047589781b70b940f1f00b419b07ae35118a692ddb0af27e3ea9a5089a01cb06dc514359a9
|
7
|
+
data.tar.gz: fa16038e70c8daa6cd27ac081a295fdba6c9bb3f96e353e72446173cce572eca39945d3a0782cd23c04f852807fd2b435f8f6d33b09fdf3ba9334308b03d0283
|
data/.travis.yml
CHANGED
@@ -8,14 +8,29 @@ matrix:
|
|
8
8
|
fast_finish: true
|
9
9
|
|
10
10
|
include:
|
11
|
-
- rvm: 1.9.3
|
12
|
-
|
11
|
+
# - rvm: 1.9.3
|
12
|
+
# env: RUN=default
|
13
13
|
- rvm: 2.0.0
|
14
14
|
env: RUN=default
|
15
15
|
- rvm: 2.1.0
|
16
16
|
env: RUN=default
|
17
17
|
- rvm: 2.2.3
|
18
18
|
env: RUN=default
|
19
|
+
- rvm: 2.2.3
|
20
|
+
# PHANTOMJS env variable is not used but it makes it easier to differentiate this build in Travis
|
21
|
+
# https://github.com/travis-ci/travis-ci/issues/3225 - Easiest way to use 2.0 on Travis
|
22
|
+
env: RUN=default PHANTOMJS=2.0
|
23
|
+
before_script:
|
24
|
+
- "mkdir phantom20"
|
25
|
+
- "export PATH=`pwd`/phantom20:$PATH"
|
26
|
+
- "echo $PATH"
|
27
|
+
- "pushd ."
|
28
|
+
- "cd phantom20"
|
29
|
+
- "curl -L -O https://s3.amazonaws.com/travis-phantomjs/phantomjs-2.0.0-ubuntu-12.04.tar.bz2"
|
30
|
+
- "tar xjvf phantomjs-2.0.0-ubuntu-12.04.tar.bz2"
|
31
|
+
- "popd"
|
32
|
+
- "export DISPLAY=:99.0"
|
33
|
+
- "sh -e /etc/init.d/xvfb start"
|
19
34
|
- rvm: 2.2.3
|
20
35
|
env: RUN=default RUNNER=node
|
21
36
|
- rvm: 2.2.3
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
## 0.5.0 (
|
1
|
+
## 0.5.0 (2015-12-08)
|
2
2
|
|
3
3
|
* By default, any subject, it example block, before(:each), after(:each), and around that returns a promise will be executed asynchronously. Async is NOT yet supported for context level hooks. Async approach from < 0.4.3 will still work.
|
4
4
|
|
@@ -17,7 +17,7 @@
|
|
17
17
|
* Formatters:
|
18
18
|
* Fixed issues with RSpec's BaseTextFormatter and made ProgressFormatter the default when run via the Rake task
|
19
19
|
* Fix redundant messages with expectation fails
|
20
|
-
* Browser formatter now works w/ progress bar
|
20
|
+
* Browser formatter now works w/ progress bar and has a 'Dump to console' link that will put a clickable stack trace for a failed example in the browser console
|
21
21
|
* JSON formatter supported
|
22
22
|
|
23
23
|
* Fixed issues with constants/example group naming
|
@@ -26,6 +26,8 @@
|
|
26
26
|
|
27
27
|
* A lot more matchers enabled
|
28
28
|
|
29
|
+
* PhantomJS 2.0 compatibility (also still compatible with 1.9.8). Thanks to @aost. Closes out https://github.com/opal/opal-rspec/issues/42
|
30
|
+
|
29
31
|
|
30
32
|
## 0.4.3 (2015-06-14)
|
31
33
|
|
data/README.md
CHANGED
@@ -14,6 +14,12 @@ Add `opal-rspec` to your Gemfile:
|
|
14
14
|
gem 'opal-rspec'
|
15
15
|
```
|
16
16
|
|
17
|
+
## Requirements
|
18
|
+
|
19
|
+
Besides what's already reflected in the GEM dependencies:
|
20
|
+
* PhantomJS 1.9.8 or 2.0 for Rake task testing
|
21
|
+
* Browser if you want to run and debug tests that way
|
22
|
+
|
17
23
|
### Run specs in phantomjs
|
18
24
|
|
19
25
|
To run specs, a rake task can be added which will load all spec files from
|
@@ -59,10 +65,13 @@ You can also customize the pattern of specs used similiar to how RSpec's rake ta
|
|
59
65
|
Opal::RSpec::RakeTask.new(:default) do |server, task|
|
60
66
|
# server is an instance of Opal::Server in case you want to add to the load path, customize, etc.
|
61
67
|
task.pattern = 'spec_alternate/**/*_spec.rb' # can also supply an array of patterns
|
68
|
+
# NOTE: opal-rspec, like rspec, only adds 'spec' to the Opal load path unless you set default_path
|
69
|
+
task.default_path = 'spec_alternate'
|
62
70
|
end
|
63
71
|
```
|
64
72
|
|
65
73
|
Excluding patterns can be setup this way:
|
74
|
+
|
66
75
|
```ruby
|
67
76
|
Opal::RSpec::RakeTask.new(:default) do |server, task|
|
68
77
|
task.exclude_pattern = 'spec_alternate/**/*_spec.rb' # can also supply an array of patterns
|
@@ -73,7 +82,7 @@ FileLists (as in Rake FileLists) can also be supplied:
|
|
73
82
|
|
74
83
|
```ruby
|
75
84
|
Opal::RSpec::RakeTask.new(:default) do |server, task|
|
76
|
-
task.files = FileList['spec/**/something_spec.rb]
|
85
|
+
task.files = FileList['spec/**/something_spec.rb']
|
77
86
|
end
|
78
87
|
```
|
79
88
|
|
@@ -81,14 +90,14 @@ PhantomJS will timeout by default after 60 seconds. If you need to lengthen the
|
|
81
90
|
|
82
91
|
```ruby
|
83
92
|
Opal::RSpec::RakeTask.new(:default) do |server, task|
|
84
|
-
task.files = FileList['spec/**/something_spec.rb]
|
93
|
+
task.files = FileList['spec/**/something_spec.rb']
|
85
94
|
task.timeout = 80000 # 80 seconds, unit needs to be milliseconds
|
86
95
|
end
|
87
96
|
```
|
88
97
|
|
89
98
|
### Run specs in nodejs
|
90
99
|
|
91
|
-
Same options as above, you can use the RUNNER=node environment variable or use the Rake task like so:
|
100
|
+
Same options as above, you can use the `RUNNER=node` environment variable or use the Rake task like so:
|
92
101
|
|
93
102
|
```ruby
|
94
103
|
Opal::RSpec::RakeTask.new(:default) do |server, task|
|
@@ -117,6 +126,10 @@ run Opal::Server.new(sprockets: sprockets_env) { |s|
|
|
117
126
|
Then run the rack server `bundle exec rackup` and visit `http://localhost:9292`
|
118
127
|
in any web browser.
|
119
128
|
|
129
|
+
A new feature of opal-rspec 0.5 allows you to click a 'Console' button in the browser's test results and get a
|
130
|
+
clickable stack trace in the browser console. This should ease debugging with long, concatenated script files and trying
|
131
|
+
to navigate to where an exception occurred.
|
132
|
+
|
120
133
|
## Async examples
|
121
134
|
|
122
135
|
`opal-rspec` adds support for async specs to rspec. These specs can be defined using 2 approaches:
|
@@ -180,9 +193,11 @@ end
|
|
180
193
|
```
|
181
194
|
|
182
195
|
Advantages:
|
196
|
+
|
183
197
|
* Assuming your subject under test (or matchers) return/use promises, the syntax is the same for sync or async specs
|
184
198
|
|
185
199
|
Limitations (apply to both async approaches):
|
200
|
+
|
186
201
|
* Right now, async `before(:context)` and `after(:context)` hooks cannot be async
|
187
202
|
* You cannot use an around hooks on any example where before(:each)/after(:each) hooks are async or with an async implicit subject
|
188
203
|
* `let` dependencies cannot be async, only subject
|
@@ -209,43 +224,40 @@ so it can move on. Any failures/expectations run inside this block will be run
|
|
209
224
|
in the context of the example.
|
210
225
|
|
211
226
|
Advantages:
|
227
|
+
|
212
228
|
* Hides promises from the specs
|
213
229
|
|
214
230
|
Disadvantages:
|
231
|
+
|
215
232
|
* Requires different syntax for async specs vs. sync specs
|
216
233
|
|
217
234
|
## Opal load path
|
218
235
|
|
219
|
-
NOTE: Only the
|
220
|
-
|
221
|
-
Example 1: For the example patterns above, only 'spec_alternate' will be added.
|
236
|
+
NOTE: Only the 'spec' directory will be added to the Opal load path by default. Use the Rake task's 'default_path' setting to change that
|
222
237
|
|
223
|
-
|
238
|
+
## Other Limitations/Known Issues
|
224
239
|
|
225
|
-
|
240
|
+
* Core Examples
|
241
|
+
* Example groups included like this are currently not working:
|
226
242
|
```ruby
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
'
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
243
|
+
module TestMod
|
244
|
+
def self.included(base)
|
245
|
+
base.class_eval do
|
246
|
+
describe 'foo' do
|
247
|
+
...
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
235
252
|
|
236
|
-
|
237
|
-
|
238
|
-
|
253
|
+
RSpec.configure do |c|
|
254
|
+
c.include TestMod
|
255
|
+
end
|
239
256
|
```
|
240
|
-
|
241
|
-
Only 'spec' will be added to the load path.
|
242
|
-
|
243
|
-
## Other Limitations/Known Issues
|
244
|
-
|
245
257
|
* Formatting
|
246
258
|
* Backtrace info on specs is buggy ([no Kernel::caller method in Opal](https://github.com/opal/opal/issues/894)), in Firefox w/ the browser runner, no backtraces show up with failed specs
|
247
259
|
* Diffs are not yet available when objects do not meet expectations (diff-lcs gem dependency has not been dealt with yet in Opal)
|
248
|
-
* Configuration
|
260
|
+
* Configuration
|
249
261
|
* Not all RSpec runner options are supported yet
|
250
262
|
* At some point, using node + Phantom's ability to read environment variables could be combined with a opal friendly optparse implementation to allow full options to be supplied/parsed
|
251
263
|
* Expect and should syntax are both enabled. They cannot be disabled due to bugs with the `undef` keyword in Opal 0.8. Status of changing this via config has not been tested in Opal 0.9.
|
@@ -263,7 +275,7 @@ Only 'spec' will be added to the load path.
|
|
263
275
|
* arity checking is not enabled by default in Opal but it can be. It's not currently enabled because it broke a lot of Opal specs. As a result, any matcher use (particularly respond_to) that depends on arity checking will not work
|
264
276
|
* splat methods and expect(...).to respond_to will be inconsistent in Opal 0.8 since several splat bugs were fixed with Opal 0.9
|
265
277
|
* Mocks
|
266
|
-
* `allow_any_instance/any_instance_of/any_instance`
|
278
|
+
* `allow_any_instance/any_instance_of/any_instance` are unstable and may cause runner to crash due to issues with redefining the `===` operator, which breaks a case statement inside `Hooks#find_hook`
|
267
279
|
* using expect/allow on `String`, `Number`, or any immutable bridged/native class, does not work since rspec-mocks uses singleton classes and those cannot be defined on immutable objects
|
268
280
|
* mocking class methods (including `::new`) is currently broken
|
269
281
|
* `class_double/class_spy` are not supported (it depends on `ClassVerifyingDouble` inheriting from `Module` to support transferring nested constants, but that doesn't work on Opal)
|
data/Rakefile
CHANGED
@@ -9,11 +9,22 @@ require_relative 'spec/rspec/expectations/expectation_spec_loader'
|
|
9
9
|
require_relative 'spec/rspec/support/support_spec_loader'
|
10
10
|
require_relative 'spec/rspec/mocks/mocks_spec_loader'
|
11
11
|
|
12
|
-
task :default => [:
|
12
|
+
task :default => [:phantom_node_ver,
|
13
|
+
:unit_specs,
|
14
|
+
:verify_opal_specs,
|
15
|
+
:integration_specs,
|
16
|
+
:verify_rspec_specs]
|
17
|
+
|
18
|
+
task :phantom_node_ver do
|
19
|
+
sh 'phantomjs -v'
|
20
|
+
sh 'node -v'
|
21
|
+
sh 'firefox --version'
|
22
|
+
end
|
13
23
|
|
14
24
|
desc 'Runs a set of specs in opal'
|
15
25
|
Opal::RSpec::RakeTask.new(:opal_specs) do |_, task|
|
16
26
|
task.pattern = 'spec/opal/**/*_spec.{rb,opal}'
|
27
|
+
task.default_path = 'spec/opal'
|
17
28
|
end
|
18
29
|
|
19
30
|
desc 'Generates an RSpec requires file free of dynamic requires'
|
@@ -36,10 +47,12 @@ end
|
|
36
47
|
desc 'A more limited spec suite to test pattern usage'
|
37
48
|
Opal::RSpec::RakeTask.new(:other_specs) do |_, task|
|
38
49
|
task.pattern = 'spec/other/dummy_spec.rb'
|
50
|
+
task.default_path = 'spec/other'
|
39
51
|
end
|
40
52
|
|
41
53
|
Opal::RSpec::RakeTask.new(:color_on_by_default) do |_, task|
|
42
54
|
task.pattern = 'spec/other/color_on_by_default_spec.rb'
|
55
|
+
task.default_path = 'spec/other'
|
43
56
|
end
|
44
57
|
|
45
58
|
Opal::RSpec::CoreSpecLoader.rake_tasks_for(:rspec_core_specs)
|
data/config.ru
CHANGED
@@ -2,11 +2,14 @@ require 'opal/rspec'
|
|
2
2
|
|
3
3
|
Opal::Processor.source_map_enabled = false
|
4
4
|
|
5
|
-
sprockets_env = Opal::RSpec::SprocketsEnvironment.new(spec_pattern='spec/opal/**/*_spec.{rb,opal}'
|
5
|
+
sprockets_env = Opal::RSpec::SprocketsEnvironment.new(spec_pattern='spec/opal/**/*_spec.{rb,opal}',
|
6
|
+
spec_exclude_pattern=nil,
|
7
|
+
spec_files=nil,
|
8
|
+
default_path='spec/opal')
|
6
9
|
run Opal::Server.new(sprockets: sprockets_env) { |s|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
}
|
10
|
+
s.main = 'sprockets_runner_js_errors'
|
11
|
+
# sprockets_runner_js_errors will not be in the opal load path by default
|
12
|
+
s.append_path 'spec/mri/integration/rack'
|
13
|
+
sprockets_env.add_spec_paths_to_sprockets
|
14
|
+
s.debug = ENV['OPAL_DEBUG']
|
15
|
+
}
|
@@ -13,7 +13,9 @@ module Opal
|
|
13
13
|
|
14
14
|
def get_opal_spec_requires
|
15
15
|
@locator.get_opal_spec_requires.map do |file|
|
16
|
-
|
16
|
+
asset = find_asset(file)
|
17
|
+
raise "Unable to find asset for file #{file} within load paths #{paths}. Check your load path/file specification." unless asset
|
18
|
+
logical_path = asset.logical_path
|
17
19
|
# These will go directly into require '...' statements in Opal, so need to trim extensions
|
18
20
|
logical_path.sub File.extname(logical_path), ''
|
19
21
|
end
|
@@ -1,67 +1,31 @@
|
|
1
1
|
require 'pathname'
|
2
|
+
# require the bundled RSpec's file and don't rely on the load path in case opal-rspec is included in a project's
|
3
|
+
# Gemfile without rspec also being in the Gemfile
|
4
|
+
require_relative '../../../rspec-core/lib/rspec/core/ruby_project'
|
2
5
|
|
3
6
|
module Opal
|
4
7
|
module RSpec
|
5
8
|
class PreRackLocator
|
9
|
+
include ::RSpec::Core::RubyProject
|
10
|
+
|
6
11
|
DEFAULT_PATTERN = 'spec/**/*_spec.{rb,opal}'
|
12
|
+
DEFAULT_DEFAULT_PATH = 'spec'
|
7
13
|
|
8
|
-
attr_accessor :spec_pattern, :spec_exclude_pattern, :spec_files
|
14
|
+
attr_accessor :spec_pattern, :spec_exclude_pattern, :spec_files, :default_path
|
9
15
|
|
10
|
-
def initialize(spec_pattern=nil, spec_exclude_pattern=nil, spec_files=nil)
|
16
|
+
def initialize(spec_pattern=nil, spec_exclude_pattern=nil, spec_files=nil, default_path=nil)
|
11
17
|
@spec_pattern = spec_pattern || DEFAULT_PATTERN
|
12
18
|
@spec_exclude_pattern = spec_exclude_pattern
|
13
19
|
@spec_files = spec_files
|
20
|
+
@default_path = default_path || DEFAULT_DEFAULT_PATH
|
14
21
|
end
|
15
22
|
|
16
|
-
def
|
17
|
-
|
18
|
-
# Want to get the smallest # of load paths that's common between our patterns
|
19
|
-
array_or_single = base_paths.inject do |path1, path2|
|
20
|
-
with_common_paths_replaced path1, path2
|
21
|
-
end
|
22
|
-
[*array_or_single]
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
def strip_globs_from_patterns
|
28
|
-
# only using spec_pattern here since we only need paths for inclusion
|
29
|
-
[*spec_pattern].map do |each_pattern|
|
30
|
-
glob_portion = /[\*\?\[\{].*/.match each_pattern
|
31
|
-
path = glob_portion ? each_pattern.sub(glob_portion.to_s, '') : each_pattern
|
32
|
-
raise "Unable to identify a single root directory/file in the pattern #{each_pattern}. Please adjust glob" unless File.exist?(path)
|
33
|
-
path = Pathname.new path
|
34
|
-
# in case a filename was used as a pattern
|
35
|
-
path.directory? ? path : path.dirname
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def get_files_directories
|
40
|
-
spec_files.map do |file|
|
41
|
-
Pathname.new(file).dirname
|
42
|
-
end.uniq
|
23
|
+
def determine_root
|
24
|
+
find_first_parent_containing(@default_path) || '.'
|
43
25
|
end
|
44
26
|
|
45
|
-
def
|
46
|
-
|
47
|
-
replaced = [*existing_paths].map do |path|
|
48
|
-
match = nil
|
49
|
-
path.ascend do |each_level|
|
50
|
-
new_path.ascend do |each_other_level|
|
51
|
-
match = each_level if each_level.expand_path == each_other_level.expand_path
|
52
|
-
break if match
|
53
|
-
end
|
54
|
-
break if match
|
55
|
-
end
|
56
|
-
if match
|
57
|
-
new_path_covered = true
|
58
|
-
match
|
59
|
-
else
|
60
|
-
path
|
61
|
-
end
|
62
|
-
end
|
63
|
-
replaced << new_path unless new_path_covered
|
64
|
-
replaced.uniq
|
27
|
+
def get_spec_load_paths
|
28
|
+
[@default_path].map { |dir| File.join(root, dir) }
|
65
29
|
end
|
66
30
|
end
|
67
31
|
end
|
data/lib/opal/rspec/rake_task.rb
CHANGED
@@ -11,7 +11,7 @@ module Opal
|
|
11
11
|
PORT = 9999
|
12
12
|
URL = "http://localhost:#{PORT}/"
|
13
13
|
|
14
|
-
attr_accessor :pattern, :exclude_pattern, :files, :runner, :timeout
|
14
|
+
attr_accessor :pattern, :exclude_pattern, :files, :default_path, :runner, :timeout
|
15
15
|
|
16
16
|
def launch_phantom(timeout_value)
|
17
17
|
command_line = %Q{phantomjs #{RUNNER} "#{URL}"#{timeout_value ? " #{timeout_value}" : ''}}
|
@@ -93,6 +93,7 @@ module Opal
|
|
93
93
|
sprockets_env.spec_pattern = self.pattern if self.pattern
|
94
94
|
sprockets_env.spec_exclude_pattern = self.exclude_pattern
|
95
95
|
sprockets_env.spec_files = self.files
|
96
|
+
sprockets_env.default_path = self.default_path if self.default_path
|
96
97
|
raise 'Cannot supply both a pattern and files!' if self.files and self.pattern
|
97
98
|
sprockets_env.add_spec_paths_to_sprockets
|
98
99
|
}
|
@@ -112,14 +113,8 @@ module Opal
|
|
112
113
|
wait_for_server
|
113
114
|
is_phantom = runner == :phantom
|
114
115
|
if is_phantom
|
115
|
-
if `phantomjs -v`.
|
116
|
-
warn
|
117
|
-
Only PhantomJS v1 is currently supported,
|
118
|
-
if you're using homebrew on OSX you can switch version with:
|
119
|
-
|
120
|
-
brew switch phantomjs 1.9.8
|
121
|
-
|
122
|
-
WARN
|
116
|
+
if `phantomjs -v`.nil?
|
117
|
+
warn "Could not find phantomjs command"
|
123
118
|
exit 1
|
124
119
|
end
|
125
120
|
end
|
@@ -16,10 +16,12 @@ module Opal
|
|
16
16
|
:spec_exclude_pattern=,
|
17
17
|
:spec_exclude_pattern,
|
18
18
|
:spec_files=,
|
19
|
-
:spec_files
|
19
|
+
:spec_files,
|
20
|
+
:default_path=,
|
21
|
+
:default_path
|
20
22
|
|
21
|
-
def initialize(spec_pattern=nil, spec_exclude_pattern=nil, spec_files=nil)
|
22
|
-
@locator = RSpec::PreRackLocator.new spec_pattern, spec_exclude_pattern, spec_files
|
23
|
+
def initialize(spec_pattern=nil, spec_exclude_pattern=nil, spec_files=nil, default_path=nil)
|
24
|
+
@locator = RSpec::PreRackLocator.new spec_pattern, spec_exclude_pattern, spec_files, default_path
|
23
25
|
super()
|
24
26
|
end
|
25
27
|
|
data/lib/opal/rspec/version.rb
CHANGED
@@ -31,8 +31,16 @@ module Opal
|
|
31
31
|
`#@native.className`
|
32
32
|
end
|
33
33
|
|
34
|
-
def get_child_by_tag_name(tag)
|
35
|
-
|
34
|
+
def get_child_by_tag_name(tag, index=0)
|
35
|
+
elements = `#@native.getElementsByTagName(#{tag})`
|
36
|
+
# is an HTMLCollection, not an array
|
37
|
+
element_array = []
|
38
|
+
%x{
|
39
|
+
for (var i=0; i < #{elements}.length; i++) {
|
40
|
+
#{element_array}.push(#{elements}[i]);
|
41
|
+
}
|
42
|
+
}
|
43
|
+
Element.new(element_array[index])
|
36
44
|
end
|
37
45
|
|
38
46
|
def class_name=(name)
|
@@ -47,6 +55,10 @@ module Opal
|
|
47
55
|
`#@native.outerHTML`
|
48
56
|
end
|
49
57
|
|
58
|
+
def on_click=(lambda)
|
59
|
+
`#@native.onclick = #{lambda}`
|
60
|
+
end
|
61
|
+
|
50
62
|
def html=(html)
|
51
63
|
`#@native.innerHTML = #{html}`
|
52
64
|
end
|
@@ -24,8 +24,12 @@ module Opal
|
|
24
24
|
@root_node = Element.klass 'results'
|
25
25
|
end
|
26
26
|
|
27
|
+
def current_node
|
28
|
+
@group_stack.last ? @group_stack.last : @root_node
|
29
|
+
end
|
30
|
+
|
27
31
|
def flush_output
|
28
|
-
node =
|
32
|
+
node = current_node
|
29
33
|
new_node = Element.from_string(@output.string)
|
30
34
|
node.append new_node
|
31
35
|
reset_output
|
@@ -38,7 +42,7 @@ module Opal
|
|
38
42
|
def print_example_group_start(group_id, description, number_of_parents)
|
39
43
|
super
|
40
44
|
@output.puts '</dl></div>'
|
41
|
-
parent_node =
|
45
|
+
parent_node = current_node
|
42
46
|
new_node = Element.from_string(@output.string)
|
43
47
|
reset_output
|
44
48
|
parent_node << new_node
|
@@ -60,6 +64,14 @@ module Opal
|
|
60
64
|
def print_example_failed(pending_fixed, description, run_time, failure_id, exception, extra_content, escape_backtrace=false)
|
61
65
|
super
|
62
66
|
flush_output
|
67
|
+
example_we_just_wrote = current_node.get_child_by_tag_name('dd', index=-1)
|
68
|
+
dump_message = lambda do
|
69
|
+
puts "Exception for example '#{description}'\n#{exception[:backtrace]}"
|
70
|
+
false
|
71
|
+
end
|
72
|
+
button = Element.from_string('<form><button type="button">Console</button></form>')
|
73
|
+
button.on_click = dump_message
|
74
|
+
example_we_just_wrote << button
|
63
75
|
end
|
64
76
|
|
65
77
|
def print_example_pending(description, pending_message)
|
@@ -6,10 +6,11 @@ require_relative 'temp_dir_helper'
|
|
6
6
|
describe Opal::RSpec::CachedEnvironment do
|
7
7
|
let(:pattern) { nil }
|
8
8
|
let(:exclude_pattern) { nil }
|
9
|
+
let(:default_path) { nil }
|
9
10
|
let(:files) { nil }
|
10
11
|
include_context :temp_dir
|
11
12
|
|
12
|
-
let(:original_env) { Opal::RSpec::SprocketsEnvironment.new pattern, exclude_pattern, files }
|
13
|
+
let(:original_env) { Opal::RSpec::SprocketsEnvironment.new pattern, exclude_pattern, files, default_path }
|
13
14
|
|
14
15
|
subject(:env) do
|
15
16
|
# in subject to allow contexts to execute before logic
|
@@ -20,54 +21,35 @@ describe Opal::RSpec::CachedEnvironment do
|
|
20
21
|
describe '#get_opal_spec_requires' do
|
21
22
|
subject { env.get_opal_spec_requires.sort }
|
22
23
|
|
23
|
-
context '
|
24
|
+
context 'no default path set' do
|
24
25
|
before do
|
25
26
|
create_dummy_spec_files 'spec/foobar/dummy_spec.rb', 'spec/foobar/ignored_spec.opal'
|
26
27
|
end
|
27
28
|
|
28
29
|
let(:pattern) { 'spec/foobar/**/*_spec.rb' }
|
29
30
|
|
30
|
-
it { is_expected.to eq ['dummy_spec'] }
|
31
|
+
it { is_expected.to eq ['foobar/dummy_spec'] }
|
31
32
|
end
|
32
33
|
|
33
|
-
context '
|
34
|
+
context 'default path set' do
|
34
35
|
before do
|
35
|
-
create_dummy_spec_files 'spec/foobar/dummy_spec.rb', 'spec/
|
36
|
-
end
|
37
|
-
|
38
|
-
let(:pattern) { ['spec/foobar/**/*y_spec.rb', 'spec/noway/**/*_spec.rb'] }
|
39
|
-
|
40
|
-
it { is_expected.to eq ['foobar/dummy_spec', 'noway/other_spec'] }
|
41
|
-
end
|
42
|
-
|
43
|
-
context '2 paths, different root' do
|
44
|
-
before do
|
45
|
-
create_dummy_spec_files 'spec/foobar/dummy_spec.rb', 'other_path/other_spec.rb'
|
46
|
-
end
|
47
|
-
|
48
|
-
let(:pattern) { ['spec/foobar/**/*_spec.rb', 'other_path/**/*.rb'] }
|
49
|
-
|
50
|
-
it { is_expected.to eq ['dummy_spec', 'other_spec'] }
|
51
|
-
end
|
52
|
-
|
53
|
-
context 'specs in different paths, same name in middle dirs' do
|
54
|
-
before do
|
55
|
-
create_dummy_spec_files 'foobar/spec/something/dummy_spec.rb', 'spec/foobar/other_spec.rb'
|
36
|
+
create_dummy_spec_files 'spec/foobar/dummy_spec.rb', 'spec/foobar/ignored_spec.opal'
|
56
37
|
end
|
57
38
|
|
58
|
-
let(:pattern) {
|
39
|
+
let(:pattern) { 'spec/foobar/**/*_spec.rb' }
|
40
|
+
let(:default_path) { 'spec/foobar' }
|
59
41
|
|
60
|
-
it { is_expected.to eq ['
|
42
|
+
it { is_expected.to eq ['dummy_spec'] }
|
61
43
|
end
|
62
44
|
|
63
|
-
context '
|
45
|
+
context 'multiple pattern' do
|
64
46
|
before do
|
65
|
-
create_dummy_spec_files 'spec/foobar/
|
47
|
+
create_dummy_spec_files 'spec/foobar/hello1_spec.rb', 'spec/foobar/hello2_spec.rb', 'spec/foobar/bye1_spec.rb', 'spec/foobar/bye2_spec.rb'
|
66
48
|
end
|
67
49
|
|
68
|
-
let(:
|
50
|
+
let(:pattern) { %w(**/*/*1_spec.rb **/*/bye*_spec.rb) }
|
69
51
|
|
70
|
-
it { is_expected.to eq
|
52
|
+
it { is_expected.to eq %w(foobar/bye1_spec foobar/bye2_spec foobar/hello1_spec) }
|
71
53
|
end
|
72
54
|
|
73
55
|
context 'exclude pattern' do
|
@@ -80,11 +62,11 @@ describe Opal::RSpec::CachedEnvironment do
|
|
80
62
|
context 'single' do
|
81
63
|
let(:exclude_pattern) { '**/*/*1_spec.rb' }
|
82
64
|
|
83
|
-
it { is_expected.to eq
|
65
|
+
it { is_expected.to eq %w(foobar/bye2_spec foobar/hello2_spec) }
|
84
66
|
end
|
85
67
|
|
86
68
|
context 'multiple' do
|
87
|
-
let(:exclude_pattern) {
|
69
|
+
let(:exclude_pattern) { %w(**/*/*1_spec.rb **/*/bye*_spec.rb) }
|
88
70
|
|
89
71
|
it { is_expected.to eq ['foobar/hello2_spec'] }
|
90
72
|
end
|
@@ -97,7 +79,7 @@ describe Opal::RSpec::CachedEnvironment do
|
|
97
79
|
|
98
80
|
let(:files) { FileList['spec/**/h*_spec.rb'] }
|
99
81
|
|
100
|
-
it { is_expected.to eq
|
82
|
+
it { is_expected.to eq %w(foobar/hello1_spec foobar/hello2_spec) }
|
101
83
|
end
|
102
84
|
end
|
103
85
|
end
|
@@ -164,9 +164,26 @@ describe Opal::RSpec::RakeTask do
|
|
164
164
|
end
|
165
165
|
|
166
166
|
context 'pattern' do
|
167
|
+
let(:task_definition) do
|
168
|
+
Opal::RSpec::RakeTask.new(task_name) do |_, task|
|
169
|
+
task.pattern = 'spec/other/**/*_spec.rb'
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
before do
|
174
|
+
create_dummy_spec_files 'spec/other/dummy_spec.rb'
|
175
|
+
end
|
176
|
+
|
177
|
+
it { is_expected.to have_attributes pattern: 'spec/other/**/*_spec.rb' }
|
178
|
+
it { is_expected.to append_opal_path 'spec' }
|
179
|
+
it { is_expected.to require_opal_specs eq ['other/dummy_spec'] }
|
180
|
+
end
|
181
|
+
|
182
|
+
context 'default path' do
|
167
183
|
let(:task_definition) do
|
168
184
|
Opal::RSpec::RakeTask.new(task_name) do |server, task|
|
169
185
|
task.pattern = 'spec/other/**/*_spec.rb'
|
186
|
+
task.default_path = 'spec/other'
|
170
187
|
end
|
171
188
|
end
|
172
189
|
|
@@ -182,7 +199,7 @@ describe Opal::RSpec::RakeTask do
|
|
182
199
|
|
183
200
|
context 'files' do
|
184
201
|
let(:task_definition) do
|
185
|
-
Opal::RSpec::RakeTask.new(task_name) do |
|
202
|
+
Opal::RSpec::RakeTask.new(task_name) do |_, task|
|
186
203
|
task.files = FileList['spec/other/**/*_spec.rb']
|
187
204
|
end
|
188
205
|
end
|
@@ -192,16 +209,15 @@ describe Opal::RSpec::RakeTask do
|
|
192
209
|
end
|
193
210
|
|
194
211
|
it { is_expected.to have_attributes files: FileList['spec/other/**/*_spec.rb'] }
|
195
|
-
it { is_expected.
|
196
|
-
it { is_expected.to
|
197
|
-
it { is_expected.to require_opal_specs eq ['dummy_spec'] }
|
212
|
+
it { is_expected.to append_opal_path 'spec' }
|
213
|
+
it { is_expected.to require_opal_specs eq ['other/dummy_spec'] }
|
198
214
|
end
|
199
215
|
|
200
216
|
context 'pattern and files' do
|
201
217
|
let(:expected_to_run) { false }
|
202
218
|
|
203
219
|
let(:task_definition) do
|
204
|
-
Opal::RSpec::RakeTask.new(task_name) do |
|
220
|
+
Opal::RSpec::RakeTask.new(task_name) do |_, task|
|
205
221
|
task.files = FileList['spec/other/**/*_spec.rb', 'util/**/*.rb']
|
206
222
|
task.pattern = 'spec/opal/**/*hooks_spec.rb'
|
207
223
|
end
|
@@ -6,89 +6,50 @@ describe Opal::RSpec::SprocketsEnvironment do
|
|
6
6
|
include_context :temp_dir
|
7
7
|
let(:args) { [] }
|
8
8
|
subject(:env) { Opal::RSpec::SprocketsEnvironment.new *args }
|
9
|
-
|
9
|
+
|
10
10
|
RSpec::Matchers.define :have_pathnames do |expected|
|
11
|
-
expected = expected.map {|p| File.expand_path(p) }
|
12
|
-
|
11
|
+
expected = expected.map { |p| File.expand_path(p) }
|
12
|
+
|
13
13
|
match do |actual|
|
14
14
|
actual == expected
|
15
15
|
end
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
describe '#cached' do
|
19
19
|
subject { env.cached }
|
20
|
-
|
20
|
+
|
21
21
|
it { is_expected.to be_a ::Opal::RSpec::CachedEnvironment }
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
describe '#add_spec_paths_to_sprockets' do
|
25
|
-
let(:args) { [pattern] }
|
26
|
-
|
25
|
+
let(:args) { [pattern, nil, nil, default_path] }
|
26
|
+
let(:default_path) { nil }
|
27
|
+
|
27
28
|
subject do
|
28
29
|
# in subject to allow contexts to execute before logic
|
29
30
|
env.add_spec_paths_to_sprockets
|
30
31
|
env.paths.sort
|
31
32
|
end
|
32
|
-
|
33
|
-
context '
|
33
|
+
|
34
|
+
context 'default path not set' do
|
34
35
|
before do
|
35
36
|
create_dummy_spec_files 'spec/foobar/dummy_spec.rb', 'spec/foobar/ignored_spec.opal'
|
36
37
|
end
|
37
|
-
|
38
|
+
|
38
39
|
let(:pattern) { 'spec/foobar/**/*_spec.rb' }
|
39
|
-
|
40
|
-
it { is_expected.to have_pathnames ['spec/foobar/'] }
|
41
|
-
end
|
42
|
-
|
43
|
-
context 'multiple patterns' do
|
44
|
-
before do
|
45
|
-
create_dummy_spec_files 'spec/foobar/dummy_spec.rb', 'spec/foobar/ignored_spec.opal'
|
46
|
-
end
|
47
|
-
|
48
|
-
let(:pattern) { ['spec/foobar/**/*_spec.rb', 'spec/foobar/**/*_spec.opal'] }
|
49
|
-
|
50
|
-
it { is_expected.to have_pathnames ['spec/foobar/'] }
|
51
|
-
end
|
52
|
-
|
53
|
-
context 'specs in different paths, same root' do
|
54
|
-
before do
|
55
|
-
create_dummy_spec_files 'spec/foobar/dummy_spec.rb', 'spec/noway/other_spec.rb'
|
56
|
-
end
|
57
|
-
|
58
|
-
let(:pattern) { ['spec/foobar/**/*y_spec.rb', 'spec/noway/**/*_spec.rb'] }
|
59
|
-
|
40
|
+
|
60
41
|
it { is_expected.to have_pathnames ['spec'] }
|
61
42
|
end
|
62
|
-
|
63
|
-
context '
|
64
|
-
before do
|
65
|
-
create_dummy_spec_files 'spec/foobar/dummy_spec.rb', 'other_path/other_spec.rb'
|
66
|
-
end
|
67
|
-
|
68
|
-
let(:pattern) { ['spec/foobar/**/*_spec.rb', 'other_path/**/*.rb'] }
|
69
|
-
|
70
|
-
it { is_expected.to have_pathnames ['other_path/', 'spec/foobar/'] }
|
71
|
-
end
|
72
|
-
|
73
|
-
context 'specs in different paths, same name in middle dirs' do
|
43
|
+
|
44
|
+
context 'default path set' do
|
74
45
|
before do
|
75
|
-
create_dummy_spec_files '
|
46
|
+
create_dummy_spec_files 'spec/foobar/dummy_spec.rb', 'spec/foobar/ignored_spec.opal'
|
76
47
|
end
|
77
|
-
|
78
|
-
let(:pattern) {
|
79
|
-
|
80
|
-
|
48
|
+
|
49
|
+
let(:pattern) { 'spec/foobar/**/*_spec.rb' }
|
50
|
+
let(:default_path) { 'spec/foobar' }
|
51
|
+
|
52
|
+
it { is_expected.to have_pathnames ['spec/foobar'] }
|
81
53
|
end
|
82
|
-
|
83
|
-
context 'absolute path and relative path that are not in the same tree' do
|
84
|
-
before do
|
85
|
-
create_dummy_spec_files 'spec/foobar/dummy_spec.rb', 'stuff/bar/other_spec.rb'
|
86
|
-
end
|
87
|
-
|
88
|
-
let(:files) { FileList['spec/foobar/**/*_spec.rb', 'stuff/bar/other_spec.rb'] }
|
89
|
-
let(:args) { [nil, nil, files] }
|
90
|
-
|
91
|
-
it { is_expected.to have_pathnames ['spec/foobar', 'stuff/bar'] }
|
92
|
-
end
|
93
54
|
end
|
94
55
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
rspec_filter filter '#any_instance' do
|
2
2
|
filter '#any_instance when used after the test has finished restores the original behaviour, even if the expectation fails'
|
3
3
|
filter '#any_instance when used after the test has finished restores the original behavior of a stubbed method'
|
4
|
-
filter
|
4
|
+
filter('#any_instance when directed at a method defined on a superclass mocks the method correctly').unless { at_least_opal_0_9? }
|
5
5
|
filter '#any_instance when resetting post-verification existing method with stubbing private methods restores a stubbed private method after the spec is run'
|
6
6
|
filter '#any_instance when resetting post-verification existing method with expectations private methods restores a stubbed private method after the spec is run'
|
7
7
|
filter '#any_instance passing the receiver to the implementation block when configured to pass the instance an any instance stub does not pass the instance to and_call_original'
|
8
|
-
filter
|
9
|
-
filter
|
8
|
+
filter('#any_instance setting a message expectation with an expectation is set on a method that exists after any one instance has received a message fails if the method is invoked on a second instance').unless { at_least_opal_0_9? }
|
9
|
+
filter("#any_instance setting a message expectation with an expectation is set on a method which does not exist behaves as 'exactly one instance' fails if the method is invoked on a second instance").unless { at_least_opal_0_9? }
|
10
10
|
filter('#any_instance setting a message expectation works with a SimpleDelegator subclass').unless { at_least_opal_0_9? }
|
11
11
|
filter "#any_instance when stubbing behaves as 'every instance' handles freeze and duplication correctly"
|
12
12
|
filter "#any_instance when stubbing behaves as 'every instance' handles method restoration on subclasses"
|
@@ -102,14 +102,29 @@ module Opal
|
|
102
102
|
end
|
103
103
|
|
104
104
|
def append_additional_load_paths(server)
|
105
|
-
baseline = ['spec/rspec/shared']
|
105
|
+
baseline = [base_dir, 'spec/rspec/shared']
|
106
|
+
baseline += tmp_load_paths
|
106
107
|
(baseline + additional_load_paths).each { |p| server.append_path p }
|
107
108
|
end
|
108
109
|
|
110
|
+
def get_tmp_load_path_dir
|
111
|
+
dir = Dir.mktmpdir
|
112
|
+
at_exit do
|
113
|
+
FileUtils.remove_entry dir
|
114
|
+
end
|
115
|
+
# something was clearing this if it was added via Opal.append_path, so save it
|
116
|
+
tmp_load_paths << dir
|
117
|
+
dir
|
118
|
+
end
|
119
|
+
|
120
|
+
def tmp_load_paths
|
121
|
+
@tmp_load_paths ||= []
|
122
|
+
end
|
123
|
+
|
109
124
|
def replace_with_regex(regex, description, starting_file_set, files_to_replace)
|
110
125
|
fix_these_files = starting_file_set.select { |f| files_to_replace.any? { |r| r.match(f) } }
|
111
126
|
return starting_file_set unless fix_these_files.any?
|
112
|
-
dir =
|
127
|
+
dir = get_tmp_load_path_dir
|
113
128
|
missing = []
|
114
129
|
expressions = [*regex]
|
115
130
|
fixed_temp_files = fix_these_files.map do |path|
|
@@ -131,9 +146,6 @@ module Opal
|
|
131
146
|
missing << path unless matching
|
132
147
|
temp_filename
|
133
148
|
end
|
134
|
-
at_exit do
|
135
|
-
FileUtils.remove_entry dir
|
136
|
-
end
|
137
149
|
raise "Expected to #{description} in #{fix_these_files} but we didn't find any expressions in #{missing}. Check if RSpec has been upgraded" if missing.any?
|
138
150
|
files_we_left_alone = starting_file_set - fix_these_files
|
139
151
|
files_we_left_alone + fixed_temp_files
|
@@ -166,7 +178,7 @@ module Opal
|
|
166
178
|
bad_regex = /^(.*)\\$/
|
167
179
|
fix_these_files = files.select { |f| files_with_line_continue.any? { |regex| regex.match(f) } }
|
168
180
|
return files unless fix_these_files.any?
|
169
|
-
dir =
|
181
|
+
dir = get_tmp_load_path_dir
|
170
182
|
missing = []
|
171
183
|
fixed_temp_files = fix_these_files.map do |path|
|
172
184
|
temp_filename = File.join dir, File.basename(path)
|
@@ -192,9 +204,6 @@ module Opal
|
|
192
204
|
missing << path unless found_blackslash
|
193
205
|
temp_filename
|
194
206
|
end
|
195
|
-
at_exit do
|
196
|
-
FileUtils.remove_entry dir
|
197
|
-
end
|
198
207
|
raise "Expected to fix blackslash continuation in #{fix_these_files} but we didn't find any backslashes in #{missing}. Check if RSpec has been upgraded (maybe those blackslashes are gone??)" if missing.any?
|
199
208
|
files_we_left_alone = files - fix_these_files
|
200
209
|
files_we_left_alone + fixed_temp_files
|
@@ -236,6 +245,7 @@ module Opal
|
|
236
245
|
task.timeout = 80000
|
237
246
|
stub_requires
|
238
247
|
task.files = sub_in_files
|
248
|
+
task.default_path = default_path
|
239
249
|
append_additional_load_paths server
|
240
250
|
server.debug = ENV['OPAL_DEBUG']
|
241
251
|
end
|
@@ -320,8 +330,8 @@ module Opal
|
|
320
330
|
rack.run Opal::Server.new(sprockets: sprockets_env) { |s|
|
321
331
|
s.main = 'opal/rspec/sprockets_runner'
|
322
332
|
stub_requires
|
323
|
-
sprockets_env.add_spec_paths_to_sprockets
|
324
333
|
append_additional_load_paths s
|
334
|
+
sprockets_env.add_spec_paths_to_sprockets
|
325
335
|
s.debug = ENV['OPAL_DEBUG']
|
326
336
|
}
|
327
337
|
end
|
data/vendor/spec_runner.js
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
/*
|
2
2
|
* Test runner for phantomjs
|
3
3
|
*/
|
4
|
-
var
|
4
|
+
var system = require('system');
|
5
|
+
var args = system.args.slice(1);
|
5
6
|
var page = require('webpage').create();
|
6
7
|
|
7
8
|
page.onConsoleMessage = function(msg) {
|
@@ -14,7 +15,6 @@ page.onInitialized = function() {
|
|
14
15
|
});
|
15
16
|
};
|
16
17
|
|
17
|
-
var system = require('system');
|
18
18
|
page.onCallback = function(data) {
|
19
19
|
switch (data[0]) {
|
20
20
|
case 'stdout':
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: opal-rspec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.0
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Beynon
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-12-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: opal
|
@@ -761,12 +761,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
761
761
|
version: '0'
|
762
762
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
763
763
|
requirements:
|
764
|
-
- - "
|
764
|
+
- - ">="
|
765
765
|
- !ruby/object:Gem::Version
|
766
|
-
version:
|
766
|
+
version: '0'
|
767
767
|
requirements: []
|
768
768
|
rubyforge_project:
|
769
|
-
rubygems_version: 2.4.
|
769
|
+
rubygems_version: 2.4.8
|
770
770
|
signing_key:
|
771
771
|
specification_version: 4
|
772
772
|
summary: RSpec for Opal
|