Chandra

 view release on metacpan or  search on metacpan

t/46_assets_edge.t  view on Meta::CPAN

    );

    for my $bad (@bad_paths) {
        eval { $a->read($bad) };
        like($@, qr/traversal/i, "blocked: $bad");
    }
}

# ---- Backslash rejection ----

{
    my $a = Chandra::Assets->new(root => $dir);

    eval { $a->read('sub\\nested.js') };
    like($@, qr/traversal/i, 'backslash path rejected');
}

# ---- Empty file ----

{
    my $a = Chandra::Assets->new(root => $dir);

    my $content = $a->read('empty.css');
    is($content, '', 'read empty file returns empty string');

    my $tag = $a->inline_css('empty.css');
    is($tag, '<style></style>', 'inline_css on empty file');
}

# ---- Binary file read ----

{
    my $a = Chandra::Assets->new(root => $dir);
    my $content = $a->read('binary.bin');
    ok(defined $content, 'read binary file');
    is(length($content), 4, 'binary content correct length');
}

# ---- Missing file ----

{
    my $a = Chandra::Assets->new(root => $dir);

    ok(!$a->exists('nonexistent.xyz'), 'missing file not found');

    eval { $a->inline_css('nonexistent.css') };
    like($@, qr/Cannot read/, 'inline_css on missing file croaks');

    eval { $a->inline_js('nonexistent.js') };
    like($@, qr/Cannot read/, 'inline_js on missing file croaks');

    eval { $a->inline_image('nonexistent.png') };
    like($@, qr/Cannot read/, 'inline_image on missing file croaks');
}

# ---- Unicode filename ----

{
    my $a = Chandra::Assets->new(root => $dir);
    my $uname = "caf\xc3\xa9.txt";  # UTF-8 bytes for café
    eval { _write("$dir/$uname", "unicode content") };

    SKIP: {
        skip "filesystem doesn't support unicode", 2 if $@ || !-f "$dir/$uname";
        ok($a->exists($uname), 'unicode filename exists');
        is($a->read($uname), "unicode content", 'read unicode filename');
    }
}

# ---- Deeply nested path ----

{
    my $a = Chandra::Assets->new(root => $dir);
    is($a->read('sub/deep/a.css'), 'a {}', 'read deeply nested file');
    ok($a->exists('sub/deep/a.css'), 'deeply nested file exists');
}

# ---- Unknown extension MIME ----

{
    my $a = Chandra::Assets->new(root => $dir);
    is($a->mime_type('file.xyz123'), 'application/octet-stream', 'unknown ext');
    is($a->mime_type('no-dot'), 'application/octet-stream', 'no extension');
    is($a->mime_type('.hidden'), 'application/octet-stream', 'dot-only name');
}

# ---- Large MIME type coverage ----

{
    my $a = Chandra::Assets->new(root => $dir);

    my @extra = (
        ['file.htm',   'text/html'],
        ['file.xml',   'application/xml'],
        ['file.csv',   'text/csv'],
        ['file.md',    'text/markdown'],
        ['file.bmp',   'image/bmp'],
        ['file.otf',   'font/otf'],
        ['file.ogg',   'audio/ogg'],
        ['file.wav',   'audio/wav'],
        ['file.wasm',  'application/wasm'],
        ['file.pdf',   'application/pdf'],
        ['file.zip',   'application/zip'],
        ['file.mjs',   'application/javascript'],
    );

    for my $case (@extra) {
        is($a->mime_type($case->[0]), $case->[1], "mime: $case->[0]");
    }
}

# ---- Multiple roots (separate instances) ----

{
    my $dir2 = tempdir(CLEANUP => 1);
    _write("$dir2/other.txt", "other content");

    my $a1 = Chandra::Assets->new(root => $dir);
    my $a2 = Chandra::Assets->new(root => $dir2);

    ok($a1->exists('file.txt'),    'a1 has its file');
    ok(!$a1->exists('other.txt'),  'a1 does not have a2 file');
    ok($a2->exists('other.txt'),   'a2 has its file');
    ok(!$a2->exists('file.txt'),   'a2 does not have a1 file');
}



( run in 1.700 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )