rspec-sleeping_king_studios 1.0.0.rc.2

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.
Files changed (35) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +22 -0
  3. data/README.md +323 -0
  4. data/lib/rspec/sleeping_king_studios.rb +5 -0
  5. data/lib/rspec/sleeping_king_studios/matchers.rb +5 -0
  6. data/lib/rspec/sleeping_king_studios/matchers/active_model.rb +5 -0
  7. data/lib/rspec/sleeping_king_studios/matchers/active_model/have_errors.rb +219 -0
  8. data/lib/rspec/sleeping_king_studios/matchers/active_model/have_errors/error_expectation.rb +60 -0
  9. data/lib/rspec/sleeping_king_studios/matchers/active_model/have_errors/message_expectation.rb +17 -0
  10. data/lib/rspec/sleeping_king_studios/matchers/active_model/have_errors/require.rb +7 -0
  11. data/lib/rspec/sleeping_king_studios/matchers/active_model/require.rb +8 -0
  12. data/lib/rspec/sleeping_king_studios/matchers/base_matcher.rb +43 -0
  13. data/lib/rspec/sleeping_king_studios/matchers/built_in.rb +5 -0
  14. data/lib/rspec/sleeping_king_studios/matchers/built_in/be_kind_of.rb +68 -0
  15. data/lib/rspec/sleeping_king_studios/matchers/built_in/include.rb +92 -0
  16. data/lib/rspec/sleeping_king_studios/matchers/built_in/require.rb +7 -0
  17. data/lib/rspec/sleeping_king_studios/matchers/built_in/respond_to.rb +187 -0
  18. data/lib/rspec/sleeping_king_studios/matchers/core.rb +5 -0
  19. data/lib/rspec/sleeping_king_studios/matchers/core/be_boolean.rb +41 -0
  20. data/lib/rspec/sleeping_king_studios/matchers/core/construct.rb +138 -0
  21. data/lib/rspec/sleeping_king_studios/matchers/core/have_property.rb +84 -0
  22. data/lib/rspec/sleeping_king_studios/matchers/core/have_reader.rb +76 -0
  23. data/lib/rspec/sleeping_king_studios/matchers/core/have_writer.rb +101 -0
  24. data/lib/rspec/sleeping_king_studios/matchers/core/require.rb +7 -0
  25. data/lib/rspec/sleeping_king_studios/matchers/meta.rb +5 -0
  26. data/lib/rspec/sleeping_king_studios/matchers/meta/fail_with_actual.rb +142 -0
  27. data/lib/rspec/sleeping_king_studios/matchers/meta/pass_with_actual.rb +96 -0
  28. data/lib/rspec/sleeping_king_studios/matchers/meta/require.rb +7 -0
  29. data/lib/rspec/sleeping_king_studios/matchers/require.rb +12 -0
  30. data/lib/rspec/sleeping_king_studios/matchers/shared/match_parameters.rb +69 -0
  31. data/lib/rspec/sleeping_king_studios/matchers/shared/require.rb +7 -0
  32. data/lib/rspec/sleeping_king_studios/mocks/custom_double.rb +13 -0
  33. data/lib/rspec/sleeping_king_studios/require.rb +7 -0
  34. data/lib/rspec/sleeping_king_studios/version.rb +7 -0
  35. metadata +151 -0
@@ -0,0 +1,5 @@
1
+ # lib/rspec/sleeping_king_studios/matchers/core.rb
2
+
3
+ Dir[File.join File.dirname(__FILE__), 'core', '*.rb'].each do |file|
4
+ require file
5
+ end # end each
@@ -0,0 +1,41 @@
1
+ # lib/rspec/sleeping_king_studios/matchers/core/be_boolean.rb
2
+
3
+ require 'rspec/sleeping_king_studios/matchers/base_matcher'
4
+ require 'rspec/sleeping_king_studios/matchers/core/require'
5
+
6
+ module RSpec::SleepingKingStudios::Matchers::Core
7
+ # Matcher for testing whether an object is true or false.
8
+ #
9
+ # @since 1.0.0
10
+ class BeBooleanMatcher < RSpec::SleepingKingStudios::Matchers::BaseMatcher
11
+ # Checks if the object is true or false.
12
+ #
13
+ # @param [Object] actual the object to check
14
+ #
15
+ # @return [Boolean] true if the object is true or false, otherwise false
16
+ def matches? actual
17
+ super
18
+
19
+ true === actual || false === actual
20
+ end # method matches?
21
+
22
+ # @see BaseMatcher#failure_message_for_should
23
+ def failure_message_for_should
24
+ "expected #{@actual.inspect} to be true or false"
25
+ end # method failure_message_for_should
26
+
27
+ # @see BaseMatcher#failure_message_for_should_not
28
+ def failure_message_for_should_not
29
+ "expected #{@actual.inspect} not to be true or false"
30
+ end # method failure_message_for_should_not
31
+ end # class
32
+ end # module
33
+
34
+ module RSpec::SleepingKingStudios::Matchers
35
+ # @see RSpec::SleepingKingStudios::Matchers::Core::BeBooleanMatcher#matches?
36
+ def be_boolean
37
+ RSpec::SleepingKingStudios::Matchers::Core::BeBooleanMatcher.new
38
+ end # method be_boolean
39
+
40
+ alias_method :be_bool, :be_boolean
41
+ end # module
@@ -0,0 +1,138 @@
1
+ # spec/rspec/sleeping_king_studios/matchers/core/construct.rb
2
+
3
+ require 'rspec/sleeping_king_studios/matchers/base_matcher'
4
+ require 'rspec/sleeping_king_studios/matchers/core/require'
5
+
6
+ require 'rspec/sleeping_king_studios/matchers/shared/match_parameters'
7
+
8
+ module RSpec::SleepingKingStudios::Matchers::Core
9
+ # Matcher for checking whether an object can be constructed via #new and
10
+ # #initialize, and the parameters accepted by #initialize.
11
+ #
12
+ # @since 1.0.0
13
+ class ConstructMatcher < RSpec::SleepingKingStudios::Matchers::BaseMatcher
14
+ include RSpec::SleepingKingStudios::Matchers::Shared::MatchParameters
15
+
16
+ # Checks if the object responds to :new. If so, allocates an instance and
17
+ # checks the parameters expected by #initialize against the expected
18
+ # parameters, if any.
19
+ #
20
+ # @param [Object] actual the object to check
21
+ #
22
+ # @return [Boolean] true if the object responds to :new and accepts the
23
+ # specified parameters for #initialize; otherwise false
24
+ def matches? actual
25
+ @actual = actual
26
+ @failing_method_reasons = {}
27
+ @actual.respond_to?(:new) &&
28
+ matches_arity?(actual) &&
29
+ matches_keywords?(actual)
30
+ end # method matches?
31
+
32
+ # Adds a parameter count expectation and/or one or more keyword
33
+ # expectations (Ruby 2.0 only).
34
+ #
35
+ # @param [Integer, Range, nil] count the number of expected parameters; can
36
+ # be an integer, a range, or nil (parameter count is ignored)
37
+ # @param [Array<String, Symbol>] keywords list of keyword arguments
38
+ # accepted by the method
39
+ #
40
+ # @return [ConstructMatcher] self
41
+ def with count = nil, *keywords
42
+ @expected_arity = count unless count.nil?
43
+ @expected_keywords = keywords
44
+ self
45
+ end # method with
46
+
47
+ # Convenience method for more fluent specs. Does nothing and returns self.
48
+ #
49
+ # @return [ConstructMatcher] self
50
+ def arguments
51
+ self
52
+ end # method arguments
53
+
54
+ # @see BaseMatcher#failure_message_for_should
55
+ def failure_message_for_should
56
+ message = "expected #{@actual.inspect} to construct"
57
+ message << " with arguments:\n#{format_errors}" if @actual.respond_to?(:new)
58
+ message
59
+ end # method failure_message_for_should
60
+
61
+ # @see BaseMatcher#failure_message_for_should_not
62
+ def failure_message_for_should_not
63
+ message = "expected #{@actual.inspect} not to construct"
64
+ unless (formatted = format_expected_arguments).empty?
65
+ message << " with #{formatted}"
66
+ end # unless
67
+ message
68
+ end # method failure_message_for_should_not
69
+
70
+ private
71
+
72
+ def matches_arity? actual
73
+ return true unless @expected_arity
74
+
75
+ if result = check_method_arity(actual.allocate.method(:initialize), @expected_arity)
76
+ @failing_method_reasons.update result
77
+ return false
78
+ end # if
79
+
80
+ true
81
+ end # method matches_arity?
82
+
83
+ def matches_keywords? actual
84
+ return true unless @expected_keywords
85
+
86
+ if result = check_method_keywords(actual.allocate.method(:initialize), @expected_keywords)
87
+ @failing_method_reasons.update result
88
+ return false
89
+ end # if
90
+
91
+ true
92
+ end # method matches_keywords?
93
+
94
+ def format_expected_arguments
95
+ messages = []
96
+
97
+ if !@expected_arity.nil?
98
+ messages << "#{@expected_arity.inspect} argument#{1 == @expected_arity ? "" : "s"}"
99
+ end # if
100
+
101
+ if !(@expected_keywords.nil? || @expected_keywords.empty?)
102
+ messages << "keywords #{@expected_keywords.map(&:inspect).join(", ")}"
103
+ end # if
104
+
105
+ case messages.count
106
+ when 0..1
107
+ messages.join(", ")
108
+ when 2
109
+ "#{messages[0]} and #{messages[1]}"
110
+ else
111
+ "#{messages[1..-1].join(", ")}, and #{messages[0]}"
112
+ end # case
113
+ end # method format_expected_arguments
114
+
115
+ def format_errors
116
+ reasons, messages = @failing_method_reasons, []
117
+
118
+ if hsh = reasons.fetch(:not_enough_args, false)
119
+ messages << " expected at least #{hsh[:count]} arguments, but received #{hsh[:arity]}"
120
+ elsif hsh = reasons.fetch(:too_many_args, false)
121
+ messages << " expected at most #{hsh[:count]} arguments, but received #{hsh[:arity]}"
122
+ end # if-elsif
123
+
124
+ if ary = reasons.fetch(:unexpected_keywords, false)
125
+ messages << " unexpected keywords #{ary.map(&:inspect).join(", ")}"
126
+ end # if
127
+
128
+ messages.join "\n"
129
+ end # method format_errors
130
+ end # class
131
+ end # module
132
+
133
+ module RSpec::SleepingKingStudios::Matchers
134
+ # @see RSpec::SleepingKingStudios::Matchers::Core::ConstructMatcher#matches?
135
+ def construct
136
+ RSpec::SleepingKingStudios::Matchers::Core::ConstructMatcher.new
137
+ end # method construct
138
+ end # module
@@ -0,0 +1,84 @@
1
+ # lib/rspec/sleeping_king_studios/matchers/core/have_property.rb
2
+
3
+ require 'rspec/sleeping_king_studios/matchers/base_matcher'
4
+ require 'rspec/sleeping_king_studios/matchers/core/require'
5
+
6
+ module RSpec::SleepingKingStudios::Matchers::Core
7
+ # Matcher for testing whether an object has a specific property, e.g.
8
+ # responds to :property and :property= and :property= updates the value of
9
+ # :property.
10
+ #
11
+ # @since 1.0.0
12
+ class HavePropertyMatcher < RSpec::SleepingKingStudios::Matchers::BaseMatcher
13
+ # @param [String, Symbol] expected the property to check for on the actual
14
+ # object
15
+ def initialize expected
16
+ super
17
+ @expected = expected.intern
18
+ end # method initialize
19
+
20
+ # Checks if the object responds to :expected and :expected=. Additionally,
21
+ # if a value expectation is set, assigns the value via :expected= and
22
+ # compares the subsequent value of :expected to the specified value.
23
+ #
24
+ # @param [Object] actual the object to check
25
+ #
26
+ # @return [Boolean] true if the object responds to :expected and
27
+ # :expected= and matches the value expectation (if any); otherwise false
28
+ def matches? actual
29
+ super
30
+
31
+ @match_reader = @actual.respond_to? @expected
32
+ @match_writer = @actual.respond_to? :"#{@expected}="
33
+
34
+ return false unless @match_reader && @match_writer
35
+
36
+ if @value_set
37
+ @actual.send :"#{@expected}=", @value
38
+ return false unless @actual.send(@expected) == @value
39
+ end # if
40
+
41
+ true
42
+ end # method matches?
43
+
44
+ # Sets a value expectation. The matcher will set the object's value to the
45
+ # specified value using :property=, then compare the value from :property
46
+ # with the specified value.
47
+ #
48
+ # @params [Object] value the value to set and then compare
49
+ #
50
+ # @return [HavePropertyMatcher] self
51
+ def with value
52
+ @value = value
53
+ @value_set = true
54
+ self
55
+ end # method with
56
+
57
+ # @see BaseMatcher#failure_message_for_should
58
+ def failure_message_for_should
59
+ methods = []
60
+ methods << ":#{@expected}" unless @match_reader
61
+ methods << ":#{@expected}=" unless @match_writer
62
+
63
+ return "expected #{@actual.inspect} to respond to #{methods.join " and "}" unless methods.empty?
64
+
65
+ "unexpected value for #{@actual.inspect}\##{@expected}" +
66
+ "\n expected: #{@value.inspect}" +
67
+ "\n got: #{@actual.send(@expected).inspect}"
68
+ end # failure_message_for_should
69
+
70
+ # @see BaseMatcher#failure_message_for_should_not
71
+ def failure_message_for_should_not
72
+ message = "expected #{@actual.inspect} not to respond to :#{@expected} or :#{@expected}="
73
+ message << " with value #{@value.inspect}" if @value_set
74
+ message
75
+ end # failure_message_for_should_not
76
+ end # class
77
+ end # module
78
+
79
+ module RSpec::SleepingKingStudios::Matchers
80
+ # @see RSpec::SleepingKingStudios::Matchers::Core::HavePropertyMatcher#matches?
81
+ def have_property expected
82
+ RSpec::SleepingKingStudios::Matchers::Core::HavePropertyMatcher.new expected
83
+ end # method have_property
84
+ end # module
@@ -0,0 +1,76 @@
1
+ # lib/rspec/sleeping_king_studios/matchers/core/have_reader.rb
2
+
3
+ require 'rspec/sleeping_king_studios/matchers/base_matcher'
4
+ require 'rspec/sleeping_king_studios/matchers/core/require'
5
+
6
+ module RSpec::SleepingKingStudios::Matchers::Core
7
+ # Matcher for testing whether an object has a specific property reader, e.g.
8
+ # responds to :property.
9
+ #
10
+ # @since 1.0.0
11
+ class HaveReaderMatcher < RSpec::SleepingKingStudios::Matchers::BaseMatcher
12
+ # @param [String, Symbol] expected the property to check for on the actual
13
+ # object
14
+ def initialize expected
15
+ super
16
+ @expected = expected.intern
17
+ end # method initialize
18
+
19
+ # Checks if the object responds to :expected. Additionally, if a value
20
+ # expectation is set, compares the value of :expected to the specified
21
+ # value.
22
+ #
23
+ # @param [Object] actual the object to check
24
+ #
25
+ # @return [Boolean] true if the object responds to :expected and matches
26
+ # the value expectation (if any); otherwise false
27
+ def matches? actual
28
+ super
29
+
30
+ return false unless @match_reader = @actual.respond_to?(@expected)
31
+
32
+ if @value_set
33
+ return false unless @match_value = @actual.send(@expected) == @value
34
+ end # if
35
+
36
+ true
37
+ end # method matches?
38
+
39
+ # Sets a value expectation. The matcher will compare the value from
40
+ # :property with the specified value.
41
+ #
42
+ # @params [Object] value the value to compare
43
+ #
44
+ # @return [HaveReaderMatcher] self
45
+ def with value
46
+ @value = value
47
+ @value_set = true
48
+ self
49
+ end # method with
50
+
51
+ # @see BaseMatcher#failure_message_for_should
52
+ def failure_message_for_should
53
+ unless @match_reader
54
+ return "expected #{@actual} to respond to #{@expected.inspect}"
55
+ end # unless
56
+
57
+ "unexpected value for #{@actual}\##{@expected}\n" +
58
+ " expected: #{@value.inspect}\n" +
59
+ " got: #{@actual.send(@expected).inspect}"
60
+ end # method failure_message_for_should
61
+
62
+ # @see BaseMatcher#failure_message_for_should_not
63
+ def failure_message_for_should_not
64
+ message = "expected #{@actual} not to respond to #{@expected.inspect}"
65
+ message << " with value #{@value.inspect}" if @value_set
66
+ message
67
+ end # method failure_message_for_should
68
+ end # class
69
+ end # module
70
+
71
+ module RSpec::SleepingKingStudios::Matchers
72
+ # @see RSpec::SleepingKingStudios::Matchers::Core::HaveReaderMatcher#matches?
73
+ def have_reader expected
74
+ RSpec::SleepingKingStudios::Matchers::Core::HaveReaderMatcher.new expected
75
+ end # method have_reader
76
+ end # module
@@ -0,0 +1,101 @@
1
+ # lib/rspec/sleeping_king_studios/matchers/core/have_mutator.rb
2
+
3
+ require 'rspec/sleeping_king_studios/matchers/base_matcher'
4
+ require 'rspec/sleeping_king_studios/matchers/core/require'
5
+
6
+ module RSpec::SleepingKingStudios::Matchers::Core
7
+ # Matcher for testing whether an object has a specific property writer, e.g.
8
+ # responds to :property= and updates the state.
9
+ #
10
+ # @since 1.0.0
11
+ class HaveWriterMatcher < RSpec::SleepingKingStudios::Matchers::BaseMatcher
12
+ # @param [String, Symbol] expected the property to check for on the actual
13
+ # object
14
+ def initialize expected
15
+ super
16
+ @expected = expected.to_s.gsub(/=$/,'').intern
17
+ end # method initialize
18
+
19
+ # Checks if the object responds to :expected=. Additionally, if a value
20
+ # expectation is set, assigns the value via :expected= and compares the
21
+ # subsequent value to the specified value using :expected or the block
22
+ # provided to #with.
23
+ #
24
+ # @param [Object] actual the object to check
25
+ #
26
+ # @return [Boolean] true if the object responds to :expected= and matches
27
+ # the value expectation (if any); otherwise false
28
+ def matches? actual
29
+ super
30
+
31
+ return false unless @match_writer = @actual.respond_to?(:"#{@expected}=")
32
+
33
+ if @value_set
34
+ @actual.send :"#{@expected}=", @value
35
+
36
+ if @value_block.respond_to?(:call)
37
+ return false unless @value == (@actual_value = @actual.instance_eval(&@value_block))
38
+ elsif @actual.respond_to?(@expected)
39
+ return false unless @value == (@actual_value = @actual.send(@expected))
40
+ else
41
+ return false
42
+ end # if-elsif
43
+ end # if
44
+
45
+ true
46
+ end # method matches?
47
+
48
+ # Sets a value expectation. The matcher will set the object's value to the
49
+ # specified value using :property=, then compare the value from :property
50
+ # with the specified value. If a block is provided, the actual object
51
+ # evaluates the block and the value is compared to the specified value
52
+ # instead of using :property.
53
+ #
54
+ # @params [Object] value the value to compare
55
+ #
56
+ # @yield if a block is provided, the block is used to check the value after
57
+ # setting :property= instead of using :property.
58
+ #
59
+ # @example Using :property to check the value
60
+ # expect(instance).to have_writer(:foo).with(42)
61
+ #
62
+ # @example Using a block to check the valuye
63
+ # expect(instance).to have_writer(:bar).with(42) { self.getBar() }
64
+ #
65
+ # @return [HaveWriterMatcher] self
66
+ def with value, &block
67
+ @value = value
68
+ @value_set = true
69
+ @value_block = block
70
+ self
71
+ end # method with
72
+
73
+ # @see BaseMatcher#failure_message_for_should
74
+ def failure_message_for_should
75
+ return "expected #{@actual.inspect} to respond to #{@expected.inspect}=" unless @match_writer
76
+
77
+ unless @actual.respond_to?(@expected) || @value_block.respond_to?(:call)
78
+ return "unable to test #{@expected.inspect}= because #{@actual} does " +
79
+ "not respond to #{@expected.inspect}; try adding a test block to #with"
80
+ end # unless
81
+
82
+ return "unexpected value for #{@actual.inspect}#foo=\n" +
83
+ " expected: #{@value.inspect}\n" +
84
+ " got: #{@actual_value.inspect}"
85
+ end # method failure_message_for_should
86
+
87
+ # @see BaseMatcher#failure_message_for_should_not
88
+ def failure_message_for_should_not
89
+ message = "expected #{@actual} not to respond to #{@expected.inspect}="
90
+ message << " with value #{@value.inspect}" if @value_set && @match_writer
91
+ message
92
+ end # method failure_message_for_should
93
+ end # class
94
+ end # module
95
+
96
+ module RSpec::SleepingKingStudios::Matchers
97
+ # @see RSpec::SleepingKingStudios::Matchers::Core::HaveWriterMatcher#matches?
98
+ def have_writer expected
99
+ RSpec::SleepingKingStudios::Matchers::Core::HaveWriterMatcher.new expected
100
+ end # method have_writer
101
+ end # module