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
|
@@ -1,776 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
module RSpec::Core
|
|
4
|
-
describe MemoizedHelpers do
|
|
5
|
-
before(:each) { RSpec.configuration.configure_expectation_framework }
|
|
6
|
-
|
|
7
|
-
def subject_value_for(describe_arg, &block)
|
|
8
|
-
group = ExampleGroup.describe(describe_arg, &block)
|
|
9
|
-
subject_value = nil
|
|
10
|
-
group.example { subject_value = subject }
|
|
11
|
-
group.run
|
|
12
|
-
subject_value
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
describe "implicit subject" do
|
|
16
|
-
describe "with a class" do
|
|
17
|
-
it "returns an instance of the class" do
|
|
18
|
-
expect(subject_value_for(Array)).to eq([])
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
describe "with a Module" do
|
|
23
|
-
it "returns the Module" do
|
|
24
|
-
expect(subject_value_for(Enumerable)).to eq(Enumerable)
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
describe "with a string" do
|
|
29
|
-
it "returns the string" do
|
|
30
|
-
expect(subject_value_for("Foo")).to eq("Foo")
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
describe "with a number" do
|
|
35
|
-
it "returns the number" do
|
|
36
|
-
expect(subject_value_for(15)).to eq(15)
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
describe "with a symbol" do
|
|
41
|
-
it "returns the string form and issues a deprecation warning" do
|
|
42
|
-
the_subject = :unset
|
|
43
|
-
deprecations = []
|
|
44
|
-
allow(RSpec).to receive(:warn_deprecation) { |msg| deprecations << msg }
|
|
45
|
-
|
|
46
|
-
line = __LINE__ + 1
|
|
47
|
-
ExampleGroup.describe :symbol do
|
|
48
|
-
example { the_subject = subject }
|
|
49
|
-
end.run
|
|
50
|
-
|
|
51
|
-
expect(the_subject).to eq("symbol")
|
|
52
|
-
expect(deprecations.size).to eq(1)
|
|
53
|
-
deprecation = deprecations.first
|
|
54
|
-
expect(deprecation).to match(/describe <a Symbol>/)
|
|
55
|
-
expect(deprecation).to include("#{__FILE__}:#{line}")
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
describe "with a hash" do
|
|
60
|
-
it "returns a blank string and issues a deprecation warning" do
|
|
61
|
-
the_subject = :unset
|
|
62
|
-
deprecations = []
|
|
63
|
-
allow(RSpec).to receive(:warn_deprecation) { |msg| deprecations << msg }
|
|
64
|
-
|
|
65
|
-
line = __LINE__ + 1
|
|
66
|
-
ExampleGroup.describe :foo => 3 do
|
|
67
|
-
example { the_subject = subject }
|
|
68
|
-
end.run
|
|
69
|
-
|
|
70
|
-
expect(the_subject).to eq("")
|
|
71
|
-
expect(deprecations.size).to eq(1)
|
|
72
|
-
deprecation = deprecations.first
|
|
73
|
-
expect(deprecation).to match(/describe <a Hash>/)
|
|
74
|
-
expect(deprecation).to include("#{__FILE__}:#{line}")
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
it "can be overriden and super'd to from a nested group" do
|
|
79
|
-
outer_subject_value = inner_subject_value = nil
|
|
80
|
-
|
|
81
|
-
ExampleGroup.describe(Array) do
|
|
82
|
-
subject { super() << :parent_group }
|
|
83
|
-
example { outer_subject_value = subject }
|
|
84
|
-
|
|
85
|
-
context "nested" do
|
|
86
|
-
subject { super() << :child_group }
|
|
87
|
-
example { inner_subject_value = subject }
|
|
88
|
-
end
|
|
89
|
-
end.run
|
|
90
|
-
|
|
91
|
-
expect(outer_subject_value).to eq([:parent_group])
|
|
92
|
-
expect(inner_subject_value).to eq([:parent_group, :child_group])
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
describe "explicit subject" do
|
|
97
|
-
it "yields the example in which it is eval'd" do
|
|
98
|
-
example_yielded_to_subject = nil
|
|
99
|
-
example_yielded_to_example = nil
|
|
100
|
-
|
|
101
|
-
group = ExampleGroup.describe
|
|
102
|
-
group.subject { |e| example_yielded_to_subject = e }
|
|
103
|
-
group.example { |e| subject; example_yielded_to_example = e }
|
|
104
|
-
group.run
|
|
105
|
-
|
|
106
|
-
expect(example_yielded_to_subject).to eq example_yielded_to_example
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
[false, nil].each do |falsy_value|
|
|
110
|
-
context "with a value of #{falsy_value.inspect}" do
|
|
111
|
-
it "is evaluated once per example" do
|
|
112
|
-
group = ExampleGroup.describe(Array)
|
|
113
|
-
group.before do
|
|
114
|
-
Object.should_receive(:this_question?).once.and_return(falsy_value)
|
|
115
|
-
end
|
|
116
|
-
group.subject do
|
|
117
|
-
Object.this_question?
|
|
118
|
-
end
|
|
119
|
-
group.example do
|
|
120
|
-
subject
|
|
121
|
-
subject
|
|
122
|
-
end
|
|
123
|
-
expect(group.run).to be_truthy, "expected subject block to be evaluated only once"
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
describe "defined in a top level group" do
|
|
129
|
-
it "replaces the implicit subject in that group" do
|
|
130
|
-
subject_value = subject_value_for(Array) do
|
|
131
|
-
subject { [1, 2, 3] }
|
|
132
|
-
end
|
|
133
|
-
expect(subject_value).to eq([1, 2, 3])
|
|
134
|
-
end
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
describe "defined in a top level group" do
|
|
138
|
-
let(:group) do
|
|
139
|
-
ExampleGroup.describe do
|
|
140
|
-
subject{ [4, 5, 6] }
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
it "is available in a nested group (subclass)" do
|
|
145
|
-
subject_value = nil
|
|
146
|
-
group.describe("I'm nested!") do
|
|
147
|
-
example { subject_value = subject }
|
|
148
|
-
end.run
|
|
149
|
-
|
|
150
|
-
expect(subject_value).to eq([4, 5, 6])
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
it "is available in a doubly nested group (subclass)" do
|
|
154
|
-
subject_value = nil
|
|
155
|
-
group.describe("Nesting level 1") do
|
|
156
|
-
describe("Nesting level 2") do
|
|
157
|
-
example { subject_value = subject }
|
|
158
|
-
end
|
|
159
|
-
end.run
|
|
160
|
-
|
|
161
|
-
expect(subject_value).to eq([4, 5, 6])
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
it "can be overriden and super'd to from a nested group" do
|
|
165
|
-
subject_value = nil
|
|
166
|
-
group.describe("Nested") do
|
|
167
|
-
subject { super() + [:override] }
|
|
168
|
-
example { subject_value = subject }
|
|
169
|
-
end.run
|
|
170
|
-
|
|
171
|
-
expect(subject_value).to eq([4, 5, 6, :override])
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
context 'when referenced in a `before(:all)` hook' do
|
|
175
|
-
before do
|
|
176
|
-
expect(::RSpec).to respond_to(:warn_deprecation)
|
|
177
|
-
::RSpec.stub(:warn_deprecation)
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
def define_and_run_group
|
|
181
|
-
values = { :reference_lines => [] }
|
|
182
|
-
|
|
183
|
-
ExampleGroup.describe do
|
|
184
|
-
subject { [1, 2] }
|
|
185
|
-
let(:list) { %w[ a b ] }
|
|
186
|
-
|
|
187
|
-
before(:all) do
|
|
188
|
-
subject << 3; values[:reference_lines] << __LINE__
|
|
189
|
-
values[:final_subject_value_in_before_all] = subject; values[:reference_lines] << __LINE__
|
|
190
|
-
end
|
|
191
|
-
|
|
192
|
-
example do
|
|
193
|
-
list << '1'
|
|
194
|
-
values[:list_in_ex_1] = list
|
|
195
|
-
values[:subject_value_in_example] = subject
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
example do
|
|
199
|
-
list << '2'
|
|
200
|
-
values[:list_in_ex_2] = list
|
|
201
|
-
end
|
|
202
|
-
end.run
|
|
203
|
-
|
|
204
|
-
values
|
|
205
|
-
end
|
|
206
|
-
|
|
207
|
-
it 'memoizes the value within the before(:all) hook' do
|
|
208
|
-
values = define_and_run_group
|
|
209
|
-
expect(values.fetch(:final_subject_value_in_before_all)).to eq([1, 2, 3])
|
|
210
|
-
end
|
|
211
|
-
|
|
212
|
-
it 'preserves the memoization into the individual examples' do
|
|
213
|
-
values = define_and_run_group
|
|
214
|
-
expect(values.fetch(:subject_value_in_example)).to eq([1, 2, 3])
|
|
215
|
-
end
|
|
216
|
-
|
|
217
|
-
it 'does not cause other lets to be shared across examples' do
|
|
218
|
-
values = define_and_run_group
|
|
219
|
-
expect(values.fetch(:list_in_ex_1)).to eq(%w[ a b 1 ])
|
|
220
|
-
expect(values.fetch(:list_in_ex_2)).to eq(%w[ a b 2 ])
|
|
221
|
-
end
|
|
222
|
-
|
|
223
|
-
it 'prints a warning since `subject` declarations are not intended to be used in :all hooks' do
|
|
224
|
-
msgs = []
|
|
225
|
-
::RSpec.stub(:warn_deprecation) { |msg| msgs << msg }
|
|
226
|
-
|
|
227
|
-
values = define_and_run_group
|
|
228
|
-
|
|
229
|
-
expect(msgs).to include(*values[:reference_lines].map { |line|
|
|
230
|
-
match(/subject accessed.*#{__FILE__}:#{line}/m)
|
|
231
|
-
})
|
|
232
|
-
end
|
|
233
|
-
end
|
|
234
|
-
end
|
|
235
|
-
|
|
236
|
-
describe "with a name" do
|
|
237
|
-
it "yields the example in which it is eval'd" do
|
|
238
|
-
example_yielded_to_subject = nil
|
|
239
|
-
example_yielded_to_example = nil
|
|
240
|
-
|
|
241
|
-
group = ExampleGroup.describe
|
|
242
|
-
group.subject(:foo) { |e| example_yielded_to_subject = e }
|
|
243
|
-
group.example { |e| foo; example_yielded_to_example = e }
|
|
244
|
-
group.run
|
|
245
|
-
|
|
246
|
-
expect(example_yielded_to_subject).to eq example_yielded_to_example
|
|
247
|
-
end
|
|
248
|
-
|
|
249
|
-
it "defines a method that returns the memoized subject" do
|
|
250
|
-
list_value_1 = list_value_2 = subject_value_1 = subject_value_2 = nil
|
|
251
|
-
|
|
252
|
-
ExampleGroup.describe do
|
|
253
|
-
subject(:list) { [1, 2, 3] }
|
|
254
|
-
example do
|
|
255
|
-
list_value_1 = list
|
|
256
|
-
list_value_2 = list
|
|
257
|
-
subject_value_1 = subject
|
|
258
|
-
subject_value_2 = subject
|
|
259
|
-
end
|
|
260
|
-
end.run
|
|
261
|
-
|
|
262
|
-
expect(list_value_1).to eq([1, 2, 3])
|
|
263
|
-
expect(list_value_1).to equal(list_value_2)
|
|
264
|
-
|
|
265
|
-
expect(subject_value_1).to equal(subject_value_2)
|
|
266
|
-
expect(subject_value_1).to equal(list_value_1)
|
|
267
|
-
end
|
|
268
|
-
|
|
269
|
-
it "is referred from inside subject by the name" do
|
|
270
|
-
inner_subject_value = nil
|
|
271
|
-
|
|
272
|
-
ExampleGroup.describe do
|
|
273
|
-
subject(:list) { [1, 2, 3] }
|
|
274
|
-
describe 'first' do
|
|
275
|
-
subject(:first_element) { list.first }
|
|
276
|
-
example { inner_subject_value = subject }
|
|
277
|
-
end
|
|
278
|
-
end.run
|
|
279
|
-
|
|
280
|
-
expect(inner_subject_value).to eq(1)
|
|
281
|
-
end
|
|
282
|
-
|
|
283
|
-
it 'can continue to be referenced by the name even when an inner group redefines the subject' do
|
|
284
|
-
named_value = nil
|
|
285
|
-
|
|
286
|
-
ExampleGroup.describe do
|
|
287
|
-
subject(:named) { :outer }
|
|
288
|
-
|
|
289
|
-
describe "inner" do
|
|
290
|
-
subject { :inner }
|
|
291
|
-
example do
|
|
292
|
-
subject # so the inner subject method is run and memoized
|
|
293
|
-
named_value = self.named
|
|
294
|
-
end
|
|
295
|
-
end
|
|
296
|
-
end.run
|
|
297
|
-
|
|
298
|
-
expect(named_value).to eq(:outer)
|
|
299
|
-
end
|
|
300
|
-
|
|
301
|
-
it 'can continue to reference an inner subject after the outer subject name is referenced' do
|
|
302
|
-
subject_value = nil
|
|
303
|
-
|
|
304
|
-
ExampleGroup.describe do
|
|
305
|
-
subject(:named) { :outer }
|
|
306
|
-
|
|
307
|
-
describe "inner" do
|
|
308
|
-
subject { :inner }
|
|
309
|
-
example do
|
|
310
|
-
named # so the outer subject method is run and memoized
|
|
311
|
-
subject_value = self.subject
|
|
312
|
-
end
|
|
313
|
-
end
|
|
314
|
-
end.run
|
|
315
|
-
|
|
316
|
-
expect(subject_value).to eq(:inner)
|
|
317
|
-
end
|
|
318
|
-
|
|
319
|
-
it 'is not overriden when an inner group defines a new method with the same name' do
|
|
320
|
-
subject_value = nil
|
|
321
|
-
|
|
322
|
-
ExampleGroup.describe do
|
|
323
|
-
subject(:named) { :outer_subject }
|
|
324
|
-
|
|
325
|
-
describe "inner" do
|
|
326
|
-
let(:named) { :inner_named }
|
|
327
|
-
example { subject_value = self.subject }
|
|
328
|
-
end
|
|
329
|
-
end.run
|
|
330
|
-
|
|
331
|
-
expect(subject_value).to be(:outer_subject)
|
|
332
|
-
end
|
|
333
|
-
|
|
334
|
-
context 'when `super` is used' do
|
|
335
|
-
def should_raise_not_supported_error(&block)
|
|
336
|
-
ex = nil
|
|
337
|
-
|
|
338
|
-
ExampleGroup.describe do
|
|
339
|
-
let(:list) { ["a", "b", "c"] }
|
|
340
|
-
subject { [1, 2, 3] }
|
|
341
|
-
|
|
342
|
-
describe 'first' do
|
|
343
|
-
module_eval(&block) if block
|
|
344
|
-
|
|
345
|
-
subject(:list) { super().first(2) }
|
|
346
|
-
ex = example { subject }
|
|
347
|
-
end
|
|
348
|
-
end.run
|
|
349
|
-
|
|
350
|
-
expect(ex.execution_result[:status]).to eq("failed")
|
|
351
|
-
expect(ex.execution_result[:exception].message).to match(/super.*not supported/)
|
|
352
|
-
end
|
|
353
|
-
|
|
354
|
-
it 'raises a "not supported" error' do
|
|
355
|
-
should_raise_not_supported_error
|
|
356
|
-
end
|
|
357
|
-
|
|
358
|
-
context 'with a `let` definition before the named subject' do
|
|
359
|
-
it 'raises a "not supported" error' do
|
|
360
|
-
should_raise_not_supported_error do
|
|
361
|
-
# My first pass implementation worked unless there was a `let`
|
|
362
|
-
# declared before the named subject -- this let is in place to
|
|
363
|
-
# ensure that bug doesn't return.
|
|
364
|
-
let(:foo) { 3 }
|
|
365
|
-
end
|
|
366
|
-
end
|
|
367
|
-
end
|
|
368
|
-
end
|
|
369
|
-
end
|
|
370
|
-
end
|
|
371
|
-
|
|
372
|
-
context "using 'self' as an explicit subject" do
|
|
373
|
-
it "delegates matcher to the ExampleGroup" do
|
|
374
|
-
group = ExampleGroup.describe("group") do
|
|
375
|
-
subject { self }
|
|
376
|
-
def ok?; true; end
|
|
377
|
-
def not_ok?; false; end
|
|
378
|
-
|
|
379
|
-
it { should eq(self) }
|
|
380
|
-
it { should be_ok }
|
|
381
|
-
it { should_not be_not_ok }
|
|
382
|
-
end
|
|
383
|
-
|
|
384
|
-
expect(group.run).to be true
|
|
385
|
-
end
|
|
386
|
-
|
|
387
|
-
it 'supports a new expect-based syntax' do
|
|
388
|
-
group = ExampleGroup.describe([1, 2, 3]) do
|
|
389
|
-
it { is_expected.to be_an Array }
|
|
390
|
-
it { is_expected.not_to include 4 }
|
|
391
|
-
end
|
|
392
|
-
|
|
393
|
-
expect(group.run).to be true
|
|
394
|
-
end
|
|
395
|
-
end
|
|
396
|
-
|
|
397
|
-
describe "#its" do
|
|
398
|
-
extend SilenceDSLDeprecations
|
|
399
|
-
silence_dsl_deprecations do
|
|
400
|
-
it "should issue deprecation warning" do
|
|
401
|
-
expect_deprecation_with_call_site(__FILE__, __LINE__+1, '`its` method')
|
|
402
|
-
RSpec::Core::ExampleGroup.its(nil) {}
|
|
403
|
-
end
|
|
404
|
-
|
|
405
|
-
subject do
|
|
406
|
-
Class.new do
|
|
407
|
-
def initialize
|
|
408
|
-
@call_count = 0
|
|
409
|
-
end
|
|
410
|
-
|
|
411
|
-
def call_count
|
|
412
|
-
@call_count += 1
|
|
413
|
-
end
|
|
414
|
-
end.new
|
|
415
|
-
end
|
|
416
|
-
|
|
417
|
-
context "with a call counter" do
|
|
418
|
-
its(:call_count) { should eq(1) }
|
|
419
|
-
end
|
|
420
|
-
|
|
421
|
-
context "with nil value" do
|
|
422
|
-
subject do
|
|
423
|
-
Class.new do
|
|
424
|
-
def nil_value
|
|
425
|
-
nil
|
|
426
|
-
end
|
|
427
|
-
end.new
|
|
428
|
-
end
|
|
429
|
-
its(:nil_value) { should be_nil }
|
|
430
|
-
end
|
|
431
|
-
|
|
432
|
-
context "with nested attributes" do
|
|
433
|
-
subject do
|
|
434
|
-
Class.new do
|
|
435
|
-
def name
|
|
436
|
-
"John"
|
|
437
|
-
end
|
|
438
|
-
end.new
|
|
439
|
-
end
|
|
440
|
-
its("name") { should eq("John") }
|
|
441
|
-
its("name.size") { should eq(4) }
|
|
442
|
-
its("name.size.class") { should eq(Fixnum) }
|
|
443
|
-
end
|
|
444
|
-
|
|
445
|
-
context "when it responds to #[]" do
|
|
446
|
-
subject do
|
|
447
|
-
Class.new do
|
|
448
|
-
def [](*objects)
|
|
449
|
-
objects.map do |object|
|
|
450
|
-
"#{object.class}: #{object.to_s}"
|
|
451
|
-
end.join("; ")
|
|
452
|
-
end
|
|
453
|
-
|
|
454
|
-
def name
|
|
455
|
-
"George"
|
|
456
|
-
end
|
|
457
|
-
end.new
|
|
458
|
-
end
|
|
459
|
-
its([:a]) { should eq("Symbol: a") }
|
|
460
|
-
its(['a']) { should eq("String: a") }
|
|
461
|
-
its([:b, 'c', 4]) { should eq("Symbol: b; String: c; Fixnum: 4") }
|
|
462
|
-
its(:name) { should eq("George") }
|
|
463
|
-
context "when referring to an attribute without the proper array syntax" do
|
|
464
|
-
context "it raises an error" do
|
|
465
|
-
its(:age) do
|
|
466
|
-
expect do
|
|
467
|
-
should eq(64)
|
|
468
|
-
end.to raise_error(NoMethodError)
|
|
469
|
-
end
|
|
470
|
-
end
|
|
471
|
-
end
|
|
472
|
-
end
|
|
473
|
-
|
|
474
|
-
context "when it does not respond to #[]" do
|
|
475
|
-
subject { Object.new }
|
|
476
|
-
|
|
477
|
-
context "it raises an error" do
|
|
478
|
-
its([:a]) do
|
|
479
|
-
expect do
|
|
480
|
-
should eq("Symbol: a")
|
|
481
|
-
end.to raise_error(NoMethodError)
|
|
482
|
-
end
|
|
483
|
-
end
|
|
484
|
-
end
|
|
485
|
-
|
|
486
|
-
context "calling and overriding super" do
|
|
487
|
-
it "calls to the subject defined in the parent group" do
|
|
488
|
-
group = ExampleGroup.describe(Array) do
|
|
489
|
-
subject { [1, 'a'] }
|
|
490
|
-
|
|
491
|
-
its(:last) { should eq("a") }
|
|
492
|
-
|
|
493
|
-
describe '.first' do
|
|
494
|
-
def subject; super().first; end
|
|
495
|
-
|
|
496
|
-
its(:next) { should eq(2) }
|
|
497
|
-
end
|
|
498
|
-
end
|
|
499
|
-
|
|
500
|
-
expect(group.run).to be_truthy
|
|
501
|
-
end
|
|
502
|
-
end
|
|
503
|
-
|
|
504
|
-
context "with nil subject" do
|
|
505
|
-
subject do
|
|
506
|
-
Class.new do
|
|
507
|
-
def initialize
|
|
508
|
-
@counter = -1
|
|
509
|
-
end
|
|
510
|
-
def nil_if_first_time
|
|
511
|
-
@counter += 1
|
|
512
|
-
@counter == 0 ? nil : true
|
|
513
|
-
end
|
|
514
|
-
end.new
|
|
515
|
-
end
|
|
516
|
-
its(:nil_if_first_time) { should be(nil) }
|
|
517
|
-
end
|
|
518
|
-
|
|
519
|
-
context "with false subject" do
|
|
520
|
-
subject do
|
|
521
|
-
Class.new do
|
|
522
|
-
def initialize
|
|
523
|
-
@counter = -1
|
|
524
|
-
end
|
|
525
|
-
def false_if_first_time
|
|
526
|
-
@counter += 1
|
|
527
|
-
@counter > 0
|
|
528
|
-
end
|
|
529
|
-
end.new
|
|
530
|
-
end
|
|
531
|
-
its(:false_if_first_time) { should be(false) }
|
|
532
|
-
end
|
|
533
|
-
|
|
534
|
-
describe 'accessing `subject` in `before` and `let`' do
|
|
535
|
-
subject { 'my subject' }
|
|
536
|
-
before { @subject_in_before = subject }
|
|
537
|
-
let(:subject_in_let) { subject }
|
|
538
|
-
let!(:eager_loaded_subject_in_let) { subject }
|
|
539
|
-
|
|
540
|
-
# These examples read weird, because we're actually
|
|
541
|
-
# specifying the behaviour of `its` itself
|
|
542
|
-
its(nil) { expect(subject).to eq('my subject') }
|
|
543
|
-
its(nil) { expect(@subject_in_before).to eq('my subject') }
|
|
544
|
-
its(nil) { expect(subject_in_let).to eq('my subject') }
|
|
545
|
-
its(nil) { expect(eager_loaded_subject_in_let).to eq('my subject') }
|
|
546
|
-
end
|
|
547
|
-
end
|
|
548
|
-
end
|
|
549
|
-
|
|
550
|
-
describe '#subject!' do
|
|
551
|
-
let(:prepared_array) { [1,2,3] }
|
|
552
|
-
subject! { prepared_array.pop }
|
|
553
|
-
|
|
554
|
-
it "evaluates subject before example" do
|
|
555
|
-
expect(prepared_array).to eq([1,2])
|
|
556
|
-
end
|
|
557
|
-
|
|
558
|
-
it "returns memoized value from first invocation" do
|
|
559
|
-
expect(subject).to eq(3)
|
|
560
|
-
end
|
|
561
|
-
end
|
|
562
|
-
end
|
|
563
|
-
|
|
564
|
-
describe "#let" do
|
|
565
|
-
let(:counter) do
|
|
566
|
-
Class.new do
|
|
567
|
-
def initialize
|
|
568
|
-
@count = 0
|
|
569
|
-
end
|
|
570
|
-
def count
|
|
571
|
-
@count += 1
|
|
572
|
-
end
|
|
573
|
-
end.new
|
|
574
|
-
end
|
|
575
|
-
|
|
576
|
-
let(:nil_value) do
|
|
577
|
-
@nil_value_count += 1
|
|
578
|
-
nil
|
|
579
|
-
end
|
|
580
|
-
|
|
581
|
-
it "generates an instance method" do
|
|
582
|
-
expect(counter.count).to eq(1)
|
|
583
|
-
end
|
|
584
|
-
|
|
585
|
-
it "caches the value" do
|
|
586
|
-
expect(counter.count).to eq(1)
|
|
587
|
-
expect(counter.count).to eq(2)
|
|
588
|
-
end
|
|
589
|
-
|
|
590
|
-
it "caches a nil value" do
|
|
591
|
-
@nil_value_count = 0
|
|
592
|
-
nil_value
|
|
593
|
-
nil_value
|
|
594
|
-
|
|
595
|
-
expect(@nil_value_count).to eq(1)
|
|
596
|
-
end
|
|
597
|
-
|
|
598
|
-
let(:yield_the_example) do |example_yielded_to_let|
|
|
599
|
-
@example_yielded_to_let = example_yielded_to_let
|
|
600
|
-
end
|
|
601
|
-
|
|
602
|
-
it "yields the example" do |example_yielded_to_example|
|
|
603
|
-
yield_the_example
|
|
604
|
-
expect(@example_yielded_to_let).to equal example_yielded_to_example
|
|
605
|
-
end
|
|
606
|
-
|
|
607
|
-
let(:regex_with_capture) { %r[RegexWithCapture(\d)] }
|
|
608
|
-
|
|
609
|
-
it 'does not pass the block up the ancestor chain' do
|
|
610
|
-
# Test for Ruby bug http://bugs.ruby-lang.org/issues/8059
|
|
611
|
-
expect("RegexWithCapture1".match(regex_with_capture)[1]).to eq('1')
|
|
612
|
-
end
|
|
613
|
-
|
|
614
|
-
it 'raises a useful error when called without a block' do
|
|
615
|
-
expect do
|
|
616
|
-
ExampleGroup.describe { let(:list) }
|
|
617
|
-
end.to raise_error(/#let or #subject called without a block/)
|
|
618
|
-
end
|
|
619
|
-
|
|
620
|
-
let(:a_value) { "a string" }
|
|
621
|
-
|
|
622
|
-
context 'when overriding let in a nested context' do
|
|
623
|
-
let(:a_value) { super() + " (modified)" }
|
|
624
|
-
|
|
625
|
-
it 'can use `super` to reference the parent context value' do
|
|
626
|
-
expect(a_value).to eq("a string (modified)")
|
|
627
|
-
end
|
|
628
|
-
end
|
|
629
|
-
|
|
630
|
-
context 'when the declaration uses `return`' do
|
|
631
|
-
let(:value) do
|
|
632
|
-
return :early_exit if @early_exit
|
|
633
|
-
:late_exit
|
|
634
|
-
end
|
|
635
|
-
|
|
636
|
-
it 'can exit the let declaration early' do
|
|
637
|
-
@early_exit = true
|
|
638
|
-
expect(value).to eq(:early_exit)
|
|
639
|
-
end
|
|
640
|
-
|
|
641
|
-
it 'can get past a conditional `return` statement' do
|
|
642
|
-
@early_exit = false
|
|
643
|
-
expect(value).to eq(:late_exit)
|
|
644
|
-
end
|
|
645
|
-
end
|
|
646
|
-
|
|
647
|
-
context 'when referenced in a `before(:all)` hook' do
|
|
648
|
-
before do
|
|
649
|
-
expect(::RSpec).to respond_to(:warn_deprecation)
|
|
650
|
-
::RSpec.stub(:warn_deprecation)
|
|
651
|
-
end
|
|
652
|
-
|
|
653
|
-
def define_and_run_group
|
|
654
|
-
values = { :reference_lines => [] }
|
|
655
|
-
|
|
656
|
-
ExampleGroup.describe do
|
|
657
|
-
let(:list) { [1, 2] }
|
|
658
|
-
subject { %w[ a b ] }
|
|
659
|
-
|
|
660
|
-
before(:all) do
|
|
661
|
-
list << 3; values[:reference_lines] << __LINE__
|
|
662
|
-
values[:final_list_value_in_before_all] = list; values[:reference_lines] << __LINE__
|
|
663
|
-
end
|
|
664
|
-
|
|
665
|
-
example do
|
|
666
|
-
subject << "1"
|
|
667
|
-
values[:subject_in_ex_1] = subject
|
|
668
|
-
values[:list_value_in_example] = list
|
|
669
|
-
end
|
|
670
|
-
|
|
671
|
-
example do
|
|
672
|
-
subject << "2"
|
|
673
|
-
values[:subject_in_ex_2] = subject
|
|
674
|
-
end
|
|
675
|
-
end.run
|
|
676
|
-
|
|
677
|
-
values
|
|
678
|
-
end
|
|
679
|
-
|
|
680
|
-
it 'memoizes the value within the before(:all) hook' do
|
|
681
|
-
values = define_and_run_group
|
|
682
|
-
expect(values.fetch(:final_list_value_in_before_all)).to eq([1, 2, 3])
|
|
683
|
-
end
|
|
684
|
-
|
|
685
|
-
it 'preserves the memoized value into the examples' do
|
|
686
|
-
values = define_and_run_group
|
|
687
|
-
expect(values.fetch(:list_value_in_example)).to eq([1, 2, 3])
|
|
688
|
-
end
|
|
689
|
-
|
|
690
|
-
it 'does not cause the subject to be shared across examples' do
|
|
691
|
-
values = define_and_run_group
|
|
692
|
-
expect(values.fetch(:subject_in_ex_1)).to eq(%w[ a b 1 ])
|
|
693
|
-
expect(values.fetch(:subject_in_ex_2)).to eq(%w[ a b 2 ])
|
|
694
|
-
end
|
|
695
|
-
|
|
696
|
-
it 'prints a warning since `let` declarations are not intended to be used in :all hooks' do
|
|
697
|
-
msgs = []
|
|
698
|
-
::RSpec.stub(:warn_deprecation) { |msg| msgs << msg }
|
|
699
|
-
|
|
700
|
-
values = define_and_run_group
|
|
701
|
-
|
|
702
|
-
expect(msgs).to include(*values[:reference_lines].map { |line|
|
|
703
|
-
match(/let declaration `list` accessed.*#{__FILE__}:#{line}/m)
|
|
704
|
-
})
|
|
705
|
-
end
|
|
706
|
-
end
|
|
707
|
-
|
|
708
|
-
context "when included modules have hooks that define memoized helpers" do
|
|
709
|
-
it "allows memoized helpers to override methods in previously included modules" do
|
|
710
|
-
group = ExampleGroup.describe do
|
|
711
|
-
include Module.new {
|
|
712
|
-
def self.included(m); m.let(:unrelated) { :unrelated }; end
|
|
713
|
-
}
|
|
714
|
-
|
|
715
|
-
include Module.new {
|
|
716
|
-
def hello_message; "Hello from module"; end
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
let(:hello_message) { "Hello from let" }
|
|
720
|
-
end
|
|
721
|
-
|
|
722
|
-
expect(group.new.hello_message).to eq("Hello from let")
|
|
723
|
-
end
|
|
724
|
-
end
|
|
725
|
-
end
|
|
726
|
-
|
|
727
|
-
describe "#let!" do
|
|
728
|
-
subject { [1,2,3] }
|
|
729
|
-
let!(:popped) { subject.pop }
|
|
730
|
-
|
|
731
|
-
it "evaluates the value non-lazily" do
|
|
732
|
-
expect(subject).to eq([1,2])
|
|
733
|
-
end
|
|
734
|
-
|
|
735
|
-
it "returns memoized value from first invocation" do
|
|
736
|
-
expect(popped).to eq(3)
|
|
737
|
-
end
|
|
738
|
-
end
|
|
739
|
-
|
|
740
|
-
describe 'using subject in before and let blocks' do
|
|
741
|
-
shared_examples_for 'a subject' do
|
|
742
|
-
let(:subject_id_in_let) { subject.object_id }
|
|
743
|
-
before { @subject_id_in_before = subject.object_id }
|
|
744
|
-
|
|
745
|
-
it 'should be memoized' do
|
|
746
|
-
expect(subject_id_in_let).to eq(@subject_id_in_before)
|
|
747
|
-
end
|
|
748
|
-
|
|
749
|
-
it { is_expected.to eq(subject) }
|
|
750
|
-
end
|
|
751
|
-
|
|
752
|
-
describe Object do
|
|
753
|
-
context 'with implicit subject' do
|
|
754
|
-
it_should_behave_like 'a subject'
|
|
755
|
-
end
|
|
756
|
-
|
|
757
|
-
context 'with explicit subject' do
|
|
758
|
-
subject { Object.new }
|
|
759
|
-
it_should_behave_like 'a subject'
|
|
760
|
-
end
|
|
761
|
-
|
|
762
|
-
context 'with a constant subject'do
|
|
763
|
-
subject { 123 }
|
|
764
|
-
it_should_behave_like 'a subject'
|
|
765
|
-
end
|
|
766
|
-
end
|
|
767
|
-
end
|
|
768
|
-
|
|
769
|
-
describe 'Module#define_method' do
|
|
770
|
-
it 'is still a private method' do
|
|
771
|
-
a_module = Module.new
|
|
772
|
-
expect { a_module.define_method(:name) { "implementation" } }.to raise_error NoMethodError
|
|
773
|
-
end
|
|
774
|
-
end
|
|
775
|
-
end
|
|
776
|
-
|