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