4 use Test::More tests=>35;
9 package Test::MooseX::Meta::TypeConstraint::Structured;
12 use Moose::Util::TypeConstraints;
13 use MooseX::Meta::TypeConstraint::Structured::Named;
14 use MooseX::Meta::TypeConstraint::Structured::Positional;
21 my ($args, $optional) = @_;
23 my @optional = ref $optional eq 'ARRAY' ? @$optional : ();
25 return MooseX::Meta::TypeConstraint::Structured::Positional->new(
27 parent => find_type_constraint('ArrayRef'),
28 package_defined_in => __PACKAGE__,
30 _normalize_type_constraint($_);
32 optional_signature => [map {
33 _normalize_type_constraint($_);
39 my ($args, $optional) = @_;
41 my %optional = ref $optional eq 'ARRAY' ? @$optional : ();
43 return MooseX::Meta::TypeConstraint::Structured::Named->new(
45 parent => find_type_constraint('HashRef'),
46 package_defined_in => __PACKAGE__,
48 $_ => _normalize_type_constraint($args{$_});
50 optional_signature => {map {
51 $_ => _normalize_type_constraint($optional{$_});
56 sub _normalize_type_constraint {
58 if($tc && blessed $tc && $tc->isa('Moose::Meta::TypeConstraint')) {
61 return Moose::Util::TypeConstraints::find_or_parse_type_constraint($tc);
65 has 'tuple' => (is=>'rw', isa=>Tuple['Int', 'Str', 'MyString']);
66 has 'dict' => (is=>'rw', isa=>Dict[name=>'Str', age=>'Int']);
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]']);
70 has 'dict_with_tuple' => (is=>'rw', isa=>Dict[key1=>'Str', key2=>Tuple['Int','Str']]);
71 has 'optional_tuple' => (is=>'rw', isa=>Tuple(['Int', 'Int'],['Int']) );
72 has 'optional_dict' => (is=>'rw', isa=>Dict([key1=>'Int'],[key2=>'Int']) );
75 ## Instantiate a new test object
77 ok my $record = Test::MooseX::Meta::TypeConstraint::Structured->new
78 => 'Instantiated new Record test class.';
80 isa_ok $record => 'Test::MooseX::Meta::TypeConstraint::Structured'
81 => 'Created correct object type.';
83 ## Test Tuple type constraint
86 $record->tuple([1,'hello', 'test.abc.test']);
87 } => 'Set tuple attribute without error';
89 is $record->tuple->[0], 1
90 => 'correct set the tuple attribute index 0';
92 is $record->tuple->[1], 'hello'
93 => 'correct set the tuple attribute index 1';
95 is $record->tuple->[2], 'test.abc.test'
96 => 'correct set the tuple attribute index 2';
99 $record->tuple([1,'hello', 'test.xxx.test']);
100 }, qr/Validation failed for 'MyString'/
101 => 'Properly failed for bad value in custom type constraint';
104 $record->tuple(['asdasd',2, 'test.abc.test']);
105 }, qr/Validation failed for 'Int'/
106 => 'Got Expected Error for violating constraints';
108 ## Test the Dictionary type constraint
111 $record->dict({name=>'frith', age=>23});
112 } => 'Set dict attribute without error';
114 is $record->dict->{name}, 'frith'
115 => 'correct set the dict attribute name';
117 is $record->dict->{age}, 23
118 => 'correct set the dict attribute age';
121 $record->dict({name=>[1,2,3], age=>'sdfsdfsd'});
122 }, qr/Validation failed for 'Str'/
123 => 'Got Expected Error for bad value in dict';
125 ## Test tuple_with_maybe
128 $record->tuple_with_maybe([1,'hello', 1]);
129 } => 'Set tuple attribute without error';
132 $record->tuple_with_maybe([1,'hello', 'a']);
133 }, qr/Validation failed for 'Maybe\[Int\]'/
134 => 'Properly failed for bad value parameterized constraint';
137 $record->tuple_with_maybe([1,'hello']);
138 } => 'Set tuple attribute without error skipping optional parameter';
140 ## Test Tuple with parameterized type
143 $record->tuple_with_param([1,'hello', [1,2,3]]);
144 } => 'Set tuple attribute without error';
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';
151 ## Test dict_with_maybe
154 $record->dict_with_maybe({name=>'frith', age=>23});
155 } => 'Set dict attribute without error';
157 is $record->dict_with_maybe->{name}, 'frith'
158 => 'correct set the dict attribute name';
160 is $record->dict_with_maybe->{age}, 23
161 => 'correct set the dict attribute age';
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';
169 $record->dict_with_maybe({age=>30});
170 }, qr/Validation failed for 'Str'/
171 => 'Got Expected Error for missing named parameter';
174 $record->dict_with_maybe({name=>'usal'});
175 } => 'Set dict attribute without error, skipping optional';
177 ## Test dict_with_tuple
180 $record->dict_with_tuple({key1=>'Hello', key2=>[1,'World']});
181 } => 'Set tuple attribute without error';
184 $record->dict_with_tuple({key1=>'Hello', key2=>['World',2]});
185 }, qr/Validation failed for 'Int'/
186 => 'Threw error on bad constraint';
188 ## Test optional_tuple
191 $record->optional_tuple([1,2,3]);
192 } => 'Set tuple attribute with optional bits';
194 is_deeply $record->optional_tuple, [1,2,3]
195 => 'correct values set';
198 $record->optional_tuple([4,5]);
199 } => 'Set tuple attribute withOUT optional bits';
201 is_deeply $record->optional_tuple, [4,5]
202 => 'correct values set again';
205 $record->optional_tuple([1,2,'bad']);
206 }, qr/Validation failed for 'Int'/
207 => 'Properly failed for bad value in optional bit';
212 $record->optional_dict({key1=>1,key2=>2});
213 } => 'Set tuple attribute with optional bits';
215 is_deeply $record->optional_dict, {key1=>1,key2=>2}
216 => 'correct values set';
219 $record->optional_dict({key1=>3});
220 } => 'Set tuple attribute withOUT optional bits';
222 is_deeply $record->optional_dict, {key1=>3}
223 => 'correct values set again';
226 $record->optional_dict({key1=>1,key2=>'bad'});
227 }, qr/Validation failed for 'Int'/
228 => 'Properly failed for bad value in optional bit';