2 # This is automatically generated by author/import-moose-test.pl.
3 # DO NOT EDIT THIS FILE. ANY CHANGES WILL BE LOST!!!
4 use t::lib::MooseCompat;
10 $TODO = q{Mouse is not yet completed};
14 my ( $role, $method ) = @_;
15 local $Test::Builder::Level = $Test::Builder::Level + 1;
18 $role->has_method($method) || $role->requires_method($method),
19 $role->name . " has or requires method $method"
22 fail("role has or requires method $method");
30 # this role eventually adds three methods, qw(foo bar xxy), but only one is
31 # known when it's still a role
33 has foo => ( is => "rw" );
35 has gorch => ( reader => "bar" );
42 # similarly this role gives attr and gorch_method
44 has attr => ( is => "rw" );
46 sub gorch_method { "gorch method" }
48 around dandy => sub { shift->(@_) . "bar" };
55 # this object will be used in an attr of Foo to test that Foo can do the
65 package Dancer::Ballerina;
74 package Dancer::Robot;
77 # this doesn't fail but it produces a requires in the role
78 # the order doesn't matter
79 has twist => ( is => "rw" );
80 ::lives_ok { with qw(Dancer) };
82 package Dancer::Something;
85 # this fail even though the method already exists
87 has twist => ( is => "rw" );
90 ::lives_ok { with qw(Dancer) };
96 # this should pass because ::Robot has the attribute to fill in the requires
97 # but due to the deferrence logic that doesn't actually work
99 local our $TODO = "attribute accessor in role doesn't satisfy role requires";
100 ::lives_ok { with qw(Dancer::Robot) };
110 handles => "Gorch", # should handles take the same arguments as 'with'? Meta::Role::Application::Delegation?
111 default => sub { Quxx->new },
118 default => sub { Dancer::Ballerina->new },
130 has bark => ( is => "rw" );
135 sub bark { warn "woof!" };
141 local our $TODO = "attrs and methods from a role should clash";
142 ::dies_ok { with qw(Tree Dog) }
146 # these fail because of the deferral logic winning over actual methods
147 # this might be tricky to fix due to the 'sub foo {}; has foo => ( )' hack
148 # we've been doing for a long while, though I doubt people relied on it for
149 # anything other than fulfilling 'requires'
151 local $TODO = "attributes from role overwrite class methods";
152 is( Foo->new->foo, 42, "attr did not zap overriding method" );
153 is( Foo->new->bar, 33, "attr did not zap overriding method" );
155 is( Foo->new->xxy, 7, "method did not zap overriding method" ); # duh
157 # these pass, simple delegate
158 # mostly they are here to contrast the next blck
159 can_ok( Foo->new->oink, "dandy" );
160 can_ok( Foo->new->oink, "attr" );
161 can_ok( Foo->new->oink, "gorch_method" );
163 ok( Foo->new->oink->does("Gorch"), "Quxx does Gorch" );
166 # these are broken because 'attr' is not technically part of the interface
167 can_ok( Foo->new, "gorch_method" );
169 local $TODO = "accessor methods from a role are omitted in handles role";
170 can_ok( Foo->new, "attr" );
174 local $TODO = "handles role doesn't add the role to the ->does of the delegate's parent class";
175 ok( Foo->new->does("Gorch"), "Foo does Gorch" );
180 can_ok( Foo->new->dancer, "pirouette" );
181 can_ok( Foo->new->dancer, "twist" );
183 can_ok( Foo->new, "twist" );
184 ok( !Foo->new->can("pirouette"), "can't pirouette, not part of the iface" );
187 local $TODO = "handles role doesn't add the role to the ->does of the delegate's parent class";
188 ok( Foo->new->does("Dancer") );
194 my $gorch = Gorch->meta;
196 isa_ok( $gorch, "Mouse::Meta::Role" );
198 ok( $gorch->has_attribute("attr"), "has attribute 'attr'" );
199 isa_ok( $gorch->get_attribute("attr"), "Mouse::Meta::Role::Attribute" );
201 req_or_has($gorch, "gorch_method");
202 ok( $gorch->has_method("gorch_method"), "has_method gorch_method" );
203 ok( !$gorch->requires_method("gorch_method"), "requires gorch method" );
204 isa_ok( $gorch->get_method("gorch_method"), "Mouse::Meta::Method" );
207 local $TODO = "method modifier doesn't yet create a method requirement or meta object";
208 req_or_has($gorch, "dandy" );
210 # this specific test is maybe not backwards compat, but in theory it *does*
211 # require that method to exist
212 ok( $gorch->requires_method("dandy"), "requires the dandy method for the modifier" );
216 local $TODO = "attribute related methods are not yet known by the role";
217 # we want this to be a part of the interface, somehow
218 req_or_has($gorch, "attr");
219 ok( $gorch->has_method("attr"), "has_method attr" );
220 isa_ok( $gorch->get_method("attr"), "Mouse::Meta::Method" );
221 isa_ok( $gorch->get_method("attr"), "Mouse::Meta::Method" );
224 my $robot = Dancer::Robot->meta;
226 isa_ok( $robot, "Mouse::Meta::Role" );
228 ok( $robot->has_attribute("twist"), "has attr 'twist'" );
229 isa_ok( $robot->get_attribute("twist"), "Mouse::Meta::Role::Attribute" );
232 req_or_has($robot, "twist");
234 local $TODO = "attribute related methods are not yet known by the role";
235 ok( $robot->has_method("twist"), "has twist method" );
236 isa_ok( $robot->get_method("twist"), "Mouse::Meta::Method" );
237 isa_ok( $robot->get_method("twist"), "Mouse::Meta::Method" );
244 I think Attribute needs to be refactored in some way to better support roles.
246 There are several possible ways to do this, all of them seem plausible to me.
248 The first approach would be to change the attribute class to allow it to be
249 queried about the methods it would install.
251 Then we instantiate the attribute in the role, and instead of deferring the
252 arguments, we just make an C<unpack>ish method.
254 Then we can interrogate the attr when adding it to the role, and generate stub
255 methods for all the methods it would produce.
257 A second approach is kinda like the Immutable hack: wrap the attr in an
258 anonmyous class that disables part of its interface.
260 A third method would be to create an Attribute::Partial object that would
261 provide a more role-ish behavior, and to do this independently of the actual
264 Something similar can be done for method modifiers, but I think that's even simpler.
268 The benefits of doing this are:
270 * Much better introspection of roles
272 * More correctness in many cases (in my opinion anyway)
274 * More roles are more usable as interface declarations, without having to split
275 them into two pieces (one for the interface with a bunch of requires(), and
276 another for the actual impl with the problematic attrs (and stub methods to
277 fix the accessors) and method modifiers (dunno if this can even work at all)