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