t/unit/MGH_Biostat/Locale/POCatalog.t


#!/usr/bin/env perl
use Modern::Perl '2013';
use Test2::V0;
use Test2::Tools::Spec;

use Path::Tiny;
use MGH_Biostat::Locale::POCatalog;

describe 'new' => sub {
    my $dir = t::unit::MGH_Biostat::Locale::POCatalog::catalog_new();

    tests 'new' => sub {
        my $catalog;

        is(
            warnings { $catalog = MGH_Biostat::Locale::POCatalog->new( dir => $dir, default_lang => 'test' ); },
            [ "Missing translation for [test||missing translation]; setting to msgid.\n" ],
            'warns about missing translation'
        );

        is(
            $catalog,
            object {
                prop 'blessed'       => 'MGH_Biostat::Locale::POCatalog';
                field 'default_lang' => 'test';
                field 'dir'          => "$dir" . '/';

                field 'data' => hash {
                    field 'test' => hash {
                        field 'test'                => object { prop 'blessed' => 'MGH_Biostat::Locale::PO'; };
                        field 'missing translation' => object { prop 'blessed' => 'MGH_Biostat::Locale::PO'; };
                        etc();
                    };
                    etc();
                };
                etc();
            },
            'POCatalog created correctly'
        );
    };

};

describe 'is_valid_lang' => sub {
    my $dir = t::unit::MGH_Biostat::Locale::POCatalog::catalog_regular();
    my $catalog = MGH_Biostat::Locale::POCatalog->new( dir => $dir );

    tests 'is_valid_lang' => sub {
        is( $catalog->is_valid_lang('en'),   T(), 'en valid' );
        is( $catalog->is_valid_lang('test'), T(), 'test valid' );
        is( $catalog->is_valid_lang('inv'),  F(), 'inv not valid' );
    };
};

describe 'lookup' => sub {
    my $dir = t::unit::MGH_Biostat::Locale::POCatalog::catalog_regular();
    my $catalog = MGH_Biostat::Locale::POCatalog->new( dir => $dir, default_lang => 'en' );

    tests 'regular use' => sub {
        is( $catalog->lookup( 'test', 'test' ), object { call 'msgstr' => 'test_test'; }, 'simple test lookup works' );
        is( $catalog->lookup( 'en',   'test' ), object { call 'msgstr' => 'en_test'; },   'simple en lookup works' );
    };

    tests 'invalid_lang' => sub {
        my $ret;

        is(
            warnings { $ret = $catalog->lookup( 'inv', 'test' ); },
            [ match qr/^Language inv not supported./ ],
            'invalid language warns'
        );
        is(
            $ret,
            object {
                prop 'blessed' => 'MGH_Biostat::Locale::PO';
                call 'msgid'   => 'test';
                call 'msgstr'  => 'test';
            },
            'returned object is correct (msgstr is same as msgid)'
        );
    };

    tests 'fallback' => sub {
        my $ret;

        is(
            warnings { $ret = $catalog->lookup( 'test', 'only en' ); },
            [ match qr/^\QKey [|only en] not defined for test.\E/ ],
            'fall back warns'
        );

        is(
            $ret,
            object {
                prop 'blessed' => 'MGH_Biostat::Locale::PO';
                call 'msgid'   => 'only en';
                call 'msgstr'  => 'only valid in en file';
            },
            'returned PO object is correct'
        );
    };

    tests 'unknown' => sub {
        my $ret;

        is(
            warnings { $ret = $catalog->lookup( 'test', 'not defined' ); },
            [ match qr/^\QKey [|not defined] not defined for any lang.\E/ ],
            'undefined translation warns'
        );

        is(
            $ret,
            object {
                prop 'blessed' => 'MGH_Biostat::Locale::PO';
                call 'msgid'   => 'not defined';
                call 'msgstr'  => 'not defined';
            },
            'returned PO object is correct'
        );
    };

    tests 'context' => sub {
        my $ctxa = $catalog->lookup( 'test', 'test_context', 'A' );
        is(
            $ctxa,
            object {
                prop 'blessed' => 'MGH_Biostat::Locale::PO';
                call 'msgstr'  => 'test_A';
            },
            'context A correct'
        );

        my $ctxb = $catalog->lookup( 'test', 'test_context', 'B' );
        is(
            $ctxb,
            object {
                prop 'blessed' => 'MGH_Biostat::Locale::PO';
                call 'msgstr'  => 'test_B';
            },
            'context B correct'
        );

        my $ctxfail;
        is(
            warnings { $ctxfail = $catalog->lookup( 'test', 'test_context', 'C' ); },
            [ match qr/^\QKey [C|test_context] not defined for any lang.\E/ ],
            'warns on invalid context'
        );
        is(
            $ctxfail,
            object {
                prop 'blessed' => 'MGH_Biostat::Locale::PO';
                call 'msgstr'  => 'test_context';
            },
            'returns supplied msgid when context fails'
        );
    };

};

done_testing();

BEGIN {

    package t::unit::MGH_Biostat::Locale::POCatalog {
        use Path::Tiny;

        sub catalog_new {
            my $dir = Path::Tiny->tempdir();
            $dir->child('test.po')->spew_utf8(<<'EOPO');
#: test
msgid "test"
msgstr "test string"

#: test missing translation
msgid "missing translation"
msgstr ""
EOPO
            return $dir;
        }

        sub catalog_regular {
            my $dir = Path::Tiny->tempdir();
            $dir->child('test.po')->spew_utf8(<<'EOPO');
# Test "test" po file
msgid ""
msgstr ""
"Language: test\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#: test 1
msgid "test"
msgstr "test_test"

#: test context b
msgctxt "A"
msgid "test_context"
msgstr "test_A"

#: test context B
msgctxt "B"
msgid "test_context"
msgstr "test_B"
EOPO

            $dir->child('en.po')->spew_utf8(<<'EOPO');
# Test "en" po file
msgid ""
msgstr ""
"Language: en\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#: test 1
msgid "test"
msgstr "en_test"

#: test context b
msgctxt "A"
msgid "test_context"
msgstr "en_A"

#: test context B
msgctxt "B"
msgid "test_context"
msgstr "en_B"

#: test fallback
msgid "only en"
msgstr "only valid in en file"
EOPO

            return $dir;
        }
    }
}