diff options
Diffstat (limited to 't')
42 files changed, 2247 insertions, 370 deletions
diff --git a/t/Mock/MapIt.pm b/t/Mock/MapIt.pm index 8dd10c53d..c57f7e0ed 100644 --- a/t/Mock/MapIt.pm +++ b/t/Mock/MapIt.pm @@ -23,6 +23,7 @@ sub output { } my @PLACES = ( + [ '?', 53.387402, -2.943997, 2527, 'Liverpool City Council', 'MTD' ], [ 'EH1 1BB', 55.952055, -3.189579, 2651, 'Edinburgh City Council', 'UTA', 20728, 'City Centre', 'UTE' ], [ 'BS10 5EE', 51.494885, -2.602237, 2561, 'Bristol City Council', 'UTA', 148646, 'Bedminster', 'UTW' ], [ 'SW1A 1AA', 51.501009, -0.141588, 2504, 'Westminster City Council', 'LBO' ], @@ -30,6 +31,7 @@ my @PLACES = ( [ '?', 51.754926, -1.256179, 2237, 'Oxfordshire County Council', 'CTY', 2421, 'Oxford City Council', 'DIS' ], [ 'OX20 1SZ', 51.754926, -1.256179, 2237, 'Oxfordshire County Council', 'CTY', 2421, 'Oxford City Council', 'DIS' ], [ 'BR1 3UH', 51.4021, 0.01578, 2482, 'Bromley Council', 'LBO' ], + [ 'BR1 3UH', 51.402096, 0.015784, 2482, 'Bromley Council', 'LBO' ], [ '?', 50.78301, -0.646929 ], [ 'GU51 4AE', 51.279456, -0.846216, 2333, 'Hart District Council', 'DIS', 2227, 'Hampshire County Council', 'CTY' ], [ 'WS1 4NH', 52.563074, -1.991032, 2535, 'Sandwell Borough Council', 'MTD' ], diff --git a/t/app/controller/admin/bodies.t b/t/app/controller/admin/bodies.t index 9bdf8fb9a..a485d286d 100644 --- a/t/app/controller/admin/bodies.t +++ b/t/app/controller/admin/bodies.t @@ -150,6 +150,45 @@ subtest 'check open311 configuring' => sub { is $conf->endpoint, 'http://example.org/open311', 'endpoint updated'; is $conf->api_key, 'new api key', 'api key updated'; is $conf->jurisdiction, 'open311', 'jurisdiction configures'; + ok !$conf->get_extra_metadata('fetch_all_problems'), 'fetch all problems unset'; + + $mech->form_number(3); + $mech->submit_form_ok( + { + with_fields => { + api_key => 'new api key', + endpoint => 'http://example.org/open311', + jurisdiction => 'open311', + send_comments => 0, + send_method => 'Open311', + fetch_all_problems => 1, + } + } + ); + + $mech->content_contains('Values updated'); + + $conf = FixMyStreet::App->model('DB::Body')->find( $body->id ); + ok $conf->get_extra_metadata('fetch_all_problems'), 'fetch all problems set'; + + $mech->form_number(3); + $mech->submit_form_ok( + { + with_fields => { + api_key => 'new api key', + endpoint => 'http://example.org/open311', + jurisdiction => 'open311', + send_comments => 0, + send_method => 'Open311', + fetch_all_problems => 0, + } + } + ); + + $mech->content_contains('Values updated'); + + $conf = FixMyStreet::App->model('DB::Body')->find( $body->id ); + ok !$conf->get_extra_metadata('fetch_all_problems'), 'fetch all problems unset'; }; subtest 'check text output' => sub { diff --git a/t/app/controller/admin/report_edit.t b/t/app/controller/admin/report_edit.t index a8a0bd143..5e3e6c315 100644 --- a/t/app/controller/admin/report_edit.t +++ b/t/app/controller/admin/report_edit.t @@ -79,6 +79,7 @@ foreach my $test ( anonymous => 0, flagged => undef, non_public => undef, + closed_updates => undef, }, changes => { title => 'Edited Report', }, log_entries => [qw/edit/], @@ -95,6 +96,7 @@ foreach my $test ( anonymous => 0, flagged => undef, non_public => undef, + closed_updates => undef, }, changes => { detail => 'Edited Detail', }, log_entries => [qw/edit edit/], @@ -111,6 +113,7 @@ foreach my $test ( anonymous => 0, flagged => undef, non_public => undef, + closed_updates => undef, }, changes => { name => 'Edited User', }, log_entries => [qw/edit edit edit/], @@ -128,6 +131,7 @@ foreach my $test ( anonymous => 0, flagged => undef, non_public => undef, + closed_updates => undef, }, changes => { flagged => 'on', @@ -147,6 +151,7 @@ foreach my $test ( anonymous => 0, flagged => 'on', non_public => undef, + closed_updates => undef, }, changes => { username => $user2->email, }, log_entries => [qw/edit edit edit edit edit/], @@ -164,6 +169,7 @@ foreach my $test ( anonymous => 0, flagged => 'on', non_public => undef, + closed_updates => undef, }, expect_comment => 1, changes => { state => 'unconfirmed' }, @@ -181,6 +187,7 @@ foreach my $test ( anonymous => 0, flagged => 'on', non_public => undef, + closed_updates => undef, }, expect_comment => 1, changes => { state => 'confirmed' }, @@ -198,6 +205,7 @@ foreach my $test ( anonymous => 0, flagged => 'on', non_public => undef, + closed_updates => undef, }, expect_comment => 1, changes => { state => 'fixed' }, @@ -216,6 +224,7 @@ foreach my $test ( anonymous => 0, flagged => 'on', non_public => undef, + closed_updates => undef, }, expect_comment => 1, changes => { state => 'hidden' }, @@ -235,6 +244,7 @@ foreach my $test ( anonymous => 0, flagged => 'on', non_public => undef, + closed_updates => undef, }, expect_comment => 1, changes => { @@ -257,6 +267,7 @@ foreach my $test ( anonymous => 1, flagged => 'on', non_public => undef, + closed_updates => undef, }, changes => {}, log_entries => [ @@ -275,6 +286,7 @@ foreach my $test ( anonymous => 1, flagged => 'on', non_public => undef, + closed_updates => undef, }, changes => { non_public => 'on', @@ -285,6 +297,24 @@ foreach my $test ( resend => 0, }, { + description => 'close to updates', + fields => { + title => 'Edited Report', + detail => 'Edited Detail', + state => 'confirmed', + name => 'Edited User', + username => $user2->email, + anonymous => 1, + flagged => 'on', + non_public => 'on', + closed_updates => undef, + }, + changes => { closed_updates => 'on' }, + log_entries => [ + qw/edit edit resend edit state_change edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/ + ], + }, + { description => 'change state to investigating as body superuser', fields => { title => 'Edited Report', @@ -295,12 +325,13 @@ foreach my $test ( anonymous => 1, flagged => 'on', non_public => 'on', + closed_updates => undef, }, expect_comment => 1, user_body => $oxfordshire, changes => { state => 'investigating' }, log_entries => [ - qw/edit state_change edit resend edit state_change edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/ + qw/edit state_change edit edit resend edit state_change edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/ ], resend => 0, }, @@ -315,13 +346,14 @@ foreach my $test ( anonymous => 1, flagged => 'on', non_public => 'on', + closed_updates => undef, }, expect_comment => 1, expected_text => '*Category changed from ‘Other’ to ‘Potholes’*', user_body => $oxfordshire, changes => { state => 'in progress', category => 'Potholes' }, log_entries => [ - qw/edit state_change edit state_change edit resend edit state_change edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/ + qw/edit state_change edit state_change edit edit resend edit state_change edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/ ], resend => 0, }, @@ -364,9 +396,22 @@ foreach my $test ( $mech->content_lacks( 'type="submit" name="resend"', 'no resend button' ); } + if ($report->state eq 'fixed') { + $mech->content_contains('pin-green'); + } + $test->{changes}->{flagged} = 1 if $test->{changes}->{flagged}; $test->{changes}->{non_public} = 1 if $test->{changes}->{non_public}; + if ($test->{changes}->{closed_updates}) { + is $report->get_extra_metadata('closed_updates'), 1, "closed_updates updated"; + $mech->get_ok("/report/$report_id"); + $mech->content_lacks('Provide an update'); + $report->unset_extra_metadata('closed_updates'); + $report->update; + delete $test->{changes}->{closed_updates}; + } + is $report->$_, $test->{changes}->{$_}, "$_ updated" for grep { $_ ne 'username' } keys %{ $test->{changes} }; if ( $test->{user} ) { @@ -447,6 +492,7 @@ subtest 'change email to new user' => sub { anonymous => 1, flagged => 'on', non_public => 'on', + closed_updates => undef, external_id => '13', external_body => '', external_team => '', @@ -553,4 +599,79 @@ subtest "Test setting a report from unconfirmed to something else doesn't cause $mech->get_ok("/report/$report_id"); }; +subtest "Test display of report extra data" => sub { + $mech->get_ok("/admin/report_edit/$report_id"); + $mech->content_contains('Extra data: No'); + $report->set_extra_metadata('extra_field', 'this is extra data'); + $report->update; + $mech->get_ok("/admin/report_edit/$report_id"); + $mech->content_contains('extra_field</strong>: this is extra data'); +}; + +my $report2 = FixMyStreet::App->model('DB::Problem')->find_or_create( + { + postcode => 'SW1A 1AA', + bodies_str => '2504', + areas => ',105255,11806,11828,2247,2504,', + category => 'Other', + title => 'Report to Duplicate Edit', + detail => 'Detail for Duplicate Report to Edit', + used_map => 't', + name => 'Test User', + anonymous => 'f', + external_id => '13', + state => 'confirmed', + confirmed => $dt->ymd . ' ' . $dt->hms, + lang => 'en-gb', + service => '', + cobrand => '', + cobrand_data => '', + send_questionnaire => 't', + latitude => '51.5016605453401', + longitude => '-0.142497580865087', + user_id => $user->id, + whensent => $dt->ymd . ' ' . $dt->hms, + } +); + +subtest "Test display of report duplicates extra data" => sub { + $report->update( { extra => undef } ); + $mech->get_ok("/admin/report_edit/$report_id"); + $mech->content_contains('Extra data: No'); + + $report2->set_duplicate_of($report_id); + $report2->update; + + $mech->get_ok("/admin/report_edit/$report_id"); + $mech->content_contains('Duplicates</strong>: ' . $report2->id); +}; + +subtest "Test display of fields extra data" => sub { + $report->unset_extra_metadata( 'duplicates' ); + $report->update; + $mech->get_ok("/admin/report_edit/$report_id"); + $mech->content_contains('Extra data: No'); + + $report->push_extra_fields( { + name => 'report_url', + value => 'http://example.com', + }); + $report->update; + + $report->discard_changes; + + $mech->get_ok("/admin/report_edit/$report_id"); + $mech->content_contains('report_url</strong>: http://example.com'); + + $report->set_extra_fields( { + description => 'Report URL', + name => 'report_url', + value => 'http://example.com', + }); + $report->update; + + $mech->get_ok("/admin/report_edit/$report_id"); + $mech->content_contains('Report URL (report_url)</strong>: http://example.com'); +}; + done_testing(); diff --git a/t/app/controller/admin/stats.t b/t/app/controller/admin/stats.t index dae51d31f..ce6f8466c 100644 --- a/t/app/controller/admin/stats.t +++ b/t/app/controller/admin/stats.t @@ -9,4 +9,30 @@ subtest "smoke view some stats pages" => sub { $mech->get_ok('/admin/stats/questionnaire'); }; +subtest "test refused stats page works" => sub { + my $body1 = $mech->create_body_ok(2651, 'Edinburgh Council'); + my $body2 = $mech->create_body_ok(2237, 'Oxfordshire Council', { send_method => 'Refused' }); + my $body3 = $mech->create_body_ok(2243, 'Warwickshire Council', { can_be_devolved => 1 }); + $mech->create_contact_ok(body_id => $body1->id, category => 'Street lighting', email => 'REFUSED'); + $mech->create_contact_ok(body_id => $body1->id, category => 'Potholes', email => 'potholes@example.org'); + $mech->create_contact_ok(body_id => $body2->id, category => 'Potholes', email => 'potholes@example.org'); + $mech->create_contact_ok(body_id => $body3->id, category => 'Street lighting', email => 'lights@example.org'); + $mech->create_contact_ok(body_id => $body3->id, category => 'Potholes', email => 'potholes@example.org', send_method => 'Refused'); + + FixMyStreet::override_config { + ALLOWED_COBRANDS => [ { fixmystreet => '.' } ], + }, sub { + $mech->get_ok('/admin/stats/refused'); + }; + $mech->content =~ /class="content"(.*)class="nav-wrapper/s; + my @lines = split /<li>/, $1; + is @lines, 7; + like $lines[1], qr/Edinburgh/; + like $lines[2], qr/Street lighting/; + like $lines[3], qr/Oxfordshire/; + like $lines[4], qr/ALL/; + like $lines[5], qr/Warwickshire/; + like $lines[6], qr/Potholes/; +}; + done_testing(); diff --git a/t/app/controller/admin/templates.t b/t/app/controller/admin/templates.t index 179a1afcb..0d4430cad 100644 --- a/t/app/controller/admin/templates.t +++ b/t/app/controller/admin/templates.t @@ -180,4 +180,55 @@ subtest "all-category auto-response templates that duplicate a single category c is $oxfordshire->response_templates->count, 1, "Duplicate response template wasn't added"; }; +subtest "auto-response templates that duplicate external_status_code can't be added" => sub { + $mech->delete_response_template($_) for $oxfordshire->response_templates; + my $template = $oxfordshire->response_templates->create({ + title => "Report fixed - potholes", + text => "Thank you for your report. This problem has been fixed.", + auto_response => 1, + external_status_code => '100', + }); + $template->contact_response_templates->find_or_create({ + contact_id => $oxfordshirecontact->id, + }); + is $oxfordshire->response_templates->count, 1, "Initial response template was created"; + + + $mech->log_in_ok( $superuser->email ); + $mech->get_ok( "/admin/templates/" . $oxfordshire->id . "/new" ); + + my $fields = { + title => "Report marked fixed - all cats", + text => "Thank you for your report. This problem has been fixed.", + auto_response => 'on', + external_status_code => '100', + }; + $mech->submit_form_ok( { with_fields => $fields } ); + is $mech->uri->path, '/admin/templates/' . $oxfordshire->id . '/new', 'not redirected'; + $mech->content_contains( 'Please correct the errors below' ); + $mech->content_contains( 'There is already an auto-response template for this category/state.' ); + + is $oxfordshire->response_templates->count, 1, "Duplicate response template wasn't added"; +}; + +subtest "templates that set state and external_status_code can't be added" => sub { + $mech->delete_response_template($_) for $oxfordshire->response_templates; + $mech->log_in_ok( $superuser->email ); + $mech->get_ok( "/admin/templates/" . $oxfordshire->id . "/new" ); + + my $fields = { + title => "Report marked fixed - all cats", + text => "Thank you for your report. This problem has been fixed.", + auto_response => 'on', + state => 'fixed - council', + external_status_code => '100', + }; + $mech->submit_form_ok( { with_fields => $fields } ); + is $mech->uri->path, '/admin/templates/' . $oxfordshire->id . '/new', 'not redirected'; + $mech->content_contains( 'Please correct the errors below' ); + $mech->content_contains( 'State and external status code cannot be used simultaneously.' ); + + is $oxfordshire->response_templates->count, 0, "Invalid response template wasn't added"; +}; + done_testing(); diff --git a/t/app/controller/alert_new.t b/t/app/controller/alert_new.t index 4e8fd1b29..27371e4a9 100644 --- a/t/app/controller/alert_new.t +++ b/t/app/controller/alert_new.t @@ -451,9 +451,8 @@ subtest "Test normal alert signups and that alerts are sent" => sub { is $count, 5, 'Three emails, with five matching lines in them'; my $email = $emails[0]; - my $body = $mech->get_text_body_from_email($email); - like $body, qr/Other User/, 'Update name given'; - unlike $body, qr/Anonymous User/, 'Update name not given'; + is +(my $c = () = $email->as_string =~ /Other User/g), 2, 'Update name given, twice'; + unlike $email->as_string, qr/Anonymous User/, 'Update name not given'; # The update alert was to the problem reporter, so has a special update URL $mech->log_out_ok; diff --git a/t/app/controller/around.t b/t/app/controller/around.t index 618998513..8eaba6450 100644 --- a/t/app/controller/around.t +++ b/t/app/controller/around.t @@ -137,7 +137,7 @@ subtest 'check non public reports are not displayed on around page' => sub { }; -subtest 'check category and status filtering works on /around' => sub { +subtest 'check category, status and extra filtering works on /around' => sub { my $body = $mech->create_body_ok(2237, "Oxfordshire"); my $categories = [ 'Pothole', 'Vegetation', 'Flytipping' ]; @@ -157,6 +157,7 @@ subtest 'check category and status filtering works on /around' => sub { %$params, category => $category, state => $state, + external_body => "$category-$state", ); $mech->create_problems_for_body( 1, $body->id, 'Around page', \%report_params ); } @@ -185,6 +186,13 @@ subtest 'check category and status filtering works on /around' => sub { $json = $mech->get_ok_json( '/around?ajax=1&status=fixed&filter_category=Vegetation&bbox=' . $bbox ); $pins = $json->{pins}; is scalar @$pins, 1, 'correct number of fixed Vegetation reports'; + + my $cobrand = Test::MockModule->new('FixMyStreet::Cobrand::Default'); + $cobrand->mock('display_location_extra_params', sub { { external_body => "Pothole-fixed" } }); + + $json = $mech->get_ok_json( '/around?ajax=1&bbox=' . $bbox ); + $pins = $json->{pins}; + is scalar @$pins, 1, 'correct number of external_body reports'; }; subtest 'check skip_around skips around page' => sub { diff --git a/t/app/controller/contact.t b/t/app/controller/contact.t index c1039d15b..4f255f058 100644 --- a/t/app/controller/contact.t +++ b/t/app/controller/contact.t @@ -37,6 +37,17 @@ for my $test ( detail => 'More detail on the different problem', postcode => 'EH99 1SP', confirmed => '2011-05-03 13:24:28.145168', + anonymous => 0, + hidden => 1, + meta => 'Reported anonymously at 13:24, Tue 3 May 2011', + }, + { + name => 'A User', + email => 'problem_report_test@example.com', + title => 'A different problem', + detail => 'More detail on the different problem', + postcode => 'EH99 1SP', + confirmed => '2011-05-03 13:24:28.145168', anonymous => 1, meta => 'Reported anonymously at 13:24, Tue 3 May 2011', update => { @@ -45,6 +56,38 @@ for my $test ( text => 'This is an update', }, }, + { + name => 'A User', + email => 'problem_report_test@example.com', + title => 'A different problem', + detail => 'More detail on the different problem', + postcode => 'EH99 1SP', + confirmed => '2011-05-03 13:24:28.145168', + anonymous => 1, + meta => 'Reported anonymously at 13:24, Tue 3 May 2011', + update => { + other_problem => 1, + name => 'Different User', + email => 'commenter@example.com', + text => 'This is an update', + }, + }, + { + name => 'A User', + email => 'problem_report_test@example.com', + title => 'A different problem', + detail => 'More detail on the different problem', + postcode => 'EH99 1SP', + confirmed => '2011-05-03 13:24:28.145168', + anonymous => 1, + meta => 'Reported anonymously at 13:24, Tue 3 May 2011', + update => { + hidden => 1, + name => 'Different User', + email => 'commenter@example.com', + text => 'This is an update', + }, + }, ) { subtest 'check reporting a problem displays correctly' => sub { @@ -58,7 +101,7 @@ for my $test ( confirmed => $test->{confirmed}, name => $test->{name}, anonymous => $test->{anonymous}, - state => 'confirmed', + state => $test->{hidden} ? 'hidden' : 'confirmed', user => $user, latitude => 0, longitude => 0, @@ -76,9 +119,9 @@ for my $test ( $update = FixMyStreet::App->model('DB::Comment')->create( { - problem_id => $problem->id, + problem_id => $update_info->{other_problem} ? $problem_main->id : $problem->id, user => $update_user, - state => 'confirmed', + state => $update_info->{hidden} ? 'hidden' : 'confirmed', text => $update_info->{text}, confirmed => \'current_timestamp', mark_fixed => 'f', @@ -90,9 +133,20 @@ for my $test ( ok $problem, 'succesfully create a problem'; if ( $update ) { - $mech->get_ok( '/contact?id=' . $problem->id . '&update_id=' . $update->id ); - $mech->content_contains('reporting the following update'); - $mech->content_contains( $test->{update}->{text} ); + if ( $test->{update}->{hidden} ) { + $mech->get( '/contact?id=' . $problem->id . '&update_id=' . $update->id ); + is $mech->res->code, 404, 'cannot report a hidden update'; + } elsif ( $test->{update}->{other_problem} ) { + $mech->get( '/contact?id=' . $problem->id . '&update_id=' . $update->id ); + is $mech->res->code, 404, 'cannot view an update for another problem'; + } else { + $mech->get_ok( '/contact?id=' . $problem->id . '&update_id=' . $update->id ); + $mech->content_contains('reporting the following update'); + $mech->content_contains( $test->{update}->{text} ); + } + } elsif ( $test->{hidden} ) { + $mech->get( '/contact?id=' . $problem->id ); + is $mech->res->code, 410, 'cannot report a hidden problem'; } else { $mech->get_ok( '/contact?id=' . $problem->id ); $mech->content_contains('reporting the following problem'); diff --git a/t/app/controller/develop.t b/t/app/controller/develop.t new file mode 100644 index 000000000..92aa86721 --- /dev/null +++ b/t/app/controller/develop.t @@ -0,0 +1,33 @@ +use FixMyStreet::TestMech; + +ok( my $mech = FixMyStreet::TestMech->new, 'Created mech object' ); + +my ($problem) = $mech->create_problems_for_body(1, 2504, 'title'); +my $update = $mech->create_comment_for_problem($problem, $problem->user, 'Name', 'Text', 'f', 'confirmed', 'confirmed'); + +subtest 'not visible on live site' => sub { + FixMyStreet::override_config { + STAGING_SITE => 0 + }, sub { + $mech->get('/_dev/email/'); + is $mech->res->code, 404; + $mech->get('/_dev/email/login'); + is $mech->res->code, 404; + }; +}; + +subtest 'dev email index page' => sub { + $mech->get_ok('/_dev/email/'); + $mech->content_contains('login">login</a></li>'); + $mech->content_contains('questionnaire?problem=' . $problem->id . '">questionnaire</a></li>'); + $mech->content_contains('update-confirm?update=' . $update->id . '">update-confirm</a></li>'); +}; + +subtest 'individual email previews' => sub { + $mech->get_ok('/_dev/email/alert-problem-area'); + $mech->get_ok('/_dev/email/alert-update?problem=' . $problem->id); + $mech->get_ok('/_dev/email/questionnaire?problem=' . $problem->id); + $mech->get_ok('/_dev/email/update-confirm?update=' . $update->id); +}; + +done_testing(); diff --git a/t/app/controller/fakemapit.t b/t/app/controller/fakemapit.t new file mode 100644 index 000000000..c89aac600 --- /dev/null +++ b/t/app/controller/fakemapit.t @@ -0,0 +1,13 @@ +use JSON::MaybeXS; +use FixMyStreet::TestMech; + +my $mech = FixMyStreet::TestMech->new; + +FixMyStreet::override_config { + MAPIT_URL => 'http://mapit.uk/', +}, sub { + $mech->get_ok('/mapit/areas/Birmingham'); + is_deeply decode_json($mech->content), {2514 => {parent_area => undef, id => 2514, name => "Birmingham City Council", type => "MTD"}}; +}; + +done_testing; diff --git a/t/app/controller/open311.t b/t/app/controller/open311.t index 29cd38129..9f4f594fe 100644 --- a/t/app/controller/open311.t +++ b/t/app/controller/open311.t @@ -1,3 +1,4 @@ +use JSON::MaybeXS; use FixMyStreet::TestMech; my $mech = FixMyStreet::TestMech->new; @@ -5,4 +6,16 @@ my $mech = FixMyStreet::TestMech->new; $mech->get_ok('/open311.cgi/v2/requests.rss?jurisdiction_id=fiksgatami.no&status=open&agency_responsible=1854'); like $mech->uri, qr[/open311/v2/requests\.rss\?.{65}]; # Don't know order parameters will be in now +$mech->create_problems_for_body(2, 2237, 'Around page'); +$mech->get_ok('/open311/v2/requests.xml?jurisdiction_id=foo&status=open&agency_responsible=2237'); +$mech->content_contains('<description>Around page Test 2 for 2237: Around page Test 2 for 2237 Detail</description>'); +$mech->content_contains('<interface_used>Web interface</interface_used>'); +$mech->content_contains('<status>open</status>'); + +$mech->get_ok('/open311/v2/requests.json?jurisdiction_id=foo&status=open&agency_responsible=2237'); +my $json = decode_json($mech->content); +my $problems = $json->{requests}[0]{request}; +is @$problems, 2; +like $problems->[0]{description}, qr/Around page Test/; + done_testing(); diff --git a/t/app/controller/photo.t b/t/app/controller/photo.t index dbbc697d7..e9183836b 100644 --- a/t/app/controller/photo.t +++ b/t/app/controller/photo.t @@ -66,7 +66,43 @@ subtest "Check multiple upload worked" => sub { 'Returned upload_fileid contains expected hash, 3 times'); my $image_file = path($UPLOAD_DIR, '74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg'); ok $image_file->exists, 'File uploaded to temp'; + + $mech->submit_form_ok({ with_fields => { name => 'Bob Jones' } }); + ok $mech->success, 'Made request with multiple photo upload'; }; }; +subtest "Check photo uploading URL works" => sub { + my $UPLOAD_DIR = tempdir( CLEANUP => 1 ); + + # submit initial pc form + FixMyStreet::override_config { + UPLOAD_DIR => $UPLOAD_DIR, + }, sub { + $mech->post( '/photo/upload', + Content_Type => 'form-data', + Content => { + photo1 => [ $sample_file, undef, Content_Type => 'application/octet-stream' ], + }, + ); + ok $mech->success, 'Made request with multiple photo upload'; + is $mech->content, '{"id":"74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg"}'; + my $image_file = path($UPLOAD_DIR, '74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg'); + ok $image_file->exists, 'File uploaded to temp'; + }; +}; + +subtest "Check photo URL endpoints work" => sub { + my $p = FixMyStreet::DB->resultset("Problem")->first; + + $mech->get_ok('/photo/temp.74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg'); + my $image_file = FixMyStreet->path_to('web/photo/temp.74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg'); + ok -e $image_file, 'File uploaded to temp'; + $mech->get_ok('/photo/' . $p->id . '.jpeg'); + $image_file = FixMyStreet->path_to('web/photo/' . $p->id . '.jpeg'); + ok -e $image_file, 'File uploaded to temp'; + my $res = $mech->get('/photo/0.jpeg'); + is $res->code, 404, "got 404"; +}; + done_testing(); diff --git a/t/app/controller/questionnaire.t b/t/app/controller/questionnaire.t index c6d112df7..75542d759 100644 --- a/t/app/controller/questionnaire.t +++ b/t/app/controller/questionnaire.t @@ -52,7 +52,7 @@ like $plain->body, qr/fill in our short questionnaire/i, "got questionnaire emai like $plain->body_str, qr/Testing \x{2013} Detail/, 'email contains encoded character'; is $plain->header('Content-Type'), 'text/plain; charset="utf-8"', 'in the right character set'; -my $url = $mech->get_link_from_email($email); +my $url = $mech->get_link_from_email($email, 0, 1); my ($token) = $url =~ m{/Q/(\S+)}; ok $token, "extracted questionnaire token '$token'"; $mech->clear_emails_ok; @@ -108,6 +108,23 @@ foreach my $test ( }; } +subtest "If been_fixed is provided in the URL" => sub { + $mech->get_ok("/Q/" . $token->token . "?been_fixed=Yes"); + $mech->content_contains('id="been_fixed_yes" value="Yes" checked'); + $report->discard_changes; + is $report->state, 'fixed - user'; + $questionnaire->discard_changes; + is $questionnaire->old_state, 'confirmed'; + is $questionnaire->new_state, 'fixed - user'; + $mech->submit_form_ok({ with_fields => { been_fixed => 'Unknown', reported => 'Yes', another => 'No' } }); + $report->discard_changes; + is $report->state, 'confirmed'; + $questionnaire->discard_changes; + is $questionnaire->old_state, 'confirmed'; + is $questionnaire->new_state, 'unknown'; + $questionnaire->update({ whenanswered => undef, ever_reported => undef, old_state => undef, new_state => undef }); +}; + $mech->get_ok("/Q/" . $token->token); $mech->title_like( qr/Questionnaire/ ); $mech->submit_form_ok( ); @@ -399,7 +416,7 @@ FixMyStreet::override_config { $mech->clear_emails_ok; $body =~ s/\s+/ /g; like $body, qr/fill in our short questionnaire/i, "got questionnaire email"; - my $url = $mech->get_link_from_email($email); + my $url = $mech->get_link_from_email($email, 0, 1); ($token) = $url =~ m{/Q/(\S+)}; ok $token, "extracted questionnaire token '$token'"; diff --git a/t/app/controller/report_as_other.t b/t/app/controller/report_as_other.t index e8f65eb7b..367d9a1d4 100644 --- a/t/app/controller/report_as_other.t +++ b/t/app/controller/report_as_other.t @@ -1,5 +1,6 @@ use FixMyStreet::TestMech; use FixMyStreet::App; +use FixMyStreet::Script::Reports; # disable info logs for this test run FixMyStreet::App->log->disable('info'); @@ -15,7 +16,7 @@ my $test_email = 'body-user@example.net'; my $user = $mech->log_in_ok($test_email); $user->update({ from_body => $body->id, name => 'Body User' }); -my ($report_to_update) = $mech->create_problems_for_body(1, $body->id, 'Title'); +my ($report_to_update) = $mech->create_problems_for_body(1, $body->id, 'Title', { category => 'Potholes' }); subtest "Body user, no permissions, no special reporting tools shown" => sub { start_report(); @@ -100,6 +101,9 @@ subtest "Body user, has permission to add report as another user with landline n }; subtest "Body user, has permission to add report as another (existing) user with email" => sub { + FixMyStreet::Script::Reports::send(); + $mech->clear_emails_ok; + $mech->create_user_ok('existing@example.net', name => 'Existing User'); my $report = add_report( 'contribute_as_another_user', @@ -116,6 +120,15 @@ subtest "Body user, has permission to add report as another (existing) user with isnt $report->user->id, $user->id, 'user does not match'; like $mech->get_text_body_from_email, qr/Your report to Oxfordshire County Council has been logged/; push @users, $report->user; + + my $send_confirmation_mail_override = Sub::Override->new( + "FixMyStreet::Cobrand::Default::report_sent_confirmation_email", + sub { return 1; } + ); + FixMyStreet::Script::Reports::send(); + $mech->email_count_is(2); + $mech->clear_emails_ok; + $send_confirmation_mail_override->restore(); }; subtest "Body user, has permission to add report as another (existing) user with phone" => sub { @@ -138,6 +151,9 @@ subtest "Body user, has permission to add report as another (existing) user with }; subtest "Body user, has permission to add report as anonymous user" => sub { + FixMyStreet::Script::Reports::send(); + $mech->clear_emails_ok; + my $report = add_report( 'contribute_as_anonymous_user', form_as => 'anonymous_user', @@ -149,6 +165,19 @@ subtest "Body user, has permission to add report as anonymous user" => sub { is $report->user->name, 'Body User', 'user name unchanged'; is $report->user->id, $user->id, 'user matches'; is $report->anonymous, 1, 'report anonymous'; + + my $send_confirmation_mail_override = Sub::Override->new( + "FixMyStreet::Cobrand::Default::report_sent_confirmation_email", + sub { return 1; } + ); + + FixMyStreet::Script::Reports::send(); + # No report sent email is sent + $mech->email_count_is(1); + my $email = $mech->get_email; + like $email->header('Subject'), qr/Problem Report: Test Report/, 'report email title correct'; + $mech->clear_emails_ok; + $send_confirmation_mail_override->restore(); }; subtest "Body user, has permission to add update as council" => sub { diff --git a/t/app/controller/report_display.t b/t/app/controller/report_display.t index f0913fbd2..17b9180c1 100644 --- a/t/app/controller/report_display.t +++ b/t/app/controller/report_display.t @@ -115,6 +115,12 @@ subtest "duplicate reports are signposted correctly" => sub { $report2->update; }; +subtest "test /report/ajax" => sub { + my $json = $mech->get_ok_json( "/report/ajax/$report_id" ); + is $json->{report}->{title}, "Test 2", "correct title"; + is $json->{report}->{state}, "confirmed", "correct state"; +}; + subtest "test a good report" => sub { $mech->get_ok("/report/$report_id"); is $mech->uri->path, "/report/$report_id", "at /report/$report_id"; @@ -419,106 +425,6 @@ for my $test ( }; } -subtest "Zurich unconfirmeds are 200" => sub { - FixMyStreet::override_config { - ALLOWED_COBRANDS => [ 'zurich' ], - MAP_TYPE => 'Zurich,OSM', - }, sub { - $mech->host( 'zurich.example.com' ); - ok $report->update( { state => 'unconfirmed' } ), 'unconfirm report'; - $mech->get_ok("/report/$report_id"); - $mech->content_contains( 'Überprüfung ausstehend' ); - ok $report->update( { state => 'confirmed' } ), 'confirm report again'; - $mech->host( 'www.fixmystreet.com' ); - }; -}; - -subtest "Zurich banners are displayed correctly" => sub { - FixMyStreet::override_config { - ALLOWED_COBRANDS => [ 'zurich' ], - MAP_TYPE => 'Zurich,OSM', - }, sub { - $mech->host( 'zurich.example.com' ); - - for my $test ( - { - description => 'new report', - state => 'unconfirmed', - banner_id => 'closed', - banner_text => 'Erfasst' - }, - { - description => 'confirmed report', - state => 'confirmed', - banner_id => 'closed', - banner_text => 'Aufgenommen', - }, - { - description => 'fixed report', - state => 'fixed - council', - banner_id => 'fixed', - banner_text => 'Beantwortet', - }, - { - description => 'closed report', - state => 'closed', - banner_id => 'closed', - banner_text => _('Extern'), - }, - { - description => 'in progress report', - state => 'in progress', - banner_id => 'progress', - banner_text => 'In Bearbeitung', - }, - { - description => 'planned report', - state => 'planned', - banner_id => 'progress', - banner_text => 'In Bearbeitung', - }, - { - description => 'planned report', - state => 'planned', - banner_id => 'progress', - banner_text => 'In Bearbeitung', - }, - { - description => 'jurisdiction unknown', - state => 'unable to fix', - banner_id => 'fixed', - # We can't use _('Jurisdiction Unknown') here because - # TestMech::extract_problem_banner decodes the HTML entities before - # the string is passed back. - banner_text => 'Zust\x{e4}ndigkeit unbekannt', - }, - ) { - subtest "banner for $test->{description}" => sub { - $report->state( $test->{state} ); - $report->update; - - $mech->get_ok("/report/$report_id"); - is $mech->uri->path, "/report/$report_id", "at /report/$report_id"; - my $banner = $mech->extract_problem_banner; - if ( $banner->{text} ) { - $banner->{text} =~ s/^ //g; - $banner->{text} =~ s/ $//g; - } - - is $banner->{id}, $test->{banner_id}, 'banner id'; - if ($test->{banner_text}) { - like_string( $banner->{text}, qr/$test->{banner_text}/i, 'banner text is ' . $test->{banner_text} ); - } else { - is $banner->{text}, $test->{banner_text}, 'banner text'; - } - - }; - } - - $mech->host( 'www.fixmystreet.com' ); - }; -}; - my $oxfordshire = $mech->create_body_ok(2237, 'Oxfordshire County Council'); my $oxfordshireuser = $mech->create_user_ok('counciluser@example.com', name => 'Council User', from_body => $oxfordshire); diff --git a/t/app/controller/report_inspect.t b/t/app/controller/report_inspect.t index 239cc408b..6a001225d 100644 --- a/t/app/controller/report_inspect.t +++ b/t/app/controller/report_inspect.t @@ -36,8 +36,8 @@ my $report_id = $report->id; my $report2_id = $report2->id; my $report3_id = $report3->id; - -my $user = $mech->log_in_ok('test@example.com'); +$mech->create_user_ok('body@example.com', name => 'Body User'); +my $user = $mech->log_in_ok('body@example.com'); $user->set_extra_metadata('categories', [ $contact->id ]); $user->update( { from_body => $oxon } ); @@ -50,18 +50,36 @@ FixMyStreet::override_config { $mech->content_lacks('Save changes'); $mech->content_lacks('Priority'); $mech->content_lacks('Traffic management'); + $mech->content_lacks('/admin/report_edit/'.$report_id.'">admin</a>)'); $user->user_body_permissions->create({ body => $oxon, permission_type => 'report_edit_priority' }); $mech->get_ok("/report/$report_id"); $mech->content_contains('Save changes'); $mech->content_contains('Priority'); $mech->content_lacks('Traffic management'); + $mech->content_lacks('/admin/report_edit/'.$report_id.'">admin</a>)'); $user->user_body_permissions->create({ body => $oxon, permission_type => 'report_inspect' }); $mech->get_ok("/report/$report_id"); $mech->content_contains('Save changes'); $mech->content_contains('Priority'); $mech->content_contains('Traffic management'); + $mech->content_lacks('/admin/report_edit/'.$report_id.'">admin</a>)'); + }; + + subtest "council staff can't see admin report edit link on FMS.com" => sub { + my $report_edit_permission = $user->user_body_permissions->create({ + body => $oxon, permission_type => 'report_edit' }); + $mech->get_ok("/report/$report_id"); + $mech->content_lacks('/admin/report_edit/'.$report_id.'">admin</a>)'); + $report_edit_permission->delete; + }; + + subtest "superusers can see admin report edit link on FMS.com" => sub { + $user->update({is_superuser => 1}); + $mech->get_ok("/report/$report_id"); + $mech->content_contains('/admin/report_edit/'.$report_id.'">admin</a>)'); + $user->update({is_superuser => 0}); }; subtest "test basic inspect submission" => sub { @@ -539,6 +557,13 @@ FixMyStreet::override_config { is $report->get_extra_metadata('traffic_information'), 'Signs and Cones', 'report data changed'; }; + subtest "admin link present on inspect page on cobrand" => sub { + my $report_edit_permission = $user->user_body_permissions->create({ + body => $oxon, permission_type => 'report_edit' }); + $mech->get_ok("/report/$report_id"); + $mech->content_contains('/admin/report_edit/'.$report_id.'">admin</a>)'); + $report_edit_permission->delete; + }; }; FixMyStreet::override_config { @@ -559,6 +584,7 @@ FixMyStreet::override_config { my $expected_fields = { state => 'action scheduled', category => 'Cows', + non_public => undef, public_update => '', priority => $rp->id, include_update => '1', @@ -594,6 +620,35 @@ FixMyStreet::override_config { is $report->comments->count, 1, "Only leaves one update"; like $report->comments->first->text, qr/Category changed.*Badgers/, 'update text included category change'; }; + + subtest "test non-public changing" => sub { + $report->comments->delete; + is $report->non_public, 0, 'Not set to non-public'; + $mech->get_ok("/report/$report_id"); + $mech->submit_form(button => 'save', with_fields => { include_update => 0, non_public => 1 }); + is $report->comments->count, 0, "No updates left"; + $report->discard_changes; + is $report->non_public, 1, 'Now set to non-public'; + $mech->submit_form(button => 'save', with_fields => { include_update => 0, non_public => 0 }); + is $report->comments->count, 0, "No updates left"; + $report->discard_changes; + is $report->non_public, 0, 'Not set to non-public'; + }; + + subtest "test saved-at setting" => sub { + $report->comments->delete; + $mech->get_ok("/report/$report_id"); + # set the timezone on this so the date comparison below doesn't fail due to mismatched + # timezones + my $now = DateTime->now( + time_zone => FixMyStreet->time_zone || FixMyStreet->local_time_zone + )->subtract(days => 1); + $mech->submit_form(button => 'save', form_id => 'report_inspect_form', + fields => { include_update => 1, public_update => 'An update', saved_at => $now->epoch }); + $report->discard_changes; + is $report->comments->count, 1, "One update"; + is $report->comments->first->confirmed, $now; + }; }; FixMyStreet::override_config { diff --git a/t/app/controller/report_new.t b/t/app/controller/report_new.t index 3c120b0b0..dff04176b 100644 --- a/t/app/controller/report_new.t +++ b/t/app/controller/report_new.t @@ -1,3 +1,4 @@ +use Test::MockModule; use FixMyStreet::TestMech; use FixMyStreet::App; use Web::Scraper; @@ -86,6 +87,16 @@ my $contact8 = $mech->create_contact_ok( category => 'Street lighting', email => 'highways@example.com' ); +my $contact9 = $mech->create_contact_ok( + body_id => $body_ids{2226}, # Gloucestershire + category => 'Street lighting', + email => 'streetlights-2226@example.com', +); +my $contact10 = $mech->create_contact_ok( + body_id => $body_ids{2326}, # Cheltenham + category => 'Street lighting', + email => 'streetlights-2326@example.com', +); # test that the various bit of form get filled in and errors correctly # generated. @@ -932,6 +943,125 @@ foreach my $test ( } +# XXX add test for category with multiple bodies +foreach my $test ( + { + desc => "test report creation for multiple bodies", + category => 'Street lighting', + councils => [ 2226, 2326 ], + extra_fields => {}, + email_count => 2, + }, + { + desc => "test single_body_only means only one report body", + category => 'Street lighting', + councils => [ 2326 ], + extra_fields => { single_body_only => 'Cheltenham Borough Council' }, + email_count => 1, + }, + { + desc => "test invalid single_body_only means multiple report bodies", + category => 'Street lighting', + councils => [ 2226, 2326 ], + extra_fields => { single_body_only => 'Invalid council' }, + email_count => 1, + }, +) { + subtest $test->{desc} => sub { + + # check that the user does not exist + my $test_email = 'test-2@example.com'; + + $mech->clear_emails_ok; + my $user = $mech->log_in_ok($test_email); + + # setup the user. + ok $user->update( + { + name => 'Test User', + phone => '01234 567 890', + } + ), + "set users details"; + + # submit initial pc form + $mech->get_ok('/around'); + FixMyStreet::override_config { + ALLOWED_COBRANDS => [ { fixmystreet => '.' } ], + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $mech->submit_form_ok( { with_fields => { pc => 'GL50 2PR', } }, + "submit location" ); + + # click through to the report page + $mech->follow_link_ok( { text_regex => qr/skip this step/i, }, + "follow 'skip this step' link" ); + + # check that the fields are correctly prefilled + is_deeply( + $mech->visible_form_values, + { + title => '', + detail => '', + may_show_name => '1', + name => 'Test User', + phone => '01234 567 890', + photo1 => '', + photo2 => '', + photo3 => '', + category => '-- Pick a category --', + }, + "user's details prefilled" + ); + + $mech->submit_form_ok( + { + with_fields => { + title => "Test Report at café", + detail => 'Test report details.', + photo1 => '', + name => 'Joe Bloggs', + may_show_name => '1', + phone => '07903 123 456', + category => $test->{category}, + %{$test->{extra_fields}} + } + }, + "submit good details" + ); + }; + + # find the report + my $report = $user->problems->first; + ok $report, "Found the report"; + + # Check the report has been assigned appropriately + is $report->bodies_str, join(',', @body_ids{@{$test->{councils}}}); + + $mech->content_contains('Thank you for reporting this issue'); + + # check that no emails have been sent + $mech->email_count_is(0); + + # check report is confirmed and available + is $report->state, 'confirmed', "report is now confirmed"; + $mech->get_ok( '/report/' . $report->id ); + + # Test that AJAX pages return the right data + $mech->get_ok( + '/around?ajax=1&bbox=' . ($report->longitude - 0.01) . ',' . ($report->latitude - 0.01) + . ',' . ($report->longitude + 0.01) . ',' . ($report->latitude + 0.01) + ); + $mech->content_contains( "Test Report at caf\xc3\xa9" ); + $saved_lat = $report->latitude; + $saved_lon = $report->longitude; + + # cleanup + $mech->delete_user($user); + }; + +} + subtest "Test inactive categories" => sub { FixMyStreet::override_config { ALLOWED_COBRANDS => [ { fixmystreet => '.' } ], @@ -958,6 +1088,21 @@ subtest "Test inactive categories" => sub { }; }; +subtest "category groups" => sub { + my $cobrand = Test::MockModule->new('FixMyStreet::Cobrand::FixMyStreet'); + $cobrand->mock('enable_category_groups', sub { 1 }); + FixMyStreet::override_config { + ALLOWED_COBRANDS => 'fixmystreet', + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $contact2->update( { extra => { group => 'Roads' } } ); + $contact9->update( { extra => { group => 'Roads' } } ); + $contact10->update( { extra => { group => 'Roads' } } ); + $mech->get_ok("/report/new?lat=$saved_lat&lon=$saved_lon"); + $mech->content_like(qr{<optgroup label="Roads">\s*<option value='Potholes'>Potholes</option>\s*<option value='Street lighting'>Street lighting</option></optgroup>}); + }; +}; + subtest "test report creation for a category that is non public" => sub { $mech->log_out_ok; $mech->clear_emails_ok; @@ -1040,6 +1185,7 @@ FixMyStreet::override_config { $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=' . $saved_lat . '&longitude=' . $saved_lon ); }; $mech->content_contains( "Pothol\xc3\xa9s" ); +like $extra_details->{councils_text}, qr/<strong>Cheltenham/; ok !$extra_details->{titles_list}, 'Non Bromley does not send back list of titles'; FixMyStreet::override_config { @@ -1733,7 +1879,11 @@ subtest "extra google analytics code displayed on email confirmation problem cre }; }; -subtest "inspectors get redirected directly to the report page" => sub { +foreach my $test ( + { non_public => 0 }, + { non_public => 1 }, +) { + subtest "inspectors get redirected directly to the report page, non_public=$test->{non_public}" => sub { FixMyStreet::override_config { ALLOWED_COBRANDS => [ { fixmystreet => '.' } ], BASE_URL => 'https://www.fixmystreet.com', @@ -1746,10 +1896,14 @@ subtest "inspectors get redirected directly to the report page" => sub { body => $bodies[0], permission_type => 'planned_reports', }); + $user->user_body_permissions->find_or_create({ + body => $bodies[0], + permission_type => 'report_inspect', + }); $mech->log_in_ok('inspector@example.org'); $mech->get_ok('/'); - $mech->submit_form_ok( { with_fields => { pc => 'GL50 2PR' } }, + $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB' } }, "submit location" ); $mech->follow_link_ok( { text_regex => qr/skip this step/i, }, @@ -1766,6 +1920,7 @@ subtest "inspectors get redirected directly to the report page" => sub { may_show_name => '1', phone => '07903 123 456', category => 'Trees', + non_public => $test->{non_public}, } }, "submit good details" @@ -1773,6 +1928,7 @@ subtest "inspectors get redirected directly to the report page" => sub { like $mech->uri->path, qr/\/report\/[0-9]+/, 'Redirects directly to report'; } -}; + }; +} done_testing(); diff --git a/t/app/controller/report_new_open311.t b/t/app/controller/report_new_open311.t index 0224e7e47..17b489447 100644 --- a/t/app/controller/report_new_open311.t +++ b/t/app/controller/report_new_open311.t @@ -1,5 +1,6 @@ use FixMyStreet::TestMech; use FixMyStreet::App; +use Test::LongString; use Web::Scraper; # disable info logs for this test run @@ -39,32 +40,57 @@ my $contact2 = $mech->create_contact_ok( category => 'Graffiti Removal', email => '101', ); +$mech->create_contact_ok( + body_id => $body->id, # Edinburgh + category => 'Ball lighting', + email => '102', + extra => { _fields => [ + { description => 'Size', code => 'size', required => 'True', automated => '' }, + { description => 'Speed', code => 'speed', required => 'True', automated => 'server_set' }, + { description => 'Colour', code => 'colour', required => 'True', automated => 'hidden_field' }, + ] }, +); + +my $body2 = $mech->create_body_ok(2651, 'Edinburgh Council'); +my $contact4 = $mech->create_contact_ok( + body_id => $body2->id, # Edinburgh + category => 'Pothole', + email => '103', + extra => { _fields => [ + { description => 'USRN', code => 'usrn', required => 'true', automated => 'hidden_field', variable => 'true', order => '1' }, + { description => 'Asset ID', code => 'central_asset_id', required => 'true', automated => 'hidden_field', variable => 'true', order => '2' }, + ] }, +); # test that the various bit of form get filled in and errors correctly # generated. +my $empty_form = { + title => '', + detail => '', + photo1 => '', + photo2 => '', + photo3 => '', + name => '', + may_show_name => '1', + username => '', + email => '', + phone => '', + category => '', + password_sign_in => '', + password_register => '', + remember_me => undef, +}; foreach my $test ( { msg => 'all fields empty', pc => 'EH99 1SP', fields => { - title => '', - detail => '', - photo1 => '', - photo2 => '', - photo3 => '', - name => '', - may_show_name => '1', - username => '', - email => '', - phone => '', - category => 'Street lighting', - password_sign_in => '', - password_register => '', - remember_me => undef, + %$empty_form, + category => 'Street lighting', }, changes => { number => '', - type => 'old', + type => '', }, errors => [ 'This information is required', @@ -80,6 +106,7 @@ foreach my $test ( username => 'testopen311@example.com', category => 'Street lighting', number => 27, + type => 'old', }, extra => [ { @@ -94,6 +121,45 @@ foreach my $test ( } ] }, + { + msg => 'automated things', + pc => 'EH99 1SP', + fields => { + %$empty_form, + category => 'Ball lighting', + }, + changes => { + size => '', + }, + hidden => [ 'colour' ], + errors => [ + 'This information is required', + 'Please enter a subject', + 'Please enter some details', + 'Please enter your email', + 'Please enter your name', + ], + submit_with => { + title => 'test', + detail => 'test detail', + name => 'Test User', + username => 'testopen311@example.com', + size => 'big', + colour => 'red', + }, + extra => [ + { + name => 'size', + value => 'big', + description => 'Size', + }, + { + name => 'colour', + value => 'red', + description => 'Colour', + } + ] + }, ) { subtest "check form errors where $test->{msg}" => sub { @@ -139,6 +205,12 @@ foreach my $test ( }; is_deeply $mech->visible_form_values, $new_values, "values correctly changed"; + if ($test->{hidden}) { + my %hidden_fields = map { $_->name => 1 } grep { $_->type eq 'hidden' } ($mech->forms)[0]->inputs; + foreach (@{$test->{hidden}}) { + is $hidden_fields{$_}, 1; + } + } if ( $test->{fields}->{category} eq 'Street lighting' ) { my $result = scraper { @@ -146,7 +218,7 @@ foreach my $test ( } ->scrape( $mech->response ); - is_deeply $result->{option}, [ qw/old modern/], 'displayed streetlight type select'; + is_deeply $result->{option}, [ "", qw/old modern/], 'displayed streetlight type select'; } $new_values = { @@ -172,4 +244,38 @@ foreach my $test ( }; } +subtest "Category extras omits description label when all fields are hidden" => sub { + FixMyStreet::override_config { + ALLOWED_COBRANDS => [ { fixmystreet => '.' } ], + MAPIT_URL => 'http://mapit.uk/', + }, sub { + my $json = $mech->get_ok_json('/report/new/category_extras?category=Pothole&latitude=55.952055&longitude=-3.189579'); + my $category_extra = $json->{category_extra}; + contains_string($category_extra, "usrn"); + contains_string($category_extra, "central_asset_id"); + lacks_string($category_extra, "USRN", "Lacks 'USRN' label"); + lacks_string($category_extra, "Asset ID", "Lacks 'Asset ID' label"); + lacks_string($category_extra, "resolve your problem quicker, by providing some extra detail", "Lacks description text"); + }; +}; + +subtest "Category extras includes description label for user" => sub { + FixMyStreet::override_config { + ALLOWED_COBRANDS => [ { fixmystreet => '.' } ], + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $contact4->push_extra_fields({ description => 'Size?', code => 'size', required => 'true', automated => '', variable => 'true', order => '3' }); + $contact4->update; + + my $json = $mech->get_ok_json('/report/new/category_extras?category=Pothole&latitude=55.952055&longitude=-3.189579'); + my $category_extra = $json->{category_extra}; + contains_string($category_extra, "usrn"); + contains_string($category_extra, "central_asset_id"); + lacks_string($category_extra, "USRN", "Lacks 'USRN' label"); + lacks_string($category_extra, "Asset ID", "Lacks 'Asset ID' label"); + contains_string($category_extra, "Size?"); + contains_string($category_extra, "resolve your problem quicker, by providing some extra detail", "Contains description text"); + }; +}; + done_testing(); diff --git a/t/app/controller/report_updates.t b/t/app/controller/report_updates.t index aefe77e47..aba7340b0 100644 --- a/t/app/controller/report_updates.t +++ b/t/app/controller/report_updates.t @@ -146,6 +146,42 @@ subtest "unconfirmed updates not displayed" => sub { }; subtest "several updates shown in correct order" => sub { + my @qs; + for my $fields ( { # One with an associated update below + problem_id => $report_id, + whensent => '2011-03-10 12:23:16', + whenanswered => '2011-03-10 12:23:16', + old_state => 'confirmed', + new_state => 'confirmed', + }, + { # One with no associated update + problem_id => $report_id, + whensent => '2011-03-11 12:23:16', + whenanswered => '2011-03-11 12:23:16', + old_state => 'confirmed', + new_state => 'confirmed', + }, + { # One with no associated update, different state (doesn't match problem state, never mind) + problem_id => $report_id, + whensent => '2011-03-12 12:23:16', + whenanswered => '2011-03-12 12:23:16', + old_state => 'investigating', + new_state => 'investigating', + }, + { # One for the fixed update + problem_id => $report_id, + whensent => '2011-03-15 08:12:36', + whenanswered => '2011-03-15 08:12:36', + old_state => 'confirmed', + new_state => 'fixed - user', + }, + ) { + my $q = FixMyStreet::App->model('DB::Questionnaire')->find_or_create( + $fields + ); + push @qs, $q; + } + for my $fields ( { problem_id => $report_id, user_id => $user2->id, @@ -180,16 +216,27 @@ subtest "several updates shown in correct order" => sub { my $comment = FixMyStreet::App->model('DB::Comment')->find_or_create( $fields ); + if ($fields->{text} eq 'Second update') { + $comment->set_extra_metadata(questionnaire_id => $qs[0]->id); + $comment->update; + } + if ($fields->{text} eq 'Third update') { + $comment->set_extra_metadata(questionnaire_id => $qs[3]->id); + $comment->update; + } } $mech->get_ok("/report/$report_id"); my $meta = $mech->extract_update_metas; - is scalar @$meta, 4, 'number of updates'; + is scalar @$meta, 6, 'number of updates'; is $meta->[0], 'Posted by Other User at 12:23, Thu 10 March 2011', 'first update'; - is $meta->[1], 'Posted by Main User at 12:23, Thu 10 March 2011', 'second update'; - is $meta->[2], 'State changed to: Fixed', 'third update, part 1'; - is $meta->[3], 'Posted anonymously at 08:12, Tue 15 March 2011', 'third update, part 2'; + is $meta->[1], 'Posted by Main User at 12:23, Thu 10 March 2011 Still open, via questionnaire', 'second update'; + is $meta->[2], 'Still open, via questionnaire, 12:23, Fri 11 March 2011', 'questionnaire'; + is $meta->[3], 'Still open, via questionnaire, 12:23, Sat 12 March 2011', 'questionnaire'; + is $meta->[4], 'State changed to: Fixed', 'third update, part 1'; + is $meta->[5], 'Posted anonymously at 08:12, Tue 15 March 2011', 'third update, part 2'; + $report->questionnaires->delete; }; for my $test ( diff --git a/t/app/controller/reports.t b/t/app/controller/reports.t index 76c920562..8cdfddd1b 100644 --- a/t/app/controller/reports.t +++ b/t/app/controller/reports.t @@ -95,6 +95,9 @@ $fife_problems[10]->update( { state => 'hidden', }); +# Run the cron script old-data (for the table no longer used by default) +FixMyStreet::Script::UpdateAllReports::generate(1); + # Run the cron script that makes the data for /reports so we don't get an error. my $data = FixMyStreet::Script::UpdateAllReports::generate_dashboard(); diff --git a/t/app/model/defecttype.t b/t/app/model/defecttype.t index 4f380db59..e924129e2 100644 --- a/t/app/model/defecttype.t +++ b/t/app/model/defecttype.t @@ -99,27 +99,6 @@ subtest 'by_categories returns defect types for an area with multiple bodies' => is scalar @$pavements, 3, 'Pavements have 3 defect types'; }; -subtest 'by_categories encodes HTML entities' => sub { - my $apostrophe_defect_type = FixMyStreet::App->model('DB::DefectType')->find_or_create( - { - body_id => $oxfordshire->id, - name => 'This defect type\'s name has an apostrophe', - description => 'This defect type is for all categories' - } - ); - $apostrophe_defect_type->set_extra_metadata('defect_code' => 'Here\'s an apostrophe'); - $apostrophe_defect_type->update(); - - my @contacts = FixMyStreet::DB->resultset('Contact')->not_deleted->search( { body_id => [ $oxfordshire->id ] } )->all; - my $defect_types = FixMyStreet::App->model('DB::DefectType')->by_categories($area_id, @contacts); - my $traffic_lights = decode_json($defect_types->{'Traffic lights'}); - my $defect_type = @$traffic_lights[2]; - is $defect_type->{name}, 'This defect type's name has an apostrophe'; - is $defect_type->{extra}->{defect_code}, 'Here's an apostrophe'; - -}; - - END { done_testing(); } diff --git a/t/app/model/problem.t b/t/app/model/problem.t index 27f6aed66..b9bbe4682 100644 --- a/t/app/model/problem.t +++ b/t/app/model/problem.t @@ -514,6 +514,7 @@ foreach my $test ( { subtest $test->{ desc } => sub { my $override = { ALLOWED_COBRANDS => [ 'fixmystreet' ], + MAPIT_URL => 'http://mapit.uk/', BASE_URL => 'http://www.fixmystreet.com', }; if ( $test->{cobrand} && $test->{cobrand} =~ /hart/ ) { @@ -587,9 +588,10 @@ foreach my $test ( { }; } -subtest 'check can set mutiple emails as a single contact' => sub { +subtest 'check can set multiple emails as a single contact' => sub { my $override = { ALLOWED_COBRANDS => [ 'fixmystreet' ], + MAPIT_URL => 'http://mapit.uk/', }; my $contact = { diff --git a/t/app/model/responsepriority.t b/t/app/model/responsepriority.t index 03c5bccae..4e624bf07 100644 --- a/t/app/model/responsepriority.t +++ b/t/app/model/responsepriority.t @@ -78,24 +78,6 @@ subtest 'by_categories returns all response priorities for an area with multiple is scalar @$traffic_lights, 2, 'Traffic lights have 2 defect types'; }; -subtest 'by_categories encodes HTML entities' => sub { - FixMyStreet::App->model('DB::ResponsePriority')->find_or_create( - { - body_id => $other_body->id, - name => 'This priority\'s name has an apostrophe', - description => 'This priority is for all categories' - } - ); - - my @contacts = FixMyStreet::DB->resultset('Contact')->not_deleted->search( { body_id => [ $oxfordshire->id ] } )->all; - my $priorities = FixMyStreet::App->model('DB::ResponsePriority')->by_categories($area_id, @contacts); - - my $traffic_lights = decode_json($priorities->{'Traffic lights'}); - use Data::Dumper; - my $priority = @$traffic_lights[2]; - is $priority->{name}, 'This priority's name has an apostrophe'; -}; - END { $mech->delete_body( $other_body ); $mech->delete_body( $oxfordshire ); diff --git a/t/app/model/responsetemplate.t b/t/app/model/responsetemplate.t new file mode 100644 index 000000000..fbabc1c12 --- /dev/null +++ b/t/app/model/responsetemplate.t @@ -0,0 +1,28 @@ +use FixMyStreet::TestMech; +use JSON::MaybeXS; + +my $mech = FixMyStreet::TestMech->new; +my $area_id = 2651; + +my $body = $mech->create_body_ok($area_id, 'Edinburgh Council'); +my $c1 = $mech->create_contact_ok(category => 'Potholes', body_id => $body->id, email => 'p'); +my $c2 = $mech->create_contact_ok(category => 'Graffiti', body_id => $body->id, email => 'g'); +my $t1 = FixMyStreet::DB->resultset('ResponseTemplate')->create({ body_id => $body->id, title => "Title 1", text => "Text 1" }); +my $t2 = FixMyStreet::DB->resultset('ResponseTemplate')->create({ body_id => $body->id, title => "Title 2", text => "Text 2", state => 'investigating' }); +my $t3 = FixMyStreet::DB->resultset('ResponseTemplate')->create({ body_id => $body->id, title => "Title 3", text => "Text 3" }); +$t1->add_to_contacts($c1); +$t2->add_to_contacts($c2); + +my @contacts = FixMyStreet::DB->resultset('Contact')->not_deleted->search( { body_id => [ $body->id ] } )->all; + +subtest 'by_categories returns allresponse templates grouped by category' => sub { + my $templates = FixMyStreet::App->model('DB::ResponseTemplate')->by_categories($area_id, @contacts); + my $potholes = decode_json($templates->{Potholes}); + my $graffiti = decode_json($templates->{Graffiti}); + + is scalar @$potholes, 2, 'Potholes have 2 templates'; + is scalar @$graffiti, 2, 'Graffiti has 2 templates'; + is $graffiti->[0]->{state}, 'investigating', 'Graffiti first template has right state'; +}; + +done_testing; diff --git a/t/app/model/session.t b/t/app/model/session.t new file mode 100644 index 000000000..f76533727 --- /dev/null +++ b/t/app/model/session.t @@ -0,0 +1,14 @@ +use FixMyStreet::TestMech; + +my $mech = FixMyStreet::TestMech->new; + +$mech->log_in_ok('test@example.com'); + +my $session = FixMyStreet::DB->resultset("Session")->first; + +my $id = $session->id; +$id =~ s/\s+$//; +is $id, "session:" . $session->id_code; +is $session->user->email, 'test@example.com'; + +done_testing; diff --git a/t/app/script/archive_old_enquiries.t b/t/app/script/archive_old_enquiries.t index e1adeec85..9774d3fc3 100644 --- a/t/app/script/archive_old_enquiries.t +++ b/t/app/script/archive_old_enquiries.t @@ -5,15 +5,18 @@ my $mech = FixMyStreet::TestMech->new(); $mech->clear_emails_ok; -my $opts = { - commit => 1, -}; - my $user = $mech->create_user_ok('test@example.com', name => 'Test User'); my $oxfordshire = $mech->create_body_ok(2237, 'Oxfordshire County Council'); my $west_oxon = $mech->create_body_ok(2420, 'West Oxfordshire District Council'); -$opts->{body} = $oxfordshire->id; +my $opts = { + commit => 1, + body => $oxfordshire->id, + cobrand => 'oxfordshire', + closure_cutoff => "2015-01-01 00:00:00", + email_cutoff => "2016-01-01 00:00:00", + user => $user->id, +}; subtest 'sets reports to the correct status' => sub { FixMyStreet::override_config { @@ -65,10 +68,48 @@ subtest 'sets reports to the correct status' => sub { is $report4->state, 'closed', 'Report 4 has been set to closed'; is $report5->state, 'closed', 'Report 5 has been set to closed'; + my $comment = $report1->comments->first; + is $comment->problem_state, 'closed'; + is $report->state, 'confirmed', 'Recent report has been left alone'; }; }; +subtest 'marks alerts as sent' => sub { + FixMyStreet::override_config { + ALLOWED_COBRANDS => [ 'oxfordshire' ], + }, sub { + my ($report) = $mech->create_problems_for_body(1, $oxfordshire->id, 'Test', { + areas => ',2237,', + lastupdate => '2015-12-01 07:00:00', + user_id => $user->id, + }); + my $alert = FixMyStreet::DB->resultset('Alert')->find_or_create( + { + user => $user, + parameter => $report->id, + alert_type => 'new_updates', + whensubscribed => '2015-12-01 07:00:00', + confirmed => 1, + cobrand => 'default', + } + ); + is $alert->alerts_sent->count, 0, 'Nothing has been sent for this alert'; + + FixMyStreet::Script::ArchiveOldEnquiries::archive($opts); + + $report->discard_changes; + + is $report->state, 'closed', 'Report has been set to closed'; + + is $alert->alerts_sent->count, 1, 'Alert marked as sent for this report'; + + my $alert_sent = $alert->alerts_sent->first; + my $comment = $report->comments->first; + is $alert_sent->parameter, $comment->id, 'AlertSent created for new comment'; + }; +}; + subtest 'sends emails to a user' => sub { FixMyStreet::override_config { ALLOWED_COBRANDS => [ 'oxfordshire' ], diff --git a/t/browser b/t/browser new file mode 120000 index 000000000..78da5bd3f --- /dev/null +++ b/t/browser @@ -0,0 +1 @@ +../.cypress/cypress/integration
\ No newline at end of file diff --git a/t/cobrand/bathnes.t b/t/cobrand/bathnes.t new file mode 100644 index 000000000..e0ad07c16 --- /dev/null +++ b/t/cobrand/bathnes.t @@ -0,0 +1,197 @@ +use FixMyStreet::TestMech; +my $mech = FixMyStreet::TestMech->new; + +my $body = $mech->create_body_ok(2551, 'Bath and North East Somerset Council'); +my @cats = ('Litter', 'Other', 'Potholes', 'Traffic lights'); +for my $contact ( @cats ) { + $mech->create_contact_ok(body_id => $body->id, category => $contact, email => "$contact\@example.org"); +} +my $superuser = $mech->create_user_ok('superuser@example.com', name => 'Super User', is_superuser => 1); +my $counciluser = $mech->create_user_ok('counciluser@example.com', name => 'Council User', from_body => $body); +my $normaluser = $mech->create_user_ok('normaluser@example.com', name => 'Normal User'); +$normaluser->update({ phone => "+447123456789" }); + +$mech->create_problems_for_body(1, $body->id, 'Title', { + areas => ",2651,", category => 'Potholes', cobrand => 'fixmystreet', + user => $normaluser, service => 'iOS', extra => { + _fields => [ + { + description => 'Width of pothole?', + name => "width", + value => "10cm" + }, + { + description => 'Depth of pothole?', + name => "depth", + value => "25cm" + }, + ] + } +}); +$mech->create_problems_for_body(1, $body->id, 'Title', { + areas => ",2651,", category => 'Traffic lights', cobrand => 'bathnes', + user => $counciluser, extra => { + contributed_as => 'body', + } +}); +$mech->create_problems_for_body(1, $body->id, 'Title', { + areas => ",2651,", category => 'Litter', cobrand => 'bathnes', + user => $normaluser, extra => { + contributed_as => 'another_user', + contributed_by => $counciluser->id, + } +}); +$mech->create_problems_for_body(1, $body->id, 'Title', { + areas => ",2651,", category => 'Other', cobrand => 'bathnes', + user => $counciluser, extra => { + contributed_as => 'anonymous_user', + } +}); + +FixMyStreet::override_config { + ALLOWED_COBRANDS => [ 'bathnes' ], + MAPIT_URL => 'http://mapit.uk/', +}, sub { + +subtest 'cobrand displays council name' => sub { + ok $mech->host("bathnes.fixmystreet.com"), "change host to bathnes"; + $mech->get_ok('/'); + $mech->content_like( qr/Bath and North East Somerset\b/ ); +}; + +subtest 'extra CSV columns are absent if permission not granted' => sub { + $mech->log_in_ok( $counciluser->email ); + + $mech->get_ok('/dashboard?export=1'); + + open my $data_handle, '<', \$mech->content; + my $csv = Text::CSV->new( { binary => 1 } ); + my @rows; + while ( my $row = $csv->getline( $data_handle ) ) { + push @rows, $row; + } + is scalar @rows, 5, '1 (header) + 4 (reports) = 5 lines'; + + is scalar @{$rows[0]}, 18, '18 columns present'; + + is_deeply $rows[0], + [ + 'Report ID', + 'Title', + 'Detail', + 'User Name', + 'Category', + 'Created', + 'Confirmed', + 'Acknowledged', + 'Fixed', + 'Closed', + 'Status', + 'Latitude', + 'Longitude', + 'Query', + 'Ward', + 'Easting', + 'Northing', + 'Report URL', + ], + 'Column headers look correct'; +}; + +subtest "Custom CSV fields permission can be granted" => sub { + $mech->log_in_ok( $superuser->email ); + + is $counciluser->user_body_permissions->count, 0, 'counciluser has no permissions'; + + $mech->get_ok("/admin/user_edit/" . $counciluser->id); + $mech->content_contains('Extra columns in CSV export'); + + $mech->submit_form_ok( { with_fields => { + name => $counciluser->name, + email => $counciluser->email, + body => $counciluser->from_body->id, + phone => '', + flagged => undef, + "permissions[export_extra_columns]" => 'on', + } } ); + + ok $counciluser->has_body_permission_to("export_extra_columns"), "counciluser has been granted CSV extra fields permission"; +}; + +subtest 'extra CSV columns are present if permission granted' => sub { + $mech->log_in_ok( $counciluser->email ); + + $mech->get_ok('/dashboard?export=1'); + + open my $data_handle, '<', \$mech->content; + my $csv = Text::CSV->new( { binary => 1 } ); + my @rows; + while ( my $row = $csv->getline( $data_handle ) ) { + push @rows, $row; + } + is scalar @rows, 5, '1 (header) + 4 (reports) = 5 lines'; + + is scalar @{$rows[0]}, 24, '24 columns present'; + + is_deeply $rows[0], + [ + 'Report ID', + 'Title', + 'Detail', + 'User Name', + 'Category', + 'Created', + 'Confirmed', + 'Acknowledged', + 'Fixed', + 'Closed', + 'Status', + 'Latitude', + 'Longitude', + 'Query', + 'Ward', + 'Easting', + 'Northing', + 'Report URL', + 'User Email', + 'User Phone', + 'Reported As', + 'Staff User', + 'Attribute Data', + 'Site Used', + ], + 'Column headers look correct'; + + is $rows[1]->[18], 'normaluser@example.com', 'User email is correct'; + is $rows[1]->[19], '+447123456789', 'User phone number is correct'; + is $rows[1]->[20], '', 'Reported As is empty if not made on behalf of another user/body'; + is $rows[1]->[21], '', 'Staff User is empty if not made on behalf of another user'; + is $rows[1]->[22], 'width = 10cm; depth = 25cm', 'Attribute Data is correct'; + is $rows[1]->[23], 'iOS', 'Site Used shows whether report made via app'; + + is $rows[2]->[18], 'counciluser@example.com', 'User email is correct'; + is $rows[2]->[19], '', 'User phone number is correct'; + is $rows[2]->[20], 'body', 'Reported As is correct if made on behalf of body'; + is $rows[2]->[21], '', 'Staff User is empty if not made on behalf of another user'; + is $rows[2]->[22], '', 'Attribute Data is correct'; + is $rows[2]->[23], 'bathnes', 'Site Used shows correct cobrand'; + + is $rows[3]->[18], 'normaluser@example.com', 'User email is correct'; + is $rows[3]->[19], '+447123456789', 'User phone number is correct'; + is $rows[3]->[20], 'another_user', 'Reported As is set if reported on behalf of another user'; + is $rows[3]->[21], 'counciluser@example.com', 'Staff User is correct if made on behalf of another user'; + is $rows[3]->[22], '', 'Attribute Data is correct'; + is $rows[3]->[23], 'bathnes', 'Site Used shows correct cobrand'; + + is $rows[4]->[18], 'counciluser@example.com', 'User email is correct'; + is $rows[4]->[19], '', 'User phone number is correct'; + is $rows[4]->[20], 'anonymous_user', 'Reported As is set if reported on behalf of another user'; + is $rows[4]->[21], '', 'Staff User is empty if not made on behalf of another user'; + is $rows[4]->[22], '', 'Attribute Data is correct'; + is $rows[4]->[23], 'bathnes', 'Site Used shows correct cobrand'; +}; + + +}; + +done_testing(); diff --git a/t/cobrand/bromley.t b/t/cobrand/bromley.t index 41e351dea..b3fb3564b 100644 --- a/t/cobrand/bromley.t +++ b/t/cobrand/bromley.t @@ -46,29 +46,68 @@ $mech->content_contains( 'State changed to: In progress' ); $mech->content_contains( 'marks it as unable to fix' ); $mech->content_contains( 'State changed to: No further action' ); -subtest 'testing special Open311 behaviour', sub { - $report->set_extra_fields(); - $report->update; - $body->update( { send_method => 'Open311', endpoint => 'http://bromley.endpoint.example.com', jurisdiction => 'FMS', api_key => 'test', send_comments => 1 } ); - my $test_data; - FixMyStreet::override_config { - STAGING_FLAGS => { send_reports => 1 }, - ALLOWED_COBRANDS => [ 'fixmystreet', 'bromley' ], - }, sub { - $test_data = FixMyStreet::Script::Reports::send(); - }; - $report->discard_changes; - ok $report->whensent, 'Report marked as sent'; - is $report->send_method_used, 'Open311', 'Report sent via Open311'; - is $report->external_id, 248, 'Report has right external ID'; +for my $test ( + { + desc => 'testing special Open311 behaviour', + updates => {}, + expected => { + 'attribute[easting]' => 529025, + 'attribute[northing]' => 179716, + 'attribute[service_request_id_ext]' => $report->id, + 'attribute[report_title]' => 'Test Test 1 for ' . $body->id, + 'jurisdiction_id' => 'FMS', + address_id => undef, + }, + }, + { + desc => 'testing Open311 behaviour with no map click or postcode', + updates => { + used_map => 0, + postcode => '' + }, + expected => { + 'attribute[easting]' => 529025, + 'attribute[northing]' => 179716, + 'attribute[service_request_id_ext]' => $report->id, + 'jurisdiction_id' => 'FMS', + 'address_id' => '#NOTPINPOINTED#', + }, + }, + { + desc => 'asset ID', + feature_id => '1234', + expected => { + 'attribute[service_request_id_ext]' => $report->id, + 'attribute[report_title]' => 'Test Test 1 for ' . $body->id . ' | ID: 1234', + }, + }, +) { + subtest $test->{desc}, sub { + $report->$_($test->{updates}->{$_}) for keys %{$test->{updates}}; + $report->$_(undef) for qw/ whensent send_method_used external_id /; + $report->set_extra_fields({ name => 'feature_id', value => $test->{feature_id} }) + if $test->{feature_id}; + $report->update; + $body->update( { send_method => 'Open311', endpoint => 'http://bromley.endpoint.example.com', jurisdiction => 'FMS', api_key => 'test', send_comments => 1 } ); + my $test_data; + FixMyStreet::override_config { + STAGING_FLAGS => { send_reports => 1 }, + ALLOWED_COBRANDS => [ 'fixmystreet', 'bromley' ], + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $test_data = FixMyStreet::Script::Reports::send(); + }; + $report->discard_changes; + ok $report->whensent, 'Report marked as sent'; + is $report->send_method_used, 'Open311', 'Report sent via Open311'; + is $report->external_id, 248, 'Report has right external ID'; - my $req = $test_data->{test_req_used}; - my $c = CGI::Simple->new($req->content); - is $c->param('attribute[easting]'), 529025, 'Request had easting'; - is $c->param('attribute[northing]'), 179716, 'Request had northing'; - is $c->param('attribute[service_request_id_ext]'), $report->id, 'Request had correct ID'; - is $c->param('jurisdiction_id'), 'FMS', 'Request had correct jurisdiction'; -}; + my $req = $test_data->{test_req_used}; + my $c = CGI::Simple->new($req->content); + is $c->param($_), $test->{expected}->{$_}, "Request had correct $_" + for keys %{$test->{expected}}; + }; +} for my $test ( { diff --git a/t/cobrand/closest.t b/t/cobrand/closest.t index 36fe78a01..6d28bb6f1 100644 --- a/t/cobrand/closest.t +++ b/t/cobrand/closest.t @@ -72,8 +72,18 @@ FixMyStreet::override_config { $near = $c->find_closest_address_for_rss($report); ok !$near, 'no closest address for RSS if not cached'; + + my $json = $mech->get_ok_json('/ajax/closest?lat=55&lon=-1'); + is_deeply $json, {"road"=> "Constitution Hill","full_address"=>"Constitution Hill, London, SW1A"}; +}; + +FixMyStreet::override_config { + ALLOWED_COBRANDS => 'fixmystreet', + MAPIT_URL => 'http://mapit.uk/', + BING_MAPS_API_KEY => 'test', +}, sub { + my $json = $mech->get_ok_json('/ajax/closest?lat=55.952055&lon=-3.189579'); + is_deeply $json, {"road"=> "Constitution Hill","full_address"=>"Constitution Hill, London, SW1A"}; }; -END { - done_testing(); -} +done_testing(); diff --git a/t/cobrand/fixmystreet.t b/t/cobrand/fixmystreet.t index 30d5765a2..57ab51198 100644 --- a/t/cobrand/fixmystreet.t +++ b/t/cobrand/fixmystreet.t @@ -18,6 +18,9 @@ FixMyStreet::override_config { $data = FixMyStreet::Script::UpdateAllReports::generate_dashboard($body); }; +FixMyStreet::App->log->disable('info'); +END { FixMyStreet::App->log->enable('info'); } + FixMyStreet::override_config { MAPIT_URL => 'http://mapit.uk/', TEST_DASHBOARD_DATA => $data, @@ -29,8 +32,7 @@ FixMyStreet::override_config { is $mech->uri->path, '/about/council-dashboard'; $mech->submit_form_ok({ with_fields => { username => 'someone@somewhere.example.org' }}); - $mech->content_contains('We will be in touch'); - # XXX Check email arrives + $mech->content_contains('did not recognise your email'); $mech->log_in_ok('someone@somewhere.example.org'); $mech->get_ok('/reports/Birmingham/summary'); diff --git a/t/cobrand/form_extras.t b/t/cobrand/form_extras.t index 84ded5bc1..df76ccbe1 100644 --- a/t/cobrand/form_extras.t +++ b/t/cobrand/form_extras.t @@ -2,7 +2,10 @@ package FixMyStreet::Cobrand::Tester; use parent 'FixMyStreet::Cobrand::FixMyStreet'; sub report_form_extras { - ( { name => 'address', required => 1 }, { name => 'passport', required => 0 } ) + ( + { name => 'address', required => 1 }, + { name => 'passport', required => 0, validator => sub { die "Invalid number\n" if $_[0] && $_[0] !~ /^P/; return $_[0] } }, + ) } # To allow a testing template override @@ -30,6 +33,7 @@ FixMyStreet::override_config { $mech->get_ok('/around'); $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB', } }, "submit location" ); $mech->follow_link_ok( { text_regex => qr/skip this step/i, }, "follow 'skip this step' link" ); + $mech->submit_form_ok( { button => 'submit_register', with_fields => { @@ -38,13 +42,24 @@ FixMyStreet::override_config { name => 'Joe Bloggs', may_show_name => '1', username => 'test-1@example.com', - passport => '123456', password_register => '', } }, - "submit details without address, with passport", + "submit details without address or passport", ); $mech->content_like(qr{<label for="form_address">Address</label>\s*<p class='form-error'>This information is required</p>}, 'Address is required'); + $mech->content_lacks("<p class='form-error'>Invalid number", 'Passport is optional'); + + $mech->submit_form_ok( { + button => 'submit_register', + with_fields => { + passport => '123456', + } + }, + "submit details with bad passport", + ); + $mech->content_like(qr{<label for="form_address">Address</label>\s*<p class='form-error'>This information is required</p>}, 'Address is required'); + $mech->content_like(qr{<p class='form-error'>Invalid number}, 'Passport format wrong'); $mech->content_contains('value="123456" name="passport"', 'Passport number reshown'); $mech->submit_form_ok( { @@ -55,11 +70,23 @@ FixMyStreet::override_config { }, "submit details, now with address", ); + $mech->content_lacks('This information is required', 'Address is present'); + $mech->content_like(qr{<p class='form-error'>Invalid number}, 'Passport format wrong'); + $mech->content_contains('value="123456" name="passport"', 'Passport number reshown'); + + $mech->submit_form_ok( { + button => 'submit_register', + with_fields => { + passport => 'P123456', + } + }, + "submit details with correct passport", + ); $mech->content_contains('Now check your email'); my $problem = FixMyStreet::DB->resultset('Problem')->search({}, { order_by => '-id' })->first; is $problem->get_extra_metadata('address'), 'My address', 'Address is stored'; - is $problem->get_extra_metadata('passport'), '123456', 'Passport number is stored'; + is $problem->get_extra_metadata('passport'), 'P123456', 'Passport number is stored'; }; END { diff --git a/t/cobrand/oxfordshire.t b/t/cobrand/oxfordshire.t index ee30e7e0b..19a82742a 100644 --- a/t/cobrand/oxfordshire.t +++ b/t/cobrand/oxfordshire.t @@ -81,8 +81,8 @@ subtest 'Exor file looks okay' => sub { $mech->log_in_ok( $superuser->email ); $mech->get_ok('/admin/exordefects'); $mech->submit_form_ok( { with_fields => { - start_date => '05/05/2017', - end_date => '05/05/2017', + start_date => '2017-05-05', + end_date => '2017-05-05', user_id => $inspector->id, } }, 'submit download'); $mech->content_contains("No inspections by that inspector in the selected date range"); @@ -120,8 +120,8 @@ subtest 'Exor file looks okay' => sub { $i++; } $mech->submit_form_ok( { with_fields => { - start_date => '05/05/2017', - end_date => '05/05/2017', + start_date => '2017-05-05', + end_date => '2017-05-05', user_id => $inspector->id, } }, 'submit download'); (my $rdi = $mech->content) =~ s/\r\n/\n/g; @@ -159,6 +159,7 @@ EOF subtest 'Reports are marked as inspected correctly' => sub { FixMyStreet::override_config { ALLOWED_COBRANDS => [ 'oxfordshire' ], + MAPIT_URL => 'http://mapit.uk/', }, sub { my $date = DateTime->new(year => 2017, month => 5, day => 5, hour => 12); @@ -185,57 +186,6 @@ subtest 'Reports are marked as inspected correctly' => sub { }; }; -subtest 'response times messages displayed' => sub { - my $oxfordshire = $mech->create_body_ok( - 2237, 'Oxfordshire County Council' - ); - my $contact = $mech->create_contact_ok( - body_id => $oxfordshire->id, - category => 'Pothole', - email => 'pothole@example.com', - ); - - FixMyStreet::override_config { - ALLOWED_COBRANDS => [ 'oxfordshire' ], - MAPIT_URL => 'http://mapit.uk/', - }, sub { - $mech->log_out_ok; - $mech->clear_emails_ok; - - $mech->get_ok('/around'); - $mech->submit_form_ok( { - with_fields => { pc => 'OX20 1SZ' } - }, - "submit_location" - ); - - $mech->follow_link_ok( { text_regex => qr/skip this step/i, }, - "follow 'skip this step' link" ); - - $mech->submit_form_ok( - { - with_fields => { - title => 'Test Report', - detail => 'Test report details.', - photo1 => '', - username => 'test-2@example.com', - name => 'Test User', - category => 'Pothole', - } - }, - "submit details" - ); - - $mech->text_contains('Problems in the Pothole category are generally responded'); - my $email = $mech->get_email; - ok $email, 'got and email'; - like $mech->get_text_body_from_email, qr/Problems in the Pothole category/, 'emails contains response time message'; - my $url = $mech->get_link_from_email($email); - $mech->get_ok($url); - $mech->text_contains('Problems in the Pothole category are generally responded') - }; -}; - END { done_testing(); } diff --git a/t/cobrand/rutland.t b/t/cobrand/rutland.t new file mode 100644 index 000000000..4d3c4befd --- /dev/null +++ b/t/cobrand/rutland.t @@ -0,0 +1,61 @@ +use CGI::Simple; +use FixMyStreet::TestMech; +use FixMyStreet::Script::Reports; +my $mech = FixMyStreet::TestMech->new; + +# Create test data +my $user = $mech->create_user_ok( 'rutland@example.com' ); +my $body = $mech->create_body_ok( 2482, 'Rutland County Council'); +my $contact = $mech->create_contact_ok( + body_id => $body->id, + category => 'Other', + email => 'LIGHT', +); +$contact->update; + +my @reports = $mech->create_problems_for_body( 1, $body->id, 'Test', { + cobrand => 'rutland', + user => $user, +}); +my $report = $reports[0]; + +for my $update ('in progress', 'unable to fix') { + FixMyStreet::DB->resultset('Comment')->find_or_create( { + problem_state => $update, + problem_id => $report->id, + user_id => $user->id, + name => 'User', + mark_fixed => 'f', + text => "This update marks it as $update", + state => 'confirmed', + confirmed => 'now()', + anonymous => 'f', + } ); +} + +subtest 'testing special Open311 behaviour', sub { + $report->set_extra_fields(); + $report->update; + $body->update( { send_method => 'Open311', endpoint => 'http://rutland.endpoint.example.com', jurisdiction => 'FMS', api_key => 'test', send_comments => 1 } ); + my $test_data; + FixMyStreet::override_config { + STAGING_FLAGS => { send_reports => 1 }, + ALLOWED_COBRANDS => [ 'fixmystreet', 'rutland' ], + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $test_data = FixMyStreet::Script::Reports::send(); + }; + $report->discard_changes; + ok $report->whensent, 'Report marked as sent'; + is $report->send_method_used, 'Open311', 'Report sent via Open311'; + is $report->external_id, 248, 'Report has right external ID'; + + my $req = $test_data->{test_req_used}; + my $c = CGI::Simple->new($req->content); + is $c->param('attribute[title]'), $report->title, 'Request had title'; + is $c->param('attribute[description]'), $report->detail, 'Request had description'; + is $c->param('attribute[external_id]'), $report->id, 'Request had correct ID'; + is $c->param('jurisdiction_id'), 'FMS', 'Request had correct jurisdiction'; +}; + +done_testing(); diff --git a/t/cobrand/zurich.t b/t/cobrand/zurich.t index 385f7f077..eccb0c8eb 100644 --- a/t/cobrand/zurich.t +++ b/t/cobrand/zurich.t @@ -23,6 +23,7 @@ my $mech = FixMyStreet::TestMech->new; use FixMyStreet; my $cobrand = FixMyStreet::Cobrand::Zurich->new(); +$cobrand->db_state_migration; my $sample_file = path(__FILE__)->parent->parent->child("app/controller/sample.jpg"); ok $sample_file->exists, "sample file $sample_file exists"; @@ -48,7 +49,7 @@ sub reset_report_state { $report->unset_extra_metadata('closed_overdue'); $report->unset_extra_metadata('closure_status'); $report->whensent(undef); - $report->state('unconfirmed'); + $report->state('submitted'); $report->created($created) if $created; $report->update; } @@ -109,7 +110,7 @@ subtest "set up superuser" => sub { }; my @reports = $mech->create_problems_for_body( 1, $division->id, 'Test', { - state => 'unconfirmed', + state => 'submitted', confirmed => undef, cobrand => 'zurich', areas => ',423017,', @@ -125,6 +126,89 @@ FixMyStreet::override_config { $mech->content_contains('Überprüfung ausstehend') or die $mech->content; +FixMyStreet::override_config { + ALLOWED_COBRANDS => [ 'zurich' ], + MAP_TYPE => 'Zurich,OSM', +}, sub { + my $json = $mech->get_ok_json( '/report/ajax/' . $report->id ); + is $json->{report}->{title}, "Überprüfung ausstehend", "correct title"; + is $json->{report}->{state}, "submitted", "correct state"; +}; + +subtest "Banners are displayed correctly" => sub { + FixMyStreet::override_config { + ALLOWED_COBRANDS => [ 'zurich' ], + MAP_TYPE => 'Zurich,OSM', + }, sub { + for my $test ( + { + description => 'new report', + state => 'submitted', + banner_id => 'closed', + banner_text => 'Erfasst' + }, + { + description => 'confirmed report', + state => 'confirmed', + banner_id => 'closed', + banner_text => 'Aufgenommen', + }, + { + description => 'fixed report', + state => 'fixed - council', + banner_id => 'fixed', + banner_text => 'Beantwortet', + }, + { + description => 'closed report', + state => 'external', + banner_id => 'closed', + banner_text => 'Extern', + }, + { + description => 'in progress report', + state => 'in progress', + banner_id => 'progress', + banner_text => 'In Bearbeitung', + }, + { + description => 'planned report', + state => 'feedback pending', + banner_id => 'progress', + banner_text => 'In Bearbeitung', + }, + { + description => 'jurisdiction unknown', + state => 'jurisdiction unknown', + banner_id => 'fixed', + banner_text => 'Zust\x{e4}ndigkeit unbekannt', + }, + ) { + subtest "banner for $test->{description}" => sub { + $report->state( $test->{state} ); + $report->update; + + $mech->get_ok("/report/" . $report->id); + is $mech->uri->path, "/report/" . $report->id, "at /report/" . $report->id; + my $banner = $mech->extract_problem_banner; + if ( $banner->{text} ) { + $banner->{text} =~ s/^ //g; + $banner->{text} =~ s/ $//g; + } + + is $banner->{id}, $test->{banner_id}, 'banner id'; + if ($test->{banner_text}) { + like_string( $banner->{text}, qr/$test->{banner_text}/i, 'banner text is ' . $test->{banner_text} ); + } else { + is $banner->{text}, $test->{banner_text}, 'banner text'; + } + + }; + } + $report->update({ state => 'submitted' }); + }; +}; + # Check logging in to deal with this report FixMyStreet::override_config { ALLOWED_COBRANDS => [ 'zurich' ], @@ -158,7 +242,7 @@ subtest "changing of categories" => sub { ); } - # full Categories dropdown is hidden for unconfirmed reports + # full Categories dropdown is hidden for submitted reports $report->update({ state => 'confirmed' }); # put report into known category @@ -269,17 +353,18 @@ subtest "report_edit" => sub { $mech->get_ok( '/admin/report_edit/' . $report->id ); $mech->submit_form_ok( { with_fields => { state => 'hidden' } } ); - $mech->get_ok( '/admin/report_edit/' . $report->id ); + $mech->get_ok( '/report/' . $report->id, 'still visible as response not published yet' ); $report->discard_changes; is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Still marked moderated_overdue' ); is ( $report->get_extra_metadata('closed_overdue'), undef, "Marking hidden doesn't set closed_overdue..." ); - is ( $report->state, 'planned', 'Marking hidden actually sets state to planned'); + is ( $report->state, 'feedback pending', 'Marking hidden actually sets state to feedback pending'); is ( $report->get_extra_metadata('closure_status'), 'hidden', 'Marking hidden sets closure_status to hidden'); is get_moderated_count(), 1, 'Check still counted moderated' or diag $report->get_column('extra'); # publishing actually sets hidden + $mech->get_ok( '/admin/report_edit/' . $report->id ); $mech->form_with_fields( 'status_update' ); $mech->submit_form_ok( { button => 'publish_response' } ); $mech->get_ok( '/admin/report_edit/' . $report->id ); @@ -289,6 +374,12 @@ subtest "report_edit" => sub { is ( $report->state, 'hidden', 'Closing as hidden sets state to hidden'); is ( $report->get_extra_metadata('closure_status'), undef, 'Closing as hidden unsets closure_status'); + $mech->submit_form_ok( { with_fields => { new_internal_note => 'Initial internal note.' } } ); + $report->discard_changes; + is ( $report->state, 'hidden', 'Another internal note does not reopen'); + + $mech->get( '/report/' . $report->id); + is $mech->res->code, 410; reset_report_state($report); is ( $report->get_extra_metadata('moderated_overdue'), undef, 'Sanity check' ); @@ -404,6 +495,12 @@ subtest 'SDM' => sub { $mech->submit_form_ok( { button => 'no_more_updates' } ); is $mech->uri->path, '/admin/summary', "redirected now finished with report."; + # Can still view the edit page but can't change anything + $mech->get_ok( '/admin/report_edit/' . $report->id ); + $mech->content_contains('<input disabled'); + $mech->submit_form_ok( { with_fields => { status_update => 'This is a disallowed update.' } } ); + $mech->content_lacks('This is a disallowed update'); + $mech->get_ok( '/report/' . $report->id ); $mech->content_contains('In Bearbeitung'); $mech->content_contains('Test Test'); @@ -416,7 +513,7 @@ subtest 'SDM' => sub { $mech->clear_emails_ok; $report->discard_changes; - is $report->state, 'planned', 'Report now in planned state'; + is $report->state, 'feedback pending', 'Report now in feedback pending state'; subtest 'send_back' => sub { FixMyStreet::override_config { @@ -441,8 +538,8 @@ subtest 'SDM' => sub { $mech->get_ok( '/admin/report_edit/' . $report->id ); $mech->submit_form_ok( { button => 'not_contactable', form_number => 2 } ); $report->discard_changes; - is $report->state, 'planned', 'Report sent back to Rueckmeldung ausstehend state'; - is $report->get_extra_metadata('closure_status'), 'partial', 'Report sent back to partial (not_contactable) state'; + is $report->state, 'feedback pending', 'Report sent back to Rueckmeldung ausstehend state'; + is $report->get_extra_metadata('closure_status'), 'not contactable', 'Report sent back to not_contactable state'; is $report->bodies_str, $division->id, 'Report sent back to division'; }; }; @@ -458,7 +555,7 @@ FixMyStreet::override_config { }; reset_report_state($report); -$report->update({ state => 'planned' }); +$report->update({ state => 'feedback pending' }); $mech->content_contains( 'report_edit/' . $report->id ); $mech->content_contains( DateTime->now->strftime("%d.%m.%Y") ); @@ -493,9 +590,9 @@ like $email->header('From'), qr/do-not-reply\@example.org/, 'from line looks cor like $email->body, qr/FINAL UPDATE/, 'body looks correct'; $mech->clear_emails_ok; -# Assign planned (via confirmed), don't confirm email +# Assign feedback pending (via confirmed), don't confirm email @reports = $mech->create_problems_for_body( 1, $division->id, 'Second', { - state => 'unconfirmed', + state => 'submitted', confirmed => undef, cobrand => 'zurich', areas => ',423017,', @@ -509,7 +606,7 @@ FixMyStreet::override_config { $mech->get_ok( '/admin/report_edit/' . $report->id ); $mech->submit_form_ok( { with_fields => { state => 'confirmed' } } ); $mech->get_ok( '/admin/report_edit/' . $report->id ); - $mech->submit_form_ok( { with_fields => { state => 'planned' } } ); + $mech->submit_form_ok( { with_fields => { state => 'feedback pending' } } ); $mech->get_ok( '/report/' . $report->id ); }; $mech->content_contains('In Bearbeitung'); @@ -536,7 +633,7 @@ $mech->email_count_is(0); # Report assigned to third party @reports = $mech->create_problems_for_body( 1, $division->id, 'Third', { - state => 'unconfirmed', + state => 'submitted', confirmed => undef, cobrand => 'zurich', areas => ',423017,', @@ -551,8 +648,8 @@ subtest "external report triggers email" => sub { }, sub { # required to see body_external field - $report->state('planned'); - $report->set_extra_metadata('closure_status' => 'closed'); + $report->state('feedback pending'); + $report->set_extra_metadata('closure_status' => 'external'); # Set the public_response manually here because the default one will have line breaks that get escaped as HTML, causing the comparison to fail. $report->set_extra_metadata('public_response' => 'Freundliche Gruesse Ihre Stadt Zuerich'); $report->update; @@ -568,7 +665,7 @@ subtest "external report triggers email" => sub { $report->discard_changes; $mech->get_ok( '/report/' . $report->id ); }; - is ($report->state, 'closed', 'Report was closed correctly'); + is ($report->state, 'external', 'Report was closed correctly'); $mech->content_contains('Extern') or die $mech->content; $mech->content_contains('Third Test'); @@ -589,8 +686,8 @@ subtest "external report triggers email" => sub { }, sub { $mech->get_ok( '/admin' ); # required to see body_external field - $report->state('planned'); - $report->set_extra_metadata('closure_status' => 'closed'); + $report->state('feedback pending'); + $report->set_extra_metadata('closure_status' => 'external'); $report->set_extra_metadata('public_response' => 'Freundliche Gruesse Ihre Stadt Zuerich'); $report->update; @@ -625,10 +722,10 @@ subtest "external report triggers email" => sub { }, sub { # set as wish $report->discard_changes; - $report->state('planned'); - $report->set_extra_metadata('closure_status' => 'investigating'); + $report->state('feedback pending'); + $report->set_extra_metadata('closure_status' => 'wish'); $report->update; - is ($report->state, 'planned', 'Sanity check') or die; + is ($report->state, 'feedback pending', 'Sanity check') or die; $mech->get_ok( '/admin/report_edit/' . $report->id ); @@ -639,6 +736,9 @@ subtest "external report triggers email" => sub { body_external => $external_body->id, external_message => $EXTERNAL_MESSAGE, } }); + # Wishes publicly viewable + $mech->get_ok( '/report/' . $report->id ); + $mech->content_contains('Freundliche Gruesse Ihre Stadt Zuerich'); }; send_reports_for_zurich(); $email = $mech->get_email; @@ -658,12 +758,12 @@ subtest "external report triggers email" => sub { }, sub { # set as extern reset_report_state($report); - $report->state('planned'); - $report->set_extra_metadata('closure_status' => 'closed'); + $report->state('feedback pending'); + $report->set_extra_metadata('closure_status' => 'external'); $report->set_extra_metadata('email_confirmed' => 1); $report->unset_extra_metadata('public_response'); $report->update; - is ($report->state, 'planned', 'Sanity check') or die; + is ($report->state, 'feedback pending', 'Sanity check') or die; $mech->get_ok( '/admin/report_edit/' . $report->id ); @@ -865,7 +965,7 @@ subtest "test admin_log" => sub { # XXX: following is dependent on all of test up till now, rewrite to explicitly # test which things need to be logged! is scalar @entries, 4, 'State changes logged'; - is $entries[-1]->action, 'state change to closed', 'State change logged as expected'; + is $entries[-1]->action, 'state change to external', 'State change logged as expected'; }; subtest 'email images to external partners' => sub { @@ -885,7 +985,7 @@ subtest 'email images to external partners' => sub { # The below email comparison must not have an external message. $report->unset_extra_metadata('external_message'); $report->update({ - state => 'closed', + state => 'external', photo => $fileid, external_body => $external_body->id, }); @@ -937,9 +1037,9 @@ subtest 'Status update shown as appropriate' => sub { }, sub { # ALL closed states must hide the public_response edit, and public ones # must show the answer in blue. - for (['planned', 1, 0, 0], + for (['feedback pending', 1, 0, 0], ['fixed - council', 0, 1, 0], - ['closed', 0, 1, 0], + ['external', 0, 1, 0], ['hidden', 0, 0, 1]) { my ($state, $update, $public, $user_response) = @$_; diff --git a/t/map/tests.t b/t/map/tests.t index 1123133e4..e6749b813 100644 --- a/t/map/tests.t +++ b/t/map/tests.t @@ -3,9 +3,11 @@ use Test::More; my $requires = { 'Angus' => 'angus/js.js', + 'BathNES' => 'bathnes/js.js', 'Bing' => 'map-bing-ol.js', 'Bristol' => 'bristol/js.js', 'Bromley' => 'bromley/map.js', + 'Buckinghamshire' => 'buckinghamshire/js.js', 'FMS' => 'map-fms.js', 'Google' => 'map-google.js', 'GoogleOL' => 'map-google-ol.js', diff --git a/t/open311.t b/t/open311.t index b41d42b55..4dc1b2959 100644 --- a/t/open311.t +++ b/t/open311.t @@ -133,8 +133,38 @@ for my $test ( } ], params => [ - [ 'attribute[title]', 'A title', 'extra paramater used correctly' ] - ] + [ 'attribute[title]', 'A title', 'extra parameter used correctly' ] + ], + debug_contains => 'attribute\[title\]: A title', + }, + { + desc => 'undef extra values handled', + extra => [ + { + name => 'title', + value => undef, + } + ], + params => [ + [ 'attribute[title]', '', 'undef extra parameter used correctly' ] + ], + # multi line warnings are not handled well so just match the + # first line + warning => qr/POST requests.xml/, + debug_contains => 'attribute\[title\]: $', + }, + { + desc => '0 extra values handled', + extra => [ + { + name => 'title', + value => 0, + } + ], + params => [ + [ 'attribute[title]', '0', '0 extra parameter used correctly' ] + ], + debug_contains => 'attribute\[title\]: 0', }, { desc => 'first and last names in extra used correctly', @@ -178,11 +208,24 @@ for my $test ( 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 $results; + if ( $test->{warning} ) { + warnings_exist { + $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>' + ); + } [ $test->{warning} ], 'warning generated by service request call'; + } else { + $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 $c = CGI::Simple->new( $results->{req}->content ); + if ( $test->{debug_contains} ) { + like $results->{o}->debug_details, qr/$test->{debug_contains}/m, 'extra handled correctly in debug'; + } + for my $param ( @{ $test->{params} } ) { is $c->param( $param->[0] ), $param->[1], $param->[2]; } @@ -196,6 +239,12 @@ for my $test ( first_name => 'Nom', last_name => 'de Report', }, + { + desc => 'Check single word name handled correctly', + name => 'Nom', + first_name => 'Nom', + last_name => '', + } ) { subtest $test->{desc} => sub { $problem->extra( undef ); @@ -482,7 +531,7 @@ for my $test ( desc => 'update name taken from extra if available', comment_name => 'First Last', user_name => 'Personal Family', - extra => { first_name => 'Forename', last_name => 'Surname' }, + extra => { first_name => 'Forename', last_name => 'Surname', title => 'Ms' }, first_name => 'Forename', last_name => 'Surname' }, @@ -756,5 +805,5 @@ sub _make_req { my $req = $o->test_req_used; - return { res => $res, req => $req }; + return { res => $res, req => $req, o => $o }; } 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; diff --git a/t/script/inactive.t b/t/script/inactive.t new file mode 100644 index 000000000..4d78b385f --- /dev/null +++ b/t/script/inactive.t @@ -0,0 +1,71 @@ +use FixMyStreet::TestMech; + +use_ok 'FixMyStreet::Script::Inactive'; + +my $in = FixMyStreet::Script::Inactive->new( anonymize => 6, email => 3 ); +my $mech = FixMyStreet::TestMech->new; + +my $user = FixMyStreet::DB->resultset("User")->find_or_create({ email => 'test@example.com' }); +my $t = DateTime->new(year => 2016, month => 1, day => 1, hour => 12); +$user->last_active($t); +$user->update; + +my $user_inactive = FixMyStreet::DB->resultset("User")->find_or_create({ email => 'inactive@example.com' }); +$t = DateTime->now->subtract(months => 4); +$user_inactive->last_active($t); +$user_inactive->update; + +my @problems; +for (my $m = 1; $m <= 12; $m++) { + my $t = DateTime->new(year => 2017, month => $m, day => 1, hour => 12); + push @problems, $mech->create_problems_for_body(1, 2237, 'Title', { + dt => $t, + lastupdate => "$t", + state => $m % 2 ? 'fixed - user' : 'confirmed', + }); +} + +$mech->create_comment_for_problem($problems[0], $user, 'Name', 'Update', 0, 'confirmed', $problems[0]->state); +FixMyStreet::DB->resultset("Alert")->create({ alert_type => 'new_updates', parameter => $problems[2]->id, user => $user }); + +subtest 'Anonymization of inactive fixed/closed reports' => sub { + $in->reports; + + my $count = FixMyStreet::DB->resultset("Problem")->search({ user_id => $user->id })->count; + is $count, 6, 'Six non-anonymised'; + + my $comment = FixMyStreet::DB->resultset("Comment")->first; + my $alert = FixMyStreet::DB->resultset("Alert")->first; + is $comment->anonymous, 1, 'Comment anonymized'; + is $comment->user->email, 'removed-automatically@example.org', 'Comment user anonymized'; + is $alert->user->email, 'removed-automatically@example.org', 'Alert anonymized'; + isnt $alert->whendisabled, undef, 'Alert disabled'; + + $mech->create_comment_for_problem($problems[0], $user, 'Name 2', 'Update', 0, 'confirmed', $problems[0]->state); + $comment = FixMyStreet::DB->resultset("Comment")->search({ name => 'Name 2' })->first; + + $in->reports; + $comment->discard_changes; + is $comment->anonymous, 1, 'Comment anonymized'; + is $comment->user->email, 'removed-automatically@example.org', 'Comment user anonymized'; +}; + +subtest 'Closing updates on inactive fixed/closed reports' => sub { + my $in = FixMyStreet::Script::Inactive->new( close => 1 ); + $in->reports; + $problems[2]->discard_changes; + is $problems[2]->get_extra_metadata('closed_updates'), 1, 'Closed to updates'; + # TODO Visit page, check closed for updates +}; + +subtest 'Anonymization of inactive users' => sub { + $in->users; + + my $email = $mech->get_email; + like $email->as_string, qr/inactive\@example.com/, 'Inactive email sent'; + + $user->discard_changes; + is $user->email, 'removed-' . $user->id . '@example.org', 'User has been anonymized'; +}; + +done_testing; diff --git a/t/sendreport/open311.t b/t/sendreport/open311.t index 1eb5535aa..26764dc19 100644 --- a/t/sendreport/open311.t +++ b/t/sendreport/open311.t @@ -1,4 +1,16 @@ +package FixMyStreet::Cobrand::Tester; + +use parent 'FixMyStreet::Cobrand::FixMyStreet'; + +sub open311_config { + my ($self, $row, $h, $params) = @_; + $params->{multi_photos} = 1; +} + +package main; + use CGI::Simple; +use Path::Tiny; use FixMyStreet::Script::Reports; use FixMyStreet::TestMech; my $mech = FixMyStreet::TestMech->new; @@ -25,6 +37,7 @@ subtest 'testing Open311 behaviour', sub { FixMyStreet::override_config { STAGING_FLAGS => { send_reports => 1 }, ALLOWED_COBRANDS => [ 'fixmystreet' ], + MAPIT_URL => 'http://mapit.uk/', }, sub { $test_data = FixMyStreet::Script::Reports::send(); }; @@ -41,4 +54,75 @@ subtest 'testing Open311 behaviour', sub { is $c->param('jurisdiction_id'), 'FMS', 'Request had correct jurisdiction'; }; +my ($photo_report) = $mech->create_problems_for_body( 1, $body->id, 'Test', { + cobrand => 'fixmystreet', + category => 'Potholes', + user => $user, +}); +my $sample_file = path(__FILE__)->parent->parent->child("app/controller/sample.jpg"); +my $UPLOAD_DIR = File::Temp->newdir(); +my @files = map { $_ x 40 . ".jpeg" } (1..3); +$sample_file->copy(path($UPLOAD_DIR, $_)) for @files; +$photo_report->photo(join(',', @files)); +$photo_report->update; + +subtest 'test report with multiple photos only sends one', sub { + $body->update( { send_method => 'Open311', endpoint => 'http://endpoint.example.com', jurisdiction => 'FMS', api_key => 'test' } ); + my $test_data; + + FixMyStreet::override_config { + STAGING_FLAGS => { send_reports => 1 }, + ALLOWED_COBRANDS => [ 'fixmystreet' ], + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $test_data = FixMyStreet::Script::Reports::send(); + }; + $photo_report->discard_changes; + ok $photo_report->whensent, 'Report marked as sent'; + is $photo_report->send_method_used, 'Open311', 'Report sent via Open311'; + is $photo_report->external_id, 248, 'Report has right external ID'; + + my $req = $test_data->{test_req_used}; + my $c = CGI::Simple->new($req->content); + is $c->param('attribute[easting]'), 529025, 'Request had easting'; + is $c->param('attribute[northing]'), 179716, 'Request had northing'; + is $c->param('attribute[fixmystreet_id]'), $photo_report->id, 'Request had correct ID'; + is $c->param('jurisdiction_id'), 'FMS', 'Request had correct jurisdiction'; + my @media = $c->param('media_url'); + is_deeply \@media, [ + 'http://www.example.org/photo/' . $photo_report->id .'.0.full.jpeg?11111111' + ], 'One photo in media_url'; +}; + +$photo_report->whensent(undef); +$photo_report->cobrand('tester'); +$photo_report->send_method_used(''); +$photo_report->update(); + +subtest 'test sending multiple photos', sub { + $body->update( { send_method => 'Open311', endpoint => 'http://endpoint.example.com', jurisdiction => 'FMS', api_key => 'test' } ); + my $test_data; + + FixMyStreet::override_config { + STAGING_FLAGS => { send_reports => 1 }, + ALLOWED_COBRANDS => [ 'tester' ], + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $test_data = FixMyStreet::Script::Reports::send(); + }; + $photo_report->discard_changes; + ok $photo_report->whensent, 'Report marked as sent'; + is $photo_report->send_method_used, 'Open311', 'Report sent via Open311'; + is $photo_report->external_id, 248, 'Report has right external ID'; + + my $req = $test_data->{test_req_used}; + my $c = CGI::Simple->new($req->content); + my @media = $c->param('media_url'); + is_deeply \@media, [ + 'http://www.example.org/photo/' . $photo_report->id .'.0.full.jpeg?11111111', + 'http://www.example.org/photo/' . $photo_report->id .'.1.full.jpeg?22222222', + 'http://www.example.org/photo/' . $photo_report->id .'.2.full.jpeg?33333333' + ], 'Multiple photos in media_url'; +}; + done_testing(); |