4 use Test::More tests=>47;
9 package Test::MooseX::Meta::TypeConstraint::Structured;
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;
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]] );
34 ## First ArrayRef Arg is the required type constraints for the top
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]],
44 ## This Tuple has one required type constraint and two optional.
45 Tuple[Int, Optional[Int,HashRef]],
51 ## Instantiate a new test object
53 ok my $record = Test::MooseX::Meta::TypeConstraint::Structured->new
54 => 'Instantiated new Record test class.';
56 isa_ok $record => 'Test::MooseX::Meta::TypeConstraint::Structured'
57 => 'Created correct object type.';
62 $record->crazy([1,'hello.abc.world', {name=>'John', age=>39}]);
63 } => 'Set crazy attribute with no optionals used';
65 is_deeply $record->crazy, [1, 'hello.abc.world', {name=>'John', age=>39}]
66 => 'correct values for crazy attributes no optionals';
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';
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';
76 $record->crazy([1,'hello.abc.world', {name=>'John', age=>39},10, [1,2]]);
77 } => 'Set crazy attribute with some optionals used';
80 $record->crazy([1,'hello', 'test.xxx.test']);
81 }, qr/Validation failed for 'MyString'/
82 => 'Properly failed for bad value in crazy attribute 01';
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';
89 ## Test Tuple type constraint
92 $record->tuple([1,'hello', 'test.abc.test']);
93 } => 'Set tuple attribute without error';
95 is $record->tuple->[0], 1
96 => 'correct set the tuple attribute index 0';
98 is $record->tuple->[1], 'hello'
99 => 'correct set the tuple attribute index 1';
101 is $record->tuple->[2], 'test.abc.test'
102 => 'correct set the tuple attribute index 2';
105 $record->tuple([1,'hello', 'test.xxx.test']);
106 }, qr/Validation failed for 'MyString'/
107 => 'Properly failed for bad value in custom type constraint';
110 $record->tuple(['asdasd',2, 'test.abc.test']);
111 }, qr/Validation failed for 'Int'/
112 => 'Got Expected Error for violating constraints';
114 ## Test the Dictionary type constraint
117 $record->dict({name=>'frith', age=>23});
118 } => 'Set dict attribute without error';
120 is $record->dict->{name}, 'frith'
121 => 'correct set the dict attribute name';
123 is $record->dict->{age}, 23
124 => 'correct set the dict attribute age';
127 $record->dict({name=>[1,2,3], age=>'sdfsdfsd'});
128 }, qr/Validation failed for 'Str'/
129 => 'Got Expected Error for bad value in dict';
131 ## Test tuple_with_maybe
134 $record->tuple_with_maybe([1,'hello', 1]);
135 } => 'Set tuple attribute without error';
138 $record->tuple_with_maybe([1,'hello', 'a']);
139 }, qr/Validation failed for 'Maybe\[Int\]'/
140 => 'Properly failed for bad value parameterized constraint';
143 $record->tuple_with_maybe([1,'hello']);
144 } => 'Set tuple attribute without error skipping optional parameter';
146 ## Test Tuple with parameterized type
149 $record->tuple_with_param([1,'hello', [1,2,3]]);
150 } => 'Set tuple attribute without error';
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';
157 ## Test dict_with_maybe
160 $record->dict_with_maybe({name=>'frith', age=>23});
161 } => 'Set dict attribute without error';
163 is $record->dict_with_maybe->{name}, 'frith'
164 => 'correct set the dict attribute name';
166 is $record->dict_with_maybe->{age}, 23
167 => 'correct set the dict attribute age';
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';
175 $record->dict_with_maybe({age=>30});
176 }, qr/Validation failed for 'Str'/
177 => 'Got Expected Error for missing named parameter';
180 $record->dict_with_maybe({name=>'usal'});
181 } => 'Set dict attribute without error, skipping optional';
183 ## Test dict_with_tuple
186 $record->dict_with_tuple({key1=>'Hello', key2=>[1,'World']});
187 } => 'Set tuple attribute without error';
190 $record->dict_with_tuple({key1=>'Hello', key2=>['World',2]});
191 }, qr/Validation failed for 'Int'/
192 => 'Threw error on bad constraint';
194 ## Test optional_tuple
197 $record->optional_tuple([1,2,3]);
198 } => 'Set tuple attribute with optional bits';
200 is_deeply $record->optional_tuple, [1,2,3]
201 => 'correct values set';
204 $record->optional_tuple([4,5]);
205 } => 'Set tuple attribute withOUT optional bits';
207 is_deeply $record->optional_tuple, [4,5]
208 => 'correct values set again';
211 $record->optional_tuple([1,2,'bad']);
212 }, qr/Validation failed for 'Int'/
213 => 'Properly failed for bad value in optional bit';
218 $record->optional_dict({key1=>1,key2=>2});
219 } => 'Set tuple attribute with optional bits';
221 is_deeply $record->optional_dict, {key1=>1,key2=>2}
222 => 'correct values set';
225 $record->optional_dict({key1=>3});
226 } => 'Set tuple attribute withOUT optional bits';
228 is_deeply $record->optional_dict, {key1=>3}
229 => 'correct values set again';
232 $record->optional_dict({key1=>1,key2=>'bad'});
233 }, qr/Validation failed for 'Int'/
234 => 'Properly failed for bad value in optional bit';
237 ## Test dict_with_tuple_with_union: Dict[key1=>'Str|Object', key2=>Tuple['Int','Str|Object']]
240 $record->dict_with_tuple_with_union({key1=>'Hello', key2=>[1,'World']});
241 } => 'Set tuple attribute without error';
244 $record->dict_with_tuple_with_union({key1=>'Hello', key2=>['World',2]});
245 }, qr/Validation failed for 'Int'/
246 => 'Threw error on bad constraint';
249 $record->dict_with_tuple_with_union({key1=>$record, key2=>[1,'World']});
250 } => 'Set tuple attribute without error';
253 $record->dict_with_tuple_with_union({key1=>'Hello', key2=>[1,$record]});
254 } => 'Set tuple attribute without error';
257 $record->dict_with_tuple_with_union({key1=>1, key2=>['World',2]});
258 }, qr/Validation failed for 'Int'/
259 => 'Threw error on bad constraint';