Commit | Line | Data |
231be3be |
1 | #!/usr/bin/perl |
2 | |
3 | use strict; |
4 | use warnings; |
5 | |
fdeb8354 |
6 | use lib 't/lib', 'lib'; |
7 | |
629ba321 |
8 | use Test::More tests => 91; |
fdeb8354 |
9 | use Test::Exception; |
231be3be |
10 | |
11 | use Moose::Util::MetaRole; |
12 | |
13 | |
14 | { |
15 | package My::Meta::Class; |
16 | use Moose; |
17 | extends 'Moose::Meta::Class'; |
18 | } |
19 | |
20 | { |
231be3be |
21 | package Role::Foo; |
22 | use Moose::Role; |
23 | has 'foo' => ( is => 'ro', default => 10 ); |
24 | } |
25 | |
26 | { |
27 | package My::Class; |
28 | |
29 | use Moose; |
30 | } |
31 | |
32 | { |
d401dc20 |
33 | package My::Role; |
34 | use Moose::Role; |
35 | } |
36 | |
37 | { |
231be3be |
38 | Moose::Util::MetaRole::apply_metaclass_roles( |
114134a5 |
39 | for_class => My::Class->meta, |
231be3be |
40 | metaclass_roles => ['Role::Foo'], |
41 | ); |
42 | |
43 | ok( My::Class->meta()->meta()->does_role('Role::Foo'), |
44 | 'apply Role::Foo to My::Class->meta()' ); |
45 | is( My::Class->meta()->foo(), 10, |
46 | '... and call foo() on that meta object' ); |
47 | } |
48 | |
49 | { |
50 | Moose::Util::MetaRole::apply_metaclass_roles( |
51 | for_class => 'My::Class', |
52 | attribute_metaclass_roles => ['Role::Foo'], |
53 | ); |
54 | |
55 | ok( My::Class->meta()->attribute_metaclass()->meta()->does_role('Role::Foo'), |
56 | q{apply Role::Foo to My::Class->meta()'s attribute metaclass} ); |
57 | ok( My::Class->meta()->meta()->does_role('Role::Foo'), |
58 | '... My::Class->meta() still does Role::Foo' ); |
59 | |
60 | My::Class->meta()->add_attribute( 'size', is => 'ro' ); |
61 | is( My::Class->meta()->get_attribute('size')->foo(), 10, |
62 | '... call foo() on an attribute metaclass object' ); |
63 | } |
64 | |
65 | { |
66 | Moose::Util::MetaRole::apply_metaclass_roles( |
67 | for_class => 'My::Class', |
68 | method_metaclass_roles => ['Role::Foo'], |
69 | ); |
70 | |
71 | ok( My::Class->meta()->method_metaclass()->meta()->does_role('Role::Foo'), |
72 | q{apply Role::Foo to My::Class->meta()'s method metaclass} ); |
73 | ok( My::Class->meta()->meta()->does_role('Role::Foo'), |
74 | '... My::Class->meta() still does Role::Foo' ); |
75 | ok( My::Class->meta()->attribute_metaclass()->meta()->does_role('Role::Foo'), |
76 | q{... My::Class->meta()'s attribute metaclass still does Role::Foo} ); |
77 | |
78 | My::Class->meta()->add_method( 'bar' => sub { 'bar' } ); |
79 | is( My::Class->meta()->get_method('bar')->foo(), 10, |
80 | '... call foo() on a method metaclass object' ); |
81 | } |
82 | |
83 | { |
84 | Moose::Util::MetaRole::apply_metaclass_roles( |
8286fcd6 |
85 | for_class => 'My::Class', |
86 | wrapped_method_metaclass_roles => ['Role::Foo'], |
87 | ); |
88 | |
89 | ok( My::Class->meta()->wrapped_method_metaclass()->meta()->does_role('Role::Foo'), |
90 | q{apply Role::Foo to My::Class->meta()'s wrapped method metaclass} ); |
91 | ok( My::Class->meta()->method_metaclass()->meta()->does_role('Role::Foo'), |
92 | '... My::Class->meta() still does Role::Foo' ); |
93 | ok( My::Class->meta()->meta()->does_role('Role::Foo'), |
94 | '... My::Class->meta() still does Role::Foo' ); |
95 | ok( My::Class->meta()->attribute_metaclass()->meta()->does_role('Role::Foo'), |
96 | q{... My::Class->meta()'s attribute metaclass still does Role::Foo} ); |
97 | |
98 | My::Class->meta()->add_after_method_modifier( 'bar' => sub { 'bar' } ); |
99 | is( My::Class->meta()->get_method('bar')->foo(), 10, |
100 | '... call foo() on a wrapped method metaclass object' ); |
101 | } |
102 | |
103 | { |
104 | Moose::Util::MetaRole::apply_metaclass_roles( |
231be3be |
105 | for_class => 'My::Class', |
106 | instance_metaclass_roles => ['Role::Foo'], |
107 | ); |
108 | |
109 | ok( My::Class->meta()->instance_metaclass()->meta()->does_role('Role::Foo'), |
110 | q{apply Role::Foo to My::Class->meta()'s instance metaclass} ); |
111 | ok( My::Class->meta()->meta()->does_role('Role::Foo'), |
112 | '... My::Class->meta() still does Role::Foo' ); |
113 | ok( My::Class->meta()->attribute_metaclass()->meta()->does_role('Role::Foo'), |
114 | q{... My::Class->meta()'s attribute metaclass still does Role::Foo} ); |
115 | ok( My::Class->meta()->method_metaclass()->meta()->does_role('Role::Foo'), |
116 | q{... My::Class->meta()'s method metaclass still does Role::Foo} ); |
117 | |
118 | is( My::Class->meta()->get_meta_instance()->foo(), 10, |
119 | '... call foo() on an instance metaclass object' ); |
120 | } |
121 | |
122 | { |
123 | Moose::Util::MetaRole::apply_metaclass_roles( |
124 | for_class => 'My::Class', |
125 | constructor_class_roles => ['Role::Foo'], |
126 | ); |
127 | |
128 | ok( My::Class->meta()->constructor_class()->meta()->does_role('Role::Foo'), |
129 | q{apply Role::Foo to My::Class->meta()'s constructor class} ); |
130 | ok( My::Class->meta()->meta()->does_role('Role::Foo'), |
131 | '... My::Class->meta() still does Role::Foo' ); |
132 | ok( My::Class->meta()->attribute_metaclass()->meta()->does_role('Role::Foo'), |
133 | q{... My::Class->meta()'s attribute metaclass still does Role::Foo} ); |
134 | ok( My::Class->meta()->method_metaclass()->meta()->does_role('Role::Foo'), |
135 | q{... My::Class->meta()'s method metaclass still does Role::Foo} ); |
136 | ok( My::Class->meta()->instance_metaclass()->meta()->does_role('Role::Foo'), |
137 | q{... My::Class->meta()'s instance metaclass still does Role::Foo} ); |
138 | |
139 | # Actually instantiating the constructor class is too freaking hard! |
140 | ok( My::Class->meta()->constructor_class()->can('foo'), |
141 | '... constructor class has a foo method' ); |
142 | } |
143 | |
144 | { |
145 | Moose::Util::MetaRole::apply_metaclass_roles( |
146 | for_class => 'My::Class', |
147 | destructor_class_roles => ['Role::Foo'], |
148 | ); |
149 | |
150 | ok( My::Class->meta()->destructor_class()->meta()->does_role('Role::Foo'), |
151 | q{apply Role::Foo to My::Class->meta()'s destructor class} ); |
152 | ok( My::Class->meta()->meta()->does_role('Role::Foo'), |
153 | '... My::Class->meta() still does Role::Foo' ); |
154 | ok( My::Class->meta()->attribute_metaclass()->meta()->does_role('Role::Foo'), |
155 | q{... My::Class->meta()'s attribute metaclass still does Role::Foo} ); |
156 | ok( My::Class->meta()->method_metaclass()->meta()->does_role('Role::Foo'), |
157 | q{... My::Class->meta()'s method metaclass still does Role::Foo} ); |
158 | ok( My::Class->meta()->instance_metaclass()->meta()->does_role('Role::Foo'), |
159 | q{... My::Class->meta()'s instance metaclass still does Role::Foo} ); |
160 | ok( My::Class->meta()->constructor_class()->meta()->does_role('Role::Foo'), |
161 | q{... My::Class->meta()'s constructor class still does Role::Foo} ); |
162 | |
163 | # same problem as the constructor class |
164 | ok( My::Class->meta()->destructor_class()->can('foo'), |
165 | '... destructor class has a foo method' ); |
166 | } |
167 | |
168 | { |
d401dc20 |
169 | Moose::Util::MetaRole::apply_metaclass_roles( |
170 | for_class => 'My::Role', |
171 | application_to_class_class_roles => ['Role::Foo'], |
172 | ); |
173 | |
174 | ok( My::Role->meta->application_to_class_class->meta->does_role('Role::Foo'), |
175 | q{apply Role::Foo to My::Role->meta's application_to_class class} ); |
176 | |
177 | is( My::Role->meta->application_to_class_class->new->foo, 10, |
178 | q{... call foo() on an application_to_class instance} ); |
179 | } |
180 | |
181 | { |
182 | Moose::Util::MetaRole::apply_metaclass_roles( |
183 | for_class => 'My::Role', |
184 | application_to_role_class_roles => ['Role::Foo'], |
185 | ); |
186 | |
187 | ok( My::Role->meta->application_to_role_class->meta->does_role('Role::Foo'), |
188 | q{apply Role::Foo to My::Role->meta's application_to_role class} ); |
189 | ok( My::Role->meta->application_to_class_class->meta->does_role('Role::Foo'), |
190 | q{... My::Role->meta's application_to_class class still does Role::Foo} ); |
191 | |
192 | is( My::Role->meta->application_to_role_class->new->foo, 10, |
193 | q{... call foo() on an application_to_role instance} ); |
194 | } |
195 | |
196 | { |
197 | Moose::Util::MetaRole::apply_metaclass_roles( |
198 | for_class => 'My::Role', |
199 | application_to_instance_class_roles => ['Role::Foo'], |
200 | ); |
201 | |
202 | ok( My::Role->meta->application_to_instance_class->meta->does_role('Role::Foo'), |
203 | q{apply Role::Foo to My::Role->meta's application_to_instance class} ); |
204 | ok( My::Role->meta->application_to_role_class->meta->does_role('Role::Foo'), |
205 | q{... My::Role->meta's application_to_role class still does Role::Foo} ); |
206 | ok( My::Role->meta->application_to_class_class->meta->does_role('Role::Foo'), |
207 | q{... My::Role->meta's application_to_class class still does Role::Foo} ); |
208 | |
209 | is( My::Role->meta->application_to_instance_class->new->foo, 10, |
210 | q{... call foo() on an application_to_instance instance} ); |
211 | } |
212 | |
213 | { |
231be3be |
214 | Moose::Util::MetaRole::apply_base_class_roles( |
215 | for_class => 'My::Class', |
216 | roles => ['Role::Foo'], |
217 | ); |
218 | |
219 | ok( My::Class->meta()->does_role('Role::Foo'), |
220 | 'apply Role::Foo to My::Class base class' ); |
221 | is( My::Class->new()->foo(), 10, |
222 | '... call foo() on a My::Class object' ); |
223 | } |
224 | |
225 | { |
226 | package My::Class2; |
227 | |
228 | use Moose; |
229 | } |
230 | |
231 | { |
232 | Moose::Util::MetaRole::apply_metaclass_roles( |
233 | for_class => 'My::Class2', |
234 | metaclass_roles => ['Role::Foo'], |
235 | attribute_metaclass_roles => ['Role::Foo'], |
236 | method_metaclass_roles => ['Role::Foo'], |
237 | instance_metaclass_roles => ['Role::Foo'], |
238 | constructor_class_roles => ['Role::Foo'], |
239 | destructor_class_roles => ['Role::Foo'], |
240 | ); |
241 | |
242 | ok( My::Class2->meta()->meta()->does_role('Role::Foo'), |
243 | 'apply Role::Foo to My::Class2->meta()' ); |
244 | is( My::Class2->meta()->foo(), 10, |
245 | '... and call foo() on that meta object' ); |
246 | ok( My::Class2->meta()->attribute_metaclass()->meta()->does_role('Role::Foo'), |
247 | q{apply Role::Foo to My::Class2->meta()'s attribute metaclass} ); |
248 | My::Class2->meta()->add_attribute( 'size', is => 'ro' ); |
249 | |
250 | is( My::Class2->meta()->get_attribute('size')->foo(), 10, |
251 | '... call foo() on an attribute metaclass object' ); |
252 | |
253 | ok( My::Class2->meta()->method_metaclass()->meta()->does_role('Role::Foo'), |
254 | q{apply Role::Foo to My::Class2->meta()'s method metaclass} ); |
255 | |
256 | My::Class2->meta()->add_method( 'bar' => sub { 'bar' } ); |
257 | is( My::Class2->meta()->get_method('bar')->foo(), 10, |
258 | '... call foo() on a method metaclass object' ); |
259 | |
260 | ok( My::Class2->meta()->instance_metaclass()->meta()->does_role('Role::Foo'), |
261 | q{apply Role::Foo to My::Class2->meta()'s instance metaclass} ); |
262 | is( My::Class2->meta()->get_meta_instance()->foo(), 10, |
263 | '... call foo() on an instance metaclass object' ); |
264 | |
265 | ok( My::Class2->meta()->constructor_class()->meta()->does_role('Role::Foo'), |
266 | q{apply Role::Foo to My::Class2->meta()'s constructor class} ); |
267 | ok( My::Class2->meta()->constructor_class()->can('foo'), |
268 | '... constructor class has a foo method' ); |
269 | |
270 | ok( My::Class2->meta()->destructor_class()->meta()->does_role('Role::Foo'), |
271 | q{apply Role::Foo to My::Class2->meta()'s destructor class} ); |
272 | ok( My::Class2->meta()->destructor_class()->can('foo'), |
273 | '... destructor class has a foo method' ); |
274 | } |
275 | |
276 | |
277 | { |
278 | package My::Meta; |
279 | |
280 | use Moose::Exporter; |
281 | Moose::Exporter->setup_import_methods( also => 'Moose' ); |
282 | |
283 | sub init_meta { |
284 | shift; |
285 | my %p = @_; |
286 | |
287 | Moose->init_meta( %p, metaclass => 'My::Meta::Class' ); |
288 | } |
289 | } |
290 | |
291 | { |
292 | package My::Class3; |
293 | |
294 | My::Meta->import(); |
295 | } |
296 | |
297 | |
298 | { |
299 | Moose::Util::MetaRole::apply_metaclass_roles( |
300 | for_class => 'My::Class3', |
301 | metaclass_roles => ['Role::Foo'], |
302 | ); |
303 | |
304 | ok( My::Class3->meta()->meta()->does_role('Role::Foo'), |
305 | 'apply Role::Foo to My::Class3->meta()' ); |
306 | is( My::Class3->meta()->foo(), 10, |
307 | '... and call foo() on that meta object' ); |
308 | ok( ( grep { $_ eq 'My::Meta::Class' } My::Class3->meta()->meta()->superclasses() ), |
309 | 'apply_metaclass_roles() does not interfere with metaclass set via Moose->init_meta()' ); |
310 | } |
82b388d5 |
311 | |
312 | { |
313 | package Role::Bar; |
314 | use Moose::Role; |
315 | has 'bar' => ( is => 'ro', default => 200 ); |
316 | } |
317 | |
318 | { |
319 | package My::Class4; |
320 | use Moose; |
321 | } |
322 | |
323 | { |
324 | Moose::Util::MetaRole::apply_metaclass_roles( |
325 | for_class => 'My::Class4', |
326 | metaclass_roles => ['Role::Foo'], |
327 | ); |
328 | |
329 | ok( My::Class4->meta()->meta()->does_role('Role::Foo'), |
330 | 'apply Role::Foo to My::Class4->meta()' ); |
331 | |
332 | Moose::Util::MetaRole::apply_metaclass_roles( |
333 | for_class => 'My::Class4', |
334 | metaclass_roles => ['Role::Bar'], |
335 | ); |
336 | |
337 | ok( My::Class4->meta()->meta()->does_role('Role::Bar'), |
338 | 'apply Role::Bar to My::Class4->meta()' ); |
339 | ok( My::Class4->meta()->meta()->does_role('Role::Foo'), |
340 | '... and My::Class4->meta() still does Role::Foo' ); |
341 | } |
4fed6bbc |
342 | |
343 | { |
344 | package My::Class5; |
345 | use Moose; |
346 | |
347 | extends 'My::Class'; |
348 | } |
349 | |
350 | { |
deed2e7e |
351 | ok( My::Class5->meta()->meta()->does_role('Role::Foo'), |
63647399 |
352 | q{My::Class5->meta()'s does Role::Foo because it extends My::Class} ); |
deed2e7e |
353 | ok( My::Class5->meta()->attribute_metaclass()->meta()->does_role('Role::Foo'), |
4fed6bbc |
354 | q{My::Class5->meta()'s attribute metaclass also does Role::Foo} ); |
deed2e7e |
355 | ok( My::Class5->meta()->method_metaclass()->meta()->does_role('Role::Foo'), |
4fed6bbc |
356 | q{My::Class5->meta()'s method metaclass also does Role::Foo} ); |
deed2e7e |
357 | ok( My::Class5->meta()->instance_metaclass()->meta()->does_role('Role::Foo'), |
4fed6bbc |
358 | q{My::Class5->meta()'s instance metaclass also does Role::Foo} ); |
deed2e7e |
359 | ok( My::Class5->meta()->constructor_class()->meta()->does_role('Role::Foo'), |
4fed6bbc |
360 | q{My::Class5->meta()'s constructor class also does Role::Foo} ); |
deed2e7e |
361 | ok( My::Class5->meta()->destructor_class()->meta()->does_role('Role::Foo'), |
362 | q{My::Class5->meta()'s destructor class also does Role::Foo} ); |
4fed6bbc |
363 | } |
364 | |
365 | { |
366 | Moose::Util::MetaRole::apply_metaclass_roles( |
367 | for_class => 'My::Class5', |
368 | metaclass_roles => ['Role::Bar'], |
369 | ); |
370 | |
371 | ok( My::Class5->meta()->meta()->does_role('Role::Bar'), |
372 | q{apply Role::Bar My::Class5->meta()} ); |
373 | ok( My::Class5->meta()->meta()->does_role('Role::Foo'), |
374 | q{... and My::Class5->meta() still does Role::Foo} ); |
375 | } |
376 | |
4fed6bbc |
377 | { |
378 | package My::Class6; |
379 | use Moose; |
9f82cc33 |
380 | |
4fed6bbc |
381 | Moose::Util::MetaRole::apply_metaclass_roles( |
382 | for_class => 'My::Class6', |
383 | metaclass_roles => ['Role::Bar'], |
384 | ); |
385 | |
386 | extends 'My::Class'; |
387 | } |
388 | |
389 | { |
390 | ok( My::Class6->meta()->meta()->does_role('Role::Bar'), |
391 | q{apply Role::Bar My::Class6->meta() before extends} ); |
392 | ok( My::Class6->meta()->meta()->does_role('Role::Foo'), |
f8b6827f |
393 | q{... and My::Class6->meta() does Role::Foo because My::Class6 extends My::Class} ); |
00c71b9f |
394 | } |
4fed6bbc |
395 | |
f8b6827f |
396 | # This is the hack that used to be needed to work around the |
397 | # _fix_metaclass_incompatibility problem. You called extends() (which |
398 | # in turn calls _fix_metaclass_imcompatibility) _before_ you apply |
399 | # more extensions in the subclass. We wabt to make sure this continues |
400 | # to work in the future. |
4fed6bbc |
401 | { |
402 | package My::Class7; |
403 | use Moose; |
404 | |
405 | # In real usage this would go in a BEGIN block so it happened |
406 | # before apply_metaclass_roles was called by an extension. |
407 | extends 'My::Class'; |
408 | |
409 | Moose::Util::MetaRole::apply_metaclass_roles( |
410 | for_class => 'My::Class7', |
411 | metaclass_roles => ['Role::Bar'], |
412 | ); |
413 | } |
414 | |
415 | { |
416 | ok( My::Class7->meta()->meta()->does_role('Role::Bar'), |
417 | q{apply Role::Bar My::Class7->meta() before extends} ); |
418 | ok( My::Class7->meta()->meta()->does_role('Role::Foo'), |
f8b6827f |
419 | q{... and My::Class7->meta() does Role::Foo because My::Class7 extends My::Class} ); |
420 | } |
421 | |
422 | { |
423 | package My::Class8; |
424 | use Moose; |
425 | |
426 | Moose::Util::MetaRole::apply_metaclass_roles( |
427 | for_class => 'My::Class8', |
428 | metaclass_roles => ['Role::Bar'], |
429 | attribute_metaclass_roles => ['Role::Bar'], |
430 | ); |
431 | |
432 | extends 'My::Class'; |
433 | } |
434 | |
435 | { |
436 | ok( My::Class8->meta()->meta()->does_role('Role::Bar'), |
437 | q{apply Role::Bar My::Class8->meta() before extends} ); |
438 | ok( My::Class8->meta()->meta()->does_role('Role::Foo'), |
439 | q{... and My::Class8->meta() does Role::Foo because My::Class8 extends My::Class} ); |
440 | ok( My::Class8->meta()->attribute_metaclass->meta()->does_role('Role::Bar'), |
441 | q{apply Role::Bar to My::Class8->meta()->attribute_metaclass before extends} ); |
442 | ok( My::Class8->meta()->attribute_metaclass->meta()->does_role('Role::Foo'), |
443 | q{... and My::Class8->meta()->attribute_metaclass does Role::Foo because My::Class8 extends My::Class} ); |
444 | } |
445 | |
446 | |
447 | { |
448 | package My::Class9; |
449 | use Moose; |
450 | |
451 | Moose::Util::MetaRole::apply_metaclass_roles( |
452 | for_class => 'My::Class9', |
453 | attribute_metaclass_roles => ['Role::Bar'], |
454 | ); |
455 | |
456 | extends 'My::Class'; |
457 | } |
458 | |
459 | { |
460 | ok( My::Class9->meta()->meta()->does_role('Role::Foo'), |
461 | q{... and My::Class9->meta() does Role::Foo because My::Class9 extends My::Class} ); |
462 | ok( My::Class9->meta()->attribute_metaclass->meta()->does_role('Role::Bar'), |
463 | q{apply Role::Bar to My::Class9->meta()->attribute_metaclass before extends} ); |
464 | ok( My::Class9->meta()->attribute_metaclass->meta()->does_role('Role::Foo'), |
465 | q{... and My::Class9->meta()->attribute_metaclass does Role::Foo because My::Class9 extends My::Class} ); |
4fed6bbc |
466 | } |
dd37a5be |
467 | |
468 | # This tests applying meta roles to a metaclass's metaclass. This is |
469 | # completely insane, but is exactly what happens with |
470 | # Fey::Meta::Class::Table. It's a subclass of Moose::Meta::Class |
471 | # itself, and then it _uses_ MooseX::ClassAttribute, so the metaclass |
472 | # for Fey::Meta::Class::Table does a role. |
473 | # |
474 | # At one point this caused a metaclass incompatibility error down |
475 | # below, when we applied roles to the metaclass of My::Class10. It's |
476 | # all madness but as long as the tests pass we're happy. |
477 | { |
478 | package My::Meta::Class2; |
479 | use Moose; |
480 | extends 'Moose::Meta::Class'; |
481 | |
482 | Moose::Util::MetaRole::apply_metaclass_roles( |
483 | for_class => 'My::Meta::Class2', |
484 | metaclass_roles => ['Role::Foo'], |
485 | ); |
486 | } |
487 | |
488 | { |
896e6f85 |
489 | package My::Object; |
490 | use Moose; |
491 | extends 'Moose::Object'; |
492 | } |
493 | |
494 | { |
dd37a5be |
495 | package My::Meta2; |
496 | |
497 | use Moose::Exporter; |
498 | Moose::Exporter->setup_import_methods( also => 'Moose' ); |
499 | |
500 | sub init_meta { |
501 | shift; |
502 | my %p = @_; |
503 | |
896e6f85 |
504 | Moose->init_meta( |
505 | %p, |
506 | metaclass => 'My::Meta::Class2', |
507 | base_class => 'My::Object', |
508 | ); |
dd37a5be |
509 | } |
510 | } |
511 | |
512 | { |
513 | package My::Class10; |
514 | My::Meta2->import; |
515 | |
516 | Moose::Util::MetaRole::apply_metaclass_roles( |
517 | for_class => 'My::Class10', |
518 | metaclass_roles => ['Role::Bar'], |
519 | ); |
520 | } |
521 | |
522 | { |
523 | ok( My::Class10->meta()->meta()->meta()->does_role('Role::Foo'), |
524 | q{My::Class10->meta()->meta() does Role::Foo } ); |
b72373c4 |
525 | ok( My::Class10->meta()->meta()->does_role('Role::Bar'), |
526 | q{My::Class10->meta()->meta() does Role::Bar } ); |
dd37a5be |
527 | ok( My::Class10->meta()->isa('My::Meta::Class2'), |
528 | q{... and My::Class10->meta still isa(My::Meta::Class2)} ); |
896e6f85 |
529 | ok( My::Class10->isa('My::Object'), |
530 | q{... and My::Class10 still isa(My::Object)} ); |
dd37a5be |
531 | } |
8f05895e |
532 | |
533 | { |
534 | package My::Constructor; |
535 | |
536 | use base 'Moose::Meta::Method::Constructor'; |
537 | } |
538 | |
539 | { |
540 | package My::Class11; |
541 | |
542 | use Moose; |
543 | |
544 | __PACKAGE__->meta->constructor_class('My::Constructor'); |
545 | |
546 | Moose::Util::MetaRole::apply_metaclass_roles( |
547 | for_class => 'My::Class11', |
548 | metaclass_roles => ['Role::Foo'], |
549 | ); |
550 | } |
551 | |
552 | { |
553 | ok( My::Class11->meta()->meta()->does_role('Role::Foo'), |
554 | q{My::Class11->meta()->meta() does Role::Foo } ); |
555 | is( My::Class11->meta()->constructor_class, 'My::Constructor', |
556 | q{... and explicitly set constructor_class value is unchanged)} ); |
557 | } |
fdeb8354 |
558 | |
559 | { |
560 | package ExportsMoose; |
561 | |
562 | Moose::Exporter->setup_import_methods( |
563 | also => 'Moose', |
564 | ); |
565 | |
566 | sub init_meta { |
567 | shift; |
568 | my %p = @_; |
569 | Moose->init_meta(%p); |
d03bd989 |
570 | return Moose::Util::MetaRole::apply_metaclass_roles( |
fdeb8354 |
571 | for_class => $p{for_class}, |
572 | # Causes us to recurse through init_meta, as we have to |
573 | # load MyMetaclassRole from disk. |
574 | metaclass_roles => [qw/MyMetaclassRole/], |
575 | ); |
576 | } |
577 | } |
578 | |
579 | lives_ok { |
580 | package UsesExportedMoose; |
581 | ExportsMoose->import; |
582 | } 'import module which loads a role from disk during init_meta'; |
583 | |
b05518b2 |
584 | { |
585 | package Foo::Meta::Role; |
586 | |
587 | use Moose::Role; |
588 | } |
589 | { |
590 | package Foo::Role; |
591 | |
592 | Moose::Exporter->setup_import_methods( |
593 | also => 'Moose::Role', |
594 | ); |
595 | |
596 | sub init_meta { |
597 | shift; |
598 | my %p = @_; |
599 | Moose::Role->init_meta(%p); |
600 | return Moose::Util::MetaRole::apply_metaclass_roles( |
601 | for_class => $p{for_class}, |
602 | method_metaclass_roles => [ 'Foo::Meta::Role', ], |
603 | ); |
604 | } |
605 | } |
606 | { |
607 | package Role::Baz; |
608 | |
609 | Foo::Role->import; |
610 | |
611 | sub bla {} |
612 | } |
613 | { |
614 | package My::Class12; |
615 | |
616 | use Moose; |
617 | |
618 | with( 'Role::Baz' ); |
619 | } |
620 | { |
621 | ok( |
622 | My::Class12->meta->does_role( 'Role::Baz' ), |
623 | 'role applied' |
624 | ); |
625 | my $method = My::Class12->meta->get_method( 'bla' ); |
626 | ok( |
627 | $method->meta->does_role( 'Foo::Meta::Role' ), |
628 | 'method_metaclass_role applied' |
629 | ); |
630 | } |
629ba321 |
631 | |
632 | { |
633 | package Parent; |
634 | use Moose; |
635 | |
636 | Moose::Util::MetaRole::apply_metaclass_roles( |
637 | for_class => __PACKAGE__, |
638 | constructor_class_roles => ['Role::Foo'], |
639 | ); |
640 | } |
641 | |
642 | { |
643 | package Child; |
644 | |
645 | use Moose; |
646 | extends 'Parent'; |
647 | } |
648 | |
649 | { |
650 | ok( |
651 | Parent->meta->constructor_class->meta->can('does_role') |
652 | && Parent->meta->constructor_class->meta->does_role('Role::Foo'), |
653 | 'Parent constructor class has metarole from Parent' |
654 | ); |
655 | |
656 | TODO: |
657 | { |
658 | local $TODO |
659 | = 'Moose does not see that the child differs from the parent because it only checks the class and instance metaclasses do determine compatibility'; |
660 | ok( |
661 | Child->meta->constructor_class->meta->can('does_role') |
662 | && Child->meta->constructor_class->meta->does_role( |
663 | 'Role::Foo'), |
664 | 'Child constructor class has metarole from Parent' |
665 | ); |
666 | } |
667 | } |