sinclair 1.6.5 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +2 -2
  3. data/Dockerfile +2 -2
  4. data/README.md +3 -1
  5. data/config/check_specs.yml +3 -0
  6. data/config/yardstick.yml +7 -1
  7. data/lib/sinclair/config.rb +46 -0
  8. data/lib/sinclair/config_class.rb +15 -0
  9. data/lib/sinclair/configurable.rb +8 -0
  10. data/lib/sinclair/matchers/add_class_method.rb +16 -13
  11. data/lib/sinclair/matchers/add_class_method_to.rb +9 -23
  12. data/lib/sinclair/matchers/add_instance_method.rb +16 -18
  13. data/lib/sinclair/matchers/add_instance_method_to.rb +12 -16
  14. data/lib/sinclair/matchers/add_method.rb +39 -30
  15. data/lib/sinclair/matchers/add_method_to.rb +4 -56
  16. data/lib/sinclair/matchers/base.rb +45 -0
  17. data/lib/sinclair/matchers/change_class_method.rb +42 -0
  18. data/lib/sinclair/matchers/change_class_method_on.rb +64 -0
  19. data/lib/sinclair/matchers/change_instance_method.rb +42 -0
  20. data/lib/sinclair/matchers/change_instance_method_on.rb +98 -0
  21. data/lib/sinclair/matchers/change_method_on.rb +25 -0
  22. data/lib/sinclair/matchers/method_to.rb +82 -0
  23. data/lib/sinclair/matchers.rb +38 -30
  24. data/lib/sinclair/options/class_methods.rb +95 -0
  25. data/lib/sinclair/options.rb +10 -60
  26. data/lib/sinclair/version.rb +1 -1
  27. data/sinclair.gemspec +12 -12
  28. data/spec/integration/readme/my_class_spec.rb +1 -1
  29. data/spec/integration/yard/sinclair/config_spec.rb +27 -0
  30. data/spec/integration/yard/sinclair/options_parser_spec.rb +9 -0
  31. data/spec/lib/sinclair/config_class_spec.rb +1 -33
  32. data/spec/lib/sinclair/config_spec.rb +71 -0
  33. data/spec/lib/sinclair/matchers/add_class_method_to_spec.rb +40 -16
  34. data/spec/lib/sinclair/matchers/add_instance_method_to_spec.rb +36 -12
  35. data/spec/lib/sinclair/matchers/change_class_method_on_spec.rb +138 -0
  36. data/spec/lib/sinclair/matchers/change_class_method_spec.rb +38 -0
  37. data/spec/lib/sinclair/matchers/change_instance_method_on_spec.rb +149 -0
  38. data/spec/lib/sinclair/matchers/change_instance_method_spec.rb +38 -0
  39. data/spec/lib/sinclair/matchers_spec.rb +30 -0
  40. data/spec/lib/sinclair/options/class_methods_spec.rb +255 -0
  41. data/spec/lib/sinclair/options_spec.rb +28 -237
  42. data/spec/support/models/builder_options.rb +7 -0
  43. data/spec/support/models/login_configurable.rb +7 -0
  44. data/spec/support/models/open_options.rb +7 -0
  45. data/spec/support/shared_examples/config.rb +48 -0
  46. metadata +43 -28
@@ -31,4 +31,34 @@ describe Sinclair::Matchers do
31
31
  .to eq(described_class::AddClassMethod.new(:method_name))
32
32
  end
33
33
  end
34
+
35
+ describe '#change_method' do
36
+ it 'has been added to DSL' do
37
+ expect(respond_to?(:change_method)).to be_truthy
38
+ end
39
+
40
+ it do
41
+ expect(change_method(:method_name)).to be_a(described_class::ChangeInstanceMethod)
42
+ end
43
+
44
+ it 'returns the matcher with correct argument' do
45
+ expect(change_method(:method_name))
46
+ .to eq(described_class::ChangeInstanceMethod.new(:method_name))
47
+ end
48
+ end
49
+
50
+ describe '#change_class_method' do
51
+ it 'has been added to DSL' do
52
+ expect(respond_to?(:change_class_method)).to be_truthy
53
+ end
54
+
55
+ it do
56
+ expect(change_class_method(:method_name)).to be_a(described_class::ChangeClassMethod)
57
+ end
58
+
59
+ it 'returns the matcher with correct argument' do
60
+ expect(change_class_method(:method_name))
61
+ .to eq(described_class::ChangeClassMethod.new(:method_name))
62
+ end
63
+ end
34
64
  end
@@ -0,0 +1,255 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Sinclair::Options::ClassMethods do
6
+ subject(:options) { klass.new }
7
+
8
+ describe '.with_options' do
9
+ let(:klass) { Class.new(Sinclair::Options) }
10
+ let(:test_keys) { %i[timeout retries invalid] }
11
+
12
+ context 'when calling with keys' do
13
+ it 'add first method' do
14
+ expect { klass.send(:with_options, :timeout, 'retries') }
15
+ .to add_method(:timeout).to(klass)
16
+ end
17
+
18
+ it 'add second method' do
19
+ expect { klass.send(:with_options, :timeout, 'retries') }
20
+ .to add_method(:retries).to(klass)
21
+ end
22
+
23
+ it 'adds options to allowed' do
24
+ expect { klass.send(:with_options, :timeout, 'retries') }
25
+ .to change { klass.invalid_options_in(test_keys) }
26
+ .from(%i[timeout retries invalid])
27
+ .to([:invalid])
28
+ end
29
+
30
+ it do
31
+ expect { klass.send(:with_options, :timeout, 'retries') }
32
+ .not_to change {
33
+ Sinclair::Options.invalid_options_in(%i[timeout retries invalid])
34
+ }
35
+ end
36
+
37
+ context 'when when calling method after building' do
38
+ before { klass.send(:with_options, :timeout, 'retries') }
39
+
40
+ it { expect(options.timeout).to be_nil }
41
+ end
42
+
43
+ context 'when calling method twice' do
44
+ before { klass.send(:with_options, :timeout, retries: 10) }
45
+
46
+ it do
47
+ expect { klass.send(:with_options, :timeout, :retries) }
48
+ .not_to change {
49
+ klass.invalid_options_in(%i[timeout retries invalid])
50
+ }
51
+ end
52
+ end
53
+ end
54
+
55
+ context 'when calling with a hash' do
56
+ it 'adds method' do
57
+ expect { klass.send(:with_options, timeout_sec: 10, 'retries' => 20) }
58
+ .to add_method(:timeout_sec).to(klass)
59
+ end
60
+
61
+ context 'when when calling method after building' do
62
+ before { klass.send(:with_options, timeout_sec: 10, 'retries' => 20) }
63
+
64
+ it 'returns default value' do
65
+ expect(options.retries).to eq(20)
66
+ end
67
+ end
68
+ end
69
+
70
+ context 'when calling on subclass' do
71
+ let(:super_class) { Class.new(Sinclair::Options) }
72
+ let(:klass) { Class.new(super_class) }
73
+
74
+ let(:test_keys) do
75
+ %i[timeout retries name protocol port invalid]
76
+ end
77
+
78
+ before { super_class.send(:with_options, :timeout, 'retries', name: 'My Connector') }
79
+
80
+ it 'add first method' do
81
+ expect { klass.send(:with_options, :protocol, 'port' => 443) }
82
+ .to add_method(:protocol).to(klass)
83
+ end
84
+
85
+ it 'add second method' do
86
+ expect { klass.send(:with_options, :protocol, 'port' => 443) }
87
+ .to add_method(:port).to(klass)
88
+ end
89
+
90
+ it do
91
+ expect { klass.send(:with_options, 'protocol', port: 443) }
92
+ .to change {
93
+ klass.invalid_options_in(test_keys)
94
+ }.from(%i[protocol port invalid])
95
+ .to([:invalid])
96
+ end
97
+
98
+ it do
99
+ expect { klass.send(:with_options, 'protocol', port: 443) }
100
+ .not_to change {
101
+ super_class.invalid_options_in(%i[protocol port])
102
+ }
103
+ end
104
+
105
+ context 'when overriding a method' do
106
+ it do
107
+ expect { klass.send(:with_options, :name, timeout: 10) }
108
+ .not_to change { klass.invalid_options_in(%i[name timeout]) }
109
+ end
110
+
111
+ it 'change methods to return new default' do
112
+ expect { klass.send(:with_options, :name, timeout: 10) }
113
+ .to change { klass.new.timeout }
114
+ .from(nil).to(10)
115
+ end
116
+
117
+ it 'change methods to return without default' do
118
+ expect { klass.send(:with_options, :name, timeout: 10) }
119
+ .to change { klass.new.name }
120
+ .from('My Connector').to(nil)
121
+ end
122
+ end
123
+ end
124
+ end
125
+
126
+ describe '.invalid_options_in' do
127
+ let(:klass) { Class.new(Sinclair::Options) }
128
+ let(:test_keys) { %i[timeout invalid] }
129
+
130
+ it 'returns alls keys as invalid' do
131
+ expect(klass.invalid_options_in(test_keys))
132
+ .to eq(test_keys)
133
+ end
134
+
135
+ context 'when allowed options was never set' do
136
+ before { klass.allow(:timeout) }
137
+
138
+ it 'returns keys that are not allowed by the input' do
139
+ expect(klass.invalid_options_in(test_keys))
140
+ .to eq([:invalid])
141
+ end
142
+ end
143
+
144
+ context 'when calling on subclass' do
145
+ let(:super_class) { Class.new(Sinclair::Options) }
146
+ let(:klass) { Class.new(super_class) }
147
+ let(:test_keys) { %i[timeout invalid] }
148
+
149
+ before { super_class.allow(:timeout) }
150
+
151
+ context 'when not adding allowed options' do
152
+ it 'returns keys that are not allowed by the input' do
153
+ expect(klass.invalid_options_in(test_keys))
154
+ .to eq([:invalid])
155
+ end
156
+ end
157
+
158
+ context 'when adding keys' do
159
+ before { super_class.allow(:retries) }
160
+
161
+ it 'returns keys that are not allowed by the input' do
162
+ expect(klass.invalid_options_in(test_keys))
163
+ .to eq([:invalid])
164
+ end
165
+
166
+ it 'adds new key to accepted' do
167
+ expect(klass.invalid_options_in([:retries]))
168
+ .to be_empty
169
+ end
170
+ end
171
+ end
172
+ end
173
+
174
+ describe '.allow' do
175
+ let(:klass) { Class.new(Sinclair::Options) }
176
+ let(:test_keys) { %i[timeout retries invalid] }
177
+
178
+ it 'adds options to allowed' do
179
+ expect { klass.allow(:timeout) }
180
+ .to change { klass.invalid_options_in(test_keys) }
181
+ .from(%i[timeout retries invalid])
182
+ .to(%i[retries invalid])
183
+ end
184
+
185
+ context 'when calling on subclass' do
186
+ let(:super_class) { Class.new(Sinclair::Options) }
187
+ let(:klass) { Class.new(super_class) }
188
+
189
+ before { super_class.allow(:timeout) }
190
+
191
+ it 'adds options to allowed' do
192
+ expect { klass.allow(:retries) }
193
+ .to change { klass.invalid_options_in(test_keys) }
194
+ .from(%i[retries invalid])
195
+ .to(%i[invalid])
196
+ end
197
+ end
198
+ end
199
+
200
+ describe '.allowed_options' do
201
+ let(:klass) { Class.new(Sinclair::Options) }
202
+
203
+ context 'when class has not been changed' do
204
+ it { expect(klass.allowed_options).to be_a(Set) }
205
+ end
206
+
207
+ context 'when initializing with with options' do
208
+ let(:expected) do
209
+ Set.new %i[timeout retries port protocol]
210
+ end
211
+
212
+ before do
213
+ klass.send(
214
+ :with_options,
215
+ :timeout, :retries, port: 443, protocol: 'https'
216
+ )
217
+ end
218
+
219
+ it do
220
+ expect(klass.allowed_options)
221
+ .to eq(expected)
222
+ end
223
+
224
+ context 'when class is descendent' do
225
+ let(:descendent_class) { Class.new(klass) }
226
+ let(:expected) do
227
+ Set.new %i[timeout retries port protocol name]
228
+ end
229
+
230
+ before do
231
+ descendent_class.send(
232
+ :with_options,
233
+ :name
234
+ )
235
+ end
236
+
237
+ it do
238
+ expect(descendent_class.allowed_options)
239
+ .to eq(expected)
240
+ end
241
+ end
242
+ end
243
+ end
244
+
245
+ describe '.skip_validation' do
246
+ let(:klass) { Class.new(Sinclair::Options) }
247
+
248
+ it 'skip initialization validation' do
249
+ klass.send(:skip_validation)
250
+
251
+ expect { klass.new(invalid: 10) }
252
+ .not_to raise_error
253
+ end
254
+ end
255
+ end
@@ -5,243 +5,6 @@ require 'spec_helper'
5
5
  describe Sinclair::Options do
6
6
  subject(:options) { klass.new }
7
7
 
8
- describe '.with_options' do
9
- let(:klass) { Class.new(described_class) }
10
- let(:test_keys) { %i[timeout retries invalid] }
11
-
12
- context 'when calling with keys' do
13
- it 'add first method' do
14
- expect { klass.send(:with_options, :timeout, 'retries') }
15
- .to add_method(:timeout).to(klass)
16
- end
17
-
18
- it 'add second method' do
19
- expect { klass.send(:with_options, :timeout, 'retries') }
20
- .to add_method(:retries).to(klass)
21
- end
22
-
23
- it 'adds options to allowed' do
24
- expect { klass.send(:with_options, :timeout, 'retries') }
25
- .to change { klass.invalid_options_in(test_keys) }
26
- .from(%i[timeout retries invalid])
27
- .to([:invalid])
28
- end
29
-
30
- it do
31
- expect { klass.send(:with_options, :timeout, 'retries') }
32
- .not_to change {
33
- described_class.invalid_options_in(%i[timeout retries invalid])
34
- }
35
- end
36
-
37
- context 'when when calling method after building' do
38
- before { klass.send(:with_options, :timeout, 'retries') }
39
-
40
- it { expect(options.timeout).to be_nil }
41
- end
42
-
43
- context 'when calling method twice' do
44
- before { klass.send(:with_options, :timeout, retries: 10) }
45
-
46
- it do
47
- expect { klass.send(:with_options, :timeout, :retries) }
48
- .not_to change {
49
- klass.invalid_options_in(%i[timeout retries invalid])
50
- }
51
- end
52
- end
53
- end
54
-
55
- context 'when calling with a hash' do
56
- it 'adds method' do
57
- expect { klass.send(:with_options, timeout_sec: 10, 'retries' => 20) }
58
- .to add_method(:timeout_sec).to(klass)
59
- end
60
-
61
- context 'when when calling method after building' do
62
- before { klass.send(:with_options, timeout_sec: 10, 'retries' => 20) }
63
-
64
- it 'returns default value' do
65
- expect(options.retries).to eq(20)
66
- end
67
- end
68
- end
69
-
70
- context 'when calling on subclass' do
71
- let(:super_class) { Class.new(described_class) }
72
- let(:klass) { Class.new(super_class) }
73
-
74
- let(:test_keys) do
75
- %i[timeout retries name protocol port invalid]
76
- end
77
-
78
- before { super_class.send(:with_options, :timeout, 'retries', name: 'My Connector') }
79
-
80
- it 'add first method' do
81
- expect { klass.send(:with_options, :protocol, 'port' => 443) }
82
- .to add_method(:protocol).to(klass)
83
- end
84
-
85
- it 'add second method' do
86
- expect { klass.send(:with_options, :protocol, 'port' => 443) }
87
- .to add_method(:port).to(klass)
88
- end
89
-
90
- it do
91
- expect { klass.send(:with_options, 'protocol', port: 443) }
92
- .to change {
93
- klass.invalid_options_in(test_keys)
94
- }.from(%i[protocol port invalid])
95
- .to([:invalid])
96
- end
97
-
98
- it do
99
- expect { klass.send(:with_options, 'protocol', port: 443) }
100
- .not_to change {
101
- super_class.invalid_options_in(%i[protocol port])
102
- }
103
- end
104
-
105
- context 'when overriding a method' do
106
- it do
107
- expect { klass.send(:with_options, :name, timeout: 10) }
108
- .not_to change { klass.invalid_options_in(%i[name timeout]) }
109
- end
110
-
111
- it 'change methods to return new default' do
112
- expect { klass.send(:with_options, :name, timeout: 10) }
113
- .to change { klass.new.timeout }
114
- .from(nil).to(10)
115
- end
116
-
117
- it 'change methods to return without default' do
118
- expect { klass.send(:with_options, :name, timeout: 10) }
119
- .to change { klass.new.name }
120
- .from('My Connector').to(nil)
121
- end
122
- end
123
- end
124
- end
125
-
126
- describe '.invalid_options_in' do
127
- let(:klass) { Class.new(described_class) }
128
- let(:test_keys) { %i[timeout invalid] }
129
-
130
- it 'returns alls keys as invalid' do
131
- expect(klass.invalid_options_in(test_keys))
132
- .to eq(test_keys)
133
- end
134
-
135
- context 'when allowed options was never set' do
136
- before { klass.allow(:timeout) }
137
-
138
- it 'returns keys that are not allowed by the input' do
139
- expect(klass.invalid_options_in(test_keys))
140
- .to eq([:invalid])
141
- end
142
- end
143
-
144
- context 'when calling on subclass' do
145
- let(:super_class) { Class.new(described_class) }
146
- let(:klass) { Class.new(super_class) }
147
- let(:test_keys) { %i[timeout invalid] }
148
-
149
- before { super_class.allow(:timeout) }
150
-
151
- context 'when not adding allowed options' do
152
- it 'returns keys that are not allowed by the input' do
153
- expect(klass.invalid_options_in(test_keys))
154
- .to eq([:invalid])
155
- end
156
- end
157
-
158
- context 'when adding keys' do
159
- before { super_class.allow(:retries) }
160
-
161
- it 'returns keys that are not allowed by the input' do
162
- expect(klass.invalid_options_in(test_keys))
163
- .to eq([:invalid])
164
- end
165
-
166
- it 'adds new key to accepted' do
167
- expect(klass.invalid_options_in([:retries]))
168
- .to be_empty
169
- end
170
- end
171
- end
172
- end
173
-
174
- describe '.allow' do
175
- let(:klass) { Class.new(described_class) }
176
- let(:test_keys) { %i[timeout retries invalid] }
177
-
178
- it 'adds options to allowed' do
179
- expect { klass.allow(:timeout) }
180
- .to change { klass.invalid_options_in(test_keys) }
181
- .from(%i[timeout retries invalid])
182
- .to(%i[retries invalid])
183
- end
184
-
185
- context 'when calling on subclass' do
186
- let(:super_class) { Class.new(described_class) }
187
- let(:klass) { Class.new(super_class) }
188
-
189
- before { super_class.allow(:timeout) }
190
-
191
- it 'adds options to allowed' do
192
- expect { klass.allow(:retries) }
193
- .to change { klass.invalid_options_in(test_keys) }
194
- .from(%i[retries invalid])
195
- .to(%i[invalid])
196
- end
197
- end
198
- end
199
-
200
- describe '.allowed_options' do
201
- let(:klass) { Class.new(described_class) }
202
-
203
- context 'when class has not been changed' do
204
- it { expect(klass.allowed_options).to be_a(Set) }
205
- end
206
-
207
- context 'when initializing with with options' do
208
- let(:expected) do
209
- Set.new %i[timeout retries port protocol]
210
- end
211
-
212
- before do
213
- klass.send(
214
- :with_options,
215
- :timeout, :retries, port: 443, protocol: 'https'
216
- )
217
- end
218
-
219
- it do
220
- expect(klass.allowed_options)
221
- .to eq(expected)
222
- end
223
-
224
- context 'when class is descendent' do
225
- let(:descendent_class) { Class.new(klass) }
226
- let(:expected) do
227
- Set.new %i[timeout retries port protocol name]
228
- end
229
-
230
- before do
231
- descendent_class.send(
232
- :with_options,
233
- :name
234
- )
235
- end
236
-
237
- it do
238
- expect(descendent_class.allowed_options)
239
- .to eq(expected)
240
- end
241
- end
242
- end
243
- end
244
-
245
8
  describe '#initialize' do
246
9
  let(:klass) { ConnectionOptions }
247
10
 
@@ -323,6 +86,34 @@ describe Sinclair::Options do
323
86
  end
324
87
  end
325
88
 
89
+ context 'when initializing with invalid args a class that skips validation' do
90
+ let(:klass) { OpenOptions }
91
+
92
+ it do
93
+ expect { klass.new(valid_option: 20, invalid: 10) }
94
+ .not_to raise_error
95
+ end
96
+
97
+ it 'initialize option' do
98
+ expect(klass.new(valid_option: 20, invalid: 10).valid_option)
99
+ .to eq(20)
100
+ end
101
+
102
+ context 'when initializing a subclass' do
103
+ let(:klass) { Class.new(OpenOptions) }
104
+
105
+ it do
106
+ expect { klass.new(valid_option: 20, invalid: 10) }
107
+ .not_to raise_error
108
+ end
109
+
110
+ it 'initialize option' do
111
+ expect(klass.new(valid_option: 20, invalid: 10).valid_option)
112
+ .to eq(20)
113
+ end
114
+ end
115
+ end
116
+
326
117
  context 'when initializing with string or symbol keys' do
327
118
  it do
328
119
  expect { klass.new('timeout' => 20, retries: 30) }
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class BuilderOptions < Sinclair::Options
4
+ with_options :name
5
+
6
+ skip_validation
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class LoginConfigurable
4
+ extend Sinclair::Configurable
5
+
6
+ configurable_by LoginConfig
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class OpenOptions < Sinclair::Options
4
+ with_options :valid_option
5
+
6
+ skip_validation
7
+ end
@@ -115,3 +115,51 @@ shared_examples 'a config class with .config_attributes method' do
115
115
  end
116
116
  end
117
117
  end
118
+
119
+ shared_examples 'a config class with .add_configs method' do
120
+ let(:setter_block) do
121
+ proc { |value| config.instance_variable_set(:@name, value) }
122
+ end
123
+
124
+ it_behaves_like 'a config methods builder adding config' do
125
+ let(:code_block) { proc { klass.add_configs(:name) } }
126
+
127
+ it 'sets nil value by default' do
128
+ code_block.call
129
+ expect(config.name).to be_nil
130
+ end
131
+
132
+ it 'adds attributes to class' do
133
+ expect(&code_block).to change(klass, :config_attributes)
134
+ .from([]).to(%i[name])
135
+ end
136
+
137
+ it do
138
+ expect(&code_block)
139
+ .to add_method(:name)
140
+ .to(klass.options_class)
141
+ end
142
+ end
143
+
144
+ context 'when giving defaults' do
145
+ it_behaves_like 'a config methods builder adding config' do
146
+ let(:code_block) { proc { klass.add_configs(name: 'Bob') } }
147
+
148
+ it 'sets default value' do
149
+ code_block.call
150
+ expect(config.name).to eq('Bob')
151
+ end
152
+
153
+ it 'adds attributes to class' do
154
+ expect(&code_block).to change(klass, :config_attributes)
155
+ .from([]).to(%i[name])
156
+ end
157
+
158
+ it do
159
+ expect(&code_block)
160
+ .to add_method(:name)
161
+ .to(klass.options_class)
162
+ end
163
+ end
164
+ end
165
+ end