The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
package Test::WWW::PivotalTracker;

use strict;
use warnings;

use base qw(Test::Class);

use Sub::Override;
use Test::Most;

sub make_fixture : Test(setup => 1)
{
    my $self = shift;

    use_ok('WWW::PivotalTracker');

    $self->{'override'} = Sub::Override->new(
        'WWW::PivotalTracker::_post_request' => sub($$) {
            die "You should override _post_request, so you're not depending on PivotalTracker being available.";
        }
    );
}

sub TEST__IS_ONE_OF : Test(4)
{
    is(
        WWW::PivotalTracker->_is_one_of('foo', [qw/ foo /]),
        1,
        "foo is in [qw/ foo /]",
    );

    is(
        WWW::PivotalTracker->_is_one_of('bar', [qw/ foo /]),
        0,
        "bar is not in [qw/ foo /]",
    );

    is(
        WWW::PivotalTracker->_is_one_of('foo', [qw/ bar baz foo qux /]),
        1,
        "Find element, even if it's not the first one in the list.",
    );

    is(
        WWW::PivotalTracker->_is_one_of('cheese', [qw/ bar baz foo qux /]),
        0,
        "Doesn't find element, even if there's more than one element in the list.",
    );
}

sub TEST__CHECK_PROJECT_ID : Test(3)
{
    is(
        WWW::PivotalTracker->_check_project_id(1234),
        1,
        "'1234' is a valid project id",
    );

    is(
        WWW::PivotalTracker->_check_project_id('12a34'),
        0,
        "'12a34' is not a valid project id",
    );

    is(
        WWW::PivotalTracker->_check_project_id('a'),
        0,
        "'a' is not a valid project id",
    );
}

sub TEST__CHECK_STORY_ID : Test(3)
{
    is(
        WWW::PivotalTracker->_check_story_id(1234),
        1,
        "'1234' is a valid story id",
    );

    is(
        WWW::PivotalTracker->_check_story_id('12a34'),
        0,
        "'12a34' is not a valid story id",
    );

    is(
        WWW::PivotalTracker->_check_story_id('a'),
        0,
        "'a' is not a valid story id",
    );
}

sub TEST__DO_REQUEST__ARRAYIFIES_ELEMENTS_THAT_COULD_APPEAR_MORE_THAN_ONCE : Test(4)
{
    my $self = shift;

    $self->{'override'}->replace(
        'WWW::PivotalTracker::_post_request' => sub($$) {
            return <<"            HERE";
<?xml version="1.0" encoding="UTF-8"?>
<response success="true">
  <story>
    <id type="integer">320532</id>
    <story_type>release</story_type>
    <url>https://www.pivotaltracker.com/story/show/320532</url>
    <estimate type="integer">-1</estimate>
    <current_state>unscheduled</current_state>
    <description></description>
    <name>Release 1</name>
    <requested_by>Jacob Helwig</requested_by>
    <created_at>Dec 20, 2008</created_at>
    <deadline>Dec 31, 2008</deadline>
    <notes type="array">
      <note>
        <id type="integer">209033</id>
        <text>Comment!</text>
        <author>Jacob Helwig</author>
        <noted_at type="datetime">Dec 20, 2008</noted_at>
      </note>
    </notes>
    <labels>needs feedback</labels>
  </story>
</response>
            HERE
        }
    );

    my $response = WWW::PivotalTracker->_do_request('token', 'some/place', 'GET');

    ok(defined $response);

    isa_ok(
        $response->{'story'},
        'ARRAY',
        '$response->{story}',
    );

    isa_ok(
        $response->{'story'}->[0]->{'notes'}->{'note'},
        'ARRAY',
        '$response->{story}->[0]->{notes}->{note}',
    );
}

sub TEST__SANITIZE_STORY_XML : Test(4)
{
    my $self = shift;

    $self->{'override'}->replace(
        'WWW::PivotalTracker::_post_request' => sub($$) {
            return <<"            HERE";
<?xml version="1.0" encoding="UTF-8"?>
<story>
  <id type="integer">320532</id>
  <story_type>release</story_type>
  <url>https://www.pivotaltracker.com/story/show/320532</url>
  <estimate type="integer">-1</estimate>
  <current_state>unscheduled</current_state>
  <description></description>
  <name>Release 1</name>
  <requested_by>Jacob Helwig</requested_by>
  <created_at type="datetime">Dec 20, 2008</created_at>
  <deadline type="datetime">Dec 31, 2008</deadline>
  <notes type="array">
    <note>
      <id type="integer">209033</id>
      <text>Comment!</text>
      <author>Jacob Helwig</author>
      <noted_at type="datetime">Dec 20, 2008</noted_at>
    </note>
  </notes>
  <labels>needs feedback</labels>
</story>
            HERE
        }
    );

    my $response = WWW::PivotalTracker->_do_request('c0ffe', 'request/goes/here', 'GET');
    isa_ok($response, 'HASH', '_do_request return value');

    eq_or_diff(
        $response,
        {
            created_at    => {
                type    => 'datetime',
                content => 'Dec 20, 2008',
            },
            current_state => 'unscheduled',
            deadline      => {
                type    => 'datetime',
                content => 'Dec 31, 2008',
            },
            description   => undef,
            estimate      => { type => 'integer', content => '-1', },
            id            => { type => 'integer', content => '320532', },
            name          => 'Release 1',
            requested_by  => 'Jacob Helwig',
            story_type    => 'release',
            url           => 'https://www.pivotaltracker.com/story/show/320532',
            labels        => 'needs feedback',
            notes         => {
                type => 'array',
                note => [{
                    author   => 'Jacob Helwig',
                    noted_at => {
                        type    => 'datetime',
                        content => 'Dec 20, 2008',
                    },
                    id       => { type => 'integer', content => '209033', },
                    text     => 'Comment!',
                }],
            },
        },
        '$response ok',
    );

    my $sanitized_response = WWW::PivotalTracker->_sanitize_story_xml($response);
    isa_ok($sanitized_response, 'HASH', '_sanitize_story_xml return value');

    eq_or_diff(
        $sanitized_response,
        {
            accepted_at   => undef,
            created_at    => 'Dec 20, 2008',
            current_state => 'unscheduled',
            deadline      => 'Dec 31, 2008',
            description   => undef,
            estimate      => '-1',
            id            => '320532',
            labels        => [ 'needs feedback', ],
            name          => 'Release 1',
            requested_by  => 'Jacob Helwig',
            owned_by      => undef,
            story_type    => 'release',
            url           => 'https://www.pivotaltracker.com/story/show/320532',
            notes => [{
                author => 'Jacob Helwig',
                date   => 'Dec 20, 2008',
                id     => '209033',
                text   => 'Comment!',
            }],
        },
        '$sanitized_response ok',
    );
}

sub TEST_PROJECT_DETAILS__BASE_CASE : Test(3)
{
    my $self = shift;

    $self->{'override'}->replace(
        'WWW::PivotalTracker::_post_request' => sub($$) {
            return <<"            HERE";
<?xml version="1.0" encoding="UTF-8"?>
<project>
  <name>Sample Project</name>
  <iteration_length type="integer">2</iteration_length>
  <week_start_day>Monday</week_start_day>
  <point_scale>0,1,2,3</point_scale>
</project>
            HERE
        }
    );

    use_ok('WWW::PivotalTracker', qw/ project_details /);

    my $response = project_details('c0ffe', 1);

    isa_ok($response, 'HASH', 'project_details return value');

    eq_or_diff(
        $response,
        {
            success         => 'true',
            iteration_weeks => '2',
            name            => 'Sample Project',
            point_scale     => '0,1,2,3',
            start_day       => 'Monday',
        },
        "project_details response ok"
    );
}

sub TEST_PROJECT_DETAILS__HANDLES_WHEN_SUCCESS_IS_NOT_TRUE : Test(3)
{
    my $self = shift;

    $self->{'override'}->replace(
        'WWW::PivotalTracker::_post_request' => sub($$) { die }
    );

    use_ok('WWW::PivotalTracker', qw/ project_details /);

    my $response = project_details('c0ffe', 1);

    isa_ok($response, 'HASH', 'project_details return value');

    eq_or_diff(
        $response,
        { success => 'false' },
        "project_details response ok"
    );
}

sub TEST_SHOW_STORY__BASE_CASE : Test(3)
{
    my $self = shift;

    $self->{'override'}->replace(
        'WWW::PivotalTracker::_post_request' => sub($$) {
            return <<"            HERE";
<?xml version="1.0" encoding="UTF-8"?>
<story>
  <id type="integer">320532</id>
  <story_type>release</story_type>
  <url>https://www.pivotaltracker.com/story/show/320532</url>
  <estimate type="integer">-1</estimate>
  <current_state>unscheduled</current_state>
  <description></description>
  <name>Release 1</name>
  <requested_by>Jacob Helwig</requested_by>
  <created_at type="datetime">Dec 20, 2008</created_at>
  <deadline type="datetime">Dec 31, 2008</deadline>
  <notes type="array">
    <note>
      <id type="integer">209033</id>
      <text>Comment!</text>
      <author>Jacob Helwig</author>
      <noted_at type="datetime">Dec 20, 2008</noted_at>
    </note>
  </notes>
  <labels>needs feedback</labels>
</story>
            HERE
        }
    );

    use_ok('WWW::PivotalTracker', qw/ show_story /);

    my $response = show_story('c0ffe', 1, 320532);
    isa_ok($response, 'HASH', 'show_story return value');

    eq_or_diff(
        $response,
        {
            success       => 'true',
            accepted_at   => undef,
            created_at    => 'Dec 20, 2008',
            current_state => 'unscheduled',
            deadline      => 'Dec 31, 2008',
            description   => undef,
            estimate      => '-1',
            id            => '320532',
            labels        => [ 'needs feedback', ],
            name          => 'Release 1',
            requested_by  => 'Jacob Helwig',
            owned_by      => undef,
            story_type    => 'release',
            url           => 'https://www.pivotaltracker.com/story/show/320532',
            notes => [{
                author => 'Jacob Helwig',
                date   => 'Dec 20, 2008',
                id     => '209033',
                text   => 'Comment!',
            }],
        },
        'show_story ok',
    );
}

sub TEST_SHOW_STORY__HANDLES_WHEN_SUCCESS_IS_NOT_TRUE : Test(3)
{
    my $self = shift;

    $self->{'override'}->replace(
        'WWW::PivotalTracker::_post_request' => sub($$) { die }
    );

    use_ok('WWW::PivotalTracker', qw/ show_story /);

    my $response = show_story('c0ffe', 1, 320532);
    isa_ok($response, 'HASH', 'show_story return value');

    eq_or_diff(
        $response,
        { success => 'false' },
        'show_story ok',
    );
}

sub TEST_ALL_STORIES__BASE_CASE : Test(3)
{
    my $self = shift;

    $self->{'override'}->replace(
        'WWW::PivotalTracker::_post_request' => sub($$) {
            return <<"            HERE";
<?xml version="1.0" encoding="UTF-8"?>
<stories type="array" count="2" total="2">
  <story>
    <id type="integer">320532</id>
    <story_type>release</story_type>
    <url>https://www.pivotaltracker.com/story/show/320532</url>
    <estimate type="integer">-1</estimate>
    <current_state>unscheduled</current_state>
    <description></description>
    <name>Release 1</name>
    <requested_by>Jacob Helwig</requested_by>
    <created_at type="datetime">Dec 20, 2008</created_at>
    <deadline type="datetime">Dec 31, 2008</deadline>
    <notes type="array">
      <note>
        <id type="integer">209033</id>
        <text>Comment!</text>
        <author>Jacob Helwig</author>
        <noted_at type="datetime">Dec 20, 2008</noted_at>
      </note>
      <note>
        <id type="integer">209034</id>
        <text>Another comment!</text>
        <author>Jacob Helwig</author>
        <noted_at type="datetime">Dec 20, 2008</noted_at>
      </note>
    </notes>
  </story>
  <story>
    <id type="integer">320008</id>
    <story_type>feature</story_type>
    <url>https://www.pivotaltracker.com/story/show/320008</url>
    <estimate type="integer">-1</estimate>
    <current_state>unscheduled</current_state>
    <description></description>
    <name>Story!</name>
    <requested_by>Jacob Helwig</requested_by>
    <created_at type="datetime">Dec 20, 2008</created_at>
    <labels>needs feedback</labels>
  </story>
</stories>
            HERE
        }
    );

    use_ok('WWW::PivotalTracker', qw/ all_stories /);

    my $response = all_stories('c0ffe', 1);
    isa_ok($response, 'HASH', 'all_stories return value');

    eq_or_diff(
        $response,
        {
            success => 'true',
            stories => [
                {
                    accepted_at   => undef,
                    created_at    => 'Dec 20, 2008',
                    current_state => 'unscheduled',
                    deadline      => 'Dec 31, 2008',
                    description   => undef,
                    estimate      => '-1',
                    id            => '320532',
                    labels        => undef,
                    name          => 'Release 1',
                    requested_by  => 'Jacob Helwig',
                    owned_by      => undef,
                    story_type    => 'release',
                    url           => 'https://www.pivotaltracker.com/story/show/320532',
                    notes => [
                    {
                        author => 'Jacob Helwig',
                        date   => 'Dec 20, 2008',
                        id     => '209033',
                        text   => 'Comment!'
                    },
                    {
                        author => 'Jacob Helwig',
                        date   => 'Dec 20, 2008',
                        id     => '209034',
                        text   => 'Another comment!'
                    }
                    ],
                },
                {
                    accepted_at   => undef,
                    created_at    => 'Dec 20, 2008',
                    current_state => 'unscheduled',
                    deadline      => undef,
                    description   => undef,
                    estimate      => '-1',
                    id            => '320008',
                    name          => 'Story!',
                    notes         => undef,
                    requested_by  => 'Jacob Helwig',
                    owned_by      => undef,
                    story_type    => 'feature',
                    url           => 'https://www.pivotaltracker.com/story/show/320008',
                    labels => [
                    'needs feedback'
                    ],
                }
            ],
        },
        'all_stories ok',
    );
}

sub TEST_ALL_STORIES__HANDLES_WHEN_SUCCESS_IS_NOT_TRUE : Test(3)
{
    my $self = shift;

    $self->{'override'}->replace(
        'WWW::PivotalTracker::_post_request' => sub($$) { die }
    );

    use_ok('WWW::PivotalTracker', qw/ all_stories /);

    my $response = all_stories('c0ffe', 1);
    isa_ok($response, 'HASH', 'show_story return value');

    eq_or_diff(
        $response,
        { success => 'false' },
        'show_story ok',
    );
}

sub TEST_STORIES_FOR_FILTER__URL_ENCODES_FILTER : Test(2)
{
    my $self = shift;

    my $query_string;

    $self->{'override'}->replace(
        'WWW::PivotalTracker::_do_request' => sub($$$$;$) {
            $query_string = $_[2];

            return {
                success => 'false',
                errors  => [ 'Dummy Data', ],
            };
        }
    );

    use_ok('WWW::PivotalTracker', qw/ stories_for_filter /);

    my $response = stories_for_filter('c0ffe', 1, 'This should be URL <Encoded>');

    eq_or_diff($query_string, "projects/1/stories?filter=This%20should%20be%20URL%20%3CEncoded%3E", "stories_for_filter URL encodes filter");
}

sub TEST_STORIES_FOR_FILTER__SANITIZES_STORY_XML : Test(3)
{
    my $self = shift;

    $self->{'override'}->replace(
        'WWW::PivotalTracker::_post_request' => sub($$) {
            return <<"            HERE";
<?xml version="1.0" encoding="UTF-8"?>
<stories type="array" count="2" total="2" filter="requested_by:'Jacob Helwig'">
<story>
  <id type="integer">320532</id>
  <story_type>release</story_type>
  <url>https://www.pivotaltracker.com/story/show/320532</url>
  <estimate type="integer">-1</estimate>
  <current_state>unscheduled</current_state>
  <description></description>
  <name>Release 1</name>
  <requested_by>Jacob Helwig</requested_by>
  <created_at type="datetime">Dec 20, 2008</created_at>
  <deadline type="datetime">Dec 31, 2008</deadline>
  <notes type="array">
    <note>
      <id type="integer">209033</id>
      <text>Comment!</text>
      <author>Jacob Helwig</author>
      <noted_at type="datetime">Dec 20, 2008</noted_at>
    </note>
    <note>
      <id type="integer">209034</id>
      <text>Another comment!</text>
      <author>Jacob Helwig</author>
      <noted_at type="datetime">Dec 20, 2008</noted_at>
    </note>
  </notes>
</story>
<story>
  <id type="integer">320008</id>
  <story_type>feature</story_type>
  <url>https://www.pivotaltracker.com/story/show/320008</url>
  <estimate type="integer">-1</estimate>
  <current_state>unscheduled</current_state>
  <description></description>
  <name>Story!</name>
  <requested_by>Jacob Helwig</requested_by>
  <created_at type="datetime">Dec 20, 2008</created_at>
  <labels>needs feedback</labels>
</story>
</stories>
            HERE
        }
    );

    use_ok('WWW::PivotalTracker', qw/ stories_for_filter /);

    my $response = stories_for_filter('c0ffe', 1, 'requested_by:"Jacob Helwig"');
    isa_ok($response, 'HASH', 'stories_for_filter return value');

    eq_or_diff(
        $response,
        {
            filter => q{requested_by:'Jacob Helwig'},
            success => 'true',
            stories => [
                {
                    accepted_at   => undef,
                    created_at    => 'Dec 20, 2008',
                    current_state => 'unscheduled',
                    deadline      => 'Dec 31, 2008',
                    description   => undef,
                    estimate      => '-1',
                    id            => '320532',
                    labels        => undef,
                    name          => 'Release 1',
                    requested_by  => 'Jacob Helwig',
                    owned_by      => undef,
                    story_type    => 'release',
                    url           => 'https://www.pivotaltracker.com/story/show/320532',
                    notes => [
                    {
                        author => 'Jacob Helwig',
                        date   => 'Dec 20, 2008',
                        id     => '209033',
                        text   => 'Comment!'
                    },
                    {
                        author => 'Jacob Helwig',
                        date   => 'Dec 20, 2008',
                        id     => '209034',
                        text   => 'Another comment!'
                    }
                    ],
                },
                {
                    accepted_at   => undef,
                    created_at    => 'Dec 20, 2008',
                    current_state => 'unscheduled',
                    deadline      => undef,
                    description   => undef,
                    estimate      => '-1',
                    id            => '320008',
                    name          => 'Story!',
                    notes         => undef,
                    requested_by  => 'Jacob Helwig',
                    owned_by      => undef,
                    story_type    => 'feature',
                    url           => 'https://www.pivotaltracker.com/story/show/320008',
                    labels => [
                    'needs feedback'
                    ],
                }
            ],
        },
        'stories_for_filter sanitized story XML ok',
    );
}

sub TEST_UPDATE_STORY__BASE_CASE : Test(3)
{
    my $self = shift;

    my $request_content;

    $self->{'override'}->replace(
        'WWW::PivotalTracker::_post_request' => sub($$) {
            return <<"            HERE";
<?xml version="1.0" encoding="UTF-8"?>
<story>
  <id type="integer">320532</id>
  <story_type>release</story_type>
  <url>https://www.pivotaltracker.com/story/show/320532</url>
  <estimate type="integer">-1</estimate>
  <current_state>unscheduled</current_state>
  <description></description>
  <name>Release 1</name>
  <requested_by>Jacob Helwig</requested_by>
  <created_at type="datetime">Dec 20, 2008</created_at>
  <deadline type="datetime">Dec 31, 2008</deadline>
  <notes type="array">
    <note>
      <id type="integer">209033</id>
      <text>Comment!</text>
      <author>Jacob Helwig</author>
      <noted_at type="datetime">Dec 20, 2008</noted_at>
    </note>
  </notes>
  <labels>needs feedback</labels>
</story>
            HERE
        }
    );

    use_ok('WWW::PivotalTracker', qw/ show_story /);

    my $response = show_story('c0ffe', 1, 320532);
    isa_ok($response, 'HASH', 'show_story return value');

    eq_or_diff(
        $response,
        {
            success       => 'true',
            accepted_at   => undef,
            created_at    => 'Dec 20, 2008',
            current_state => 'unscheduled',
            deadline      => 'Dec 31, 2008',
            description   => undef,
            estimate      => '-1',
            id            => '320532',
            labels        => [ 'needs feedback', ],
            name          => 'Release 1',
            requested_by  => 'Jacob Helwig',
            owned_by      => undef,
            story_type    => 'release',
            url           => 'https://www.pivotaltracker.com/story/show/320532',
            notes => [{
                author => 'Jacob Helwig',
                date   => 'Dec 20, 2008',
                id     => '209033',
                text   => 'Comment!',
            }],
        },
        'show_story ok',
    );
}

sub TEST_UPDATE_STORY__HANDLES_WHEN_SUCCESS_IS_NOT_TRUE : Test(3)
{
    my $self = shift;

    $self->{'override'}->replace(
        'WWW::PivotalTracker::_post_request' => sub($$) { die; }
    );

    use_ok('WWW::PivotalTracker', qw/ update_story /);

    my $response = update_story('c0ffe', 1, 320532);
    isa_ok($response, 'HASH', 'update_story return value');

    eq_or_diff(
        $response,
        { success => 'false' },
        'update_story ok',
    );
}

sub teardown : Test(teardown)
{
    my $self = shift;

    $self->{'override'} = undef;
}

1;