rspec-core 2.99.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +8 -8
- checksums.yaml.gz.sig +0 -0
- data/.yardopts +1 -0
- data/Changelog.md +339 -1
- data/License.txt +1 -0
- data/README.md +19 -37
- data/exe/rspec +2 -23
- data/lib/rspec/core/backport_random.rb +336 -0
- data/lib/rspec/core/backtrace_formatter.rb +70 -0
- data/lib/rspec/core/configuration.rb +479 -577
- data/lib/rspec/core/configuration_options.rb +71 -54
- data/lib/rspec/core/drb.rb +111 -0
- data/lib/rspec/core/dsl.rb +86 -18
- data/lib/rspec/core/example.rb +267 -119
- data/lib/rspec/core/example_group.rb +381 -393
- data/lib/rspec/core/filter_manager.rb +133 -114
- data/lib/rspec/core/flat_map.rb +18 -0
- data/lib/rspec/core/formatters/base_formatter.rb +51 -125
- data/lib/rspec/core/formatters/base_text_formatter.rb +34 -286
- data/lib/rspec/core/formatters/console_codes.rb +24 -1
- data/lib/rspec/core/formatters/deprecation_formatter.rb +25 -26
- data/lib/rspec/core/formatters/documentation_formatter.rb +27 -25
- data/lib/rspec/core/formatters/helpers.rb +14 -36
- data/lib/rspec/core/formatters/html_formatter.rb +58 -65
- data/lib/rspec/core/formatters/html_printer.rb +12 -18
- data/lib/rspec/core/formatters/json_formatter.rb +54 -31
- data/lib/rspec/core/formatters/profile_formatter.rb +67 -0
- data/lib/rspec/core/formatters/progress_formatter.rb +11 -15
- data/lib/rspec/core/formatters/snippet_extractor.rb +22 -11
- data/lib/rspec/core/formatters.rb +90 -43
- data/lib/rspec/core/hooks.rb +325 -270
- data/lib/rspec/core/memoized_helpers.rb +45 -156
- data/lib/rspec/core/metadata.rb +284 -236
- data/lib/rspec/core/metadata_filter.rb +86 -0
- data/lib/rspec/core/mocking_adapters/flexmock.rb +29 -0
- data/lib/rspec/core/{mocking/with_mocha.rb → mocking_adapters/mocha.rb} +19 -16
- data/lib/rspec/core/mocking_adapters/null.rb +12 -0
- data/lib/rspec/core/mocking_adapters/rr.rb +29 -0
- data/lib/rspec/core/mocking_adapters/rspec.rb +30 -0
- data/lib/rspec/core/notifications.rb +511 -0
- data/lib/rspec/core/option_parser.rb +49 -74
- data/lib/rspec/core/ordering.rb +156 -0
- data/lib/rspec/core/pending.rb +94 -96
- data/lib/rspec/core/project_initializer/.rspec +3 -0
- data/lib/rspec/core/project_initializer/spec/spec_helper.rb +78 -0
- data/lib/rspec/core/project_initializer.rb +24 -64
- data/lib/rspec/core/rake_task.rb +44 -130
- data/lib/rspec/core/reporter.rb +76 -59
- data/lib/rspec/core/ruby_project.rb +2 -1
- data/lib/rspec/core/runner.rb +117 -52
- data/lib/rspec/core/shared_context.rb +10 -10
- data/lib/rspec/core/shared_example_group.rb +108 -121
- data/lib/rspec/core/version.rb +3 -1
- data/lib/rspec/core/warnings.rb +40 -0
- data/lib/rspec/core/world.rb +66 -10
- data/lib/rspec/core.rb +64 -104
- data.tar.gz.sig +3 -0
- metadata +75 -322
- metadata.gz.sig +1 -0
- data/exe/autospec +0 -13
- data/features/Autotest.md +0 -38
- data/features/README.md +0 -17
- data/features/Upgrade.md +0 -364
- data/features/command_line/README.md +0 -28
- data/features/command_line/example_name_option.feature +0 -97
- data/features/command_line/exit_status.feature +0 -82
- data/features/command_line/format_option.feature +0 -75
- data/features/command_line/init.feature +0 -18
- data/features/command_line/line_number_appended_to_path.feature +0 -140
- data/features/command_line/line_number_option.feature +0 -53
- data/features/command_line/order.feature +0 -26
- data/features/command_line/pattern_option.feature +0 -49
- data/features/command_line/rake_task.feature +0 -122
- data/features/command_line/require_option.feature +0 -43
- data/features/command_line/ruby.feature +0 -22
- data/features/command_line/tag.feature +0 -98
- data/features/command_line/warnings_option.feature +0 -29
- data/features/configuration/alias_example_to.feature +0 -48
- data/features/configuration/backtrace_clean_patterns.feature +0 -102
- data/features/configuration/custom_settings.feature +0 -84
- data/features/configuration/default_path.feature +0 -38
- data/features/configuration/deprecation_stream.feature +0 -58
- data/features/configuration/fail_fast.feature +0 -77
- data/features/configuration/failure_exit_code.feature +0 -36
- data/features/configuration/order_and_seed.feature +0 -3
- data/features/configuration/output_stream.feature +0 -24
- data/features/configuration/pattern.feature +0 -38
- data/features/configuration/profile.feature +0 -220
- data/features/configuration/read_options_from_file.feature +0 -90
- data/features/configuration/run_all_when_everything_filtered.feature +0 -76
- data/features/configuration/show_failures_in_pending_blocks.feature +0 -61
- data/features/configuration/treat_symbols_as_metadata_keys_with_true_values.feature +0 -52
- data/features/example_groups/basic_structure.feature +0 -55
- data/features/example_groups/shared_context.feature +0 -74
- data/features/example_groups/shared_examples.feature +0 -294
- data/features/expectation_framework_integration/configure_expectation_framework.feature +0 -197
- data/features/filtering/exclusion_filters.feature +0 -138
- data/features/filtering/if_and_unless.feature +0 -168
- data/features/filtering/inclusion_filters.feature +0 -105
- data/features/formatters/configurable_colors.feature +0 -31
- data/features/formatters/custom_formatter.feature +0 -36
- data/features/formatters/json_formatter.feature +0 -30
- data/features/formatters/text_formatter.feature +0 -46
- data/features/helper_methods/arbitrary_methods.feature +0 -40
- data/features/helper_methods/let.feature +0 -50
- data/features/helper_methods/modules.feature +0 -149
- data/features/hooks/around_hooks.feature +0 -343
- data/features/hooks/before_and_after_hooks.feature +0 -427
- data/features/hooks/filtering.feature +0 -234
- data/features/metadata/current_example.feature +0 -56
- data/features/metadata/described_class.feature +0 -17
- data/features/metadata/user_defined.feature +0 -113
- data/features/mock_framework_integration/use_any_framework.feature +0 -106
- data/features/mock_framework_integration/use_flexmock.feature +0 -96
- data/features/mock_framework_integration/use_mocha.feature +0 -97
- data/features/mock_framework_integration/use_rr.feature +0 -98
- data/features/mock_framework_integration/use_rspec.feature +0 -97
- data/features/pending/pending_examples.feature +0 -229
- data/features/spec_files/arbitrary_file_suffix.feature +0 -13
- data/features/step_definitions/additional_cli_steps.rb +0 -49
- data/features/subject/attribute_of_subject.feature +0 -124
- data/features/subject/explicit_subject.feature +0 -101
- data/features/subject/implicit_subject.feature +0 -63
- data/features/subject/one_liner_syntax.feature +0 -71
- data/features/support/env.rb +0 -14
- data/features/support/rubinius.rb +0 -6
- data/lib/autotest/discover.rb +0 -10
- data/lib/autotest/rspec2.rb +0 -77
- data/lib/rspec/core/backtrace_cleaner.rb +0 -46
- data/lib/rspec/core/backward_compatibility.rb +0 -55
- data/lib/rspec/core/caller_filter.rb +0 -60
- data/lib/rspec/core/command_line.rb +0 -47
- data/lib/rspec/core/deprecated_mutable_array_proxy.rb +0 -32
- data/lib/rspec/core/deprecation.rb +0 -26
- data/lib/rspec/core/drb_command_line.rb +0 -26
- data/lib/rspec/core/drb_options.rb +0 -87
- data/lib/rspec/core/extensions/instance_eval_with_args.rb +0 -44
- data/lib/rspec/core/extensions/kernel.rb +0 -9
- data/lib/rspec/core/extensions/module_eval_with_args.rb +0 -38
- data/lib/rspec/core/extensions/ordered.rb +0 -27
- data/lib/rspec/core/formatters/text_mate_formatter.rb +0 -34
- data/lib/rspec/core/metadata_hash_builder.rb +0 -97
- data/lib/rspec/core/mocking/with_absolutely_nothing.rb +0 -11
- data/lib/rspec/core/mocking/with_flexmock.rb +0 -27
- data/lib/rspec/core/mocking/with_rr.rb +0 -27
- data/lib/rspec/core/mocking/with_rspec.rb +0 -27
- data/lib/rspec/core/shared_example_group/collection.rb +0 -45
- data/spec/autotest/discover_spec.rb +0 -49
- data/spec/autotest/failed_results_re_spec.rb +0 -45
- data/spec/autotest/rspec_spec.rb +0 -133
- data/spec/command_line/order_spec.rb +0 -204
- data/spec/rspec/core/backtrace_cleaner_spec.rb +0 -68
- data/spec/rspec/core/caller_filter_spec.rb +0 -58
- data/spec/rspec/core/command_line_spec.rb +0 -127
- data/spec/rspec/core/command_line_spec_output.txt +0 -0
- data/spec/rspec/core/configuration_options_spec.rb +0 -417
- data/spec/rspec/core/configuration_spec.rb +0 -2072
- data/spec/rspec/core/deprecation_spec.rb +0 -27
- data/spec/rspec/core/deprecations_spec.rb +0 -59
- data/spec/rspec/core/drb_command_line_spec.rb +0 -102
- data/spec/rspec/core/drb_options_spec.rb +0 -193
- data/spec/rspec/core/dsl_spec.rb +0 -25
- data/spec/rspec/core/example_group_spec.rb +0 -1337
- data/spec/rspec/core/example_spec.rb +0 -502
- data/spec/rspec/core/filter_manager_spec.rb +0 -246
- data/spec/rspec/core/formatters/base_formatter_spec.rb +0 -108
- data/spec/rspec/core/formatters/base_text_formatter_spec.rb +0 -524
- data/spec/rspec/core/formatters/console_codes_spec.rb +0 -50
- data/spec/rspec/core/formatters/deprecation_formatter_spec.rb +0 -263
- data/spec/rspec/core/formatters/documentation_formatter_spec.rb +0 -89
- data/spec/rspec/core/formatters/helpers_spec.rb +0 -104
- data/spec/rspec/core/formatters/html_formatted.html +0 -397
- data/spec/rspec/core/formatters/html_formatter_spec.rb +0 -131
- data/spec/rspec/core/formatters/json_formatter_spec.rb +0 -115
- data/spec/rspec/core/formatters/progress_formatter_spec.rb +0 -30
- data/spec/rspec/core/formatters/snippet_extractor_spec.rb +0 -26
- data/spec/rspec/core/formatters/text_mate_formatted.html +0 -397
- data/spec/rspec/core/formatters/text_mate_formatter_spec.rb +0 -107
- data/spec/rspec/core/hooks_filtering_spec.rb +0 -227
- data/spec/rspec/core/hooks_spec.rb +0 -269
- data/spec/rspec/core/kernel_extensions_spec.rb +0 -9
- data/spec/rspec/core/memoized_helpers_spec.rb +0 -776
- data/spec/rspec/core/metadata_spec.rb +0 -514
- data/spec/rspec/core/option_parser_spec.rb +0 -297
- data/spec/rspec/core/pending_example_spec.rb +0 -260
- data/spec/rspec/core/pending_spec.rb +0 -27
- data/spec/rspec/core/project_initializer_spec.rb +0 -130
- data/spec/rspec/core/rake_task_spec.rb +0 -202
- data/spec/rspec/core/reporter_spec.rb +0 -167
- data/spec/rspec/core/resources/a_bar.rb +0 -0
- data/spec/rspec/core/resources/a_foo.rb +0 -0
- data/spec/rspec/core/resources/a_spec.rb +0 -1
- data/spec/rspec/core/resources/custom_example_group_runner.rb +0 -14
- data/spec/rspec/core/resources/formatter_specs.rb +0 -60
- data/spec/rspec/core/resources/utf8_encoded.rb +0 -8
- data/spec/rspec/core/rspec_matchers_spec.rb +0 -45
- data/spec/rspec/core/ruby_project_spec.rb +0 -26
- data/spec/rspec/core/runner_spec.rb +0 -82
- data/spec/rspec/core/shared_context_spec.rb +0 -114
- data/spec/rspec/core/shared_example_group/collection_spec.rb +0 -70
- data/spec/rspec/core/shared_example_group_spec.rb +0 -138
- data/spec/rspec/core/world_spec.rb +0 -142
- data/spec/rspec/core_spec.rb +0 -108
- data/spec/spec_helper.rb +0 -135
- data/spec/support/config_options_helper.rb +0 -15
- data/spec/support/helper_methods.rb +0 -55
- data/spec/support/in_sub_process.rb +0 -37
- data/spec/support/isolate_load_path_mutation.rb +0 -6
- data/spec/support/isolated_directory.rb +0 -10
- data/spec/support/isolated_home_directory.rb +0 -16
- data/spec/support/matchers.rb +0 -65
- data/spec/support/mathn_integration_support.rb +0 -12
- data/spec/support/sandboxed_mock_space.rb +0 -116
- data/spec/support/shared_example_groups.rb +0 -42
- data/spec/support/silence_dsl_deprecations.rb +0 -32
- data/spec/support/spec_files.rb +0 -44
data/lib/rspec/core/metadata.rb
CHANGED
|
@@ -24,11 +24,11 @@ module RSpec
|
|
|
24
24
|
# @see FilterManager
|
|
25
25
|
# @see Configuration#filter_run_including
|
|
26
26
|
# @see Configuration#filter_run_excluding
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
module Metadata
|
|
28
|
+
# @api private
|
|
29
|
+
#
|
|
30
|
+
# @param line [String] current code line
|
|
31
|
+
# @return [String] relative path to line
|
|
32
32
|
def self.relative_path(line)
|
|
33
33
|
line = line.sub(File.expand_path("."), ".")
|
|
34
34
|
line = line.sub(/\A([^:]+:\d+)$/, '\\1')
|
|
@@ -39,323 +39,371 @@ module RSpec
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
# @private
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
42
|
+
# Used internally to build a hash from an args array.
|
|
43
|
+
# Symbols are converted into hash keys with a value of `true`.
|
|
44
|
+
# This is done to support simple tagging using a symbol, rather
|
|
45
|
+
# than needing to do `:symbol => true`.
|
|
46
|
+
def self.build_hash_from(args)
|
|
47
|
+
hash = args.last.is_a?(Hash) ? args.pop : {}
|
|
48
|
+
|
|
49
|
+
while args.last.is_a?(Symbol)
|
|
50
|
+
hash[args.pop] = true
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
hash
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# @private
|
|
57
|
+
def self.backtrace_from(block)
|
|
58
|
+
return caller unless block.respond_to?(:source_location)
|
|
59
|
+
[block.source_location.join(':')]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# @private
|
|
63
|
+
# Used internally to populate metadata hashes with computed keys
|
|
64
|
+
# managed by RSpec.
|
|
65
|
+
class HashPopulator
|
|
66
|
+
attr_reader :metadata, :user_metadata, :description_args, :block
|
|
67
|
+
|
|
68
|
+
def initialize(metadata, user_metadata, description_args, block)
|
|
69
|
+
@metadata = metadata
|
|
70
|
+
@user_metadata = user_metadata
|
|
71
|
+
@description_args = description_args
|
|
72
|
+
@block = block
|
|
56
73
|
end
|
|
57
74
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
klass = described_class
|
|
72
|
-
store(:described_class, klass)
|
|
73
|
-
# TODO (2011-11-07 DC) deprecate :describes as a key
|
|
74
|
-
store(:describes, klass)
|
|
75
|
-
when :full_description
|
|
76
|
-
store(:full_description, full_description)
|
|
77
|
-
when :description
|
|
78
|
-
store(:description, build_description_from(*self[:description_args]))
|
|
79
|
-
when :description_args
|
|
80
|
-
store(:description_args, [])
|
|
81
|
-
end
|
|
75
|
+
def populate
|
|
76
|
+
ensure_valid_user_keys
|
|
77
|
+
|
|
78
|
+
metadata[:execution_result] = Example::ExecutionResult.new
|
|
79
|
+
metadata[:block] = block
|
|
80
|
+
metadata[:description_args] = description_args
|
|
81
|
+
metadata[:description] = build_description_from(*metadata[:description_args])
|
|
82
|
+
metadata[:full_description] = full_description
|
|
83
|
+
metadata[:described_class] = described_class
|
|
84
|
+
|
|
85
|
+
populate_location_attributes
|
|
86
|
+
metadata.update(user_metadata)
|
|
87
|
+
RSpec.configuration.apply_derived_metadata_to(metadata)
|
|
82
88
|
end
|
|
83
89
|
|
|
84
|
-
|
|
85
|
-
|
|
90
|
+
private
|
|
91
|
+
|
|
92
|
+
def populate_location_attributes
|
|
93
|
+
file_path, line_number = if backtrace = user_metadata.delete(:caller)
|
|
94
|
+
file_path_and_line_number_from(backtrace)
|
|
95
|
+
elsif block.respond_to?(:source_location)
|
|
96
|
+
block.source_location
|
|
97
|
+
else
|
|
98
|
+
file_path_and_line_number_from(caller)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
file_path = Metadata.relative_path(file_path)
|
|
102
|
+
metadata[:file_path] = file_path
|
|
103
|
+
metadata[:line_number] = line_number.to_i
|
|
104
|
+
metadata[:location] = "#{file_path}:#{line_number}"
|
|
86
105
|
end
|
|
87
106
|
|
|
88
|
-
def
|
|
89
|
-
first_caller_from_outside_rspec
|
|
90
|
-
|
|
107
|
+
def file_path_and_line_number_from(backtrace)
|
|
108
|
+
first_caller_from_outside_rspec = backtrace.detect { |l| l !~ CallerFilter::LIB_REGEX }
|
|
109
|
+
first_caller_from_outside_rspec ||= backtrace.first
|
|
110
|
+
/(.+?):(\d+)(?:|:\d+)/.match(first_caller_from_outside_rspec).captures
|
|
91
111
|
end
|
|
92
112
|
|
|
93
|
-
def
|
|
94
|
-
|
|
113
|
+
def description_separator(parent_part, child_part)
|
|
114
|
+
if parent_part.is_a?(Module) && child_part =~ /^(#|::|\.)/
|
|
115
|
+
''
|
|
116
|
+
else
|
|
117
|
+
' '
|
|
118
|
+
end
|
|
95
119
|
end
|
|
96
120
|
|
|
97
|
-
def
|
|
98
|
-
return
|
|
99
|
-
|
|
121
|
+
def build_description_from(parent_description=nil, my_description=nil)
|
|
122
|
+
return parent_description.to_s unless my_description
|
|
123
|
+
separator = description_separator(parent_description, my_description)
|
|
124
|
+
parent_description.to_s + separator + my_description
|
|
100
125
|
end
|
|
101
126
|
|
|
102
|
-
def
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
127
|
+
def ensure_valid_user_keys
|
|
128
|
+
RESERVED_KEYS.each do |key|
|
|
129
|
+
if user_metadata.has_key?(key)
|
|
130
|
+
raise <<-EOM.gsub(/^\s+\|/, '')
|
|
131
|
+
|#{"*"*50}
|
|
132
|
+
|:#{key} is not allowed
|
|
133
|
+
|
|
|
134
|
+
|RSpec reserves some hash keys for its own internal use,
|
|
135
|
+
|including :#{key}, which is used on:
|
|
136
|
+
|
|
|
137
|
+
| #{CallerFilter.first_non_rspec_line}.
|
|
138
|
+
|
|
|
139
|
+
|Here are all of RSpec's reserved hash keys:
|
|
140
|
+
|
|
|
141
|
+
| #{RESERVED_KEYS.join("\n ")}
|
|
142
|
+
|#{"*"*50}
|
|
143
|
+
EOM
|
|
144
|
+
end
|
|
107
145
|
end
|
|
108
|
-
|
|
109
|
-
description
|
|
110
146
|
end
|
|
111
147
|
end
|
|
112
148
|
|
|
113
|
-
#
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
149
|
+
# @private
|
|
150
|
+
class ExampleHash < HashPopulator
|
|
151
|
+
def self.create(group_metadata, user_metadata, description, block)
|
|
152
|
+
example_metadata = group_metadata.dup
|
|
153
|
+
group_metadata = Hash.new(&ExampleGroupHash.backwards_compatibility_default_proc do |hash|
|
|
154
|
+
hash[:parent_example_group]
|
|
155
|
+
end)
|
|
156
|
+
group_metadata.update(example_metadata)
|
|
157
|
+
|
|
158
|
+
example_metadata[:example_group] = group_metadata
|
|
159
|
+
example_metadata.delete(:parent_example_group)
|
|
160
|
+
|
|
161
|
+
hash = new(example_metadata, user_metadata, [description].compact, block)
|
|
162
|
+
hash.populate
|
|
163
|
+
hash.metadata
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
private
|
|
117
167
|
|
|
118
168
|
def described_class
|
|
119
|
-
|
|
169
|
+
metadata[:example_group][:described_class]
|
|
120
170
|
end
|
|
121
171
|
|
|
122
172
|
def full_description
|
|
123
|
-
build_description_from(
|
|
173
|
+
build_description_from(
|
|
174
|
+
metadata[:example_group][:full_description],
|
|
175
|
+
metadata[:description]
|
|
176
|
+
)
|
|
124
177
|
end
|
|
125
178
|
end
|
|
126
179
|
|
|
127
|
-
#
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
180
|
+
# @private
|
|
181
|
+
class ExampleGroupHash < HashPopulator
|
|
182
|
+
def self.create(parent_group_metadata, user_metadata, *args, &block)
|
|
183
|
+
group_metadata = hash_with_backwards_compatibility_default_proc
|
|
131
184
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
value_for_rspec_2 = described_class_for_rspec_2
|
|
136
|
-
value_for_rspec_3 = described_class_for_rspec_3
|
|
137
|
-
|
|
138
|
-
if value_for_rspec_2 != value_for_rspec_3
|
|
139
|
-
RSpec.warn_deprecation(<<-EOS.gsub(/^\s+\|/, ''))
|
|
140
|
-
|The semantics of `described_class` in a nested `describe <SomeClass>`
|
|
141
|
-
|example group are changing in RSpec 3. In RSpec 2.x, `described_class`
|
|
142
|
-
|would return the outermost described class (#{value_for_rspec_2.inspect}).
|
|
143
|
-
|In RSpec 3, it will return the innermost described class (#{value_for_rspec_3.inspect}).
|
|
144
|
-
|In general, we recommend not describing multiple classes or objects in a
|
|
145
|
-
|nested manner as it creates confusion.
|
|
146
|
-
|
|
|
147
|
-
|To make your code compatible with RSpec 3, change from `described_class` to a reference
|
|
148
|
-
|to `#{value_for_rspec_3.inspect}`, or change the arg of the inner `describe` to a string.
|
|
149
|
-
|(Called from #{CallerFilter.first_non_rspec_line})
|
|
150
|
-
EOS
|
|
185
|
+
if parent_group_metadata
|
|
186
|
+
group_metadata.update(parent_group_metadata)
|
|
187
|
+
group_metadata[:parent_example_group] = parent_group_metadata
|
|
151
188
|
end
|
|
152
189
|
|
|
153
|
-
|
|
190
|
+
hash = new(group_metadata, user_metadata, args, block)
|
|
191
|
+
hash.populate
|
|
192
|
+
hash.metadata
|
|
154
193
|
end
|
|
155
194
|
|
|
156
|
-
def
|
|
157
|
-
|
|
158
|
-
[:described_class, :describes].each do |key|
|
|
159
|
-
if g.has_key?(key)
|
|
160
|
-
value = g[key]
|
|
161
|
-
return value unless value.nil?
|
|
162
|
-
end
|
|
163
|
-
end
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
container_stack.reverse.each do |g|
|
|
167
|
-
candidate = g[:description_args].first
|
|
168
|
-
return candidate unless String === candidate || Symbol === candidate
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
nil
|
|
195
|
+
def self.hash_with_backwards_compatibility_default_proc
|
|
196
|
+
Hash.new(&backwards_compatibility_default_proc { |hash| hash })
|
|
172
197
|
end
|
|
173
198
|
|
|
174
|
-
def
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
199
|
+
def self.backwards_compatibility_default_proc(&example_group_selector)
|
|
200
|
+
Proc.new do |hash, key|
|
|
201
|
+
case key
|
|
202
|
+
when :example_group
|
|
203
|
+
RSpec.deprecate("The `:example_group` key in an example group's metadata hash",
|
|
204
|
+
:replacement => "the example group's hash directly for the " +
|
|
205
|
+
"computed keys and `:parent_example_group` to access the parent " +
|
|
206
|
+
"example group metadata")
|
|
207
|
+
group_hash = example_group_selector.call(hash)
|
|
208
|
+
LegacyExampleGroupHash.new(group_hash) if group_hash
|
|
209
|
+
when :example_group_block
|
|
210
|
+
RSpec.deprecate("`metadata[:example_group_block]`",
|
|
211
|
+
:replacement => "`metadata[:block]`")
|
|
212
|
+
hash[:block]
|
|
213
|
+
when :describes
|
|
214
|
+
RSpec.deprecate("`metadata[:describes]`",
|
|
215
|
+
:replacement => "`metadata[:described_class]`")
|
|
216
|
+
hash[:described_class]
|
|
181
217
|
end
|
|
182
|
-
|
|
183
|
-
candidate = g[:description_args].first
|
|
184
|
-
return candidate unless NilClass === candidate || String === candidate || Symbol === candidate
|
|
185
218
|
end
|
|
186
|
-
|
|
187
|
-
nil
|
|
188
219
|
end
|
|
189
220
|
|
|
190
|
-
|
|
191
|
-
return unless behavior_change = self[:description_arg_behavior_changing_in_rspec_3]
|
|
192
|
-
RSpec.warn_deprecation(behavior_change.warning)
|
|
193
|
-
end
|
|
221
|
+
private
|
|
194
222
|
|
|
195
|
-
def
|
|
196
|
-
|
|
223
|
+
def described_class
|
|
224
|
+
candidate = metadata[:description_args].first
|
|
225
|
+
return candidate unless NilClass === candidate || String === candidate
|
|
226
|
+
parent_group = metadata[:parent_example_group]
|
|
227
|
+
parent_group && parent_group[:described_class]
|
|
197
228
|
end
|
|
198
229
|
|
|
199
230
|
def full_description
|
|
200
|
-
|
|
201
|
-
|
|
231
|
+
description = metadata[:description]
|
|
232
|
+
parent_example_group = metadata[:parent_example_group]
|
|
233
|
+
return description unless parent_example_group
|
|
202
234
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
while group.has_key?(:example_group)
|
|
207
|
-
groups << group[:example_group]
|
|
208
|
-
group = group[:example_group]
|
|
209
|
-
end
|
|
210
|
-
groups
|
|
211
|
-
end
|
|
212
|
-
end
|
|
213
|
-
end
|
|
235
|
+
parent_description = parent_example_group[:full_description]
|
|
236
|
+
separator = description_separator(parent_example_group[:description_args].last,
|
|
237
|
+
metadata[:description_args].first)
|
|
214
238
|
|
|
215
|
-
|
|
216
|
-
if parent_group_metadata
|
|
217
|
-
update(parent_group_metadata)
|
|
218
|
-
store(:example_group, {:example_group => parent_group_metadata[:example_group].extend(GroupMetadataHash)}.extend(GroupMetadataHash))
|
|
219
|
-
else
|
|
220
|
-
store(:example_group, {}.extend(GroupMetadataHash))
|
|
239
|
+
parent_description + separator + description
|
|
221
240
|
end
|
|
222
|
-
|
|
223
|
-
yield self if block_given?
|
|
224
241
|
end
|
|
225
242
|
|
|
226
243
|
# @private
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
244
|
+
RESERVED_KEYS = [
|
|
245
|
+
:description,
|
|
246
|
+
:example_group,
|
|
247
|
+
:parent_example_group,
|
|
248
|
+
:execution_result,
|
|
249
|
+
:file_path,
|
|
250
|
+
:full_description,
|
|
251
|
+
:line_number,
|
|
252
|
+
:location,
|
|
253
|
+
:block
|
|
254
|
+
]
|
|
255
|
+
end
|
|
234
256
|
|
|
235
|
-
|
|
257
|
+
# Mixin that makes the including class imitate a hash for backwards
|
|
258
|
+
# compatibility. The including class should use `attr_accessor` to
|
|
259
|
+
# declare attributes.
|
|
260
|
+
# @private
|
|
261
|
+
module HashImitatable
|
|
262
|
+
def self.included(klass)
|
|
263
|
+
klass.extend ClassMethods
|
|
236
264
|
end
|
|
237
265
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
dup.extend(ExampleMetadataHash).configure_for_example(description, user_metadata)
|
|
241
|
-
end
|
|
266
|
+
def to_h
|
|
267
|
+
hash = extra_hash_attributes.dup
|
|
242
268
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
end
|
|
269
|
+
self.class.hash_attribute_names.each do |name|
|
|
270
|
+
hash[name] = __send__(name)
|
|
271
|
+
end
|
|
247
272
|
|
|
248
|
-
|
|
249
|
-
def all_apply?(filters)
|
|
250
|
-
filters.all? {|k,v| filter_applies?(k,v)}
|
|
273
|
+
hash
|
|
251
274
|
end
|
|
252
275
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
return metadata.filter_applies_to_any_value?(key, value) if Array === metadata[key] && !(Proc === value)
|
|
276
|
+
(Hash.public_instance_methods - Object.public_instance_methods).each do |method_name|
|
|
277
|
+
next if [:[], :[]=, :to_h].include?(method_name.to_sym)
|
|
256
278
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
279
|
+
define_method(method_name) do |*args, &block|
|
|
280
|
+
issue_deprecation(method_name, *args)
|
|
281
|
+
|
|
282
|
+
hash = hash_for_delegation
|
|
283
|
+
self.class.hash_attribute_names.each do |name|
|
|
284
|
+
hash.delete(name) unless instance_variable_defined?(:"@#{name}")
|
|
261
285
|
end
|
|
262
286
|
|
|
263
|
-
|
|
287
|
+
hash.__send__(method_name, *args, &block).tap do
|
|
288
|
+
# apply mutations back to the object
|
|
289
|
+
hash.each do |name, value|
|
|
290
|
+
if directly_supports_attribute?(name)
|
|
291
|
+
set_value(name, value)
|
|
292
|
+
else
|
|
293
|
+
extra_hash_attributes[name] = value
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
end
|
|
264
297
|
end
|
|
298
|
+
end
|
|
265
299
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
return false unless metadata.has_key?(key)
|
|
300
|
+
def [](key)
|
|
301
|
+
issue_deprecation(:[], key)
|
|
270
302
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
metadata[key] =~ value
|
|
274
|
-
when Proc
|
|
275
|
-
case value.arity
|
|
276
|
-
when 0 then value.call
|
|
277
|
-
when 2 then value.call(metadata[key], metadata)
|
|
278
|
-
else value.call(metadata[key])
|
|
279
|
-
end
|
|
303
|
+
if directly_supports_attribute?(key)
|
|
304
|
+
get_value(key)
|
|
280
305
|
else
|
|
281
|
-
|
|
306
|
+
extra_hash_attributes[key]
|
|
282
307
|
end
|
|
283
308
|
end
|
|
284
309
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
310
|
+
def []=(key, value)
|
|
311
|
+
issue_deprecation(:[]=, key, value)
|
|
312
|
+
|
|
313
|
+
if directly_supports_attribute?(key)
|
|
314
|
+
set_value(key, value)
|
|
315
|
+
else
|
|
316
|
+
extra_hash_attributes[key] = value
|
|
317
|
+
end
|
|
288
318
|
end
|
|
289
319
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
320
|
+
private
|
|
321
|
+
|
|
322
|
+
def extra_hash_attributes
|
|
323
|
+
@extra_hash_attributes ||= {}
|
|
293
324
|
end
|
|
294
325
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
# it ignores location filters for other files
|
|
298
|
-
line_number = example_group_declaration_line(locations)
|
|
299
|
-
line_number ? line_number_filter_applies?(line_number) : true
|
|
326
|
+
def directly_supports_attribute?(name)
|
|
327
|
+
self.class.hash_attribute_names.include?(name)
|
|
300
328
|
end
|
|
301
329
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
preceding_declaration_lines = line_numbers.map {|n| RSpec.world.preceding_declaration_line(n)}
|
|
305
|
-
!(relevant_line_numbers & preceding_declaration_lines).empty?
|
|
330
|
+
def get_value(name)
|
|
331
|
+
__send__(name)
|
|
306
332
|
end
|
|
307
333
|
|
|
308
|
-
|
|
334
|
+
def set_value(name, value)
|
|
335
|
+
__send__(:"#{name}=", value)
|
|
336
|
+
end
|
|
309
337
|
|
|
310
|
-
def
|
|
311
|
-
|
|
312
|
-
store(:caller, user_metadata.delete(:caller) || caller)
|
|
313
|
-
update(user_metadata)
|
|
338
|
+
def hash_for_delegation
|
|
339
|
+
to_h
|
|
314
340
|
end
|
|
315
341
|
|
|
316
|
-
|
|
342
|
+
def issue_deprecation(method_name, *args)
|
|
343
|
+
# no-op by default: subclasses can override
|
|
344
|
+
end
|
|
317
345
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
:full_description,
|
|
324
|
-
:line_number,
|
|
325
|
-
:location
|
|
326
|
-
]
|
|
346
|
+
# @private
|
|
347
|
+
module ClassMethods
|
|
348
|
+
def hash_attribute_names
|
|
349
|
+
@hash_attribute_names ||= []
|
|
350
|
+
end
|
|
327
351
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
352
|
+
def attr_accessor(*names)
|
|
353
|
+
hash_attribute_names.concat(names)
|
|
354
|
+
super
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
end
|
|
334
358
|
|
|
335
|
-
|
|
336
|
-
|
|
359
|
+
# @private
|
|
360
|
+
# Together with the example group metadata hash default block,
|
|
361
|
+
# provides backwards compatibility for the old `:example_group`
|
|
362
|
+
# key. In RSpec 2.x, the computed keys of a group's metadata
|
|
363
|
+
# were exposed from a nested subhash keyed by `[:example_group]`, and
|
|
364
|
+
# then the parent group's metadata was exposed by sub-subhash
|
|
365
|
+
# keyed by `[:example_group][:example_group]`.
|
|
366
|
+
#
|
|
367
|
+
# In RSpec 3, we reorganized this to that the computed keys are
|
|
368
|
+
# exposed directly of the group metadata hash (no nesting), and
|
|
369
|
+
# `:parent_example_group` returns the parent group's metadata.
|
|
370
|
+
#
|
|
371
|
+
# Maintaining backwards compatibility was difficult: we wanted
|
|
372
|
+
# `:example_group` to return an object that:
|
|
373
|
+
#
|
|
374
|
+
# * Exposes the top-level metadata keys that used to be nested
|
|
375
|
+
# under `:example_group`.
|
|
376
|
+
# * Supports mutation (rspec-rails, for example, assigns
|
|
377
|
+
# `metadata[:example_group][:described_class]` when you use
|
|
378
|
+
# anonymous controller specs) such that changes are written
|
|
379
|
+
# back to the top-level metadata hash.
|
|
380
|
+
# * Exposes the parent group metadata as `[:example_group][:example_group]`.
|
|
381
|
+
class LegacyExampleGroupHash
|
|
382
|
+
include HashImitatable
|
|
383
|
+
|
|
384
|
+
def initialize(metadata)
|
|
385
|
+
@metadata = metadata
|
|
386
|
+
parent_group_metadata = metadata.fetch(:parent_example_group) { {} }[:example_group]
|
|
387
|
+
self[:example_group] = parent_group_metadata if parent_group_metadata
|
|
388
|
+
end
|
|
337
389
|
|
|
338
|
-
|
|
390
|
+
def to_h
|
|
391
|
+
super.merge(@metadata)
|
|
392
|
+
end
|
|
339
393
|
|
|
340
|
-
|
|
394
|
+
private
|
|
341
395
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
EOM
|
|
345
|
-
end
|
|
346
|
-
end
|
|
396
|
+
def directly_supports_attribute?(name)
|
|
397
|
+
name != :example_group
|
|
347
398
|
end
|
|
348
399
|
|
|
349
|
-
def
|
|
350
|
-
|
|
400
|
+
def get_value(name)
|
|
401
|
+
@metadata[name]
|
|
351
402
|
end
|
|
352
403
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
def relevant_line_numbers(metadata=self)
|
|
356
|
-
[metadata[:line_number]] + (metadata[:example_group] ? relevant_line_numbers(metadata[:example_group]) : [])
|
|
404
|
+
def set_value(name, value)
|
|
405
|
+
@metadata[name] = value
|
|
357
406
|
end
|
|
358
|
-
|
|
359
407
|
end
|
|
360
408
|
end
|
|
361
409
|
end
|