diff options
Diffstat (limited to 't/open311')
-rw-r--r-- | t/open311/getservicerequests.t | 427 | ||||
-rw-r--r-- | t/open311/getservicerequestupdates.t | 153 | ||||
-rw-r--r-- | t/open311/populate-service-list.t | 72 |
3 files changed, 588 insertions, 64 deletions
diff --git a/t/open311/getservicerequests.t b/t/open311/getservicerequests.t new file mode 100644 index 000000000..57f112e2f --- /dev/null +++ b/t/open311/getservicerequests.t @@ -0,0 +1,427 @@ +#!/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 $dtf = DateTime::Format::W3CDTF->new; + +my $requests_xml = qq{<?xml version="1.0" encoding="utf-8"?> +<service_requests> +<request> +<service_request_id>638344</service_request_id> +<status>open</status> +<status_notes>This is a note.</status_notes> +<service_name>Sidewalk and Curb Issues</service_name> +<service_code>sidewalks</service_code> +<description>This is a sidewalk problem</description> +<agency_responsible></agency_responsible> +<service_notice></service_notice> +<requested_datetime>2010-04-14T06:37:38-08:00</requested_datetime> +<updated_datetime>2010-04-14T06:37:38-08:00</updated_datetime> +<expected_datetime>2010-04-15T06:37:38-08:00</expected_datetime> +<lat>51.4021</lat> +<long>0.01578</long> +</request> +<request> +<service_request_id>638345</service_request_id> +<status>investigating</status> +<status_notes>This is a for a different issue.</status_notes> +<service_name>Not Sidewalk and Curb Issues</service_name> +<service_code>not_sidewalks</service_code> +<description>This is a problem</description> +<agency_responsible></agency_responsible> +<service_notice></service_notice> +<requested_datetime>2010-04-15T06:37:38-08:00</requested_datetime> +<updated_datetime>2010-04-15T06:37:38-08:00</updated_datetime> +<expected_datetime>2010-04-15T06:37:38-08:00</expected_datetime> +<lat>51.4021</lat> +<long>0.01578</long> +</request> +</service_requests> +}; + +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->time_zone || FixMyStreet->local_time_zone + ); +my $p2_date = $dtf->parse_datetime('2010-04-15T06:37:38-08:00') + ->set_time_zone( + FixMyStreet->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 { + 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'; +}; + +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" +}; + +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[<?xml version="1.0" encoding="utf-8"?> +<service_requests> +<request> +<service_request_id>XXX_ID</service_request_id> +<status>open</status> +<status_notes></status_notes> +<service_name>Sidewalk and Curb Issues</service_name> +<service_code>sidewalks</service_code> +<description>XXX_DESC</description> +<agency_responsible></agency_responsible> +<service_notice></service_notice> +<requested_datetime>2010-04-14T06:37:38-08:00</requested_datetime> +<updated_datetime>XXX_UPDATE_TIME</updated_datetime> +<expected_datetime>2010-04-15T06:37:38-08:00</expected_datetime> +<lat>XXX_LAT</lat> +<long>XXX_LONG</long> +</request> +</service_requests> +]; + + for my $key (keys %defaults) { + my $string = 'XXX_' . uc $key; + $xml =~ s/$string/$defaults{$key}/; + } + + return $xml; +} + +done_testing(); diff --git a/t/open311/getservicerequestupdates.t b/t/open311/getservicerequestupdates.t index da427e505..3c279d776 100644 --- a/t/open311/getservicerequestupdates.t +++ b/t/open311/getservicerequestupdates.t @@ -1,6 +1,7 @@ #!/usr/bin/env perl use FixMyStreet::Test; +use Test::Output; use CGI::Simple; use LWP::Protocol::PSGI; use t::Mock::Static; @@ -149,7 +150,7 @@ for my $test ( comment_status => 'OPEN', mark_fixed=> 0, mark_open => 0, - problem_state => undef, + problem_state => 'confirmed', end_state => 'confirmed', }, { @@ -357,6 +358,19 @@ for my $test ( end_state => 'investigating', }, { + desc => 'unchanging state does not trigger auto-response template', + description => '', + xml_description => '', + external_id => 638344, + start_state => 'investigating', + comment_status => 'INVESTIGATING', + mark_fixed => 0, + mark_open => 0, + problem_state => 'investigating', + end_state => 'investigating', + comment_state => 'hidden', + }, + { desc => 'open status does not re-open hidden report', description => 'This is a note', external_id => 638344, @@ -388,6 +402,7 @@ for my $test ( is $c->mark_fixed, $test->{mark_fixed}, 'mark_closed correct'; is $c->problem_state, $test->{problem_state}, 'problem_state correct'; is $c->mark_open, $test->{mark_open}, 'mark_open correct'; + is $c->state, $test->{comment_state} || 'confirmed', 'comment state correct'; is $problem->state, $test->{end_state}, 'correct problem state'; $problem->comments->delete; }; @@ -649,6 +664,95 @@ subtest 'check that existing comments are not duplicated' => sub { is $problem->comments->count, 2, 'if comments are deleted then they are added'; }; +subtest 'check that external_status_code is stored correctly' => sub { + my $requests_xml = qq{<?xml version="1.0" encoding="utf-8"?> + <service_requests_updates> + <request_update> + <update_id>638344</update_id> + <service_request_id>@{[ $problem->external_id ]}</service_request_id> + <status>open</status> + <description>This is a note</description> + <updated_datetime>UPDATED_DATETIME</updated_datetime> + <external_status_code>060</external_status_code> + </request_update> + <request_update> + <update_id>638354</update_id> + <service_request_id>@{[ $problem->external_id ]}</service_request_id> + <status>open</status> + <description>This is a different note</description> + <updated_datetime>UPDATED_DATETIME2</updated_datetime> + <external_status_code>101</external_status_code> + </request_update> + </service_requests_updates> + }; + + $problem->comments->delete; + + my $dt2 = $dt->clone->subtract( hours => 1 ); + $requests_xml =~ s/UPDATED_DATETIME2/$dt/; + $requests_xml =~ s/UPDATED_DATETIME/$dt2/; + + my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'servicerequestupdates.xml' => $requests_xml } ); + + my $update = Open311::GetServiceRequestUpdates->new( + system_user => $user, + ); + + $update->update_comments( $o, $bodies{2482} ); + + $problem->discard_changes; + is $problem->comments->count, 2, 'two comments after fetching updates'; + + my @comments = $problem->comments->search(undef, { order_by => [ 'created' ] } )->all; + + is $comments[0]->get_extra_metadata('external_status_code'), "060", "correct external status code on first comment"; + is $comments[1]->get_extra_metadata('external_status_code'), "101", "correct external status code on second comment"; + + is $problem->get_extra_metadata('external_status_code'), "101", "correct external status code"; + +}; + +subtest 'check that external_status_code triggers auto-responses' => sub { + my $requests_xml = qq{<?xml version="1.0" encoding="utf-8"?> + <service_requests_updates> + <request_update> + <update_id>638344</update_id> + <service_request_id>@{[ $problem->external_id ]}</service_request_id> + <status>open</status> + <description></description> + <updated_datetime>UPDATED_DATETIME</updated_datetime> + <external_status_code>060</external_status_code> + </request_update> + </service_requests_updates> + }; + + my $response_template = $bodies{2482}->response_templates->create({ + title => "Acknowledgement", + text => "Thank you for your report. We will provide an update within 24 hours.", + auto_response => 1, + external_status_code => "060" + }); + + $problem->comments->delete; + + $requests_xml =~ s/UPDATED_DATETIME/$dt/; + + my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'servicerequestupdates.xml' => $requests_xml } ); + + my $update = Open311::GetServiceRequestUpdates->new( + system_user => $user, + ); + + $update->update_comments( $o, $bodies{2482} ); + + $problem->discard_changes; + is $problem->comments->count, 1, 'one comment after fetching updates'; + + my $comment = $problem->comments->first; + + is $problem->comments->first->text, "Thank you for your report. We will provide an update within 24 hours.", "correct external status code on first comment"; +}; + foreach my $test ( { desc => 'check that closed and then open comment results in correct state', dt1 => $dt->clone->subtract( hours => 1 ), @@ -782,6 +886,53 @@ foreach my $test ( { } } +foreach my $test ( { + desc => 'normally blank text produces a warning', + num_alerts => 1, + blank_updates_permitted => 0, + }, + { + desc => 'no warning if blank updates permitted', + num_alerts => 1, + blank_updates_permitted => 1, + }, +) { + subtest $test->{desc} => sub { + my $requests_xml = qq{<?xml version="1.0" encoding="utf-8"?> + <service_requests_updates> + <request_update> + <update_id>638344</update_id> + <service_request_id>@{[ $problem->external_id ]}</service_request_id> + <status>closed</status> + <description></description> + <updated_datetime>UPDATED_DATETIME</updated_datetime> + </request_update> + </service_requests_updates> + }; + + $problem->state( 'confirmed' ); + $problem->lastupdate( $dt->clone->subtract( hours => 3 ) ); + $problem->update; + + $requests_xml =~ s/UPDATED_DATETIME/$dt/; + + my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'servicerequestupdates.xml' => $requests_xml } ); + + my $update = Open311::GetServiceRequestUpdates->new( + system_user => $user, + blank_updates_permitted => $test->{blank_updates_permitted}, + ); + + if ( $test->{blank_updates_permitted} ) { + stderr_is { $update->update_comments( $o, $bodies{2482} ) } '', 'No error message' + } else { + stderr_like { $update->update_comments( $o, $bodies{2482} ) } qr/Couldn't determine update text for/, 'Error message displayed' + } + $problem->discard_changes; + $problem->comments->delete; + } +} + done_testing(); sub setup_xml { diff --git a/t/open311/populate-service-list.t b/t/open311/populate-service-list.t index 7d4f491c6..b54b1c242 100644 --- a/t/open311/populate-service-list.t +++ b/t/open311/populate-service-list.t @@ -192,67 +192,6 @@ subtest 'check conflicting contacts not changed' => sub { is $contact_count, 4, 'correct number of contacts'; }; -subtest 'check meta data population' => sub { - my $processor = Open311::PopulateServiceList->new(); - - my $meta_xml = '<?xml version="1.0" encoding="utf-8"?> -<service_definition> - <service_code>100</service_code> - <attributes> - <attribute> - <variable>true</variable> - <code>type</code> - <datatype>string</datatype> - <required>true</required> - <datatype_description>Type of bin</datatype_description> - <order>1</order> - <description>Type of bin</description> - </attribute> - </attributes> -</service_definition> - '; - - my $contact = FixMyStreet::DB->resultset('Contact')->find_or_create( - { - body_id => 1, - email => '001', - category => 'Bins left out 24x7', - state => 'confirmed', - editor => $0, - whenedited => \'current_timestamp', - note => 'test contact', - } - ); - - my $o = Open311->new( - jurisdiction => 'mysociety', - endpoint => 'http://example.com', - test_mode => 1, - test_get_returns => { 'services/100.xml' => $meta_xml } - ); - - $processor->_current_open311( $o ); - $processor->_current_body( $bromley ); - $processor->_current_service( { service_code => 100 } ); - - $processor->_add_meta_to_contact( $contact ); - - my $extra = [ { - variable => 'true', - code => 'type', - datatype => 'string', - required => 'true', - datatype_description => 'Type of bin', - order => 1, - description => 'Type of bin' - - } ]; - - $contact->discard_changes; - - is_deeply $contact->get_extra_fields, $extra, 'meta data saved'; -}; - for my $test ( { desc => 'check meta data added to existing contact', @@ -527,7 +466,7 @@ subtest 'check attribute ordering' => sub { is_deeply $contact->get_extra_fields, $extra, 'meta data re-ordered correctly'; }; -subtest 'check bromely skip code' => sub { +subtest 'check Bromley skip code' => sub { my $processor = Open311::PopulateServiceList->new(); my $meta_xml = '<?xml version="1.0" encoding="utf-8"?> @@ -598,7 +537,14 @@ subtest 'check bromely skip code' => sub { datatype_description => 'Type of bin', order => 1, description => 'Type of bin' - + }, { + automated => 'hidden_field', + variable => 'true', + code => 'prow_reference', + datatype => 'string', + required => 'false', + order => 101, + description => 'Right of way reference' } ]; $contact->discard_changes; |