axiom-types 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/.rspec +1 -0
  2. data/.travis.yml +11 -16
  3. data/Gemfile +5 -2
  4. data/Gemfile.devtools +19 -24
  5. data/Guardfile +18 -10
  6. data/README.md +5 -28
  7. data/axiom-types.gemspec +2 -3
  8. data/config/flay.yml +2 -2
  9. data/config/flog.yml +1 -1
  10. data/config/reek.yml +15 -13
  11. data/config/rubocop.yml +62 -0
  12. data/lib/axiom/types.rb +5 -3
  13. data/lib/axiom/types/boolean.rb +4 -2
  14. data/lib/axiom/types/collection.rb +5 -2
  15. data/lib/axiom/types/encodable.rb +1 -1
  16. data/lib/axiom/types/float.rb +3 -0
  17. data/lib/axiom/types/hash.rb +8 -3
  18. data/lib/axiom/types/length_comparable.rb +7 -4
  19. data/lib/axiom/types/numeric.rb +5 -0
  20. data/lib/axiom/types/object.rb +2 -2
  21. data/lib/axiom/types/support/infinity.rb +116 -0
  22. data/lib/axiom/types/support/options.rb +9 -18
  23. data/lib/axiom/types/time.rb +2 -2
  24. data/lib/axiom/types/type.rb +13 -9
  25. data/lib/axiom/types/value_comparable.rb +5 -2
  26. data/lib/axiom/types/version.rb +1 -1
  27. data/spec/unit/axiom/types/boolean/class_methods/infer_spec.rb +6 -0
  28. data/spec/unit/axiom/types/collection/class_methods/finalize_spec.rb +3 -3
  29. data/spec/unit/axiom/types/encodable/class_methods/extended_spec.rb +8 -7
  30. data/spec/unit/axiom/types/encodable/finalize_spec.rb +30 -8
  31. data/spec/unit/axiom/types/hash/class_methods/infer_spec.rb +17 -17
  32. data/spec/unit/axiom/types/infinity/class_methods/coerce_spec.rb +64 -0
  33. data/spec/unit/axiom/types/infinity/class_methods/spaceship_operator_spec.rb +67 -0
  34. data/spec/unit/axiom/types/infinity/class_methods/succ_spec.rb +11 -0
  35. data/spec/unit/axiom/types/length_comparable/class_methods/extended_spec.rb +17 -8
  36. data/spec/unit/axiom/types/negative_infinity/class_methods/spaceship_operator_spec.rb +67 -0
  37. data/spec/unit/axiom/types/object/class_methods/coercion_method_spec.rb +2 -2
  38. data/spec/unit/axiom/types/object/class_methods/infer_spec.rb +13 -1
  39. data/spec/unit/axiom/types/object/class_methods/primitive_spec.rb +4 -4
  40. data/spec/unit/axiom/types/options/accept_options_spec.rb +12 -4
  41. data/spec/unit/axiom/types/options/inherited_spec.rb +10 -36
  42. data/spec/unit/axiom/types/type/class_methods/constraint_spec.rb +6 -11
  43. data/spec/unit/axiom/types/type/class_methods/include_predicate_spec.rb +7 -7
  44. data/spec/unit/axiom/types/type/class_methods/includes_spec.rb +2 -2
  45. data/spec/unit/axiom/types/value_comparable/class_methods/extended_spec.rb +17 -8
  46. metadata +29 -31
  47. checksums.yaml +0 -7
@@ -2,27 +2,28 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Axiom::Types::Encodable, '.extended', :if => RUBY_VERSION >= '1.9' do
5
+ describe Axiom::Types::Encodable, '.extended' do
6
6
  subject { object.extend(described_class) }
7
7
 
8
8
  let(:object) { Class.new(Axiom::Types::Type) }
9
9
 
10
10
  it 'delegates to the ancestor' do
11
11
  # RSpec will reset stubbed methods after the example. A normal expectation
12
- # causes a SystemStackError to be thrown, so we stub it first so that RSpec
13
- # tracks the original method (if any), then we add our own stub that
14
- # actually works, and finally when the example finishes RSpec will reset the
15
- # Module#extended method back to it's original state.
12
+ # causes a SystemStackError to be thrown, so we stub it first so that
13
+ # RSpec tracks the original method (if any), then we add our own stub that
14
+ # actually works, and finally when the example finishes RSpec will reset
15
+ # the Module#extended method back to it's original state.
16
16
  Module.any_instance.stub(:extended).with(object)
17
17
 
18
18
  delegated_ancestor = false
19
+ Module.send(:undef_method, :extended)
19
20
  Module.send(:define_method, :extended) { |_| delegated_ancestor = true }
20
21
  expect { subject }.to change { delegated_ancestor }.from(false).to(true)
21
22
  end
22
23
 
23
24
  it 'adds encoding method' do
24
- expect { subject }.to change { object.respond_to?(:encoding) }.
25
- from(false).to(true)
25
+ expect { subject }.to change { object.respond_to?(:encoding) }
26
+ .from(false).to(true)
26
27
  end
27
28
 
28
29
  it 'sets the encoding default to UTF-8' do
@@ -2,11 +2,19 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Axiom::Types::Encodable, '#finalize', :if => RUBY_VERSION >= '1.9' do
5
+ describe Axiom::Types::Encodable, '#finalize' do
6
6
  subject { object.finalize }
7
7
 
8
8
  let(:object) { Class.new(Axiom::Types::Type).extend(described_class) }
9
9
 
10
+ # Test if Symbol encoding is supported
11
+ let(:symbol_encoding) do
12
+ ! RUBY_PLATFORM.include?('java') && begin
13
+ encoding = Encoding::UTF_32BE
14
+ ''.force_encoding(encoding).to_sym.encoding.equal?(encoding)
15
+ end
16
+ end
17
+
10
18
  context 'when an ascii compatible encoding (UTF-8) is used' do
11
19
  it_should_behave_like 'a command method'
12
20
  it_should_behave_like 'an idempotent method'
@@ -15,14 +23,24 @@ describe Axiom::Types::Encodable, '#finalize', :if => RUBY_VERSION >= '1.9' do
15
23
 
16
24
  its(:constraint) { should be_frozen }
17
25
 
18
- defined?(::Encoding) && Encoding.list.each do |encoding|
19
- if encoding.ascii_compatible?
26
+ Encoding.list.each do |encoding|
27
+ if encoding.equal?(Encoding::UTF_8)
28
+ string = '𝒜wesome'.force_encoding(encoding)
29
+ it "adds a constraint that returns true for #{encoding} encoding" do
30
+ should include(string)
31
+ should include(string.to_sym) if symbol_encoding
32
+ end
33
+ elsif encoding.ascii_compatible?
34
+ string = ''.force_encoding(encoding)
20
35
  it "adds a constraint that returns true for #{encoding} encoding" do
21
- should include(''.force_encoding(encoding))
36
+ should include(string)
37
+ should include(string.to_sym) if symbol_encoding
22
38
  end
23
39
  else
40
+ string = ''.force_encoding(encoding)
24
41
  it "adds a constraint that returns false for #{encoding} encoding" do
25
- should_not include(''.force_encoding(encoding))
42
+ should_not include(string)
43
+ should_not include(string.to_sym) if symbol_encoding
26
44
  end
27
45
  end
28
46
  end
@@ -40,14 +58,18 @@ describe Axiom::Types::Encodable, '#finalize', :if => RUBY_VERSION >= '1.9' do
40
58
 
41
59
  its(:constraint) { should be_frozen }
42
60
 
43
- defined?(::Encoding) && Encoding.list.each do |encoding|
61
+ Encoding.list.each do |encoding|
44
62
  if encoding.equal?(Encoding::UTF_16BE)
63
+ string = '𝒜wesome'.force_encoding(encoding)
45
64
  it "adds a constraint that returns true for #{encoding} encoding" do
46
- should include(''.force_encoding(encoding))
65
+ should include(string)
66
+ should include(string.to_sym) if symbol_encoding
47
67
  end
48
68
  else
69
+ string = ''.force_encoding(encoding)
49
70
  it "adds a constraint that returns false for #{encoding} encoding" do
50
- should_not include(''.force_encoding(encoding))
71
+ should_not include(string)
72
+ should_not include(string.to_sym) if symbol_encoding
51
73
  end
52
74
  end
53
75
  end
@@ -12,25 +12,25 @@ describe Axiom::Types::Hash, '.infer' do
12
12
  context 'with Axiom::Types::Hash' do
13
13
  let(:object) { described_class }
14
14
 
15
- context 'when the argument is the type object' do
15
+ context 'with a type object' do
16
16
  let(:arg) { object }
17
17
 
18
18
  it { should be(object) }
19
19
  end
20
20
 
21
- context 'when the argument is ::Hash' do
21
+ context 'with a ::Hash' do
22
22
  let(:arg) { ::Hash }
23
23
 
24
24
  it { should be(object) }
25
25
  end
26
26
 
27
- context 'when the argument is an empty Hash' do
27
+ context 'with an empty Hash' do
28
28
  let(:arg) { ::Hash[] }
29
29
 
30
30
  it { should be(object) }
31
31
  end
32
32
 
33
- context 'when the argument is an Hash with a key type and nil value' do
33
+ context 'with an Hash with a key type and nil value' do
34
34
  let(:arg) { ::Hash[object => nil] }
35
35
 
36
36
  its(:ancestors) { should include(object) }
@@ -42,7 +42,7 @@ describe Axiom::Types::Hash, '.infer' do
42
42
  its(:value_type) { should be(Axiom::Types::Object) }
43
43
  end
44
44
 
45
- context 'when the argument is an Hash with a nil key and value type' do
45
+ context 'with an Hash with a nil key and value type' do
46
46
  let(:arg) { ::Hash[nil => object] }
47
47
 
48
48
  its(:ancestors) { should include(object) }
@@ -54,7 +54,7 @@ describe Axiom::Types::Hash, '.infer' do
54
54
  its(:value_type) { should be(object) }
55
55
  end
56
56
 
57
- context 'when the argument is an Hash with key and value types' do
57
+ context 'with an Hash with key and value types' do
58
58
  let(:arg) { ::Hash[object => object] }
59
59
 
60
60
  its(:ancestors) { should include(object) }
@@ -66,7 +66,7 @@ describe Axiom::Types::Hash, '.infer' do
66
66
  its(:value_type) { should be(object) }
67
67
  end
68
68
 
69
- context 'when the argument is an Hash with a key primitive and nil value' do
69
+ context 'with an Hash with a key primitive and nil value' do
70
70
  let(:arg) { ::Hash[::Hash => nil] }
71
71
 
72
72
  its(:ancestors) { should include(object) }
@@ -78,7 +78,7 @@ describe Axiom::Types::Hash, '.infer' do
78
78
  its(:value_type) { should be(Axiom::Types::Object) }
79
79
  end
80
80
 
81
- context 'when the argument is an Hash with a nil key and value primitive' do
81
+ context 'with an Hash with a nil key and value primitive' do
82
82
  let(:arg) { ::Hash[nil => ::Hash] }
83
83
 
84
84
  its(:ancestors) { should include(object) }
@@ -90,7 +90,7 @@ describe Axiom::Types::Hash, '.infer' do
90
90
  its(:value_type) { should be(object) }
91
91
  end
92
92
 
93
- context 'when the argument is an Hash with key and value primitives' do
93
+ context 'with an Hash with key and value primitives' do
94
94
  let(:arg) { ::Hash[::Hash => ::Hash] }
95
95
 
96
96
  its(:ancestors) { should include(object) }
@@ -124,49 +124,49 @@ describe Axiom::Types::Hash, '.infer' do
124
124
  it { should be(object) }
125
125
  end
126
126
 
127
- context 'when the argument is an empty Hash' do
127
+ context 'with an empty Hash' do
128
128
  let(:arg) { ::Hash[] }
129
129
 
130
130
  it { should be(object) }
131
131
  end
132
132
 
133
- context 'when the argument is an Hash with a key type and nil value' do
133
+ context 'with an Hash with a key type and nil value' do
134
134
  let(:arg) { ::Hash[object => nil] }
135
135
 
136
136
  it { should be_nil }
137
137
  end
138
138
 
139
- context 'when the argument is an Hash with a nil key and value type' do
139
+ context 'with an Hash with a nil key and value type' do
140
140
  let(:arg) { ::Hash[nil => object] }
141
141
 
142
142
  it { should be_nil }
143
143
  end
144
144
 
145
- context 'when the argument is an Hash with key and value types' do
145
+ context 'with an Hash with key and value types' do
146
146
  let(:arg) { ::Hash[object => object] }
147
147
 
148
148
  it { should be_nil }
149
149
  end
150
150
 
151
- context 'when the argument is an Hash with a key primitive and nil value' do
151
+ context 'with an Hash with a key primitive and nil value' do
152
152
  let(:arg) { ::Hash[::Hash => nil] }
153
153
 
154
154
  it { should be_nil }
155
155
  end
156
156
 
157
- context 'when the argument is an Hash with a nil key and value primitive' do
157
+ context 'with an Hash with a nil key and value primitive' do
158
158
  let(:arg) { ::Hash[nil => ::Hash] }
159
159
 
160
160
  it { should be_nil }
161
161
  end
162
162
 
163
- context 'when the argument is an Hash with key and value primitives' do
163
+ context 'with an Hash with key and value primitives' do
164
164
  let(:arg) { ::Hash[::Hash => ::Hash] }
165
165
 
166
166
  it { should be_nil }
167
167
  end
168
168
 
169
- context 'when the argument is nil' do
169
+ context 'with a nil' do
170
170
  let(:arg) { nil }
171
171
 
172
172
  it { should be_nil }
@@ -0,0 +1,64 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Axiom::Types::Infinity, '.coerce' do
6
+ subject { object.coerce(other) }
7
+
8
+ let(:object) { described_class }
9
+
10
+ [
11
+ 1, # Fixnum
12
+ 2**63, # Bignum
13
+ 1.0, # Float
14
+ Rational(1, 1), # Rational
15
+ BigDecimal('1'), # BigDecimal
16
+ ].each do |number|
17
+ context "when other is a #{number.class}" do
18
+ let(:other) { number }
19
+
20
+ it 'coerces into an array containing inverse and self' do
21
+ should eql([Axiom::Types::NegativeInfinity, object])
22
+ end
23
+
24
+ it 'coerces when comparing' do
25
+ expect(other).to be < object
26
+ expect(other).to_not be == object
27
+ end
28
+ end
29
+ end
30
+
31
+ context 'when other is a Float::INFINITY' do
32
+ let(:other) { Float::INFINITY }
33
+
34
+ it 'coerces into an array containing inverse and self' do
35
+ should eql([Axiom::Types::Infinity, object])
36
+ end
37
+
38
+ it 'coerces when comparing' do
39
+ expect(other).to_not be < object
40
+ expect(other).to be == object
41
+ end
42
+ end
43
+
44
+ context 'when other is a -Float::INFINITY' do
45
+ let(:other) { -Float::INFINITY }
46
+
47
+ it 'coerces into an array containing inverse and self' do
48
+ should eql([Axiom::Types::NegativeInfinity, object])
49
+ end
50
+
51
+ it 'coerces when comparing' do
52
+ expect(other).to be < object
53
+ expect(other).to_not be == object
54
+ end
55
+ end
56
+
57
+ context 'when other is not a number' do
58
+ let(:other) { 'string' }
59
+
60
+ specify do
61
+ expect { subject }.to raise_error(TypeError, 'String cannot be coerced')
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,67 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Axiom::Types::Infinity, '.<=>' do
6
+ subject { object <=> other }
7
+
8
+ let(:object) { described_class }
9
+
10
+ [
11
+ 1, # Fixnum
12
+ 2**63, # Bignum
13
+ 1.0, # Float
14
+ Rational(1, 1), # Rational
15
+ BigDecimal('1'), # BigDecimal
16
+ ].each do |number|
17
+ context "when other object is a #{number.class}" do
18
+ let(:other) { number }
19
+
20
+ it { should be(1) }
21
+
22
+ it 'is symmetric' do
23
+ should be(-(other <=> object))
24
+ end
25
+ end
26
+ end
27
+
28
+ context 'when the other object is negative infinity' do
29
+ let(:other) { Axiom::Types::NegativeInfinity }
30
+
31
+ it { should be(1) }
32
+
33
+ it 'is symmetric' do
34
+ should be(-(other <=> object))
35
+ end
36
+ end
37
+
38
+ context 'when the other object is infinity' do
39
+ let(:other) { object }
40
+
41
+ it { should be(0) }
42
+
43
+ it 'is symmetric' do
44
+ should be(-(other <=> object))
45
+ end
46
+ end
47
+
48
+ context 'when the other object is Float::INFINITY' do
49
+ let(:other) { Float::INFINITY }
50
+
51
+ it { should be(0) }
52
+
53
+ it 'is symmetric' do
54
+ should be(-(other <=> object))
55
+ end
56
+ end
57
+
58
+ context 'when the other object is not comparable' do
59
+ let(:other) { 'string' }
60
+
61
+ it { should be_nil }
62
+
63
+ it 'is symmetric' do
64
+ should be(other <=> object)
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Axiom::Types::Infinity, '.succ' do
6
+ subject { object.succ }
7
+
8
+ let(:object) { described_class }
9
+
10
+ it { should be(object) }
11
+ end
@@ -9,24 +9,33 @@ describe Axiom::Types::LengthComparable, '.extended' do
9
9
 
10
10
  it 'delegates to the ancestor' do
11
11
  # RSpec will reset stubbed methods after the example. A normal expectation
12
- # causes a SystemStackError to be thrown, so we stub it first so that RSpec
13
- # tracks the original method (if any), then we add our own stub that
14
- # actually works, and finally when the example finishes RSpec will reset the
15
- # Module#extended method back to it's original state.
12
+ # causes a SystemStackError to be thrown, so we stub it first so that
13
+ # RSpec tracks the original method (if any), then we add our own stub that
14
+ # actually works, and finally when the example finishes RSpec will reset
15
+ # the Module#extended method back to it's original state.
16
16
  Module.any_instance.stub(:extended).with(object)
17
17
 
18
18
  delegated_ancestor = false
19
+ Module.send(:undef_method, :extended)
19
20
  Module.send(:define_method, :extended) { |_| delegated_ancestor = true }
20
21
  expect { subject }.to change { delegated_ancestor }.from(false).to(true)
21
22
  end
22
23
 
23
24
  it 'adds minimum_length method' do
24
- expect { subject }.to change { object.respond_to?(:minimum_length) }.
25
- from(false).to(true)
25
+ expect { subject }.to change { object.respond_to?(:minimum_length) }
26
+ .from(false).to(true)
26
27
  end
27
28
 
28
29
  it 'adds maxumum_length method' do
29
- expect { subject }.to change { object.respond_to?(:maximum_length) }.
30
- from(false).to(true)
30
+ expect { subject }.to change { object.respond_to?(:maximum_length) }
31
+ .from(false).to(true)
32
+ end
33
+
34
+ it 'sets the default minimum_length' do
35
+ expect(subject.minimum_length).to equal(Axiom::Types::Infinity)
36
+ end
37
+
38
+ it 'sets the default maximum_length' do
39
+ expect(subject.maximum_length).to equal(Axiom::Types::NegativeInfinity)
31
40
  end
32
41
  end
@@ -0,0 +1,67 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Axiom::Types::NegativeInfinity, '.<=>' do
6
+ subject { object <=> other }
7
+
8
+ let(:object) { described_class }
9
+
10
+ [
11
+ 1, # Fixnum
12
+ 2**63, # Bignum
13
+ 1.0, # Float
14
+ Rational(1, 1), # Rational
15
+ BigDecimal('1'), # BigDecimal
16
+ ].each do |number|
17
+ context "when other object is a #{number.class}" do
18
+ let(:other) { number }
19
+
20
+ it { should be(-1) }
21
+
22
+ it 'is symmetric' do
23
+ should be(-(other <=> object))
24
+ end
25
+ end
26
+ end
27
+
28
+ context 'when the other object is infinity' do
29
+ let(:other) { Axiom::Types::Infinity }
30
+
31
+ it { should be(-1) }
32
+
33
+ it 'is symmetric' do
34
+ should be(-(other <=> object))
35
+ end
36
+ end
37
+
38
+ context 'when the other object is negative infinity' do
39
+ let(:other) { object }
40
+
41
+ it { should be(0) }
42
+
43
+ it 'is symmetric' do
44
+ should be(other <=> object)
45
+ end
46
+ end
47
+
48
+ context 'when the other object is -Float::INFINITY' do
49
+ let(:other) { -Float::INFINITY }
50
+
51
+ it { should be(0) }
52
+
53
+ it 'is symmetric' do
54
+ should be(other <=> object)
55
+ end
56
+ end
57
+
58
+ context 'when the other object is not comparable' do
59
+ let(:other) { 'string' }
60
+
61
+ it { should be_nil }
62
+
63
+ it 'is symmetric' do
64
+ should be(other <=> object)
65
+ end
66
+ end
67
+ end