### ----------------------------------------------------
### -- Cro::Core
### -- Licenses: Artistic-2.0
### -- Authors: Jonathan Worthington <jnthn@jnthn.net>
### -- File: t/mediatype.rakutest
### ----------------------------------------------------
use Cro::MediaType;
use Test;

sub parses($media-type, $desc, &checks) {
    my $parsed;
    lives-ok { $parsed = Cro::MediaType.parse($media-type) }, $desc;
    checks($parsed) if $parsed;
}

sub refuses($media-type, $desc) {
    dies-ok { Cro::MediaType.parse($media-type) }, $desc;
}

parses 'text/plain', 'Simple text/plain media type', {
    is .type, 'text', 'Correct type';
    is .subtype, 'plain', 'Correct subtype';
    is .subtype-name, 'plain', 'Correct subtype name';
    is .tree, '', 'No tree';
    is .suffix, '', 'No suffix';
    is .parameters.elems, 0, 'No parameters';
    is .Str, 'text/plain', 'Stringifies correctly';
};

parses 'application/vnd.foobar+json', 'Vendor media type with suffix', {
    is .type, 'application', 'Correct type';
    is .subtype, 'vnd.foobar+json', 'Correct subtype';
    is .subtype-name, 'foobar', 'Correct subtype name';
    is .tree, 'vnd', 'Correct tree';
    is .suffix, 'json', 'Correct suffix';
    is .parameters.elems, 0, 'No parameters';
    is .Str, 'application/vnd.foobar+json', 'Stringifies correctly';
};

parses 'text/plain; charset=UTF-8', 'text/plain media type with charset', {
    is .type, 'text', 'Correct type';
    is .subtype, 'plain', 'Correct subtype';
    is .subtype-name, 'plain', 'Correct subtype name';
    is .tree, '', 'No tree';
    is .suffix, '', 'No suffix';
    is-deeply .parameters.List, ('charset' => 'UTF-8',), 'Correct parameter';
    is .Str, 'text/plain; charset=UTF-8', 'Stringifies correctly';
};

parses 'text/plain; charset="UTF-8"', 'text/plain media type with charset quoted', {
    is .type, 'text', 'Correct type';
    is .subtype, 'plain', 'Correct subtype';
    is .subtype-name, 'plain', 'Correct subtype name';
    is .tree, '', 'No tree';
    is .suffix, '', 'No suffix';
    is-deeply .parameters.List, ('charset' => 'UTF-8',), 'Correct parameter';
    is .Str, 'text/plain; charset=UTF-8', 'Stringifies correctly';
};

parses 'application/vnd.foobar; foo="bar\"d"; baz="\""', 'Parameters with escape', {
    is .type, 'application', 'Correct type';
    is .subtype, 'vnd.foobar', 'Correct subtype';
    is .subtype-name, 'foobar', 'Correct subtype name';
    is .tree, 'vnd', 'Correct tree';
    is .suffix, '', 'No suffix';
    is-deeply .parameters.List, ('foo' => 'bar"d', 'baz' => '"'),
        'Correct parameters';
    is .Str, 'application/vnd.foobar; foo="bar\"d"; baz="\""', 'Stringifies correctly';
};

parses 'text/plain; charset=UTF-8;', 'Media type with stray ; after parameter', {
    is .type, 'text', 'Correct type';
    is .subtype, 'plain', 'Correct subtype';
    is .subtype-name, 'plain', 'Correct subtype name';
    is .tree, '', 'No tree';
    is .suffix, '', 'No suffix';
    is-deeply .parameters.List, ('charset' => 'UTF-8',), 'Correct parameter';
    is .Str, 'text/plain; charset=UTF-8', 'Stringifies correctly';
};

parses 'application/json; charset=utf-8; api-version=7.1-preview.1', 'Media type with . in parameter', {
    is .type, 'application', 'Correct type';
    is .subtype, 'json', 'Correct subtype';
    is .subtype-name, 'json', 'Correct subtype name';
    is .tree, '', 'No tree';
    is .suffix, '', 'No suffix';
    is-deeply .parameters.List, ('charset' => 'utf-8', api-version => '7.1-preview.1'), 'Correct parameters';
    is .Str, 'application/json; charset=utf-8; api-version=7.1-preview.1', 'Stringifies correctly';
};

parses 'text/plain;', 'Media type with stray ; at end, but no parameters', {
    is .type, 'text', 'Correct type';
    is .subtype, 'plain', 'Correct subtype';
    is .subtype-name, 'plain', 'Correct subtype name';
    is .tree, '', 'No tree';
    is .suffix, '', 'No suffix';
    is-deeply .parameters.List, (), 'No parameters';
    is .Str, 'text/plain', 'Stringifies correctly';
};

parses 'application/vnd.pgrst.object+json', 'Multiple dotted parts in the name', {
    is .type, 'application', 'Correct type';
    is .subtype, 'vnd.pgrst.object+json', 'Correct subtype';
    is .subtype-name, 'pgrst.object', 'Correct subtype name';
    is .tree, 'vnd', 'Correct tree';
    is .suffix, 'json', 'No suffix';
    is-deeply .parameters.List, (), 'Correct parameters';
    is .Str, 'application/vnd.pgrst.object+json', 'Stringifies correctly';
}
parses 'application/vnd.pgrst.object+some+other+data+json', 'Multiple + parts in the name', {
    is .type, 'application', 'Correct type';
    is .subtype, 'vnd.pgrst.object+some+other+data+json', 'Correct subtype';
    is .subtype-name, 'pgrst.object+some+other+data', 'Correct subtype name';
    is .tree, 'vnd', 'Correct tree';
    is .suffix, 'json', 'No suffix';
    is-deeply .parameters.List, (), 'Correct parameters';
    is .Str, 'application/vnd.pgrst.object+some+other+data+json', 'Stringifies correctly';
}

refuses 'text', 'No /subtype';
refuses 'text', 'No subtype';
refuses 'x{y}/plain', 'Bad chars in type';
refuses 'text/z{d}', 'Bad chars in subtype';

parses 'application/x-amz-json-1.1', 'Can handle subtype x-amz-json-1.1', {
    is .type, 'application', 'Correct type';
    is .subtype, 'x-amz-json-1.1', 'Correct subtype';
}

done-testing;


