Ancient

 view release on metacpan or  search on metacpan

t/4024-object-roles.t  view on Meta::CPAN

object::role('Serializable',
    'format:Str:default("json")',
);

# Add a method to the role
package Serializable;
sub serialize { 
    my ($self) = @_;
    return "serialized:" . $self->format; 
}
package main;

# Define a class
object::define('Document',
    'title:Str:required',
    'content:Str',
);

# Apply the role
object::with('Document', 'Serializable');

# Test 1: Class has role's slots
my $doc = Document->new(title => "Test");
ok($doc->can('format'), 'Document has format accessor from role');
is($doc->format, 'json', 'Default value from role slot works');

# Test 2: Class has role's methods
ok($doc->can('serialize'), 'Document has serialize method from role');
is($doc->serialize, 'serialized:json', 'Role method works');

# Test 3: object::does check
ok(object::does($doc, 'Serializable'), 'Object does Serializable');
ok(object::does('Document', 'Serializable'), 'Class does Serializable');
ok(!object::does($doc, 'NonExistent'), 'Object does not do NonExistent');

# Test 4: Role with required methods
object::role('Printable');
object::requires('Printable', 'to_string');

# Define class with required method
package PrintableDoc;
sub to_string { 
    my ($self) = @_;
    return $self->title; 
}
package main;

object::define('PrintableDoc', 'title:Str');
eval { object::with('PrintableDoc', 'Printable') };
ok(!$@, 'Class with required method consumes role OK');

# Test 5: Role without required method fails
object::define('BadDoc', 'title:Str');
eval { object::with('BadDoc', 'Printable') };
ok($@, 'Class without required method fails');
like($@, qr/does not implement required method 'to_string'/, 'Error mentions missing method');

# Test 6: Multiple roles
object::role('Timestamped',
    'created_at:Str',
    'updated_at:Str',
);

object::define('Article',
    'title:Str:required',
);
object::with('Article', 'Serializable', 'Timestamped');

my $article = Article->new(title => "News");
ok($article->can('format'), 'Article has Serializable slot');
ok($article->can('created_at'), 'Article has Timestamped slot');
ok(object::does($article, 'Serializable'), 'Article does Serializable');
ok(object::does($article, 'Timestamped'), 'Article does Timestamped');

# Test 7: Slot conflict detection
object::role('Conflicting',
    'title:Str',  # Same as Article's slot
);

eval { object::with('Article', 'Conflicting') };
ok($@, 'Slot conflict detected');
like($@, qr/Slot conflict.*'title'/, 'Error mentions conflicting slot');

done_testing();



( run in 0.729 second using v1.01-cache-2.11-cpan-e1769b4cff6 )