ns-options 0.1.1 → 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.
@@ -0,0 +1,144 @@
1
+ require 'assert'
2
+
3
+ class NsOptions::Helper::Advisor
4
+
5
+ module Output
6
+ module_function
7
+
8
+ def capture
9
+ out = StringIO.new
10
+ $stdout = out
11
+ yield
12
+ return out
13
+ ensure
14
+ $stdout = STDOUT
15
+ end
16
+ end
17
+
18
+ class BaseTest < Assert::Context
19
+ desc "NsOptions::Helper::Advisor"
20
+ setup do
21
+ @namespace = NsOptions::Namespace.new("something")
22
+ @advisor = NsOptions::Helper::Advisor.new(@namespace)
23
+ end
24
+ subject{ @advisor }
25
+
26
+ should have_accessors :namespace
27
+ should have_instance_methods :is_this_ok?, :is_this_option_ok?, :is_this_namespace_ok?,
28
+ :is_already_defined?, :bad_methods, :not_recommended_methods, :bad_method_message,
29
+ :duplicate_message, :not_recommended_method_message
30
+
31
+ should "return methods that cannot be overwritten with a call to #bad_methods" do
32
+ expected = [ :define, :namespace, :option, :options ].map(&:to_s).sort
33
+ assert_equal(expected, subject.bad_methods.map(&:to_s).sort)
34
+ end
35
+ should "return methods that shouldn't be overwritten with a call to #not_recommended_methods" do
36
+ expected = NsOptions::Namespace.instance_methods(false).map(&:to_sym)
37
+ assert_equal(expected, subject.not_recommended_methods)
38
+ end
39
+ should "return if an option/namespace is defined with a call to #is_already_defined?" do
40
+ assert_equal false, subject.is_already_defined?(:first)
41
+ end
42
+ end
43
+
44
+ class BadOptionTest < BaseTest
45
+ desc "with a bad option"
46
+ setup do
47
+ begin
48
+ @advisor.is_this_option_ok?("namespace")
49
+ rescue Exception => @exception
50
+ end
51
+ end
52
+
53
+ should "raise an exception when an option matches one of the bad methods" do
54
+ assert_kind_of NsOptions::Errors::InvalidName, @exception
55
+ expected = subject.bad_method_message("option", "namespace")
56
+ assert_equal expected, @exception.message
57
+ end
58
+ end
59
+
60
+ class DuplicateOptionTest < BaseTest
61
+ desc "with a duplicate option"
62
+ setup do
63
+ @namespace.option(:duplicate)
64
+ @output = Output.capture do
65
+ @advisor.is_this_option_ok?("duplicate")
66
+ end
67
+ end
68
+
69
+ should "output a message warning that they are re-defining an option" do
70
+ expected = subject.duplicate_message("duplicate")
71
+ assert_match expected, @output.string
72
+ assert_match "From: ", @output.string
73
+ end
74
+ should "return true with a call to #is_already_defined?" do
75
+ assert_equal true, subject.is_already_defined?(:duplicate)
76
+ end
77
+ end
78
+
79
+ class NotRecommendedOptionTest < BaseTest
80
+ desc "with a not recommended option"
81
+ setup do
82
+ @output = Output.capture do
83
+ @advisor.is_this_option_ok?("apply")
84
+ end
85
+ end
86
+
87
+ should "output a message warning using the method name as an option name" do
88
+ expected = subject.not_recommended_method_message("option", "apply")
89
+ assert_match expected, @output.string
90
+ assert_match "From: ", @output.string
91
+ end
92
+ end
93
+
94
+ class BadNamespaceTest < BaseTest
95
+ desc "with a bad namespace"
96
+ setup do
97
+ begin
98
+ @advisor.is_this_namespace_ok?("options")
99
+ rescue Exception => @exception
100
+ end
101
+ end
102
+
103
+ should "raise an exception when a namespace matches one of the bad methods" do
104
+ assert_kind_of NsOptions::Errors::InvalidName, @exception
105
+ expected = subject.bad_method_message("sub-namespace", "options")
106
+ assert_equal expected, @exception.message
107
+ end
108
+ end
109
+
110
+ class DuplicateNamespaceTest < BaseTest
111
+ desc "with a duplicate namespace"
112
+ setup do
113
+ @namespace.namespace(:duplicate)
114
+ @output = Output.capture do
115
+ @advisor.is_this_namespace_ok?("duplicate")
116
+ end
117
+ end
118
+
119
+ should "output a message warning that they are re-defining a namespace" do
120
+ expected = subject.duplicate_message("duplicate")
121
+ assert_match expected, @output.string
122
+ assert_match "From: ", @output.string
123
+ end
124
+ should "return true with a call to #is_already_defined?" do
125
+ assert_equal true, subject.is_already_defined?(:duplicate)
126
+ end
127
+ end
128
+
129
+ class NotRecommendedNamespaceTest < BaseTest
130
+ desc "with a not recommended namespace"
131
+ setup do
132
+ @output = Output.capture do
133
+ @advisor.is_this_namespace_ok?("apply")
134
+ end
135
+ end
136
+
137
+ should "output a message warning using the method name as a namespace name" do
138
+ expected = subject.not_recommended_method_message("sub-namespace", "apply")
139
+ assert_match expected, @output.string
140
+ assert_match "From: ", @output.string
141
+ end
142
+ end
143
+
144
+ end
@@ -9,54 +9,43 @@ module NsOptions::Helper
9
9
  end
10
10
  subject{ @module }
11
11
 
12
- should have_instance_methods :new_namespace, :new_child_namespace, :fetch_and_define_option
13
-
12
+ should have_instance_methods :find_and_define_namespace, :find_and_define_option,
13
+ :define_namespace_methods, :define_option_methods, :advisor
14
+
15
+ should "return an instance of NsOptions::Helper::Advisor with a call to #advisor" do
16
+ advisor = subject.advisor(NsOptions::Namespace.new("something"))
17
+ assert_instance_of NsOptions::Helper::Advisor, advisor
18
+ end
14
19
  end
15
-
16
- class NewNamespaceTest < BaseTest
17
- desc "new_namespace method"
20
+
21
+ class FindAndDefineOptionTest < BaseTest
22
+ desc "find_and_define_option method"
18
23
  setup do
19
- @parent = @module.new_namespace("parent")
20
- @child = @module.new_namespace("child", @parent) do
21
- option :something
22
- end
24
+ @namespace = NsOptions::Namespace.new("something")
25
+ @option = @namespace.options.add(:anything)
26
+ @result = @module.find_and_define_option(@namespace, @option.name)
23
27
  end
24
-
25
- should "have created a parent namespace" do
26
- assert_equal "parent", @parent.options.key
27
- end
28
- should "have created a child namespace" do
29
- assert_equal "child", @child.options.key
30
- assert_equal @parent, @child.options.parent
31
- assert @child.options[:something]
28
+ subject{ @namespace }
29
+
30
+ should "have defined reader/writer methods for the option and returned the option" do
31
+ assert_respond_to @option.name, subject
32
+ assert_respond_to "#{@option.name}=", subject
33
+ assert_equal @option, @result
32
34
  end
33
- end
35
+ end
34
36
 
35
- class NewChildNamespaceTest < BaseTest
36
- desc "new_child_namespace method"
37
+ class FindAndDefineNamespaceTest < BaseTest
38
+ desc "find_and_define_namespace method"
37
39
  setup do
38
- @parent = @module.new_namespace("parent")
39
- @mock_class = mock()
40
- @mock_class.stubs(:super_settings).returns(@parent)
41
- @first_owner = mock()
42
- @first_owner.stubs({ :class => @mock_class })
43
- @first = @module.new_child_namespace(@first_owner, "super_settings") do
44
- option :something
45
- end
46
- @second_owner = User.new
47
- @second = @module.new_child_namespace(@second_owner, "preferences")
40
+ @namespace = NsOptions::Namespace.new("something")
41
+ @namespace.options.add_namespace(:else, "something:else")
42
+ @result = @module.find_and_define_namespace(@namespace, :else)
48
43
  end
44
+ subject{ @namespace }
49
45
 
50
- should "have created a child namespace" do
51
- class_name = @mock_class.to_s.split('::').last.downcase
52
- key = "#{@parent.options.key}:#{class_name}_#{@first_owner.object_id}"
53
- assert_equal key, @first.options.key
54
- assert_equal @parent, @first.options.parent
55
- assert @first.options[:something]
56
- end
57
- should "have created a second child namespace" do
58
- key = "#{@second.options.parent.options.key}:#{@second_owner.preferences_key}"
59
- assert_equal key, @second.options.key
46
+ should "have defined reader method for the namespace and returned the namespace" do
47
+ assert_respond_to :else, subject
48
+ assert_equal subject.options.get_namespace(:else), @result
60
49
  end
61
50
  end
62
51
 
@@ -5,33 +5,43 @@ class NsOptions::Namespace
5
5
  class BaseTest < Assert::Context
6
6
  desc "NsOptions::Namespace"
7
7
  setup do
8
- @key = "options"
8
+ @key = "something"
9
9
  @namespace = NsOptions::Namespace.new(@key)
10
10
  end
11
11
  subject{ @namespace }
12
12
 
13
13
  should have_accessors :metaclass, :options
14
- should have_instance_methods :option, :namespace, :required_set?, :define
14
+ should have_instance_methods :option, :namespace, :required_set?, :define, :apply, :valid?
15
+ should have_instance_methods :to_hash, :each
15
16
 
16
17
  should "have set it's metaclass accessor" do
17
18
  assert subject.metaclass
18
19
  end
20
+
19
21
  should "have created a new options collection and set it's options accessor" do
20
22
  assert subject.options
21
23
  assert_kind_of NsOptions::Options, subject.options
22
24
  assert_equal @key, subject.options.key
23
25
  assert_nil subject.options.parent
24
26
  end
27
+
28
+ should "contain its options key in its inspect output" do
29
+ assert_included ":#{subject.options.key}", subject.inspect
30
+ end
31
+
25
32
  end
26
33
 
27
34
  class OptionTest < BaseTest
28
35
  desc "option method"
29
36
  setup do
30
37
  @name = :something
31
- @type = NsOptions::Option::Boolean
38
+ @type = String
32
39
  @rules = { :default => true }
33
40
  @namespace.option(@name, @type, @rules)
34
41
  end
42
+ teardown do
43
+ NsOptions::Helper.unstub(:advisor)
44
+ end
35
45
  subject{ @namespace }
36
46
 
37
47
  should "have added the option to the namespace's options collection" do
@@ -40,6 +50,15 @@ class NsOptions::Namespace
40
50
  assert_equal @type, option.type_class
41
51
  assert_equal @rules, option.rules
42
52
  end
53
+
54
+ should "check if the option name is ok" do
55
+ advisor = NsOptions::Helper::Advisor.new(@namespace)
56
+ NsOptions::Helper.expects(:advisor).with(@namespace).returns(advisor)
57
+ advisor.expects(:is_this_option_ok?)
58
+ assert_nothing_raised do
59
+ @namespace.option(:amazing)
60
+ end
61
+ end
43
62
  end
44
63
 
45
64
  class OptionWithNoTypeTest < BaseTest
@@ -50,10 +69,11 @@ class NsOptions::Namespace
50
69
  end
51
70
  subject{ @namespace }
52
71
 
53
- should "default the type to String" do
72
+ should "default the type to Object" do
54
73
  assert(option = subject.options[@name])
55
- assert_equal String, option.type_class
74
+ assert_equal Object, option.type_class
56
75
  end
76
+
57
77
  end
58
78
 
59
79
  class OptionMethodsTest < OptionTest
@@ -62,13 +82,15 @@ class NsOptions::Namespace
62
82
  should have_instance_methods :something, :something=
63
83
 
64
84
  should "be writable through the defined writer" do
65
- assert_nothing_raised{ subject.something = false }
66
- assert_equal false, subject.something
85
+ assert_nothing_raised{ subject.something = "abc" }
86
+ assert_equal "abc", subject.something
67
87
  end
88
+
68
89
  should "be writable through the reader with args" do
69
- assert_nothing_raised{ subject.something true }
70
- assert_equal true, subject.something
90
+ assert_nothing_raised{ subject.something "123" }
91
+ assert_equal "123", subject.something
71
92
  end
93
+
72
94
  end
73
95
 
74
96
  class NamespaceTest < BaseTest
@@ -79,6 +101,9 @@ class NsOptions::Namespace
79
101
  end
80
102
  @namespace.namespace(:another, "special_key")
81
103
  end
104
+ teardown do
105
+ NsOptions::Helper.unstub(:advisor)
106
+ end
82
107
  subject{ @namespace }
83
108
 
84
109
  should "have added a namespace to the namespace's options collection" do
@@ -87,10 +112,21 @@ class NsOptions::Namespace
87
112
  assert_equal subject, namespace.options.parent
88
113
  assert namespace.options[:something_else]
89
114
  end
115
+
90
116
  should "allow passing a special key to the namespace" do
91
117
  assert(namespace = subject.options.namespaces[:another])
92
118
  assert_equal "#{subject.options.key}:special_key", namespace.options.key
93
119
  end
120
+
121
+ should "check if the namespace name is ok" do
122
+ advisor = NsOptions::Helper::Advisor.new(@namespace)
123
+ NsOptions::Helper.expects(:advisor).with(@namespace).returns(advisor)
124
+ advisor.expects(:is_this_namespace_ok?)
125
+ assert_nothing_raised do
126
+ @namespace.namespace(:yet_another)
127
+ end
128
+ end
129
+
94
130
  end
95
131
 
96
132
  class NamespaceMethodsTest < NamespaceTest
@@ -101,12 +137,14 @@ class NsOptions::Namespace
101
137
  should "be return the namespace using the reader" do
102
138
  assert_equal subject.options.namespaces[:something], subject.something
103
139
  end
140
+
104
141
  should "define the namespace with the reader and a block" do
105
142
  subject.something do
106
143
  option :another
107
144
  end
108
145
  assert subject.something.options[:another]
109
146
  end
147
+
110
148
  end
111
149
 
112
150
  class DefineTest < BaseTest
@@ -146,10 +184,9 @@ class NsOptions::Namespace
146
184
  class MethodMissingTest < BaseTest
147
185
  desc "method missing"
148
186
  setup do
149
- @parent = @namespace
150
- @parent.options.add(:something)
151
- @parent.options.set(:something, "amazing")
152
- @namespace = NsOptions::Namespace.new("child", @parent)
187
+ @namespace = NsOptions::Namespace.new("strange")
188
+ @namespace.options.add(:something)
189
+ @namespace.options.set(:something, "amazing")
153
190
  end
154
191
 
155
192
  class ReaderForAKnownOptionTest < MethodMissingTest
@@ -184,6 +221,8 @@ class NsOptions::Namespace
184
221
  @namespace.something_not_defined = "you know it"
185
222
  @namespace.another_not_defined = true
186
223
  @namespace.even_more_not_defined = 12
224
+ @namespace.just_one_more_not_defined = nil
225
+ @namespace.proc_opt_not_defined = Proc.new { "imma proc!" }
187
226
  end
188
227
 
189
228
  should "have defined the accessors and added the option" do
@@ -193,11 +232,20 @@ class NsOptions::Namespace
193
232
  assert_includes :something_not_defined=, defined_methods
194
233
  assert_equal "you know it", subject.something_not_defined
195
234
  end
196
- should "use the class of the value for the option's type class" do
197
- assert_equal String, subject.options[:something_not_defined].type_class
198
- assert_equal Integer, subject.options[:even_more_not_defined].type_class
199
- assert_equal NsOptions::Option::Boolean, subject.options[:another_not_defined].type_class
235
+
236
+ should "use Object for the option's type class, no matter what the value is" do
237
+ assert_equal Object, subject.options[:something_not_defined].type_class
238
+ assert_equal Object, subject.options[:another_not_defined].type_class
239
+ assert_equal Object, subject.options[:even_more_not_defined].type_class
240
+ assert_equal Object, subject.options[:just_one_more_not_defined].type_class
241
+ assert_equal Object, subject.options[:proc_opt_not_defined].type_class
242
+ end
243
+
244
+ should "return the Proc return val when an unknow option is set to a Proc" do
245
+ assert_not_kind_of Proc, subject.options[:proc_opt_not_defined].type_class
246
+ assert_equal "imma proc!", subject.proc_opt_not_defined
200
247
  end
248
+
201
249
  end
202
250
  end
203
251
 
@@ -229,4 +277,125 @@ class NsOptions::Namespace
229
277
  end
230
278
  end
231
279
 
280
+
281
+
282
+ class HandlingTests < BaseTest
283
+ setup do
284
+ @namespace.define do
285
+ option :first
286
+ option :second
287
+ option :third
288
+ namespace(:child_a) do
289
+ option(:fourth)
290
+ option(:fifth)
291
+ namespace(:child_b) do
292
+ option(:sixth)
293
+ end
294
+ end
295
+ end
296
+
297
+ @named_values = {
298
+ :first => "1", :second => "2", :third => "3", :twenty_one => "21",
299
+ :child_a => {
300
+ :fourth => "4", :fifth => "5",
301
+ :child_b => { :sixth => "6" }
302
+ },
303
+ :child_c => { :what => "?" }
304
+ }
305
+ end
306
+
307
+ end
308
+
309
+
310
+
311
+ class ApplyTest < HandlingTests
312
+ desc "apply method"
313
+ setup do
314
+ @namespace.apply(@named_values)
315
+ end
316
+
317
+ should "have mass set all the defined options" do
318
+ assert_equal @named_values[:first], subject.first
319
+ assert_equal @named_values[:second], subject.second
320
+ assert_equal @named_values[:third], subject.third
321
+ assert_equal @named_values[:child_a][:fourth], subject.child_a.fourth
322
+ assert_equal @named_values[:child_a][:fifth], subject.child_a.fifth
323
+ assert_equal @named_values[:child_a][:child_b][:sixth], subject.child_a.child_b.sixth
324
+ end
325
+ should "have dynamically added options for the undefined keys" do
326
+ assert_equal @named_values[:twenty_one], subject.twenty_one
327
+ assert_equal @named_values[:child_c], subject.child_c
328
+ end
329
+
330
+ end
331
+
332
+
333
+
334
+ class ToHashTests < HandlingTests
335
+ desc "when to_hash"
336
+ subject { @namespace.to_hash }
337
+
338
+ should "return a Hash representation for the namespace" do
339
+ assert_equal({
340
+ :first => nil,
341
+ :second => nil,
342
+ :third => nil,
343
+ :child_a => {
344
+ :fourth => nil,
345
+ :fifth => nil,
346
+ :child_b => {
347
+ :sixth => nil
348
+ }
349
+ }
350
+ }, subject)
351
+
352
+ @namespace.first = "first"
353
+ assert_equal({
354
+ :first => "first",
355
+ :second => nil,
356
+ :third => nil,
357
+ :child_a => {
358
+ :fourth => nil,
359
+ :fifth => nil,
360
+ :child_b => {
361
+ :sixth => nil
362
+ }
363
+ }
364
+ }, subject)
365
+
366
+ @namespace.apply(@named_values)
367
+ assert_equal @named_values, subject
368
+ end
369
+
370
+ should "contain its to_hash representation in its inspect output" do
371
+ assert_included subject.inspect, @namespace.inspect
372
+ end
373
+
374
+ end
375
+
376
+
377
+ class EachTests < HandlingTests
378
+ desc "iterated with the each method"
379
+ setup do
380
+ @namespace.apply(@named_values)
381
+ @exp = "".tap do |exp|
382
+ @namespace.to_hash.each do |k,v|
383
+ exp << "#{k}=#{v};"
384
+ end
385
+ end
386
+ @act = "".tap do |exp|
387
+ @namespace.each do |k,v|
388
+ exp << "#{k}=#{v};"
389
+ end
390
+ end
391
+ end
392
+
393
+ should "yield k/v pairs by iterating over the #to_hash" do
394
+ assert_equal @exp, @act
395
+ end
396
+
397
+ end
398
+
399
+
400
+
232
401
  end
@@ -45,7 +45,7 @@ class NsOptions::Namespaces
45
45
 
46
46
  class GetTest < AddTest
47
47
  desc "get method"
48
-
48
+
49
49
  should "return the namespace matching the name" do
50
50
  assert(namespace = subject.get("a_name"))
51
51
  assert_equal subject[:a_name], namespace