opal-rspec 1.0.0.alpha1 → 1.1.0.alpha1
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/.github/workflows/build.yml +1 -1
- data/CHANGELOG.md +17 -1
- 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
- data/opal-rspec.gemspec +0 -1
- metadata +4 -17
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,6 +1,19 @@
|
|
1
1
|
# Opal-RSpec Changelog
|
2
2
|
|
3
|
-
## 1.
|
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
|
+
|
16
|
+
## 1.0.0 - 2022-11-24
|
4
17
|
|
5
18
|
- Drop support for anything below Opal v1.6.alpha1
|
6
19
|
|
@@ -14,6 +27,9 @@
|
|
14
27
|
* In `around` blocks, you must call `example.run_await` instead of just `example.run`
|
15
28
|
* Only `PromiseV2` is supported (`PromiseV1` may work, but you should migrate your application to use `PromiseV2` nevertheless, in Opal 2.0 it will become the default)
|
16
29
|
|
30
|
+
- Drop a requirement of `opal-sprockets`
|
31
|
+
* Sprockets support is still provided, but you need to manually `require "opal/rspec/sprockets"`
|
32
|
+
|
17
33
|
|
18
34
|
## 0.8.0 - 2021-12-01
|
19
35
|
|
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.
|
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
|
data/opal-rspec.gemspec
CHANGED
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.
|
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
|
@@ -32,20 +32,6 @@ dependencies:
|
|
32
32
|
- - "<"
|
33
33
|
- !ruby/object:Gem::Version
|
34
34
|
version: '2.0'
|
35
|
-
- !ruby/object:Gem::Dependency
|
36
|
-
name: opal-sprockets
|
37
|
-
requirement: !ruby/object:Gem::Requirement
|
38
|
-
requirements:
|
39
|
-
- - "<"
|
40
|
-
- !ruby/object:Gem::Version
|
41
|
-
version: '2.0'
|
42
|
-
type: :runtime
|
43
|
-
prerelease: false
|
44
|
-
version_requirements: !ruby/object:Gem::Requirement
|
45
|
-
requirements:
|
46
|
-
- - "<"
|
47
|
-
- !ruby/object:Gem::Version
|
48
|
-
version: '2.0'
|
49
35
|
- !ruby/object:Gem::Dependency
|
50
36
|
name: rake
|
51
37
|
requirement: !ruby/object:Gem::Requirement
|
@@ -308,6 +294,7 @@ files:
|
|
308
294
|
- lib/opal-rspec.rb
|
309
295
|
- lib/opal/rspec.rb
|
310
296
|
- lib/opal/rspec/cached_environment.rb
|
297
|
+
- lib/opal/rspec/configuration_parser.rb
|
311
298
|
- lib/opal/rspec/locator.rb
|
312
299
|
- lib/opal/rspec/project_initializer.rb
|
313
300
|
- lib/opal/rspec/project_initializer/.rspec-opal
|
@@ -969,7 +956,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
969
956
|
- !ruby/object:Gem::Version
|
970
957
|
version: 1.3.1
|
971
958
|
requirements: []
|
972
|
-
rubygems_version: 3.
|
959
|
+
rubygems_version: 3.4.10
|
973
960
|
signing_key:
|
974
961
|
specification_version: 4
|
975
962
|
summary: RSpec for Opal
|