Add another MOOSE_TEST_MD option, MooseX
[gitmo/Moose.git] / t / roles / roles_and_req_method_edge_cases.t
CommitLineData
0558683c 1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
a28e50e4 6use Test::More;
b10dde3a 7use Test::Fatal;
0558683c 8
1db8ecc7 9=pod
10
11NOTE:
d03bd989 12A fair amount of these tests will likely be irrelevant
1db8ecc7 13once we have more fine grained control over the class
14building process. A lot of the edge cases tested here
d03bd989 15are actually related to class construction order and
1db8ecc7 16not any real functionality.
17- SL
18
d03bd989 19Role which requires a method implemented
20in another role as an override (it does
0558683c 21not remove the requirement)
22
23=cut
24
25{
26 package Role::RequireFoo;
27 use strict;
28 use warnings;
29 use Moose::Role;
d03bd989 30
0558683c 31 requires 'foo';
d03bd989 32
0558683c 33 package Role::ProvideFoo;
34 use strict;
35 use warnings;
36 use Moose::Role;
d03bd989 37
b10dde3a 38 ::is( ::exception {
0558683c 39 with 'Role::RequireFoo';
b10dde3a 40 }, undef, '... the required "foo" method will not exist yet (but we will live)' );
d03bd989 41
42 override 'foo' => sub { 'Role::ProvideFoo::foo' };
0558683c 43}
44
45is_deeply(
d03bd989 46 [ Role::ProvideFoo->meta->get_required_method_list ],
47 [ 'foo' ],
0558683c 48 '... foo method is still required for Role::ProvideFoo');
49
50=pod
51
d03bd989 52Role which requires a method implemented
53in the consuming class as an override.
54It will fail since method modifiers are
0558683c 55second class citizens.
56
57=cut
58
59{
60 package Class::ProvideFoo::Base;
61 use Moose;
62
63 sub foo { 'Class::ProvideFoo::Base::foo' }
d03bd989 64
0558683c 65 package Class::ProvideFoo::Override1;
66 use Moose;
d03bd989 67
0558683c 68 extends 'Class::ProvideFoo::Base';
d03bd989 69
b10dde3a 70 ::is( ::exception {
0558683c 71 with 'Role::RequireFoo';
b10dde3a 72 }, undef, '... the required "foo" method will be found in the superclass' );
d03bd989 73
74 override 'foo' => sub { 'Class::ProvideFoo::foo' };
75
0558683c 76 package Class::ProvideFoo::Override2;
77 use Moose;
d03bd989 78
0558683c 79 extends 'Class::ProvideFoo::Base';
d03bd989 80
81 override 'foo' => sub { 'Class::ProvideFoo::foo' };
82
b10dde3a 83 ::is( ::exception {
0558683c 84 with 'Role::RequireFoo';
b10dde3a 85 }, undef, '... the required "foo" method exists, although it is overriden locally' );
0558683c 86
87}
88
89=pod
90
d03bd989 91Now same thing, but with a before
0558683c 92method modifier.
93
94=cut
95
96{
97 package Class::ProvideFoo::Before1;
98 use Moose;
d03bd989 99
0558683c 100 extends 'Class::ProvideFoo::Base';
d03bd989 101
b10dde3a 102 ::is( ::exception {
0558683c 103 with 'Role::RequireFoo';
b10dde3a 104 }, undef, '... the required "foo" method will be found in the superclass' );
d03bd989 105
106 before 'foo' => sub { 'Class::ProvideFoo::foo:before' };
107
0558683c 108 package Class::ProvideFoo::Before2;
109 use Moose;
d03bd989 110
0558683c 111 extends 'Class::ProvideFoo::Base';
d03bd989 112
113 before 'foo' => sub { 'Class::ProvideFoo::foo:before' };
114
b10dde3a 115 ::is( ::exception {
0558683c 116 with 'Role::RequireFoo';
b10dde3a 117 }, undef, '... the required "foo" method exists, although it is a before modifier locally' );
d03bd989 118
0558683c 119 package Class::ProvideFoo::Before3;
120 use Moose;
d03bd989 121
0558683c 122 extends 'Class::ProvideFoo::Base';
d03bd989 123
0558683c 124 sub foo { 'Class::ProvideFoo::foo' }
d03bd989 125 before 'foo' => sub { 'Class::ProvideFoo::foo:before' };
126
b10dde3a 127 ::is( ::exception {
e7f8d0c2 128 with 'Role::RequireFoo';
b10dde3a 129 }, undef, '... the required "foo" method exists locally, and it is modified locally' );
d03bd989 130
0558683c 131 package Class::ProvideFoo::Before4;
132 use Moose;
d03bd989 133
0558683c 134 extends 'Class::ProvideFoo::Base';
d03bd989 135
136 sub foo { 'Class::ProvideFoo::foo' }
137 before 'foo' => sub { 'Class::ProvideFoo::foo:before' };
0558683c 138
139 ::isa_ok(__PACKAGE__->meta->get_method('foo'), 'Class::MOP::Method::Wrapped');
d03bd989 140 ::is(__PACKAGE__->meta->get_method('foo')->get_original_method->package_name, __PACKAGE__,
0558683c 141 '... but the original method is from our package');
d03bd989 142
b10dde3a 143 ::is( ::exception {
0558683c 144 with 'Role::RequireFoo';
b10dde3a 145 }, undef, '... the required "foo" method exists in the symbol table (and we will live)' );
d03bd989 146
147}
0558683c 148
149=pod
150
151Now same thing, but with a method from an attribute
152method modifier.
153
154=cut
155
156{
d03bd989 157
0558683c 158 package Class::ProvideFoo::Attr1;
159 use Moose;
d03bd989 160
0558683c 161 extends 'Class::ProvideFoo::Base';
d03bd989 162
b10dde3a 163 ::is( ::exception {
0558683c 164 with 'Role::RequireFoo';
b10dde3a 165 }, undef, '... the required "foo" method will be found in the superclass (but then overriden)' );
d03bd989 166
0558683c 167 has 'foo' => (is => 'ro');
d03bd989 168
0558683c 169 package Class::ProvideFoo::Attr2;
170 use Moose;
d03bd989 171
0558683c 172 extends 'Class::ProvideFoo::Base';
d03bd989 173
174 has 'foo' => (is => 'ro');
175
b10dde3a 176 ::is( ::exception {
0558683c 177 with 'Role::RequireFoo';
b10dde3a 178 }, undef, '... the required "foo" method exists, and is an accessor' );
d03bd989 179}
825a80de 180
181# ...
d03bd989 182# a method required in a role, but then
183# implemented in the superclass (as an
825a80de 184# attribute accessor too)
d03bd989 185
825a80de 186{
187 package Foo::Class::Base;
188 use Moose;
d03bd989 189
190 has 'bar' => (
191 isa => 'Int',
192 is => 'rw',
825a80de 193 default => sub { 1 }
194 );
195}
196{
197 package Foo::Role;
198 use Moose::Role;
d03bd989 199
825a80de 200 requires 'bar';
d03bd989 201
202 has 'foo' => (
203 isa => 'Int',
204 is => 'rw',
205 lazy => 1,
206 default => sub { (shift)->bar + 1 }
825a80de 207 );
208}
209{
210 package Foo::Class::Child;
211 use Moose;
212 extends 'Foo::Class::Base';
d03bd989 213
b10dde3a 214 ::is( ::exception {
825a80de 215 with 'Foo::Role';
b10dde3a 216 }, undef, '... our role combined successfully' );
825a80de 217}
218
3dd18b73 219# a method required in a role and implemented in a superclass, with a method
220# modifier in the subclass. this should live, but dies in 0.26 -- hdp,
221# 2007-10-11
825a80de 222
3dd18b73 223{
224 package Bar::Class::Base;
225 use Moose;
825a80de 226
3dd18b73 227 sub bar { "hello!" }
228}
229{
230 package Bar::Role;
231 use Moose::Role;
232 requires 'bar';
233}
234{
235 package Bar::Class::Child;
236 use Moose;
237 extends 'Bar::Class::Base';
238 after bar => sub { "o noes" };
53a4d826 239 # technically we could run lives_ok here, too, but putting it into a
4ec69f21 240 # grandchild class makes it more obvious why this matters.
241}
242{
243 package Bar::Class::Grandchild;
244 use Moose;
245 extends 'Bar::Class::Child';
b10dde3a 246 ::is( ::exception {
3dd18b73 247 with 'Bar::Role';
b10dde3a 248 }, undef, 'required method exists in superclass as non-modifier, so we live' );
3dd18b73 249}
e7f8d0c2 250
251{
252 package Bar2::Class::Base;
253 use Moose;
254
255 sub bar { "hello!" }
256}
257{
258 package Bar2::Role;
259 use Moose::Role;
260 requires 'bar';
261}
262{
263 package Bar2::Class::Child;
264 use Moose;
265 extends 'Bar2::Class::Base';
266 override bar => sub { "o noes" };
53a4d826 267 # technically we could run lives_ok here, too, but putting it into a
e7f8d0c2 268 # grandchild class makes it more obvious why this matters.
269}
270{
271 package Bar2::Class::Grandchild;
272 use Moose;
273 extends 'Bar2::Class::Child';
b10dde3a 274 ::is( ::exception {
e7f8d0c2 275 with 'Bar2::Role';
b10dde3a 276 }, undef, 'required method exists in superclass as non-modifier, so we live' );
e7f8d0c2 277}
a28e50e4 278
279done_testing;