duckpond 1.1.4 → 1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6b28a479d7cc232dbbd474d545caece0c5927ff8
4
- data.tar.gz: ffd5f52ff703529d2c96ae47c680d85ab0367bde
3
+ metadata.gz: e412869c6899468637cccaf6debbf31ffef6fd7a
4
+ data.tar.gz: aaf49e52a9f2c35987260541a3c888d7cf89e7c6
5
5
  SHA512:
6
- metadata.gz: 5ac93596986601000969400607f1cc2b2f57b78c0e539848a3df6f6cd55fbf11d5f170328a5b7daebf6493c37a27fc5b408f3f416d314b7d9e20df16ffa8ef71
7
- data.tar.gz: 8af2817b6a54bd9954fc9b93a965b4699166ef898198283117e74b738d4291b873e48d2b84953aa49fe34681fe9a70bbb10eca9dca38e9e4d9e7c671533d2551
6
+ metadata.gz: f14ccc6e1268198efc50b0116e0fa4a4c0d4ec52ffeee97e4bf92f2fbf2396bf4a682614f08204310112a52fb24ec8b2c99ff7bb87e302b5bf8eb10d42c738b1
7
+ data.tar.gz: 42995441b44f631d907cec3d3e5d8849b2f0266cb84f16a01a627e2e202c042459b139ae9f2ad82dcb440630db0f267e08d8c1ac92aa55817049067da936a440
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- duckpond (1.1.3)
4
+ duckpond (1.1.4)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -86,6 +86,20 @@ five characters long (such as the word "Hello"):
86
86
  has_method :length, responds_with: 5
87
87
  end
88
88
 
89
+ Finally, if you really want to get down and dirty with interrogating method results, you can use a block thusly (the result of calling the method will be yielded to the block):
90
+
91
+ class MyBlockContract < DuckPond::Contract
92
+ has_method :length do |method_result|
93
+ method_result == 5
94
+ end
95
+ end
96
+
97
+ class MyOtherBlockContract < DuckPond::Contract
98
+ has_method :include?, given_args: "Hell" do |method_result|
99
+ method_result == true
100
+ end
101
+ end
102
+
89
103
  Note: The method will only be *called* if you use the :reponds_with option. Otherwise, it just tests for the method's existence.
90
104
 
91
105
  In the real world, a contract might look like this:
@@ -21,21 +21,26 @@ module DuckPond
21
21
  # Check the method actually exists.
22
22
  return false unless subject.respond_to? method_name
23
23
 
24
- # If required, check the response from the method was what the user expected.
25
- return false unless _responds_with?(subject, method_name, @options[:responds_with], @options[:given_args])
24
+ # Unless a block was given, or a response is required, we're done!
25
+ return true unless @options[:block] || @options[:responds_with]
26
26
 
27
+ # If we get this far, we need to tap into the result of the method
28
+ # call, as the user is interrogating it somehow.
29
+ response_when_called(subject, method_name, @options[:given_args])
30
+ .tap do |response_when_called|
31
+ if @options[:block]
32
+ return false unless @options[:block].call(response_when_called)
33
+ end
34
+ if @options[:responds_with]
35
+ return false unless response_when_called == @options[:responds_with]
36
+ end
37
+ end
27
38
  true
28
39
  end
29
40
 
30
41
  private
31
- #
32
- # _responds_with?
33
- #
34
- # if a method response expectation was passed in, this just calls the method (with the arguments
35
- # if given) and does an == compare with the subject.
36
- #
37
- def _responds_with?(subject, method, expected_result, args = [])
38
- return expected_result ? subject.send(method_name, *args) == expected_result : true
42
+ def response_when_called(subject, method, args = [])
43
+ subject.send(method_name, *args)
39
44
  end
40
45
 
41
46
  end
@@ -11,9 +11,9 @@ module DuckPond
11
11
  #
12
12
  # initialize
13
13
  #
14
- def initialize(opts = {})
14
+ def initialize(opts={}, block)
15
15
  @options = opts
16
+ @options[:block] = block
16
17
  end
17
-
18
18
  end
19
19
  end
@@ -37,8 +37,8 @@ module DuckPond
37
37
  #
38
38
  # add a clause to the contract's list of clauses
39
39
  #
40
- def has_clause(clause_klass, opts = {})
41
- clauses << clause_klass.new(opts)
40
+ def has_clause(clause_klass, opts = {}, &block)
41
+ clauses << clause_klass.new(opts, block)
42
42
  end
43
43
 
44
44
 
@@ -48,7 +48,11 @@ module DuckPond
48
48
  # Adds a method clause to the contract
49
49
  #
50
50
  def has_method(method_name, opts = {})
51
- has_clause MethodClause, opts.merge(:method_name => method_name)
51
+ if block_given?
52
+ has_clause(MethodClause, opts.merge(:method_name => method_name), &Proc.new)
53
+ else
54
+ has_clause(MethodClause, opts.merge(:method_name => method_name))
55
+ end
52
56
  end
53
57
 
54
58
  #
@@ -1,3 +1,3 @@
1
1
  module DuckPond
2
- VERSION = "1.1.4"
2
+ VERSION = "1.2"
3
3
  end
@@ -0,0 +1,5 @@
1
+ class SpecificIncludeBehaviourContract < DuckPond::Contract
2
+ has_method :include?, given_args: "Hell" do |method_result|
3
+ method_result == true
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ class SpecificLengthBehaviourContract < DuckPond::Contract
2
+
3
+ has_method :length do |method_result|
4
+ method_result == 5
5
+ end
6
+
7
+ end
@@ -0,0 +1,7 @@
1
+ class SpecificLengthContract < DuckPond::Contract
2
+
3
+ has_method :length, responds_with: 5
4
+
5
+ has_method :include?, responds_with: true, given_args: "Hell"
6
+
7
+ end
@@ -11,7 +11,7 @@ module DuckPond
11
11
  describe 'Constructor' do
12
12
  context 'when constructed with a method name option' do
13
13
  it 'adds that method name as an attribute' do
14
- clause = MethodClause.new(:method_name => :foo)
14
+ clause = MethodClause.new({:method_name => :foo}, nil)
15
15
  expect(clause.method_name).to eq :foo
16
16
  end
17
17
  end
@@ -20,7 +20,7 @@ module DuckPond
20
20
  describe 'Instance Methods' do
21
21
 
22
22
  describe '#satisfied_by?' do
23
- let(:clause) { MethodClause.new(:method_name => :length) }
23
+ let(:clause) { MethodClause.new({:method_name => :length}, nil) }
24
24
 
25
25
  context 'when the subject responds to the clauses method' do
26
26
  it 'returns true' do
@@ -53,11 +53,25 @@ module DuckPond
53
53
  #
54
54
  # see spec/classes/specific_length_contract.rb
55
55
  #
56
- describe SpecificLenghtContract do
56
+ describe SpecificLengthContract do
57
57
  it 'checks a methods response is correct' do
58
- expect(SpecificLenghtContract.fulfills?("Hello")).to eq true
59
- expect(SpecificLenghtContract.fulfills?("Yello")).to eq false
60
- expect(SpecificLenghtContract.fulfills?("Goodbye")).to eq false
58
+ expect(SpecificLengthContract.fulfills?("Hello")).to eq true
59
+ expect(SpecificLengthContract.fulfills?("Yello")).to eq false
60
+ expect(SpecificLengthContract.fulfills?("Goodbye")).to eq false
61
+ end
62
+ end
63
+
64
+ describe SpecificLengthBehaviourContract do
65
+ it 'checks the given block against the subjects method repsonse' do
66
+ expect(SpecificLengthBehaviourContract.fulfills?('Hello')).to eq true
67
+ expect(SpecificLengthBehaviourContract.fulfills?('Goodbye')).to eq false
68
+ end
69
+ end
70
+
71
+ describe SpecificIncludeBehaviourContract do
72
+ it 'checks the given block against the subjects method response' do
73
+ expect(SpecificIncludeBehaviourContract.fulfills?('Hello')).to eq true
74
+ expect(SpecificLengthBehaviourContract.fulfills?('Goodbye')).to eq false
61
75
  end
62
76
  end
63
77
 
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,9 @@
1
1
  require 'duckpond'
2
2
  require 'classes/contracts/length_contract'
3
3
  require 'classes/contracts/specific_length_contract'
4
+ require 'classes/contracts/specific_length_behaviour_contract'
5
+ require 'classes/contracts/specific_include_behaviour_contract'
6
+
4
7
  require 'classes/contracts/composite_contract'
5
8
  require 'coveralls'
6
9
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: duckpond
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.4
4
+ version: '1.2'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mikey Hogarth
@@ -64,6 +64,9 @@ files:
64
64
  - lib/duckpond/version.rb
65
65
  - spec/classes/contracts/composite_contract.rb
66
66
  - spec/classes/contracts/length_contract.rb
67
+ - spec/classes/contracts/specific_include_behaviour_contract.rb
68
+ - spec/classes/contracts/specific_length_behaviour_contract.rb
69
+ - spec/classes/contracts/specific_length_contract.rb
67
70
  - spec/clauses/method_clause_spec.rb
68
71
  - spec/contract_spec.rb
69
72
  - spec/inspection_spec.rb
@@ -88,15 +91,17 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
91
  version: '0'
89
92
  requirements: []
90
93
  rubyforge_project:
91
- rubygems_version: 2.1.10
94
+ rubygems_version: 2.2.2
92
95
  signing_key:
93
96
  specification_version: 4
94
97
  summary: Explicit duck-typing for ruby
95
98
  test_files:
96
99
  - spec/classes/contracts/composite_contract.rb
97
100
  - spec/classes/contracts/length_contract.rb
101
+ - spec/classes/contracts/specific_include_behaviour_contract.rb
102
+ - spec/classes/contracts/specific_length_behaviour_contract.rb
103
+ - spec/classes/contracts/specific_length_contract.rb
98
104
  - spec/clauses/method_clause_spec.rb
99
105
  - spec/contract_spec.rb
100
106
  - spec/inspection_spec.rb
101
107
  - spec/spec_helper.rb
102
- has_rdoc: