rollback some stuff to reset my brain a bit
[gitmo/MooseX-Types-Structured.git] / t / 02-constraints.t
1 BEGIN {
2         use strict;
3         use warnings;
4         use Test::More tests=>47;
5         use Test::Exception;
6 }
7
8 {
9     package Test::MooseX::Meta::TypeConstraint::Structured;
10
11     use Moose;
12     use MooseX::Types::Structured qw(Tuple Dict Optional);
13         use MooseX::Types::Moose qw(Int Str Object ArrayRef HashRef Maybe);
14         use MooseX::Types -declare => [qw(MyString)];
15         use Moose::Util::TypeConstraints;
16
17     subtype MyString,
18      as 'Str',
19      where { $_=~m/abc/};
20
21     has 'tuple' => (is=>'rw', isa=>Tuple[Int, Str, MyString]);
22     has 'dict' => (is=>'rw', isa=>Dict[name=>Str, age=>Int]);
23     has 'dict_with_maybe' => (is=>'rw', isa=>Dict[name=>Str, age=>Maybe[Int]]); 
24         has 'tuple_with_param' => (is=>'rw', isa=>Tuple[Int, Str, ArrayRef[Int]]);
25         has 'tuple_with_maybe' => (is=>'rw', isa=>Tuple[Int, Str, Maybe[Int]]);
26         has 'dict_with_tuple' => (is=>'rw', isa=>Dict[key1=>Str, key2=>Tuple[Int,Str]]);
27     has 'optional_tuple' => (is=>'rw', isa=>Tuple[Int, Int, Optional[Int]] );
28     has 'optional_dict' => (is=>'rw', isa=>Dict[key1=>Int, Optional[key2=>Int]] );
29     has 'dict_with_tuple_with_union' => (is=>'rw', isa=>Dict[key1=>Str|Object, key2=>Tuple[Int,Str|Object]] );
30         
31     has 'crazy' => (
32         is=>'rw',
33         isa=>Tuple
34             ## First ArrayRef Arg is the required type constraints for the top
35             ## level Tuple.
36             [
37                 Int,
38                 MyString,
39                 ## The third required element is a Dict type constraint, which
40                 ## itself has two required keys and a third optional key.
41                 Dict[name=>Str,age=>Int, Optional[visits=>Int]],
42                 Optional[
43                     Int,
44                     ## This Tuple has one required type constraint and two optional.
45                     Tuple[Int, Optional[Int,HashRef]],                    
46                 ],
47             ],      
48     );
49 }
50
51 ## Instantiate a new test object
52
53 ok my $record = Test::MooseX::Meta::TypeConstraint::Structured->new
54  => 'Instantiated new Record test class.';
55  
56 isa_ok $record => 'Test::MooseX::Meta::TypeConstraint::Structured'
57  => 'Created correct object type.';
58  
59 ## Test crazy
60
61 lives_ok sub {
62     $record->crazy([1,'hello.abc.world', {name=>'John', age=>39}]);
63 } => 'Set crazy attribute with no optionals used';
64
65 is_deeply $record->crazy, [1, 'hello.abc.world', {name=>'John', age=>39}]
66  => 'correct values for crazy attributes no optionals';
67  
68 lives_ok sub {
69     $record->crazy([1,'hello.abc.world', {name=>'John', age=>39, visits=>10},10, [1,2,{key=>'value'}]]);
70 } => 'Set crazy attribute with all optionals used';
71
72 is_deeply $record->crazy, [1,'hello.abc.world', {name=>'John', age=>39, visits=>10},10, [1,2,{key=>'value'}]]
73  => 'correct values for crazy attributes all optionals';
74
75 lives_ok sub {
76     $record->crazy([1,'hello.abc.world', {name=>'John', age=>39},10, [1,2]]);
77 } => 'Set crazy attribute with some optionals used';
78
79 throws_ok sub {
80     $record->crazy([1,'hello', 'test.xxx.test']);    
81 }, qr/Validation failed for 'MyString'/
82  => 'Properly failed for bad value in crazy attribute 01';
83
84 throws_ok sub {
85     $record->crazy([1,'hello.abc.world', {notname=>'John', notage=>39}]);    
86 }, qr/Validation failed for 'Str'/
87  => 'Properly failed for bad value in crazy attribute 02';
88  
89 ## Test Tuple type constraint
90
91 lives_ok sub {
92     $record->tuple([1,'hello', 'test.abc.test']);
93 } => 'Set tuple attribute without error';
94
95 is $record->tuple->[0], 1
96  => 'correct set the tuple attribute index 0';
97
98 is $record->tuple->[1], 'hello'
99  => 'correct set the tuple attribute index 1';
100
101 is $record->tuple->[2], 'test.abc.test'
102  => 'correct set the tuple attribute index 2';
103
104 throws_ok sub {
105     $record->tuple([1,'hello', 'test.xxx.test']);    
106 }, qr/Validation failed for 'MyString'/
107  => 'Properly failed for bad value in custom type constraint';
108  
109 throws_ok sub {
110     $record->tuple(['asdasd',2, 'test.abc.test']);      
111 }, qr/Validation failed for 'Int'/
112  => 'Got Expected Error for violating constraints';
113
114 ## Test the Dictionary type constraint
115  
116 lives_ok sub {
117     $record->dict({name=>'frith', age=>23});
118 } => 'Set dict attribute without error';
119
120 is $record->dict->{name}, 'frith'
121  => 'correct set the dict attribute name';
122
123 is $record->dict->{age}, 23
124  => 'correct set the dict attribute age';
125  
126 throws_ok sub {
127     $record->dict({name=>[1,2,3], age=>'sdfsdfsd'});      
128 }, qr/Validation failed for 'Str'/
129  => 'Got Expected Error for bad value in dict';
130
131 ## Test tuple_with_maybe
132
133 lives_ok sub {
134     $record->tuple_with_maybe([1,'hello', 1]);
135 } => 'Set tuple attribute without error';
136
137 throws_ok sub {
138     $record->tuple_with_maybe([1,'hello', 'a']);
139 }, qr/Validation failed for 'Maybe\[Int\]'/
140  => 'Properly failed for bad value parameterized constraint';
141
142 lives_ok sub {
143     $record->tuple_with_maybe([1,'hello']);
144 } => 'Set tuple attribute without error skipping optional parameter';
145
146 ## Test Tuple with parameterized type
147
148 lives_ok sub {
149     $record->tuple_with_param([1,'hello', [1,2,3]]);
150 } => 'Set tuple attribute without error';
151
152 throws_ok sub {
153     $record->tuple_with_param([1,'hello', [qw/a b c/]]);
154 }, qr/Validation failed for 'ArrayRef\[Int\]'/
155  => 'Properly failed for bad value parameterized constraint';
156
157 ## Test dict_with_maybe
158
159 lives_ok sub {
160     $record->dict_with_maybe({name=>'frith', age=>23});
161 } => 'Set dict attribute without error';
162
163 is $record->dict_with_maybe->{name}, 'frith'
164  => 'correct set the dict attribute name';
165
166 is $record->dict_with_maybe->{age}, 23
167  => 'correct set the dict attribute age';
168  
169 throws_ok sub {
170     $record->dict_with_maybe({name=>[1,2,3], age=>'sdfsdfsd'});      
171 }, qr/Validation failed for 'Str'/
172  => 'Got Expected Error for bad value in dict';
173
174 throws_ok sub {
175     $record->dict_with_maybe({age=>30});      
176 }, qr/Validation failed for 'Str'/
177  => 'Got Expected Error for missing named parameter';
178
179 lives_ok sub {
180     $record->dict_with_maybe({name=>'usal'});
181 } => 'Set dict attribute without error, skipping optional';
182
183 ## Test dict_with_tuple
184
185 lives_ok sub {
186     $record->dict_with_tuple({key1=>'Hello', key2=>[1,'World']});
187 } => 'Set tuple attribute without error';
188
189 throws_ok sub {
190     $record->dict_with_tuple({key1=>'Hello', key2=>['World',2]});
191 }, qr/Validation failed for 'Int'/
192  => 'Threw error on bad constraint';
193
194 ## Test optional_tuple
195
196 lives_ok sub {
197     $record->optional_tuple([1,2,3]);
198 } => 'Set tuple attribute with optional bits';
199
200 is_deeply $record->optional_tuple, [1,2,3]
201  => 'correct values set';
202  
203 lives_ok sub {
204     $record->optional_tuple([4,5]);
205 } => 'Set tuple attribute withOUT optional bits';
206
207 is_deeply $record->optional_tuple, [4,5]
208  => 'correct values set again';
209  
210 throws_ok sub {
211     $record->optional_tuple([1,2,'bad']);   
212 }, qr/Validation failed for 'Int'/
213  => 'Properly failed for bad value in optional bit';
214
215 # Test optional_dict
216
217 lives_ok sub {
218     $record->optional_dict({key1=>1,key2=>2});
219 } => 'Set tuple attribute with optional bits';
220
221 is_deeply $record->optional_dict, {key1=>1,key2=>2}
222  => 'correct values set';
223  
224 lives_ok sub {
225     $record->optional_dict({key1=>3});
226 } => 'Set tuple attribute withOUT optional bits';
227
228 is_deeply $record->optional_dict, {key1=>3}
229  => 'correct values set again';
230  
231 throws_ok sub {
232     $record->optional_dict({key1=>1,key2=>'bad'});   
233 }, qr/Validation failed for 'Int'/
234  => 'Properly failed for bad value in optional bit';
235
236
237 ## Test dict_with_tuple_with_union: Dict[key1=>'Str|Object', key2=>Tuple['Int','Str|Object']]
238
239 lives_ok sub {
240     $record->dict_with_tuple_with_union({key1=>'Hello', key2=>[1,'World']});
241 } => 'Set tuple attribute without error';
242
243 throws_ok sub {
244     $record->dict_with_tuple_with_union({key1=>'Hello', key2=>['World',2]});
245 }, qr/Validation failed for 'Int'/
246  => 'Threw error on bad constraint';
247  
248 lives_ok sub {
249     $record->dict_with_tuple_with_union({key1=>$record, key2=>[1,'World']});
250 } => 'Set tuple attribute without error';
251
252 lives_ok sub {
253     $record->dict_with_tuple_with_union({key1=>'Hello', key2=>[1,$record]});
254 } => 'Set tuple attribute without error';
255
256 throws_ok sub {
257     $record->dict_with_tuple_with_union({key1=>1, key2=>['World',2]});
258 }, qr/Validation failed for 'Int'/
259  => 'Threw error on bad constraint';