#!/usr/bin/env perl
use FixMyStreet::TestMech;
use_ok( 'Open311' );
use_ok( 'Open311::GetServiceRequests' );
use DateTime;
use DateTime::Format::W3CDTF;
use Test::MockObject::Extends;
my $mech = FixMyStreet::TestMech->new;
my $user = $mech->create_user_ok('system_user@example.com', name => 'test users');
my $body = $mech->create_body_ok(2482, 'Bromley');
my $contact = $mech->create_contact_ok( body_id => $body->id, category => 'Sidewalk and Curb Issues', email => 'sidewalks' );
my $body2 = $mech->create_body_ok(2217, 'Buckinghamshire');
my $contact2 = $mech->create_contact_ok( body_id => $body2->id, category => 'Sidewalk and Curb Issues', email => 'sidewalks' );
my $hounslow = $mech->create_body_ok(2483, 'Hounslow');
my $hounslowcontact = $mech->create_contact_ok( body_id => $hounslow->id, category => 'Sidewalk and Curb Issues', email => 'sidewalks' );
my $dtf = DateTime::Format::W3CDTF->new;
my $requests_xml = qq{
638344
open
This is a note.
Sidewalk and Curb Issues
sidewalks
This is a sidewalk problem
2010-04-14T06:37:38-08:00
2010-04-14T06:37:38-08:00
2010-04-15T06:37:38-08:00
51.4021
0.01578
638345
investigating
This is a for a different issue.
Not Sidewalk and Curb Issues
not_sidewalks
This is a problem
2010-04-15T06:37:38-08:00
2010-04-15T06:37:38-08:00
2010-04-15T06:37:38-08:00
51.4021
0.01578
638346
open
This is a note.
Sidewalk and Curb Issues
sidewalks
2010-04-14T06:37:38-08:00
2010-04-14T06:37:38-08:00
2010-04-15T06:37:38-08:00
51.4021
0.01578
};
my $o = Open311->new(
jurisdiction => 'mysociety',
endpoint => 'http://example.com',
test_mode => 1,
test_get_returns => { 'requests.xml' => $requests_xml }
);
my $p1_date = $dtf->parse_datetime('2010-04-14T06:37:38-08:00')
->set_time_zone(FixMyStreet->local_time_zone);
my $p2_date = $dtf->parse_datetime('2010-04-15T06:37:38-08:00')
->set_time_zone(FixMyStreet->local_time_zone);
my $start_date = $p1_date->clone;
$start_date->add( hours => -2);
my $end_date = $p2_date->clone;
$end_date->add( hours => 2);
subtest 'basic parsing checks' => sub {
my $update = Open311::GetServiceRequests->new(
system_user => $user,
start_date => $start_date,
end_date => $end_date
);
FixMyStreet::override_config {
TIME_ZONE => 'Asia/Tokyo',
MAPIT_URL => 'http://mapit.uk/',
}, sub {
$update->create_problems( $o, $body );
};
my $p = FixMyStreet::DB->resultset('Problem')->search(
{ external_id => 638344 }
)->first;
ok $p, 'Found problem';
is $p->title, 'Sidewalk and Curb Issues problem', 'correct problem title';
is $p->detail, 'This is a sidewalk problem', 'correct problem description';
is $p->created, $p1_date, 'Problem has correct creation date';
is $p->confirmed, $p1_date, 'Problem has correct confirmed date';
is $p->whensent, $p1_date, 'Problem has whensent set';
is $p->state, 'confirmed', 'correct problem state';
is $p->user->id, $user->id, 'user set to system user';
is $p->category, 'Sidewalk and Curb Issues', 'correct problem category';
my $p2 = FixMyStreet::DB->resultset('Problem')->search( { external_id => 638345 } )->first;
ok $p2, 'second problem found';
ok $p2->whensent, 'second problem marked sent';
is $p2->state, 'investigating', 'second problem correct state';
is $p2->category, 'Other', 'category falls back to Other';
my $p3 = FixMyStreet::DB->resultset('Problem')->search( { external_id => 638346 } )->first;
ok $p3, 'third problem found';
ok $p3->whensent, 'third problem marked sent';
is $p3->state, 'confirmed', 'second problem correct state';
is $p3->category, 'Sidewalk and Curb Issues', 'correct problem category';
is $p3->detail, 'Sidewalk and Curb Issues problem', 'problem detail based on category name';
};
subtest 'check problems not re-created' => sub {
my $update = Open311::GetServiceRequests->new( system_user => $user );
FixMyStreet::override_config {
MAPIT_URL => 'http://mapit.uk/',
}, sub {
$update->create_problems( $o, $body );
};
my $count = FixMyStreet::DB->resultset('Problem')->count;
FixMyStreet::override_config {
MAPIT_URL => 'http://mapit.uk/',
}, sub {
$update->create_problems( $o, $body );
};
my $after_count = FixMyStreet::DB->resultset('Problem')->count;
is $count, $after_count, "problems not re-created";
};
for my $test (
{
desc => 'problem with no id is not created',
detail => 'This is a problem with no service_code',
subs => { id => '', desc => 'This is a problem with service code' },
},
{
desc => 'problem with no lat is not created',
detail => 'This is a problem with no lat',
subs => { lat => '', desc => 'This is a problem with no lat' },
},
{
desc => 'problem with no long is not created',
detail => 'This is a problem with no long',
subs => { long => '', desc => 'This is a problem with no long' },
},
{
desc => 'problem with bad lat/long is not created',
detail => 'This is a problem with bad lat/long',
subs => { lat => '51', long => 0.1, desc => 'This is a problem with bad lat/long' },
},
) {
subtest $test->{desc} => sub {
my $xml = prepare_xml( $test->{subs} );
my $o = Open311->new(
jurisdiction => 'mysociety',
endpoint => 'http://example.com',
test_mode => 1,
test_get_returns => { 'requests.xml' => $xml}
);
my $count = FixMyStreet::DB->resultset('Problem')->count;
my $update = Open311::GetServiceRequests->new( system_user => $user );
FixMyStreet::override_config {
MAPIT_URL => 'http://mapit.uk/',
}, sub {
$update->create_problems( $o, $body );
};
my $after_count = FixMyStreet::DB->resultset('Problem')->count;
is $count, $after_count, "problems not created";
my $with_text = FixMyStreet::DB->resultset('Problem')->search( {
detail => $test->{detail}
} )->count;
is $with_text, 0, 'no matching problem created';
};
}
my $date = DateTime->new(
year => 2010,
month => 4,
day => 14,
hour => 6,
minute => 37
);
for my $test (
{
start_date => '1',
end_date => '',
desc => 'do not process if only a start_date',
subs => {},
},
{
start_date => '',
end_date => '1',
desc => 'do not process if only an end_date',
subs => {},
},
) {
subtest $test->{desc} => sub {
my $xml = prepare_xml( $test->{subs} );
my $o = Open311->new(
jurisdiction => 'mysociety',
endpoint => 'http://example.com',
test_mode => 1,
test_get_returns => { 'requests.xml' => $xml}
);
my $update = Open311::GetServiceRequests->new(
start_date => $test->{start_date},
end_date => $test->{end_date},
system_user => $user,
);
my $ret = $update->create_problems( $o, $body );
is $ret, 0, 'failed correctly'
};
}
$date = DateTime->new(
year => 2010,
month => 4,
day => 14,
hour => 6,
minute => 37
);
for my $test (
{
start_date => $date->clone->add(hours => -2),
end_date => $date->clone->add(hours => -1),
desc => 'do not process if update time after end_date',
subs => {},
},
{
start_date => $date->clone->add(hours => 2),
end_date => $date->clone->add(hours => 4),
desc => 'do not process if update time before start_date',
subs => {},
},
{
start_date => $date->clone->add(hours => -2),
end_date => $date->clone->add(hours => 4),
desc => 'do not process if update time is bad',
subs => { update_time => '2010/12/12' },
},
) {
subtest $test->{desc} => sub {
my $xml = prepare_xml( $test->{subs} );
my $o = Open311->new(
jurisdiction => 'mysociety',
endpoint => 'http://example.com',
test_mode => 1,
test_get_returns => { 'requests.xml' => $xml}
);
my $update = Open311::GetServiceRequests->new(
start_date => $test->{start_date},
end_date => $test->{end_date},
system_user => $user,
);
my $count = FixMyStreet::DB->resultset('Problem')->count;
FixMyStreet::override_config {
MAPIT_URL => 'http://mapit.uk/',
}, sub {
$update->create_problems( $o, $body );
};
my $after = FixMyStreet::DB->resultset('Problem')->count;
is $count, $after, 'problem not added';
};
}
subtest 'check fetch_all body setting ignores date errors' => sub {
my $xml = prepare_xml({ id => '12345678' });
$body->update( {
send_method => 'Open311',
fetch_problems => 1,
comment_user_id => $user->id,
endpoint => 'http://open311.localhost/',
api_key => 'KEY',
jurisdiction => 'test',
} );
$body->set_extra_metadata( fetch_all_problems => 1 );
$body->update();
my $update = Open311::GetServiceRequests->new(
verbose => 1,
system_user => $user,
);
$update = Test::MockObject::Extends->new($update);
$update->mock('create_open311_object', sub {
return Open311->new(
jurisdiction => 'mysociety',
endpoint => 'http://example.com',
test_mode => 1,
test_get_returns => { 'requests.xml' => $xml}
);
} );
my $count = FixMyStreet::DB->resultset('Problem')->count;
FixMyStreet::override_config {
MAPIT_URL => 'http://mapit.uk/',
}, sub {
$update->fetch;
};
my $after = FixMyStreet::DB->resultset('Problem')->count;
is $after, $count + 1, 'problem created';
};
for my $test (
{
desc => 'convert easting/northing to lat/long',
subs => { lat => 168935, long => 540315 },
expected => { lat => 51.402096, long => 0.015784 },
},
) {
subtest $test->{desc} => sub {
my $xml = prepare_xml( $test->{subs} );
my $o = Open311->new(
jurisdiction => 'mysociety',
endpoint => 'http://example.com',
test_mode => 1,
test_get_returns => { 'requests.xml' => $xml}
);
my $update = Open311::GetServiceRequests->new(
system_user => $user,
convert_latlong => 1,
start_date => $start_date,
end_date => $end_date
);
FixMyStreet::override_config {
MAPIT_URL => 'http://mapit.uk/',
}, sub {
$update->create_problems( $o, $body );
};
my $p = FixMyStreet::DB->resultset('Problem')->search(
{ external_id => 123456 }
)->first;
ok $p, 'problem created';
is $p->latitude, $test->{expected}->{lat}, 'correct latitude';
is $p->longitude, $test->{expected}->{long}, 'correct longitude';
$p->delete;
};
}
subtest "check options passed through from body" => sub {
my $xml = prepare_xml( {} );
$body->update( {
send_method => 'Open311',
fetch_problems => 1,
comment_user_id => $user->id,
endpoint => 'http://open311.localhost/',
convert_latlong => 1,
api_key => 'KEY',
jurisdiction => 'test',
} );
my $o = Open311::GetServiceRequests->new();
my $props = {};
$o = Test::MockObject::Extends->new($o);
$o->mock('create_problems', sub {
my $self = shift;
$props->{convert_latlong} = $self->convert_latlong;
} );
$o->fetch();
ok $props->{convert_latlong}, "convert latlong set"
};
my $non_public_xml = qq[
123456
open
Sidewalk and Curb Issues
sidewalks
this is a problem
2010-04-14T06:37:38-08:00
2010-04-14T06:37:38-08:00
2010-04-15T06:37:38-08:00
51.4021
0.01578
1
];
for my $test (
{
desc => 'non public is set',
non_public => 1,
},
{
desc => 'non public is not set',
non_public => 0,
},
) {
subtest $test->{desc} => sub {
(my $xml = $non_public_xml) =~ s/non_public>1/non_public>$test->{non_public}/;
my $o = Open311->new(
jurisdiction => 'mysociety',
endpoint => 'http://example.com',
test_mode => 1,
test_get_returns => { 'requests.xml' => $xml}
);
my $update = Open311::GetServiceRequests->new(
system_user => $user,
start_date => $start_date,
end_date => $end_date
);
FixMyStreet::override_config {
MAPIT_URL => 'http://mapit.uk/',
}, sub {
$update->create_problems( $o, $body );
};
my $p = FixMyStreet::DB->resultset('Problem')->search(
{ external_id => 123456 }
)->first;
ok $p, 'problem created';
is $p->non_public, $test->{non_public}, "report non_public is set correctly";
$p->delete;
};
}
my $hounslow_non_public_xml = qq[
123456
open
Sidewalk and Curb Issues
sidewalks
this is a problem
2010-04-14T06:37:38-08:00
2010-04-14T06:37:38-08:00
2010-04-15T06:37:38-08:00
51.482286
-0.328163
1
];
for my $test (
{
desc => 'Hounslow non_public reports not created',
non_public => 1,
count => 0,
},
{
desc => 'Hounslow public reports are created',
non_public => 0,
count => 1,
},
) {
subtest $test->{desc} => sub {
(my $xml = $hounslow_non_public_xml) =~ s/non_public>1/non_public>$test->{non_public}/;
my $o = Open311->new(
jurisdiction => 'mysociety',
endpoint => 'http://example.com',
test_mode => 1,
test_get_returns => { 'requests.xml' => $xml}
);
my $update = Open311::GetServiceRequests->new(
system_user => $user,
start_date => $start_date,
end_date => $end_date
);
FixMyStreet::override_config {
MAPIT_URL => 'http://mapit.uk/',
ALLOWED_COBRANDS => [ 'hounslow' ],
}, sub {
$update->create_problems( $o, $hounslow );
};
my $q = FixMyStreet::DB->resultset('Problem')->search(
{ external_id => 123456 }
);
is $q->count, $test->{count}, 'problem count is correct';
$q->first->delete if $test->{count};
};
}
subtest "non_public contacts result in non_public reports" => sub {
$contact->update({
non_public => 1
});
my $o = Open311->new(
jurisdiction => 'mysociety',
endpoint => 'http://example.com',
test_mode => 1,
test_get_returns => { 'requests.xml' => prepare_xml( {} ) }
);
my $update = Open311::GetServiceRequests->new(
system_user => $user,
start_date => $start_date,
end_date => $end_date
);
FixMyStreet::override_config {
MAPIT_URL => 'http://mapit.uk/',
}, sub {
$update->create_problems( $o, $body );
};
my $p = FixMyStreet::DB->resultset('Problem')->search(
{ external_id => 123456 }
)->first;
ok $p, 'problem created';
is $p->non_public, 1, "report non_public is set correctly";
$p->delete;
$contact->update({
non_public => 0
});
};
for my $test (
{
test_desc => 'filters out phone numbers',
desc => 'This has a description with values:0117 469 0123 and more 07700 900123',
},
{
test_desc => 'filters out emails',
desc => 'This has a description with values:test@example.org and more user@council.gov.uk',
},
) {
subtest $test->{test_desc} => sub {
my $xml = prepare_xml({
desc => $test->{desc},
lat => 51.615559,
long => -0.556903,
});
my $o = Open311->new(
jurisdiction => 'mysociety',
endpoint => 'http://example.com',
test_mode => 1,
test_get_returns => { 'requests.xml' => $xml}
);
my $update = Open311::GetServiceRequests->new(
system_user => $user,
start_date => $start_date,
end_date => $end_date
);
FixMyStreet::override_config {
ALLOWED_COBRANDS => [ 'FixMyStreet', 'Buckinghamshire' ],
MAPIT_URL => 'http://mapit.uk/',
}, sub {
$update->create_problems( $o, $body2 );
};
my $p = FixMyStreet::DB->resultset('Problem')->search(
{ external_id => 123456 }
)->first;
ok $p, 'problem created';
is $p->detail, 'This has a description with values: and more ', "report description filtered";
$p->delete;
};
}
sub prepare_xml {
my $replacements = shift;
my %defaults = (
desc => 'this is a problem',
lat => 51.4021,
long => 0.01578,
id => 123456,
update_time => '2010-04-14T06:37:38-08:00',
%$replacements
);
my $xml = qq[
XXX_ID
open
Sidewalk and Curb Issues
sidewalks
XXX_DESC
2010-04-14T06:37:38-08:00
XXX_UPDATE_TIME
2010-04-15T06:37:38-08:00
XXX_LAT
XXX_LONG
];
for my $key (keys %defaults) {
my $string = 'XXX_' . uc $key;
$xml =~ s/$string/$defaults{$key}/;
}
return $xml;
}
done_testing();