wardrobe 0.1.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 (165) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +10 -0
  3. data/.gitignore +19 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +11 -0
  6. data/CHANGELOG.md +5 -0
  7. data/Gemfile +18 -0
  8. data/Guardfile +42 -0
  9. data/LICENSE +19 -0
  10. data/README.md +227 -0
  11. data/Rakefile +20 -0
  12. data/examples/new_york_times_article.rb +55 -0
  13. data/lib/wardrobe/attribute.rb +76 -0
  14. data/lib/wardrobe/attribute_store.rb +16 -0
  15. data/lib/wardrobe/block_setup.rb +124 -0
  16. data/lib/wardrobe/boolean.rb +6 -0
  17. data/lib/wardrobe/class_methods.rb +127 -0
  18. data/lib/wardrobe/getter_setter.rb +48 -0
  19. data/lib/wardrobe/instance_methods.rb +56 -0
  20. data/lib/wardrobe/module_methods.rb +51 -0
  21. data/lib/wardrobe/option.rb +30 -0
  22. data/lib/wardrobe/option_store.rb +22 -0
  23. data/lib/wardrobe/plugin.rb +39 -0
  24. data/lib/wardrobe/plugin_store.rb +28 -0
  25. data/lib/wardrobe/plugins/alias_setters.rb +35 -0
  26. data/lib/wardrobe/plugins/coercible/refinements/array.rb +63 -0
  27. data/lib/wardrobe/plugins/coercible/refinements/boolean.rb +36 -0
  28. data/lib/wardrobe/plugins/coercible/refinements/date.rb +31 -0
  29. data/lib/wardrobe/plugins/coercible/refinements/date_time.rb +29 -0
  30. data/lib/wardrobe/plugins/coercible/refinements/float.rb +23 -0
  31. data/lib/wardrobe/plugins/coercible/refinements/hash.rb +65 -0
  32. data/lib/wardrobe/plugins/coercible/refinements/integer.rb +23 -0
  33. data/lib/wardrobe/plugins/coercible/refinements/object.rb +15 -0
  34. data/lib/wardrobe/plugins/coercible/refinements/set.rb +33 -0
  35. data/lib/wardrobe/plugins/coercible/refinements/string.rb +21 -0
  36. data/lib/wardrobe/plugins/coercible/refinements/symbol.rb +21 -0
  37. data/lib/wardrobe/plugins/coercible/refinements/time.rb +30 -0
  38. data/lib/wardrobe/plugins/coercible/refinements/unsupported_error.rb +11 -0
  39. data/lib/wardrobe/plugins/coercible.rb +52 -0
  40. data/lib/wardrobe/plugins/configurable/configurable_store.rb +26 -0
  41. data/lib/wardrobe/plugins/configurable.rb +40 -0
  42. data/lib/wardrobe/plugins/default.rb +33 -0
  43. data/lib/wardrobe/plugins/dirty_tracker.rb +66 -0
  44. data/lib/wardrobe/plugins/equality.rb +19 -0
  45. data/lib/wardrobe/plugins/html_initializer.rb +38 -0
  46. data/lib/wardrobe/plugins/immutable.rb +164 -0
  47. data/lib/wardrobe/plugins/ivy_presenter.rb +42 -0
  48. data/lib/wardrobe/plugins/json_initializer.rb +41 -0
  49. data/lib/wardrobe/plugins/nil_if_empty.rb +27 -0
  50. data/lib/wardrobe/plugins/nil_if_zero.rb +19 -0
  51. data/lib/wardrobe/plugins/optional_getter.rb +21 -0
  52. data/lib/wardrobe/plugins/optional_setter.rb +24 -0
  53. data/lib/wardrobe/plugins/presenter/refinements/array.rb +15 -0
  54. data/lib/wardrobe/plugins/presenter/refinements/hash.rb +15 -0
  55. data/lib/wardrobe/plugins/presenter/refinements/object.rb +15 -0
  56. data/lib/wardrobe/plugins/presenter/refinements/time.rb +19 -0
  57. data/lib/wardrobe/plugins/presenter/refinements.rb +6 -0
  58. data/lib/wardrobe/plugins/presenter.rb +25 -0
  59. data/lib/wardrobe/plugins/validation/block_handler.rb +83 -0
  60. data/lib/wardrobe/plugins/validation/class_methods.rb +13 -0
  61. data/lib/wardrobe/plugins/validation/deep_merge.rb +27 -0
  62. data/lib/wardrobe/plugins/validation/error_store.rb +27 -0
  63. data/lib/wardrobe/plugins/validation/instance_methods.rb +39 -0
  64. data/lib/wardrobe/plugins/validation/refinements/_size.rb +30 -0
  65. data/lib/wardrobe/plugins/validation/refinements/array.rb +26 -0
  66. data/lib/wardrobe/plugins/validation/refinements/date.rb +15 -0
  67. data/lib/wardrobe/plugins/validation/refinements/hash.rb +27 -0
  68. data/lib/wardrobe/plugins/validation/refinements/integer.rb +21 -0
  69. data/lib/wardrobe/plugins/validation/refinements/nil_class.rb +19 -0
  70. data/lib/wardrobe/plugins/validation/refinements/numeric.rb +31 -0
  71. data/lib/wardrobe/plugins/validation/refinements/object.rb +35 -0
  72. data/lib/wardrobe/plugins/validation/refinements/set.rb +25 -0
  73. data/lib/wardrobe/plugins/validation/refinements/string.rb +55 -0
  74. data/lib/wardrobe/plugins/validation/refinements/symbol.rb +26 -0
  75. data/lib/wardrobe/plugins/validation/refinements.rb +13 -0
  76. data/lib/wardrobe/plugins/validation/validation.rb +63 -0
  77. data/lib/wardrobe/plugins/validation/validation_error.rb +19 -0
  78. data/lib/wardrobe/plugins/validation/validaton_runner.rb +38 -0
  79. data/lib/wardrobe/plugins/validation/validator.rb +119 -0
  80. data/lib/wardrobe/plugins/validation.rb +28 -0
  81. data/lib/wardrobe/root_config.rb +31 -0
  82. data/lib/wardrobe/store.rb +62 -0
  83. data/lib/wardrobe/stores.rb +106 -0
  84. data/lib/wardrobe/version.rb +5 -0
  85. data/lib/wardrobe.rb +34 -0
  86. data/sandbox/Gemfile +5 -0
  87. data/sandbox/Gemfile.lock +52 -0
  88. data/sandbox/bench_mutable_coercion.rb +91 -0
  89. data/sandbox/bench_test_1.rb +50 -0
  90. data/sandbox/bench_test_2.rb +48 -0
  91. data/sandbox/bench_test_3.rb +92 -0
  92. data/sandbox/cnn_article_find.rb +20 -0
  93. data/sandbox/define_method_procs.rb +139 -0
  94. data/sandbox/hanami_validations.rb +40 -0
  95. data/sandbox/middleware_bench_test.rb +97 -0
  96. data/sandbox/middleware_bench_v2_test.rb +130 -0
  97. data/test/assertions.rb +22 -0
  98. data/test/test_helper.rb +37 -0
  99. data/test/unit/atrs_config_test.rb +33 -0
  100. data/test/unit/atrs_root_module_test.rb +19 -0
  101. data/test/unit/attribute_test.rb +44 -0
  102. data/test/unit/block_runner/array_test.rb +29 -0
  103. data/test/unit/block_setup_test.rb +41 -0
  104. data/test/unit/class_methods_test.rb +92 -0
  105. data/test/unit/create_class_from_hash_test.rb +28 -0
  106. data/test/unit/define_getter_test.rb +94 -0
  107. data/test/unit/define_setter_test.rb +0 -0
  108. data/test/unit/disable_coercion_test.rb +19 -0
  109. data/test/unit/inheritance_composition_test.rb +36 -0
  110. data/test/unit/method_override_test.rb +18 -0
  111. data/test/unit/method_polution_test.rb +48 -0
  112. data/test/unit/option_test.rb +17 -0
  113. data/test/unit/plugin_test.rb +12 -0
  114. data/test/unit/plugins/alias_setters_test.rb +24 -0
  115. data/test/unit/plugins/coercible/array_test.rb +79 -0
  116. data/test/unit/plugins/coercible/boolean_test.rb +68 -0
  117. data/test/unit/plugins/coercible/custom_class_test.rb +61 -0
  118. data/test/unit/plugins/coercible/date_test.rb +38 -0
  119. data/test/unit/plugins/coercible/date_time_test.rb +44 -0
  120. data/test/unit/plugins/coercible/float_test.rb +42 -0
  121. data/test/unit/plugins/coercible/hash_test.rb +62 -0
  122. data/test/unit/plugins/coercible/integer_test.rb +42 -0
  123. data/test/unit/plugins/coercible/nested_wardrobe_test.rb +63 -0
  124. data/test/unit/plugins/coercible/set_test.rb +49 -0
  125. data/test/unit/plugins/coercible/string_test.rb +36 -0
  126. data/test/unit/plugins/coercible/symbol_test.rb +30 -0
  127. data/test/unit/plugins/coercible/time_test.rb +43 -0
  128. data/test/unit/plugins/configurable_test.rb +64 -0
  129. data/test/unit/plugins/default_value_test.rb +78 -0
  130. data/test/unit/plugins/dirty_tracker_test.rb +78 -0
  131. data/test/unit/plugins/equality_test.rb +36 -0
  132. data/test/unit/plugins/html_initializer_test.rb +19 -0
  133. data/test/unit/plugins/immutable_test.rb +149 -0
  134. data/test/unit/plugins/ivy_presenter_test.rb +57 -0
  135. data/test/unit/plugins/json_initializer_test.rb +67 -0
  136. data/test/unit/plugins/nil_if_empty_test.rb +39 -0
  137. data/test/unit/plugins/nil_if_zero_test.rb +26 -0
  138. data/test/unit/plugins/presenter_test.rb +68 -0
  139. data/test/unit/plugins/validate/inheritance_test.rb +36 -0
  140. data/test/unit/plugins/validate/nested_model_test.rb +40 -0
  141. data/test/unit/plugins/validate/predicates/each_key_each_value_test.rb +34 -0
  142. data/test/unit/plugins/validate/predicates/each_test.rb +33 -0
  143. data/test/unit/plugins/validate/predicates/empty_test.rb +37 -0
  144. data/test/unit/plugins/validate/predicates/even_test.rb +33 -0
  145. data/test/unit/plugins/validate/predicates/excluded_from_test.rb +55 -0
  146. data/test/unit/plugins/validate/predicates/filled_test.rb +49 -0
  147. data/test/unit/plugins/validate/predicates/format_test.rb +28 -0
  148. data/test/unit/plugins/validate/predicates/gt_test.rb +36 -0
  149. data/test/unit/plugins/validate/predicates/gteq_test.rb +36 -0
  150. data/test/unit/plugins/validate/predicates/included_in_test.rb +55 -0
  151. data/test/unit/plugins/validate/predicates/lt_test.rb +36 -0
  152. data/test/unit/plugins/validate/predicates/lteq_test.rb +36 -0
  153. data/test/unit/plugins/validate/predicates/max_size_test.rb +43 -0
  154. data/test/unit/plugins/validate/predicates/min_size_test.rb +43 -0
  155. data/test/unit/plugins/validate/predicates/none_test.rb +49 -0
  156. data/test/unit/plugins/validate/predicates/odd_test.rb +33 -0
  157. data/test/unit/plugins/validate/predicates/size_range_test.rb +43 -0
  158. data/test/unit/plugins/validate/predicates/size_test.rb +43 -0
  159. data/test/unit/plugins/validate/predicates/type_test.rb +77 -0
  160. data/test/unit/plugins/validate/predicates_test.rb +73 -0
  161. data/test/unit/plugins/validate/validate_bang_test.rb +30 -0
  162. data/test/unit/store_test.rb +15 -0
  163. data/test/unit/stores_test.rb +18 -0
  164. data/wardrobe.gemspec +26 -0
  165. metadata +344 -0
@@ -0,0 +1,78 @@
1
+ require 'test_helper'
2
+
3
+ class DirtyRoot
4
+ include Wardrobe
5
+ plugin :dirty_tracker
6
+ attribute :depth, Integer
7
+ end
8
+
9
+ class DirtyTree
10
+ include Wardrobe
11
+ plugin :dirty_tracker
12
+ attribute :name, String
13
+ attribute :branches, Hash
14
+ attribute :leaves, Array
15
+ attribute :colors, Set
16
+ attribute :root, DirtyRoot
17
+ # TODO: Test sub wardrobe class
18
+ end
19
+
20
+ class DirtyTrackerTest < TestBase
21
+ def setup
22
+ @tree = DirtyTree.new(name: 'CleanTree', branches: {one: 'value'}, leaves: ['one'], colors: ['yellow', 'brown'], root: { depth: 5})
23
+ end
24
+
25
+ def test_string
26
+ assert_equal 'CleanTree', @tree.name
27
+ assert_equal false, @tree._changed?
28
+
29
+ @tree.name = 'DirtyTree'
30
+
31
+ assert_equal 'DirtyTree', @tree.name
32
+ assert_equal true, @tree._changed?
33
+ end
34
+
35
+ def test_array
36
+ assert_equal ['one'], @tree.leaves
37
+ assert_equal false, @tree._changed?
38
+
39
+ @tree.leaves.map(&:upcase)
40
+ assert_equal false, @tree._changed?
41
+
42
+ @tree.leaves.map!(&:upcase)
43
+ assert_equal ['ONE'], @tree.leaves
44
+ assert_equal true, @tree._changed?
45
+
46
+ @tree.leaves << 'two'
47
+ assert_equal ['ONE', 'two'], @tree.leaves
48
+ assert_equal true, @tree._changed?
49
+ end
50
+
51
+ def test_hash
52
+ hash = {one: 'value'}
53
+ assert_equal hash, @tree.branches
54
+ assert_equal false, @tree._changed?
55
+
56
+ @tree.branches[:two] = 'another'
57
+ hash = {one: 'value', two: 'another'}
58
+ assert_equal hash, @tree.branches
59
+ assert_equal true, @tree._changed?
60
+ end
61
+
62
+ def test_set
63
+ assert_equal Set.new(['yellow', 'brown']), @tree.colors
64
+ assert_equal false, @tree._changed?
65
+ @tree.colors.add('yellow')
66
+ assert_equal false, @tree._changed?
67
+ @tree.colors.add('blue')
68
+ assert_equal true, @tree._changed?
69
+ end
70
+
71
+ def test_sub_model
72
+ assert_equal 5, @tree.root.depth
73
+ assert_equal false, @tree._changed?
74
+ @tree.root.depth = 3
75
+ assert_equal true, @tree.root._changed?
76
+ assert_equal true, @tree._changed?
77
+ end
78
+ end
@@ -0,0 +1,36 @@
1
+ require 'test_helper'
2
+
3
+ class EqualityTest < TestBase
4
+ class Person
5
+ include Wardrobe
6
+ plugin :equality
7
+ attribute :name, String
8
+ attribute :age, Integer, include_in_equality: false
9
+ end
10
+
11
+ class Alien
12
+ include Wardrobe
13
+ attribute :name, String
14
+ end
15
+
16
+ def setup
17
+ @alien_1 = Alien.new(name: 'Rudolf')
18
+ @alien_2 = Alien.new(name: 'Santa')
19
+ @alien_3 = Alien.new(name: 'Rudolf')
20
+ @person_1 = Person.new(name: 'Santa', age: 435)
21
+ @person_2 = Person.new(name: 'Rudolf', age: 1)
22
+ @person_3 = Person.new(name: 'Santa', age: 56)
23
+ end
24
+
25
+ def test_aliens
26
+ refute @alien_1 == @alien_2
27
+ refute @alien_2 == @alien_3
28
+ refute @alien_3 == @alien_1
29
+ end
30
+
31
+ def test_people
32
+ refute @person_1 == @person_2
33
+ refute @person_2 == @person_3
34
+ assert @person_1 == @person_3
35
+ end
36
+ end
@@ -0,0 +1,19 @@
1
+ require 'test_helper'
2
+
3
+ class HtmlInitializerTest < TestBase
4
+ class Article
5
+ include Wardrobe
6
+ plugin :html_initializer
7
+ attribute :title, String, html_selector: proc { |doc| doc.at_xpath('//div/h1')&.text }
8
+ end
9
+
10
+ def setup
11
+ @article_html = Article.new('<html><div><h1>Html</h1></div></html>')
12
+ @article_hash = Article.new(title: 'Hash')
13
+ end
14
+
15
+ def test_html_parsing
16
+ assert_equal 'Html', @article_html.title
17
+ assert_equal 'Hash', @article_hash.title
18
+ end
19
+ end
@@ -0,0 +1,149 @@
1
+ require 'test_helper'
2
+
3
+ class ImmutableTest < TestBase
4
+ class Person
5
+ include Wardrobe
6
+ attribute :name, String
7
+ end
8
+
9
+ class ImmutableClass
10
+ include Wardrobe
11
+ plugin :immutable
12
+ attribute :string, String
13
+ attribute :hash, Hash
14
+ attribute :array, Array
15
+ attribute :array_of_people, Array[Person]
16
+ end
17
+
18
+ def setup
19
+ @object = ImmutableClass.new(
20
+ string: 'Clean',
21
+ hash: { one: 'value' },
22
+ array: [
23
+ 'one'
24
+ ],
25
+ array_of_people: [
26
+ { name: 'Person 1' }
27
+ ]
28
+ )
29
+ end
30
+
31
+ def test_setter_no_method_error
32
+ assert_raises(NoMethodError) do
33
+ @object.string = 'Changed'
34
+ end
35
+ end
36
+
37
+ def test_immutable_hash_raises_error
38
+ assert_raises(RuntimeError) do
39
+ @object.hash[:two] = 'another_value'
40
+ end
41
+ end
42
+
43
+ def test_immutable_array_raises_error
44
+ assert_raises(RuntimeError) do
45
+ @object.array << 'two'
46
+ end
47
+ end
48
+
49
+ def test_child_wardrobe_object_raises_error
50
+ assert_raises(RuntimeError) do
51
+ @object.array_of_people.first.name = 'Person 2'
52
+ end
53
+ end
54
+
55
+ def test_instance_frozen
56
+ assert @object.frozen?
57
+ end
58
+
59
+ def mutate_test
60
+ @mutated_object = yield
61
+ refute_equal @mutated_object.object_id, @object.object_id
62
+ end
63
+
64
+ def test_immutable_args_only_changes_given_pairs
65
+ mutate_test do
66
+ @object.mutate(string: 'Changed')
67
+ end
68
+ assert_equal @object.array, @mutated_object.array
69
+ end
70
+
71
+ def test_immutable_string_args
72
+ mutate_test do
73
+ @object.mutate(string: 'Changed')
74
+ end
75
+ assert_equal 'Clean', @object.string
76
+ assert_equal 'Changed', @mutated_object.string
77
+ end
78
+
79
+ def test_immutable_string_block
80
+ mutate_test do
81
+ @object.mutate do |o|
82
+ o.string = 'Changed'
83
+ end
84
+ end
85
+ assert_equal 'Changed', @mutated_object.string
86
+ assert_equal 'Clean', @object.string
87
+ end
88
+
89
+ def test_immutable_hash_args
90
+ mutate_test do
91
+ @object.mutate(hash: @object.hash.merge(added: 'key'))
92
+ end
93
+ assert_equal({ one: 'value', added: 'key' }, @mutated_object.hash)
94
+ assert_equal({ one: 'value' }, @object.hash)
95
+ assert_raises(RuntimeError) { @mutated_object.hash[:should] = 'fail' }
96
+ assert_raises(RuntimeError) { @object.hash[:should] = 'fail' }
97
+ end
98
+
99
+ def test_immutable_hash_block
100
+ mutate_test do
101
+ @object.mutate do |o|
102
+ o.hash[:added] = 'key'
103
+ end
104
+ end
105
+ assert_equal({ one: 'value', added: 'key' }, @mutated_object.hash)
106
+ assert_equal({ one: 'value' }, @object.hash)
107
+ assert_raises(RuntimeError) { @mutated_object.hash[:should] = 'fail' }
108
+ assert_raises(RuntimeError) { @object.hash[:should] = 'fail' }
109
+ end
110
+
111
+ def test_immutable_array_args
112
+ mutate_test do
113
+ @object.mutate(array: @object.array + ['added element'])
114
+ end
115
+ assert_equal(['one', 'added element'], @mutated_object.array)
116
+ assert_equal(['one'], @object.array)
117
+ assert_raises(RuntimeError) { @mutated_object.array << 'Should fail' }
118
+ assert_raises(RuntimeError) { @object.array << 'Should fail' }
119
+ end
120
+
121
+ def test_immutable_array_block
122
+ mutate_test do
123
+ @object.mutate do |o|
124
+ o.array << 'added element'
125
+ end
126
+ end
127
+ assert_equal(['one', 'added element'], @mutated_object.array)
128
+ assert_equal(['one'], @object.array)
129
+ assert_raises(RuntimeError) { @mutated_object.array << 'Should fail' }
130
+ assert_raises(RuntimeError) { @object.array << 'Should fail' }
131
+ end
132
+
133
+ def test_mutate_block
134
+ new_object = @object.mutate do |o|
135
+ o.string = 'In Mutate Block'
136
+ o.array << 'Another Leave'
137
+ o.hash[:added_key] = 'From mutate block'
138
+ o.array_of_people.first.name = 'Changed child instance name'
139
+ o.array_of_people << { name: 'Added friend in mutate block' }
140
+ end
141
+ assert @object.frozen?
142
+ assert @object.array_of_people.frozen?
143
+ assert_equal 2, new_object.array.count
144
+ assert new_object.frozen?
145
+ assert new_object.array_of_people.frozen?
146
+ assert_equal 2, new_object.array_of_people.count
147
+ refute new_object.array_of_people.instance_variable_defined?(:@_mutating)
148
+ end
149
+ end
@@ -0,0 +1,57 @@
1
+ require 'test_helper'
2
+
3
+ class IvyPresenterTest < TestBase
4
+ class Article
5
+ include Wardrobe
6
+ plugin :presenter
7
+ plugin :ivy_presenter
8
+ attributes source: true do
9
+ attribute :id, Integer
10
+ preset :one do
11
+ attribute :title, String
12
+ attribute :author, String
13
+ preset :two do
14
+ attribute :body, String
15
+ end
16
+ end
17
+ source false do
18
+ attribute :body_text, String
19
+ end
20
+ end
21
+
22
+ def body_text
23
+ 'Lorem ipsum...'
24
+ end
25
+ end
26
+
27
+
28
+ def setup
29
+ @article = Article.new(
30
+ id: 1,
31
+ title: 'Article One',
32
+ author: 'Test Tester',
33
+ body: '<p>Lorem ipsum...</p>'
34
+ )
35
+ end
36
+
37
+ def test_preset_one
38
+ result = @article._ivy_present(preset: :one)
39
+ assert_equal 3, result.keys.length
40
+ end
41
+
42
+ def test_preset_two
43
+ result = @article._ivy_present(preset: :two)
44
+ assert_equal 1, result.keys.length
45
+ end
46
+
47
+ def test_source_true
48
+ result = @article._ivy_present(source: true)
49
+ assert_equal 4, result.keys.length
50
+ end
51
+
52
+ def test_source_false
53
+ result = @article._ivy_present(source: false)
54
+ assert_equal 'Lorem ipsum...', result[:body_text]
55
+ assert_equal 1, result.keys.length
56
+ end
57
+ end
@@ -0,0 +1,67 @@
1
+ require 'test_helper'
2
+
3
+ class JsonInitializerTest < TestBase
4
+ class Article
5
+ include Wardrobe
6
+ plugin :json_initializer
7
+ attribute :title, String
8
+ end
9
+
10
+ def setup
11
+ if Wardrobe::Plugins::JsonInitializer.instance_variable_defined?(:@parser)
12
+ Wardrobe::Plugins::JsonInitializer.remove_instance_variable(:@parser)
13
+ end
14
+ end
15
+
16
+ def initiate_articles
17
+ @article_json = Article.new('{"title":"Json"}')
18
+ @article_hash = Article.new(title: 'Hash')
19
+ end
20
+
21
+ def do_in_child
22
+ read, write = IO.pipe
23
+
24
+ pid = fork do
25
+ read.close
26
+ result = yield
27
+ Marshal.dump(result, write)
28
+ exit!(0)
29
+ end
30
+
31
+ write.close
32
+ result = read.read
33
+ Process.wait(pid)
34
+ raise 'child failed' if result.empty?
35
+ Marshal.load(result)
36
+ end
37
+
38
+ def test_multi_json_loaded
39
+ res = do_in_child do
40
+ require 'multi_json'
41
+ assert_equal MultiJson, Wardrobe::Plugins::JsonInitializer.parser
42
+ initiate_articles
43
+ {
44
+ json: @article_json.title,
45
+ hash: @article_hash.title
46
+ }
47
+ end
48
+
49
+ assert_equal 'Json', res[:json]
50
+ assert_equal 'Hash', res[:hash]
51
+ end
52
+
53
+ def test_json_loaded
54
+ res = do_in_child do
55
+ require 'json'
56
+ assert_equal JSON, Wardrobe::Plugins::JsonInitializer.parser
57
+ initiate_articles
58
+ {
59
+ json: @article_json.title,
60
+ hash: @article_hash.title
61
+ }
62
+ end
63
+
64
+ assert_equal 'Json', res[:json]
65
+ assert_equal 'Hash', res[:hash]
66
+ end
67
+ end
@@ -0,0 +1,39 @@
1
+ require 'test_helper'
2
+
3
+ class NilIfEmptyTest < TestBase
4
+ class Tree
5
+ include Wardrobe
6
+ plugin :nil_if_empty
7
+ attribute :name, String, nil_if_empty: true
8
+ attribute :branches, Hash, nil_if_empty: true
9
+ attribute :leaves, Array, nil_if_empty: true
10
+ end
11
+
12
+ class TreeFalse
13
+ include Wardrobe
14
+ plugin :nil_if_empty
15
+ attribute :name, String, nil_if_empty: false
16
+ attribute :branches, Hash, nil_if_empty: false
17
+ attribute :leaves, Array, nil_if_empty: false
18
+ end
19
+
20
+ def setup
21
+ @tree = Tree.new(name: '', branches: {}, leaves: [])
22
+ @tree_false = TreeFalse.new(name: '', branches: {}, leaves: [])
23
+ end
24
+
25
+ def test_string
26
+ assert_nil @tree.name
27
+ assert_equal '', @tree_false.name
28
+ end
29
+
30
+ def test_hash
31
+ assert_nil @tree.branches
32
+ assert_equal Hash.new, @tree_false.branches
33
+ end
34
+
35
+ def test_array
36
+ assert_nil @tree.leaves
37
+ assert_equal [], @tree_false.leaves
38
+ end
39
+ end
@@ -0,0 +1,26 @@
1
+ require 'test_helper'
2
+
3
+ class Row
4
+ include Wardrobe
5
+ plugin :nil_if_zero
6
+
7
+ attributes do
8
+ nil_if_zero do
9
+ attribute :test_in_block, Integer
10
+ end
11
+ end
12
+ attribute :some_relation_id, Integer, nil_if_zero: true
13
+ attribute :some_other_relation_id, Integer, nil_if_zero: false
14
+ end
15
+
16
+ class NilIfZeroTest < TestBase
17
+ def setup
18
+ @row = Row.new(some_relation_id: 0, some_other_relation_id: 0, test_in_block: 0)
19
+ end
20
+
21
+ def test_default_literal
22
+ assert_nil @row.some_relation_id
23
+ assert_equal 0, @row.some_other_relation_id
24
+ assert_nil @row.test_in_block
25
+ end
26
+ end
@@ -0,0 +1,68 @@
1
+ require 'test_helper'
2
+ class PresenterTest < TestBase
3
+ class Address
4
+ include Wardrobe
5
+ plugin :presenter
6
+ attribute :zip_code, String
7
+ attribute :street, String
8
+ attribute :time, Time
9
+ end
10
+
11
+ class User
12
+ include Wardrobe
13
+ plugin :presenter, time_formatter: proc { |input| input.utc.iso8601 }
14
+ attribute :name, String
15
+ attribute :email, String
16
+ attribute :address, Address
17
+ attribute :password, String
18
+ attribute :status, Symbol
19
+ attribute :data, Hash
20
+ attribute :created, Time
21
+ attribute :friends, Array[User]
22
+ end
23
+
24
+ class WithoutTimeFormatter
25
+ include Wardrobe
26
+ plugin :presenter
27
+ attribute :created, Time
28
+ end
29
+
30
+ def setup
31
+ @time = Time.now - 60
32
+ @user = User.new(
33
+ name: 'Test Person',
34
+ email: 'user@example.com',
35
+ address: { zip_code: '1234', street: 'No Where Street' },
36
+ status: :open,
37
+ friends: [{ name: 'Friend One' }],
38
+ created: @time.to_s,
39
+ data: {
40
+ a: :b
41
+ }
42
+ )
43
+ end
44
+
45
+ def test_types
46
+ result = @user._present
47
+ assert_equal 'Friend One', result[:friends].first[:name]
48
+ assert_equal 'Test Person', result[:name]
49
+ assert_equal 'user@example.com', result[:email]
50
+ assert_equal '1234', result[:address][:zip_code]
51
+ assert_equal :open, result[:status]
52
+ assert_equal @time.utc.iso8601, result[:created]
53
+ assert_equal({a: :b}, result[:data])
54
+ end
55
+
56
+ def test_selection
57
+ result = @user._present(attributes: { name: nil, address: { street: nil }})
58
+ assert_equal 'Test Person', result[:name]
59
+ assert_equal 'No Where Street', result[:address][:street]
60
+ assert_nil result[:address][:zip_code]
61
+ assert_nil result[:address][:status]
62
+ end
63
+
64
+ def test_without_time_formater
65
+ result = WithoutTimeFormatter.new(created: @time.to_s)._present
66
+ assert_equal @time.to_s, result[:created]
67
+ end
68
+ end
@@ -0,0 +1,36 @@
1
+ require 'test_helper'
2
+
3
+ module ValidateMixin
4
+ include Wardrobe
5
+ plugin :validation
6
+ attribute :name, String, validates: { in: %w(Two Words) }
7
+ end
8
+
9
+ class KlassOne
10
+ include ValidateMixin
11
+ end
12
+
13
+ class KlassTwo
14
+ include ValidateMixin
15
+ attribute :name, String, validates: { length: 10..100 }
16
+ attribute :name1, String, validates: { length: 10..100 }
17
+ end
18
+
19
+ class KlassThree < KlassTwo
20
+ attributes do
21
+ validates match: /$[A-Z]+^/ do
22
+ attribute :name, String
23
+ end
24
+ end
25
+ end
26
+
27
+ class InheritanceTest < TestBase
28
+ def test_inheritance
29
+ instance = KlassOne.new(name: 'Lorem')
30
+ assert_equal [:in], instance._attribute_store.name.options[:validates].keys
31
+ instance = KlassTwo.new(name: 'Lorem')
32
+ assert_equal [:in, :length], instance._attribute_store.name.options[:validates].keys
33
+ instance = KlassThree.new(name: 'Lorem')
34
+ assert_equal [:in, :length, :match], instance._attribute_store.name.options[:validates].keys
35
+ end
36
+ end
@@ -0,0 +1,40 @@
1
+ require 'test_helper'
2
+
3
+ class ValidationNestedModelTest < TestBase
4
+ class FooWithValidation
5
+ include Wardrobe
6
+ plugin :validation
7
+ attribute :name, String, validates { size?(1) }
8
+ end
9
+
10
+ class FooWithoutValidation
11
+ include Wardrobe
12
+ attribute :name, String
13
+ end
14
+
15
+ class Bar
16
+ include Wardrobe
17
+ plugin :validation
18
+ attribute :name, String, validates { size?(1) }
19
+ attribute :foo_with, FooWithValidation
20
+ attribute :foo_without, FooWithoutValidation
21
+ end
22
+
23
+ def test_nested_models
24
+ errors = Bar.new(
25
+ name: 'Bar With Validation',
26
+ foo_with: {
27
+ name: 'Foo With Validation'
28
+ },
29
+ foo_without: {
30
+ name: 'Foo Without Validation'
31
+ }
32
+ )._validation_errors
33
+
34
+ assert_equal 2, errors.length
35
+ assert_equal ['size must be 1'], errors[:name]
36
+ assert_equal ['size must be 1'], errors[:foo_with][:name]
37
+ assert_equal 1, log_messages.length
38
+ refute errors.has_key?(:foo_without)
39
+ end
40
+ end
@@ -0,0 +1,34 @@
1
+ require 'test_helper'
2
+
3
+ class ValidationPredicatesEachKeyTest < MiniTest::Test
4
+ class Foo
5
+ include Wardrobe
6
+ plugin :validation
7
+ attribute :simple, Hash, validates { each_key? { int? } }
8
+ attribute :advanced, Hash, validates { array? & min_size?(4) & each_key? { int? } & each_value? { sym? } }
9
+ end
10
+
11
+ def test_nil
12
+ errors = Foo.new(
13
+ simple: nil,
14
+ advanced: nil
15
+ )._validation_errors
16
+
17
+ refute errors.has_key?(:simple)
18
+ assert_equal ['must be a Array', 'size cannot be less than 4'], errors[:advanced]
19
+ end
20
+
21
+ def test_with_content
22
+ errors = Foo.new(
23
+ simple: { one: 1, two: 2 },
24
+ advanced: { one: 1, two: 2 }
25
+ )._validation_errors
26
+
27
+ assert_equal 1, errors[:simple].length
28
+ assert_equal 3, errors[:advanced].length
29
+ assert_equal ['key must be a Integer'], errors[:simple].first[:one]
30
+ assert_equal ['key must be a Integer', 'value must be a Symbol'], errors[:advanced].first[:one]
31
+ assert_equal 'must be a Array', errors[:advanced][1]
32
+ assert_equal 'size cannot be less than 4', errors[:advanced].last
33
+ end
34
+ end
@@ -0,0 +1,33 @@
1
+ require 'test_helper'
2
+
3
+ class ValidationPredicatesEachTest < MiniTest::Test
4
+ class Foo
5
+ include Wardrobe
6
+ plugin :validation
7
+ attribute :simple, Array, validates { each? { int? } }
8
+ attribute :advanced, Array, validates { array? & min_size?(4) & each? { int? & min_size?(4) } }
9
+ end
10
+
11
+ def test_nil
12
+ errors = Foo.new(
13
+ simple: nil,
14
+ advanced: nil
15
+ )._validation_errors
16
+
17
+ refute errors.has_key?(:simple)
18
+ assert_equal ['size cannot be less than 4'], errors[:advanced]
19
+ end
20
+
21
+ def test_with_content
22
+ errors = Foo.new(
23
+ simple: ['1','2'],
24
+ advanced: ['1', '2']
25
+ )._validation_errors
26
+
27
+ assert_equal 1, errors[:simple].length
28
+ assert_equal 2, errors[:advanced].length
29
+ assert_equal ['must be a Integer'], errors[:simple].first[0]
30
+ assert_equal ['must be a Integer', 'size cannot be less than 4'], errors[:advanced].first[0]
31
+ assert_equal 'size cannot be less than 4', errors[:advanced].last
32
+ end
33
+ end