1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
|
#!/usr/bin/perl
use strict;
use warnings;
use Test::More;
use Test::Exception;
=pod
This basically just makes sure that using +name
on role attributes works right.
=cut
{
package Foo::Role;
use Moose::Role;
has 'bar' => (
is => 'rw',
isa => 'Int',
default => sub { 10 },
);
package Foo;
use Moose;
with 'Foo::Role';
::lives_ok {
has '+bar' => (default => sub { 100 });
} '... extended the attribute successfully';
}
my $foo = Foo->new;
isa_ok($foo, 'Foo');
is($foo->bar, 100, '... got the extended attribute');
{
package Bar::Role;
use Moose::Role;
has 'foo' => (
is => 'rw',
isa => 'Str | Int',
);
package Bar;
use Moose;
with 'Bar::Role';
::lives_ok {
has '+foo' => (
isa => 'Int',
)
} "... narrowed the role's type constraint successfully";
}
my $bar = Bar->new(foo => 42);
isa_ok($bar, 'Bar');
is($bar->foo, 42, '... got the extended attribute');
$bar->foo(100);
is($bar->foo, 100, "... can change the attribute's value to an Int");
throws_ok { $bar->foo("baz") } qr/^Attribute \(foo\) does not pass the type constraint because: Validation failed for 'Int' with value baz at /;
is($bar->foo, 100, "... still has the old Int value");
{
package Baz::Role;
use Moose::Role;
has 'baz' => (
is => 'rw',
isa => 'Value',
);
package Baz;
use Moose;
with 'Baz::Role';
::lives_ok {
has '+baz' => (
isa => 'Int | ClassName',
)
} "... narrowed the role's type constraint successfully";
}
my $baz = Baz->new(baz => 99);
isa_ok($baz, 'Baz');
is($baz->baz, 99, '... got the extended attribute');
$baz->baz('Foo');
is($baz->baz, 'Foo', "... can change the attribute's value to a ClassName");
throws_ok { $baz->baz("zonk") } qr/^Attribute \(baz\) does not pass the type constraint because: Validation failed for 'ClassName\|Int' with value zonk at /;
is_deeply($baz->baz, 'Foo', "... still has the old ClassName value");
{
package Quux::Role;
use Moose::Role;
has 'quux' => (
is => 'rw',
isa => 'Str | Int | Ref',
);
package Quux;
use Moose;
use Moose::Util::TypeConstraints;
with 'Quux::Role';
subtype 'Positive'
=> as 'Int'
=> where { $_ > 0 };
::lives_ok {
has '+quux' => (
isa => 'Positive | ArrayRef',
)
} "... narrowed the role's type constraint successfully";
}
my $quux = Quux->new(quux => 99);
isa_ok($quux, 'Quux');
is($quux->quux, 99, '... got the extended attribute');
$quux->quux(100);
is($quux->quux, 100, "... can change the attribute's value to an Int");
$quux->quux(["hi"]);
is_deeply($quux->quux, ["hi"], "... can change the attribute's value to an ArrayRef");
throws_ok { $quux->quux("quux") } qr/^Attribute \(quux\) does not pass the type constraint because: Validation failed for 'ArrayRef\|Positive' with value quux at /;
is_deeply($quux->quux, ["hi"], "... still has the old ArrayRef value");
throws_ok { $quux->quux({a => 1}) } qr/^Attribute \(quux\) does not pass the type constraint because: Validation failed for 'ArrayRef\|Positive' with value HASH\(\w+\) at /;
is_deeply($quux->quux, ["hi"], "... still has the old ArrayRef value");
{
package Err::Role;
use Moose::Role;
for (1..3) {
has "err$_" => (
isa => 'Str | Int',
is => 'bare',
);
}
package Err;
use Moose;
with 'Err::Role';
::lives_ok {
has '+err1' => (isa => 'Defined');
} "can get less specific in the subclass";
::lives_ok {
has '+err2' => (isa => 'Bool');
} "or change the type completely";
::lives_ok {
has '+err3' => (isa => 'Str | ArrayRef');
} "or add new types to the union";
}
{
package Role::With::PlusAttr;
use Moose::Role;
with 'Foo::Role';
::throws_ok {
has '+bar' => ( is => 'ro' );
} qr/has '\+attr' is not supported in roles/,
"Test has '+attr' in roles explodes";
}
done_testing;
|