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.
- checksums.yaml +7 -0
- data/.codeclimate.yml +10 -0
- data/.gitignore +19 -0
- data/.ruby-version +1 -0
- data/.travis.yml +11 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +18 -0
- data/Guardfile +42 -0
- data/LICENSE +19 -0
- data/README.md +227 -0
- data/Rakefile +20 -0
- data/examples/new_york_times_article.rb +55 -0
- data/lib/wardrobe/attribute.rb +76 -0
- data/lib/wardrobe/attribute_store.rb +16 -0
- data/lib/wardrobe/block_setup.rb +124 -0
- data/lib/wardrobe/boolean.rb +6 -0
- data/lib/wardrobe/class_methods.rb +127 -0
- data/lib/wardrobe/getter_setter.rb +48 -0
- data/lib/wardrobe/instance_methods.rb +56 -0
- data/lib/wardrobe/module_methods.rb +51 -0
- data/lib/wardrobe/option.rb +30 -0
- data/lib/wardrobe/option_store.rb +22 -0
- data/lib/wardrobe/plugin.rb +39 -0
- data/lib/wardrobe/plugin_store.rb +28 -0
- data/lib/wardrobe/plugins/alias_setters.rb +35 -0
- data/lib/wardrobe/plugins/coercible/refinements/array.rb +63 -0
- data/lib/wardrobe/plugins/coercible/refinements/boolean.rb +36 -0
- data/lib/wardrobe/plugins/coercible/refinements/date.rb +31 -0
- data/lib/wardrobe/plugins/coercible/refinements/date_time.rb +29 -0
- data/lib/wardrobe/plugins/coercible/refinements/float.rb +23 -0
- data/lib/wardrobe/plugins/coercible/refinements/hash.rb +65 -0
- data/lib/wardrobe/plugins/coercible/refinements/integer.rb +23 -0
- data/lib/wardrobe/plugins/coercible/refinements/object.rb +15 -0
- data/lib/wardrobe/plugins/coercible/refinements/set.rb +33 -0
- data/lib/wardrobe/plugins/coercible/refinements/string.rb +21 -0
- data/lib/wardrobe/plugins/coercible/refinements/symbol.rb +21 -0
- data/lib/wardrobe/plugins/coercible/refinements/time.rb +30 -0
- data/lib/wardrobe/plugins/coercible/refinements/unsupported_error.rb +11 -0
- data/lib/wardrobe/plugins/coercible.rb +52 -0
- data/lib/wardrobe/plugins/configurable/configurable_store.rb +26 -0
- data/lib/wardrobe/plugins/configurable.rb +40 -0
- data/lib/wardrobe/plugins/default.rb +33 -0
- data/lib/wardrobe/plugins/dirty_tracker.rb +66 -0
- data/lib/wardrobe/plugins/equality.rb +19 -0
- data/lib/wardrobe/plugins/html_initializer.rb +38 -0
- data/lib/wardrobe/plugins/immutable.rb +164 -0
- data/lib/wardrobe/plugins/ivy_presenter.rb +42 -0
- data/lib/wardrobe/plugins/json_initializer.rb +41 -0
- data/lib/wardrobe/plugins/nil_if_empty.rb +27 -0
- data/lib/wardrobe/plugins/nil_if_zero.rb +19 -0
- data/lib/wardrobe/plugins/optional_getter.rb +21 -0
- data/lib/wardrobe/plugins/optional_setter.rb +24 -0
- data/lib/wardrobe/plugins/presenter/refinements/array.rb +15 -0
- data/lib/wardrobe/plugins/presenter/refinements/hash.rb +15 -0
- data/lib/wardrobe/plugins/presenter/refinements/object.rb +15 -0
- data/lib/wardrobe/plugins/presenter/refinements/time.rb +19 -0
- data/lib/wardrobe/plugins/presenter/refinements.rb +6 -0
- data/lib/wardrobe/plugins/presenter.rb +25 -0
- data/lib/wardrobe/plugins/validation/block_handler.rb +83 -0
- data/lib/wardrobe/plugins/validation/class_methods.rb +13 -0
- data/lib/wardrobe/plugins/validation/deep_merge.rb +27 -0
- data/lib/wardrobe/plugins/validation/error_store.rb +27 -0
- data/lib/wardrobe/plugins/validation/instance_methods.rb +39 -0
- data/lib/wardrobe/plugins/validation/refinements/_size.rb +30 -0
- data/lib/wardrobe/plugins/validation/refinements/array.rb +26 -0
- data/lib/wardrobe/plugins/validation/refinements/date.rb +15 -0
- data/lib/wardrobe/plugins/validation/refinements/hash.rb +27 -0
- data/lib/wardrobe/plugins/validation/refinements/integer.rb +21 -0
- data/lib/wardrobe/plugins/validation/refinements/nil_class.rb +19 -0
- data/lib/wardrobe/plugins/validation/refinements/numeric.rb +31 -0
- data/lib/wardrobe/plugins/validation/refinements/object.rb +35 -0
- data/lib/wardrobe/plugins/validation/refinements/set.rb +25 -0
- data/lib/wardrobe/plugins/validation/refinements/string.rb +55 -0
- data/lib/wardrobe/plugins/validation/refinements/symbol.rb +26 -0
- data/lib/wardrobe/plugins/validation/refinements.rb +13 -0
- data/lib/wardrobe/plugins/validation/validation.rb +63 -0
- data/lib/wardrobe/plugins/validation/validation_error.rb +19 -0
- data/lib/wardrobe/plugins/validation/validaton_runner.rb +38 -0
- data/lib/wardrobe/plugins/validation/validator.rb +119 -0
- data/lib/wardrobe/plugins/validation.rb +28 -0
- data/lib/wardrobe/root_config.rb +31 -0
- data/lib/wardrobe/store.rb +62 -0
- data/lib/wardrobe/stores.rb +106 -0
- data/lib/wardrobe/version.rb +5 -0
- data/lib/wardrobe.rb +34 -0
- data/sandbox/Gemfile +5 -0
- data/sandbox/Gemfile.lock +52 -0
- data/sandbox/bench_mutable_coercion.rb +91 -0
- data/sandbox/bench_test_1.rb +50 -0
- data/sandbox/bench_test_2.rb +48 -0
- data/sandbox/bench_test_3.rb +92 -0
- data/sandbox/cnn_article_find.rb +20 -0
- data/sandbox/define_method_procs.rb +139 -0
- data/sandbox/hanami_validations.rb +40 -0
- data/sandbox/middleware_bench_test.rb +97 -0
- data/sandbox/middleware_bench_v2_test.rb +130 -0
- data/test/assertions.rb +22 -0
- data/test/test_helper.rb +37 -0
- data/test/unit/atrs_config_test.rb +33 -0
- data/test/unit/atrs_root_module_test.rb +19 -0
- data/test/unit/attribute_test.rb +44 -0
- data/test/unit/block_runner/array_test.rb +29 -0
- data/test/unit/block_setup_test.rb +41 -0
- data/test/unit/class_methods_test.rb +92 -0
- data/test/unit/create_class_from_hash_test.rb +28 -0
- data/test/unit/define_getter_test.rb +94 -0
- data/test/unit/define_setter_test.rb +0 -0
- data/test/unit/disable_coercion_test.rb +19 -0
- data/test/unit/inheritance_composition_test.rb +36 -0
- data/test/unit/method_override_test.rb +18 -0
- data/test/unit/method_polution_test.rb +48 -0
- data/test/unit/option_test.rb +17 -0
- data/test/unit/plugin_test.rb +12 -0
- data/test/unit/plugins/alias_setters_test.rb +24 -0
- data/test/unit/plugins/coercible/array_test.rb +79 -0
- data/test/unit/plugins/coercible/boolean_test.rb +68 -0
- data/test/unit/plugins/coercible/custom_class_test.rb +61 -0
- data/test/unit/plugins/coercible/date_test.rb +38 -0
- data/test/unit/plugins/coercible/date_time_test.rb +44 -0
- data/test/unit/plugins/coercible/float_test.rb +42 -0
- data/test/unit/plugins/coercible/hash_test.rb +62 -0
- data/test/unit/plugins/coercible/integer_test.rb +42 -0
- data/test/unit/plugins/coercible/nested_wardrobe_test.rb +63 -0
- data/test/unit/plugins/coercible/set_test.rb +49 -0
- data/test/unit/plugins/coercible/string_test.rb +36 -0
- data/test/unit/plugins/coercible/symbol_test.rb +30 -0
- data/test/unit/plugins/coercible/time_test.rb +43 -0
- data/test/unit/plugins/configurable_test.rb +64 -0
- data/test/unit/plugins/default_value_test.rb +78 -0
- data/test/unit/plugins/dirty_tracker_test.rb +78 -0
- data/test/unit/plugins/equality_test.rb +36 -0
- data/test/unit/plugins/html_initializer_test.rb +19 -0
- data/test/unit/plugins/immutable_test.rb +149 -0
- data/test/unit/plugins/ivy_presenter_test.rb +57 -0
- data/test/unit/plugins/json_initializer_test.rb +67 -0
- data/test/unit/plugins/nil_if_empty_test.rb +39 -0
- data/test/unit/plugins/nil_if_zero_test.rb +26 -0
- data/test/unit/plugins/presenter_test.rb +68 -0
- data/test/unit/plugins/validate/inheritance_test.rb +36 -0
- data/test/unit/plugins/validate/nested_model_test.rb +40 -0
- data/test/unit/plugins/validate/predicates/each_key_each_value_test.rb +34 -0
- data/test/unit/plugins/validate/predicates/each_test.rb +33 -0
- data/test/unit/plugins/validate/predicates/empty_test.rb +37 -0
- data/test/unit/plugins/validate/predicates/even_test.rb +33 -0
- data/test/unit/plugins/validate/predicates/excluded_from_test.rb +55 -0
- data/test/unit/plugins/validate/predicates/filled_test.rb +49 -0
- data/test/unit/plugins/validate/predicates/format_test.rb +28 -0
- data/test/unit/plugins/validate/predicates/gt_test.rb +36 -0
- data/test/unit/plugins/validate/predicates/gteq_test.rb +36 -0
- data/test/unit/plugins/validate/predicates/included_in_test.rb +55 -0
- data/test/unit/plugins/validate/predicates/lt_test.rb +36 -0
- data/test/unit/plugins/validate/predicates/lteq_test.rb +36 -0
- data/test/unit/plugins/validate/predicates/max_size_test.rb +43 -0
- data/test/unit/plugins/validate/predicates/min_size_test.rb +43 -0
- data/test/unit/plugins/validate/predicates/none_test.rb +49 -0
- data/test/unit/plugins/validate/predicates/odd_test.rb +33 -0
- data/test/unit/plugins/validate/predicates/size_range_test.rb +43 -0
- data/test/unit/plugins/validate/predicates/size_test.rb +43 -0
- data/test/unit/plugins/validate/predicates/type_test.rb +77 -0
- data/test/unit/plugins/validate/predicates_test.rb +73 -0
- data/test/unit/plugins/validate/validate_bang_test.rb +30 -0
- data/test/unit/store_test.rb +15 -0
- data/test/unit/stores_test.rb +18 -0
- data/wardrobe.gemspec +26 -0
- 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
|