opal-rspec 0.0.1.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/Gemfile +15 -0
- data/README.md +78 -0
- data/Rakefile +46 -0
- data/app/rspec-builder.rb +10 -0
- data/app/rspec/core.rb +202 -0
- data/app/rspec/core/configuration.rb +1070 -0
- data/app/rspec/core/example_group.rb +573 -0
- data/app/rspec/core/project_initializer.rb +0 -0
- data/app/rspec/core/shared_example_group.rb +146 -0
- data/app/rspec/core/shared_example_group/collection.rb +27 -0
- data/app/rspec/matchers/built_in/have.rb +0 -0
- data/config.ru +10 -0
- data/lib/opal-rspec.rb +2 -0
- data/lib/opal/rspec.rb +6 -0
- data/lib/opal/rspec/rake_task.rb +44 -0
- data/lib/opal/rspec/version.rb +6 -0
- data/opal-rspec.gemspec +23 -0
- data/opal/opal-rspec.rb +1 -0
- data/opal/opal/rspec.rb +21 -0
- data/opal/opal/rspec/browser_formatter.rb +194 -0
- data/opal/opal/rspec/fixes.rb +62 -0
- data/opal/opal/rspec/runner.rb +52 -0
- data/opal/opal/rspec/sprockets_runner.rb.erb +11 -0
- data/opal/opal/rspec/text_formatter.rb +74 -0
- data/spec/example_spec.rb +143 -0
- data/spec/matchers_spec.rb +181 -0
- data/vendor/spec_runner.js +41 -0
- metadata +113 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ed072aad1768de7d20b2cabb9f11f670976874fc
|
4
|
+
data.tar.gz: 0a4f28128a5b045a1b0b385d2d4ca38b776075d7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7ab1aad04e561cc0a8c45701b2edde80be2d5ad00cf3d02c60dcd00f21d7684a74f6d57c69ae4081f3eb2d77be7dd5b8a04712ece70d86485ad87c4bb5715958
|
7
|
+
data.tar.gz: b086f9fff0bdc56e51a4f9a3f8ef858f9af4116cae085f15ddbda6a26cfafd7fb5215219d62395e57acf7844352b7ba350243cb14135e667ac07e414868b932a
|
data/.gitignore
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
gemspec
|
3
|
+
|
4
|
+
gem 'rake'
|
5
|
+
|
6
|
+
gem 'opal', :github => 'opal/opal'
|
7
|
+
gem 'opal-sprockets', :github => 'opal/opal-sprockets'
|
8
|
+
|
9
|
+
# As we monkey patch a lot, work of a specific commit on github
|
10
|
+
gem 'rspec-support', :github => 'rspec/rspec-support', :ref => 'f235ccb129'
|
11
|
+
gem 'rspec-expectations', :github => 'rspec/rspec-expectations', :ref => 'd3277fd42e'
|
12
|
+
gem 'rspec-core', :github => 'rspec/rspec-core', :ref => 'ed8898c58b'
|
13
|
+
gem 'rspec-mocks', :github => 'rspec/rspec-mocks', :ref => 'a2f952a025'
|
14
|
+
|
15
|
+
gem 'rspec', :github => 'rspec/rspec'
|
data/README.md
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# opal-rspec
|
2
|
+
|
3
|
+
An attempt at a compatibility layer of rspec for opal.
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
|
7
|
+
Install required gems at required versions:
|
8
|
+
|
9
|
+
$ bundle install
|
10
|
+
|
11
|
+
opal-rspec uses a prebuilt version of rspec to fix the areas where
|
12
|
+
opal cannot handle certain features of rspec. To build that file,
|
13
|
+
which is needed to run specs, use:
|
14
|
+
|
15
|
+
$ bundle exec rake build
|
16
|
+
|
17
|
+
This should build `opal/opal/rspec/rspec.js` ready to use.
|
18
|
+
|
19
|
+
### Run on command line
|
20
|
+
|
21
|
+
A simple rake task should run the example specs in `spec/`:
|
22
|
+
|
23
|
+
$ bundle exec rake
|
24
|
+
|
25
|
+
### Run in the browser
|
26
|
+
|
27
|
+
Run attached rack app to handle building:
|
28
|
+
|
29
|
+
$ bundle exec rackup
|
30
|
+
|
31
|
+
Visit the page in any browser and view the console:
|
32
|
+
|
33
|
+
$ open http://localhost:9292
|
34
|
+
|
35
|
+
## Things to fix
|
36
|
+
|
37
|
+
`opal/opal-rspec/fixes.rb` contains a few bug fixes that need to be merged upstream
|
38
|
+
to opal itself. In app/rspec we have to stub various rspec files.
|
39
|
+
|
40
|
+
### rspec/core.rb
|
41
|
+
|
42
|
+
* **line 1**: `require_rspec` to fake require_relative doesnt work at runtime.
|
43
|
+
opal has to include all dependencies into build.
|
44
|
+
|
45
|
+
* **line 90**: heredoc fails to parse in opal as EOS is used within heredoc
|
46
|
+
|
47
|
+
* **line 171**: `&::Time.method(:now)` doesnt work so wrong method is set
|
48
|
+
|
49
|
+
### rspec/core/configuration.rb
|
50
|
+
|
51
|
+
* **line ?**: something in that file is causing opal to generate bad javascript.
|
52
|
+
This is possible a require statement used as an expression which generates empty
|
53
|
+
code.
|
54
|
+
|
55
|
+
### rspec/core/example_group.rb
|
56
|
+
|
57
|
+
* **line 434**: cannot parse heredoc as it uses EOS inline before string ends
|
58
|
+
|
59
|
+
* **line 547**: opal cannot use mutable strings (see opal/rspec/fixes.rb)
|
60
|
+
|
61
|
+
* **line 564**: opal cannot use mutable strings (see opal/rspec/fixes.rb)
|
62
|
+
|
63
|
+
### rspec/core/project_initializer.rb
|
64
|
+
|
65
|
+
* **line 1**: opal cannot parse these heredocs (EOS used before last line of string)
|
66
|
+
|
67
|
+
### rspec/core/shared_example_group.rb
|
68
|
+
|
69
|
+
* **line 112**: opal cannot parse this heredoc
|
70
|
+
|
71
|
+
### rspec/core/shared_example_group/collection.rb
|
72
|
+
|
73
|
+
* **line 17**: opal cannot parse command call inside aref
|
74
|
+
|
75
|
+
### rspec/matchers/built_in/have.rb
|
76
|
+
|
77
|
+
* **line 1**: this is an error in rspec. This autoload does not exist so we must
|
78
|
+
stub the file.
|
data/Rakefile
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler.require
|
3
|
+
|
4
|
+
require 'opal/rspec/rake_task'
|
5
|
+
Opal::RSpec::RakeTask.new(:default)
|
6
|
+
|
7
|
+
desc "Build opal/opal/rspec/rspec.js"
|
8
|
+
task :build do
|
9
|
+
File.open('opal/opal/rspec/rspec.js', 'w+') do |out|
|
10
|
+
out << build_rspec
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "Show dev/min sizes"
|
15
|
+
task :sizes do
|
16
|
+
code = build_rspec
|
17
|
+
min = uglify code
|
18
|
+
|
19
|
+
puts "\ndevelopment: #{code.size}, minified: #{min.size}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def build_rspec
|
23
|
+
Opal::Processor.dynamic_require_severity = :warning
|
24
|
+
Opal.append_path 'app'
|
25
|
+
|
26
|
+
Opal.use_gem 'rspec'
|
27
|
+
Opal.use_gem 'rspec-expectations'
|
28
|
+
|
29
|
+
%w[fileutils test/unit/assertions coderay optparse shellwords socket uri
|
30
|
+
drb/drb diff/lcs diff/lcs/hunk].each do |asset|
|
31
|
+
Opal::Processor.stub_file asset
|
32
|
+
end
|
33
|
+
|
34
|
+
Opal.process('rspec-builder')
|
35
|
+
end
|
36
|
+
|
37
|
+
def uglify(str)
|
38
|
+
IO.popen('uglifyjs', 'r+') do |i|
|
39
|
+
i.puts str
|
40
|
+
i.close_write
|
41
|
+
return i.read
|
42
|
+
end
|
43
|
+
rescue Errno::ENOENT
|
44
|
+
$stderr.puts '"uglifyjs" command not found (install with: "npm install -g uglify-js")'
|
45
|
+
nil
|
46
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'rspec/support'
|
2
|
+
require 'rspec/core'
|
3
|
+
require 'rspec/mocks'
|
4
|
+
require 'rspec-expectations'
|
5
|
+
|
6
|
+
# we want access to BaseFormatter
|
7
|
+
require 'rspec/core/formatters/base_formatter'
|
8
|
+
|
9
|
+
# For now, we don't support mocking. This placeholder in rspec-core allows that.
|
10
|
+
require 'rspec/core/mocking/with_absolutely_nothing'
|
data/app/rspec/core.rb
ADDED
@@ -0,0 +1,202 @@
|
|
1
|
+
require_rspec = if defined?(require_relative)
|
2
|
+
lambda do |path|
|
3
|
+
require_relative path
|
4
|
+
end
|
5
|
+
else # for 1.8.7
|
6
|
+
lambda do |path|
|
7
|
+
require "rspec/#{path}"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'set'
|
12
|
+
require 'time'
|
13
|
+
require 'rbconfig'
|
14
|
+
|
15
|
+
require 'rspec/core/version'
|
16
|
+
|
17
|
+
require 'rspec/support/caller_filter'
|
18
|
+
|
19
|
+
require 'rspec/core/flat_map'
|
20
|
+
require 'rspec/core/filter_manager'
|
21
|
+
require 'rspec/core/dsl'
|
22
|
+
require 'rspec/core/warnings'
|
23
|
+
require 'rspec/core/reporter'
|
24
|
+
|
25
|
+
require 'rspec/core/hooks'
|
26
|
+
require 'rspec/core/memoized_helpers'
|
27
|
+
require 'rspec/core/metadata'
|
28
|
+
require 'rspec/core/pending'
|
29
|
+
require 'rspec/core/formatters'
|
30
|
+
require 'rspec/core/ordering'
|
31
|
+
|
32
|
+
require 'rspec/core/world'
|
33
|
+
require 'rspec/core/configuration'
|
34
|
+
require 'rspec/core/option_parser'
|
35
|
+
require 'rspec/core/configuration_options'
|
36
|
+
require 'rspec/core/command_line'
|
37
|
+
require 'rspec/core/runner'
|
38
|
+
require 'rspec/core/example'
|
39
|
+
require 'rspec/core/shared_example_group/collection'
|
40
|
+
require 'rspec/core/shared_example_group'
|
41
|
+
require 'rspec/core/example_group'
|
42
|
+
|
43
|
+
module RSpec
|
44
|
+
autoload :SharedContext, 'rspec/core/shared_context'
|
45
|
+
|
46
|
+
# @private
|
47
|
+
def self.wants_to_quit
|
48
|
+
# Used internally to determine what to do when a SIGINT is received
|
49
|
+
world.wants_to_quit
|
50
|
+
end
|
51
|
+
|
52
|
+
# @private
|
53
|
+
# Used internally to determine what to do when a SIGINT is received
|
54
|
+
def self.wants_to_quit=(maybe)
|
55
|
+
world.wants_to_quit=(maybe)
|
56
|
+
end
|
57
|
+
|
58
|
+
# @private
|
59
|
+
# Internal container for global non-configuration data
|
60
|
+
def self.world
|
61
|
+
@world ||= RSpec::Core::World.new
|
62
|
+
end
|
63
|
+
|
64
|
+
# @private
|
65
|
+
# Used internally to set the global object
|
66
|
+
def self.world=(new_world)
|
67
|
+
@world = new_world
|
68
|
+
end
|
69
|
+
|
70
|
+
# @private
|
71
|
+
# Used internally to ensure examples get reloaded between multiple runs in
|
72
|
+
# the same process.
|
73
|
+
def self.reset
|
74
|
+
@world = nil
|
75
|
+
@configuration = nil
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns the global [Configuration](RSpec/Core/Configuration) object. While you
|
79
|
+
# _can_ use this method to access the configuration, the more common
|
80
|
+
# convention is to use [RSpec.configure](RSpec#configure-class_method).
|
81
|
+
#
|
82
|
+
# @example
|
83
|
+
# RSpec.configuration.drb_port = 1234
|
84
|
+
# @see RSpec.configure
|
85
|
+
# @see Core::Configuration
|
86
|
+
def self.configuration
|
87
|
+
if block_given?
|
88
|
+
RSpec.warn_deprecation <<-WARNING
|
89
|
+
|
90
|
+
*****************************************************************
|
91
|
+
DEPRECATION WARN
|
92
|
+
|
93
|
+
* RSpec.configuration with a block is deprecated and has no effect.
|
94
|
+
* please use RSpec.configure with a block instead.
|
95
|
+
|
96
|
+
Called from
|
97
|
+
*****************************************************************
|
98
|
+
|
99
|
+
WARNING
|
100
|
+
end
|
101
|
+
@configuration ||= RSpec::Core::Configuration.new
|
102
|
+
end
|
103
|
+
|
104
|
+
# @private
|
105
|
+
# Used internally to set the global object
|
106
|
+
def self.configuration=(new_configuration)
|
107
|
+
@configuration = new_configuration
|
108
|
+
end
|
109
|
+
|
110
|
+
# Yields the global configuration to a block.
|
111
|
+
# @yield [Configuration] global configuration
|
112
|
+
#
|
113
|
+
# @example
|
114
|
+
# RSpec.configure do |config|
|
115
|
+
# config.add_formatter 'documentation'
|
116
|
+
# end
|
117
|
+
# @see Core::Configuration
|
118
|
+
def self.configure
|
119
|
+
yield configuration if block_given?
|
120
|
+
end
|
121
|
+
|
122
|
+
# @private
|
123
|
+
# Used internally to clear remaining groups when fail_fast is set
|
124
|
+
def self.clear_remaining_example_groups
|
125
|
+
world.example_groups.clear
|
126
|
+
end
|
127
|
+
|
128
|
+
# The example being executed.
|
129
|
+
#
|
130
|
+
# The primary audience for this method is library authors who need access
|
131
|
+
# to the example currently being executed and also want to support all
|
132
|
+
# versions of RSpec 2 and 3.
|
133
|
+
#
|
134
|
+
# @example
|
135
|
+
#
|
136
|
+
# RSpec.configure do |c|
|
137
|
+
# # context.example is deprecated, but RSpec.current_example is not
|
138
|
+
# # available until RSpec 3.0.
|
139
|
+
# fetch_current_example = RSpec.respond_to?(:current_example) ?
|
140
|
+
# proc { RSpec.current_example } : proc { |context| context.example }
|
141
|
+
#
|
142
|
+
# c.before(:each) do
|
143
|
+
# example = fetch_current_example.call(self)
|
144
|
+
#
|
145
|
+
# # ...
|
146
|
+
# end
|
147
|
+
# end
|
148
|
+
#
|
149
|
+
def self.current_example
|
150
|
+
Thread.current[:_rspec_current_example]
|
151
|
+
end
|
152
|
+
|
153
|
+
# Set the current example being executed.
|
154
|
+
# @api private
|
155
|
+
def self.current_example=(example)
|
156
|
+
Thread.current[:_rspec_current_example] = example
|
157
|
+
end
|
158
|
+
|
159
|
+
# @private
|
160
|
+
def self.windows_os?
|
161
|
+
RbConfig::CONFIG['host_os'] =~ /cygwin|mswin|mingw|bccwin|wince|emx/
|
162
|
+
end
|
163
|
+
|
164
|
+
module Core
|
165
|
+
# @private
|
166
|
+
# This avoids issues with reporting time caused by examples that
|
167
|
+
# change the value/meaning of Time.now without properly restoring
|
168
|
+
# it.
|
169
|
+
class Time
|
170
|
+
class << self
|
171
|
+
def now; ::Time.now; end #define_method(:now, &::Time.method(:now))
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
# @private path to executable file
|
176
|
+
def self.path_to_executable
|
177
|
+
@path_to_executable ||= File.expand_path('../../../exe/rspec', __FILE__)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
MODULES_TO_AUTOLOAD = {
|
182
|
+
:Matchers => "rspec/expectations",
|
183
|
+
:Expectations => "rspec/expectations",
|
184
|
+
:Mocks => "rspec/mocks"
|
185
|
+
}
|
186
|
+
|
187
|
+
def self.const_missing(name)
|
188
|
+
# Load rspec-expectations when RSpec::Matchers is referenced. This allows
|
189
|
+
# people to define custom matchers (using `RSpec::Matchers.define`) before
|
190
|
+
# rspec-core has loaded rspec-expectations (since it delays the loading of
|
191
|
+
# it to allow users to configure a different assertion/expectation
|
192
|
+
# framework). `autoload` can't be used since it works with ruby's built-in
|
193
|
+
# require (e.g. for files that are available relative to a load path dir),
|
194
|
+
# but not with rubygems' extended require.
|
195
|
+
#
|
196
|
+
# As of rspec 2.14.1, we no longer require `rspec/mocks` and
|
197
|
+
# `rspec/expectations` when `rspec` is required, so we want
|
198
|
+
# to make them available as an autoload. For more info, see:
|
199
|
+
# require MODULES_TO_AUTOLOAD.fetch(name) { return super }
|
200
|
+
::RSpec.const_get(name)
|
201
|
+
end
|
202
|
+
end
|
@@ -0,0 +1,1070 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'rspec/core/backtrace_formatter'
|
3
|
+
require 'rspec/core/ruby_project'
|
4
|
+
require 'rspec/core/formatters/deprecation_formatter.rb'
|
5
|
+
|
6
|
+
module RSpec
|
7
|
+
module Core
|
8
|
+
# Stores runtime configuration information.
|
9
|
+
#
|
10
|
+
# Configuration options are loaded from `~/.rspec`, `.rspec`,
|
11
|
+
# `.rspec-local`, command line switches, and the `SPEC_OPTS` environment
|
12
|
+
# variable (listed in lowest to highest precedence; for example, an option
|
13
|
+
# in `~/.rspec` can be overridden by an option in `.rspec-local`).
|
14
|
+
#
|
15
|
+
# @example Standard settings
|
16
|
+
# RSpec.configure do |c|
|
17
|
+
# c.drb = true
|
18
|
+
# c.drb_port = 1234
|
19
|
+
# c.default_path = 'behavior'
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# @example Hooks
|
23
|
+
# RSpec.configure do |c|
|
24
|
+
# c.before(:suite) { establish_connection }
|
25
|
+
# c.before(:each) { log_in_as :authorized }
|
26
|
+
# c.around(:each) { |ex| Database.transaction(&ex) }
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# @see RSpec.configure
|
30
|
+
# @see Hooks
|
31
|
+
class Configuration
|
32
|
+
include RSpec::Core::Hooks
|
33
|
+
|
34
|
+
class MustBeConfiguredBeforeExampleGroupsError < StandardError; end
|
35
|
+
|
36
|
+
# @private
|
37
|
+
def self.define_reader(name)
|
38
|
+
define_method(name) do
|
39
|
+
variable = instance_variable_defined?("@#{name}") ? instance_variable_get("@#{name}") : nil
|
40
|
+
value_for(name, variable)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# @private
|
45
|
+
def self.deprecate_alias_key
|
46
|
+
RSpec.deprecate("add_setting with :alias option", :replacement => ":alias_with")
|
47
|
+
end
|
48
|
+
|
49
|
+
# @private
|
50
|
+
def self.define_aliases(name, alias_name)
|
51
|
+
alias_method alias_name, name
|
52
|
+
alias_method "#{alias_name}=", "#{name}="
|
53
|
+
define_predicate_for alias_name
|
54
|
+
end
|
55
|
+
|
56
|
+
# @private
|
57
|
+
def self.define_predicate_for(*names)
|
58
|
+
names.each {|name| alias_method "#{name}?", name}
|
59
|
+
end
|
60
|
+
|
61
|
+
# @private
|
62
|
+
#
|
63
|
+
# Invoked by the `add_setting` instance method. Use that method on a
|
64
|
+
# `Configuration` instance rather than this class method.
|
65
|
+
def self.add_setting(name, opts={})
|
66
|
+
raise "Use the instance add_setting method if you want to set a default" if opts.has_key?(:default)
|
67
|
+
if opts[:alias]
|
68
|
+
deprecate_alias_key
|
69
|
+
define_aliases(opts[:alias], name)
|
70
|
+
else
|
71
|
+
attr_writer name
|
72
|
+
define_reader name
|
73
|
+
define_predicate_for name
|
74
|
+
end
|
75
|
+
Array(opts[:alias_with]).each do |alias_name|
|
76
|
+
define_aliases(name, alias_name)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# @macro [attach] add_setting
|
81
|
+
# @attribute $1
|
82
|
+
#
|
83
|
+
# @macro [attach] define_reader
|
84
|
+
# @attribute $1
|
85
|
+
|
86
|
+
# @macro add_setting
|
87
|
+
# Path to use if no path is provided to the `rspec` command (default:
|
88
|
+
# `"spec"`). Allows you to just type `rspec` instead of `rspec spec` to
|
89
|
+
# run all the examples in the `spec` directory.
|
90
|
+
add_setting :default_path
|
91
|
+
|
92
|
+
# @macro add_setting
|
93
|
+
# Run examples over DRb (default: `false`). RSpec doesn't supply the DRb
|
94
|
+
# server, but you can use tools like spork.
|
95
|
+
add_setting :drb
|
96
|
+
|
97
|
+
# @macro add_setting
|
98
|
+
# The drb_port (default: nil).
|
99
|
+
add_setting :drb_port
|
100
|
+
|
101
|
+
# @macro add_setting
|
102
|
+
# Default: `$stderr`.
|
103
|
+
add_setting :error_stream
|
104
|
+
|
105
|
+
# @macro add_setting
|
106
|
+
# Default: `$stderr`.
|
107
|
+
add_setting :deprecation_stream
|
108
|
+
|
109
|
+
# @macro add_setting
|
110
|
+
# Clean up and exit after the first failure (default: `false`).
|
111
|
+
add_setting :fail_fast
|
112
|
+
|
113
|
+
# @macro add_setting
|
114
|
+
# Prints the formatter output of your suite without running any
|
115
|
+
# examples or hooks.
|
116
|
+
add_setting :dry_run
|
117
|
+
|
118
|
+
# @macro add_setting
|
119
|
+
# The exit code to return if there are any failures (default: 1).
|
120
|
+
add_setting :failure_exit_code
|
121
|
+
|
122
|
+
# @macro define_reader
|
123
|
+
# Indicates files configured to be required
|
124
|
+
define_reader :requires
|
125
|
+
|
126
|
+
# @macro define_reader
|
127
|
+
# Returns dirs that have been prepended to the load path by #lib=
|
128
|
+
define_reader :libs
|
129
|
+
|
130
|
+
# @macro add_setting
|
131
|
+
# Default: `$stdout`.
|
132
|
+
# Also known as `output` and `out`
|
133
|
+
add_setting :output_stream, :alias_with => [:output, :out]
|
134
|
+
|
135
|
+
# @macro add_setting
|
136
|
+
# Load files matching this pattern (default: `'**/*_spec.rb'`)
|
137
|
+
add_setting :pattern, :alias_with => :filename_pattern
|
138
|
+
|
139
|
+
def pattern= value
|
140
|
+
if @spec_files_loaded
|
141
|
+
RSpec.warning "Configuring `pattern` to #{value} has no effect since RSpec has already loaded the spec files."
|
142
|
+
end
|
143
|
+
@pattern = value
|
144
|
+
end
|
145
|
+
alias :filename_pattern= :pattern=
|
146
|
+
|
147
|
+
# @macro add_setting
|
148
|
+
# Report the times for the slowest examples (default: `false`).
|
149
|
+
# Use this to specify the number of examples to include in the profile.
|
150
|
+
add_setting :profile_examples
|
151
|
+
|
152
|
+
# @macro add_setting
|
153
|
+
# Run all examples if none match the configured filters (default: `false`).
|
154
|
+
add_setting :run_all_when_everything_filtered
|
155
|
+
|
156
|
+
# @macro add_setting
|
157
|
+
# Color to use to indicate success.
|
158
|
+
# @param [Symbol] color one of the following: [:black, :white, :red, :green, :yellow, :blue, :magenta, :cyan]
|
159
|
+
add_setting :success_color
|
160
|
+
|
161
|
+
# @macro add_setting
|
162
|
+
# Color to use to print pending examples.
|
163
|
+
# @param [Symbol] color one of the following: [:black, :white, :red, :green, :yellow, :blue, :magenta, :cyan]
|
164
|
+
add_setting :pending_color
|
165
|
+
|
166
|
+
# @macro add_setting
|
167
|
+
# Color to use to indicate failure.
|
168
|
+
# @param [Symbol] color one of the following: [:black, :white, :red, :green, :yellow, :blue, :magenta, :cyan]
|
169
|
+
add_setting :failure_color
|
170
|
+
|
171
|
+
# @macro add_setting
|
172
|
+
# The default output color.
|
173
|
+
# @param [Symbol] color one of the following: [:black, :white, :red, :green, :yellow, :blue, :magenta, :cyan]
|
174
|
+
add_setting :default_color
|
175
|
+
|
176
|
+
# @macro add_setting
|
177
|
+
# Color used when a pending example is fixed.
|
178
|
+
# @param [Symbol] color one of the following: [:black, :white, :red, :green, :yellow, :blue, :magenta, :cyan]
|
179
|
+
add_setting :fixed_color
|
180
|
+
|
181
|
+
# @macro add_setting
|
182
|
+
# Color used to print details.
|
183
|
+
# @param [Symbol] color one of the following: [:black, :white, :red, :green, :yellow, :blue, :magenta, :cyan]
|
184
|
+
add_setting :detail_color
|
185
|
+
|
186
|
+
# @macro add_setting
|
187
|
+
# When a block passed to pending fails (as expected), display the failure
|
188
|
+
# without reporting it as a failure (default: false).
|
189
|
+
add_setting :show_failures_in_pending_blocks
|
190
|
+
|
191
|
+
# Deprecated. This config option was added in RSpec 2 to pave the way
|
192
|
+
# for this being the default behavior in RSpec 3. Now this option is
|
193
|
+
# a no-op.
|
194
|
+
def treat_symbols_as_metadata_keys_with_true_values=(value)
|
195
|
+
RSpec.deprecate("RSpec::Core::Configuration#treat_symbols_as_metadata_keys_with_true_values=")
|
196
|
+
end
|
197
|
+
|
198
|
+
# @private
|
199
|
+
add_setting :tty
|
200
|
+
# @private
|
201
|
+
add_setting :include_or_extend_modules
|
202
|
+
# @private
|
203
|
+
add_setting :files_to_run
|
204
|
+
# @private
|
205
|
+
add_setting :expecting_with_rspec
|
206
|
+
# @private
|
207
|
+
attr_accessor :filter_manager
|
208
|
+
# @private
|
209
|
+
attr_reader :backtrace_formatter, :ordering_manager
|
210
|
+
|
211
|
+
# Alias for rspec-2.x's backtrace_cleaner (now backtrace_formatter)
|
212
|
+
#
|
213
|
+
# TODO: consider deprecating and removing this rather than aliasing in rspec-3?
|
214
|
+
alias backtrace_cleaner backtrace_formatter
|
215
|
+
|
216
|
+
def initialize
|
217
|
+
@expectation_frameworks = []
|
218
|
+
@include_or_extend_modules = []
|
219
|
+
@mock_framework = nil
|
220
|
+
@files_to_run = []
|
221
|
+
@formatters = []
|
222
|
+
@color = false
|
223
|
+
@pattern = '**/*_spec.rb'
|
224
|
+
@failure_exit_code = 1
|
225
|
+
@spec_files_loaded = false
|
226
|
+
|
227
|
+
@backtrace_formatter = BacktraceFormatter.new
|
228
|
+
|
229
|
+
@default_path = 'spec'
|
230
|
+
@deprecation_stream = $stderr
|
231
|
+
@filter_manager = FilterManager.new
|
232
|
+
@ordering_manager = Ordering::ConfigurationManager.new
|
233
|
+
@preferred_options = {}
|
234
|
+
@failure_color = :red
|
235
|
+
@success_color = :green
|
236
|
+
@pending_color = :yellow
|
237
|
+
@default_color = :white
|
238
|
+
@fixed_color = :blue
|
239
|
+
@detail_color = :cyan
|
240
|
+
@profile_examples = false
|
241
|
+
@requires = []
|
242
|
+
@libs = []
|
243
|
+
end
|
244
|
+
|
245
|
+
# @private
|
246
|
+
#
|
247
|
+
# Used to set higher priority option values from the command line.
|
248
|
+
def force(hash)
|
249
|
+
ordering_manager.force(hash)
|
250
|
+
@preferred_options.merge!(hash)
|
251
|
+
self.warnings = value_for :warnings, nil
|
252
|
+
end
|
253
|
+
|
254
|
+
# @private
|
255
|
+
def reset
|
256
|
+
@spec_files_loaded = false
|
257
|
+
@reporter = nil
|
258
|
+
@formatters.clear
|
259
|
+
end
|
260
|
+
|
261
|
+
# @overload add_setting(name)
|
262
|
+
# @overload add_setting(name, opts)
|
263
|
+
# @option opts [Symbol] :default
|
264
|
+
#
|
265
|
+
# set a default value for the generated getter and predicate methods:
|
266
|
+
#
|
267
|
+
# add_setting(:foo, :default => "default value")
|
268
|
+
#
|
269
|
+
# @option opts [Symbol] :alias_with
|
270
|
+
#
|
271
|
+
# Use `:alias_with` to alias the setter, getter, and predicate to another
|
272
|
+
# name, or names:
|
273
|
+
#
|
274
|
+
# add_setting(:foo, :alias_with => :bar)
|
275
|
+
# add_setting(:foo, :alias_with => [:bar, :baz])
|
276
|
+
#
|
277
|
+
# Adds a custom setting to the RSpec.configuration object.
|
278
|
+
#
|
279
|
+
# RSpec.configuration.add_setting :foo
|
280
|
+
#
|
281
|
+
# Used internally and by extension frameworks like rspec-rails, so they
|
282
|
+
# can add config settings that are domain specific. For example:
|
283
|
+
#
|
284
|
+
# RSpec.configure do |c|
|
285
|
+
# c.add_setting :use_transactional_fixtures,
|
286
|
+
# :default => true,
|
287
|
+
# :alias_with => :use_transactional_examples
|
288
|
+
# end
|
289
|
+
#
|
290
|
+
# `add_setting` creates three methods on the configuration object, a
|
291
|
+
# setter, a getter, and a predicate:
|
292
|
+
#
|
293
|
+
# RSpec.configuration.foo=(value)
|
294
|
+
# RSpec.configuration.foo
|
295
|
+
# RSpec.configuration.foo? # returns true if foo returns anything but nil or false
|
296
|
+
def add_setting(name, opts={})
|
297
|
+
default = opts.delete(:default)
|
298
|
+
(class << self; self; end).class_eval do
|
299
|
+
add_setting(name, opts)
|
300
|
+
end
|
301
|
+
send("#{name}=", default) if default
|
302
|
+
end
|
303
|
+
|
304
|
+
# Returns the configured mock framework adapter module
|
305
|
+
def mock_framework
|
306
|
+
mock_with :rspec unless @mock_framework
|
307
|
+
@mock_framework
|
308
|
+
end
|
309
|
+
|
310
|
+
# Delegates to mock_framework=(framework)
|
311
|
+
def mock_framework=(framework)
|
312
|
+
mock_with framework
|
313
|
+
end
|
314
|
+
|
315
|
+
# Regexps used to exclude lines from backtraces.
|
316
|
+
#
|
317
|
+
# Excludes lines from ruby (and jruby) source, installed gems, anything
|
318
|
+
# in any "bin" directory, and any of the rspec libs (outside gem
|
319
|
+
# installs) by default.
|
320
|
+
#
|
321
|
+
# You can modify the list via the getter, or replace it with the setter.
|
322
|
+
#
|
323
|
+
# To override this behaviour and display a full backtrace, use
|
324
|
+
# `--backtrace`on the command line, in a `.rspec` file, or in the
|
325
|
+
# `rspec_options` attribute of RSpec's rake task.
|
326
|
+
def backtrace_exclusion_patterns
|
327
|
+
@backtrace_formatter.exclusion_patterns
|
328
|
+
end
|
329
|
+
|
330
|
+
def backtrace_exclusion_patterns=(patterns)
|
331
|
+
@backtrace_formatter.exclusion_patterns = patterns
|
332
|
+
end
|
333
|
+
|
334
|
+
# Regexps used to include lines in backtraces.
|
335
|
+
#
|
336
|
+
# Defaults to [Regexp.new Dir.getwd].
|
337
|
+
#
|
338
|
+
# Lines that match an exclusion _and_ an inclusion pattern
|
339
|
+
# will be included.
|
340
|
+
#
|
341
|
+
# You can modify the list via the getter, or replace it with the setter.
|
342
|
+
def backtrace_inclusion_patterns
|
343
|
+
@backtrace_formatter.inclusion_patterns
|
344
|
+
end
|
345
|
+
|
346
|
+
def backtrace_inclusion_patterns=(patterns)
|
347
|
+
@backtrace_formatter.inclusion_patterns = patterns
|
348
|
+
end
|
349
|
+
|
350
|
+
# Sets the mock framework adapter module.
|
351
|
+
#
|
352
|
+
# `framework` can be a Symbol or a Module.
|
353
|
+
#
|
354
|
+
# Given any of `:rspec`, `:mocha`, `:flexmock`, or `:rr`, configures the
|
355
|
+
# named framework.
|
356
|
+
#
|
357
|
+
# Given `:nothing`, configures no framework. Use this if you don't use
|
358
|
+
# any mocking framework to save a little bit of overhead.
|
359
|
+
#
|
360
|
+
# Given a Module, includes that module in every example group. The module
|
361
|
+
# should adhere to RSpec's mock framework adapter API:
|
362
|
+
#
|
363
|
+
# setup_mocks_for_rspec
|
364
|
+
# - called before each example
|
365
|
+
#
|
366
|
+
# verify_mocks_for_rspec
|
367
|
+
# - called after each example. Framework should raise an exception
|
368
|
+
# when expectations fail
|
369
|
+
#
|
370
|
+
# teardown_mocks_for_rspec
|
371
|
+
# - called after verify_mocks_for_rspec (even if there are errors)
|
372
|
+
#
|
373
|
+
# If the module responds to `configuration` and `mock_with` receives a block,
|
374
|
+
# it will yield the configuration object to the block e.g.
|
375
|
+
#
|
376
|
+
# config.mock_with OtherMockFrameworkAdapter do |mod_config|
|
377
|
+
# mod_config.custom_setting = true
|
378
|
+
# end
|
379
|
+
def mock_with(framework)
|
380
|
+
framework_module = case framework
|
381
|
+
when Module
|
382
|
+
framework
|
383
|
+
when String, Symbol
|
384
|
+
require case framework.to_s
|
385
|
+
when /rspec/i
|
386
|
+
'rspec/core/mocking/with_rspec'
|
387
|
+
when /mocha/i
|
388
|
+
'rspec/core/mocking/with_mocha'
|
389
|
+
when /rr/i
|
390
|
+
'rspec/core/mocking/with_rr'
|
391
|
+
when /flexmock/i
|
392
|
+
'rspec/core/mocking/with_flexmock'
|
393
|
+
else
|
394
|
+
'rspec/core/mocking/with_absolutely_nothing'
|
395
|
+
end
|
396
|
+
RSpec::Core::MockFrameworkAdapter
|
397
|
+
end
|
398
|
+
|
399
|
+
new_name, old_name = [framework_module, @mock_framework].map do |mod|
|
400
|
+
mod.respond_to?(:framework_name) ? mod.framework_name : :unnamed
|
401
|
+
end
|
402
|
+
|
403
|
+
unless new_name == old_name
|
404
|
+
assert_no_example_groups_defined(:mock_framework)
|
405
|
+
end
|
406
|
+
|
407
|
+
if block_given?
|
408
|
+
raise "#{framework_module} must respond to `configuration` so that mock_with can yield it." unless framework_module.respond_to?(:configuration)
|
409
|
+
yield framework_module.configuration
|
410
|
+
end
|
411
|
+
|
412
|
+
@mock_framework = framework_module
|
413
|
+
end
|
414
|
+
|
415
|
+
# Returns the configured expectation framework adapter module(s)
|
416
|
+
def expectation_frameworks
|
417
|
+
expect_with :rspec if @expectation_frameworks.empty?
|
418
|
+
@expectation_frameworks
|
419
|
+
end
|
420
|
+
|
421
|
+
# Delegates to expect_with(framework)
|
422
|
+
def expectation_framework=(framework)
|
423
|
+
expect_with(framework)
|
424
|
+
end
|
425
|
+
|
426
|
+
# Sets the expectation framework module(s) to be included in each example
|
427
|
+
# group.
|
428
|
+
#
|
429
|
+
# `frameworks` can be `:rspec`, `:stdlib`, a custom module, or any
|
430
|
+
# combination thereof:
|
431
|
+
#
|
432
|
+
# config.expect_with :rspec
|
433
|
+
# config.expect_with :stdlib
|
434
|
+
# config.expect_with :rspec, :stdlib
|
435
|
+
# config.expect_with OtherExpectationFramework
|
436
|
+
#
|
437
|
+
# RSpec will translate `:rspec` and `:stdlib` into the appropriate
|
438
|
+
# modules.
|
439
|
+
#
|
440
|
+
# ## Configuration
|
441
|
+
#
|
442
|
+
# If the module responds to `configuration`, `expect_with` will
|
443
|
+
# yield the `configuration` object if given a block:
|
444
|
+
#
|
445
|
+
# config.expect_with OtherExpectationFramework do |custom_config|
|
446
|
+
# custom_config.custom_setting = true
|
447
|
+
# end
|
448
|
+
def expect_with(*frameworks)
|
449
|
+
modules = frameworks.map do |framework|
|
450
|
+
case framework
|
451
|
+
when Module
|
452
|
+
framework
|
453
|
+
when :rspec
|
454
|
+
require 'rspec/expectations'
|
455
|
+
self.expecting_with_rspec = true
|
456
|
+
::RSpec::Matchers
|
457
|
+
when :stdlib
|
458
|
+
require 'test/unit/assertions'
|
459
|
+
::Test::Unit::Assertions
|
460
|
+
else
|
461
|
+
raise ArgumentError, "#{framework.inspect} is not supported"
|
462
|
+
end
|
463
|
+
end
|
464
|
+
|
465
|
+
if (modules - @expectation_frameworks).any?
|
466
|
+
assert_no_example_groups_defined(:expect_with)
|
467
|
+
end
|
468
|
+
|
469
|
+
if block_given?
|
470
|
+
raise "expect_with only accepts a block with a single argument. Call expect_with #{modules.length} times, once with each argument, instead." if modules.length > 1
|
471
|
+
raise "#{modules.first} must respond to `configuration` so that expect_with can yield it." unless modules.first.respond_to?(:configuration)
|
472
|
+
yield modules.first.configuration
|
473
|
+
end
|
474
|
+
|
475
|
+
@expectation_frameworks.push(*modules)
|
476
|
+
end
|
477
|
+
|
478
|
+
def full_backtrace?
|
479
|
+
@backtrace_formatter.full_backtrace?
|
480
|
+
end
|
481
|
+
|
482
|
+
def full_backtrace=(true_or_false)
|
483
|
+
@backtrace_formatter.full_backtrace = true_or_false
|
484
|
+
end
|
485
|
+
|
486
|
+
def color(output=output_stream)
|
487
|
+
# rspec's built-in formatters all call this with the output argument,
|
488
|
+
# but defaulting to output_stream for backward compatibility with
|
489
|
+
# formatters in extension libs
|
490
|
+
return false unless output_to_tty?(output)
|
491
|
+
value_for(:color, @color)
|
492
|
+
end
|
493
|
+
|
494
|
+
def color=(bool)
|
495
|
+
if bool
|
496
|
+
if RSpec.windows_os? and not ENV['ANSICON']
|
497
|
+
RSpec.warning "You must use ANSICON 1.31 or later (http://adoxa.3eeweb.com/ansicon/) to use colour on Windows"
|
498
|
+
@color = false
|
499
|
+
else
|
500
|
+
@color = true
|
501
|
+
end
|
502
|
+
end
|
503
|
+
end
|
504
|
+
|
505
|
+
# TODO - deprecate color_enabled - probably not until the last 2.x
|
506
|
+
# release before 3.0
|
507
|
+
alias_method :color_enabled, :color
|
508
|
+
alias_method :color_enabled=, :color=
|
509
|
+
define_predicate_for :color_enabled, :color
|
510
|
+
|
511
|
+
def libs=(libs)
|
512
|
+
libs.map do |lib|
|
513
|
+
@libs.unshift lib
|
514
|
+
$LOAD_PATH.unshift lib
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
518
|
+
def requires=(paths)
|
519
|
+
RSpec.deprecate("RSpec::Core::Configuration#requires=(paths)",
|
520
|
+
:replacement => "paths.each {|path| require path}")
|
521
|
+
paths.map {|path| require path}
|
522
|
+
@requires += paths
|
523
|
+
end
|
524
|
+
|
525
|
+
# Run examples defined on `line_numbers` in all files to run.
|
526
|
+
def line_numbers=(line_numbers)
|
527
|
+
filter_run :line_numbers => line_numbers.map{|l| l.to_i}
|
528
|
+
end
|
529
|
+
|
530
|
+
def line_numbers
|
531
|
+
filter.fetch(:line_numbers,[])
|
532
|
+
end
|
533
|
+
|
534
|
+
def full_description=(description)
|
535
|
+
filter_run :full_description => Regexp.union(*Array(description).map {|d| Regexp.new(d) })
|
536
|
+
end
|
537
|
+
|
538
|
+
def full_description
|
539
|
+
filter.fetch :full_description, nil
|
540
|
+
end
|
541
|
+
|
542
|
+
# @overload add_formatter(formatter)
|
543
|
+
#
|
544
|
+
# Adds a formatter to the formatters collection. `formatter` can be a
|
545
|
+
# string representing any of the built-in formatters (see
|
546
|
+
# `built_in_formatter`), or a custom formatter class.
|
547
|
+
#
|
548
|
+
# ### Note
|
549
|
+
#
|
550
|
+
# For internal purposes, `add_formatter` also accepts the name of a class
|
551
|
+
# and paths to use for output streams, but you should consider that a
|
552
|
+
# private api that may change at any time without notice.
|
553
|
+
def add_formatter(formatter_to_use, *paths)
|
554
|
+
formatter_class =
|
555
|
+
built_in_formatter(formatter_to_use) ||
|
556
|
+
custom_formatter(formatter_to_use) ||
|
557
|
+
(raise ArgumentError, "Formatter '#{formatter_to_use}' unknown - maybe you meant 'documentation' or 'progress'?.")
|
558
|
+
|
559
|
+
paths << output if paths.empty?
|
560
|
+
formatters << formatter_class.new(*paths.map {|p| String === p ? file_at(p) : p})
|
561
|
+
end
|
562
|
+
|
563
|
+
alias_method :formatter=, :add_formatter
|
564
|
+
|
565
|
+
def formatters
|
566
|
+
@formatters ||= []
|
567
|
+
end
|
568
|
+
|
569
|
+
def reporter
|
570
|
+
@reporter ||= begin
|
571
|
+
add_formatter('progress') if formatters.empty?
|
572
|
+
add_formatter(RSpec::Core::Formatters::DeprecationFormatter, deprecation_stream, output_stream)
|
573
|
+
Reporter.new(self, *formatters)
|
574
|
+
end
|
575
|
+
end
|
576
|
+
|
577
|
+
# @api private
|
578
|
+
#
|
579
|
+
# Defaults `profile_examples` to 10 examples when `@profile_examples` is `true`.
|
580
|
+
#
|
581
|
+
def profile_examples
|
582
|
+
profile = value_for(:profile_examples, @profile_examples)
|
583
|
+
if profile && !profile.is_a?(Integer)
|
584
|
+
10
|
585
|
+
else
|
586
|
+
profile
|
587
|
+
end
|
588
|
+
end
|
589
|
+
|
590
|
+
# @private
|
591
|
+
def files_or_directories_to_run=(*files)
|
592
|
+
files = files.flatten
|
593
|
+
files << default_path if (command == 'rspec' || Runner.running_in_drb?) && default_path && files.empty?
|
594
|
+
self.files_to_run = get_files_to_run(files)
|
595
|
+
end
|
596
|
+
|
597
|
+
# Creates a method that delegates to `example` including the submitted
|
598
|
+
# `args`. Used internally to add variants of `example` like `pending`:
|
599
|
+
#
|
600
|
+
# @example
|
601
|
+
# alias_example_to :pending, :pending => true
|
602
|
+
#
|
603
|
+
# # This lets you do this:
|
604
|
+
#
|
605
|
+
# describe Thing do
|
606
|
+
# pending "does something" do
|
607
|
+
# thing = Thing.new
|
608
|
+
# end
|
609
|
+
# end
|
610
|
+
#
|
611
|
+
# # ... which is the equivalent of
|
612
|
+
#
|
613
|
+
# describe Thing do
|
614
|
+
# it "does something", :pending => true do
|
615
|
+
# thing = Thing.new
|
616
|
+
# end
|
617
|
+
# end
|
618
|
+
def alias_example_to(new_name, *args)
|
619
|
+
extra_options = Metadata.build_hash_from(args)
|
620
|
+
RSpec::Core::ExampleGroup.alias_example_to(new_name, extra_options)
|
621
|
+
end
|
622
|
+
|
623
|
+
# Define an alias for it_should_behave_like that allows different
|
624
|
+
# language (like "it_has_behavior" or "it_behaves_like") to be
|
625
|
+
# employed when including shared examples.
|
626
|
+
#
|
627
|
+
# Example:
|
628
|
+
#
|
629
|
+
# alias_it_behaves_like_to(:it_has_behavior, 'has behavior:')
|
630
|
+
#
|
631
|
+
# allows the user to include a shared example group like:
|
632
|
+
#
|
633
|
+
# describe Entity do
|
634
|
+
# it_has_behavior 'sortability' do
|
635
|
+
# let(:sortable) { Entity.new }
|
636
|
+
# end
|
637
|
+
# end
|
638
|
+
#
|
639
|
+
# which is reported in the output as:
|
640
|
+
#
|
641
|
+
# Entity
|
642
|
+
# has behavior: sortability
|
643
|
+
# # sortability examples here
|
644
|
+
def alias_it_behaves_like_to(new_name, report_label = '')
|
645
|
+
RSpec::Core::ExampleGroup.alias_it_behaves_like_to(new_name, report_label)
|
646
|
+
end
|
647
|
+
|
648
|
+
alias_method :alias_it_should_behave_like_to, :alias_it_behaves_like_to
|
649
|
+
|
650
|
+
# Adds key/value pairs to the `inclusion_filter`. If `args`
|
651
|
+
# includes any symbols that are not part of the hash, each symbol
|
652
|
+
# is treated as a key in the hash with the value `true`.
|
653
|
+
#
|
654
|
+
# ### Note
|
655
|
+
#
|
656
|
+
# Filters set using this method can be overridden from the command line
|
657
|
+
# or config files (e.g. `.rspec`).
|
658
|
+
#
|
659
|
+
# @example
|
660
|
+
# # given this declaration
|
661
|
+
# describe "something", :foo => 'bar' do
|
662
|
+
# # ...
|
663
|
+
# end
|
664
|
+
#
|
665
|
+
# # any of the following will include that group
|
666
|
+
# config.filter_run_including :foo => 'bar'
|
667
|
+
# config.filter_run_including :foo => /^ba/
|
668
|
+
# config.filter_run_including :foo => lambda {|v| v == 'bar'}
|
669
|
+
# config.filter_run_including :foo => lambda {|v,m| m[:foo] == 'bar'}
|
670
|
+
#
|
671
|
+
# # given a proc with an arity of 1, the lambda is passed the value related to the key, e.g.
|
672
|
+
# config.filter_run_including :foo => lambda {|v| v == 'bar'}
|
673
|
+
#
|
674
|
+
# # given a proc with an arity of 2, the lambda is passed the value related to the key,
|
675
|
+
# # and the metadata itself e.g.
|
676
|
+
# config.filter_run_including :foo => lambda {|v,m| m[:foo] == 'bar'}
|
677
|
+
#
|
678
|
+
# filter_run_including :foo # same as filter_run_including :foo => true
|
679
|
+
def filter_run_including(*args)
|
680
|
+
filter_manager.include_with_low_priority Metadata.build_hash_from(args)
|
681
|
+
end
|
682
|
+
|
683
|
+
alias_method :filter_run, :filter_run_including
|
684
|
+
|
685
|
+
# Clears and reassigns the `inclusion_filter`. Set to `nil` if you don't
|
686
|
+
# want any inclusion filter at all.
|
687
|
+
#
|
688
|
+
# ### Warning
|
689
|
+
#
|
690
|
+
# This overrides any inclusion filters/tags set on the command line or in
|
691
|
+
# configuration files.
|
692
|
+
def inclusion_filter=(filter)
|
693
|
+
filter_manager.include! Metadata.build_hash_from([filter])
|
694
|
+
end
|
695
|
+
|
696
|
+
alias_method :filter=, :inclusion_filter=
|
697
|
+
|
698
|
+
# Returns the `inclusion_filter`. If none has been set, returns an empty
|
699
|
+
# hash.
|
700
|
+
def inclusion_filter
|
701
|
+
filter_manager.inclusions
|
702
|
+
end
|
703
|
+
|
704
|
+
alias_method :filter, :inclusion_filter
|
705
|
+
|
706
|
+
# Adds key/value pairs to the `exclusion_filter`. If `args`
|
707
|
+
# includes any symbols that are not part of the hash, each symbol
|
708
|
+
# is treated as a key in the hash with the value `true`.
|
709
|
+
#
|
710
|
+
# ### Note
|
711
|
+
#
|
712
|
+
# Filters set using this method can be overridden from the command line
|
713
|
+
# or config files (e.g. `.rspec`).
|
714
|
+
#
|
715
|
+
# @example
|
716
|
+
# # given this declaration
|
717
|
+
# describe "something", :foo => 'bar' do
|
718
|
+
# # ...
|
719
|
+
# end
|
720
|
+
#
|
721
|
+
# # any of the following will exclude that group
|
722
|
+
# config.filter_run_excluding :foo => 'bar'
|
723
|
+
# config.filter_run_excluding :foo => /^ba/
|
724
|
+
# config.filter_run_excluding :foo => lambda {|v| v == 'bar'}
|
725
|
+
# config.filter_run_excluding :foo => lambda {|v,m| m[:foo] == 'bar'}
|
726
|
+
#
|
727
|
+
# # given a proc with an arity of 1, the lambda is passed the value related to the key, e.g.
|
728
|
+
# config.filter_run_excluding :foo => lambda {|v| v == 'bar'}
|
729
|
+
#
|
730
|
+
# # given a proc with an arity of 2, the lambda is passed the value related to the key,
|
731
|
+
# # and the metadata itself e.g.
|
732
|
+
# config.filter_run_excluding :foo => lambda {|v,m| m[:foo] == 'bar'}
|
733
|
+
#
|
734
|
+
# filter_run_excluding :foo # same as filter_run_excluding :foo => true
|
735
|
+
def filter_run_excluding(*args)
|
736
|
+
filter_manager.exclude_with_low_priority Metadata.build_hash_from(args)
|
737
|
+
end
|
738
|
+
|
739
|
+
# Clears and reassigns the `exclusion_filter`. Set to `nil` if you don't
|
740
|
+
# want any exclusion filter at all.
|
741
|
+
#
|
742
|
+
# ### Warning
|
743
|
+
#
|
744
|
+
# This overrides any exclusion filters/tags set on the command line or in
|
745
|
+
# configuration files.
|
746
|
+
def exclusion_filter=(filter)
|
747
|
+
filter_manager.exclude! Metadata.build_hash_from([filter])
|
748
|
+
end
|
749
|
+
|
750
|
+
# Returns the `exclusion_filter`. If none has been set, returns an empty
|
751
|
+
# hash.
|
752
|
+
def exclusion_filter
|
753
|
+
filter_manager.exclusions
|
754
|
+
end
|
755
|
+
|
756
|
+
# Tells RSpec to include `mod` in example groups. Methods defined in
|
757
|
+
# `mod` are exposed to examples (not example groups). Use `filters` to
|
758
|
+
# constrain the groups in which to include the module.
|
759
|
+
#
|
760
|
+
# @example
|
761
|
+
#
|
762
|
+
# module AuthenticationHelpers
|
763
|
+
# def login_as(user)
|
764
|
+
# # ...
|
765
|
+
# end
|
766
|
+
# end
|
767
|
+
#
|
768
|
+
# module UserHelpers
|
769
|
+
# def users(username)
|
770
|
+
# # ...
|
771
|
+
# end
|
772
|
+
# end
|
773
|
+
#
|
774
|
+
# RSpec.configure do |config|
|
775
|
+
# config.include(UserHelpers) # included in all modules
|
776
|
+
# config.include(AuthenticationHelpers, :type => :request)
|
777
|
+
# end
|
778
|
+
#
|
779
|
+
# describe "edit profile", :type => :request do
|
780
|
+
# it "can be viewed by owning user" do
|
781
|
+
# login_as users(:jdoe)
|
782
|
+
# get "/profiles/jdoe"
|
783
|
+
# assert_select ".username", :text => 'jdoe'
|
784
|
+
# end
|
785
|
+
# end
|
786
|
+
#
|
787
|
+
# @see #extend
|
788
|
+
def include(mod, *filters)
|
789
|
+
include_or_extend_modules << [:include, mod, Metadata.build_hash_from(filters)]
|
790
|
+
end
|
791
|
+
|
792
|
+
# Tells RSpec to extend example groups with `mod`. Methods defined in
|
793
|
+
# `mod` are exposed to example groups (not examples). Use `filters` to
|
794
|
+
# constrain the groups to extend.
|
795
|
+
#
|
796
|
+
# Similar to `include`, but behavior is added to example groups, which
|
797
|
+
# are classes, rather than the examples, which are instances of those
|
798
|
+
# classes.
|
799
|
+
#
|
800
|
+
# @example
|
801
|
+
#
|
802
|
+
# module UiHelpers
|
803
|
+
# def run_in_browser
|
804
|
+
# # ...
|
805
|
+
# end
|
806
|
+
# end
|
807
|
+
#
|
808
|
+
# RSpec.configure do |config|
|
809
|
+
# config.extend(UiHelpers, :type => :request)
|
810
|
+
# end
|
811
|
+
#
|
812
|
+
# describe "edit profile", :type => :request do
|
813
|
+
# run_in_browser
|
814
|
+
#
|
815
|
+
# it "does stuff in the client" do
|
816
|
+
# # ...
|
817
|
+
# end
|
818
|
+
# end
|
819
|
+
#
|
820
|
+
# @see #include
|
821
|
+
def extend(mod, *filters)
|
822
|
+
include_or_extend_modules << [:extend, mod, Metadata.build_hash_from(filters)]
|
823
|
+
end
|
824
|
+
|
825
|
+
# @private
|
826
|
+
#
|
827
|
+
# Used internally to extend a group with modules using `include` and/or
|
828
|
+
# `extend`.
|
829
|
+
def configure_group(group)
|
830
|
+
include_or_extend_modules.each do |include_or_extend, mod, filters|
|
831
|
+
next unless filters.empty? || group.any_apply?(filters)
|
832
|
+
send("safe_#{include_or_extend}", mod, group)
|
833
|
+
end
|
834
|
+
end
|
835
|
+
|
836
|
+
# @private
|
837
|
+
def safe_include(mod, host)
|
838
|
+
host.send(:include,mod) unless host < mod
|
839
|
+
end
|
840
|
+
|
841
|
+
# @private
|
842
|
+
def setup_load_path_and_require(paths)
|
843
|
+
directories = ['lib', default_path].select { |p| File.directory? p }
|
844
|
+
RSpec::Core::RubyProject.add_to_load_path(*directories)
|
845
|
+
paths.each {|path| require path}
|
846
|
+
@requires += paths
|
847
|
+
end
|
848
|
+
|
849
|
+
# @private
|
850
|
+
if RUBY_VERSION.to_f >= 1.9
|
851
|
+
def safe_extend(mod, host)
|
852
|
+
host.extend(mod) unless (class << host; self; end) < mod
|
853
|
+
end
|
854
|
+
else
|
855
|
+
def safe_extend(mod, host)
|
856
|
+
host.extend(mod) unless (class << host; self; end).included_modules.include?(mod)
|
857
|
+
end
|
858
|
+
end
|
859
|
+
|
860
|
+
# @private
|
861
|
+
def configure_mock_framework
|
862
|
+
RSpec::Core::ExampleGroup.send(:include, mock_framework)
|
863
|
+
end
|
864
|
+
|
865
|
+
# @private
|
866
|
+
def configure_expectation_framework
|
867
|
+
expectation_frameworks.each do |framework|
|
868
|
+
RSpec::Core::ExampleGroup.send(:include, framework)
|
869
|
+
end
|
870
|
+
end
|
871
|
+
|
872
|
+
# @private
|
873
|
+
def load_spec_files
|
874
|
+
files_to_run.uniq.each {|f| load File.expand_path(f) }
|
875
|
+
@spec_files_loaded = true
|
876
|
+
end
|
877
|
+
|
878
|
+
# @private
|
879
|
+
DEFAULT_FORMATTER = lambda { |string| string }
|
880
|
+
|
881
|
+
# Formats the docstring output using the block provided.
|
882
|
+
#
|
883
|
+
# @example
|
884
|
+
# # This will strip the descriptions of both examples and example groups.
|
885
|
+
# RSpec.configure do |config|
|
886
|
+
# config.format_docstrings { |s| s.strip }
|
887
|
+
# end
|
888
|
+
def format_docstrings(&block)
|
889
|
+
@format_docstrings_block = block_given? ? block : DEFAULT_FORMATTER
|
890
|
+
end
|
891
|
+
|
892
|
+
# @private
|
893
|
+
def format_docstrings_block
|
894
|
+
@format_docstrings_block ||= DEFAULT_FORMATTER
|
895
|
+
end
|
896
|
+
|
897
|
+
# @private
|
898
|
+
def self.delegate_to_ordering_manager(*methods)
|
899
|
+
methods.each do |method|
|
900
|
+
define_method method do |*args, &block|
|
901
|
+
ordering_manager.__send__(method, *args, &block)
|
902
|
+
end
|
903
|
+
end
|
904
|
+
end
|
905
|
+
|
906
|
+
# @macro delegate_to_ordering_manager
|
907
|
+
#
|
908
|
+
# Sets the seed value and sets the default global ordering to random.
|
909
|
+
delegate_to_ordering_manager :seed=
|
910
|
+
|
911
|
+
# @macro delegate_to_ordering_manager
|
912
|
+
# Seed for random ordering (default: generated randomly each run).
|
913
|
+
#
|
914
|
+
# When you run specs with `--order random`, RSpec generates a random seed
|
915
|
+
# for the randomization and prints it to the `output_stream` (assuming
|
916
|
+
# you're using RSpec's built-in formatters). If you discover an ordering
|
917
|
+
# dependency (i.e. examples fail intermittently depending on order), set
|
918
|
+
# this (on Configuration or on the command line with `--seed`) to run
|
919
|
+
# using the same seed while you debug the issue.
|
920
|
+
#
|
921
|
+
# We recommend, actually, that you use the command line approach so you
|
922
|
+
# don't accidentally leave the seed encoded.
|
923
|
+
delegate_to_ordering_manager :seed
|
924
|
+
|
925
|
+
# @macro delegate_to_ordering_manager
|
926
|
+
#
|
927
|
+
# Sets the default global order and, if order is `'rand:<seed>'`, also sets the seed.
|
928
|
+
delegate_to_ordering_manager :order=
|
929
|
+
|
930
|
+
# @macro delegate_to_ordering_manager
|
931
|
+
# Registers a named ordering strategy that can later be
|
932
|
+
# used to order an example group's subgroups by adding
|
933
|
+
# `:order => <name>` metadata to the example group.
|
934
|
+
#
|
935
|
+
# @param name [Symbol] The name of the ordering.
|
936
|
+
# @yield Block that will order the given examples or example groups
|
937
|
+
# @yieldparam list [Array<RSpec::Core::Example>, Array<RSpec::Core::ExampleGropu>] The examples or groups to order
|
938
|
+
# @yieldreturn [Array<RSpec::Core::Example>, Array<RSpec::Core::ExampleGroup>] The re-ordered examples or groups
|
939
|
+
#
|
940
|
+
# @example
|
941
|
+
# RSpec.configure do |rspec|
|
942
|
+
# rspec.register_ordering :reverse do |list|
|
943
|
+
# list.reverse
|
944
|
+
# end
|
945
|
+
# end
|
946
|
+
#
|
947
|
+
# describe MyClass, :order => :reverse do
|
948
|
+
# # ...
|
949
|
+
# end
|
950
|
+
#
|
951
|
+
# @note Pass the symbol `:global` to set the ordering strategy that
|
952
|
+
# will be used to order the top-level example groups and any example
|
953
|
+
# groups that do not have declared `:order` metadata.
|
954
|
+
delegate_to_ordering_manager :register_ordering
|
955
|
+
|
956
|
+
# @private
|
957
|
+
delegate_to_ordering_manager :seed_used?, :ordering_registry
|
958
|
+
|
959
|
+
# Set Ruby warnings on or off
|
960
|
+
def warnings= value
|
961
|
+
$VERBOSE = !!value
|
962
|
+
end
|
963
|
+
|
964
|
+
def warnings
|
965
|
+
$VERBOSE
|
966
|
+
end
|
967
|
+
|
968
|
+
private
|
969
|
+
|
970
|
+
def get_files_to_run(paths)
|
971
|
+
FlatMap.flat_map(paths) do |path|
|
972
|
+
path = path.gsub(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
|
973
|
+
File.directory?(path) ? gather_directories(path) : extract_location(path)
|
974
|
+
end.sort
|
975
|
+
end
|
976
|
+
|
977
|
+
def gather_directories(path)
|
978
|
+
stripped = "{#{pattern.gsub(/\s*,\s*/, ',')}}"
|
979
|
+
files = pattern =~ /^#{Regexp.escape path}/ ? Dir[stripped] : Dir["#{path}/#{stripped}"]
|
980
|
+
files.sort
|
981
|
+
end
|
982
|
+
|
983
|
+
def extract_location(path)
|
984
|
+
if path =~ /^(.*?)((?:\:\d+)+)$/
|
985
|
+
path, lines = $1, $2[1..-1].split(":").map{|n| n.to_i}
|
986
|
+
filter_manager.add_location path, lines
|
987
|
+
end
|
988
|
+
path
|
989
|
+
end
|
990
|
+
|
991
|
+
def command
|
992
|
+
$0.split(File::SEPARATOR).last
|
993
|
+
end
|
994
|
+
|
995
|
+
def value_for(key, default=nil)
|
996
|
+
@preferred_options.has_key?(key) ? @preferred_options[key] : default
|
997
|
+
end
|
998
|
+
|
999
|
+
def assert_no_example_groups_defined(config_option)
|
1000
|
+
if RSpec.world.example_groups.any?
|
1001
|
+
raise MustBeConfiguredBeforeExampleGroupsError.new(
|
1002
|
+
"RSpec's #{config_option} configuration option must be configured before " +
|
1003
|
+
"any example groups are defined, but you have already defined a group."
|
1004
|
+
)
|
1005
|
+
end
|
1006
|
+
end
|
1007
|
+
|
1008
|
+
def output_to_tty?(output=output_stream)
|
1009
|
+
tty? || (output.respond_to?(:tty?) && output.tty?)
|
1010
|
+
end
|
1011
|
+
|
1012
|
+
def built_in_formatter(key)
|
1013
|
+
case key.to_s
|
1014
|
+
when 'd', 'doc', 'documentation', 's', 'n', 'spec', 'nested'
|
1015
|
+
require 'rspec/core/formatters/documentation_formatter'
|
1016
|
+
RSpec::Core::Formatters::DocumentationFormatter
|
1017
|
+
when 'h', 'html'
|
1018
|
+
require 'rspec/core/formatters/html_formatter'
|
1019
|
+
RSpec::Core::Formatters::HtmlFormatter
|
1020
|
+
when 'p', 'progress'
|
1021
|
+
require 'rspec/core/formatters/progress_formatter'
|
1022
|
+
RSpec::Core::Formatters::ProgressFormatter
|
1023
|
+
when 'j', 'json'
|
1024
|
+
require 'rspec/core/formatters/json_formatter'
|
1025
|
+
RSpec::Core::Formatters::JsonFormatter
|
1026
|
+
end
|
1027
|
+
end
|
1028
|
+
|
1029
|
+
def custom_formatter(formatter_ref)
|
1030
|
+
if Class === formatter_ref
|
1031
|
+
formatter_ref
|
1032
|
+
elsif string_const?(formatter_ref)
|
1033
|
+
begin
|
1034
|
+
formatter_ref.gsub(/^::/,'').split('::').inject(Object) { |const,string| const.const_get string }
|
1035
|
+
rescue NameError
|
1036
|
+
# require( path_for(formatter_ref) ) ? retry : raise
|
1037
|
+
end
|
1038
|
+
end
|
1039
|
+
end
|
1040
|
+
|
1041
|
+
def string_const?(str)
|
1042
|
+
str.is_a?(String) && /\A[A-Z][a-zA-Z0-9_:]*\z/ =~ str
|
1043
|
+
end
|
1044
|
+
|
1045
|
+
def path_for(const_ref)
|
1046
|
+
underscore_with_fix_for_non_standard_rspec_naming(const_ref)
|
1047
|
+
end
|
1048
|
+
|
1049
|
+
def underscore_with_fix_for_non_standard_rspec_naming(string)
|
1050
|
+
underscore(string).sub(%r{(^|/)r_spec($|/)}, '\\1rspec\\2')
|
1051
|
+
end
|
1052
|
+
|
1053
|
+
# activesupport/lib/active_support/inflector/methods.rb, line 48
|
1054
|
+
def underscore(camel_cased_word)
|
1055
|
+
word = camel_cased_word.to_s.dup
|
1056
|
+
word.gsub!(/::/, '/')
|
1057
|
+
word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
1058
|
+
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
1059
|
+
word.tr!("-", "_")
|
1060
|
+
word.downcase!
|
1061
|
+
word
|
1062
|
+
end
|
1063
|
+
|
1064
|
+
def file_at(path)
|
1065
|
+
FileUtils.mkdir_p(File.dirname(path))
|
1066
|
+
File.new(path, 'w')
|
1067
|
+
end
|
1068
|
+
end
|
1069
|
+
end
|
1070
|
+
end
|