4 use Test::More tests=>30;
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 'HASH' ? @$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']) );
74 ## Instantiate a new test object
76 ok my $record = Test::MooseX::Meta::TypeConstraint::Structured->new
77 => 'Instantiated new Record test class.';
79 isa_ok $record => 'Test::MooseX::Meta::TypeConstraint::Structured'
80 => 'Created correct object type.';
82 ## Test Tuple type constraint
85 $record->tuple([1,'hello', 'test.abc.test']);
86 } => 'Set tuple attribute without error';
88 is $record->tuple->[0], 1
89 => 'correct set the tuple attribute index 0';
91 is $record->tuple->[1], 'hello'
92 => 'correct set the tuple attribute index 1';
94 is $record->tuple->[2], 'test.abc.test'
95 => 'correct set the tuple attribute index 2';
98 $record->tuple([1,'hello', 'test.xxx.test']);
99 }, qr/Validation failed for 'MyString'/
100 => 'Properly failed for bad value in custom type constraint';
103 $record->tuple(['asdasd',2, 'test.abc.test']);
104 }, qr/Validation failed for 'Int'/
105 => 'Got Expected Error for violating constraints';
107 ## Test the Dictionary type constraint
110 $record->dict({name=>'frith', age=>23});
111 } => 'Set dict attribute without error';
113 is $record->dict->{name}, 'frith'
114 => 'correct set the dict attribute name';
116 is $record->dict->{age}, 23
117 => 'correct set the dict attribute age';
120 $record->dict({name=>[1,2,3], age=>'sdfsdfsd'});
121 }, qr/Validation failed for 'Str'/
122 => 'Got Expected Error for bad value in dict';
124 ## Test tuple_with_maybe
127 $record->tuple_with_maybe([1,'hello', 1]);
128 } => 'Set tuple attribute without error';
131 $record->tuple_with_maybe([1,'hello', 'a']);
132 }, qr/Validation failed for 'Maybe\[Int\]'/
133 => 'Properly failed for bad value parameterized constraint';
136 $record->tuple_with_maybe([1,'hello']);
137 } => 'Set tuple attribute without error skipping optional parameter';
139 ## Test Tuple with parameterized type
142 $record->tuple_with_param([1,'hello', [1,2,3]]);
143 } => 'Set tuple attribute without error';
146 $record->tuple_with_param([1,'hello', [qw/a b c/]]);
147 }, qr/Validation failed for 'ArrayRef\[Int\]'/
148 => 'Properly failed for bad value parameterized constraint';
150 ## Test dict_with_maybe
153 $record->dict_with_maybe({name=>'frith', age=>23});
154 } => 'Set dict attribute without error';
156 is $record->dict_with_maybe->{name}, 'frith'
157 => 'correct set the dict attribute name';
159 is $record->dict_with_maybe->{age}, 23
160 => 'correct set the dict attribute age';
163 $record->dict_with_maybe({name=>[1,2,3], age=>'sdfsdfsd'});
164 }, qr/Validation failed for 'Str'/
165 => 'Got Expected Error for bad value in dict';
168 $record->dict_with_maybe({age=>30});
169 }, qr/Validation failed for 'Str'/
170 => 'Got Expected Error for missing named parameter';
173 $record->dict_with_maybe({name=>'usal'});
174 } => 'Set dict attribute without error, skipping optional';
176 ## Test dict_with_tuple
179 $record->dict_with_tuple({key1=>'Hello', key2=>[1,'World']});
180 } => 'Set tuple attribute without error';
183 $record->dict_with_tuple({key1=>'Hello', key2=>['World',2]});
184 }, qr/Validation failed for 'Int'/
185 => 'Threw error on bad constraint';
187 ## Test optional_tuple
190 $record->optional_tuple([1,2,3]);
191 } => 'Set tuple attribute with optional bits';
193 is_deeply $record->optional_tuple, [1,2,3]
194 => 'correct values set';
197 $record->optional_tuple([4,5]);
198 } => 'Set tuple attribute withOUT optional bits';
200 is_deeply $record->optional_tuple, [4,5]
201 => 'correct values set again';
204 $record->optional_tuple([1,2,'bad']);
205 }, qr/Validation failed for 'Int'/
206 => 'Properly failed for bad value in optional bit';