Group
Extension

Statocles/t/app/blog/command.t


use Test::Lib;
use My::Test;
use Capture::Tiny qw( capture );
use Statocles::App::Blog;
my $SHARE_DIR = path( __DIR__ )->parent->parent->child( 'share' );

my $site = build_test_site(
    theme => $SHARE_DIR->child( 'theme' ),
);

# We need an app we can edit
my $tmpdir = tempdir;
$tmpdir->child( 'blog' )->mkpath;

my $app = Statocles::App::Blog->new(
    store => $tmpdir->child( 'blog' ),
    url_root => '/blog',
    site => $site,
);

subtest 'errors' => sub {
    subtest 'invalid command' => sub {
        my @args = qw( blog foo );
        my ( $out, $err, $exit ) = capture { $app->command( @args ) };
        ok !$out, 'blog error is on stderr' or diag $out;
        isnt $exit, 0;
        like $err, qr{\QERROR: Unknown command "foo"}, "contains error message";
        like $err, qr{\Qblog post [--date YYYY-MM-DD] <title> -- Create a new blog post},
            'contains blog usage information';
    };

    subtest 'missing command' => sub {
        my @args = qw( blog );
        my ( $out, $err, $exit ) = capture { $app->command( @args ) };
        ok !$out, 'blog error is on stderr' or diag $out;
        isnt $exit, 0;
        like $err, qr{\QERROR: Missing command}, "contains error message";
        like $err, qr{\Qblog post [--date YYYY-MM-DD] <title> -- Create a new blog post},
            'contains blog usage information';
    };
};

subtest 'help' => sub {
    my @args = qw( blog help );
    my ( $out, $err, $exit ) = capture { $app->command( @args ) };
    ok !$err, 'blog help is on stdout';
    is $exit, 0;
    like $out, qr{\Qblog post [--date YYYY-MM-DD] <title> -- Create a new blog post},
        'contains blog help information';
};

local $ENV{EDITOR} = 'echo';

subtest 'post' => sub {
    subtest 'create new post' => sub {
        subtest 'without $EDITOR, title is required' => sub {
            no warnings 'redefine';
            # must redefine the imported version
            local *Statocles::App::Blog::read_stdin = sub { "hello" };
            local *Statocles::App::Blog::run_editor = sub { undef };
            local $ENV{EDITOR};
            my @args = qw( blog post );
            my ( $out, $err, $exit ) = capture { $app->command( @args ) };
            like $err, qr{Title is required when \$EDITOR is not set};
            like $err, qr{blog post <title>};
            isnt $exit, 0;
        };

        subtest 'default document' => sub {
            no warnings 'redefine';
            local *Statocles::App::Blog::run_editor = sub { undef };
            my ( undef, undef, undef, $day, $mon, $year ) = localtime;
            my $doc_path = $tmpdir->child(
                'blog',
                sprintf( '%04i', $year + 1900 ),
                sprintf( '%02i', $mon + 1 ),
                sprintf( '%02i', $day ),
                'this-is-a-title',
                'index.markdown',
            );

            subtest 'run the command' => sub {
                my @args = qw( blog post This is a Title );
                my ( $out, $err, $exit ) = capture { $app->command( @args ) };
                ok !$err, 'nothing on stdout';
                is $exit, 0;
                like $out, qr{New post at: \Q$doc_path},
                    'contains blog post document path';
            };

            subtest 'check the generated document' => sub {
                my $path = $doc_path->relative( $tmpdir->child('blog') )->stringify;
                my $doc = Statocles::Document->parse_content(
                    path => $path,
                    content => $doc_path->slurp_utf8,
                    store => $app->store,
                );
                cmp_deeply $doc, Statocles::Document->new(
                    path => $path,
                    title => 'This is a Title',
                    tags => undef,
                    content => <<'ENDMARKDOWN',
Markdown content goes here.
ENDMARKDOWN
                    store => $app->store,
                );
                eq_or_diff $doc_path->slurp, <<ENDCONTENT;
---
status: published
title: This is a Title
---
Markdown content goes here.
ENDCONTENT
            };
        };

        subtest 'special characters in title' => sub {
            no warnings 'redefine';
            local *Statocles::App::Blog::run_editor = sub { undef };
            my ( undef, undef, undef, $day, $mon, $year ) = localtime;
            my $doc_path = $tmpdir->child(
                'blog',
                sprintf( '%04i', $year + 1900 ),
                sprintf( '%02i', $mon + 1 ),
                sprintf( '%02i', $day ),
                'special-characters-a-retrospective-2-the-return',
                'index.markdown',
            );

            subtest 'run the command' => sub {
                my @args = qw{ blog post Special Characters: A Retrospective (2) - The Return};
                my ( $out, $err, $exit ) = capture { $app->command( @args ) };
                ok !$err, 'nothing on stdout';
                is $exit, 0;
                like $out, qr{New post at: \Q$doc_path},
                    'contains blog post document path';
            };

            subtest 'check the generated document' => sub {
                my $path = $doc_path->relative( $tmpdir->child('blog') )->stringify;
                my $doc = Statocles::Document->parse_content(
                    path => $path,
                    content => $doc_path->slurp_utf8,
                    store => $app->store,
                );
                cmp_deeply $doc, Statocles::Document->new(
                    path => $path,
                    title => 'Special Characters: A Retrospective (2) - The Return',
                    tags => undef,
                    content => <<'ENDMARKDOWN',
Markdown content goes here.
ENDMARKDOWN
                    store => $app->store,
                );
                eq_or_diff $doc_path->slurp, <<ENDCONTENT;
---
status: published
title: 'Special Characters: A Retrospective (2) - The Return'
---
Markdown content goes here.
ENDCONTENT
            };
        };

        subtest 'custom date' => sub {
            no warnings 'redefine';
            local *Statocles::App::Blog::run_editor = sub { undef };

            my $doc_path = $tmpdir->child(
                'blog', '2014', '04', '01', 'this-is-a-title', 'index.markdown',
            );

            subtest 'run the command' => sub {
                my @args = qw( blog post --date 2014-4-1 This is a Title );
                my ( $out, $err, $exit ) = capture { $app->command( @args ) };
                ok !$err, 'nothing on stdout' or diag $err;
                is $exit, 0;
                like $out, qr{New post at: \Q$doc_path},
                    'contains blog post document path';
            };

            subtest 'check the generated document' => sub {
                my $path = $doc_path->relative( $tmpdir->child( 'blog' ) )->stringify;
                my $doc = Statocles::Document->parse_content(
                    path => $path,
                    content => $doc_path->slurp_utf8,
                    store => $app->store,
                );
                cmp_deeply $doc, Statocles::Document->new(
                    path => $path,
                    title => 'This is a Title',
                    tags => undef,
                    content => <<'ENDMARKDOWN',
Markdown content goes here.
ENDMARKDOWN
                    store => $app->store,
                );
                eq_or_diff $doc_path->slurp, <<ENDCONTENT;
---
status: published
title: This is a Title
---
Markdown content goes here.
ENDCONTENT
            };
        };

        subtest 'content from STDIN' => sub {
            subtest 'without frontmatter' => sub {
                no warnings 'redefine';
                local *Statocles::App::Blog::run_editor = sub { };

                my ( undef, undef, undef, $day, $mon, $year ) = localtime;
                my $doc_path = $tmpdir->child(
                    'blog',
                    sprintf( '%04i', $year + 1900 ),
                    sprintf( '%02i', $mon + 1 ),
                    sprintf( '%02i', $day ),
                    'this-is-a-title-for-stdin',
                    'index.markdown',
                );

                subtest 'run the command' => sub {
                    no warnings 'redefine';
                    local *Statocles::App::Blog::read_stdin = sub {
                        return "This is content from STDIN\n";
                    };

                    my @args = qw( blog post This is a Title for stdin );
                    my ( $out, $err, $exit ) = capture { $app->command( @args ) };
                    ok !$err, 'nothing on stdout' or diag $err;
                    is $exit, 0;
                    like $out, qr{New post at: \Q$doc_path},
                        'contains blog post document path';
                };

                subtest 'check the generated document' => sub {
                    my $path = $doc_path->relative( $tmpdir->child('blog') )->stringify;
                    my $doc = Statocles::Document->parse_content(
                        path => $path,
                        content => $doc_path->slurp_utf8,
                        store => $app->store,
                    );
                    cmp_deeply $doc, Statocles::Document->new(
                        path => $path,
                        title => 'This is a Title for stdin',
                        tags => undef,
                        content => <<'ENDMARKDOWN',
This is content from STDIN
ENDMARKDOWN
                        store => $app->store,
                    );
                };
            };

            subtest 'author option' => sub {
                no warnings 'redefine';
                local *Statocles::App::Blog::run_editor = sub { };

                my ( undef, undef, undef, $day, $mon, $year ) = localtime;
                my $doc_path = $tmpdir->child(
                    'blog',
                    sprintf( '%04i', $year + 1900 ),
                    sprintf( '%02i', $mon + 1 ),
                    sprintf( '%02i', $day ),
                    'this-is-a-title-for-stdin',
                    'index.markdown',
                );

                subtest 'run the command' => sub {
                    no warnings 'redefine';
                    local *Statocles::App::Blog::read_stdin = sub {
                        return "This is content from STDIN\n";
                    };

                    my @args = qw( blog post --author iasimov This is a Title for stdin );
                    my ( $out, $err, $exit ) = capture { $app->command( @args ) };
                    ok !$err, 'nothing on stdout' or diag $err;
                    is $exit, 0;
                    like $out, qr{New post at: \Q$doc_path},
                        'contains blog post document path';
                };

                subtest 'check the generated document' => sub {
                    my $path = $doc_path->relative( $tmpdir->child('blog') )->stringify;
                    my $doc = Statocles::Document->parse_content(
                        path => $path,
                        content => $doc_path->slurp_utf8,
                        store => $app->store,
                    );
                    cmp_deeply $doc, Statocles::Document->new(
                        path => $path,
                        title => 'This is a Title for stdin',
                        author => 'iasimov',
                        tags => undef,
                        content => <<'ENDMARKDOWN',
This is content from STDIN
ENDMARKDOWN
                        store => $app->store,
                    );
                };
            };

            subtest 'with frontmatter' => sub {
                no warnings 'redefine';
                local *Statocles::App::Blog::run_editor = sub { };

                my ( undef, undef, undef, $day, $mon, $year ) = localtime;
                my $doc_path = $tmpdir->child(
                    'blog',
                    sprintf( '%04i', $year + 1900 ),
                    sprintf( '%02i', $mon + 1 ),
                    sprintf( '%02i', $day ),
                    'this-is-frontmatter',
                    'index.markdown',
                );

                subtest 'run the command' => sub {
                    no warnings 'redefine';
                    local *Statocles::App::Blog::read_stdin = sub {
                        return <<ENDSTDIN;
---
title: This is Frontmatter
tags: one, two
---
This is content from STDIN
ENDSTDIN
                    };

                    my @args = qw( blog post );
                    my ( $out, $err, $exit ) = capture { $app->command( @args ) };
                    ok !$err, 'nothing on stdout' or diag $err;
                    is $exit, 0;
                    like $out, qr{New post at: \Q$doc_path},
                        'contains blog post document path';

                };

                subtest 'check the generated document' => sub {
                    my $path = $doc_path->relative( $tmpdir->child('blog') )->stringify;
                    my $doc = Statocles::Document->parse_content(
                        path => $path,
                        content => $doc_path->slurp_utf8,
                        store => $app->store,
                    );
                    cmp_deeply $doc, Statocles::Document->new(
                        path => $path,
                        title => 'This is Frontmatter',
                        tags => [qw( one two )],
                        content => <<'ENDMARKDOWN',
This is content from STDIN
ENDMARKDOWN
                        store => $app->store,
                    );
                };
            };

        };


        subtest 'title change creates different folder' => sub {
            no warnings 'redefine';
            local *Statocles::App::Blog::run_editor = sub {
                $SHARE_DIR->child(qw( app blog draft a-draft-post.markdown ))->slurp_utf8;
            };

            my ( undef, undef, undef, $day, $mon, $year ) = localtime;
            my $doc_path = $tmpdir->child(
                'blog',
                sprintf( '%04i', $year + 1900 ),
                sprintf( '%02i', $mon + 1 ),
                sprintf( '%02i', $day ),
                'a-draft',
                'index.markdown',
            );

            subtest 'run the command' => sub {
                my @args = qw( blog post );
                my ( $out, $err, $exit ) = capture { $app->command( @args ) };
                ok !$err, 'nothing on stdout' or diag $err;
                is $exit, 0;
                like $out, qr{New post at: \Q$doc_path},
                    'contains blog post document path';
            };

            subtest 'check the generated document' => sub {
                my $path = $doc_path->relative( $tmpdir->child('blog') )->stringify;
                my $doc = Statocles::Document->parse_content(
                    path => $path.'',
                    content => $doc_path->slurp_utf8,
                    store => $app->store,
                );
                my $content = "Draft body content\n";
                cmp_deeply $doc, Statocles::Document->new(
                    path => $path.'',
                    title => 'A Draft',
                    author => 'preaction',
                    date => DateTimeObj->coerce( '2014-06-21 00:06:00' ),
                    content => $content,
                    store => $app->store,
                );

                ok !$doc_path->parent->parent->child( 'new-post' )->exists, 'new-post dir is cleaned up';
            };
        };

    };
};

done_testing;


Powered by Groonga
Maintained by Kenichi Ishigaki <ishigaki@cpan.org>. If you find anything, submit it on GitHub.