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