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