aboutsummaryrefslogtreecommitdiffstats
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/app/controller/report_new.t116
-rw-r--r--t/open311.t317
-rw-r--r--t/open311/getservicerequestupdates.t409
-rw-r--r--t/open311/populate-service-list.t298
4 files changed, 1136 insertions, 4 deletions
diff --git a/t/app/controller/report_new.t b/t/app/controller/report_new.t
index 625c7531f..1e751997b 100644
--- a/t/app/controller/report_new.t
+++ b/t/app/controller/report_new.t
@@ -48,6 +48,12 @@ my $contact3 = FixMyStreet::App->model('DB::Contact')->find_or_create( {
category => 'Trees',
email => 'trees@example.com',
} );
+my $contact4 = FixMyStreet::App->model('DB::Contact')->find_or_create( {
+ %contact_params,
+ area_id => 2482, # Bromley
+ category => 'Trees',
+ email => 'trees@example.com',
+} );
ok $contact1, "created test contact 1";
ok $contact2, "created test contact 2";
ok $contact3, "created test contact 3";
@@ -293,7 +299,7 @@ foreach my $test (
is_deeply $mech->form_errors, [], "no errors for pc '$test->{pc}'";
# click through to the report page
- $mech->follow_link_ok( { text => 'skip this step', },
+ $mech->follow_link_ok( { text_regex => qr/skip this step/i, },
"follow 'skip this step' link" );
# submit the main form
@@ -473,7 +479,7 @@ subtest "test password errors for a user who is signing in as they report" => su
"submit location" );
# click through to the report page
- $mech->follow_link_ok( { text => 'Skip this step', },
+ $mech->follow_link_ok( { text_regex => qr/skip this step/i, },
"follow 'skip this step' link" );
$mech->submit_form_ok(
@@ -520,7 +526,7 @@ subtest "test report creation for a user who is signing in as they report" => su
"submit location" );
# click through to the report page
- $mech->follow_link_ok( { text => 'Skip this step', },
+ $mech->follow_link_ok( { text_regex => qr/skip this step/i, },
"follow 'skip this step' link" );
$mech->submit_form_ok(
@@ -614,7 +620,7 @@ foreach my $test (
"submit location" );
# click through to the report page
- $mech->follow_link_ok( { text => 'Skip this step', },
+ $mech->follow_link_ok( { text_regex => qr/skip this step/i, },
"follow 'skip this step' link" );
# check that the fields are correctly prefilled
@@ -725,6 +731,108 @@ subtest "check that a lat/lon off coast leads to /around" => sub {
};
+for my $test (
+ {
+ desc => 'title shown for bromley problem on main site',
+ host => 'http://www.fixmystreet.com',
+ extra => [
+ {
+ name => 'fms_extra_title',
+ value => 'Mr',
+ description => 'FMS_EXTRA_TITLE',
+ },
+ ],
+ },
+ {
+ desc =>
+ 'title, first and last name shown for bromley problem on cobrand',
+ host => 'http://bromley.fixmystreet.com',
+ first_name => 'Test',
+ last_name => 'User',
+ extra => [
+ {
+ name => 'fms_extra_title',
+ value => 'Mr',
+ description => 'FMS_EXTRA_TITLE',
+ },
+ {
+ name => 'first_name',
+ value => 'Test',
+ description => 'FIRST_NAME',
+ },
+ {
+ name => 'last_name',
+ value => 'User',
+ description => 'LAST_NAME',
+ },
+ ],
+ },
+ )
+{
+ subtest $test->{desc} => sub {
+ $mech->host( $test->{host} );
+
+ $mech->log_out_ok;
+
+ $mech->get_ok('/around');
+ $mech->submit_form_ok( { with_fields => { pc => 'BR1 3UH', } },
+ "submit location" );
+ $mech->follow_link_ok(
+ { text_regex => qr/skip this step/i, },
+ "follow 'skip this step' link"
+ );
+
+ my $fields = $mech->visible_form_values('mapSkippedForm');
+ ok exists( $fields->{fms_extra_title} ), 'user title field displayed';
+ if ( $test->{first_name} ) {
+ ok exists( $fields->{first_name} ), 'first name field displayed';
+ ok exists( $fields->{last_name} ), 'last name field displayed';
+ ok !exists( $fields->{name} ), 'no name field displayed';
+ }
+ else {
+ ok !exists( $fields->{first_name} ),
+ 'first name field not displayed';
+ ok !exists( $fields->{last_name} ), 'last name field not displayed';
+ ok exists( $fields->{name} ), 'name field displayed';
+ }
+
+ my $submission_fields = {
+ title => "Test Report",
+ detail => 'Test report details.',
+ photo => '',
+ email => 'firstlast@example.com',
+ fms_extra_title => 'Mr',
+ may_show_name => '1',
+ phone => '07903 123 456',
+ category => 'Trees',
+ password_register => '',
+ };
+
+ if ( $test->{first_name} ) {
+ $submission_fields->{first_name} = $test->{first_name};
+ $submission_fields->{last_name} = $test->{last_name};
+ }
+ else {
+ $submission_fields->{name} = 'Test User';
+ }
+
+ $mech->submit_form_ok( { with_fields => $submission_fields },
+ "submit good details" );
+
+ my $user =
+ FixMyStreet::App->model('DB::User')
+ ->find( { email => 'firstlast@example.com' } );
+
+ my $report = $user->problems->first;
+ ok $report, "Found the report";
+ my $extras = $report->extra;
+ is_deeply $extras, $test->{extra}, 'extra contains correct values';
+
+ $user->problems->delete;
+ $user->delete;
+ };
+}
+
$contact1->delete;
$contact2->delete;
$contact3->delete;
diff --git a/t/open311.t b/t/open311.t
index 30de330b6..83b81d8aa 100644
--- a/t/open311.t
+++ b/t/open311.t
@@ -5,6 +5,9 @@ use warnings;
use Test::More;
use Test::Warn;
use FixMyStreet::App;
+use CGI::Simple;
+use HTTP::Response;
+use DateTime;
use FindBin;
use lib "$FindBin::Bin/../perllib";
@@ -39,4 +42,318 @@ my $expected_error = qr{.*request failed: 500 Can.t connect to 192.168.50.1:80 \
warning_like {$o2->send_service_request( $p, { url => 'http://example.com/' }, 1 )} $expected_error, 'warning generated on failed call';
+my $dt = DateTime->now();
+
+my $user = FixMyStreet::App->model('DB::User')->new( {
+ name => 'Test User',
+ email => 'test@example.com',
+} );
+
+my $problem = FixMyStreet::App->model('DB::Problem')->new( {
+ id => 80,
+ external_id => 81,
+ state => 'confirmed',
+ title => 'a problem',
+ detail => 'problem detail',
+ category => 'pothole',
+ latitude => 1,
+ longitude => 2,
+ user => $user,
+} );
+
+subtest 'posting service request' => sub {
+ my $extra = {
+ url => 'http://example.com/report/1',
+ };
+
+ my $results = make_service_req( $problem, $extra, $problem->category, '<?xml version="1.0" encoding="utf-8"?><service_requests><request><service_request_id>248</service_request_id></request></service_requests>' );
+
+ is $results->{ res }, 248, 'got request id';
+
+ my $req = $o->test_req_used;
+
+ my $description = <<EOT;
+title: a problem
+
+detail: problem detail
+
+url: http://example.com/report/1
+
+Submitted via FixMyStreet
+EOT
+;
+
+ my $c = CGI::Simple->new( $results->{ req }->content );
+
+ is $c->param('email'), $user->email, 'correct email';
+ is $c->param('first_name'), 'Test', 'correct first name';
+ is $c->param('last_name'), 'User', 'correct last name';
+ is $c->param('lat'), 1, 'latitide correct';
+ is $c->param('long'), 2, 'longitude correct';
+ is $c->param('description'), $description, 'descritpion correct';
+ is $c->param('service_code'), 'pothole', 'service code correct';
+};
+
+for my $test (
+ {
+ desc => 'extra values in service request',
+ extra => [
+ {
+ name => 'title',
+ value => 'A title',
+ }
+ ],
+ params => [
+ [ 'attribute[title]', 'A title', 'extra paramater used correctly' ]
+ ]
+ },
+ {
+ desc => 'first and last names in extra used correctly',
+ extra => [
+ {
+ name => 'first_name',
+ value => 'First',
+ },
+ {
+ name => 'last_name',
+ value => 'Last',
+ },
+ ],
+ params => [
+ [ 'first_name', 'First', 'first name correct' ],
+ [ 'last_name', 'Last', 'last name correct' ],
+ [ 'attribute[first_name]', undef, 'no first_name attribute param' ],
+ [ 'attribute[last_name]', undef, 'no last_name attribute param' ],
+ ],
+ },
+ {
+ title => 'magic fms_extra parameters handled correctly',
+ extra => [
+ {
+ name => 'fms_extra_title',
+ value => 'Extra title',
+ }
+ ],
+ params => [
+ [
+ 'attribute[title]',
+ 'Extra title',
+ 'fms_extra extra param used correctly'
+ ]
+ ],
+ },
+ )
+{
+ subtest $test->{desc} => sub {
+ $problem->extra( $test->{extra} );
+
+ my $extra = { url => 'http://example.com/report/1', };
+
+ my $results = make_service_req( $problem, $extra, $problem->category,
+'<?xml version="1.0" encoding="utf-8"?><service_requests><request><service_request_id>248</service_request_id></request></service_requests>'
+ );
+ my $req = $o->test_req_used;
+ my $c = CGI::Simple->new( $results->{req}->content );
+
+ for my $param ( @{ $test->{params} } ) {
+ is $c->param( $param->[0] ), $param->[1], $param->[2];
+ }
+ };
+}
+
+my $comment = FixMyStreet::App->model('DB::Comment')->new( {
+ id => 38362,
+ user => $user,
+ problem => $problem,
+ anonymous => 0,
+ text => 'this is a comment',
+ confirmed => $dt,
+ extra => { title => 'Mr', email_alerts_requested => 0 },
+} );
+
+subtest 'basic request update post parameters' => sub {
+ my $results = make_update_req( $comment, '<?xml version="1.0" encoding="utf-8"?><service_request_updates><request_update><update_id>248</update_id></request_update></service_request_updates>' );
+
+ is $results->{ res }, 248, 'got update id';
+
+ my $req = $o->test_req_used;
+
+ my $c = CGI::Simple->new( $results->{ req }->content );
+
+ is $c->param('description'), 'this is a comment', 'email correct';
+ is $c->param('email'), 'test@example.com', 'email correct';
+ is $c->param('status'), 'OPEN', 'status correct';
+ is $c->param('service_request_id_ext'), 80, 'external request id correct';
+ is $c->param('service_request_id'), 81, 'request id correct';
+ is $c->param('public_anonymity_required'), 'FALSE', 'anon status correct';
+ is $c->param('updated_datetime'), $dt, 'correct date';
+ is $c->param('title'), 'Mr', 'correct title';
+ is $c->param('last_name'), 'User', 'correct first name';
+ is $c->param('first_name'), 'Test', 'correct second name';
+ is $c->param('email_alerts_requested'), 'FALSE', 'email alerts flag correct';
+};
+
+foreach my $test (
+ {
+ desc => 'comment with fixed state sends status of CLOSED',
+ state => 'fixed',
+ anon => 0,
+ status => 'CLOSED',
+ },
+ {
+ desc => 'comment with fixed - user state sends status of CLOSED',
+ state => 'fixed - user',
+ anon => 0,
+ status => 'CLOSED',
+ },
+ {
+ desc => 'comment with fixed - council state sends status of CLOSED',
+ state => 'fixed - council',
+ anon => 0,
+ status => 'CLOSED',
+ },
+ {
+ desc => 'comment with closed state sends status of CLOSED',
+ state => 'closed',
+ anon => 0,
+ status => 'CLOSED',
+ },
+ {
+ desc => 'comment with investigating state sends status of OPEN',
+ state => 'investigating',
+ anon => 0,
+ status => 'OPEN',
+ },
+ {
+ desc => 'comment with planned state sends status of OPEN',
+ state => 'planned',
+ anon => 0,
+ status => 'OPEN',
+ },
+ {
+ desc => 'comment with in progress state sends status of OPEN',
+ state => 'in progress',
+ anon => 0,
+ status => 'OPEN',
+ },
+ {
+ desc => 'anonymous commment sets public_anonymity_required to true',
+ state => 'confirmed',
+ anon => 1,
+ status => 'OPEN',
+ },
+) {
+ subtest $test->{desc} => sub {
+ $comment->problem->state( $test->{state} );
+ $comment->anonymous( $test->{anon} );
+
+ my $results = make_update_req( $comment, '<?xml version="1.0" encoding="utf-8"?><service_request_updates><request_update><update_id>248</update_id></request_update></service_request_updates>' );
+
+ my $c = CGI::Simple->new( $results->{ req }->content );
+ is $c->param('status'), $test->{status}, 'correct status';
+ is $c->param('public_anonymity_required'), $test->{anon} ? 'TRUE' : 'FALSE', 'correct anonymity';
+ };
+}
+
+
+for my $test (
+ {
+ desc => 'update name name taken from comment over user',
+ comment_name => 'First Last',
+ user_name => 'Personal Family',
+ extra => undef,
+ first_name => 'First',
+ last_name => 'Last'
+ },
+ {
+ desc => 'update name name taken from user if no comment name',
+ comment_name => '',
+ user_name => 'Personal Family',
+ extra => undef,
+ first_name => 'Personal',
+ last_name => 'Family'
+ },
+ {
+ desc => 'update name taken from extra if available',
+ comment_name => 'First Last',
+ user_name => 'Personal Family',
+ extra => { first_name => 'Forename', last_name => 'Surname' },
+ first_name => 'Forename',
+ last_name => 'Surname'
+ },
+ )
+{
+ subtest $test->{desc} => sub {
+ $comment->name( $test->{comment_name} );
+ $user->name( $test->{user_name} );
+ $comment->extra( $test->{ extra } );
+
+ my $results = make_update_req( $comment,
+'<?xml version="1.0" encoding="utf-8"?><service_request_updates><request_update><update_id>248</update_id></request_update></service_request_updates>'
+ );
+
+ my $c = CGI::Simple->new( $results->{req}->content );
+ is $c->param('first_name'), $test->{first_name}, 'first name correct';
+ is $c->param('last_name'), $test->{last_name}, 'last name correct';
+ };
+}
+
+subtest 'No update id in reponse' => sub {
+ my $results;
+ warning_like {
+ $results = make_update_req( $comment, '<?xml version="1.0" encoding="utf-8"?><service_request_updates><request_update><update_id></update_id></request_update></service_request_updates>' )
+ } qr/Failed to submit comment \d+ over Open311/, 'correct error message';
+
+ is $results->{ res }, 0, 'No update_id is a failure';
+};
+
+subtest 'error reponse' => sub {
+ my $results;
+ warning_like {
+ $results = make_update_req( $comment, '<?xml version="1.0" encoding="utf-8"?><errors><error><code>400</code><description>There was an error</description</error></errors>' )
+ } qr/Failed to submit comment \d+ over Open311.*There was an error/, 'correct error messages';
+
+ is $results->{ res }, 0, 'error in response is a failure';
+};
+
done_testing();
+
+sub make_update_req {
+ my $comment = shift;
+ my $xml = shift;
+
+ return make_req( $comment, $xml, 'post_service_request_update', 'update.xml' );
+}
+
+sub make_service_req {
+ my $problem = shift;
+ my $extra = shift;
+ my $service_code = shift;
+ my $xml = shift;
+
+ return make_req( $problem, $xml, 'send_service_request', 'requests.xml', $extra, $service_code );
+}
+
+sub make_req {
+ my $object = shift;
+ my $xml = shift;
+ my $method = shift;
+ my $path = shift;
+ my @args = @_;
+
+ my $o =
+ Open311->new( test_mode => 1, end_point => 'http://localhost/o311' );
+
+ my $test_res = HTTP::Response->new();
+ $test_res->code(200);
+ $test_res->message('OK');
+ $test_res->content($xml);
+
+ $o->test_get_returns( { $path => $test_res } );
+
+ my $res = $o->$method($object, @args);
+
+ my $req = $o->test_req_used;
+
+ return { res => $res, req => $req };
+}
diff --git a/t/open311/getservicerequestupdates.t b/t/open311/getservicerequestupdates.t
new file mode 100644
index 000000000..063d7e378
--- /dev/null
+++ b/t/open311/getservicerequestupdates.t
@@ -0,0 +1,409 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+use Test::More;
+use CGI::Simple;
+
+use FindBin;
+use lib "$FindBin::Bin/../perllib";
+use lib "$FindBin::Bin/../commonlib/perllib";
+
+use_ok( 'Open311' );
+
+use_ok( 'Open311::GetServiceRequestUpdates' );
+use DateTime;
+use FixMyStreet::App;
+
+my $user = FixMyStreet::App->model('DB::User')->find_or_create(
+ {
+ email => 'system_user@example.com'
+ }
+);
+
+my $requests_xml = qq{<?xml version="1.0" encoding="utf-8"?>
+<service_requests_updates>
+<request_update>
+<update_id>638344</update_id>
+<service_request_id>1</service_request_id>
+<service_request_id_ext>1</service_request_id_ext>
+<status>open</status>
+<description>This is a note</description>
+UPDATED_DATETIME
+</request_update>
+</service_requests_updates>
+};
+
+
+my $dt = DateTime->now;
+
+# basic xml -> perl object tests
+for my $test (
+ {
+ desc => 'basic parsing - element missing',
+ updated_datetime => '',
+ res => { update_id => 638344, service_request_id => 1, service_request_id_ext => 1,
+ status => 'open', description => 'This is a note' },
+ },
+ {
+ desc => 'basic parsing - empty element',
+ updated_datetime => '<updated_datetime />',
+ res => { update_id => 638344, service_request_id => 1, service_request_id_ext => 1,
+ status => 'open', description => 'This is a note', updated_datetime => {} } ,
+ },
+ {
+ desc => 'basic parsing - element with no content',
+ updated_datetime => '<updated_datetime></updated_datetime>',
+ res => { update_id => 638344, service_request_id => 1, service_request_id_ext => 1,
+ status => 'open', description => 'This is a note', updated_datetime => {} } ,
+ },
+ {
+ desc => 'basic parsing - element with content',
+ updated_datetime => sprintf( '<updated_datetime>%s</updated_datetime>', $dt ),
+ res => { update_id => 638344, service_request_id => 1, service_request_id_ext => 1,
+ status => 'open', description => 'This is a note', updated_datetime => $dt } ,
+ },
+) {
+ subtest $test->{desc} => sub {
+ my $local_requests_xml = $requests_xml;
+ $local_requests_xml =~ s/UPDATED_DATETIME/$test->{updated_datetime}/;
+
+ my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'update.xml' => $local_requests_xml } );
+
+ my $res = $o->get_service_request_updates;
+ is_deeply $res->[0], $test->{ res }, 'result looks correct';
+
+ };
+}
+
+my $problem_rs = FixMyStreet::App->model('DB::Problem');
+my $problem = $problem_rs->new(
+ {
+ postcode => 'EH99 1SP',
+ latitude => 1,
+ longitude => 1,
+ areas => 1,
+ title => '',
+ detail => '',
+ used_map => 1,
+ user_id => 1,
+ name => '',
+ state => 'confirmed',
+ service => '',
+ cobrand => 'default',
+ cobrand_data => '',
+ user => $user,
+ created => DateTime->now()->subtract( days => 1 ),
+ lastupdate => DateTime->now()->subtract( days => 1 ),
+ anonymous => 1,
+ external_id => time(),
+ council => 2482,
+ }
+);
+
+$problem->insert;
+
+for my $test (
+ {
+ desc => 'element with content',
+ updated_datetime => sprintf( '<updated_datetime>%s</updated_datetime>', $dt ),
+ description => 'This is a note',
+ external_id => 638344,
+ start_state => 'confirmed',
+ close_comment => 0,
+ mark_fixed=> 0,
+ mark_open => 0,
+ end_state => 'confirmed',
+ },
+ {
+ desc => 'comment closes report',
+ updated_datetime => sprintf( '<updated_datetime>%s</updated_datetime>', $dt ),
+ description => 'This is a note',
+ external_id => 638344,
+ start_state => 'confirmed',
+ close_comment => 1,
+ mark_fixed=> 1,
+ mark_open => 0,
+ end_state => 'fixed - council',
+ },
+ {
+ desc => 'comment re-opens fixed report',
+ updated_datetime => sprintf( '<updated_datetime>%s</updated_datetime>', $dt ),
+ description => 'This is a note',
+ external_id => 638344,
+ start_state => 'fixed - user',
+ close_comment => 0,
+ mark_fixed => 0,
+ mark_open => 1,
+ end_state => 'confirmed',
+ },
+ {
+ desc => 'comment re-opens closed report',
+ updated_datetime => sprintf( '<updated_datetime>%s</updated_datetime>', $dt ),
+ description => 'This is a note',
+ external_id => 638344,
+ start_state => 'closed',
+ close_comment => 0,
+ mark_fixed => 0,
+ mark_open => 1,
+ end_state => 'confirmed',
+ },
+ {
+ desc => 'comment leaves report closed',
+ updated_datetime => sprintf( '<updated_datetime>%s</updated_datetime>', $dt ),
+ description => 'This is a note',
+ external_id => 638344,
+ start_state => 'closed',
+ close_comment => 1,
+ mark_fixed => 0,
+ mark_open => 0,
+ end_state => 'closed',
+ },
+) {
+ subtest $test->{desc} => sub {
+ my $local_requests_xml = $requests_xml;
+ $local_requests_xml =~ s/UPDATED_DATETIME/$test->{updated_datetime}/;
+ $local_requests_xml =~ s#<service_request_id>\d+</service_request_id>#<service_request_id>@{[$problem->external_id]}</service_request_id>#;
+ $local_requests_xml =~ s#<service_request_id_ext>\d+</service_request_id_ext>#<service_request_id_ext>@{[$problem->id]}</service_request_id_ext>#;
+ $local_requests_xml =~ s#<status>\w+</status>#<status>closed</status># if $test->{close_comment};
+
+ my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'update.xml' => $local_requests_xml } );
+
+ $problem->comments->delete;
+ $problem->state( $test->{start_state} );
+ $problem->update;
+
+ my $council_details = { areaid => 2482 };
+ my $update = Open311::GetServiceRequestUpdates->new( system_user => $user );
+ $update->update_comments( $o, $council_details );
+
+ is $problem->comments->count, 1, 'comment count';
+ $problem->discard_changes;
+
+ my $c = FixMyStreet::App->model('DB::Comment')->search( { external_id => $test->{external_id} } )->first;
+ ok $c, 'comment exists';
+ is $c->text, $test->{description}, 'text correct';
+ is $c->mark_fixed, $test->{mark_fixed}, 'mark_closed correct';
+ is $c->mark_open, $test->{mark_open}, 'mark_open correct';
+ is $problem->state, $test->{end_state}, 'correct problem state';
+ };
+}
+
+
+foreach my $test (
+ {
+ desc => 'date for comment correct',
+ updated_datetime => sprintf( '<updated_datetime>%s</updated_datetime>', $dt ),
+ external_id => 638344,
+ },
+) {
+ subtest $test->{desc} => sub {
+ my $dt = DateTime->now();
+ $dt->subtract( minutes => 10 );
+ my $local_requests_xml = $requests_xml;
+
+ my $updated = sprintf( '<updated_datetime>%s</updated_datetime>', $dt );
+ $local_requests_xml =~ s/UPDATED_DATETIME/$updated/;
+ $local_requests_xml =~ s#<service_request_id>\d+</service_request_id>#<service_request_id>@{[$problem->external_id]}</service_request_id>#;
+ $local_requests_xml =~ s#<service_request_id_ext>\d+</service_request_id_ext>#<service_request_id_ext>@{[$problem->id]}</service_request_id_ext>#;
+
+ my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'update.xml' => $local_requests_xml } );
+
+ $problem->comments->delete;
+
+ my $council_details = { areaid => 2482 };
+ my $update = Open311::GetServiceRequestUpdates->new( system_user => $user );
+ $update->update_comments( $o, $council_details );
+
+ my $comment = $problem->comments->first;
+ is $comment->created, $dt, 'created date set to date from XML';
+ is $comment->confirmed, $dt, 'confirmed date set to date from XML';
+ };
+}
+
+my $problem2 = $problem_rs->new(
+ {
+ postcode => 'EH99 1SP',
+ latitude => 1,
+ longitude => 1,
+ areas => 1,
+ title => '',
+ detail => '',
+ used_map => 1,
+ user_id => 1,
+ name => '',
+ state => 'confirmed',
+ service => '',
+ cobrand => 'default',
+ cobrand_data => '',
+ user => $user,
+ created => DateTime->now(),
+ lastupdate => DateTime->now(),
+ anonymous => 1,
+ external_id => $problem->external_id,
+ council => 2651,
+ }
+);
+
+$problem2->insert();
+$problem->comments->delete;
+$problem2->comments->delete;
+
+for my $test (
+ {
+ desc => 'identical external_ids on problem resolved using council',
+ updated_datetime => sprintf( '<updated_datetime>%s</updated_datetime>', $dt ),
+ external_id => 638344,
+ area_id => 2651,
+ request_id => $problem2->external_id,
+ request_id_ext => $problem2->id,
+ p1_comments => 0,
+ p2_comments => 1,
+ },
+ {
+ desc => 'identical external_ids on comments resolved',
+ updated_datetime => sprintf( '<updated_datetime>%s</updated_datetime>', $dt ),
+ external_id => 638344,
+ area_id => 2482,
+ request_id => $problem->external_id,
+ request_id_ext => $problem->id,
+ p1_comments => 1,
+ p2_comments => 1,
+ },
+) {
+ subtest $test->{desc} => sub {
+ my $local_requests_xml = $requests_xml;
+ $local_requests_xml =~ s/UPDATED_DATETIME/$test->{updated_datetime}/;
+ $local_requests_xml =~ s#<service_request_id>\d+</service_request_id>#<service_request_id>$test->{request_id}</service_request_id>#;
+ $local_requests_xml =~ s#<service_request_id_ext>\d+</service_request_id_ext>#<service_request_id_ext>$test->{request_id_ext}</service_request_id_ext>#;
+
+ my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'update.xml' => $local_requests_xml } );
+
+
+ my $council_details = { areaid => $test->{area_id} };
+ my $update = Open311::GetServiceRequestUpdates->new( system_user => $user );
+ $update->update_comments( $o, $council_details );
+
+ is $problem->comments->count, $test->{p1_comments}, 'comment count for first problem';
+ is $problem2->comments->count, $test->{p2_comments}, 'comment count for second problem';
+ };
+}
+
+subtest 'using start and end date' => sub {
+ my $local_requests_xml = $requests_xml;
+ my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'update.xml' => $local_requests_xml } );
+
+ my $start_dt = DateTime->now();
+ $start_dt->subtract( days => 1 );
+ my $end_dt = DateTime->now();
+
+
+ my $update = Open311::GetServiceRequestUpdates->new(
+ system_user => $user,
+ start_date => $start_dt,
+ );
+
+ my $res = $update->update_comments( $o );
+ is $res, 0, 'returns 0 if start but no end date';
+
+ $update = Open311::GetServiceRequestUpdates->new(
+ system_user => $user,
+ end_date => $end_dt,
+ );
+
+ $res = $update->update_comments( $o );
+ is $res, 0, 'returns 0 if end but no start date';
+
+ $update = Open311::GetServiceRequestUpdates->new(
+ system_user => $user,
+ start_date => $start_dt,
+ end_date => $end_dt,
+ );
+
+ my $council_details = { areaid => 2482 };
+ $update->update_comments( $o, $council_details );
+
+ my $start = $start_dt . '';
+ my $end = $end_dt . '';
+
+ my $uri = URI->new( $o->test_uri_used );
+ my $c = CGI::Simple->new( $uri->query );
+
+ is $c->param('start_date'), $start, 'start date used';
+ is $c->param('end_date'), $end, 'end date used';
+};
+
+subtest 'check that existing comments are not duplicated' => 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>
+ <service_request_id_ext>@{[ $problem->id ]}</service_request_id_ext>
+ <status>open</status>
+ <description>This is a note</description>
+ <updated_datetime>UPDATED_DATETIME</updated_datetime>
+ </request_update>
+ <request_update>
+ <update_id>638354</update_id>
+ <service_request_id>@{[ $problem->external_id ]}</service_request_id>
+ <service_request_id_ext>@{[ $problem->id ]}</service_request_id_ext>
+ <status>open</status>
+ <description>This is a different note</description>
+ <updated_datetime>UPDATED_DATETIME2</updated_datetime>
+ </request_update>
+ </service_requests_updates>
+ };
+
+ $problem->comments->delete;
+
+ my $comment = FixMyStreet::App->model('DB::Comment')->new(
+ {
+ problem => $problem,
+ external_id => 638344,
+ text => 'This is a note',
+ user => $user,
+ state => 'confirmed',
+ mark_fixed => 0,
+ anonymous => 0,
+ confirmed => $dt,
+ }
+ );
+ $comment->insert;
+
+ is $problem->comments->count, 1, 'one comment before fetching updates';
+
+ $requests_xml =~ s/UPDATED_DATETIME2/$dt/;
+ $requests_xml =~ s/UPDATED_DATETIME/@{[ $comment->confirmed ]}/;
+
+ my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'update.xml' => $requests_xml } );
+
+ my $update = Open311::GetServiceRequestUpdates->new(
+ system_user => $user,
+ );
+
+ my $council_details = { areaid => 2482 };
+ $update->update_comments( $o, $council_details );
+
+ $problem->discard_changes;
+ is $problem->comments->count, 2, 'two comments after fetching updates';
+
+ $update->update_comments( $o, $council_details );
+ $problem->discard_changes;
+ is $problem->comments->count, 2, 're-fetching updates does not add comments';
+
+ $problem->comments->delete;
+ $update->update_comments( $o, $council_details );
+ $problem->discard_changes;
+ is $problem->comments->count, 2, 'if comments are deleted then they are added';
+};
+
+$problem2->comments->delete();
+$problem->comments->delete();
+$problem2->delete;
+$problem->delete;
+$user->comments->delete;
+$user->problems->delete;
+$user->delete;
+
+done_testing();
diff --git a/t/open311/populate-service-list.t b/t/open311/populate-service-list.t
index bdb7404f9..63500d6cb 100644
--- a/t/open311/populate-service-list.t
+++ b/t/open311/populate-service-list.t
@@ -203,6 +203,304 @@ 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( council_list => [] );
+
+ 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::App->model('DB::Contact')->find_or_create(
+ {
+ area_id => 1,
+ email => '001',
+ category => 'Bins left out 24x7',
+ confirmed => 1,
+ deleted => 0,
+ editor => $0,
+ whenedited => \'ms_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 }
+ );
+
+ my $council = FixMyStreet::App->model('DB::Open311conf')->new( {
+ area_id => 2482
+ } );
+
+ $processor->_current_open311( $o );
+ $processor->_current_council( $council );
+ $processor->_current_service( { service_code => 100 } );
+
+ $processor->_add_contact_to_meta( $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->extra, $extra, 'meta data saved';
+};
+
+subtest 'check attribute ordering' => sub {
+ my $processor = Open311::PopulateServiceList->new( council_list => [] );
+
+ 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>
+ <attribute>
+ <variable>true</variable>
+ <code>colour</code>
+ <datatype>string</datatype>
+ <required>true</required>
+ <datatype_description>Colour of bin</datatype_description>
+ <order>3</order>
+ <description>Colour of bin</description>
+ </attribute>
+ <attribute>
+ <variable>true</variable>
+ <code>size</code>
+ <datatype>string</datatype>
+ <required>true</required>
+ <datatype_description>Size of bin</datatype_description>
+ <order>2</order>
+ <description>Size of bin</description>
+ </attribute>
+ </attributes>
+</service_definition>
+ ';
+
+ my $contact = FixMyStreet::App->model('DB::Contact')->find_or_create(
+ {
+ area_id => 1,
+ email => '001',
+ category => 'Bins left out 24x7',
+ confirmed => 1,
+ deleted => 0,
+ editor => $0,
+ whenedited => \'ms_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 }
+ );
+
+ my $council = FixMyStreet::App->model('DB::Open311conf')->new( {
+ area_id => 1
+ } );
+
+ $processor->_current_open311( $o );
+ $processor->_current_council( $council );
+ $processor->_current_service( { service_code => 100 } );
+
+ $processor->_add_contact_to_meta( $contact );
+
+ my $extra = [
+ {
+ variable => 'true',
+ code => 'type',
+ datatype => 'string',
+ required => 'true',
+ datatype_description => 'Type of bin',
+ order => 1,
+ description => 'Type of bin'
+
+ },
+ {
+ variable => 'true',
+ code => 'size',
+ datatype => 'string',
+ required => 'true',
+ datatype_description => 'Size of bin',
+ order => 2,
+ description => 'Size of bin'
+
+ },
+ {
+ variable => 'true',
+ code => 'colour',
+ datatype => 'string',
+ required => 'true',
+ datatype_description => 'Colour of bin',
+ order => 3,
+ description => 'Colour of bin'
+
+ },
+ ];
+
+ $contact->discard_changes;
+
+ is_deeply $contact->extra, $extra, 'meta data re-ordered correctly';
+};
+
+subtest 'check bromely skip code' => sub {
+ my $processor = Open311::PopulateServiceList->new( council_list => [] );
+
+ 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>
+ <attribute>
+ <variable>true</variable>
+ <code>title</code>
+ <datatype>string</datatype>
+ <required>true</required>
+ <datatype_description>Type of bin</datatype_description>
+ <order>1</order>
+ <description>Type of bin</description>
+ </attribute>
+ <attribute>
+ <variable>true</variable>
+ <code>report_url</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::App->model('DB::Contact')->find_or_create(
+ {
+ area_id => 1,
+ email => '001',
+ category => 'Bins left out 24x7',
+ confirmed => 1,
+ deleted => 0,
+ editor => $0,
+ whenedited => \'ms_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 }
+ );
+
+ my $council = FixMyStreet::App->model('DB::Open311conf')->new( {
+ area_id => 2482
+ } );
+
+ $processor->_current_open311( $o );
+ $processor->_current_council( $council );
+ $processor->_current_service( { service_code => 100 } );
+
+ $processor->_add_contact_to_meta( $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->extra, $extra, 'only non std bromley meta data saved';
+
+ $council->area_id(1);
+
+ $processor->_current_council( $council );
+ $processor->_add_contact_to_meta( $contact );
+
+ $extra = [
+ {
+ variable => 'true',
+ code => 'type',
+ datatype => 'string',
+ required => 'true',
+ datatype_description => 'Type of bin',
+ order => 1,
+ description => 'Type of bin'
+
+ },
+ {
+ variable => 'true',
+ code => 'title',
+ datatype => 'string',
+ required => 'true',
+ datatype_description => 'Type of bin',
+ order => 1,
+ description => 'Type of bin'
+
+ },
+ {
+ variable => 'true',
+ code => 'report_url',
+ datatype => 'string',
+ required => 'true',
+ datatype_description => 'Type of bin',
+ order => 1,
+ description => 'Type of bin'
+
+ },
+ ];
+
+ $contact->discard_changes;
+
+ is_deeply $contact->extra, $extra, 'all meta data saved for non bromley';
+};
+
sub get_standard_xml {
return qq{<?xml version="1.0" encoding="utf-8"?>
<services>