Ancient

 view release on metacpan or  search on metacpan

t/4007-object-edge-cases.t  view on Meta::CPAN

    eval { $wrapper->wrapped({a => 1}) };
    like($@, qr/Type constraint failed/, 'Object rejects plain hashref');

    eval { $wrapper->wrapped('string') };
    like($@, qr/Type constraint failed/, 'Object rejects string');

    # Object accepts any blessed reference
    my $blessed_array = bless [], 'SomeClass';
    $wrapper->wrapped($blessed_array);
    isa_ok($wrapper->wrapped, 'SomeClass', 'Object accepts any blessed ref');
};

# ==== Bool Edge Cases ====

subtest 'Bool edge cases' => sub {
    object::define('BoolClass', 'flag:Bool');

    my $obj = new BoolClass;

    # Standard booleans
    $obj->flag(1);
    is($obj->flag, 1, 'Bool accepts 1');

    $obj->flag(0);
    is($obj->flag, 0, 'Bool accepts 0');

    $obj->flag('');
    is($obj->flag, '', 'Bool accepts empty string');

    # Bool rejects non-0/1 integers
    eval { $obj->flag(2) };
    like($@, qr/Type constraint failed/, 'Bool rejects 2');

    # Bool accepts truthy values (Perl-style boolean)
    $obj->flag('true');
    ok($obj->flag, 'Bool accepts "true" string (truthy)');

    $obj->flag([]);
    ok(ref($obj->flag) eq 'ARRAY', 'Bool accepts arrayref (truthy)');
};

# ==== Int Edge Cases ====

subtest 'Int edge cases' => sub {
    object::define('IntClass', 'num:Int');

    my $obj = new IntClass num => 0;

    is($obj->num, 0, 'Int accepts 0');

    $obj->num(-999);
    is($obj->num, -999, 'Int accepts negative');

    $obj->num(999999999);
    is($obj->num, 999999999, 'Int accepts large positive');

    # Float should be rejected or truncated
    eval { $obj->num(3.14) };
    like($@, qr/Type constraint failed/, 'Int rejects float');

    # String that looks like int
    $obj->num('42');
    is($obj->num, '42', 'Int accepts numeric string');

    eval { $obj->num('42.5') };
    like($@, qr/Type constraint failed/, 'Int rejects decimal string');
};

# ==== Num Edge Cases ====

subtest 'Num edge cases' => sub {
    object::define('NumClass', 'value:Num');

    my $obj = new NumClass value => 0;

    $obj->value(3.14159);
    ok(abs($obj->value - 3.14159) < 0.00001, 'Num accepts float');

    $obj->value(-273.15);
    ok(abs($obj->value - -273.15) < 0.00001, 'Num accepts negative float');

    $obj->value(1e10);
    is($obj->value, 1e10, 'Num accepts scientific notation');

    $obj->value('123.456');
    ok(abs($obj->value - 123.456) < 0.00001, 'Num accepts numeric string');
};

# ==== Default Expression Freshness ====

subtest 'default array freshness' => sub {
    object::define('ArrayDefaultClass', 'items:ArrayRef:default([])');

    my $obj1 = new ArrayDefaultClass;
    my $obj2 = new ArrayDefaultClass;

    push @{$obj1->items}, 'item1';
    is_deeply($obj1->items, ['item1'], 'first object has item');
    is_deeply($obj2->items, [], 'second object still empty (fresh array)');

    # Verify they're different references
    ok($obj1->items != $obj2->items, 'different array references');
};

subtest 'default hash freshness' => sub {
    object::define('HashDefaultClass', 'data:HashRef:default({})');

    my $obj1 = new HashDefaultClass;
    my $obj2 = new HashDefaultClass;

    $obj1->data->{key} = 'value';
    is_deeply($obj1->data, {key => 'value'}, 'first object has key');
    is_deeply($obj2->data, {}, 'second object still empty (fresh hash)');

    ok($obj1->data != $obj2->data, 'different hash references');
};

subtest 'default undef' => sub {
    object::define('UndefDefaultClass', 'value:Any:default(undef)');

    my $obj = new UndefDefaultClass;



( run in 2.422 seconds using v1.01-cache-2.11-cpan-140bd7fdf52 )