entitlements 0.1.8 → 0.2.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.
Files changed (176) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/bin/deploy-entitlements +10 -1
  4. data/lib/contracts-ruby2/CHANGELOG.markdown +115 -0
  5. data/lib/contracts-ruby2/Gemfile +17 -0
  6. data/lib/contracts-ruby2/LICENSE +23 -0
  7. data/lib/contracts-ruby2/README.md +108 -0
  8. data/lib/contracts-ruby2/Rakefile +8 -0
  9. data/lib/contracts-ruby2/TODO.markdown +6 -0
  10. data/lib/contracts-ruby2/TUTORIAL.md +773 -0
  11. data/lib/contracts-ruby2/benchmarks/bench.rb +67 -0
  12. data/lib/contracts-ruby2/benchmarks/hash.rb +69 -0
  13. data/lib/contracts-ruby2/benchmarks/invariants.rb +91 -0
  14. data/lib/contracts-ruby2/benchmarks/io.rb +62 -0
  15. data/lib/contracts-ruby2/benchmarks/wrap_test.rb +57 -0
  16. data/lib/contracts-ruby2/contracts.gemspec +17 -0
  17. data/lib/contracts-ruby2/cucumber.yml +1 -0
  18. data/lib/contracts-ruby2/dependabot.yml +20 -0
  19. data/lib/contracts-ruby2/features/README.md +17 -0
  20. data/lib/contracts-ruby2/features/basics/functype.feature +71 -0
  21. data/lib/contracts-ruby2/features/basics/pretty-print.feature +241 -0
  22. data/lib/contracts-ruby2/features/basics/simple_example.feature +210 -0
  23. data/lib/contracts-ruby2/features/builtin_contracts/README.md +22 -0
  24. data/lib/contracts-ruby2/features/builtin_contracts/and.feature +103 -0
  25. data/lib/contracts-ruby2/features/builtin_contracts/any.feature +44 -0
  26. data/lib/contracts-ruby2/features/builtin_contracts/args.feature +80 -0
  27. data/lib/contracts-ruby2/features/builtin_contracts/array_of.feature +1 -0
  28. data/lib/contracts-ruby2/features/builtin_contracts/bool.feature +64 -0
  29. data/lib/contracts-ruby2/features/builtin_contracts/enum.feature +1 -0
  30. data/lib/contracts-ruby2/features/builtin_contracts/eq.feature +1 -0
  31. data/lib/contracts-ruby2/features/builtin_contracts/exactly.feature +1 -0
  32. data/lib/contracts-ruby2/features/builtin_contracts/func.feature +1 -0
  33. data/lib/contracts-ruby2/features/builtin_contracts/hash_of.feature +1 -0
  34. data/lib/contracts-ruby2/features/builtin_contracts/int.feature +93 -0
  35. data/lib/contracts-ruby2/features/builtin_contracts/keyword_args.feature +1 -0
  36. data/lib/contracts-ruby2/features/builtin_contracts/maybe.feature +1 -0
  37. data/lib/contracts-ruby2/features/builtin_contracts/nat.feature +115 -0
  38. data/lib/contracts-ruby2/features/builtin_contracts/nat_pos.feature +119 -0
  39. data/lib/contracts-ruby2/features/builtin_contracts/neg.feature +115 -0
  40. data/lib/contracts-ruby2/features/builtin_contracts/none.feature +145 -0
  41. data/lib/contracts-ruby2/features/builtin_contracts/not.feature +1 -0
  42. data/lib/contracts-ruby2/features/builtin_contracts/num.feature +64 -0
  43. data/lib/contracts-ruby2/features/builtin_contracts/or.feature +83 -0
  44. data/lib/contracts-ruby2/features/builtin_contracts/pos.feature +116 -0
  45. data/lib/contracts-ruby2/features/builtin_contracts/range_of.feature +1 -0
  46. data/lib/contracts-ruby2/features/builtin_contracts/respond_to.feature +78 -0
  47. data/lib/contracts-ruby2/features/builtin_contracts/send.feature +147 -0
  48. data/lib/contracts-ruby2/features/builtin_contracts/set_of.feature +1 -0
  49. data/lib/contracts-ruby2/features/builtin_contracts/xor.feature +99 -0
  50. data/lib/contracts-ruby2/features/support/env.rb +6 -0
  51. data/lib/contracts-ruby2/lib/contracts/attrs.rb +24 -0
  52. data/lib/contracts-ruby2/lib/contracts/builtin_contracts.rb +542 -0
  53. data/lib/contracts-ruby2/lib/contracts/call_with.rb +108 -0
  54. data/lib/contracts-ruby2/lib/contracts/core.rb +52 -0
  55. data/lib/contracts-ruby2/lib/contracts/decorators.rb +47 -0
  56. data/lib/contracts-ruby2/lib/contracts/engine/base.rb +136 -0
  57. data/lib/contracts-ruby2/lib/contracts/engine/eigenclass.rb +50 -0
  58. data/lib/contracts-ruby2/lib/contracts/engine/target.rb +70 -0
  59. data/lib/contracts-ruby2/lib/contracts/engine.rb +26 -0
  60. data/lib/contracts-ruby2/lib/contracts/errors.rb +71 -0
  61. data/lib/contracts-ruby2/lib/contracts/formatters.rb +136 -0
  62. data/lib/contracts-ruby2/lib/contracts/invariants.rb +68 -0
  63. data/lib/contracts-ruby2/lib/contracts/method_handler.rb +187 -0
  64. data/lib/contracts-ruby2/lib/contracts/method_reference.rb +100 -0
  65. data/lib/contracts-ruby2/lib/contracts/support.rb +61 -0
  66. data/lib/contracts-ruby2/lib/contracts/validators.rb +139 -0
  67. data/lib/contracts-ruby2/lib/contracts/version.rb +3 -0
  68. data/lib/contracts-ruby2/lib/contracts.rb +281 -0
  69. data/lib/contracts-ruby2/script/docs-release +3 -0
  70. data/lib/contracts-ruby2/script/docs-staging +3 -0
  71. data/lib/contracts-ruby2/script/rubocop.rb +5 -0
  72. data/lib/contracts-ruby2/spec/attrs_spec.rb +119 -0
  73. data/lib/contracts-ruby2/spec/builtin_contracts_spec.rb +461 -0
  74. data/lib/contracts-ruby2/spec/contracts_spec.rb +770 -0
  75. data/lib/contracts-ruby2/spec/fixtures/fixtures.rb +730 -0
  76. data/lib/contracts-ruby2/spec/invariants_spec.rb +17 -0
  77. data/lib/contracts-ruby2/spec/methods_spec.rb +54 -0
  78. data/lib/contracts-ruby2/spec/module_spec.rb +18 -0
  79. data/lib/contracts-ruby2/spec/override_validators_spec.rb +162 -0
  80. data/lib/contracts-ruby2/spec/ruby_version_specific/contracts_spec_1.9.rb +24 -0
  81. data/lib/contracts-ruby2/spec/ruby_version_specific/contracts_spec_2.0.rb +55 -0
  82. data/lib/contracts-ruby2/spec/ruby_version_specific/contracts_spec_2.1.rb +63 -0
  83. data/lib/contracts-ruby2/spec/spec_helper.rb +102 -0
  84. data/lib/contracts-ruby2/spec/support.rb +10 -0
  85. data/lib/contracts-ruby2/spec/support_spec.rb +21 -0
  86. data/lib/contracts-ruby2/spec/validators_spec.rb +47 -0
  87. data/lib/contracts-ruby3/CHANGELOG.markdown +117 -0
  88. data/lib/contracts-ruby3/Gemfile +21 -0
  89. data/lib/contracts-ruby3/LICENSE +23 -0
  90. data/lib/contracts-ruby3/README.md +114 -0
  91. data/lib/contracts-ruby3/Rakefile +10 -0
  92. data/lib/contracts-ruby3/TODO.markdown +6 -0
  93. data/lib/contracts-ruby3/TUTORIAL.md +773 -0
  94. data/lib/contracts-ruby3/benchmarks/bench.rb +67 -0
  95. data/lib/contracts-ruby3/benchmarks/hash.rb +69 -0
  96. data/lib/contracts-ruby3/benchmarks/invariants.rb +91 -0
  97. data/lib/contracts-ruby3/benchmarks/io.rb +62 -0
  98. data/lib/contracts-ruby3/benchmarks/wrap_test.rb +57 -0
  99. data/lib/contracts-ruby3/contracts.gemspec +20 -0
  100. data/lib/contracts-ruby3/cucumber.yml +1 -0
  101. data/lib/contracts-ruby3/dependabot.yml +20 -0
  102. data/lib/contracts-ruby3/features/README.md +17 -0
  103. data/lib/contracts-ruby3/features/basics/functype.feature +71 -0
  104. data/lib/contracts-ruby3/features/basics/pretty-print.feature +241 -0
  105. data/lib/contracts-ruby3/features/basics/simple_example.feature +210 -0
  106. data/lib/contracts-ruby3/features/builtin_contracts/README.md +22 -0
  107. data/lib/contracts-ruby3/features/builtin_contracts/and.feature +103 -0
  108. data/lib/contracts-ruby3/features/builtin_contracts/any.feature +44 -0
  109. data/lib/contracts-ruby3/features/builtin_contracts/args.feature +80 -0
  110. data/lib/contracts-ruby3/features/builtin_contracts/array_of.feature +1 -0
  111. data/lib/contracts-ruby3/features/builtin_contracts/bool.feature +64 -0
  112. data/lib/contracts-ruby3/features/builtin_contracts/enum.feature +1 -0
  113. data/lib/contracts-ruby3/features/builtin_contracts/eq.feature +1 -0
  114. data/lib/contracts-ruby3/features/builtin_contracts/exactly.feature +1 -0
  115. data/lib/contracts-ruby3/features/builtin_contracts/func.feature +1 -0
  116. data/lib/contracts-ruby3/features/builtin_contracts/hash_of.feature +1 -0
  117. data/lib/contracts-ruby3/features/builtin_contracts/int.feature +93 -0
  118. data/lib/contracts-ruby3/features/builtin_contracts/keyword_args.feature +1 -0
  119. data/lib/contracts-ruby3/features/builtin_contracts/maybe.feature +1 -0
  120. data/lib/contracts-ruby3/features/builtin_contracts/nat.feature +115 -0
  121. data/lib/contracts-ruby3/features/builtin_contracts/nat_pos.feature +119 -0
  122. data/lib/contracts-ruby3/features/builtin_contracts/neg.feature +115 -0
  123. data/lib/contracts-ruby3/features/builtin_contracts/none.feature +145 -0
  124. data/lib/contracts-ruby3/features/builtin_contracts/not.feature +1 -0
  125. data/lib/contracts-ruby3/features/builtin_contracts/num.feature +64 -0
  126. data/lib/contracts-ruby3/features/builtin_contracts/or.feature +83 -0
  127. data/lib/contracts-ruby3/features/builtin_contracts/pos.feature +116 -0
  128. data/lib/contracts-ruby3/features/builtin_contracts/range_of.feature +1 -0
  129. data/lib/contracts-ruby3/features/builtin_contracts/respond_to.feature +78 -0
  130. data/lib/contracts-ruby3/features/builtin_contracts/send.feature +147 -0
  131. data/lib/contracts-ruby3/features/builtin_contracts/set_of.feature +1 -0
  132. data/lib/contracts-ruby3/features/builtin_contracts/xor.feature +99 -0
  133. data/lib/contracts-ruby3/features/support/env.rb +8 -0
  134. data/lib/contracts-ruby3/lib/contracts/attrs.rb +26 -0
  135. data/lib/contracts-ruby3/lib/contracts/builtin_contracts.rb +575 -0
  136. data/lib/contracts-ruby3/lib/contracts/call_with.rb +119 -0
  137. data/lib/contracts-ruby3/lib/contracts/core.rb +54 -0
  138. data/lib/contracts-ruby3/lib/contracts/decorators.rb +50 -0
  139. data/lib/contracts-ruby3/lib/contracts/engine/base.rb +137 -0
  140. data/lib/contracts-ruby3/lib/contracts/engine/eigenclass.rb +51 -0
  141. data/lib/contracts-ruby3/lib/contracts/engine/target.rb +72 -0
  142. data/lib/contracts-ruby3/lib/contracts/engine.rb +28 -0
  143. data/lib/contracts-ruby3/lib/contracts/errors.rb +74 -0
  144. data/lib/contracts-ruby3/lib/contracts/formatters.rb +140 -0
  145. data/lib/contracts-ruby3/lib/contracts/invariants.rb +72 -0
  146. data/lib/contracts-ruby3/lib/contracts/method_handler.rb +197 -0
  147. data/lib/contracts-ruby3/lib/contracts/method_reference.rb +102 -0
  148. data/lib/contracts-ruby3/lib/contracts/support.rb +63 -0
  149. data/lib/contracts-ruby3/lib/contracts/validators.rb +143 -0
  150. data/lib/contracts-ruby3/lib/contracts/version.rb +5 -0
  151. data/lib/contracts-ruby3/lib/contracts.rb +290 -0
  152. data/lib/contracts-ruby3/script/docs-release +3 -0
  153. data/lib/contracts-ruby3/script/docs-staging +3 -0
  154. data/lib/contracts-ruby3/script/rubocop.rb +5 -0
  155. data/lib/contracts-ruby3/spec/attrs_spec.rb +119 -0
  156. data/lib/contracts-ruby3/spec/builtin_contracts_spec.rb +457 -0
  157. data/lib/contracts-ruby3/spec/contracts_spec.rb +773 -0
  158. data/lib/contracts-ruby3/spec/fixtures/fixtures.rb +725 -0
  159. data/lib/contracts-ruby3/spec/invariants_spec.rb +17 -0
  160. data/lib/contracts-ruby3/spec/methods_spec.rb +54 -0
  161. data/lib/contracts-ruby3/spec/module_spec.rb +18 -0
  162. data/lib/contracts-ruby3/spec/override_validators_spec.rb +162 -0
  163. data/lib/contracts-ruby3/spec/ruby_version_specific/contracts_spec_1.9.rb +24 -0
  164. data/lib/contracts-ruby3/spec/ruby_version_specific/contracts_spec_2.0.rb +55 -0
  165. data/lib/contracts-ruby3/spec/ruby_version_specific/contracts_spec_2.1.rb +63 -0
  166. data/lib/contracts-ruby3/spec/spec_helper.rb +102 -0
  167. data/lib/contracts-ruby3/spec/support.rb +10 -0
  168. data/lib/contracts-ruby3/spec/support_spec.rb +21 -0
  169. data/lib/contracts-ruby3/spec/validators_spec.rb +47 -0
  170. data/lib/entitlements/data/groups/calculated/yaml.rb +7 -1
  171. data/lib/entitlements/data/people/yaml.rb +9 -1
  172. data/lib/entitlements/extras/ldap_group/rules/ldap_group.rb +5 -1
  173. data/lib/entitlements/extras/orgchart/person_methods.rb +7 -1
  174. data/lib/entitlements.rb +13 -2
  175. data/lib/ruby_version_check.rb +17 -0
  176. metadata +209 -14
@@ -0,0 +1,64 @@
1
+ Feature: Num
2
+
3
+ Checks that an argument is `Numeric`.
4
+
5
+ ```ruby
6
+ Contract C::Num => C::Num
7
+ ```
8
+
9
+ Background:
10
+ Given a file named "num_usage.rb" with:
11
+ """ruby
12
+ require "contracts"
13
+ C = Contracts
14
+
15
+ class Example
16
+ include Contracts::Core
17
+
18
+ Contract C::Num => C::Num
19
+ def increase(number)
20
+ number + 1
21
+ end
22
+ end
23
+ """
24
+
25
+ Scenario: Accepts integers
26
+ Given a file named "accepts_integers.rb" with:
27
+ """ruby
28
+ require "./num_usage"
29
+ puts Example.new.increase(7)
30
+ """
31
+ When I run `ruby accepts_integers.rb`
32
+ Then output should contain:
33
+ """
34
+ 8
35
+ """
36
+
37
+ Scenario: Accepts floats
38
+ Given a file named "accepts_floats.rb" with:
39
+ """ruby
40
+ require "./num_usage"
41
+ puts Example.new.increase(7.5)
42
+ """
43
+ When I run `ruby accepts_floats.rb`
44
+ Then output should contain:
45
+ """
46
+ 8.5
47
+ """
48
+
49
+ Scenario: Rejects other values
50
+ Given a file named "rejects_others.rb" with:
51
+ """ruby
52
+ require "./num_usage"
53
+ puts Example.new.increase("foo")
54
+ """
55
+ When I run `ruby rejects_others.rb`
56
+ Then output should contain:
57
+ """
58
+ : Contract violation for argument 1 of 1: (ParamContractError)
59
+ Expected: Num,
60
+ Actual: "foo"
61
+ Value guarded in: Example::increase
62
+ With Contract: Num => Num
63
+ """
64
+ And output should contain "num_usage.rb:8"
@@ -0,0 +1,83 @@
1
+ Feature: Or
2
+
3
+ Takes a variable number of contracts. The contract passes if any of the
4
+ contracts pass.
5
+
6
+ ```ruby
7
+ Contract C::Or[Float, C::Nat] => String
8
+ ```
9
+
10
+ This example will validate first argument of a method and accept either
11
+ `Float` or natural integer.
12
+
13
+ Background:
14
+ Given a file named "or_usage.rb" with:
15
+ """ruby
16
+ require "contracts"
17
+ C = Contracts
18
+
19
+ class Example
20
+ include Contracts::Core
21
+
22
+ Contract C::Or[Float, C::Nat] => String
23
+ def nat_string(number)
24
+ number.to_i.to_s
25
+ end
26
+ end
27
+ """
28
+
29
+ Scenario: Accepts float
30
+ Given a file named "accepts_float.rb" with:
31
+ """ruby
32
+ require "./or_usage"
33
+ puts Example.new.nat_string(3.7)
34
+ """
35
+ When I run `ruby accepts_float.rb`
36
+ Then output should contain:
37
+ """
38
+ 3
39
+ """
40
+
41
+ Scenario: Accepts natural
42
+ Given a file named "accepts_natural.rb" with:
43
+ """ruby
44
+ require "./or_usage"
45
+ puts Example.new.nat_string(7)
46
+ """
47
+ When I run `ruby accepts_natural.rb`
48
+ Then output should contain:
49
+ """
50
+ 7
51
+ """
52
+
53
+ Scenario: Rejects negative integer
54
+ Given a file named "rejects_negative_integer.rb" with:
55
+ """ruby
56
+ require "./or_usage"
57
+ puts Example.new.nat_string(-3)
58
+ """
59
+ When I run `ruby rejects_negative_integer.rb`
60
+ Then output should contain:
61
+ """
62
+ : Contract violation for argument 1 of 1: (ParamContractError)
63
+ Expected: (Float or Nat),
64
+ Actual: -3
65
+ Value guarded in: Example::nat_string
66
+ With Contract: Or => String
67
+ """
68
+
69
+ Scenario: Rejects other values
70
+ Given a file named "rejects_other.rb" with:
71
+ """ruby
72
+ require "./or_usage"
73
+ puts Example.new.nat_string(nil)
74
+ """
75
+ When I run `ruby rejects_other.rb`
76
+ Then output should contain:
77
+ """
78
+ : Contract violation for argument 1 of 1: (ParamContractError)
79
+ Expected: (Float or Nat),
80
+ Actual: nil
81
+ Value guarded in: Example::nat_string
82
+ With Contract: Or => String
83
+ """
@@ -0,0 +1,116 @@
1
+ Feature: Pos
2
+
3
+ Checks that an argument is positive `Numeric`.
4
+
5
+ ```ruby
6
+ Contract C::Pos => C::Pos
7
+ ```
8
+
9
+ Background:
10
+ Given a file named "pos_usage.rb" with:
11
+ """ruby
12
+ require "contracts"
13
+ C = Contracts
14
+
15
+ class Example
16
+ include Contracts::Core
17
+
18
+ Contract C::Pos, C::Pos => C::Pos
19
+ def power(number, power)
20
+ return number if power <= 1
21
+ number * self.power(number, power - 1)
22
+ end
23
+ end
24
+ """
25
+
26
+ Scenario: Accepts positive integers
27
+ Given a file named "accepts_positive_integers.rb" with:
28
+ """ruby
29
+ require "./pos_usage"
30
+ puts Example.new.power(3, 4)
31
+ """
32
+ When I run `ruby accepts_positive_integers.rb`
33
+ Then output should contain:
34
+ """
35
+ 81
36
+ """
37
+
38
+ Scenario: Accepts positive floats
39
+ Given a file named "accepts_positive_floats.rb" with:
40
+ """ruby
41
+ require "./pos_usage"
42
+ puts Example.new.power(3.7, 4.5)
43
+ """
44
+ When I run `ruby accepts_positive_floats.rb`
45
+ Then output should contain:
46
+ """
47
+ 693.4395
48
+ """
49
+
50
+ Scenario: Rejects negative integers
51
+ Given a file named "rejects_negative_integers.rb" with:
52
+ """ruby
53
+ require "./pos_usage"
54
+ puts Example.new.power(3, -4)
55
+ """
56
+ When I run `ruby rejects_negative_integers.rb`
57
+ Then output should contain:
58
+ """
59
+ : Contract violation for argument 2 of 2: (ParamContractError)
60
+ Expected: Pos,
61
+ Actual: -4
62
+ Value guarded in: Example::power
63
+ With Contract: Pos, Pos => Pos
64
+ """
65
+ And output should contain "pos_usage.rb:8"
66
+
67
+ Scenario: Rejects negative floats
68
+ Given a file named "rejects_negative_floats.rb" with:
69
+ """ruby
70
+ require "./pos_usage"
71
+ puts Example.new.power(3.7, -4.4)
72
+ """
73
+ When I run `ruby rejects_negative_floats.rb`
74
+ Then output should contain:
75
+ """
76
+ : Contract violation for argument 2 of 2: (ParamContractError)
77
+ Expected: Pos,
78
+ Actual: -4.4
79
+ Value guarded in: Example::power
80
+ With Contract: Pos, Pos => Pos
81
+ """
82
+ And output should contain "pos_usage.rb:8"
83
+
84
+ Scenario: Rejects zero
85
+ Given a file named "rejects_zero.rb" with:
86
+ """ruby
87
+ require "./pos_usage"
88
+ puts Example.new.power(3, 0)
89
+ """
90
+ When I run `ruby rejects_zero.rb`
91
+ Then output should contain:
92
+ """
93
+ : Contract violation for argument 2 of 2: (ParamContractError)
94
+ Expected: Pos,
95
+ Actual: 0
96
+ Value guarded in: Example::power
97
+ With Contract: Pos, Pos => Pos
98
+ """
99
+ And output should contain "pos_usage.rb:8"
100
+
101
+ Scenario: Rejects other values
102
+ Given a file named "rejects_others.rb" with:
103
+ """ruby
104
+ require "./pos_usage"
105
+ puts Example.new.power("foo", 2)
106
+ """
107
+ When I run `ruby rejects_others.rb`
108
+ Then output should contain:
109
+ """
110
+ : Contract violation for argument 1 of 2: (ParamContractError)
111
+ Expected: Pos,
112
+ Actual: "foo"
113
+ Value guarded in: Example::power
114
+ With Contract: Pos, Pos => Pos
115
+ """
116
+ And output should contain "pos_usage.rb:8"
@@ -0,0 +1 @@
1
+ Feature: RangeOf (TODO)
@@ -0,0 +1,78 @@
1
+ Feature: RespondTo
2
+
3
+ Takes a variable number of method names as symbols. The contract passes if
4
+ the argument responds to all of those methods.
5
+
6
+ ```ruby
7
+ Contract C::RespondTo[:email, :password, :confirmation] => C::Bool
8
+ ```
9
+
10
+ This contract will pass only for objects that `respond_to?` `:email`,
11
+ `:password` and `:confirmation`.
12
+
13
+ Background:
14
+ Given a file named "signup_validator.rb" with:
15
+ """ruby
16
+ require "contracts"
17
+ C = Contracts
18
+
19
+ class SignupValidator
20
+ include Contracts::Core
21
+
22
+ Contract C::RespondTo[:email, :password, :confirmation] => C::Bool
23
+ def valid?(signup)
24
+ !!signup.email.match("@") &&
25
+ signup.password.length > 6 &&
26
+ signup.password == signup.confirmation
27
+ end
28
+ end
29
+ """
30
+
31
+ Given a file named "signup.rb" with:
32
+ """ruby
33
+ Signup = Struct.new(:email, :password, :confirmation)
34
+ """
35
+
36
+ Given a file named "signin.rb" with:
37
+ """ruby
38
+ Signin = Struct.new(:email, :password)
39
+ """
40
+
41
+ Given a file named "helper.rb" with:
42
+ """ruby
43
+ require "./signup_validator"
44
+ require "./signup"
45
+ require "./signin"
46
+ """
47
+
48
+ Scenario: Accepts correct object
49
+ Given a file named "correct.rb" with:
50
+ """ruby
51
+ require "./helper"
52
+
53
+ puts SignupValidator.new.valid?(Signup["john@example.org", "welcome", "welcome"])
54
+ puts SignupValidator.new.valid?(Signup["john@example.org", "welcome", "welcomr"])
55
+ """
56
+ When I run `ruby correct.rb`
57
+ Then output should contain:
58
+ """
59
+ true
60
+ false
61
+ """
62
+
63
+ Scenario: Rejects incorrect object
64
+ Given a file named "incorrect.rb" with:
65
+ """ruby
66
+ require "./helper"
67
+
68
+ puts SignupValidator.new.valid?(Signin["john@example.org", "welcome"])
69
+ """
70
+ When I run `ruby incorrect.rb`
71
+ Then output should contain:
72
+ """
73
+ : Contract violation for argument 1 of 1: (ParamContractError)
74
+ Expected: (a value that responds to [:email, :password, :confirmation]),
75
+ Actual: #<struct Signin email="john@example.org", password="welcome">
76
+ Value guarded in: SignupValidator::valid?
77
+ With Contract: RespondTo => Bool
78
+ """
@@ -0,0 +1,147 @@
1
+ Feature: Send
2
+
3
+ Takes a variable number of method names as symbols. Given an argument, all of
4
+ those methods are called on the argument one by one. If they all return true,
5
+ the contract passes.
6
+
7
+ ```ruby
8
+ Contract C::Send[:valid?, :has_items?] => C::ArrayOf[Item]
9
+ ```
10
+
11
+ This contract will pass only if:
12
+ `arg.valid? == true && arg.has_items? == true`,
13
+ where `arg` is the first argument.
14
+
15
+ Background:
16
+ Given a file named "item.rb" with:
17
+ """ruby
18
+ Item = Struct.new(:name, :cost)
19
+ Item::DEFAULT = Item["default", 0]
20
+ """
21
+
22
+ Given a file named "send_usage.rb" with:
23
+ """ruby
24
+ require "contracts"
25
+ C = Contracts
26
+ require "./item"
27
+
28
+ class FetchItemCommand
29
+ include Contracts::Core
30
+
31
+ Contract C::Send[:valid?, :has_items?] => C::ArrayOf[Item]
32
+ def call(subject)
33
+ ([Item::DEFAULT] + subject.items).uniq
34
+ end
35
+ end
36
+ """
37
+
38
+ Scenario: All methods return `true`
39
+ Given a file named "box.rb" with:
40
+ """ruby
41
+ class Box
42
+ def valid?
43
+ true
44
+ end
45
+
46
+ def has_items?
47
+ true
48
+ end
49
+
50
+ def items
51
+ [Item["cat", 599.99]]
52
+ end
53
+ end
54
+
55
+ require "./send_usage"
56
+ p FetchItemCommand.new.call(Box.new)
57
+ """
58
+ When I run `ruby box.rb`
59
+ Then output should contain:
60
+ """
61
+ [#<struct Item name="default", cost=0>, #<struct Item name="cat", cost=599.99>]
62
+ """
63
+
64
+ Scenario: When second method returns `false`
65
+ Given a file named "cat.rb" with:
66
+ """ruby
67
+ class Cat
68
+ def valid?
69
+ true
70
+ end
71
+
72
+ def has_items?
73
+ false
74
+ end
75
+ end
76
+
77
+ require "./send_usage"
78
+ p FetchItemCommand.new.call(Cat.new)
79
+ """
80
+ When I run `ruby cat.rb`
81
+ Then output should contain:
82
+ """
83
+ : Contract violation for argument 1 of 1: (ParamContractError)
84
+ Expected: (a value that returns true for all of [:valid?, :has_items?]),
85
+ """
86
+ And output should contain:
87
+ """
88
+ Actual: #<Cat
89
+ """
90
+
91
+ Scenario: When first method returns `false`
92
+ Given a file named "invalid.rb" with:
93
+ """ruby
94
+ class Invalid
95
+ def valid?
96
+ false
97
+ end
98
+
99
+ def has_items?
100
+ true
101
+ end
102
+
103
+ def items
104
+ []
105
+ end
106
+ end
107
+
108
+ require "./send_usage"
109
+ p FetchItemCommand.new.call(Invalid.new)
110
+ """
111
+ When I run `ruby invalid.rb`
112
+ Then output should contain:
113
+ """
114
+ : Contract violation for argument 1 of 1: (ParamContractError)
115
+ Expected: (a value that returns true for all of [:valid?, :has_items?]),
116
+ """
117
+ And output should contain:
118
+ """
119
+ Actual: #<Invalid
120
+ """
121
+
122
+ Scenario: When all methods return `false`
123
+ Given a file named "nothing.rb" with:
124
+ """ruby
125
+ class Nothing
126
+ def valid?
127
+ false
128
+ end
129
+
130
+ def has_items?
131
+ false
132
+ end
133
+ end
134
+
135
+ require "./send_usage"
136
+ p FetchItemCommand.new.call(Nothing.new)
137
+ """
138
+ When I run `ruby nothing.rb`
139
+ Then output should contain:
140
+ """
141
+ : Contract violation for argument 1 of 1: (ParamContractError)
142
+ Expected: (a value that returns true for all of [:valid?, :has_items?]),
143
+ """
144
+ And output should contain:
145
+ """
146
+ Actual: #<Nothing
147
+ """
@@ -0,0 +1 @@
1
+ Feature: SetOf (TODO)
@@ -0,0 +1,99 @@
1
+ Feature: Xor
2
+
3
+ Takes a variable number of contracts. The contract passes if one and only one
4
+ of the contracts pass.
5
+
6
+ ```ruby
7
+ Contract C::Xor[Float, C::Neg] => String
8
+ ```
9
+
10
+ This example will validate first argument of a method and accept either
11
+ `Float` or natural integer, but not both.
12
+
13
+ Background:
14
+ Given a file named "xor_usage.rb" with:
15
+ """ruby
16
+ require "contracts"
17
+ C = Contracts
18
+
19
+ class Example
20
+ include Contracts::Core
21
+
22
+ Contract C::Xor[Float, C::Neg] => String
23
+ def strange_number(number)
24
+ number.to_i.to_s
25
+ end
26
+ end
27
+ """
28
+
29
+ Scenario: Accepts float
30
+ Given a file named "accepts_float.rb" with:
31
+ """ruby
32
+ require "./xor_usage"
33
+ puts Example.new.strange_number(3.7)
34
+ """
35
+ When I run `ruby accepts_float.rb`
36
+ Then output should contain:
37
+ """
38
+ 3
39
+ """
40
+
41
+ Scenario: Accepts negative integer
42
+ Given a file named "accepts_negative_integer.rb" with:
43
+ """ruby
44
+ require "./xor_usage"
45
+ puts Example.new.strange_number(-7)
46
+ """
47
+ When I run `ruby accepts_negative_integer.rb`
48
+ Then output should contain:
49
+ """
50
+ -7
51
+ """
52
+
53
+ Scenario: Rejects negative float
54
+ Given a file named "rejects_negative_float.rb" with:
55
+ """ruby
56
+ require "./xor_usage"
57
+ puts Example.new.strange_number(-3.5)
58
+ """
59
+ When I run `ruby rejects_negative_float.rb`
60
+ Then output should contain:
61
+ """
62
+ : Contract violation for argument 1 of 1: (ParamContractError)
63
+ Expected: (Float xor Neg),
64
+ Actual: -3.5
65
+ Value guarded in: Example::strange_number
66
+ With Contract: Xor => String
67
+ """
68
+
69
+ Scenario: Rejects positive integer
70
+ Given a file named "rejects_positive_integer.rb" with:
71
+ """ruby
72
+ require "./xor_usage"
73
+ puts Example.new.strange_number(9)
74
+ """
75
+ When I run `ruby rejects_positive_integer.rb`
76
+ Then output should contain:
77
+ """
78
+ : Contract violation for argument 1 of 1: (ParamContractError)
79
+ Expected: (Float xor Neg),
80
+ Actual: 9
81
+ Value guarded in: Example::strange_number
82
+ With Contract: Xor => String
83
+ """
84
+
85
+ Scenario: Rejects other values
86
+ Given a file named "rejects_other.rb" with:
87
+ """ruby
88
+ require "./xor_usage"
89
+ puts Example.new.strange_number(:foo)
90
+ """
91
+ When I run `ruby rejects_other.rb`
92
+ Then output should contain:
93
+ """
94
+ : Contract violation for argument 1 of 1: (ParamContractError)
95
+ Expected: (Float xor Neg),
96
+ Actual: :foo
97
+ Value guarded in: Example::strange_number
98
+ With Contract: Xor => String
99
+ """
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "aruba/cucumber"
4
+ require "aruba/jruby" if RUBY_PLATFORM == "java"
5
+
6
+ Before do
7
+ @aruba_timeout_seconds = RUBY_PLATFORM == "java" ? 30 : 5
8
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Contracts
4
+ module Attrs
5
+ def attr_reader_with_contract(*names, contract)
6
+ names.each do |name|
7
+ Contract Contracts::None => contract
8
+ attr_reader(name)
9
+ end
10
+ end
11
+
12
+ def attr_writer_with_contract(*names, contract)
13
+ names.each do |name|
14
+ Contract contract => contract
15
+ attr_writer(name)
16
+ end
17
+ end
18
+
19
+ def attr_accessor_with_contract(*names, contract)
20
+ attr_reader_with_contract(*names, contract)
21
+ attr_writer_with_contract(*names, contract)
22
+ end
23
+ end
24
+
25
+ include Attrs
26
+ end