ns-options 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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