Add what does moose stand for section back to docs
[gitmo/Moose.git] / t / metaclasses / metarole.t
CommitLineData
231be3be 1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
fdeb8354 6use lib 't/lib', 'lib';
7
a28e50e4 8use Test::More;
b10dde3a 9use Test::Fatal;
231be3be 10
11use 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{
f785aad8 38 Moose::Util::MetaRole::apply_metaroles(
39 for => My::Class->meta,
40 class_metaroles => { class => ['Role::Foo'] },
231be3be 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{
f785aad8 50 Moose::Util::MetaRole::apply_metaroles(
51 for => 'My::Class',
52 class_metaroles => { attribute => ['Role::Foo'] },
231be3be 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{
f785aad8 66 Moose::Util::MetaRole::apply_metaroles(
67 for => 'My::Class',
68 class_metaroles => { method => ['Role::Foo'] },
231be3be 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{
f785aad8 84 Moose::Util::MetaRole::apply_metaroles(
85 for => 'My::Class',
86 class_metaroles => { wrapped_method => ['Role::Foo'] },
8286fcd6 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{
f785aad8 104 Moose::Util::MetaRole::apply_metaroles(
105 for => 'My::Class',
106 class_metaroles => { instance => ['Role::Foo'] },
231be3be 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{
f785aad8 123 Moose::Util::MetaRole::apply_metaroles(
124 for => 'My::Class',
125 class_metaroles => { constructor => ['Role::Foo'] },
231be3be 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{
f785aad8 145 Moose::Util::MetaRole::apply_metaroles(
146 for => 'My::Class',
147 class_metaroles => { destructor => ['Role::Foo'] },
231be3be 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{
f785aad8 169 Moose::Util::MetaRole::apply_metaroles(
170 for => 'My::Role',
171 role_metaroles => { application_to_class => ['Role::Foo'] },
d401dc20 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{
f785aad8 182 Moose::Util::MetaRole::apply_metaroles(
183 for => 'My::Role',
184 role_metaroles => { application_to_role => ['Role::Foo'] },
d401dc20 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{
f785aad8 197 Moose::Util::MetaRole::apply_metaroles(
198 for => 'My::Role',
199 role_metaroles => { application_to_instance => ['Role::Foo'] },
d401dc20 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(
f785aad8 215 for => 'My::Class',
216 roles => ['Role::Foo'],
231be3be 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{
f785aad8 232 Moose::Util::MetaRole::apply_metaroles(
233 for => 'My::Class2',
234 class_metaroles => {
235 class => ['Role::Foo'],
236 attribute => ['Role::Foo'],
237 method => ['Role::Foo'],
238 instance => ['Role::Foo'],
239 constructor => ['Role::Foo'],
240 destructor => ['Role::Foo'],
241 },
231be3be 242 );
243
244 ok( My::Class2->meta()->meta()->does_role('Role::Foo'),
245 'apply Role::Foo to My::Class2->meta()' );
246 is( My::Class2->meta()->foo(), 10,
247 '... and call foo() on that meta object' );
248 ok( My::Class2->meta()->attribute_metaclass()->meta()->does_role('Role::Foo'),
249 q{apply Role::Foo to My::Class2->meta()'s attribute metaclass} );
250 My::Class2->meta()->add_attribute( 'size', is => 'ro' );
251
252 is( My::Class2->meta()->get_attribute('size')->foo(), 10,
253 '... call foo() on an attribute metaclass object' );
254
255 ok( My::Class2->meta()->method_metaclass()->meta()->does_role('Role::Foo'),
256 q{apply Role::Foo to My::Class2->meta()'s method metaclass} );
257
258 My::Class2->meta()->add_method( 'bar' => sub { 'bar' } );
259 is( My::Class2->meta()->get_method('bar')->foo(), 10,
260 '... call foo() on a method metaclass object' );
261
262 ok( My::Class2->meta()->instance_metaclass()->meta()->does_role('Role::Foo'),
263 q{apply Role::Foo to My::Class2->meta()'s instance metaclass} );
264 is( My::Class2->meta()->get_meta_instance()->foo(), 10,
265 '... call foo() on an instance metaclass object' );
266
267 ok( My::Class2->meta()->constructor_class()->meta()->does_role('Role::Foo'),
268 q{apply Role::Foo to My::Class2->meta()'s constructor class} );
269 ok( My::Class2->meta()->constructor_class()->can('foo'),
270 '... constructor class has a foo method' );
271
272 ok( My::Class2->meta()->destructor_class()->meta()->does_role('Role::Foo'),
273 q{apply Role::Foo to My::Class2->meta()'s destructor class} );
274 ok( My::Class2->meta()->destructor_class()->can('foo'),
275 '... destructor class has a foo method' );
276}
277
278
279{
280 package My::Meta;
281
282 use Moose::Exporter;
283 Moose::Exporter->setup_import_methods( also => 'Moose' );
284
285 sub init_meta {
286 shift;
287 my %p = @_;
288
289 Moose->init_meta( %p, metaclass => 'My::Meta::Class' );
290 }
291}
292
293{
294 package My::Class3;
295
296 My::Meta->import();
297}
298
299
300{
f785aad8 301 Moose::Util::MetaRole::apply_metaroles(
302 for => 'My::Class3',
303 class_metaroles => { class => ['Role::Foo'] },
231be3be 304 );
305
306 ok( My::Class3->meta()->meta()->does_role('Role::Foo'),
307 'apply Role::Foo to My::Class3->meta()' );
308 is( My::Class3->meta()->foo(), 10,
309 '... and call foo() on that meta object' );
310 ok( ( grep { $_ eq 'My::Meta::Class' } My::Class3->meta()->meta()->superclasses() ),
f785aad8 311 'apply_metaroles() does not interfere with metaclass set via Moose->init_meta()' );
231be3be 312}
82b388d5 313
314{
315 package Role::Bar;
316 use Moose::Role;
317 has 'bar' => ( is => 'ro', default => 200 );
318}
319
320{
321 package My::Class4;
322 use Moose;
323}
324
325{
f785aad8 326 Moose::Util::MetaRole::apply_metaroles(
327 for => 'My::Class4',
328 class_metaroles => { class => ['Role::Foo'] },
82b388d5 329 );
330
331 ok( My::Class4->meta()->meta()->does_role('Role::Foo'),
332 'apply Role::Foo to My::Class4->meta()' );
333
f785aad8 334 Moose::Util::MetaRole::apply_metaroles(
335 for => 'My::Class4',
336 class_metaroles => { class => ['Role::Bar'] },
82b388d5 337 );
338
339 ok( My::Class4->meta()->meta()->does_role('Role::Bar'),
340 'apply Role::Bar to My::Class4->meta()' );
341 ok( My::Class4->meta()->meta()->does_role('Role::Foo'),
342 '... and My::Class4->meta() still does Role::Foo' );
343}
4fed6bbc 344
345{
346 package My::Class5;
347 use Moose;
348
349 extends 'My::Class';
350}
351
352{
deed2e7e 353 ok( My::Class5->meta()->meta()->does_role('Role::Foo'),
63647399 354 q{My::Class5->meta()'s does Role::Foo because it extends My::Class} );
deed2e7e 355 ok( My::Class5->meta()->attribute_metaclass()->meta()->does_role('Role::Foo'),
4fed6bbc 356 q{My::Class5->meta()'s attribute metaclass also does Role::Foo} );
deed2e7e 357 ok( My::Class5->meta()->method_metaclass()->meta()->does_role('Role::Foo'),
4fed6bbc 358 q{My::Class5->meta()'s method metaclass also does Role::Foo} );
deed2e7e 359 ok( My::Class5->meta()->instance_metaclass()->meta()->does_role('Role::Foo'),
4fed6bbc 360 q{My::Class5->meta()'s instance metaclass also does Role::Foo} );
deed2e7e 361 ok( My::Class5->meta()->constructor_class()->meta()->does_role('Role::Foo'),
4fed6bbc 362 q{My::Class5->meta()'s constructor class also does Role::Foo} );
deed2e7e 363 ok( My::Class5->meta()->destructor_class()->meta()->does_role('Role::Foo'),
364 q{My::Class5->meta()'s destructor class also does Role::Foo} );
4fed6bbc 365}
366
367{
f785aad8 368 Moose::Util::MetaRole::apply_metaroles(
369 for => 'My::Class5',
370 class_metaroles => { class => ['Role::Bar'] },
4fed6bbc 371 );
372
373 ok( My::Class5->meta()->meta()->does_role('Role::Bar'),
374 q{apply Role::Bar My::Class5->meta()} );
375 ok( My::Class5->meta()->meta()->does_role('Role::Foo'),
376 q{... and My::Class5->meta() still does Role::Foo} );
377}
378
4fed6bbc 379{
380 package My::Class6;
381 use Moose;
9f82cc33 382
f785aad8 383 Moose::Util::MetaRole::apply_metaroles(
384 for => 'My::Class6',
385 class_metaroles => { class => ['Role::Bar'] },
4fed6bbc 386 );
387
388 extends 'My::Class';
389}
390
391{
392 ok( My::Class6->meta()->meta()->does_role('Role::Bar'),
393 q{apply Role::Bar My::Class6->meta() before extends} );
394 ok( My::Class6->meta()->meta()->does_role('Role::Foo'),
f8b6827f 395 q{... and My::Class6->meta() does Role::Foo because My::Class6 extends My::Class} );
00c71b9f 396}
4fed6bbc 397
f8b6827f 398# This is the hack that used to be needed to work around the
399# _fix_metaclass_incompatibility problem. You called extends() (which
400# in turn calls _fix_metaclass_imcompatibility) _before_ you apply
401# more extensions in the subclass. We wabt to make sure this continues
402# to work in the future.
4fed6bbc 403{
404 package My::Class7;
405 use Moose;
406
407 # In real usage this would go in a BEGIN block so it happened
f785aad8 408 # before apply_metaroles was called by an extension.
4fed6bbc 409 extends 'My::Class';
410
f785aad8 411 Moose::Util::MetaRole::apply_metaroles(
412 for => 'My::Class7',
413 class_metaroles => { class => ['Role::Bar'] },
4fed6bbc 414 );
415}
416
417{
418 ok( My::Class7->meta()->meta()->does_role('Role::Bar'),
419 q{apply Role::Bar My::Class7->meta() before extends} );
420 ok( My::Class7->meta()->meta()->does_role('Role::Foo'),
f8b6827f 421 q{... and My::Class7->meta() does Role::Foo because My::Class7 extends My::Class} );
422}
423
424{
425 package My::Class8;
426 use Moose;
427
f785aad8 428 Moose::Util::MetaRole::apply_metaroles(
429 for => 'My::Class8',
430 class_metaroles => {
431 class => ['Role::Bar'],
432 attribute => ['Role::Bar'],
433 },
f8b6827f 434 );
435
436 extends 'My::Class';
437}
438
439{
440 ok( My::Class8->meta()->meta()->does_role('Role::Bar'),
441 q{apply Role::Bar My::Class8->meta() before extends} );
442 ok( My::Class8->meta()->meta()->does_role('Role::Foo'),
443 q{... and My::Class8->meta() does Role::Foo because My::Class8 extends My::Class} );
444 ok( My::Class8->meta()->attribute_metaclass->meta()->does_role('Role::Bar'),
445 q{apply Role::Bar to My::Class8->meta()->attribute_metaclass before extends} );
446 ok( My::Class8->meta()->attribute_metaclass->meta()->does_role('Role::Foo'),
447 q{... and My::Class8->meta()->attribute_metaclass does Role::Foo because My::Class8 extends My::Class} );
448}
449
450
451{
452 package My::Class9;
453 use Moose;
454
f785aad8 455 Moose::Util::MetaRole::apply_metaroles(
456 for => 'My::Class9',
457 class_metaroles => { attribute => ['Role::Bar'] },
f8b6827f 458 );
459
460 extends 'My::Class';
461}
462
463{
464 ok( My::Class9->meta()->meta()->does_role('Role::Foo'),
465 q{... and My::Class9->meta() does Role::Foo because My::Class9 extends My::Class} );
466 ok( My::Class9->meta()->attribute_metaclass->meta()->does_role('Role::Bar'),
467 q{apply Role::Bar to My::Class9->meta()->attribute_metaclass before extends} );
468 ok( My::Class9->meta()->attribute_metaclass->meta()->does_role('Role::Foo'),
469 q{... and My::Class9->meta()->attribute_metaclass does Role::Foo because My::Class9 extends My::Class} );
4fed6bbc 470}
dd37a5be 471
472# This tests applying meta roles to a metaclass's metaclass. This is
473# completely insane, but is exactly what happens with
474# Fey::Meta::Class::Table. It's a subclass of Moose::Meta::Class
475# itself, and then it _uses_ MooseX::ClassAttribute, so the metaclass
476# for Fey::Meta::Class::Table does a role.
477#
478# At one point this caused a metaclass incompatibility error down
479# below, when we applied roles to the metaclass of My::Class10. It's
480# all madness but as long as the tests pass we're happy.
481{
482 package My::Meta::Class2;
483 use Moose;
484 extends 'Moose::Meta::Class';
485
f785aad8 486 Moose::Util::MetaRole::apply_metaroles(
487 for => 'My::Meta::Class2',
488 class_metaroles => { class => ['Role::Foo'] },
dd37a5be 489 );
490}
491
492{
896e6f85 493 package My::Object;
494 use Moose;
495 extends 'Moose::Object';
496}
497
498{
dd37a5be 499 package My::Meta2;
500
501 use Moose::Exporter;
502 Moose::Exporter->setup_import_methods( also => 'Moose' );
503
504 sub init_meta {
505 shift;
506 my %p = @_;
507
896e6f85 508 Moose->init_meta(
509 %p,
510 metaclass => 'My::Meta::Class2',
511 base_class => 'My::Object',
512 );
dd37a5be 513 }
514}
515
516{
517 package My::Class10;
518 My::Meta2->import;
519
f785aad8 520 Moose::Util::MetaRole::apply_metaroles(
521 for => 'My::Class10',
522 class_metaroles => { class => ['Role::Bar'] },
dd37a5be 523 );
524}
525
526{
527 ok( My::Class10->meta()->meta()->meta()->does_role('Role::Foo'),
528 q{My::Class10->meta()->meta() does Role::Foo } );
b72373c4 529 ok( My::Class10->meta()->meta()->does_role('Role::Bar'),
530 q{My::Class10->meta()->meta() does Role::Bar } );
dd37a5be 531 ok( My::Class10->meta()->isa('My::Meta::Class2'),
532 q{... and My::Class10->meta still isa(My::Meta::Class2)} );
896e6f85 533 ok( My::Class10->isa('My::Object'),
534 q{... and My::Class10 still isa(My::Object)} );
dd37a5be 535}
8f05895e 536
537{
538 package My::Constructor;
539
540 use base 'Moose::Meta::Method::Constructor';
541}
542
543{
544 package My::Class11;
545
546 use Moose;
547
548 __PACKAGE__->meta->constructor_class('My::Constructor');
549
f785aad8 550 Moose::Util::MetaRole::apply_metaroles(
551 for => 'My::Class11',
552 class_metaroles => { class => ['Role::Foo'] },
8f05895e 553 );
554}
555
556{
557 ok( My::Class11->meta()->meta()->does_role('Role::Foo'),
558 q{My::Class11->meta()->meta() does Role::Foo } );
559 is( My::Class11->meta()->constructor_class, 'My::Constructor',
560 q{... and explicitly set constructor_class value is unchanged)} );
561}
fdeb8354 562
563{
564 package ExportsMoose;
565
566 Moose::Exporter->setup_import_methods(
f785aad8 567 also => 'Moose',
fdeb8354 568 );
569
570 sub init_meta {
571 shift;
572 my %p = @_;
573 Moose->init_meta(%p);
f785aad8 574 return Moose::Util::MetaRole::apply_metaroles(
3b400403 575 for => $p{for_class},
fdeb8354 576 # Causes us to recurse through init_meta, as we have to
577 # load MyMetaclassRole from disk.
3b400403 578 class_metaroles => { class => [qw/MyMetaclassRole/] },
fdeb8354 579 );
580 }
581}
582
b10dde3a 583is( exception {
fdeb8354 584 package UsesExportedMoose;
585 ExportsMoose->import;
b10dde3a 586}, undef, 'import module which loads a role from disk during init_meta' );
fdeb8354 587
b05518b2 588{
589 package Foo::Meta::Role;
590
591 use Moose::Role;
592}
f785aad8 593
b05518b2 594{
595 package Foo::Role;
596
597 Moose::Exporter->setup_import_methods(
f785aad8 598 also => 'Moose::Role',
b05518b2 599 );
600
601 sub init_meta {
602 shift;
603 my %p = @_;
f785aad8 604
b05518b2 605 Moose::Role->init_meta(%p);
f785aad8 606
607 return Moose::Util::MetaRole::apply_metaroles(
608 for => $p{for_class},
609 role_metaroles => { method => ['Foo::Meta::Role'] },
b05518b2 610 );
611 }
612}
f785aad8 613
b05518b2 614{
615 package Role::Baz;
616
617 Foo::Role->import;
618
619 sub bla {}
620}
f785aad8 621
b05518b2 622{
623 package My::Class12;
624
625 use Moose;
626
627 with( 'Role::Baz' );
628}
f785aad8 629
b05518b2 630{
631 ok(
632 My::Class12->meta->does_role( 'Role::Baz' ),
633 'role applied'
634 );
f785aad8 635
b05518b2 636 my $method = My::Class12->meta->get_method( 'bla' );
637 ok(
638 $method->meta->does_role( 'Foo::Meta::Role' ),
639 'method_metaclass_role applied'
640 );
641}
629ba321 642
643{
644 package Parent;
645 use Moose;
646
f785aad8 647 Moose::Util::MetaRole::apply_metaroles(
648 for => __PACKAGE__,
649 class_metaroles => { constructor => ['Role::Foo'] },
629ba321 650 );
651}
652
653{
654 package Child;
655
656 use Moose;
657 extends 'Parent';
658}
659
660{
661 ok(
662 Parent->meta->constructor_class->meta->can('does_role')
663 && Parent->meta->constructor_class->meta->does_role('Role::Foo'),
664 'Parent constructor class has metarole from Parent'
665 );
666
63eeb72b 667 ok(
668 Child->meta->constructor_class->meta->can('does_role')
669 && Child->meta->constructor_class->meta->does_role(
670 'Role::Foo'),
671 'Child constructor class has metarole from Parent'
672 );
629ba321 673}
a28e50e4 674
4e5b5d20 675{
676 package NotMoosey;
677
678 use metaclass;
679}
680
681{
682 like(
683 exception {
684 Moose::Util::MetaRole::apply_metaroles(
685 for => 'Does::Not::Exist',
686 class_metaroles => { class => ['Role::Foo'] },
687 );
688 },
689 qr/When using Moose::Util::MetaRole.+You passed Does::Not::Exist.+Maybe you need to call.+/,
690 'useful error when apply metaroles to a class without a metaclass'
691 );
692
693 like(
694 exception {
695 Moose::Util::MetaRole::apply_metaroles(
696 for => 'NotMoosey',
697 class_metaroles => { class => ['Role::Foo'] },
698 );
699 },
700 qr/When using Moose::Util::MetaRole.+You passed NotMoosey.+we resolved this to a Class::MOP::Class object.+/,
701 'useful error when using apply metaroles to a class with a Class::MOP::Class metaclass'
702 );
703
704 like(
705 exception {
706 Moose::Util::MetaRole::apply_base_class_roles(
707 for => 'NotMoosey',
708 roles => { class => ['Role::Foo'] },
709 );
710 },
711 qr/When using Moose::Util::MetaRole.+You passed NotMoosey.+we resolved this to a Class::MOP::Class object.+/,
712 'useful error when applying base class to roles to a non-Moose class'
713 );
714
715 like(
716 exception {
717 Moose::Util::MetaRole::apply_base_class_roles(
718 for => 'My::Role',
719 roles => { class => ['Role::Foo'] },
720 );
721 },
722 qr/You can only apply base class roles to a Moose class.+/,
723 'useful error when applying base class to roles to a non-Moose class'
724 );
725}
726
a28e50e4 727done_testing;