App-karr
view release on metacpan or search on metacpan
t/07-context.t view on Meta::CPAN
use strict;
use warnings;
use lib 't/lib';
use Test::More;
use File::Temp qw( tempdir );
use Path::Tiny;
use YAML::XS qw( DumpFile );
use Time::Piece;
use App::karr::Task;
use App::karr::Config;
use App::karr::Cmd::Context;
use MockStore;
subtest 'context markdown rendering' => sub {
my $dir = tempdir(CLEANUP => 1);
my $board = path($dir)->child('karr');
$board->mkpath;
my $tasks = $board->child('tasks');
$tasks->mkpath;
DumpFile($board->child('config.yml')->stringify, App::karr::Config->default_config);
# Create tasks in various states
App::karr::Task->new(
id => 1, title => 'Active Task', status => 'in-progress',
priority => 'high',
)->save($tasks->stringify);
App::karr::Task->new(
id => 2, title => 'Blocked Task', status => 'in-progress',
priority => 'medium', blocked => 'waiting on API',
)->save($tasks->stringify);
App::karr::Task->new(
id => 3, title => 'Done Task', status => 'done',
priority => 'low', completed => gmtime->strftime('%Y-%m-%d'),
)->save($tasks->stringify);
# Load and verify tasks
my @files = sort $tasks->children(qr/\.md$/);
is scalar @files, 3, 'three task files created';
my @loaded = map { App::karr::Task->from_file($_) } @files;
my @in_progress = grep { $_->status eq 'in-progress' && !$_->has_blocked } @loaded;
is scalar @in_progress, 1, 'one active non-blocked task';
my @blocked = grep { $_->has_blocked } @loaded;
is scalar @blocked, 1, 'one blocked task';
};
subtest 'write-to with sentinels' => sub {
my $dir = tempdir(CLEANUP => 1);
my $file = path($dir)->child('AGENTS.md');
# Write initial content
my $context = "<!-- BEGIN kanban-md context -->\n## Board: Test\n<!-- END kanban-md context -->\n";
$file->spew_utf8("# My Agents\n\n" . $context);
# Update with new context
my $new_context = "<!-- BEGIN kanban-md context -->\n## Board: Updated\n<!-- END kanban-md context -->\n";
my $content = $file->slurp_utf8;
$content =~ s/<!-- BEGIN kanban-md context -->.*<!-- END kanban-md context -->\n?/$new_context/s;
$file->spew_utf8($content);
my $result = $file->slurp_utf8;
like $result, qr/# My Agents/, 'preserves existing content';
like $result, qr/Board: Updated/, 'updated context';
unlike $result, qr/Board: Test/, 'old context replaced';
};
# Regression: karr context crashed with
# Can't locate object method "strftime" via package "Sun May 24 ..."
# because Cmd::Context never did `use Time::Piece`, so gmtime returned a
# plain string in the overdue / recently-completed / _count_overdue paths.
# These subtests drive the real command through every gmtime->strftime branch.
subtest 'context command runs without strftime crash' => sub {
my $today = gmtime->strftime('%Y-%m-%d');
my @tasks = (
App::karr::Task->new(
id => 1, title => 'Active', status => 'in-progress', priority => 'high',
),
App::karr::Task->new(
id => 2, title => 'Overdue', status => 'todo', priority => 'medium',
due => '2000-01-01',
),
App::karr::Task->new(
id => 3, title => 'Recently Done', status => 'done', priority => 'low',
completed => $today,
),
);
# Plain markdown output exercises overdue (line ~112) and _count_overdue
# (line ~221) gmtime->strftime calls.
my $cmd = App::karr::Cmd::Context->new( store => MockStore->new( tasks => \@tasks ) );
my $md;
my $err = do {
local $@;
eval {
local *STDOUT;
( run in 1.185 second using v1.01-cache-2.11-cpan-df04353d9ac )