Ancient

 view release on metacpan or  search on metacpan

t/4019-object-introspection.t  view on Meta::CPAN

# ==== Setup Test Classes ====

object::define('Person',
    'name:Str:required',
    'age:Int:default(0)',
    'email:Str:readonly',
    'bio:Str:lazy:builder(_build_bio)',
    'tags:ArrayRef:default([])',
);

package Person;
sub _build_bio { "Default bio for " . shift->name }
package main;

object::define('Simple', 'foo', 'bar', 'baz');

# ==== object::clone() Tests ====

subtest 'clone() basic functionality' => sub {
    my $p = new Person name => 'Alice', age => 30, email => 'alice@example.com';
    my $clone = object::clone($p);

    isa_ok($clone, 'Person', 'Clone is same class');
    isnt($clone, $p, 'Clone is different reference');
    is($clone->name, 'Alice', 'Clone has same name');
    is($clone->age, 30, 'Clone has same age');
    is($clone->email, 'alice@example.com', 'Clone has same email');
};

subtest 'clone() shallow copy semantics' => sub {
    my $p = new Person name => 'Carol', age => 35, email => 'carol@example.com';
    push @{$p->tags}, 'original';

    my $clone = object::clone($p);

    # Both should see the same array reference
    is_deeply($p->tags, ['original'], 'Original has tag');
    is_deeply($clone->tags, ['original'], 'Clone shares same array');

    # Modify original's array
    push @{$p->tags}, 'added';

    # Clone should see the change (shallow copy = shared reference)
    is_deeply($clone->tags, ['original', 'added'],
        'Shallow copy shares references');
};

subtest 'clone() does not copy frozen state' => sub {
    my $p = new Person name => 'Dave', age => 40, email => 'dave@example.com';
    object::freeze($p);
    ok(object::is_frozen($p), 'Original is frozen');

    my $clone = object::clone($p);
    ok(!object::is_frozen($clone), 'Clone is not frozen');

    # Clone should be mutable
    $clone->age(41);
    is($clone->age, 41, 'Clone can be modified');
};

subtest 'clone() does not copy locked state' => sub {
    my $p = new Person name => 'Eve', age => 28, email => 'eve@example.com';
    object::lock($p);
    ok(object::is_locked($p), 'Original is locked');

    my $clone = object::clone($p);
    ok(!object::is_locked($clone), 'Clone is not locked');
};

subtest 'clone() with undef slots' => sub {
    my $s = new Simple foo => 'x';
    # bar and baz are undef
    my $clone = object::clone($s);

    is($clone->foo, 'x', 'Clone has foo value');
    ok(!defined $clone->bar, 'Clone bar is undef');
    ok(!defined $clone->baz, 'Clone baz is undef');
};

subtest 'clone() error handling' => sub {
    eval { object::clone("not an object") };
    like($@, qr/not an object/i, 'Croaks on non-object');

    eval { object::clone([1,2,3]) };
    like($@, qr/not an object/i, 'Croaks on plain arrayref');
};

# ==== object::properties() Tests ====

subtest 'properties() list context' => sub {
    my @props = object::properties('Person');
    is(scalar @props, 5, 'Person has 5 properties');
    ok((grep { $_ eq 'name' } @props), 'name in list');
    ok((grep { $_ eq 'age' } @props), 'age in list');
    ok((grep { $_ eq 'email' } @props), 'email in list');
    ok((grep { $_ eq 'bio' } @props), 'bio in list');
    ok((grep { $_ eq 'tags' } @props), 'tags in list');
};

subtest 'properties() scalar context' => sub {
    my $count = object::properties('Person');
    is($count, 5, 'Person has 5 properties (scalar)');
};

subtest 'properties() simple class' => sub {
    my @props = object::properties('Simple');
    is(scalar @props, 3, 'Simple has 3 properties');
    is_deeply([sort @props], ['bar', 'baz', 'foo'], 'Simple properties correct');
};

subtest 'properties() non-existent class' => sub {
    my @props = object::properties('NonExistent');
    is(scalar @props, 0, 'Empty list for non-existent class');

    my $count = object::properties('NonExistent');
    is($count, 0, 'Zero count for non-existent class');
};

# ==== object::slot_info() Tests ====

subtest 'slot_info() required typed property' => sub {
    my $info = object::slot_info('Person', 'name');
    is(ref $info, 'HASH', 'Returns hashref');
    is($info->{name}, 'name', 'name field correct');
    is($info->{index}, 1, 'index field correct (first property is slot 1)');
    is($info->{type}, 'Str', 'type field correct');
    is($info->{is_required}, 1, 'is_required is true');



( run in 0.490 second using v1.01-cache-2.11-cpan-df04353d9ac )