sinclair 1.6.6 → 1.6.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Sinclair
4
+ module Matchers
5
+ # @abstract
6
+ # @api private
7
+ #
8
+ # Base class for all matchers
9
+ class Base < RSpec::Matchers::BuiltIn::BaseMatcher
10
+ # @param method_name [String,Symbol] the method, to be checked, name
11
+ def initialize(method_name)
12
+ @method_name = method_name.to_sym
13
+ end
14
+
15
+ # definition needed for block matchers
16
+ #
17
+ # @return [Boolean]
18
+ def supports_block_expectations?
19
+ true
20
+ end
21
+
22
+ # Checkes if another instnce is equal self
23
+ #
24
+ # @return [Boolean]
25
+ def equal?(other)
26
+ return unless other.class == self.class
27
+
28
+ other.method_name == method_name &&
29
+ other.try(:klass) == try(:klass)
30
+ end
31
+
32
+ alias == equal?
33
+
34
+ protected
35
+
36
+ # @method method_name
37
+ # @private
38
+ #
39
+ # The method, to be checked, name
40
+ #
41
+ # @return [Symbol]
42
+ attr_reader :method_name
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Sinclair
4
+ module Matchers
5
+ # @api private
6
+ # @author darthjee
7
+ #
8
+ # AddInstanceMethod is able to build an instance of
9
+ # {Sinclair::Matchers::ChangeClassMethodOn}
10
+ class ChangeClassMethod < Base
11
+ include AddMethod
12
+
13
+ # @api public
14
+ #
15
+ # Builds final matcher
16
+ #
17
+ # @return [Sinclair::Matchers::ChangeClassMethodOn]
18
+ alias on to
19
+
20
+ private
21
+
22
+ # @private
23
+ #
24
+ # Error description on wrong usage
25
+ #
26
+ # @return String
27
+ def matcher_error
28
+ 'You should specify which class the method is being changed on' \
29
+ "change_class_method(:#{method_name}).on(klass)"
30
+ end
31
+
32
+ # @private
33
+ #
34
+ # Class of the real matcher
35
+ #
36
+ # @return [Class<ChangeClassMethodOn>]
37
+ def add_method_to_class
38
+ ChangeClassMethodOn
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Sinclair
4
+ module Matchers
5
+ # @api private
6
+ # @author darthjee
7
+ #
8
+ # Checks if a class method was changed
9
+ # by the call of a block
10
+ #
11
+ # This is used with a RSpec DSL method
12
+ # change_class_method(method_name).on(class_object)
13
+ class ChangeClassMethodOn < ChangeMethodOn
14
+ # @param [Class] klass
15
+ # Class where the class method should be added to
16
+ #
17
+ # @param method_name [SYmbol,String] method name
18
+ def initialize(target, method_name)
19
+ @klass = target
20
+ super(method_name)
21
+ end
22
+
23
+ # Return expectaton description
24
+ #
25
+ # @return [String]
26
+ def description
27
+ "change class method '#{method_name}' on #{klass}"
28
+ end
29
+
30
+ # Returns message on expectation failure
31
+ #
32
+ # @return [String]
33
+ def failure_message_for_should
34
+ "expected class method '#{method_name}' to be changed on #{klass} but " \
35
+ "#{initial_state ? "it didn't" : "it didn't exist"}"
36
+ end
37
+
38
+ # Returns message on expectation failure for negative expectation
39
+ #
40
+ # @return [String]
41
+ def failure_message_for_should_not
42
+ "expected class method '#{method_name}' not to be changed on #{klass} but it was"
43
+ end
44
+
45
+ private
46
+
47
+ # Checks if class has instance method defined
48
+ #
49
+ # @return [Boolean]
50
+ def state
51
+ klass.methods(false).include?(method_name.to_sym) \
52
+ && klass.method(method_name)
53
+ end
54
+
55
+ # Raises when block was not given
56
+ #
57
+ # @raise SyntaxError
58
+ def raise_block_syntax_error
59
+ raise SyntaxError, 'Block not received by the `change_class_method_on` matcher. ' \
60
+ 'Perhaps you want to use `{ ... }` instead of do/end?'
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Sinclair
4
+ module Matchers
5
+ # @api private
6
+ # @author darthjee
7
+ #
8
+ # AddInstanceMethod is able to build an instance of
9
+ # {Sinclair::Matchers::ChangeInstanceMethodOn}
10
+ class ChangeInstanceMethod < Base
11
+ include AddMethod
12
+
13
+ # @api public
14
+ #
15
+ # Builds final matcher
16
+ #
17
+ # @return [Sinclair::Matchers::ChangeInstanceMethodOn]
18
+ alias on to
19
+
20
+ private
21
+
22
+ # @private
23
+ #
24
+ # Error description on wrong usage
25
+ #
26
+ # @return String
27
+ def matcher_error
28
+ 'You should specify which instance the method is being changed on' \
29
+ "change_method(:#{method_name}).on(instance)"
30
+ end
31
+
32
+ # @private
33
+ #
34
+ # Class of the real matcher
35
+ #
36
+ # @return [Class<Sinclair::Matchers::Base>]
37
+ def add_method_to_class
38
+ ChangeInstanceMethodOn
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Sinclair
4
+ module Matchers
5
+ # @api private
6
+ # @author darthjee
7
+ #
8
+ # Checks if a method was changed
9
+ # by the call of a block
10
+ #
11
+ # This is used with a RSpec DSL method
12
+ # change_method(method_name).on(class_object)
13
+ class ChangeInstanceMethodOn < ChangeMethodOn
14
+ # @overload initialize(klass, method_name)
15
+ # @param [Class] klass
16
+ # class where the method should be added to
17
+ #
18
+ # @overload initialize(instance, method_name)
19
+ # @param [Object] instance
20
+ # instance of the class where the method should be added to
21
+ #
22
+ # @param method_name [Symbol,String] method name
23
+ def initialize(target, method_name)
24
+ if target.is_a?(Class)
25
+ @klass = target
26
+ else
27
+ @instance = target
28
+ end
29
+
30
+ super(method_name)
31
+ end
32
+
33
+ # Returnst expectaton description
34
+ #
35
+ # @return [String]
36
+ def description
37
+ "change method '#{method_name}' on #{klass} instances"
38
+ end
39
+
40
+ # Returns message on expectation failure
41
+ #
42
+ # @return [String]
43
+ def failure_message_for_should
44
+ "expected '#{method_name}' to be changed on #{klass} but " \
45
+ "#{initial_state ? "it didn't" : "it didn't exist"}"
46
+ end
47
+
48
+ # Returns message on expectation failure for negative expectation
49
+ #
50
+ # @return [String]
51
+ def failure_message_for_should_not
52
+ "expected '#{method_name}' not to be changed on #{klass} but it was"
53
+ end
54
+
55
+ protected
56
+
57
+ # @method instance
58
+ # @api private
59
+ # @private
60
+ #
61
+ # Instance of the class where the method should be added
62
+ #
63
+ # @return [Object]
64
+ attr_reader :instance
65
+
66
+ # @private
67
+ #
68
+ # Class to be analised
69
+ #
70
+ # @return [Class]
71
+ def klass
72
+ @klass ||= instance.class
73
+ end
74
+
75
+ private
76
+
77
+ # @private
78
+ #
79
+ # Checks if class has instance method defined
80
+ #
81
+ # @return [Boolean]
82
+ def state
83
+ klass.method_defined?(method_name) &&
84
+ klass.instance_method(method_name)
85
+ end
86
+
87
+ # @private
88
+ #
89
+ # Raises when block was not given
90
+ #
91
+ # @raise SyntaxError
92
+ def raise_block_syntax_error
93
+ raise SyntaxError, 'Block not received by the `change_instance_method_on` matcher. ' \
94
+ 'Perhaps you want to use `{ ... }` instead of do/end?'
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Sinclair
4
+ module Matchers
5
+ # @api private
6
+ # @author darthjee
7
+ # @abstract
8
+ #
9
+ # Base class for change_method_on matcher
10
+ class ChangeMethodOn < Base
11
+ include MethodTo
12
+
13
+ private
14
+
15
+ # @private
16
+ #
17
+ # Checks if a method was changed
18
+ #
19
+ # @return Boolean
20
+ def check
21
+ initial_state && initial_state != final_state
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Sinclair
4
+ module Matchers
5
+ # @api private
6
+ #
7
+ # Common methods on final matchers
8
+ module MethodTo
9
+ # Used for other versions of rspec
10
+ #
11
+ # Some versions call failure_message, others
12
+ # call failure_message_for_should
13
+ #
14
+ # @return [String]
15
+ def failure_message
16
+ failure_message_for_should
17
+ end
18
+
19
+ # Used for other versions of rspec
20
+ #
21
+ # Some versions call failure_message_when_negated, others
22
+ # call failure_message_for_should_not
23
+ #
24
+ # @return [String]
25
+ def failure_message_when_negated
26
+ failure_message_for_should_not
27
+ end
28
+
29
+ # Checks if expectation is true or not
30
+ #
31
+ # @return [Boolean] expectation check
32
+ def matches?(event_proc)
33
+ return false unless event_proc.is_a?(Proc)
34
+
35
+ raise_block_syntax_error if block_given?
36
+ perform_change(event_proc)
37
+ check
38
+ end
39
+
40
+ protected
41
+
42
+ # @method klass
43
+ # @api private
44
+ # @private
45
+ #
46
+ # Class where class method should be added to
47
+ #
48
+ # @return [Class]
49
+ attr_reader :klass
50
+
51
+ private
52
+
53
+ # @method initial_state
54
+ # @api private
55
+ # @private
56
+ #
57
+ # State before running the block
58
+ #
59
+ # @return [Object]
60
+
61
+ # @method final_state
62
+ # @api private
63
+ # @private
64
+ #
65
+ # State after running the block
66
+ #
67
+ # @return [Object]
68
+ attr_reader :initial_state, :final_state
69
+
70
+ # @private
71
+ #
72
+ # Call block to check if it aded a method or not
73
+ #
74
+ # @return [Boolan]
75
+ def perform_change(event_proc)
76
+ @initial_state = state
77
+ event_proc.call
78
+ @final_state = state
79
+ end
80
+ end
81
+ end
82
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Sinclair
4
- VERSION = '1.6.6'
4
+ VERSION = '1.6.7'
5
5
  end
@@ -13,22 +13,46 @@ describe Sinclair::Matchers::AddClassMethodTo do
13
13
  proc { klass.send(:define_singleton_method, method) {} }
14
14
  end
15
15
 
16
- context 'when a method is added' do
17
- it { expect(matcher).to be_matches(event_proc) }
18
- end
16
+ context 'when class does not have the method yet' do
17
+ context 'when a method is added' do
18
+ it { expect(matcher).to be_matches(event_proc) }
19
+ end
19
20
 
20
- context 'when a method is not added' do
21
- let(:event_proc) { proc {} }
21
+ context 'when a method is not added' do
22
+ let(:event_proc) { proc {} }
22
23
 
23
- it { expect(matcher).not_to be_matches(event_proc) }
24
- end
24
+ it { expect(matcher).not_to be_matches(event_proc) }
25
+ end
26
+
27
+ context 'when the wrong method is added' do
28
+ let(:event_proc) do
29
+ proc { klass.send(:define_singleton_method, :another_method) {} }
30
+ end
31
+
32
+ it { expect(matcher).not_to be_matches(event_proc) }
33
+ end
25
34
 
26
- context 'when the wrong method is added' do
27
- let(:event_proc) do
28
- proc { klass.send(:define_singleton_method, :another_method) {} }
35
+ context 'when method already existed' do
36
+ before { event_proc.call }
37
+
38
+ it { expect(matcher).not_to be_matches(event_proc) }
29
39
  end
30
40
 
31
- it { expect(matcher).not_to be_matches(event_proc) }
41
+ context 'when method is added to instances' do
42
+ let(:event_proc) do
43
+ proc { klass.send(:define_method, method) {} }
44
+ end
45
+
46
+ it { expect(matcher).not_to be_matches(event_proc) }
47
+ end
48
+ end
49
+
50
+ context 'when class already has the method' do
51
+ before { klass.send(:define_singleton_method, method) {} }
52
+
53
+ context 'when a method is changed' do
54
+ it { expect(matcher).not_to be_matches(event_proc) }
55
+ end
32
56
  end
33
57
 
34
58
  context 'when a block is given' do
@@ -36,7 +60,7 @@ describe Sinclair::Matchers::AddClassMethodTo do
36
60
  expect { matcher.matches?(event_proc) { 1 } }
37
61
  .to raise_error(
38
62
  SyntaxError, 'Block not received by the `add_class_method_to` matcher. ' \
39
- 'Perhaps you want to use `{ ... }` instead of do/end?'
63
+ 'Perhaps you want to use `{ ... }` instead of do/end?'
40
64
  )
41
65
  end
42
66
  end
@@ -45,7 +69,7 @@ describe Sinclair::Matchers::AddClassMethodTo do
45
69
  describe '#failure_message_for_should' do
46
70
  it 'returns information on the instance class and method' do
47
71
  expect(matcher.failure_message_for_should)
48
- .to eq("expected class_method '#{method}' to be added to #{klass} but it didn't")
72
+ .to eq("expected class method '#{method}' to be added to #{klass} but it didn't")
49
73
  end
50
74
 
51
75
  context 'when method already exited' do
@@ -56,7 +80,7 @@ describe Sinclair::Matchers::AddClassMethodTo do
56
80
 
57
81
  it 'returns information on the instance class and method' do
58
82
  expect(matcher.failure_message_for_should)
59
- .to eq("expected class_method '#{method}' to be added to #{klass} but it already existed")
83
+ .to eq("expected class method '#{method}' to be added to #{klass} but it already existed")
60
84
  end
61
85
  end
62
86
  end
@@ -64,14 +88,14 @@ describe Sinclair::Matchers::AddClassMethodTo do
64
88
  describe '#failure_message_for_should_not' do
65
89
  it 'returns information on the instance class and method' do
66
90
  expect(matcher.failure_message_for_should_not)
67
- .to eq("expected class_method '#{method}' not to be added to #{klass} but it was")
91
+ .to eq("expected class method '#{method}' not to be added to #{klass} but it was")
68
92
  end
69
93
  end
70
94
 
71
95
  describe 'description' do
72
96
  it 'returns information on the instance class and method' do
73
97
  expect(matcher.description)
74
- .to eq("add method class_method '#{method}' to #{klass}")
98
+ .to eq("add class method '#{method}' to #{klass}")
75
99
  end
76
100
  end
77
101
  end