more refactoring to the Structured Role, put together some tests to show the optional...
[gitmo/MooseX-Types-Structured.git] / t / constraints.t
CommitLineData
65748864 1BEGIN {
2 use strict;
3 use warnings;
b5f77bd3 4 use Test::More tests=>30;
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;
41 my %optional = ref $optional eq 'HASH' ? @$optional : ();
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']) );
65748864 72}
73
74## Instantiate a new test object
75
bc64165b 76ok my $record = Test::MooseX::Meta::TypeConstraint::Structured->new
65748864 77 => 'Instantiated new Record test class.';
78
bc64165b 79isa_ok $record => 'Test::MooseX::Meta::TypeConstraint::Structured'
65748864 80 => 'Created correct object type.';
b5f77bd3 81
bc64165b 82## Test Tuple type constraint
83
65748864 84lives_ok sub {
c3abf064 85 $record->tuple([1,'hello', 'test.abc.test']);
65748864 86} => 'Set tuple attribute without error';
87
88is $record->tuple->[0], 1
89 => 'correct set the tuple attribute index 0';
90
91is $record->tuple->[1], 'hello'
92 => 'correct set the tuple attribute index 1';
93
c3abf064 94is $record->tuple->[2], 'test.abc.test'
95 => 'correct set the tuple attribute index 2';
96
97throws_ok sub {
98 $record->tuple([1,'hello', 'test.xxx.test']);
99}, qr/Validation failed for 'MyString'/
100 => 'Properly failed for bad value in custom type constraint';
101
65748864 102throws_ok sub {
c3abf064 103 $record->tuple(['asdasd',2, 'test.abc.test']);
65748864 104}, qr/Validation failed for 'Int'/
105 => 'Got Expected Error for violating constraints';
106
bc64165b 107## Test the Dictionary type constraint
108
109lives_ok sub {
110 $record->dict({name=>'frith', age=>23});
111} => 'Set dict attribute without error';
112
113is $record->dict->{name}, 'frith'
114 => 'correct set the dict attribute name';
115
116is $record->dict->{age}, 23
117 => 'correct set the dict attribute age';
118
119throws_ok sub {
120 $record->dict({name=>[1,2,3], age=>'sdfsdfsd'});
121}, qr/Validation failed for 'Str'/
122 => 'Got Expected Error for bad value in dict';
8b276dd4 123
124## Test tuple_with_maybe
125
126lives_ok sub {
127 $record->tuple_with_maybe([1,'hello', 1]);
128} => 'Set tuple attribute without error';
129
130throws_ok sub {
131 $record->tuple_with_maybe([1,'hello', 'a']);
132}, qr/Validation failed for 'Maybe\[Int\]'/
133 => 'Properly failed for bad value parameterized constraint';
134
135lives_ok sub {
136 $record->tuple_with_maybe([1,'hello']);
137} => 'Set tuple attribute without error skipping optional parameter';
138
139## Test Tuple with parameterized type
140
141lives_ok sub {
142 $record->tuple_with_param([1,'hello', [1,2,3]]);
143} => 'Set tuple attribute without error';
144
145throws_ok sub {
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';
149
150## Test dict_with_maybe
151
152lives_ok sub {
153 $record->dict_with_maybe({name=>'frith', age=>23});
154} => 'Set dict attribute without error';
155
156is $record->dict_with_maybe->{name}, 'frith'
157 => 'correct set the dict attribute name';
158
159is $record->dict_with_maybe->{age}, 23
160 => 'correct set the dict attribute age';
161
162throws_ok sub {
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';
166
167throws_ok sub {
168 $record->dict_with_maybe({age=>30});
169}, qr/Validation failed for 'Str'/
170 => 'Got Expected Error for missing named parameter';
171
172lives_ok sub {
173 $record->dict_with_maybe({name=>'usal'});
174} => 'Set dict attribute without error, skipping optional';
9a920d27 175
176## Test dict_with_tuple
177
178lives_ok sub {
179 $record->dict_with_tuple({key1=>'Hello', key2=>[1,'World']});
180} => 'Set tuple attribute without error';
181
182throws_ok sub {
183 $record->dict_with_tuple({key1=>'Hello', key2=>['World',2]});
184}, qr/Validation failed for 'Int'/
185 => 'Threw error on bad constraint';
186
b5f77bd3 187## Test optional_tuple
9a920d27 188
b5f77bd3 189lives_ok sub {
190 $record->optional_tuple([1,2,3]);
191} => 'Set tuple attribute with optional bits';
192
193is_deeply $record->optional_tuple, [1,2,3]
194 => 'correct values set';
195
196lives_ok sub {
197 $record->optional_tuple([4,5]);
198} => 'Set tuple attribute withOUT optional bits';
199
200is_deeply $record->optional_tuple, [4,5]
201 => 'correct values set again';
202
203throws_ok sub {
204 $record->optional_tuple([1,2,'bad']);
205}, qr/Validation failed for 'Int'/
206 => 'Properly failed for bad value in optional bit';
9a920d27 207