opal-rspec 1.0.0 → 1.1.0.alpha1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/build.yml +1 -1
- data/CHANGELOG.md +13 -0
- data/Gemfile +2 -1
- data/README.md +10 -1
- data/exe/opal-rspec +11 -69
- data/lib/opal/rspec/configuration_parser.rb +46 -0
- data/lib/opal/rspec/locator.rb +31 -7
- data/lib/opal/rspec/project_initializer/.rspec-opal +0 -1
- data/lib/opal/rspec/project_initializer/spec-opal/spec_helper.rb +85 -0
- data/lib/opal/rspec/project_initializer.rb +11 -0
- data/lib/opal/rspec/runner.rb +70 -12
- data/lib/opal/rspec/version.rb +6 -1
- data/lib/opal/rspec.rb +24 -24
- data/lib-opal/opal/rspec/browser.rb +5 -1
- data/lib-opal/opal/rspec/fixes/rspec/core/configuration.rb +96 -4
- data/lib-opal/opal/rspec/fixes/rspec/core/ordering/random.rb +2 -0
- data/lib-opal/opal/rspec/formatter/document_io.rb +2 -0
- data/lib-opal/opal/rspec/formatter/element.rb +2 -0
- data/lib-opal/opal/rspec/formatter/html_printer.rb +2 -0
- data/lib-opal/opal/rspec/sprockets_runner.rb.erb +3 -1
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 95ab0afeb6b8db964c718d2716cd7b4f91cf022dc38eb33b7271219a7f277e8d
|
4
|
+
data.tar.gz: c256b94c07aae78d0fab3407aad4cadc5f23f2d60662551056e1c65ad70d4a20
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0567fb3f9293fbcafa0c6990dcdfb36bf2e40936ff75b6f8879a798628c3a9384842e95da555851a9ff9abb876409d148434e066e8071bd62a525670760ed914
|
7
|
+
data.tar.gz: 0ee3ad1ace7524f5daf1025a7671309d23905bd9f6f87c280a297b8817c4292943a6a773cbe7c4dd208cf70836b5f197e2cec95924912880b13119136bc64419
|
data/.github/workflows/build.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# Opal-RSpec Changelog
|
2
2
|
|
3
|
+
## 1.1.0.alpha1 - 2023-09-16
|
4
|
+
|
5
|
+
- Support Opal headless browser runners
|
6
|
+
|
7
|
+
- (Almost) full support for `rspec` CLI util (which we run using `opal-rspec` command)
|
8
|
+
* Focus works, you can type `opal-rspec spec-opal-passing/tautology_spec.rb:8` to select a given test
|
9
|
+
* Most of other command line switches of `opal-rspec` work
|
10
|
+
* You can use a `.rspec-opal` configuration file akin to `.rspec` with the regular RSpec
|
11
|
+
* Just like with RSpec, switches set in this file propagate everywhere (eg. Rake task), so this is from now a prefered place to set up paths, etc.
|
12
|
+
|
13
|
+
- Compatibility for upcoming Opal v1.8
|
14
|
+
|
15
|
+
|
3
16
|
## 1.0.0 - 2022-11-24
|
4
17
|
|
5
18
|
- Drop support for anything below Opal v1.6.alpha1
|
data/Gemfile
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
gemspec
|
3
3
|
|
4
|
-
unless Dir['rspec{,-{core,expectations,mocks,support}}/upstream'].any?
|
4
|
+
unless Dir[__dir__ + '/rspec{,-{core,expectations,mocks,support}}/upstream'].any?
|
5
5
|
raise 'Run: "git submodule update --init" to get RSpec sources'
|
6
6
|
end
|
7
7
|
|
@@ -26,3 +26,4 @@ end
|
|
26
26
|
gem 'opal-sprockets', '>=1.0'
|
27
27
|
|
28
28
|
gem 'puma'
|
29
|
+
gem 'rack', '<3'
|
data/README.md
CHANGED
@@ -135,6 +135,10 @@ end
|
|
135
135
|
|
136
136
|
If you don't specify a runner using `task.runner`, a default one is Node. In this case you can also use `RUNNER=chrome` to run a particular test with Headless Chromium.
|
137
137
|
|
138
|
+
*(since v1.1.0)*
|
139
|
+
|
140
|
+
You can also put default options into an `.rspec-opal` file, akin to how RSpec works. Those options will be propagated to Rake task, invocations of `Opal::RSpec::Runner` and also the `opal-rspec` command line tool.
|
141
|
+
|
138
142
|
### Run specs in Node.js
|
139
143
|
|
140
144
|
Same options as above, you can use the `RUNNER=node` environment variable
|
@@ -157,6 +161,11 @@ Opal::RSpec::RakeTask.new(:default) do |server, task|
|
|
157
161
|
end
|
158
162
|
```
|
159
163
|
|
164
|
+
*(since v1.1.0)*
|
165
|
+
|
166
|
+
While `server` value runs a server, you can here supply also respectively
|
167
|
+
`chrome`, `firefox` or `safari` to run the test using a headless browser.
|
168
|
+
|
160
169
|
### Run specs in a browser (Sprockets, deprecated)
|
161
170
|
|
162
171
|
`opal-rspec` can use sprockets to build and serve specs over a simple rack
|
@@ -347,7 +356,7 @@ When updating the RSpec versions, after updating the submodule revisions, you ma
|
|
347
356
|
|
348
357
|
(The MIT License)
|
349
358
|
|
350
|
-
Copyright (C) 2022 by hmdne and the Opal contributors
|
359
|
+
Copyright (C) 2022-2023 by hmdne and the Opal contributors
|
351
360
|
Copyright (C) 2015 by Brady Wied
|
352
361
|
Copyright (C) 2013 by Adam Beynon
|
353
362
|
|
data/exe/opal-rspec
CHANGED
@@ -4,81 +4,23 @@
|
|
4
4
|
|
5
5
|
require 'rake'
|
6
6
|
require 'opal/rspec/runner'
|
7
|
+
require 'opal/rspec/configuration_parser'
|
7
8
|
|
8
9
|
require 'shellwords'
|
9
|
-
require 'optparse'
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
parser.on('--init', 'Initialize your project with Opal-RSpec.') do |_cmd|
|
14
|
-
Opal::RSpec::ProjectInitializer.new.run
|
15
|
-
exit
|
16
|
-
end
|
17
|
-
|
18
|
-
parser.on('-c', '--[no-]color', '--[no-]colour', 'Enable color in the output.') do |o|
|
19
|
-
options[:color] = o
|
20
|
-
end
|
21
|
-
|
22
|
-
parser.on('-f', '--format FORMATTER', 'Choose a formatter.',
|
23
|
-
' [p]rogress (default - dots)',
|
24
|
-
' [d]ocumentation (group and example names)',
|
25
|
-
' [h]tml',
|
26
|
-
' [j]son',
|
27
|
-
' custom formatter class name') do |o|
|
28
|
-
options[:formatters] ||= []
|
29
|
-
options[:formatters] << [o]
|
30
|
-
end
|
31
|
-
|
32
|
-
parser.on('-r', '--require PATH', 'Require a file.') do |path|
|
33
|
-
options[:requires] ||= []
|
34
|
-
options[:requires] << path
|
35
|
-
end
|
36
|
-
|
37
|
-
parser.on('-I PATH', 'Specify PATH to add to $LOAD_PATH (may be used more than once).') do |dir|
|
38
|
-
options[:includes] ||= []
|
39
|
-
options[:includes] << dir
|
40
|
-
end
|
41
|
-
|
42
|
-
parser.on('-P', '--pattern PATTERN', 'Load files matching pattern (default: "spec-opal/**/*_spec.rb").') do |o|
|
43
|
-
options[:pattern] = o
|
44
|
-
end
|
45
|
-
|
46
|
-
parser.on('--default-path PATH', 'Set the default path where RSpec looks for examples (can',
|
47
|
-
' be a path to a file or a directory).') do |path|
|
48
|
-
options[:default_path] = path
|
49
|
-
end
|
50
|
-
|
51
|
-
parser.separator 'Opal specific options:'
|
52
|
-
|
53
|
-
parser.on('-R', '--runner NAME', 'Use a different JS runner (default is nodejs)') do |name|
|
54
|
-
options[:runner] = name
|
55
|
-
end
|
56
|
-
end.parse!
|
57
|
-
|
58
|
-
runner = Opal::RSpec::Runner.new do |server, config|
|
59
|
-
spec_opts = []
|
60
|
-
spec_opts += ['--color', options[:color]] if options[:color]
|
61
|
-
options[:requires].each {|req| spec_opts += ['-r', req]} if options[:requires]
|
62
|
-
raise "can accept only one formatter at this time" if options[:formatters] && options[:formatters].size != 1
|
63
|
-
spec_opts += ['--format', options[:formatters].flatten.first] if options[:formatters]
|
64
|
-
raw_files = ARGV
|
65
|
-
raw_files = ['spec-opal'] if raw_files.empty?
|
11
|
+
parser = Opal::RSpec::Core::Parser.new(ARGV)
|
12
|
+
options = parser.parse
|
66
13
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
else
|
73
|
-
raise "Can't stat path: #{file}"
|
74
|
-
end
|
14
|
+
case options[:runner]
|
15
|
+
when String, nil
|
16
|
+
runner = Opal::RSpec::Runner.new do |server, config|
|
17
|
+
config.runner = options.delete(:runner)
|
18
|
+
config.spec_opts = options
|
75
19
|
end
|
76
20
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
config.files = files
|
21
|
+
runner.run
|
22
|
+
else
|
23
|
+
exit options[:runner].(ARGV, $stderr, $stdout)
|
81
24
|
end
|
82
25
|
|
83
|
-
runner.run
|
84
26
|
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module Opal; module RSpec; module Core; end; end; end
|
4
|
+
# Load necessary files under Opal's namespace, so as not to conflict with RSpec if it's being loaded too.
|
5
|
+
# Later, we will monkey-patch those methods.
|
6
|
+
load __dir__ + "/../../../rspec-core/upstream/lib/rspec/core/invocations.rb", ::Opal
|
7
|
+
load __dir__ + "/../../../rspec-core/upstream/lib/rspec/core/option_parser.rb", ::Opal
|
8
|
+
|
9
|
+
class Opal::RSpec::Core::Parser
|
10
|
+
alias parser_before_opal parser
|
11
|
+
|
12
|
+
def parser(options)
|
13
|
+
parser_before_opal(options).tap do |parser|
|
14
|
+
parser.banner = "Usage: opal-rspec [options] [files or directories]\n\n"
|
15
|
+
|
16
|
+
parser.separator ''
|
17
|
+
parser.separator ' **** Opal specific options ****'
|
18
|
+
parser.separator ''
|
19
|
+
|
20
|
+
parser.on('-R', '--runner NAME', 'Use a different JS runner (default is nodejs)') do |name|
|
21
|
+
options[:runner] = name
|
22
|
+
end
|
23
|
+
|
24
|
+
parser.separator ''
|
25
|
+
parser.separator ' **** Help ****'
|
26
|
+
parser.separator ''
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Opal::RSpec::Core::Invocations::PrintVersion
|
32
|
+
alias call_before_opal call
|
33
|
+
|
34
|
+
def call(options, err, out)
|
35
|
+
exitcode = call_before_opal(options, err, out)
|
36
|
+
out.puts "Opal #{Opal::VERSION}"
|
37
|
+
out.puts " - opal-rspec #{Opal::RSpec::VERSION}"
|
38
|
+
exitcode
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
module Opal::RSpec::Support
|
43
|
+
def self.require_rspec_core(arg)
|
44
|
+
require "opal/rspec/"+arg
|
45
|
+
end
|
46
|
+
end
|
data/lib/opal/rspec/locator.rb
CHANGED
@@ -2,24 +2,31 @@ require 'pathname'
|
|
2
2
|
require 'rake'
|
3
3
|
# require the bundled RSpec's file and don't rely on the load path in case opal-rspec is included in a project's
|
4
4
|
# Gemfile without rspec also being in the Gemfile
|
5
|
-
|
5
|
+
load __dir__+'/../../../rspec-core/upstream/lib/rspec/core/ruby_project.rb', ::Opal
|
6
6
|
|
7
7
|
module Opal
|
8
8
|
module RSpec
|
9
9
|
class Locator
|
10
|
-
include ::RSpec::Core::RubyProject
|
10
|
+
include ::Opal::RSpec::Core::RubyProject
|
11
11
|
|
12
12
|
DEFAULT_GLOB = '**{,/*/**}/*_spec{.js,}.{rb,opal}'
|
13
|
-
DEFAULT_PATTERN = "spec-opal/#{DEFAULT_GLOB}"
|
14
13
|
DEFAULT_DEFAULT_PATH = 'spec-opal'
|
15
14
|
|
16
15
|
attr_accessor :spec_pattern, :spec_exclude_pattern, :spec_files, :default_path
|
17
16
|
|
18
17
|
def initialize(pattern: nil, exclude_pattern: nil, files: nil, default_path: nil)
|
19
|
-
@
|
20
|
-
@spec_exclude_pattern = exclude_pattern
|
18
|
+
@spec_exclude_pattern = Array(exclude_pattern)
|
21
19
|
@spec_files = files
|
22
20
|
@default_path = default_path || DEFAULT_DEFAULT_PATH
|
21
|
+
@spec_pattern = Array(pattern || DEFAULT_GLOB)
|
22
|
+
|
23
|
+
@spec_pattern = @spec_pattern.map do |pattern|
|
24
|
+
pattern.sub(/\A#{Regexp.escape(@default_path)}/, '')
|
25
|
+
end
|
26
|
+
|
27
|
+
@spec_exclude_pattern = @spec_exclude_pattern.map do |pattern|
|
28
|
+
pattern.sub(/\A#{Regexp.escape(@default_path)}/, '')
|
29
|
+
end
|
23
30
|
end
|
24
31
|
|
25
32
|
def determine_root
|
@@ -27,11 +34,28 @@ module Opal
|
|
27
34
|
end
|
28
35
|
|
29
36
|
def get_spec_load_paths
|
30
|
-
[
|
37
|
+
[File.join(root, @default_path)]
|
38
|
+
end
|
39
|
+
|
40
|
+
def get_matching_files_under(path: )
|
41
|
+
FileList[*@spec_pattern.map { |i| "#{path}/#{i}" }]
|
42
|
+
.exclude(*@spec_exclude_pattern.map { |i| "#{path}/#{i}" })
|
31
43
|
end
|
32
44
|
|
33
45
|
def get_opal_spec_requires
|
34
|
-
|
46
|
+
if !@spec_files || @spec_files.empty?
|
47
|
+
files = get_matching_files_under(path: @default_path)
|
48
|
+
else
|
49
|
+
files = @spec_files.map do |file|
|
50
|
+
file = file.split(/[\[:]/).first
|
51
|
+
if File.directory?(file)
|
52
|
+
get_matching_files_under(path: file).to_a
|
53
|
+
else
|
54
|
+
file
|
55
|
+
end
|
56
|
+
end.flatten
|
57
|
+
files = FileList[*files]
|
58
|
+
end
|
35
59
|
files.uniq.map { |file| File.expand_path file }
|
36
60
|
end
|
37
61
|
end
|
@@ -1,4 +1,88 @@
|
|
1
|
+
# This file was generated by the `opal-rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec-opal` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# The generated `.rspec-opal` file contains `--require spec_helper` which will cause
|
4
|
+
# this file to always be loaded, without a need to explicitly require it in any
|
5
|
+
# files.
|
6
|
+
#
|
7
|
+
# Given that it is always loaded, you are encouraged to keep this file as
|
8
|
+
# light-weight as possible. Requiring heavyweight dependencies from this file
|
9
|
+
# will add to the boot time of your test suite on EVERY test run, even for an
|
10
|
+
# individual file that may not need all of that loaded. Instead, consider making
|
11
|
+
# a separate helper file that requires the additional dependencies and performs
|
12
|
+
# the additional setup, and require it from the spec files that actually need
|
13
|
+
# it.
|
14
|
+
#
|
15
|
+
# See https://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
1
16
|
RSpec.configure do |config|
|
17
|
+
# rspec-expectations config goes here. You can use an alternate
|
18
|
+
# assertion/expectation library such as wrong or the stdlib/minitest
|
19
|
+
# assertions if you prefer.
|
20
|
+
config.expect_with :rspec do |expectations|
|
21
|
+
# This option will default to `true` in RSpec 4. It makes the `description`
|
22
|
+
# and `failure_message` of custom matchers include text for helper methods
|
23
|
+
# defined using `chain`, e.g.:
|
24
|
+
# be_bigger_than(2).and_smaller_than(4).description
|
25
|
+
# # => "be bigger than 2 and smaller than 4"
|
26
|
+
# ...rather than:
|
27
|
+
# # => "be bigger than 2"
|
28
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
29
|
+
end
|
30
|
+
|
31
|
+
# rspec-mocks config goes here. You can use an alternate test double
|
32
|
+
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
33
|
+
config.mock_with :rspec do |mocks|
|
34
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
35
|
+
# a real object. This is generally recommended, and will default to
|
36
|
+
# `true` in RSpec 4.
|
37
|
+
mocks.verify_partial_doubles = true
|
38
|
+
end
|
39
|
+
|
40
|
+
# This option will default to `:apply_to_host_groups` in RSpec 4 (and will
|
41
|
+
# have no way to turn it off -- the option exists only for backwards
|
42
|
+
# compatibility in RSpec 3). It causes shared context metadata to be
|
43
|
+
# inherited by the metadata hash of host groups and examples, rather than
|
44
|
+
# triggering implicit auto-inclusion in groups with matching metadata.
|
45
|
+
config.shared_context_metadata_behavior = :apply_to_host_groups
|
46
|
+
|
47
|
+
# The settings below are suggested to provide a good initial experience
|
48
|
+
# with RSpec, but feel free to customize to your heart's content.
|
49
|
+
=begin
|
50
|
+
# This allows you to limit a spec run to individual examples or groups
|
51
|
+
# you care about by tagging them with `:focus` metadata. When nothing
|
52
|
+
# is tagged with `:focus`, all examples get run. RSpec also provides
|
53
|
+
# aliases for `it`, `describe`, and `context` that include `:focus`
|
54
|
+
# metadata: `fit`, `fdescribe` and `fcontext`, respectively.
|
55
|
+
config.filter_run_when_matching :focus
|
56
|
+
|
57
|
+
# Allows RSpec to persist some state between runs in order to support
|
58
|
+
# the `--only-failures` and `--next-failure` CLI options. We recommend
|
59
|
+
# you configure your source control system to ignore this file.
|
60
|
+
config.example_status_persistence_file_path = "spec/examples.txt"
|
61
|
+
|
62
|
+
# Limits the available syntax to the non-monkey patched syntax that is
|
63
|
+
# recommended. For more details, see:
|
64
|
+
# https://relishapp.com/rspec/rspec-core/docs/configuration/zero-monkey-patching-mode
|
65
|
+
config.disable_monkey_patching!
|
66
|
+
|
67
|
+
# This setting enables warnings. It's recommended, but in some cases may
|
68
|
+
# be too noisy due to issues in dependencies.
|
69
|
+
config.warnings = true
|
70
|
+
|
71
|
+
# Many RSpec users commonly either run the entire suite or an individual
|
72
|
+
# file, and it's useful to allow more verbose output when running an
|
73
|
+
# individual spec file.
|
74
|
+
if config.files_to_run.one?
|
75
|
+
# Use the documentation formatter for detailed output,
|
76
|
+
# unless a formatter has already been configured
|
77
|
+
# (e.g. via a command-line flag).
|
78
|
+
config.default_formatter = "doc"
|
79
|
+
end
|
80
|
+
|
81
|
+
# Print the 10 slowest examples and example groups at the
|
82
|
+
# end of the spec run, to help surface which specs are running
|
83
|
+
# particularly slow.
|
84
|
+
config.profile_examples = 10
|
85
|
+
|
2
86
|
# Run specs in random order to surface order dependencies. If you find an
|
3
87
|
# order dependency and want to debug it, you can fix the order by providing
|
4
88
|
# the seed, which is printed after each run.
|
@@ -10,4 +94,5 @@ RSpec.configure do |config|
|
|
10
94
|
# test failures related to randomization by passing the same `--seed` value
|
11
95
|
# as the one that triggered the failure.
|
12
96
|
Kernel.srand config.seed
|
97
|
+
=end
|
13
98
|
end
|
@@ -19,6 +19,17 @@ module Opal
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def run
|
22
|
+
puts <<~EOF
|
23
|
+
** Do note, that Opal-RSpec defaults to the following paths:
|
24
|
+
** - config file: .rspec-opal
|
25
|
+
** - spec directory: spec-opal
|
26
|
+
** - program: lib-opal
|
27
|
+
**
|
28
|
+
** If you want to share Opal specs with Ruby specs, you will
|
29
|
+
** need to put the following into your .rspec-opal:
|
30
|
+
**
|
31
|
+
** -Ilib --default-path=spec
|
32
|
+
EOF
|
22
33
|
copy_template DOT_RSPEC_FILE
|
23
34
|
copy_template SPEC_HELPER_FILE
|
24
35
|
end
|
data/lib/opal/rspec/runner.rb
CHANGED
@@ -9,7 +9,24 @@ require 'opal/rspec/locator'
|
|
9
9
|
module Opal
|
10
10
|
module RSpec
|
11
11
|
class Runner
|
12
|
-
attr_accessor :
|
12
|
+
attr_accessor :runner, :arity_checking, :spec_opts, :cli_options, :files
|
13
|
+
|
14
|
+
# Delegate property changes to spec_opts
|
15
|
+
def self.spec_opts_accessor(*names)
|
16
|
+
names.each do |name|
|
17
|
+
define_method name do
|
18
|
+
spec_opts[name]
|
19
|
+
end
|
20
|
+
define_method :"#{name}=" do |value|
|
21
|
+
spec_opts[name] = value
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
spec_opts_accessor :libs, :requires, :pattern, :exclude_pattern, :default_path, :files_or_directories_to_run
|
27
|
+
|
28
|
+
alias files files_or_directories_to_run
|
29
|
+
alias files= files_or_directories_to_run=
|
13
30
|
|
14
31
|
def timeout= _
|
15
32
|
warn "deprecated: setting timeout has no effect"
|
@@ -33,11 +50,11 @@ module Opal
|
|
33
50
|
end
|
34
51
|
|
35
52
|
def requires
|
36
|
-
|
53
|
+
spec_opts[:requires] ||= []
|
37
54
|
end
|
38
55
|
|
39
56
|
def spec_opts
|
40
|
-
@spec_opts
|
57
|
+
@spec_opts = Opal::RSpec.convert_spec_opts(@spec_opts)
|
41
58
|
end
|
42
59
|
|
43
60
|
def get_load_asset_code(server)
|
@@ -80,9 +97,16 @@ module Opal
|
|
80
97
|
@legacy_server_proxy = LegacyServerProxy.new
|
81
98
|
block.call(@legacy_server_proxy, self) if block_given? # for compatibility
|
82
99
|
|
83
|
-
raise 'Cannot supply both a pattern and files!' if self.files
|
100
|
+
raise 'Cannot supply both a pattern and files!' if self.files \
|
101
|
+
&& !self.files.empty? \
|
102
|
+
&& self.pattern
|
84
103
|
|
85
|
-
|
104
|
+
append_opts_from_config_file
|
105
|
+
|
106
|
+
locator = ::Opal::RSpec::Locator.new pattern: self.pattern,
|
107
|
+
exclude_pattern: self.exclude_pattern,
|
108
|
+
files: self.files,
|
109
|
+
default_path: self.default_path
|
86
110
|
|
87
111
|
options = []
|
88
112
|
options << '--arity-check' if arity_checking?
|
@@ -93,21 +117,55 @@ module Opal
|
|
93
117
|
options << '--missing-require=ignore'
|
94
118
|
options += @legacy_server_proxy.to_cli_options
|
95
119
|
|
96
|
-
Opal.paths.
|
97
|
-
|
120
|
+
load_paths = [Opal.paths, locator.get_spec_load_paths, self.libs].compact.sum([]).uniq
|
121
|
+
|
122
|
+
load_paths.each { |p| options << "-I#{p}" }
|
98
123
|
requires.each { |p| options << "-r#{p}" }
|
99
|
-
locator.get_opal_spec_requires.each { |p| options << "-
|
124
|
+
locator.get_opal_spec_requires.each { |p| options << "-p#{p}" }
|
100
125
|
::Opal::Config.stubbed_files.each { |p| options << "-s#{p}" }
|
101
126
|
|
102
127
|
options += @cli_options if @cli_options
|
103
|
-
|
104
|
-
|
105
|
-
'::RSpec::Core::Runner.autorun',
|
106
|
-
].join(';')
|
128
|
+
|
129
|
+
bootstrap_code = ::Opal::RSpec.spec_opts_code(spec_opts)
|
107
130
|
|
108
131
|
@args = "#{options.map(&:shellescape).join ' '} -e #{bootstrap_code.shellescape}"
|
109
132
|
end
|
110
133
|
|
134
|
+
def append_opts_from_config_file
|
135
|
+
self.libs ||= []
|
136
|
+
self.requires ||= []
|
137
|
+
|
138
|
+
config_location = nil
|
139
|
+
path = self.default_path || "spec-opal"
|
140
|
+
|
141
|
+
# Locate config file
|
142
|
+
begin
|
143
|
+
loop do
|
144
|
+
if File.exist?(File.join(path, ".rspec-opal"))
|
145
|
+
path = File.join(path, ".rspec-opal")
|
146
|
+
break
|
147
|
+
else
|
148
|
+
new_path = File.expand_path("..", path)
|
149
|
+
return if new_path == path
|
150
|
+
path = new_path
|
151
|
+
end
|
152
|
+
end
|
153
|
+
rescue e
|
154
|
+
# we've gone too far beyond our permissions without finding a config file
|
155
|
+
return
|
156
|
+
end
|
157
|
+
|
158
|
+
if path
|
159
|
+
config_opts = Opal::RSpec.convert_spec_opts(File.read(path))
|
160
|
+
else
|
161
|
+
return
|
162
|
+
end
|
163
|
+
|
164
|
+
self.spec_opts = config_opts.merge(spec_opts) do |key, oldval, newval|
|
165
|
+
[:libs, :requires].include?(key) ? oldval + newval : newval
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
111
169
|
def options
|
112
170
|
{
|
113
171
|
pattern: pattern,
|
data/lib/opal/rspec/version.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
module Opal
|
2
2
|
module RSpec
|
3
|
-
VERSION = '1.0.
|
3
|
+
VERSION = '1.1.0.alpha1'
|
4
4
|
end
|
5
5
|
end
|
6
|
+
|
7
|
+
load __dir__ + "/../../../rspec-core/upstream/lib/rspec/core/version.rb", ::Opal
|
8
|
+
load __dir__ + "/../../../rspec-expectations/upstream/lib/rspec/expectations/version.rb", ::Opal
|
9
|
+
load __dir__ + "/../../../rspec-mocks/upstream/lib/rspec/mocks/version.rb", ::Opal
|
10
|
+
load __dir__ + "/../../../rspec-support/upstream/lib/rspec/support/version.rb", ::Opal
|
data/lib/opal/rspec.rb
CHANGED
@@ -2,6 +2,7 @@ require 'opal'
|
|
2
2
|
require 'opal-sprockets'
|
3
3
|
require 'opal/rspec/version'
|
4
4
|
require 'opal/rspec/runner'
|
5
|
+
require 'opal/rspec/configuration_parser'
|
5
6
|
|
6
7
|
# Just register our opal code path with opal build tools
|
7
8
|
Opal.append_path File.expand_path('../../../lib-opal', __FILE__)
|
@@ -19,32 +20,31 @@ module Opal
|
|
19
20
|
module RSpec
|
20
21
|
autoload :ProjectInitializer, 'opal/rspec/project_initializer'
|
21
22
|
|
23
|
+
def self.convert_spec_opts(opts)
|
24
|
+
opts ||= ENV['SPEC_OPTS'] || {}
|
25
|
+
|
26
|
+
unless opts.is_a? Hash
|
27
|
+
opts = Shellwords.split(opts) if opts.is_a? String
|
28
|
+
opts = Opal::RSpec::Core::Parser.parse(opts || [])
|
29
|
+
end
|
30
|
+
|
31
|
+
opts
|
32
|
+
end
|
33
|
+
|
22
34
|
def self.spec_opts_code(spec_opts)
|
35
|
+
spec_opts = convert_spec_opts(spec_opts)
|
36
|
+
|
23
37
|
code = []
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
if (requires = spec_opts.scan(/(?:--require|-r) \S+/)).any?
|
35
|
-
requires.map {|r| /--require (.*)/.match(r).captures[0]}.each do |req|
|
36
|
-
code << %{require "#{req}"}
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
if (match = /--format (\S+)/.match(spec_opts))
|
41
|
-
formatter = match.captures[0]
|
42
|
-
code << %{config.formatter = "#{formatter}"}
|
43
|
-
end
|
44
|
-
|
45
|
-
code << 'end'
|
46
|
-
end
|
47
|
-
code.join('; ')
|
38
|
+
code << '# await: true'
|
39
|
+
|
40
|
+
# New API - passthru options
|
41
|
+
spec_opts[:files_or_directories_to_run] ||= []
|
42
|
+
|
43
|
+
code << "$rspec_opts = #{spec_opts.inspect}"
|
44
|
+
code << "$0 = 'opal-rspec'"
|
45
|
+
|
46
|
+
code << '::RSpec::Core::Runner.invoke.__await__'
|
47
|
+
code.join("\n")
|
48
48
|
end
|
49
49
|
end
|
50
50
|
end
|
@@ -1,5 +1,9 @@
|
|
1
1
|
require 'opal/rspec/formatter/browser_formatter'
|
2
2
|
|
3
3
|
RSpec.configure do |config|
|
4
|
-
|
4
|
+
if OPAL_PLATFORM.nil?
|
5
|
+
# We want the browser formatter ONLY for the real browser, not
|
6
|
+
# our headless browser runners.
|
7
|
+
config.default_formatter = ::Opal::RSpec::BrowserFormatter
|
8
|
+
end
|
5
9
|
end
|
@@ -1,20 +1,112 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# backtick_javascript: true
|
2
|
+
|
3
|
+
require 'rspec/core/configuration'
|
4
|
+
|
5
|
+
module ::RSpec; module Core; class Configuration
|
3
6
|
def files_or_directories_to_run=(*files)
|
4
|
-
|
7
|
+
files = files.flatten
|
8
|
+
|
9
|
+
# patch: rspec -> opal-rspec
|
10
|
+
if (command == 'opal-rspec' || Runner.running_in_drb?) && default_path && files.empty?
|
11
|
+
files << default_path
|
12
|
+
end
|
13
|
+
|
14
|
+
@files_or_directories_to_run = files
|
5
15
|
@files_to_run = nil
|
6
16
|
end
|
7
17
|
|
8
18
|
def requires=(paths)
|
9
19
|
# can't change requires @ this stage, this method calls RubyProject which will crash on Opal
|
10
20
|
end
|
11
|
-
|
21
|
+
|
22
|
+
def remove_ruby_ext(str)
|
23
|
+
str.gsub(/(?:\.js)?\.(?:rb|opal|\{rb,opal\})\z/, '')
|
24
|
+
end
|
25
|
+
|
26
|
+
def glob_to_re(path, pattern)
|
27
|
+
pattern = remove_ruby_ext(pattern)
|
28
|
+
path = "" if pattern.start_with?(path)
|
29
|
+
path += "/" unless path.end_with?("/")
|
30
|
+
re = Regexp.escape(pattern).gsub('\*\*', '.*?')
|
31
|
+
.gsub('\*', '[^/]*?')
|
32
|
+
.gsub('\?', '[^/]')
|
33
|
+
.gsub(/\\{(.*?)\\}/) {
|
34
|
+
'(?:' + $1.gsub(",", "|") + ')'
|
35
|
+
}
|
36
|
+
re = "(?:^|/)" + Regexp.escape(path) + re + "$"
|
37
|
+
# Strip the first `/` so it acts more like the intention of `**`
|
38
|
+
re = re.gsub("/.*?", ".*?")
|
39
|
+
# Strip the `/./`
|
40
|
+
re = re.gsub("/\\.\\/", "\\/")
|
41
|
+
re = re.gsub("/)\\.\\/", "\\/)")
|
42
|
+
Regexp.new(re)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Only load from loaded files
|
46
|
+
def get_matching_files(path, pattern)
|
47
|
+
`Object.keys(Opal.modules)`.grep(glob_to_re(path, pattern)).sort
|
48
|
+
end
|
49
|
+
|
50
|
+
# A crude logic to check if a path is a directory perhaps...
|
51
|
+
# This ought to work in places where we don't have a filesystem.
|
52
|
+
def is_directory?(path)
|
53
|
+
return true if path.end_with? '/'
|
54
|
+
# This is passed with ":" if we run something like:
|
55
|
+
# opal-rspec spec-opal-passing/tautology_spec.rb:8
|
56
|
+
return false if path =~ /\[[0-9:]+\]$|:[0-9]+$/
|
57
|
+
# Ruby files are certainly not directories
|
58
|
+
return false if ['.rb', '.opal'].any? { |i| path.end_with? i }
|
59
|
+
# Otherwise, let's check for modules
|
60
|
+
!`Object.keys(Opal.modules)`.any? { |i| i.end_with?("/"+remove_ruby_ext(path)) }
|
61
|
+
end
|
62
|
+
|
63
|
+
def get_files_to_run(paths)
|
64
|
+
files = paths_to_check(paths).flat_map do |path|
|
65
|
+
path = path.gsub(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
|
66
|
+
is_directory?(path) ? gather_directories(path) : extract_location(path)
|
67
|
+
end.uniq
|
68
|
+
|
69
|
+
return files unless only_failures?
|
70
|
+
relative_files = files.map { |f| Metadata.relative_path(File.expand_path f) }
|
71
|
+
intersection = (relative_files & spec_files_with_failures.to_a)
|
72
|
+
intersection.empty? ? files : intersection
|
73
|
+
end
|
74
|
+
|
75
|
+
def opal_special_load(file)
|
76
|
+
file = remove_ruby_ext(file)
|
77
|
+
long_file = `Object.keys(Opal.modules)`.find { |i| i.end_with?(file) }
|
78
|
+
`Opal.modules[file] = Opal.modules[long_file]` if long_file
|
79
|
+
|
80
|
+
# Let's try a normalized load
|
81
|
+
`Opal.load_normalized(file)`
|
82
|
+
rescue LoadError
|
83
|
+
# Otherwise, a regular require
|
84
|
+
require file
|
85
|
+
end
|
86
|
+
|
87
|
+
alias load_file_handling_errors_before_opal load_file_handling_errors
|
88
|
+
|
89
|
+
def load_file_handling_errors(method, file)
|
90
|
+
load_file_handling_errors_before_opal(:opal_special_load, file)
|
91
|
+
end
|
92
|
+
end; end; end
|
12
93
|
|
13
94
|
class ::RSpec::Core::ConfigurationOptions
|
95
|
+
# Opal-RSpec should work without need of filesystem
|
96
|
+
# access, therefore we can't support access to the
|
97
|
+
# options file.
|
14
98
|
def options_file_as_erb_string(path)
|
15
99
|
# ERB.new(File.read(path), nil, '-').result(binding)
|
16
100
|
# ERB.new(File.read(path), nil, '-')
|
17
101
|
''
|
18
102
|
end
|
103
|
+
|
104
|
+
# Pass command line options directly
|
105
|
+
def command_line_options
|
106
|
+
$rspec_opts || {}
|
107
|
+
end
|
19
108
|
end
|
20
109
|
|
110
|
+
# Set the default path to spec-opal, to be overwritten
|
111
|
+
# later.
|
112
|
+
RSpec.configuration.default_path = "spec-opal"
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# await: true
|
2
|
+
|
1
3
|
# This file is used by Opal::Server to basically load all spec files that
|
2
4
|
# can be found in the spec/ directory.
|
3
5
|
|
@@ -10,5 +12,5 @@ require <%= s.inspect %>
|
|
10
12
|
<% end %>
|
11
13
|
require 'opal/rspec/spec_opts'
|
12
14
|
|
13
|
-
::RSpec::Core::Runner.
|
15
|
+
::RSpec::Core::Runner.invoke.__await__
|
14
16
|
::Kernel.exit
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: opal-rspec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.1.0.alpha1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Beynon
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2023-09-15 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: opal
|
@@ -294,6 +294,7 @@ files:
|
|
294
294
|
- lib/opal-rspec.rb
|
295
295
|
- lib/opal/rspec.rb
|
296
296
|
- lib/opal/rspec/cached_environment.rb
|
297
|
+
- lib/opal/rspec/configuration_parser.rb
|
297
298
|
- lib/opal/rspec/locator.rb
|
298
299
|
- lib/opal/rspec/project_initializer.rb
|
299
300
|
- lib/opal/rspec/project_initializer/.rspec-opal
|
@@ -951,11 +952,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
951
952
|
version: '0'
|
952
953
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
953
954
|
requirements:
|
954
|
-
- - "
|
955
|
+
- - ">"
|
955
956
|
- !ruby/object:Gem::Version
|
956
|
-
version:
|
957
|
+
version: 1.3.1
|
957
958
|
requirements: []
|
958
|
-
rubygems_version: 3.
|
959
|
+
rubygems_version: 3.4.10
|
959
960
|
signing_key:
|
960
961
|
specification_version: 4
|
961
962
|
summary: RSpec for Opal
|