rspec-sleeping_king_studios 2.1.1 → 2.2.0.rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +52 -0
- data/DEVELOPMENT.md +26 -17
- data/LICENSE +1 -1
- data/README.md +198 -19
- data/lib/rspec/sleeping_king_studios/configuration.rb +63 -2
- data/lib/rspec/sleeping_king_studios/examples/property_examples.rb +115 -27
- data/lib/rspec/sleeping_king_studios/examples/rspec_matcher_examples.rb +66 -51
- data/lib/rspec/sleeping_king_studios/matchers/active_model/have_errors.rb +8 -269
- data/lib/rspec/sleeping_king_studios/matchers/active_model/have_errors_matcher.rb +268 -0
- data/lib/rspec/sleeping_king_studios/matchers/base_matcher.rb +5 -15
- data/lib/rspec/sleeping_king_studios/matchers/built_in/be_kind_of.rb +3 -63
- data/lib/rspec/sleeping_king_studios/matchers/built_in/be_kind_of_matcher.rb +65 -0
- data/lib/rspec/sleeping_king_studios/matchers/built_in/include.rb +3 -108
- data/lib/rspec/sleeping_king_studios/matchers/built_in/include_matcher.rb +134 -0
- data/lib/rspec/sleeping_king_studios/matchers/built_in/respond_to.rb +3 -258
- data/lib/rspec/sleeping_king_studios/matchers/built_in/respond_to_matcher.rb +116 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/alias_method.rb +11 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/alias_method_matcher.rb +107 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/be_boolean.rb +9 -36
- data/lib/rspec/sleeping_king_studios/matchers/core/be_boolean_matcher.rb +37 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/construct.rb +3 -210
- data/lib/rspec/sleeping_king_studios/matchers/core/construct_matcher.rb +113 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/delegate_method.rb +11 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/delegate_method_matcher.rb +311 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/have_constant.rb +16 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/have_constant_matcher.rb +225 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/have_predicate.rb +11 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/have_predicate_matcher.rb +97 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/have_property.rb +3 -104
- data/lib/rspec/sleeping_king_studios/matchers/core/have_property_matcher.rb +108 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/have_reader.rb +3 -74
- data/lib/rspec/sleeping_king_studios/matchers/core/have_reader_matcher.rb +96 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/have_writer.rb +4 -59
- data/lib/rspec/sleeping_king_studios/matchers/core/have_writer_matcher.rb +55 -0
- data/lib/rspec/sleeping_king_studios/matchers/description.rb +62 -0
- data/lib/rspec/sleeping_king_studios/matchers/macros.rb +32 -0
- data/lib/rspec/sleeping_king_studios/matchers/shared/match_parameters.rb +168 -66
- data/lib/rspec/sleeping_king_studios/matchers/shared/match_property.rb +25 -0
- data/lib/rspec/sleeping_king_studios/matchers.rb +0 -4
- data/lib/rspec/sleeping_king_studios/support/method_signature.rb +51 -0
- data/lib/rspec/sleeping_king_studios/support/method_signature_expectation.rb +158 -0
- data/lib/rspec/sleeping_king_studios/support.rb +9 -0
- data/lib/rspec/sleeping_king_studios/version.rb +10 -4
- metadata +46 -30
@@ -2,6 +2,9 @@
|
|
2
2
|
|
3
3
|
require 'rspec/sleeping_king_studios/concerns/shared_example_group'
|
4
4
|
require 'rspec/sleeping_king_studios/examples'
|
5
|
+
require 'rspec/sleeping_king_studios/matchers/core/have_constant'
|
6
|
+
require 'rspec/sleeping_king_studios/matchers/core/have_predicate'
|
7
|
+
require 'rspec/sleeping_king_studios/matchers/core/have_property'
|
5
8
|
require 'rspec/sleeping_king_studios/matchers/core/have_reader'
|
6
9
|
require 'rspec/sleeping_king_studios/matchers/core/have_writer'
|
7
10
|
require 'sleeping_king_studios/tools/object_tools'
|
@@ -15,50 +18,135 @@ module RSpec::SleepingKingStudios::Examples::PropertyExamples
|
|
15
18
|
#
|
16
19
|
# Internal object used to differentiate a nil expectation from a default
|
17
20
|
# value expectation.
|
18
|
-
|
21
|
+
UNDEFINED_VALUE_EXPECTATION = Object.new.freeze
|
19
22
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
+
private def format_expected_value expected_value
|
24
|
+
if expected_value.is_a?(Proc)
|
25
|
+
object_tools = SleepingKingStudios::Tools::ObjectTools
|
26
|
+
|
27
|
+
if 0 == expected_value.arity
|
28
|
+
comparable_value = object_tools.apply self, expected_value
|
29
|
+
else
|
30
|
+
comparable_value = satisfy do |actual_value|
|
31
|
+
object_tools.apply self, expected_value, actual_value
|
32
|
+
end # satisfy
|
33
|
+
end # if-else
|
34
|
+
else
|
35
|
+
comparable_value = expected_value
|
36
|
+
end # if
|
37
|
+
|
38
|
+
comparable_value
|
39
|
+
end # method format_expected_value
|
40
|
+
|
41
|
+
shared_examples 'should have constant' do |constant_name, expected_value = UNDEFINED_VALUE_EXPECTATION|
|
42
|
+
it "should have constant :#{constant_name}" do
|
43
|
+
if defined?(described_class) && described_class.is_a?(Module)
|
44
|
+
object = described_class
|
45
|
+
else
|
46
|
+
object = subject
|
47
|
+
end # if-else
|
48
|
+
|
49
|
+
if expected_value == UNDEFINED_VALUE_EXPECTATION
|
50
|
+
expect(object).to have_constant(constant_name)
|
51
|
+
else
|
52
|
+
expected_value = format_expected_value(expected_value)
|
23
53
|
|
24
|
-
|
54
|
+
expect(object).to have_constant(constant_name).with_value(expected_value)
|
55
|
+
end # if-else
|
56
|
+
end # it
|
57
|
+
end # shared_examples
|
25
58
|
|
26
|
-
|
59
|
+
shared_examples 'should have immutable constant' do |constant_name, expected_value = UNDEFINED_VALUE_EXPECTATION|
|
60
|
+
it "should have immutable constant :#{constant_name}" do
|
61
|
+
if defined?(described_class) && described_class.is_a?(Module)
|
62
|
+
object = described_class
|
63
|
+
else
|
64
|
+
object = subject
|
65
|
+
end # if-else
|
27
66
|
|
28
|
-
|
67
|
+
if expected_value == UNDEFINED_VALUE_EXPECTATION
|
68
|
+
expect(object).to have_immutable_constant(constant_name)
|
69
|
+
else
|
70
|
+
expected_value = format_expected_value(expected_value)
|
29
71
|
|
30
|
-
|
31
|
-
|
32
|
-
|
72
|
+
expect(object).to have_immutable_constant(constant_name).with_value(expected_value)
|
73
|
+
end # if-else
|
74
|
+
end # it
|
75
|
+
end # shared_examples
|
33
76
|
|
34
|
-
|
35
|
-
|
77
|
+
shared_examples 'should have predicate' do |property, expected_value = UNDEFINED_VALUE_EXPECTATION|
|
78
|
+
it "should have predicate :#{property}?" do
|
79
|
+
object = defined?(instance) ? instance : subject
|
36
80
|
|
37
|
-
|
38
|
-
|
39
|
-
expect(actual_value).to expected_value
|
40
|
-
when true, false
|
41
|
-
expected_value
|
81
|
+
if expected_value == UNDEFINED_VALUE_EXPECTATION
|
82
|
+
expect(object).to have_predicate(property)
|
42
83
|
else
|
43
|
-
|
44
|
-
|
84
|
+
expected_value = format_expected_value(expected_value)
|
85
|
+
|
86
|
+
expect(object).to have_predicate(property).with_value(expected_value)
|
87
|
+
end # if-else
|
45
88
|
end # it
|
46
89
|
end # shared_examples
|
47
|
-
alias_shared_examples '
|
90
|
+
alias_shared_examples 'has predicate', 'should have predicate'
|
48
91
|
|
49
|
-
shared_examples '
|
50
|
-
it "
|
92
|
+
shared_examples 'should have reader' do |property, expected_value = UNDEFINED_VALUE_EXPECTATION|
|
93
|
+
it "should have reader :#{property}" do
|
94
|
+
object = defined?(instance) ? instance : subject
|
95
|
+
|
96
|
+
if expected_value == UNDEFINED_VALUE_EXPECTATION
|
97
|
+
expect(object).to have_reader(property)
|
98
|
+
else
|
99
|
+
expected_value = format_expected_value(expected_value)
|
100
|
+
|
101
|
+
expect(object).to have_reader(property).with_value(expected_value)
|
102
|
+
end # if-else
|
103
|
+
end # it
|
104
|
+
end # shared_examples
|
105
|
+
alias_shared_examples 'has reader', 'should have reader'
|
106
|
+
|
107
|
+
shared_examples 'should not have reader' do |property|
|
108
|
+
it "should not have reader :#{property}" do
|
109
|
+
object = defined?(instance) ? instance : subject
|
110
|
+
|
111
|
+
expect(object).not_to have_reader(property)
|
112
|
+
end # it
|
113
|
+
end # shared_examples
|
114
|
+
alias_shared_examples 'does not have reader', 'should not have reader'
|
115
|
+
|
116
|
+
shared_examples 'should have writer' do |property|
|
117
|
+
property_name = property.to_s.sub /\=\z/, ''
|
118
|
+
|
119
|
+
it "should have writer :#{property_name}=" do
|
51
120
|
object = defined?(instance) ? instance : subject
|
52
121
|
|
53
122
|
expect(object).to have_writer(property)
|
54
123
|
end # it
|
55
124
|
end # shared_examples
|
56
|
-
alias_shared_examples '
|
125
|
+
alias_shared_examples 'has writer', 'should have writer'
|
57
126
|
|
58
|
-
shared_examples '
|
59
|
-
|
127
|
+
shared_examples 'should not have writer' do |property|
|
128
|
+
property_name = property.to_s.sub /\=\z/, ''
|
60
129
|
|
61
|
-
|
130
|
+
it "should not have writer :#{property}=" do
|
131
|
+
object = defined?(instance) ? instance : subject
|
132
|
+
|
133
|
+
expect(object).not_to have_writer(property)
|
134
|
+
end # it
|
135
|
+
end # shared_examples
|
136
|
+
alias_shared_examples 'does not have writer', 'should not have writer'
|
137
|
+
|
138
|
+
shared_examples 'should have property' do |property, expected_value = UNDEFINED_VALUE_EXPECTATION|
|
139
|
+
it "should have property :#{property}" do
|
140
|
+
object = defined?(instance) ? instance : subject
|
141
|
+
|
142
|
+
if expected_value == UNDEFINED_VALUE_EXPECTATION
|
143
|
+
expect(object).to have_property(property)
|
144
|
+
else
|
145
|
+
expected_value = format_expected_value(expected_value)
|
146
|
+
|
147
|
+
expect(object).to have_property(property).with_value(expected_value)
|
148
|
+
end # if-else
|
149
|
+
end # it
|
62
150
|
end # shared_examples
|
63
|
-
alias_shared_examples '
|
151
|
+
alias_shared_examples 'has property', 'should have property'
|
64
152
|
end # module
|
@@ -8,54 +8,74 @@ require 'rspec/sleeping_king_studios/matchers/base_matcher'
|
|
8
8
|
module RSpec::SleepingKingStudios::Examples::RSpecMatcherExamples
|
9
9
|
extend RSpec::SleepingKingStudios::Concerns::SharedExampleGroup
|
10
10
|
|
11
|
-
|
11
|
+
private def config
|
12
|
+
RSpec.configuration.sleeping_king_studios
|
13
|
+
end # method config
|
14
|
+
|
15
|
+
private def compare_message actual, expected
|
16
|
+
case expected
|
17
|
+
when String
|
18
|
+
if config.examples.match_string_failure_message_as == :exact
|
19
|
+
expect(actual).to be == expected
|
20
|
+
else
|
21
|
+
expect(actual).to include expected
|
22
|
+
end # if-else
|
23
|
+
when Regexp
|
24
|
+
expect(actual).to be =~ expected
|
25
|
+
when ->(obj) { obj.respond_to?(:matches?) && obj.respond_to?(:failure_message) }
|
26
|
+
expect(actual).to expected
|
27
|
+
else
|
28
|
+
expect(actual).to match expected
|
29
|
+
end # when
|
30
|
+
end # method compare_message
|
31
|
+
|
32
|
+
private def handle_missing_failure_message message
|
33
|
+
case config.examples.handle_missing_failure_message_with
|
34
|
+
when :pending
|
35
|
+
skip message
|
36
|
+
when :exception
|
37
|
+
raise StandardError.new message
|
38
|
+
end # case
|
39
|
+
end # method handle_missing_failure_message
|
40
|
+
|
41
|
+
shared_examples 'should pass with a positive expectation' do
|
12
42
|
let(:matcher_being_examined) { defined?(instance) ? instance : subject }
|
13
43
|
|
14
|
-
it '
|
44
|
+
it 'should pass with positive expectation' do
|
15
45
|
expect(matcher_being_examined.matches? actual).to be true
|
16
46
|
end # it
|
17
47
|
end # shared_examples
|
18
|
-
alias_shared_examples '
|
48
|
+
alias_shared_examples 'passes with a positive expectation', 'should pass with a positive expectation'
|
19
49
|
|
20
|
-
shared_examples '
|
50
|
+
shared_examples 'should fail with a positive expectation' do
|
21
51
|
let(:matcher_being_examined) { defined?(instance) ? instance : subject }
|
22
52
|
|
23
|
-
it '
|
53
|
+
it 'should fail with a positive expectation' do
|
24
54
|
expect(matcher_being_examined.matches? actual).to be false
|
25
55
|
end # it
|
26
56
|
|
27
|
-
it '
|
57
|
+
it 'should have a failure message with a positive expectation' do
|
28
58
|
if defined?(failure_message)
|
29
59
|
matcher_being_examined.matches?(actual)
|
30
60
|
|
31
|
-
|
32
|
-
Regexp.new(Regexp.escape(failure_message)) :
|
33
|
-
failure_message
|
34
|
-
|
35
|
-
expect(matcher_being_examined.failure_message).to match expected
|
61
|
+
compare_message(matcher_being_examined.failure_message, failure_message)
|
36
62
|
else
|
37
|
-
message =
|
38
|
-
expected to match #{matcher_being_examined.class}#failure_message,
|
39
|
-
value was undefined. Define a failure message
|
40
|
-
let(:failure_message) or set
|
41
|
-
config.handle_missing_failure_message_with to :ignore or :pending.
|
42
|
-
|
43
|
-
message
|
44
|
-
case RSpec.configuration.sleeping_king_studios.examples.handle_missing_failure_message_with
|
45
|
-
when :pending
|
46
|
-
skip message
|
47
|
-
when :exception
|
48
|
-
raise StandardError.new message
|
49
|
-
end # case
|
63
|
+
message =
|
64
|
+
"expected to match #{matcher_being_examined.class}#failure_message, "\
|
65
|
+
"but the expected value was undefined. Define a failure message "\
|
66
|
+
"using let(:failure_message) or set "\
|
67
|
+
"config.handle_missing_failure_message_with to :ignore or :pending."
|
68
|
+
|
69
|
+
handle_missing_failure_message(message)
|
50
70
|
end # if
|
51
71
|
end # it
|
52
72
|
end # shared_examples
|
53
|
-
alias_shared_examples '
|
73
|
+
alias_shared_examples 'fails with a positive expectation', 'should fail with a positive expectation'
|
54
74
|
|
55
|
-
shared_examples '
|
75
|
+
shared_examples 'should pass with a negative expectation' do
|
56
76
|
let(:matcher_being_examined) { defined?(instance) ? instance : subject }
|
57
77
|
|
58
|
-
it '
|
78
|
+
it 'should pass with a negative expectation' do
|
59
79
|
if matcher_being_examined.respond_to?(:does_not_match?)
|
60
80
|
expect(matcher_being_examined.does_not_match? actual).to be true
|
61
81
|
else
|
@@ -63,12 +83,12 @@ module RSpec::SleepingKingStudios::Examples::RSpecMatcherExamples
|
|
63
83
|
end # if-else
|
64
84
|
end # it
|
65
85
|
end # shared_examples
|
66
|
-
alias_shared_examples '
|
86
|
+
alias_shared_examples 'passes with a negative expectation', 'should pass with a negative expectation'
|
67
87
|
|
68
|
-
shared_examples '
|
88
|
+
shared_examples 'should fail with a negative expectation' do
|
69
89
|
let(:matcher_being_examined) { defined?(instance) ? instance : subject }
|
70
90
|
|
71
|
-
it '
|
91
|
+
it 'should fail with a negative expectation' do
|
72
92
|
if matcher_being_examined.respond_to?(:does_not_match?)
|
73
93
|
expect(matcher_being_examined.does_not_match? actual).to be false
|
74
94
|
else
|
@@ -76,31 +96,26 @@ module RSpec::SleepingKingStudios::Examples::RSpecMatcherExamples
|
|
76
96
|
end # if-else
|
77
97
|
end # it
|
78
98
|
|
79
|
-
it '
|
99
|
+
it 'should have a failure message with a negative expectation' do
|
80
100
|
if defined?(failure_message_when_negated)
|
81
|
-
matcher_being_examined.respond_to?(:does_not_match?)
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
101
|
+
if matcher_being_examined.respond_to?(:does_not_match?)
|
102
|
+
matcher_being_examined.does_not_match?(actual)
|
103
|
+
else
|
104
|
+
matcher_being_examined.matches?(actual)
|
105
|
+
end # if-else
|
86
106
|
|
87
|
-
|
107
|
+
compare_message(matcher_being_examined.failure_message_when_negated, failure_message_when_negated)
|
88
108
|
else
|
89
|
-
message =
|
90
|
-
expected to match #{matcher_being_examined.class}#
|
91
|
-
the expected value was undefined.
|
92
|
-
let(:failure_message_when_negated)
|
93
|
-
config.handle_missing_failure_message_with to :ignore or
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
when :pending
|
98
|
-
skip message
|
99
|
-
when :exception
|
100
|
-
raise StandardError.new message
|
101
|
-
end # case
|
109
|
+
message =
|
110
|
+
"expected to match #{matcher_being_examined.class}#"\
|
111
|
+
"failure_message_when_negated, but the expected value was undefined."\
|
112
|
+
" Define a failure message using let(:failure_message_when_negated) "\
|
113
|
+
"or set config.handle_missing_failure_message_with to :ignore or "\
|
114
|
+
":pending."
|
115
|
+
|
116
|
+
handle_missing_failure_message(message)
|
102
117
|
end # if
|
103
118
|
end # it
|
104
119
|
end # shared_examples
|
105
|
-
alias_shared_examples '
|
120
|
+
alias_shared_examples 'fails with a negative expectation', 'should fail with a negative expectation'
|
106
121
|
end # module
|
@@ -1,272 +1,11 @@
|
|
1
1
|
# lib/rspec/sleeping_king_studios/matchers/active_model/have_errors.rb
|
2
2
|
|
3
|
-
require 'rspec/sleeping_king_studios/matchers/
|
4
|
-
require 'rspec/sleeping_king_studios/matchers/
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
#
|
11
|
-
#
|
12
|
-
# @since 1.0.0
|
13
|
-
class HaveErrorsMatcher < RSpec::SleepingKingStudios::Matchers::BaseMatcher
|
14
|
-
include RSpec::SleepingKingStudios::Matchers::ActiveModel::HaveErrors
|
15
|
-
include SleepingKingStudios::Tools::EnumerableTools
|
16
|
-
include SleepingKingStudios::Tools::StringTools
|
17
|
-
|
18
|
-
def initialize
|
19
|
-
super
|
20
|
-
|
21
|
-
# The error and message expectations are set up through #on and
|
22
|
-
# #with_message.
|
23
|
-
@error_expectations = []
|
24
|
-
end # constructor
|
25
|
-
|
26
|
-
# (see BaseMatcher#description)
|
27
|
-
def description
|
28
|
-
message = 'have errors'
|
29
|
-
|
30
|
-
attribute_messages = @error_expectations.select(&:expected).map do |expectation|
|
31
|
-
attribute_message = ":#{expectation.attribute}"
|
32
|
-
|
33
|
-
error_messages = expectation.messages.select(&:expected).map do |message_expectation|
|
34
|
-
%{"#{message_expectation.message}"}
|
35
|
-
end # map
|
36
|
-
|
37
|
-
unless error_messages.empty?
|
38
|
-
attribute_message << " with #{pluralize(error_messages.count, 'message', 'messages')} #{humanize_list error_messages}"
|
39
|
-
end # unless
|
40
|
-
|
41
|
-
attribute_message
|
42
|
-
end # each
|
43
|
-
message << " on #{attribute_messages.join(", and on ")}" unless attribute_messages.empty?
|
44
|
-
|
45
|
-
message
|
46
|
-
end # method description
|
47
|
-
|
48
|
-
# Checks if the object can be validated, whether the object is valid, and
|
49
|
-
# checks the errors on the object against the expected errors and messages
|
50
|
-
# from #on and #with_message, if any.
|
51
|
-
#
|
52
|
-
# @param [Object] actual The object to test against the matcher.
|
53
|
-
#
|
54
|
-
# @return [Boolean] True if the object responds to :valid? and is valid
|
55
|
-
# or object.errors does not match the specified errors and messages (if
|
56
|
-
# any); otherwise false.
|
57
|
-
#
|
58
|
-
# @see #matches?
|
59
|
-
def does_not_match? actual
|
60
|
-
@negative_expectation = true
|
61
|
-
|
62
|
-
return false unless @validates = actual.respond_to?(:valid?)
|
63
|
-
|
64
|
-
!matches?(actual)
|
65
|
-
end # method does_not_match?
|
66
|
-
|
67
|
-
# Checks if the object can be validated, whether the object is valid, and
|
68
|
-
# checks the errors on the object against the expected errors and messages
|
69
|
-
# from #on and #with_message, if any.
|
70
|
-
#
|
71
|
-
# @param [Object] actual The object to test against the matcher.
|
72
|
-
#
|
73
|
-
# @return [Boolean] True if the object responds to :valid?, is not valid,
|
74
|
-
# and object.errors matches the specified errors and messages (if any);
|
75
|
-
# otherwise false.
|
76
|
-
#
|
77
|
-
# @see RSpec::SleepingKingStudios::Matchers::BaseMatcher#matches?
|
78
|
-
def matches? actual
|
79
|
-
super
|
80
|
-
|
81
|
-
return false unless @validates = actual.respond_to?(:valid?)
|
82
|
-
|
83
|
-
!@actual.valid? && attributes_have_errors?
|
84
|
-
end # method matches?
|
85
|
-
|
86
|
-
# Adds an error expectation. If the actual object does not have an error on
|
87
|
-
# the specified attribute, #matches? will return false.
|
88
|
-
#
|
89
|
-
# @param [String, Symbol] attribute
|
90
|
-
#
|
91
|
-
# @return [HaveErrorsMatcher] self
|
92
|
-
#
|
93
|
-
# @example Setting an error expectation
|
94
|
-
# expect(actual).to have_errors.on(:foo)
|
95
|
-
def on attribute
|
96
|
-
@error_expectations << ErrorExpectation.new(attribute)
|
97
|
-
|
98
|
-
self
|
99
|
-
end # method on
|
100
|
-
|
101
|
-
# Adds a message expectation for the most recently added error attribute.
|
102
|
-
# If the actual object does not have an error on the that attribute with
|
103
|
-
# the specified message, #matches? will return false.
|
104
|
-
#
|
105
|
-
# @param [String, Regexp] message The expected error message. If a string,
|
106
|
-
# matcher will check for an exact match; if a regular expression, matcher
|
107
|
-
# will check if the message matches the regexp.
|
108
|
-
#
|
109
|
-
# @raise [ArgumentError] If no error attribute has been added.
|
110
|
-
#
|
111
|
-
# @return [HaveErrorsMatcher] self
|
112
|
-
#
|
113
|
-
# @example Setting an error and a message expectation
|
114
|
-
# expect(actual).to have_errors.on(:foo).with("can't be blank")
|
115
|
-
#
|
116
|
-
# @see #on
|
117
|
-
def with_message message
|
118
|
-
raise ArgumentError.new "no attribute specified for error message" if
|
119
|
-
@error_expectations.empty?
|
120
|
-
|
121
|
-
@error_expectations.last.messages << MessageExpectation.new(message)
|
122
|
-
|
123
|
-
self
|
124
|
-
end # method with_message
|
125
|
-
|
126
|
-
# Adds a set of message expectations for the most recently added error
|
127
|
-
# attribute.
|
128
|
-
#
|
129
|
-
# @param [Array<String, Regexp>] messages
|
130
|
-
#
|
131
|
-
# @see #with_message
|
132
|
-
def with_messages *messages
|
133
|
-
messages.each do |message| self.with_message(message); end
|
134
|
-
|
135
|
-
self
|
136
|
-
end # method with_message
|
137
|
-
alias_method :with, :with_messages
|
138
|
-
|
139
|
-
# (see BaseMatcher#failure_message)
|
140
|
-
def failure_message
|
141
|
-
# Failure cases:
|
142
|
-
# * object is not a model ("to respond to valid")
|
143
|
-
# * expected one or more errors, but received none ("to have errors")
|
144
|
-
# * expected one or more messages on :attribute, but received none or a
|
145
|
-
# subset ("to have errors on")
|
146
|
-
|
147
|
-
if !@validates
|
148
|
-
"expected #{@actual.inspect} to respond to :valid?"
|
149
|
-
elsif expected_errors.empty?
|
150
|
-
"expected #{@actual.inspect} to have errors"
|
151
|
-
else
|
152
|
-
"expected #{@actual.inspect} to have errors#{expected_errors_message}#{received_errors_message}"
|
153
|
-
end # if-elsif-else
|
154
|
-
end # method failure_message
|
155
|
-
|
156
|
-
# (see BaseMatcher#failure_message_when_negated)
|
157
|
-
def failure_message_when_negated
|
158
|
-
# Failure cases:
|
159
|
-
# * object is not a model ("to respond to valid")
|
160
|
-
# * expected one or more errors, received one or more ("not to have
|
161
|
-
# errors")
|
162
|
-
# * expected one or more messages on attribute, received one or more
|
163
|
-
# ("not to have errors on")
|
164
|
-
# * expected specific messages on attribute, received all ("not to have
|
165
|
-
# errors on")
|
166
|
-
|
167
|
-
if !@validates
|
168
|
-
"expected #{@actual.inspect} to respond to :valid?"
|
169
|
-
elsif expected_errors.empty?
|
170
|
-
return "expected #{@actual.inspect} not to have errors#{received_errors_message}"
|
171
|
-
else
|
172
|
-
return "expected #{@actual.inspect} not to have errors#{expected_errors_message}#{received_errors_message}"
|
173
|
-
end # if-else
|
174
|
-
end # method failure_message_when_negated
|
175
|
-
|
176
|
-
private
|
177
|
-
|
178
|
-
def attributes_have_errors?
|
179
|
-
# Iterate through the received errors and match them against the expected
|
180
|
-
# errors and messages.
|
181
|
-
@actual.errors.messages.each do |attribute, messages|
|
182
|
-
# Find the matching error expectation, if any.
|
183
|
-
error_expectation = @error_expectations.detect do |error_expectation|
|
184
|
-
error_expectation.attribute == attribute
|
185
|
-
end # detect
|
186
|
-
|
187
|
-
if error_expectation
|
188
|
-
error_expectation.received = true
|
189
|
-
|
190
|
-
# If the error includes message expectations, iterate through the
|
191
|
-
# received messages.
|
192
|
-
unless error_expectation.messages.empty?
|
193
|
-
messages.each do |message|
|
194
|
-
# Find the matching message expectation, if any.
|
195
|
-
message_expectation = error_expectation.messages.detect do |message_expectation|
|
196
|
-
if Regexp === message_expectation.message
|
197
|
-
message =~ message_expectation.message
|
198
|
-
else
|
199
|
-
message == message_expectation.message
|
200
|
-
end # if-else
|
201
|
-
end # detect
|
202
|
-
|
203
|
-
if message_expectation
|
204
|
-
message_expectation.received = true
|
205
|
-
else
|
206
|
-
error_expectation.messages << MessageExpectation.new(message, false, true)
|
207
|
-
end # if-else
|
208
|
-
end # each
|
209
|
-
end # unless
|
210
|
-
else
|
211
|
-
error_expectation = ErrorExpectation.new attribute, false, true
|
212
|
-
messages.each do |message|
|
213
|
-
error_expectation.messages << MessageExpectation.new(message, false, true)
|
214
|
-
end # each
|
215
|
-
|
216
|
-
@error_expectations << error_expectation
|
217
|
-
end # if-else
|
218
|
-
end # each
|
219
|
-
|
220
|
-
missing_errors.empty? && missing_messages.empty?
|
221
|
-
end # method attributes_have_errors
|
222
|
-
|
223
|
-
def expected_errors
|
224
|
-
@error_expectations.select do |error_expectation|
|
225
|
-
error_expectation.expected
|
226
|
-
end # select
|
227
|
-
end # method expected_errors
|
228
|
-
|
229
|
-
def missing_errors
|
230
|
-
@error_expectations.select do |error_expectation|
|
231
|
-
error_expectation.expected && !error_expectation.received
|
232
|
-
end # select
|
233
|
-
end # method missing_errors
|
234
|
-
|
235
|
-
def missing_messages
|
236
|
-
@error_expectations.select do |error_expectation|
|
237
|
-
!error_expectation.messages.missing.empty?
|
238
|
-
end # select
|
239
|
-
end # method missing_messages
|
240
|
-
|
241
|
-
def unexpected_errors
|
242
|
-
@error_expectations.select do |error_expectation|
|
243
|
-
!error_expectation.expected && error_expectation.received
|
244
|
-
end # select
|
245
|
-
end # method unexpected_errors
|
246
|
-
|
247
|
-
def expected_errors_message
|
248
|
-
"\n expected errors:" + expected_errors.map do |error_expectation|
|
249
|
-
"\n #{error_expectation.attribute}: " + (error_expectation.messages.empty? ?
|
250
|
-
"(#{@negative_expectation ? 'none' : 'any'})" :
|
251
|
-
error_expectation.messages.expected.map(&:message).map(&:inspect).join(", "))
|
252
|
-
end.join # map
|
253
|
-
end # method expected_errors_message
|
254
|
-
|
255
|
-
def received_errors_message
|
256
|
-
return "" unless @validates
|
257
|
-
|
258
|
-
return "\n received errors:\n (none)" if @actual.errors.messages.empty?
|
259
|
-
|
260
|
-
"\n received errors:" + @actual.errors.messages.map do |attr, ary|
|
261
|
-
"\n #{attr}: " + ary.map(&:inspect).join(", ")
|
262
|
-
end.join # map
|
263
|
-
end # method received_errors_message
|
264
|
-
end # class
|
265
|
-
|
266
|
-
module RSpec::SleepingKingStudios::Matchers
|
267
|
-
# @see RSpec::SleepingKingStudios::Matchers::ActiveModel::HaveErrorsMatcher#matches?
|
268
|
-
def have_errors
|
269
|
-
RSpec::SleepingKingStudios::Matchers::ActiveModel::HaveErrorsMatcher.new
|
270
|
-
end # method have_errors
|
271
|
-
end # module
|
3
|
+
require 'rspec/sleeping_king_studios/matchers/active_model/have_errors_matcher'
|
4
|
+
require 'rspec/sleeping_king_studios/matchers/macros'
|
5
|
+
|
6
|
+
module RSpec::SleepingKingStudios::Matchers::Macros
|
7
|
+
# @see RSpec::SleepingKingStudios::Matchers::ActiveModel::HaveErrorsMatcher#matches?
|
8
|
+
def have_errors
|
9
|
+
RSpec::SleepingKingStudios::Matchers::ActiveModel::HaveErrorsMatcher.new
|
10
|
+
end # method have_errors
|
272
11
|
end # module
|