AnyEvent-WebService-Tracks

 view release on metacpan or  search on metacpan

Makefile.PL  view on Meta::CPAN

    AUTHOR              => q{Rob Hoelz <rob@hoelz.ro>},
    VERSION_FROM        => 'lib/AnyEvent/WebService/Tracks.pm',
    ABSTRACT_FROM       => 'lib/AnyEvent/WebService/Tracks.pm',
    ($ExtUtils::MakeMaker::VERSION >= 6.3002
      ? ('LICENSE'=> 'perl')
      : ()),
    PL_FILES            => {},
    PREREQ_PM => {
        'AnyEvent'                  => 0,
        'AnyEvent::HTTP'            => 0,
        'DateTime'                  => 0,
        'DateTime::Format::ISO8601' => 0,
        'FindBin'                   => 0,
        'List::MoreUtils'           => 0,
        'MIME::Base64'              => 0,
        'namespace::clean'          => 0,
        'Scalar::Util'              => 0,
        'Storable'                  => 0,
        'Test::Exception'           => 0,
        'Test::More'                => 0,
        'URI'                       => 0,
        'XML::Parser'               => 0,

lib/AnyEvent/WebService/Tracks.pm  view on Meta::CPAN

package AnyEvent::WebService::Tracks;

use strict;
use warnings;

use AnyEvent::HTTP qw(http_request);
use Carp qw(croak);
use DateTime;
use DateTime::Format::ISO8601;
use MIME::Base64 qw(encode_base64);
use URI;
use XML::Parser;
use XML::Writer;

use AnyEvent::WebService::Tracks::Context;
use AnyEvent::WebService::Tracks::Project;
use AnyEvent::WebService::Tracks::Todo;

our $VERSION = '0.02';

lib/AnyEvent/WebService/Tracks.pm  view on Meta::CPAN

    return bless {
        url      => URI->new($params{url}),
        username => $params{username},
        password => $params{password},
    }, $class;
}

sub parse_datetime {
    my ( $self, $str ) = @_;

    return DateTime::Format::ISO8601->parse_datetime($str);
}

sub format_datetime {
    my ( $self, $datetime ) = @_;

    my @fields = qw/year month day hour minute second/;
    my %attrs = map { $_ => $datetime->$_() } @fields;
    my $offset = DateTime::TimeZone->offset_as_string($datetime->offset);

    return sprintf '%04d-%02d-%02dT%02d:%02d:%02d%s', @attrs{@fields}, $offset;
}

sub handle_error {
    my ( $self, $body, $headers, $cb ) = @_;

    my $message;

    if($body) {

lib/AnyEvent/WebService/Tracks.pm  view on Meta::CPAN

    my $xml  = '';
    my $w    = XML::Writer->new(OUTPUT => \$xml);
    my @keys = sort keys %$attrs;

    $w->startTag($root);
    foreach my $k (@keys) {
        my $v = $attrs->{$k};
        my @xml_attrs;

        push @xml_attrs, (nil => 'true') unless defined $v;
        if(ref($v) eq 'DateTime') {
            push @xml_attrs, (type => 'datetime');
            $v = $self->format_datetime($v);
        }

        my $nk = $k;
        $nk =~ tr/_/-/;

        $w->startTag($nk, @xml_attrs);
        $w->characters($v) if defined $v;
        $w->endTag($nk);

lib/AnyEvent/WebService/Tracks/Todo.pm  view on Meta::CPAN

        $self->{'_dirty'}{'show_from'} = 1;
    }
}

sub defer {
    my ( $self, $amount ) = @_;

    my $show_from;

    if(! ref($amount)) {
        $show_from = DateTime->now->add(days => $amount);
    } elsif(ref($amount) eq 'DateTime') {
        $show_from = $amount;
    } elsif(ref($amount) eq 'DateTime::Duration') {
        $show_from = DateTime->now->add_duration($amount);
    }

    $self->{'show_from'}           = $show_from;
    $self->{'_dirty'}{'show_from'} = 1;
}

sub context {
    my ( $self, $cb_or_ctx ) = @_;

    if(ref($cb_or_ctx) eq 'CODE') {

lib/AnyEvent/WebService/Tracks/Todo.pm  view on Meta::CPAN

=head2 $todo->complete

Mark this todo item as complete on its next update.

=head2 $todo->activate

Mark this todo item as active on its next update.

=head2 $todo->defer($amount)

Defer this todo item.  C<$amount> can be a DateTime, a
DateTime::Duration, or simply an integer (which is interpreted
as the number of days to defer the item.)

=head1 AUTHOR

Rob Hoelz, C<< rob at hoelz.ro >>

=head1 BUGS

Please report any bugs or feature requests to C<bug-AnyEvent-WebService-Tracks at rt.cpan.org>, or through
the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=AnyEvent-WebService-Tracks>. I will

t/02-context.t  view on Meta::CPAN

    $run = sub {
        my $name = shift @contexts;

        $tracks->create_context($name, sub {
            my ( $ctx ) = @_;

            ok($ctx);
            isa_ok($ctx, 'AnyEvent::WebService::Tracks::Context');
            is($ctx->name, $name);
            ok(looks_like_number $ctx->id);
            isa_ok($ctx->created_at, 'DateTime');
            isa_ok($ctx->updated_at, 'DateTime');
            ok(looks_like_number $ctx->position);
            ok(! $ctx->is_hidden);

            dies_ok {
                $ctx->id(0);
            };
            lives_ok {
                $ctx->name('New Name');
            };
            dies_ok {
                $ctx->created_at(DateTime->now);
            };
            dies_ok {
                $ctx->updated_at(DateTime->now);
            };
            lives_ok {
                $ctx->position(1);
            };
            lives_ok {
                $ctx->hide;
            };
            lives_ok {
                $ctx->unhide;
            };

t/02-context.t  view on Meta::CPAN

    $run = sub {
        my $name = shift @contexts;

        $tracks->create_context(name => $name, sub {
            my ( $ctx ) = @_;

            ok($ctx);
            isa_ok($ctx, 'AnyEvent::WebService::Tracks::Context');
            is($ctx->name, $name);
            ok(looks_like_number $ctx->id);
            isa_ok($ctx->created_at, 'DateTime');
            isa_ok($ctx->updated_at, 'DateTime');
            ok(looks_like_number $ctx->position);
            ok(! $ctx->is_hidden);

            dies_ok {
                $ctx->id(0);
            };
            lives_ok {
                $ctx->name('New Name');
            };
            dies_ok {
                $ctx->created_at(DateTime->now);
            };
            dies_ok {
                $ctx->updated_at(DateTime->now);
            };
            lives_ok {
                $ctx->position(1);
            };
            lives_ok {
                $ctx->hide;
            };
            lives_ok {
                $ctx->unhide;
            };

t/02-context.t  view on Meta::CPAN

    $run = sub {
        my $name = shift @contexts;

        $tracks->create_context(name => $name, hide => 1, sub {
            my ( $ctx ) = @_;

            ok($ctx);
            isa_ok($ctx, 'AnyEvent::WebService::Tracks::Context');
            is($ctx->name, $name);
            ok(looks_like_number $ctx->id);
            isa_ok($ctx->created_at, 'DateTime');
            isa_ok($ctx->updated_at, 'DateTime');
            ok(looks_like_number $ctx->position);
            ok($ctx->is_hidden);

            dies_ok {
                $ctx->id(0);
            };
            lives_ok {
                $ctx->name('New Name');
            };
            dies_ok {
                $ctx->created_at(DateTime->now);
            };
            dies_ok {
                $ctx->updated_at(DateTime->now);
            };
            lives_ok {
                $ctx->position(1);
            };
            lives_ok {
                $ctx->hide;
            };
            lives_ok {
                $ctx->unhide;
            };

t/03-project.t  view on Meta::CPAN

            ok($proj);
            isa_ok($proj, 'AnyEvent::WebService::Tracks::Project');
            is($proj->name, $name);
            ok(! defined($proj->description));

            ok(looks_like_number $proj->position);
            ok(! defined($proj->completed_at));
            ok(! $proj->is_complete);
            ok(! $proj->is_hidden);
            ok($proj->is_active);
            isa_ok($proj->created_at, 'DateTime');
            isa_ok($proj->updated_at, 'DateTime');

            dies_ok {
                $proj->completed_at(DateTime->now);
            };
            dies_ok {
                $proj->created_at(DateTime->now);
            };
            dies_ok {
                $proj->id(0);
            };
            dies_ok {
                $proj->updated_at(DateTime->now);
            };

            lives_ok {
                $proj->description('Phony description');
            };
            lives_ok {
                $proj->name('Another name');
            };
            lives_ok {
                $proj->position(4);

t/03-project.t  view on Meta::CPAN

            ok($proj);
            isa_ok($proj, 'AnyEvent::WebService::Tracks::Project');
            is($proj->name, $name);
            ok(! defined($proj->description));
            ok(looks_like_number $proj->id);
            ok(looks_like_number $proj->position);
            ok(! defined($proj->completed_at));
            ok(! $proj->is_complete);
            ok(! $proj->is_hidden);
            ok($proj->is_active);
            isa_ok($proj->created_at, 'DateTime');
            isa_ok($proj->updated_at, 'DateTime');

            dies_ok {
                $proj->completed_at(DateTime->now);
            };
            dies_ok {
                $proj->created_at(DateTime->now);
            };
            dies_ok {
                $proj->id(0);
            };
            dies_ok {
                $proj->updated_at(DateTime->now);
            };

            lives_ok {
                $proj->description('Phony description');
            };
            lives_ok {
                $proj->name('Another name');
            };
            lives_ok {
                $proj->position(4);

t/03-project.t  view on Meta::CPAN


            ok($proj);
            isa_ok($proj, 'AnyEvent::WebService::Tracks::Project');
            is($proj->name, $name);
            is($proj->description, $desc);
            ok(looks_like_number $proj->position);
            ok(! defined($proj->completed_at));
            ok(! $proj->is_complete);
            ok(! $proj->is_hidden);
            ok($proj->is_active);
            isa_ok($proj->created_at, 'DateTime');
            isa_ok($proj->updated_at, 'DateTime');

            dies_ok {
                $proj->completed_at(DateTime->now);
            };
            dies_ok {
                $proj->created_at(DateTime->now);
            };
            dies_ok {
                $proj->id(0);
            };
            dies_ok {
                $proj->updated_at(DateTime->now);
            };

            lives_ok {
                $proj->description('Phony description');
            };
            lives_ok {
                $proj->description('Another name');
            };
            lives_ok {
                $proj->position(4);

t/04-todo.t  view on Meta::CPAN

            ok(! defined($todo->due));
            ok(! defined($todo->notes));
            ok(! defined($todo->show_from));
            ok($todo->is_active);
            ok(! $todo->is_project_hidden);
            ok(! $todo->is_complete);
            ok(! $todo->is_deferred);
            ok(looks_like_number $todo->id);
            ok(! $todo->completed_at);
            ok(! $todo->recurring_todo_id);
            isa_ok($todo->created_at, 'DateTime');
            isa_ok($todo->updated_at, 'DateTime');

            dies_ok {
                $todo->completed_at(DateTime->now);
            };
            dies_ok {
                $todo->created_at(DateTime->now);
            };
            dies_ok {
                $todo->updated_at(DateTime->now);
            };
            dies_ok {
                $todo->id(0);
            };
            dies_ok {
                $todo->recurring_todo_id(0);
            };

            lives_ok {
                $todo->description('Test description');
            };
            lives_ok {
                $todo->due(DateTime->now);
            };
            lives_ok {
                $todo->notes('Test notes');
            };
            lives_ok {
                $todo->show_from(DateTime->now);
            };

            $todo->context(sub {
                my ( $c ) = @_;

                is($c->id, $ctx->id);

                $todo->project(sub {
                    my ( $p, $e ) = @_;

t/04-todo.t  view on Meta::CPAN

            ok(! defined($todo->due));
            ok(! defined($todo->notes));
            ok(! defined($todo->show_from));
            ok($todo->is_active);
            ok(! $todo->is_project_hidden);
            ok(! $todo->is_complete);
            ok(! $todo->is_deferred);
            ok(looks_like_number $todo->id);
            ok(! $todo->completed_at);
            ok(! $todo->recurring_todo_id);
            isa_ok($todo->created_at, 'DateTime');
            isa_ok($todo->updated_at, 'DateTime');

            dies_ok {
                $todo->completed_at(DateTime->now);
            };
            dies_ok {
                $todo->created_at(DateTime->now);
            };
            dies_ok {
                $todo->updated_at(DateTime->now);
            };
            dies_ok {
                $todo->id(0);
            };
            dies_ok {
                $todo->recurring_todo_id(0);
            };

            lives_ok {
                $todo->description('Test description');
            };
            lives_ok {
                $todo->due(DateTime->now);
            };
            lives_ok {
                $todo->notes('Test notes');
            };
            lives_ok {
                $todo->show_from(DateTime->now);
            };

            $todo->context(sub {
                my ( $c ) = @_;

                is($c->id, $ctx->id);

                $todo->project(sub {
                    my ( $p, $e ) = @_;

t/04-todo.t  view on Meta::CPAN

            is($todo->notes, $notes);
            ok(! defined($todo->due));
            ok(! defined($todo->show_from));
            ok($todo->is_active);
            ok(! $todo->is_project_hidden);
            ok(! $todo->is_complete);
            ok(! $todo->is_deferred);
            ok(looks_like_number $todo->id);
            ok(! $todo->completed_at);
            ok(! $todo->recurring_todo_id);
            isa_ok($todo->created_at, 'DateTime');
            isa_ok($todo->updated_at, 'DateTime');

            dies_ok {
                $todo->completed_at(DateTime->now);
            };
            dies_ok {
                $todo->created_at(DateTime->now);
            };
            dies_ok {
                $todo->updated_at(DateTime->now);
            };
            dies_ok {
                $todo->id(0);
            };
            dies_ok {
                $todo->recurring_todo_id(0);
            };

            lives_ok {
                $todo->description('Test description');
            };
            lives_ok {
                $todo->due(DateTime->now);
            };
            lives_ok {
                $todo->notes('Test notes');
            };
            lives_ok {
                $todo->show_from(DateTime->now);
            };

            $todo->context(sub {
                my ( $c ) = @_;

                is($c->id, $ctx->id);

                $todo->project(sub {
                    my ( $p, $e ) = @_;

t/04-todo.t  view on Meta::CPAN

            });
        };

        $run->();
    });
};

run_tests_in_loop {
    my ( $cond ) = @_;

    my $now      = DateTime->now;
    my $other    = $now->clone->add(days => 7, hours => 3, minutes => 1);
    my $duration = DateTime::Duration->new(days => 7, hours => 3, minutes => 1);
    my @defer    = (
        1         => $now->clone->add(days => 1),
        $other    => $other,
        $duration => $other,
    );

    $tracks->create_todo(
        description => 'Deferred Task',
        context     => $ctx,
        show_from   => $now->clone->add(days => 1),

t/04-todo.t  view on Meta::CPAN

            });
        };

        $run->();
    });
};

run_tests_in_loop {
    my ( $cond ) = @_;

    my $time = DateTime->now;
    $time->set_hour(17);
    $time->set_minute(0);
    $time->set_second(0);

    $tracks->create_todo(
        description => 'Another Deferred Task',
        context     => $ctx,
        show_from   => $time->clone->add(days => 1),
    sub {
        my ( $todo ) = @_;

t/04-todo.t  view on Meta::CPAN

            $expected->set_second(0);
        };
        is($todo->show_from, $expected);
        $cond->send;
    });
};

run_tests_in_loop {
    my ( $cond ) = @_;

    my $time = DateTime->now;
    $time->set_hour(20);
    $time->set_minute(0);
    $time->set_second(0);

    $tracks->create_todo(
        description => 'Yet Another Deferred Task',
        context     => $ctx,
        show_from   => $time->clone->add(days => 1),
    sub {
        my ( $todo ) = @_;



( run in 0.318 second using v1.01-cache-2.11-cpan-05444aca049 )