aboutsummaryrefslogtreecommitdiffstats
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/Mock/Bing.pm47
-rw-r--r--t/Mock/MapIt.pm5
-rw-r--r--t/Mock/Nominatim.pm5
-rw-r--r--t/Mock/OpenIDConnect.pm48
-rw-r--r--t/Mock/Tilma.pm2
-rw-r--r--t/app/controller/admin/bodies.t164
-rw-r--r--t/app/controller/admin/report_edit.t59
-rw-r--r--t/app/controller/admin/update_edit.t4
-rw-r--r--t/app/controller/admin/users.t61
-rw-r--r--t/app/controller/alert.t22
-rw-r--r--t/app/controller/alert_new.t47
-rw-r--r--t/app/controller/around.t174
-rw-r--r--t/app/controller/auth.t28
-rw-r--r--t/app/controller/auth_profile.t12
-rw-r--r--t/app/controller/auth_social.t74
-rw-r--r--t/app/controller/contact.t2
-rw-r--r--t/app/controller/contact_enquiry.t16
-rw-r--r--t/app/controller/dashboard.t56
-rw-r--r--t/app/controller/moderate.t3
-rw-r--r--t/app/controller/my.t23
-rw-r--r--t/app/controller/offline.t1
-rw-r--r--t/app/controller/questionnaire.t9
-rw-r--r--t/app/controller/report_display.t2
-rw-r--r--t/app/controller/report_import.t2
-rw-r--r--t/app/controller/report_inspect.t178
-rw-r--r--t/app/controller/report_new.t16
-rw-r--r--t/app/controller/report_new_anon.t75
-rw-r--r--t/app/controller/report_new_errors.t76
-rw-r--r--t/app/controller/report_new_open311.t34
-rw-r--r--t/app/controller/report_new_text.t67
-rw-r--r--t/app/controller/report_new_unresponsive.t2
-rw-r--r--t/app/controller/report_new_update.t4
-rw-r--r--t/app/controller/report_update_text.t63
-rw-r--r--t/app/controller/report_updates.t209
-rw-r--r--t/app/controller/waste.t211
-rw-r--r--t/app/model/comment.t25
-rw-r--r--t/app/model/problem.t65
-rw-r--r--t/app/model/responsepriority.t49
-rw-r--r--t/app/model/responsetemplate.t8
-rw-r--r--t/app/sendreport/email.t16
-rw-r--r--t/app/sendreport/email/highways.t10
-rw-r--r--t/cobrand/bexley.t41
-rw-r--r--t/cobrand/bristol.t8
-rw-r--r--t/cobrand/bromley.t313
-rw-r--r--t/cobrand/bucks.t40
-rw-r--r--t/cobrand/form_extras.t2
-rw-r--r--t/cobrand/get_body_sender.t18
-rw-r--r--t/cobrand/hackney.t325
-rw-r--r--t/cobrand/highwaysengland.t18
-rw-r--r--t/cobrand/hounslow.t9
-rw-r--r--t/cobrand/isleofwight.t15
-rw-r--r--t/cobrand/northamptonshire.t182
-rw-r--r--t/cobrand/oxfordshire.t107
-rw-r--r--t/cobrand/peterborough.t81
-rw-r--r--t/cobrand/tfl.t40
-rw-r--r--t/cobrand/zurich.t73
-rw-r--r--t/email.t6
-rw-r--r--t/geocode/bing.t30
-rw-r--r--t/map/bing.t12
-rw-r--r--t/map/fms.t55
-rw-r--r--t/map/google.t2
-rw-r--r--t/map/tests.t1
-rw-r--r--t/open311.t1
-rw-r--r--t/open311/getservicerequests.t40
-rw-r--r--t/open311/getupdates.t31
-rw-r--r--t/open311/populate-service-list.t64
-rw-r--r--t/open311/post-service-request-updates.t17
-rw-r--r--t/roles/translatable.t5
-rw-r--r--t/script/tfl/autoclose.t216
-rw-r--r--t/workingdays.t21
70 files changed, 3279 insertions, 468 deletions
diff --git a/t/Mock/Bing.pm b/t/Mock/Bing.pm
index 3dfb8fbe0..cc4dab845 100644
--- a/t/Mock/Bing.pm
+++ b/t/Mock/Bing.pm
@@ -14,6 +14,53 @@ has json => (
sub dispatch_request {
my $self = shift;
+ sub (GET + /REST/v1/Locations + ?*) {
+ my ($self, $query) = @_;
+ my $results = [ {
+ point => { coordinates => [ 51, -1 ] },
+ name => 'Constitution Hill, London, SW1A',
+ confidence => 'High',
+ address => {
+ addressLine => 'Constitution Hill',
+ locality => 'London',
+ countryRegion => 'United Kingdom',
+ }
+ } ];
+ if ($query->{q} =~ /two results/) {
+ push @$results, {
+ point => { coordinates => [ 51, -1 ] },
+ name => 'Constitution Hill again, United Kingdom',
+ confidence => 'High',
+ address => {
+ addressLine => 'Constitution Hill again',
+ locality => 'London',
+ countryRegion => 'United Kingdom',
+ }
+ };
+ }
+ if ($query->{q} =~ /low/) {
+ push @$results, {
+ point => { coordinates => [ 52, -2 ] },
+ name => 'Constitution Hill elsewhere, United Kingdom',
+ confidence => 'Low',
+ address => {
+ addressLine => 'Constitution Hill elsewhere',
+ locality => 'London',
+ countryRegion => 'United Kingdom',
+ }
+ };
+ }
+ if ($query->{q} =~ /onlylow/) {
+ @$results = map { $_->{confidence} = 'Low'; $_ } @$results;
+ }
+ my $data = {
+ statusCode => 200,
+ resourceSets => [ { resources => $results } ],
+ };
+ my $json = $self->json->encode($data);
+ return [ 200, [ 'Content-Type' => 'application/json' ], [ $json ] ];
+ },
+
sub (GET + /REST/v1/Locations/* + ?*) {
my ($self, $location, $query) = @_;
my $data = {
diff --git a/t/Mock/MapIt.pm b/t/Mock/MapIt.pm
index d49294a6a..74e360974 100644
--- a/t/Mock/MapIt.pm
+++ b/t/Mock/MapIt.pm
@@ -44,13 +44,14 @@ my @PLACES = (
[ 'NN1 2NS', 52.238301, -0.889992, 2234, 'Northamptonshire County Council', 'CTY', 2397, 'Northampton Borough Council', 'DIS' ],
[ '?', 52.238827, -0.894970, 2234, 'Northamptonshire County Council', 'CTY', 2397, 'Northampton Borough Council', 'DIS' ],
[ '?', 52.23025, -1.015826, 2234, 'Northamptonshire County Council', 'CTY', 2397, 'Northampton Borough Council', 'DIS' ],
+ [ 'E8 1DY', 51.552267, -0.063316, 2508, 'Hackney Borough Council', 'LBO' ],
+ [ 'E8 2DY', 51.552287, -0.063326, 2508, 'Hackney Council', 'LBO' ],
[ 'TW7 5JN', 51.482286, -0.328163, 2483, 'Hounslow Borough Council', 'LBO' ],
[ '?', 51.48111, -0.327219, 2483, 'Hounslow Borough Council', 'LBO' ],
[ '?', 51.482045, -0.327219, 2483, 'Hounslow Borough Council', 'LBO' ],
[ '?', 51.345714, -0.227959, 2457, 'Epsom and Ewell Borough Council', 'DIS' ],
[ 'CW11 1HZ', 53.145324, -2.370437, 21069, 'Cheshire East Council', 'UTA', 135301, 'Sandbach Town', 'UTW' ],
[ '?', 50.78301, -0.646929 ],
- [ 'TA1 1QP', 51.023569, -3.099055, 2239, 'Somerset County Council', 'CTY', 2429, 'Taunton Deane Borough Council', 'DIS' ],
[ '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' ],
[ 'PO30 5XJ', 50.71086, -1.29573, 2636, 'Isle of Wight Council', 'UTA' ],
@@ -121,6 +122,8 @@ sub dispatch_request {
$self->output({2326 => {parent_area => undef, id => 2326, name => "Cheltenham Borough Council", type => "DIS"}});
} elsif ($areas eq 'UTA') {
$self->output({2650 => {parent_area => undef, id => 2650, name => "Aberdeen Council", type => "UTA"}});
+ } elsif ($areas eq 'DIS,LBO,MTD,UTA,CTY,COI,LGD') {
+ $self->output({2508 => {parent_area => undef, id => 2508, name => "Hackney Council", type => "LBO"}});
} elsif ($areas eq 'GRE') {
$self->output({2493 => {parent_area => undef, id => 2493, name => "Greenwich Borough Council", type => "LBO"}});
} elsif ($areas eq 'LBO') {
diff --git a/t/Mock/Nominatim.pm b/t/Mock/Nominatim.pm
index 806ebbfd3..d108256f5 100644
--- a/t/Mock/Nominatim.pm
+++ b/t/Mock/Nominatim.pm
@@ -1,6 +1,7 @@
package t::Mock::Nominatim;
use JSON::MaybeXS;
+use LWP::Protocol::PSGI;
use Web::Simple;
has json => (
@@ -35,6 +36,10 @@ sub query {
{"osm_type"=>"way","osm_id"=>"4684282","lat"=>"55.9504009","lon"=>"-3.1858425","display_name"=>"High Street, Old Town, City of Ed\x{ed}nburgh, Scotland, EH1 1SP, United Kingdom","class"=>"highway","type"=>"tertiary","importance"=>0.55892577838734},
{"osm_type"=>"node","osm_id"=>"27424410","lat"=>"55.8596449","lon"=>"-4.240377","display_name"=>"High Street, Collegelands, Merchant City, Glasgow, Glasgow City, Scotland, G, United Kingdom","class"=>"railway","type"=>"station","importance"=>0.53074299592768}
];
+ } elsif ($q eq 'edinburgh') {
+ return [
+ {"osm_type"=>"node","osm_id"=>"17898859","lat"=>"55.9533456","lon"=>"-3.1883749","display_name"=>"Edinburgh","class"=>"place","type"=>"place:city","importance"=>0.676704}
+ ];
}
return [];
}
diff --git a/t/Mock/OpenIDConnect.pm b/t/Mock/OpenIDConnect.pm
index ba7d03b1d..61a67f329 100644
--- a/t/Mock/OpenIDConnect.pm
+++ b/t/Mock/OpenIDConnect.pm
@@ -27,6 +27,11 @@ sub dispatch_request {
return [ 200, [ 'Content-Type' => 'text/html' ], [ 'OpenID Connect login page' ] ];
},
+ sub (GET + /oauth2/v2.0/authorize_google + ?*) {
+ my ($self) = @_;
+ return [ 200, [ 'Content-Type' => 'text/html' ], [ 'OpenID Connect login page' ] ];
+ },
+
sub (GET + /oauth2/v2.0/logout + ?*) {
my ($self) = @_;
return [ 200, [ 'Content-Type' => 'text/html' ], [ 'OpenID Connect logout page' ] ];
@@ -72,6 +77,49 @@ sub dispatch_request {
my $json = $self->json->encode($data);
return [ 200, [ 'Content-Type' => 'application/json' ], [ $json ] ];
},
+
+ sub (POST + /oauth2/v2.0/token_google + ?*) {
+ my ($self) = @_;
+ my $header = {
+ typ => "JWT",
+ alg => "RS256",
+ kid => "XXXfakeKEY1234",
+ };
+ my $now = DateTime->now->epoch;
+ my $payload = {
+ exp => $now + 3600,
+ nbf => $now,
+ locale => 'en-GB',
+ ver => "1.0",
+ iss => 'https://accounts.google.com',
+ sub => "my_google_user_id",
+ aud => "example_client_id",
+ iat => $now,
+ auth_time => $now,
+ given_name => "Andy",
+ family_name => "Dwyer",
+ name => "Andy Dwyer",
+ nonce => 'MyAwesomeRandomValue',
+ hd => 'example.org',
+ };
+ $payload->{email} = 'pkg-tappcontrollerauth_socialt-oidc_google@example.org' if $self->returns_email;
+ $payload->{email_verified} = JSON->true if $self->returns_email;
+ my $signature = "dummy";
+ my $id_token = join(".", (
+ encode_base64($self->json->encode($header), ''),
+ encode_base64($self->json->encode($payload), ''),
+ encode_base64($signature, '')
+ ));
+ my $data = {
+ id_token => $id_token,
+ token_type => "Bearer",
+ not_before => $now,
+ id_token_expires_in => 3600,
+ profile_info => encode_base64($self->json->encode({}), ''),
+ };
+ my $json = $self->json->encode($data);
+ return [ 200, [ 'Content-Type' => 'application/json' ], [ $json ] ];
+ },
}
__PACKAGE__->run_if_script;
diff --git a/t/Mock/Tilma.pm b/t/Mock/Tilma.pm
index 7542b1f5e..b7ef2be2f 100644
--- a/t/Mock/Tilma.pm
+++ b/t/Mock/Tilma.pm
@@ -28,7 +28,7 @@ sub dispatch_request {
sub (GET + /mapserver/tfl + ?*) {
my ($self, $args) = @_;
my $features = [];
- if ($args->{Filter} =~ /540512,169141/) {
+ if ($args->{Filter} =~ /540512,169141|534371,185488/) {
$features = [
{ type => "Feature", properties => { HA_ID => "19" }, geometry => { type => "Polygon", coordinates => [ [
[ 539408.94, 170607.58 ],
diff --git a/t/app/controller/admin/bodies.t b/t/app/controller/admin/bodies.t
index c73a90da1..811ac4362 100644
--- a/t/app/controller/admin/bodies.t
+++ b/t/app/controller/admin/bodies.t
@@ -1,3 +1,13 @@
+package FixMyStreet::Cobrand::AnonAllowedByCategory;
+use parent 'FixMyStreet::Cobrand::UKCouncils';
+sub council_url { 'anonbycategory' }
+sub council_name { 'Aberdeen City Council' }
+sub council_area { 'Aberdeen' }
+sub council_area_id { 2650 }
+sub anonymous_account { { email => 'anoncategory@example.org', name => 'Anonymous Category' } }
+
+package main;
+
use FixMyStreet::TestMech;
my $mech = FixMyStreet::TestMech->new;
@@ -5,6 +15,10 @@ my $mech = FixMyStreet::TestMech->new;
my $superuser = $mech->create_user_ok('superuser@example.com', name => 'Super User', is_superuser => 1);
$mech->log_in_ok( $superuser->email );
my $body = $mech->create_body_ok(2650, 'Aberdeen City Council');
+my $body2 = $mech->create_body_ok(2237, 'Oxfordshire County Council');
+
+my $user = $mech->create_user_ok('user@example.com', name => 'OCC User', from_body => $body2);
+$user->user_body_permissions->create({ body => $body2, permission_type => 'category_edit' });
# This override is wrapped around ALL the /admin/body tests
FixMyStreet::override_config {
@@ -101,11 +115,14 @@ subtest 'check contact renaming' => sub {
$mech->get('/admin/body/' . $body->id . '/test%20category');
is $mech->res->code, 404;
$mech->get_ok('/admin/body/' . $body->id . '/testing%20category');
+ $mech->content_contains('<td><strong>test2@example.com</strong></td>');
$report->discard_changes;
is $report->category, 'testing category';
$mech->submit_form_ok( { with_fields => { category => 'test category' } } );
};
+
+
subtest 'check contact updating' => sub {
$mech->get_ok('/admin/body/' . $body->id . '/test%20category');
$mech->content_like(qr{test2\@example.com</strong>[^<]*</td>[^<]*<td>unconfirmed}s);
@@ -210,6 +227,7 @@ subtest 'check open311 configuring' => sub {
subtest 'check open311 devolved editing' => sub {
$mech->get_ok('/admin/body/' . $body->id . '/test%20category');
+ $mech->content_contains("name=\"category\"\n size=\"30\" value=\"test category\"\n readonly>", 'Cannot edit Open311 category name');
$mech->submit_form_ok( { with_fields => {
send_method => 'Email',
email => 'testing@example.org',
@@ -217,11 +235,13 @@ subtest 'check open311 devolved editing' => sub {
} } );
$mech->content_contains('Values updated');
$mech->get_ok('/admin/body/' . $body->id . '/test%20category');
+ $mech->content_contains("name=\"category\"\n size=\"30\" value=\"test category\"\n required>", 'Can edit as now devolved');
$mech->submit_form_ok( { with_fields => {
send_method => '',
- email => 'open311-code',
+ email => 'open311 code',
note => 'Removing email send method',
} } );
+ $mech->content_contains('open311 code');
$mech->content_contains('Values updated');
};
@@ -261,8 +281,64 @@ subtest 'open311 protection editing' => sub {
is $contact->get_extra_metadata('open311_protect'), 1, 'Open311 protect flag set';
};
+subtest 'test assigned_users_only setting' => sub {
+ $mech->get_ok('/admin/body/' . $body->id . '/test%20category');
+ $mech->submit_form_ok( { with_fields => {
+ assigned_users_only => 1,
+ } } );
+ $mech->content_contains('Values updated');
+ my $contact = $body->contacts->find({ category => 'test category' });
+ is $contact->get_extra_metadata('assigned_users_only'), 1;
+};
+
+subtest 'updates disabling' => sub {
+ $mech->get_ok('/admin/body/' . $body->id . '/test%20category');
+ $mech->submit_form_ok( { with_fields => {
+ updates_disallowed => 1,
+ note => 'Disabling updates',
+ } } );
+ $mech->content_contains('Values updated');
+ my $contact = $body->contacts->find({ category => 'test category' });
+ is $contact->get_extra_metadata('updates_disallowed'), 1, 'Updates disallowed flag set';
+};
+
+subtest 'reopen disabling' => sub {
+ $mech->get_ok('/admin/body/' . $body->id . '/test%20category');
+ $mech->submit_form_ok( { with_fields => {
+ reopening_disallowed => 1,
+ note => 'Disabling reopening',
+ } } );
+ $mech->content_contains('Values updated');
+ my $contact = $body->contacts->find({ category => 'test category' });
+ is $contact->get_extra_metadata('reopening_disallowed'), 1, 'Reopening disallowed flag set';
+};
+
+subtest 'allow anonymous reporting' => sub {
+ $mech->get_ok('/admin/body/' . $body->id . '/test%20category');
+ $mech->content_lacks('Allow anonymous reports');
+};
}; # END of override wrap
+FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ MAPIT_TYPES => [ 'UTA' ],
+ BASE_URL => 'http://www.example.org',
+ ALLOWED_COBRANDS => [ "fixmystreet", "anonallowedbycategory" ],
+}, sub {
+
+subtest 'allow anonymous reporting' => sub {
+ $mech->get_ok('/admin/body/' . $body->id . '/test%20category');
+ $mech->submit_form_ok( { with_fields => {
+ anonymous_allowed => 1,
+ note => 'Anonymous Allowed',
+ } } );
+ $mech->content_contains('Values updated');
+ my $contact = $body->contacts->find({ category => 'test category' });
+ is $contact->get_extra_metadata('anonymous_allowed'), 1, 'Anonymous reports allowed flag set';
+};
+
+};
+
FixMyStreet::override_config {
MAPIT_URL => 'http://mapit.uk/',
@@ -345,4 +421,90 @@ subtest 'check log of the above' => sub {
$mech->content_contains('Edited body <a href="/admin/body/' . $body->id . '">Aberdeen City Council</a>');
};
+subtest 'check update disallowed message' => sub {
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => 'bathnes',
+ COBRAND_FEATURES => { updates_allowed => { bathnes => 'open' } }
+ }, sub {
+ $mech->get_ok('/admin/body/' . $body->id .'/test%20category');
+ $mech->content_contains('even if this is unticked, only open reports can have updates left on them.');
+ };
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => 'bathnes',
+ COBRAND_FEATURES => { updates_allowed => { bathnes => 'staff' } }
+ }, sub {
+ $mech->get_ok('/admin/body/' . $body->id .'/test%20category');
+ $mech->content_contains('even if this is unticked, only staff will be able to leave updates.');
+ };
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => 'bathnes',
+ COBRAND_FEATURES => { updates_allowed => { bathnes => 'reporter' } }
+ }, sub {
+ $mech->get_ok('/admin/body/' . $body->id .'/test%20category');
+ $mech->content_contains('even if this is unticked, only the problem reporter will be able to leave updates');
+ };
+};
+
+subtest 'check hardcoded contact renaming' => sub {
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ 'ALLOWED_COBRANDS' => [ 'oxfordshire' ],
+ }, sub {
+ my $contact = FixMyStreet::DB->resultset('Contact')->create(
+ {
+ body_id => $body2->id,
+ category => 'protected category',
+ state => 'confirmed',
+ editor => $0,
+ whenedited => \'current_timestamp',
+ note => 'protected contact',
+ email => 'protected@example.org',
+ }
+ );
+ $contact->set_extra_metadata( 'hardcoded', 1 );
+ $contact->update;
+ $mech->get_ok('/admin/body/' . $body2->id .'/protected%20category');
+ $mech->content_contains( 'name="hardcoded"' );
+ $mech->content_like( qr'value="protected category"[^>]*readonly's );
+ $mech->submit_form_ok( { with_fields => { category => 'non protected category', note => 'rename category' } } );
+ $mech->content_contains( 'protected category' );
+ $mech->content_lacks( 'non protected category' );
+ $mech->get('/admin/body/' . $body2->id . '/non%20protected%20category');
+ is $mech->res->code, 404;
+
+ $mech->get_ok('/admin/body/' . $body2->id .'/protected%20category');
+ $mech->submit_form_ok( { with_fields => { hardcoded => 0, note => 'remove hardcoding' } } );
+ $mech->get_ok('/admin/body/' . $body2->id .'/protected%20category');
+ $mech->content_unlike( qr'value="protected category"[^>]*readonly's );
+ $mech->submit_form_ok( { with_fields => { category => 'non protected category', note => 'rename category' } } );
+ $mech->content_contains( 'non protected category' );
+ $mech->get_ok('/admin/body/' . $body2->id . '/non%20protected%20category');
+ $mech->get('/admin/body/' . $body2->id . '/protected%20category');
+ is $mech->res->code, 404;
+
+ $contact->discard_changes;
+ $contact->set_extra_metadata( 'hardcoded', 1 );
+ $contact->update;
+
+ $mech->log_out_ok( $superuser->email );
+ $mech->log_in_ok( $user->email );
+ $mech->get_ok('/admin/body/' . $body2->id . '/non%20protected%20category');
+ $mech->content_lacks( 'name="hardcoded"' );
+ $user->update( { is_superuser => 1 } );
+ $mech->get_ok('/admin/body/' . $body2->id . '/non%20protected%20category');
+ $mech->content_contains('name="hardcoded"' );
+ $user->update( { is_superuser => 0 } );
+ $mech->submit_form_ok( { with_fields => { hardcoded => 0, note => 'remove hardcoding' } } );
+ $mech->content_lacks( 'name="hardcoded"' );
+
+ $contact->discard_changes;
+ is $contact->get_extra_metadata('hardcoded'), 1, "non superuser can't remove hardcoding";
+
+ $mech->log_out_ok( $user->email );
+ };
+};
+
done_testing();
diff --git a/t/app/controller/admin/report_edit.t b/t/app/controller/admin/report_edit.t
index 438bcc241..e041154db 100644
--- a/t/app/controller/admin/report_edit.t
+++ b/t/app/controller/admin/report_edit.t
@@ -9,6 +9,7 @@ my $user2 = $mech->create_user_ok('test2@example.com', name => 'Test User 2');
my $superuser = $mech->create_user_ok('superuser@example.com', name => 'Super User', is_superuser => 1);
my $oxfordshire = $mech->create_body_ok(2237, 'Oxfordshire County Council');
+my $user3 = $mech->create_user_ok('body_user@example.com', name => 'Body User', from_body => $oxfordshire);
my $oxfordshirecontact = $mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Potholes', email => 'potholes@example.com' );
$mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Traffic lights', email => 'lights@example.com' );
@@ -328,7 +329,6 @@ foreach my $test (
closed_updates => undef,
},
expect_comment => 1,
- user_body => $oxfordshire,
changes => { state => 'investigating' },
log_entries => [
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/
@@ -350,7 +350,6 @@ foreach my $test (
},
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 category_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/
@@ -363,11 +362,6 @@ foreach my $test (
$report->comments->delete;
$log_entries->reset;
- if ( $test->{user_body} ) {
- $superuser->from_body( $test->{user_body}->id );
- $superuser->update;
- }
-
$mech->get_ok("/admin/report_edit/$report_id");
@{$test->{fields}}{'external_id', 'external_body', 'external_team', 'category'} = (13, "", "", "Other");
@@ -439,21 +433,12 @@ foreach my $test (
} else {
is $comment->text, '', 'comment has no text';
}
- if ( $test->{user_body} ) {
- ok $comment->get_extra_metadata('is_body_user'), 'body user metadata set';
- ok !$comment->get_extra_metadata('is_superuser'), 'superuser metadata not set';
- is $comment->name, $test->{user_body}->name, 'comment name is body name';
- } else {
- ok !$comment->get_extra_metadata('is_body_user'), 'body user metadata not set';
- ok $comment->get_extra_metadata('is_superuser'), 'superuser metadata set';
- is $comment->name, _('an administrator'), 'comment name is admin';
- }
+ ok !$comment->get_extra_metadata('is_body_user'), 'body user metadata not set';
+ ok $comment->get_extra_metadata('is_superuser'), 'superuser metadata set';
+ is $comment->name, _('an administrator'), 'comment name is admin';
} else {
is $report->comments->count, 0, 'report has no comments';
}
-
- $superuser->from_body(undef);
- $superuser->update;
};
}
@@ -685,16 +670,28 @@ subtest "Test display of fields extra data" => sub {
$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->push_extra_fields(
+ {
+ name => 'report_url',
+ value => 'http://example.com',
+ },
+ {
+ name => 'sent_to',
+ value => [ 'onerecipient@example.org' ],
+ },
+ {
+ name => 'sent_too',
+ value => [ 'onemorerecipient@example.org', 'another@example.org' ],
+ },
+ );
$report->update;
$report->discard_changes;
$mech->get_ok("/admin/report_edit/$report_id");
$mech->content_contains('report_url</strong>: http://example.com');
+ $mech->content_contains('sent_to</strong>: onerecipient@example.org');
+ $mech->content_contains('sent_too</strong>: onemorerecipient@example.org, another@example.org');
$report->set_extra_fields( {
description => 'Report URL',
@@ -707,4 +704,20 @@ subtest "Test display of fields extra data" => sub {
$mech->content_contains('Report URL (report_url)</strong>: http://example.com');
};
+subtest "Test display of contributed_as data" => sub {
+ $report->update( { extra => undef } );
+ $mech->get_ok("/admin/report_edit/$report_id");
+ $mech->content_contains('Extra data: No');
+
+ $report->set_extra_metadata( contributed_as => 'another_user' );
+ $report->set_extra_metadata( contributed_by => $user3->id );
+ $report->update;
+
+ $report->discard_changes;
+
+ $mech->get_ok("/admin/report_edit/$report_id");
+ $mech->content_like(qr!Created By</strong>: <a[^>]*>Body User \(@{[ $user3->email ]}!);
+ $mech->content_contains('Created Body</strong>: Oxfordshire County Council');
+};
+
done_testing();
diff --git a/t/app/controller/admin/update_edit.t b/t/app/controller/admin/update_edit.t
index 57c8973d4..8650e7771 100644
--- a/t/app/controller/admin/update_edit.t
+++ b/t/app/controller/admin/update_edit.t
@@ -81,7 +81,7 @@ for my $test (
fields => {
text => 'this is an update',
state => 'confirmed',
- name => '',
+ name => 'Test User',
anonymous => 1,
username => $update->user->email,
},
@@ -96,7 +96,7 @@ for my $test (
fields => {
text => 'this is a changed update',
state => 'confirmed',
- name => '',
+ name => 'Test User',
anonymous => 1,
username => $update->user->email,
},
diff --git a/t/app/controller/admin/users.t b/t/app/controller/admin/users.t
index 4f0298103..6f3971149 100644
--- a/t/app/controller/admin/users.t
+++ b/t/app/controller/admin/users.t
@@ -6,6 +6,8 @@ my $user = $mech->create_user_ok('test@example.com', name => 'Test User');
my $original_user_id = $user->id; # For log later
my $user2 = $mech->create_user_ok('test2@example.com', name => 'Test User 2');
my $user3 = $mech->create_user_ok('test3@example.com', name => 'Test User 3');
+my $user4 = $mech->create_user_ok('test4@example.com', name => 'Test User 4');
+my $user5 = $mech->create_user_ok('test5@example.com', name => 'Test User 5');
my $superuser = $mech->create_user_ok('superuser@example.com', name => 'Super User', is_superuser => 1);
@@ -13,6 +15,21 @@ my $oxfordshire = $mech->create_body_ok(2237, 'Oxfordshire County Council');
my $haringey = $mech->create_body_ok(2509, 'Haringey Borough Council');
my $southend = $mech->create_body_ok(2607, 'Southend-on-Sea Borough Council');
+$user4->from_body( $oxfordshire->id );
+$user4->update;
+$user4->user_body_permissions->create( {
+ body => $oxfordshire,
+ permission_type => 'user_edit',
+} );
+$user5->from_body( $oxfordshire->id );
+$user5->update;
+my $occ_role = $user5->roles->create({
+ body => $oxfordshire,
+ name => 'Role A',
+ permissions => ['moderate', 'user_edit'],
+});
+$user5->add_to_roles($occ_role);
+
$mech->log_in_ok( $superuser->email );
subtest 'search abuse' => sub {
@@ -84,8 +101,6 @@ subtest 'user search' => sub {
permissions => ['moderate', 'user_edit'],
});
$user->add_to_roles($role);
- $mech->get_ok('/admin/users?search=' . $haringey->id );
- $mech->content_contains('test@example.com');
$mech->get_ok('/admin/users?role=' . $role->id);
$mech->content_contains('selected>Role A');
$mech->content_contains('test@example.com');
@@ -99,6 +114,38 @@ subtest 'user assign role' => sub {
is $user->roles->count, 1;
};
+subtest 'remove users from staff' => sub {
+ is $user4->from_body->id, $oxfordshire->id, 'user4 has a body';
+ is $user4->email_verified, 1, 'user4 email is verified';
+ is $user4->user_body_permissions->count, 1, 'user4 has permissions';
+ is $user5->from_body->id, $oxfordshire->id, 'user5 has a body';
+ is $user5->email_verified, 1, 'user5 email is verified';
+ is $user5->user_roles->count, 1, 'user5 has a role';
+
+ $mech->get_ok('/admin/users');
+ $mech->content_contains($user4->email);
+ $mech->content_contains($user5->email);
+
+ $mech->submit_form_ok({ with_fields => { uid => $user4->id, 'remove-staff' => 'remove-staff'} });
+ $mech->content_lacks($user4->email);
+ $mech->content_contains($user5->email);
+ $user4->discard_changes;
+ $user5->discard_changes;
+ is $user4->from_body, undef, 'user4 removed from body';
+ is $user4->email_verified, 0, 'user4 email unverified';
+ is $user4->user_body_permissions->count, 0, 'no user4 permissions';
+ is $user5->from_body->id, $oxfordshire->id, 'user5 has a body';
+ is $user5->email_verified, 1, 'user5 email is verified';
+ is $user5->user_roles->count, 1, 'user5 has a role';
+
+ $mech->submit_form_ok({ with_fields => { uid => $user5->id, 'remove-staff' => 'remove-staff'} });
+ $mech->content_lacks($user5->email);
+ $user5->discard_changes;
+ is $user5->from_body, undef, 'user5 has no body';
+ is $user5->email_verified, 0, 'user5 email unverified';
+ is $user5->user_roles->count, 0, 'no user5 roles';
+};
+
subtest 'search does not show user from another council' => sub {
FixMyStreet::override_config {
ALLOWED_COBRANDS => [ 'oxfordshire' ],
@@ -299,6 +346,7 @@ FixMyStreet::override_config {
flagged => undef,
is_superuser => undef,
area_ids => undef,
+ assigned_categories_only => undef,
%default_perms,
roles => $role->id,
},
@@ -320,6 +368,7 @@ FixMyStreet::override_config {
flagged => undef,
is_superuser => undef,
area_ids => undef,
+ assigned_categories_only => undef,
%default_perms,
roles => $role->id,
},
@@ -341,6 +390,7 @@ FixMyStreet::override_config {
flagged => undef,
is_superuser => undef,
area_ids => undef,
+ assigned_categories_only => undef,
%default_perms,
roles => $role->id,
},
@@ -365,6 +415,7 @@ FixMyStreet::override_config {
flagged => undef,
is_superuser => undef,
area_ids => undef,
+ assigned_categories_only => undef,
%default_perms,
},
changes => {
@@ -385,6 +436,7 @@ FixMyStreet::override_config {
flagged => 'on',
is_superuser => undef,
area_ids => undef,
+ assigned_categories_only => undef,
%default_perms,
},
changes => {
@@ -394,7 +446,7 @@ FixMyStreet::override_config {
log_entries => [qw/edit edit edit edit/],
},
{
- desc => 'edit user add is_superuser',
+ desc => 'edit user add is_superuser and assigned_categories_only',
fields => {
name => 'Changed User',
email => 'changed@example.com',
@@ -405,10 +457,12 @@ FixMyStreet::override_config {
flagged => undef,
is_superuser => undef,
area_ids => undef,
+ assigned_categories_only => undef,
%default_perms,
},
changes => {
is_superuser => 'on',
+ assigned_categories_only => 'on',
},
removed => [
keys %default_perms,
@@ -428,6 +482,7 @@ FixMyStreet::override_config {
flagged => undef,
is_superuser => 'on',
area_ids => undef,
+ assigned_categories_only => 'on',
},
changes => {
is_superuser => undef,
diff --git a/t/app/controller/alert.t b/t/app/controller/alert.t
index 41aee5bbc..34e68177c 100644
--- a/t/app/controller/alert.t
+++ b/t/app/controller/alert.t
@@ -1,6 +1,7 @@
use FixMyStreet::TestMech;
my $mech = FixMyStreet::TestMech->new;
+use Test::MockModule;
use t::Mock::Nominatim;
# check that we can get the page
@@ -73,4 +74,25 @@ FixMyStreet::override_config {
is $mech->uri->path, '/rss/reports/Cheltenham/Lansdown';
};
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'fixmystreet',
+ MAPIT_URL => 'http://mapit.uk/',
+ GEOCODER => '',
+ RECAPTCHA => { secret => 'secret', site_key => 'site_key' },
+}, sub {
+ subtest 'recaptcha' => sub {
+ $mech->get_ok('/alert/list?pc=EH11BB');
+ $mech->content_lacks('g-recaptcha'); # GB is default test country
+
+ my $mod_app = Test::MockModule->new('FixMyStreet::App');
+ $mod_app->mock('user_country', sub { 'FR' });
+ my $mod_lwp = Test::MockModule->new('LWP::UserAgent');
+ $mod_lwp->mock('post', sub { HTTP::Response->new(200, 'OK', [], '{ "success": true }') });
+
+ $mech->get_ok('/alert/list?pc=EH11BB');
+ $mech->content_contains('g-recaptcha');
+ $mech->submit_form_ok({ with_fields => { rznvy => 'someone@example.org' } });
+ };
+};
+
done_testing();
diff --git a/t/app/controller/alert_new.t b/t/app/controller/alert_new.t
index 7eba90530..562b173c8 100644
--- a/t/app/controller/alert_new.t
+++ b/t/app/controller/alert_new.t
@@ -1,3 +1,4 @@
+use utf8;
use FixMyStreet::TestMech;
use FixMyStreet::Script::Alerts;
@@ -523,6 +524,8 @@ subtest "Test alerts are not sent for no-text updates" => sub {
};
$mech->email_count_is(1);
+ $user2->discard_changes;
+ isnt $user2->last_active, undef, 'Last active has been set';
$mech->delete_user($user1);
$mech->delete_user($user2);
@@ -864,4 +867,48 @@ subtest 'check setting include dates in new updates cobrand option' => sub {
$include_date_in_alert_override->restore();
};
+subtest 'check staff updates can include sanitized HTML' => sub {
+ my $user1 = $mech->create_user_ok('reporter@example.com', name => 'Reporter User');
+ my $user2 = $mech->create_user_ok('staff@example.com', name => 'Staff User', from_body => $body);
+ my $user3 = $mech->create_user_ok('updater@example.com', name => 'Another User');
+
+ my $dt = DateTime->now->add( minutes => -30 );
+ my $r_dt = $dt->clone->add( minutes => 20 );
+
+ my ($report) = $mech->create_problems_for_body(1, $body->id, 'Testing', {
+ user => $user1,
+ });
+
+ my $update1 = $mech->create_comment_for_problem($report, $user2, 'Staff User', '<p>This is some update text with <strong>HTML</strong> and *italics*.</p> <ul><li>Even a list</li><li>Which might work</li><li>In the <a href="https://www.fixmystreet.com/">text</a> part</li></ul> <script>not allowed</script>', 't', 'confirmed', undef, { confirmed => $r_dt->clone->add( minutes => 8 ) });
+ $update1->set_extra_metadata(is_body_user => $user2->from_body->id);
+ $update1->set_extra_metadata(something_unicodey => "The cafɇ is here");
+ $update1->update;
+
+ $mech->create_comment_for_problem($report, $user3, 'Updater User', 'Public users <i>cannot</i> use HTML. <script>not allowed</script>', 't', 'confirmed', undef, { confirmed => $r_dt->clone->add( minutes => 9 ) });
+
+ my $alert_user1 = FixMyStreet::DB->resultset('Alert')->create( {
+ user => $user1,
+ alert_type => 'new_updates',
+ parameter => $report->id,
+ confirmed => 1,
+ whensubscribed => $dt,
+ } );
+ ok $alert_user1, "alert created";
+
+ FixMyStreet::DB->resultset('AlertType')->email_alerts();
+ my $email = $mech->get_email;
+ my $plain = $mech->get_text_body_from_email($email);
+ like $plain, qr/This is some update text with \*HTML\* and \*italics\*\.\r\n\r\n\* Even a list\r\n\r\n\* Which might work\r\n\r\n\* In the text \[https:\/\/www.fixmystreet.com\/\] part/, 'plain text part contains no HTML tags from staff update';
+ like $plain, qr/Public users <i>cannot<\/i> use HTML\./, 'plain text part contains exactly what was entered';
+
+ my $html = $mech->get_html_body_from_email($email);
+ like $html, qr{This is some update text with <strong>HTML</strong> and <i>italics</i>\.}, 'HTML part contains HTML tags';
+ unlike $html, qr/<script>/, 'HTML part contains no script tags';
+
+ $mech->delete_user( $user1 );
+ $mech->delete_user( $user2 );
+ $mech->delete_user( $user3 );
+};
+
+
done_testing();
diff --git a/t/app/controller/around.t b/t/app/controller/around.t
index 186b833fd..3f5d31c02 100644
--- a/t/app/controller/around.t
+++ b/t/app/controller/around.t
@@ -9,6 +9,7 @@ use constant MIN_ZOOM_LEVEL => 88;
package main;
use Test::MockModule;
+use t::Mock::Nominatim;
use FixMyStreet::TestMech;
my $mech = FixMyStreet::TestMech->new;
@@ -53,6 +54,11 @@ foreach my $test (
};
}
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'fixmystreet',
+ MAPIT_URL => 'http://mapit.uk/',
+}, sub {
+
# check that exact queries result in the correct lat,lng
foreach my $test (
{
@@ -69,19 +75,45 @@ foreach my $test (
{
subtest "check lat/lng for '$test->{pc}'" => sub {
$mech->get_ok('/');
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { 'fixmystreet' => '.' } ],
- MAPIT_URL => 'http://mapit.uk/',
- }, sub {
- $mech->submit_form_ok( { with_fields => { pc => $test->{pc} } },
- "good location" );
- };
+ $mech->submit_form_ok( { with_fields => { pc => $test->{pc} } },
+ "good location" );
is_deeply $mech->page_errors, [], "no errors for pc '$test->{pc}'";
is_deeply $mech->extract_location, $test,
"got expected location for pc '$test->{pc}'";
+ $mech->get_ok('/');
+ my $pc = "$test->{latitude},$test->{longitude}";
+ $mech->submit_form_ok( { with_fields => { pc => $pc } },
+ "good location" );
+ is_deeply $mech->page_errors, [], "no errors for pc '$pc'";
+ is_deeply $mech->extract_location, { %$test, pc => $pc },
+ "got expected location for pc '$pc'";
};
}
+subtest "check lat/lng for full plus code" => sub {
+ $mech->get_ok('/');
+ $mech->submit_form_ok( { with_fields => { pc => "9C7RXR26+R5" } } );
+ is_deeply $mech->page_errors, [], "no errors for plus code";
+ is_deeply $mech->extract_location, {
+ pc => "9C7RXR26+R5",
+ latitude => 55.952063,
+ longitude => -3.189562,
+ },
+ "got expected location for full plus code";
+};
+
+subtest "check lat/lng for short plus code" => sub {
+ $mech->get_ok('/');
+ $mech->submit_form_ok( { with_fields => { pc => "XR26+R5 Edinburgh" } } );
+ is_deeply $mech->page_errors, [], "no errors for plus code";
+ is_deeply $mech->extract_location, {
+ pc => "XR26+R5 Edinburgh",
+ latitude => 55.952063,
+ longitude => -3.189562,
+ },
+ "got expected location for short plus code";
+};
+
my $body_edin_id = $mech->create_body_ok(2651, 'City of Edinburgh Council')->id;
my $body_west_id = $mech->create_body_ok(2504, 'Westminster City Council')->id;
@@ -93,10 +125,10 @@ my @edinburgh_problems = $mech->create_problems_for_body( 5, $body_edin_id, 'Aro
subtest 'check lookup by reference' => sub {
$mech->get_ok('/');
- $mech->submit_form_ok( { with_fields => { pc => 'ref:12345' } }, 'bad ref');
+ $mech->submit_form_ok( { with_fields => { pc => '12345' } }, 'bad ref');
$mech->content_contains('Searching found no reports');
my $id = $edinburgh_problems[0]->id;
- $mech->submit_form_ok( { with_fields => { pc => "ref:$id" } }, 'good ref');
+ $mech->submit_form_ok( { with_fields => { pc => $id } }, 'good ref');
is $mech->uri->path, "/report/$id", "redirected to report page";
};
@@ -106,19 +138,14 @@ subtest 'check lookup by reference does not show non_public reports' => sub {
});
my $id = $edinburgh_problems[0]->id;
$mech->get_ok('/');
- $mech->submit_form_ok( { with_fields => { pc => "ref:$id" } }, 'non_public ref');
+ $mech->submit_form_ok( { with_fields => { pc => $id } }, 'non_public ref');
$mech->content_contains('Searching found no reports');
};
subtest 'check non public reports are not displayed on around page' => sub {
$mech->get_ok('/');
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { 'fixmystreet' => '.' } ],
- MAPIT_URL => 'http://mapit.uk/',
- }, sub {
- $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB' } },
- "good location" );
- };
+ $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB' } },
+ "good location" );
$mech->content_contains( "Around page Test 3 for $body_edin_id",
'problem to be marked non public visible' );
@@ -126,31 +153,21 @@ subtest 'check non public reports are not displayed on around page' => sub {
ok $private->update( { non_public => 1 } ), 'problem marked non public';
$mech->get_ok('/');
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { 'fixmystreet' => '.' } ],
- MAPIT_URL => 'http://mapit.uk/',
- }, sub {
- $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB' } },
- "good location" );
- };
+ $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB' } },
+ "good location" );
$mech->content_lacks( "Around page Test 3 for $body_edin_id",
'problem marked non public is not visible' );
};
subtest 'check missing body message not shown when it does not need to be' => sub {
$mech->get_ok('/');
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => 'fixmystreet',
- MAPIT_URL => 'http://mapit.uk/',
- }, sub {
- $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB' } },
- "good location" );
- };
+ $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB' } },
+ "good location" );
$mech->content_lacks('yet have details for the other councils that cover this location');
};
for my $permission ( qw/ report_inspect report_mark_private/ ) {
- subtest 'check non public reports are displayed on around page with $permission permission' => sub {
+ subtest "check non public reports are displayed on around page with $permission permission" => sub {
my $body = FixMyStreet::DB->resultset('Body')->find( $body_edin_id );
my $body2 = FixMyStreet::DB->resultset('Body')->find( $body_west_id );
my $user = $mech->log_in_ok( 'test@example.com' );
@@ -162,24 +179,14 @@ for my $permission ( qw/ report_inspect report_mark_private/ ) {
});
$mech->get_ok('/');
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { 'fixmystreet' => '.' } ],
- MAPIT_URL => 'http://mapit.uk/',
- }, sub {
- $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB' } },
- "good location" );
- };
+ $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB' } },
+ "good location" );
$mech->content_contains( "Around page Test 3 for $body_edin_id",
'problem marked non public is visible' );
$mech->content_contains( "Around page Test 2 for $body_edin_id",
'problem marked public is visible' );
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { 'fixmystreet' => '.' } ],
- MAPIT_URL => 'http://mapit.uk/',
- }, sub {
- $mech->get_ok('/around?pc=EH1+1BB&status=non_public');
- };
+ $mech->get_ok('/around?pc=EH1+1BB&status=non_public');
$mech->content_contains( "Around page Test 3 for $body_edin_id",
'problem marked non public is visible' );
$mech->content_lacks( "Around page Test 2 for $body_edin_id",
@@ -193,24 +200,14 @@ for my $permission ( qw/ report_inspect report_mark_private/ ) {
});
$mech->get_ok('/');
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { 'fixmystreet' => '.' } ],
- MAPIT_URL => 'http://mapit.uk/',
- }, sub {
- $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB' } },
- "good location" );
- };
+ $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB' } },
+ "good location" );
$mech->content_lacks( "Around page Test 3 for $body_edin_id",
'problem marked non public is not visible' );
$mech->content_contains( "Around page Test 2 for $body_edin_id",
'problem marked public is visible' );
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { 'fixmystreet' => '.' } ],
- MAPIT_URL => 'http://mapit.uk/',
- }, sub {
- $mech->get_ok('/around?pc=EH1+1BB&status=non_public');
- };
+ $mech->get_ok('/around?pc=EH1+1BB&status=non_public');
$mech->content_lacks( "Around page Test 3 for $body_edin_id",
'problem marked non public is not visible' );
$mech->content_lacks( "Around page Test 2 for $body_edin_id",
@@ -218,6 +215,26 @@ for my $permission ( qw/ report_inspect report_mark_private/ ) {
};
}
+subtest 'check assigned-only list items do not display shortlist buttons' => sub {
+ my $body = FixMyStreet::DB->resultset('Body')->find( $body_edin_id );
+ my $contact = $mech->create_contact_ok( category => 'Horses & Ponies', body_id => $body->id, email => "horses\@example.org" );
+ $edinburgh_problems[4]->update({ category => 'Horses & Ponies' });
+
+ my $user = $mech->log_in_ok( 'test@example.com' );
+ $user->set_extra_metadata(assigned_categories_only => 1);
+ $user->user_body_permissions->delete();
+ $user->set_extra_metadata(categories => [ $contact->id ]);
+ $user->update({ from_body => $body });
+ $user->user_body_permissions->find_or_create({ body => $body, permission_type => 'planned_reports' });
+
+ $mech->get_ok('/around?pc=EH1+1BB');
+ $mech->content_contains('shortlist-add-' . $edinburgh_problems[4]->id);
+ $mech->content_lacks('shortlist-add-' . $edinburgh_problems[3]->id);
+ $mech->content_lacks('shortlist-add-' . $edinburgh_problems[1]->id);
+};
+
+}; # End big override_config
+
my $body = $mech->create_body_ok(2237, "Oxfordshire");
subtest 'check category, status and extra filtering works on /around' => sub {
@@ -233,7 +250,10 @@ subtest 'check category, status and extra filtering works on /around' => sub {
# Create one open and one fixed report in each category
foreach my $category ( @$categories ) {
my $contact = $mech->create_contact_ok( category => $category, body_id => $body->id, email => "$category\@example.org" );
- if ($category ne 'Pothole') {
+ if ($category eq 'Vegetation') {
+ $contact->set_extra_metadata(group => ['Environment', 'Green']);
+ $contact->update;
+ } elsif ($category eq 'Flytipping') {
$contact->set_extra_metadata(group => ['Environment']);
$contact->update;
}
@@ -264,6 +284,9 @@ subtest 'check category, status and extra filtering works on /around' => sub {
$mech->get_ok( '/around?filter_group=Environment&bbox=' . $bbox );
$mech->content_contains('<option value="Flytipping" selected>');
+
+ $mech->get_ok( '/around?filter_group=Environment&filter_category=Vegetation&bbox=' . $bbox );
+ $mech->content_like(qr/<optgroup label="Environment">.*?<option value="Vegetation" selected>.*?<optgroup label="Green">.*?<option value="Vegetation">/s);
};
$json = $mech->get_ok_json( '/around?ajax=1&filter_category=Pothole&bbox=' . $bbox );
@@ -286,6 +309,37 @@ subtest 'check category, status and extra filtering works on /around' => sub {
is scalar @$pins, 1, 'correct number of external_body reports';
};
+subtest 'check categories with same name are only shown once in filters' => sub {
+ my $params = {
+ postcode => 'OX20 1SZ',
+ latitude => 51.754926,
+ longitude => -1.256179,
+ };
+ my $bbox = ($params->{longitude} - 0.01) . ',' . ($params->{latitude} - 0.01)
+ . ',' . ($params->{longitude} + 0.01) . ',' . ($params->{latitude} + 0.01);
+
+ my $district = $mech->create_body_ok(2421, "Oxford City");
+ # Identically-named categories should be combined even if their extra metadata is different
+ my $contact2 = $mech->create_contact_ok( category => "Pothole", body_id => $district->id, email => 'pothole@district-example.org' );
+ $contact2->set_extra_metadata(some_extra_field => "dummy");
+ $contact2->update;
+ # And categories with the same display name should be combined too
+ my $contact3 = $mech->create_contact_ok( category => "Pothole (alternative)", body_id => $district->id, email => 'pothole-alternative@district-example.org' );
+ $contact3->set_extra_metadata(display_name => "Pothole");
+ $contact3->update;
+
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'fixmystreet',
+ MAPIT_URL => 'http://mapit.uk/',
+ COBRAND_FEATURES => { category_groups => { fixmystreet => 1 } },
+ }, sub {
+ $mech->get_ok( '/around?bbox=' . $bbox );
+ $mech->content_contains('<option value="Pothole">');
+ $mech->content_unlike(qr{Pothole</option>.*<option value="Pothole">\s*Pothole</option>}s, "Pothole category only appears once");
+ $mech->content_lacks('<option value="Pothole (alternative)">');
+ };
+};
+
subtest 'check old problems not shown by default on around page' => sub {
my $params = {
postcode => 'OX20 1SZ',
@@ -390,7 +444,7 @@ subtest 'check map zoom level customisation' => sub {
MAP_TYPE => 'OSM',
}, sub {
$mech->get('/around?latitude=51.754926&longitude=-1.256179');
- $mech->content_contains('data-numZoomLevels=6');
+ $mech->content_contains('data-numZoomLevels=7');
$mech->content_contains('data-zoomOffset=13');
};
diff --git a/t/app/controller/auth.t b/t/app/controller/auth.t
index 24deb8cab..0326bbacd 100644
--- a/t/app/controller/auth.t
+++ b/t/app/controller/auth.t
@@ -245,19 +245,20 @@ subtest "check logging in with token" => sub {
my $user = FixMyStreet::DB->resultset('User')->find( { email => $test_email } );
# token needs to be 18 characters
- $user->set_extra_metadata('access_token', '1234567890abcdefgh');
+ my $u = FixMyStreet::DB->resultset("User")->new({ password => '1234567890abcdefgh' });
+ $user->set_extra_metadata('access_token', $u->password);
$user->update();
- $mech->add_header('Authorization', 'Bearer 1234567890abcdefgh');
+ $mech->add_header('Authorization', 'Bearer ' . $user->id . '-1234567890abcdefgh');
$mech->logged_in_ok;
$mech->delete_header('Authorization');
$mech->not_logged_in_ok;
- $mech->get_ok('/auth/check_auth?access_token=1234567890abcdefgh');
+ $mech->get_ok('/auth/check_auth?access_token=' . $user->id . '-1234567890abcdefgh');
- $mech->add_header('Authorization', 'Bearer 1234567890abcdefgh');
- $user->set_extra_metadata('access_token', 'XXXXXXXXXXXXXXXXXX');
+ $mech->add_header('Authorization', 'Bearer ' . $user->id . '-1234567890abcdefgh');
+ $user->set_extra_metadata('access_token', '$2a$08$HNslSx7Uic7q6Ti5WYT5JOT6npYPwrwLnDMJMJoD22LIqG5TfDIKf');
$user->update();
$mech->not_logged_in_ok;
@@ -287,6 +288,23 @@ subtest 'check common password AJAX call' => sub {
$mech->content_contains("true");
};
+subtest 'check hibp password call' => sub {
+ FixMyStreet::override_config {
+ CHECK_HAVEIBEENPWNED => 1,
+ }, sub {
+ my $lwp = Test::MockModule->new('LWP::Simple');
+ # Switch mock round from live site, so we know we're not testing live site by mistake
+ $lwp->mock(get => sub($) {
+ return '9958D0F0EE6744E7CCAFC84515FCFAD7B1B:10' if $_[0] =~ /6EF4D$/; # squirblewirble
+ return '';
+ });
+ $mech->post_ok('/auth/common_password', { password_register => 'p@ssword2' });
+ $mech->content_contains("true");
+ $mech->post_ok('/auth/common_password', { password_register => 'squirblewirble' });
+ $mech->content_contains("That password has appeared in a known");
+ };
+};
+
subtest 'test forgotten password page' => sub {
$mech->get_ok('/auth/forgot');
$mech->content_contains('Forgot password');
diff --git a/t/app/controller/auth_profile.t b/t/app/controller/auth_profile.t
index e5dfe2764..230e02d2b 100644
--- a/t/app/controller/auth_profile.t
+++ b/t/app/controller/auth_profile.t
@@ -417,16 +417,16 @@ subtest "Test generate token page" => sub {
"submit generate token form"
);
$mech->content_contains( 'Your token has been generated', "token generated" );
+ my ($token) = $mech->content =~ /<span>(.*?)<\/span>/;
+ my @parts = split /-/, $token, 2;
+ is $parts[0], $user->id, 'token has user ID at start';
$user->discard_changes();
- my $token = $user->get_extra_metadata('access_token');
- ok $token, 'access token set';
-
- $mech->content_contains($token, 'access token displayed');
+ $user->password($user->get_extra_metadata('access_token'), 1);
+ ok $user->check_password($parts[1]), 'access token set';
$mech->get_ok('/auth/generate_token');
- $mech->content_contains('Current token:');
- $mech->content_contains($token, 'access token displayed');
+ $mech->content_lacks($parts[1], 'access token not displayed');
$mech->content_contains('If you generate a new token');
$mech->log_out_ok;
diff --git a/t/app/controller/auth_social.t b/t/app/controller/auth_social.t
index 200863029..9d1ea836f 100644
--- a/t/app/controller/auth_social.t
+++ b/t/app/controller/auth_social.t
@@ -15,9 +15,12 @@ FixMyStreet::App->log->disable('info');
END { FixMyStreet::App->log->enable('info'); }
my $body = $mech->create_body_ok(2504, 'Westminster City Council');
+my $body2 = $mech->create_body_ok(2508, 'Hackney Council');
my ($report) = $mech->create_problems_for_body(1, $body->id, 'My Test Report');
my $test_email = $report->user->email;
+my ($report2) = $mech->create_problems_for_body(1, $body2->id, 'My Test Report');
+my $test_email2 = $report->user->email;
my $contact = $mech->create_contact_ok(
body_id => $body->id, category => 'Damaged bin', email => 'BIN',
@@ -26,11 +29,21 @@ my $contact = $mech->create_contact_ok(
{ code => 'bin_service', description => 'Service needed', required => 'False' },
]
);
+$mech->create_contact_ok(
+ body_id => $body2->id, category => 'Damaged bin', email => 'BIN',
+ extra => [
+ { code => 'bin_type', description => 'Type of bin', required => 'True' },
+ { code => 'bin_service', description => 'Service needed', required => 'False' },
+ ]
+);
# Two options, incidentally, so that the template "Only one option, select it"
# code doesn't kick in and make the tests pass
my $contact2 = $mech->create_contact_ok(
body_id => $body->id, category => 'Whatever', email => 'WHATEVER',
);
+$mech->create_contact_ok(
+ body_id => $body2->id, category => 'Whatever', email => 'WHATEVER',
+);
my $resolver = Test::MockModule->new('Email::Valid');
my $social = Test::MockModule->new('FixMyStreet::App::Controller::Auth::Social');
@@ -88,6 +101,44 @@ for my $test (
user_extras => [
[westminster_account_id => "1c304134-ef12-c128-9212-123908123901"],
],
+}, {
+ type => 'oidc',
+ config => {
+ ALLOWED_COBRANDS => 'hackney',
+ MAPIT_URL => 'http://mapit.uk/',
+ COBRAND_FEATURES => {
+ anonymous_account => {
+ hackney => 'test',
+ },
+ oidc_login => {
+ hackney => {
+ client_id => 'example_client_id',
+ secret => 'example_secret_key',
+ auth_uri => 'http://oidc.example.org/oauth2/v2.0/authorize_google',
+ token_uri => 'http://oidc.example.org/oauth2/v2.0/token_google',
+ allowed_domains => [ 'example.org' ],
+ }
+ },
+ do_not_reply_email => {
+ hackney => 'fms-hackney-DO-NOT-REPLY@hackney-example.com',
+ },
+ verp_email_domain => {
+ hackney => 'hackney-example.com',
+ },
+ }
+ },
+ email => $mech->uniquify_email('oidc_google@example.org'),
+ uid => "hackney:example_client_id:my_google_user_id",
+ mock => 't::Mock::OpenIDConnect',
+ mock_hosts => ['oidc.example.org'],
+ host => 'oidc.example.org',
+ error_callback => '/auth/OIDC?error=ERROR',
+ success_callback => '/auth/OIDC?code=response-code&state=login',
+ redirect_pattern => qr{oidc\.example\.org/oauth2/v2\.0/authorize_google},
+ pc => 'E8 1DY',
+ # Need to use a different report that's within Hackney
+ report => $report2,
+ report_email => $test_email2,
}
) {
@@ -100,6 +151,7 @@ for my $state ( 'refused', 'no email', 'existing UID', 'okay' ) {
next if $page eq 'update' && !$test->{update};
subtest "test $test->{type} '$state' login for page '$page'" => sub {
+ my $test_report = $test->{report} || $report;
# Lots of user changes happening here, make sure we don't confuse
# Catalyst with a cookie session user that no longer exists
$mech->log_out_ok;
@@ -115,9 +167,9 @@ for my $state ( 'refused', 'no email', 'existing UID', 'okay' ) {
$mech->delete_user($test->{email});
}
if ($page eq 'my' && $state eq 'existing UID') {
- $report->update({ user_id => FixMyStreet::DB->resultset( 'User' )->find( { email => $test->{email} } )->id });
+ $test_report->update({ user_id => FixMyStreet::DB->resultset( 'User' )->find( { email => $test->{email} } )->id });
} else {
- $report->update({ user_id => FixMyStreet::DB->resultset( 'User' )->find( { email => $test_email } )->id });
+ $test_report->update({ user_id => FixMyStreet::DB->resultset( 'User' )->find( { email => ($report->{test_email} || $test_email) } )->id });
}
# Set up a mock to catch (most, see below) requests to the OAuth API
@@ -139,7 +191,7 @@ for my $state ( 'refused', 'no email', 'existing UID', 'okay' ) {
$mech->get_ok('/my');
} elsif ($page eq 'report') {
$mech->get_ok('/');
- $mech->submit_form_ok( { with_fields => { pc => 'SW1A1AA' } }, "submit location" );
+ $mech->submit_form_ok( { with_fields => { pc => $test->{pc} || 'SW1A1AA' } }, "submit location" );
$mech->follow_link_ok( { text_regex => qr/skip this step/i, }, "follow 'skip this step' link" );
$mech->submit_form(with_fields => {
category => 'Damaged bin',
@@ -150,7 +202,7 @@ for my $state ( 'refused', 'no email', 'existing UID', 'okay' ) {
bin_type => 'Salt bin',
};
} else {
- $mech->get_ok('/report/' . $report->id);
+ $mech->get_ok('/report/' . $test_report->id);
$fields = {
update => 'Test update',
};
@@ -189,7 +241,8 @@ for my $state ( 'refused', 'no email', 'existing UID', 'okay' ) {
$mech->content_contains('We need your email address, please give it below.');
# We don't have an email, so check that we can still submit it,
# and the ID carries through the confirmation
- $fields->{username} = $test->{email};
+ $fields->{username} = $test->{email} if $page eq 'my';
+ $fields->{username_register} = $test->{email} unless $page eq 'my';
$fields->{name} = 'Ffion Tester' unless $page eq 'my';
$mech->submit_form(with_fields => $fields, $page eq 'my' ? (button => 'sign_in_by_code') : ());
$mech->content_contains('Nearly done! Now check your email');
@@ -243,17 +296,17 @@ for my $state ( 'refused', 'no email', 'existing UID', 'okay' ) {
}
}
if ($state eq 'existing UID') {
- my $report_id = $report->id;
- $mech->content_contains( $report->title );
+ my $report_id = $test_report->id;
+ $mech->content_contains( $test_report->title );
$mech->content_contains( "/report/$report_id" );
}
- if ($test->{type} eq 'oidc') {
+ if ($test->{type} eq 'oidc' && $test->{password_change_pattern}) {
ok $mech->find_link( text => 'Change password', url_regex => $test->{password_change_pattern} );
}
}
$mech->get('/auth/sign_out');
- if ($test->{type} eq 'oidc' && $state ne 'refused' && $state ne 'no email') {
+ if ($test->{type} eq 'oidc' && $test->{logout_redirect_pattern} && $state ne 'refused' && $state ne 'no email') {
# XXX the 'no email' situation is skipped because of some confusion
# with the hosts/sessions that I've not been able to get to the bottom of.
# The code does behave as expected when testing manually, however.
@@ -356,7 +409,8 @@ for my $tw_state ( 'refused', 'existing UID', 'no email' ) {
$mech->content_contains('We need your email address, please give it below.');
# We don't have an email, so check that we can still submit it,
# and the ID carries through the confirmation
- $fields->{username} = $tw_email;
+ $fields->{username_register} = $tw_email unless $page eq 'my';
+ $fields->{username} = $tw_email if $page eq 'my';
$fields->{name} = 'Ffion Tester' unless $page eq 'my';
$mech->submit_form(with_fields => $fields, $page eq 'my' ? (button => 'sign_in_by_code') : ());
$mech->content_contains('Nearly done! Now check your email');
diff --git a/t/app/controller/contact.t b/t/app/controller/contact.t
index d6e56e7cc..01e8b0886 100644
--- a/t/app/controller/contact.t
+++ b/t/app/controller/contact.t
@@ -382,7 +382,7 @@ for my $test (
$mech->clear_emails_ok;
$mech->get_ok('/contact');
- $test->{fields}{em} = $user->email;
+ $test->{fields}{em} = ucfirst $user->email; # Check case
$mech->submit_form_ok( { with_fields => $test->{fields} } );
my $email = $mech->get_email;
diff --git a/t/app/controller/contact_enquiry.t b/t/app/controller/contact_enquiry.t
index af249ec6c..f1b5b15cd 100644
--- a/t/app/controller/contact_enquiry.t
+++ b/t/app/controller/contact_enquiry.t
@@ -40,9 +40,18 @@ my $contact4 = $mech->create_contact_ok(
category => 'Carriageway Defect',
email => 'potholes@example.com',
);
+my $contact5 = $mech->create_contact_ok(
+ body_id => $body->id,
+ category => 'Other (disabled)',
+ email => 'other@example.com',
+);
$contact->update( { extra => { group => 'General Enquiries' } } );
$contact2->update( { extra => { group => 'General Enquiries' } } );
$contact3->update( { extra => { group => 'Other' } } );
+$contact5->update( { extra => { group => 'Other' } } );
+
+$contact5->push_extra_fields({ code => '_fms_disable_', 'disable_form' => 'true', description => 'form_disabled' });
+$contact5->update;
FixMyStreet::override_config { ALLOWED_COBRANDS => ['bromley'], }, sub {
subtest 'redirected to / if general enquiries not enabled' => sub {
@@ -60,6 +69,7 @@ FixMyStreet::override_config {
subtest 'Non-general enquiries category not shown' => sub {
$mech->get_ok( '/contact/enquiry' );
$mech->content_lacks('Carriageway Defect');
+ $mech->content_lacks('Other (disabled)');
$mech->content_contains('FOI Request');
};
@@ -70,7 +80,7 @@ FixMyStreet::override_config {
$mech->submit_form_ok( {
with_fields => {
name => 'Test User',
- username => 'testuser@example.org',
+ username_register => 'testuser@example.org',
category => 'Other',
detail => 'This is a general enquiry',
}
@@ -139,7 +149,7 @@ FixMyStreet::override_config {
$mech->submit_form_ok( {
with_fields => {
name => 'Simon Neil',
- username => $user->email,
+ username_register => $user->email,
category => 'General Enquiry',
detail => 'This is a general enquiry',
}
@@ -202,7 +212,7 @@ FixMyStreet::override_config {
submit_problem => 1,
token => $csrf,
name => 'Test User',
- username => 'testuser@example.org',
+ username_register => 'testuser@example.org',
category => 'Other',
detail => encode_utf8('This is a general enquiry‽'),
photo1 => [ $sample_jpeg, undef, Content_Type => 'image/jpeg' ],
diff --git a/t/app/controller/dashboard.t b/t/app/controller/dashboard.t
index 72fc00128..fd491b540 100644
--- a/t/app/controller/dashboard.t
+++ b/t/app/controller/dashboard.t
@@ -20,6 +20,8 @@ use strict;
use warnings;
use FixMyStreet::TestMech;
+use File::Temp 'tempdir';
+use Path::Tiny;
use Web::Scraper;
set_absolute_time('2014-02-01T12:00:00');
@@ -70,6 +72,7 @@ foreach my $problem (@fixed_problems) {
foreach my $problem (@closed_problems) {
$problem->update({ state => 'closed' });
+ $mech->create_comment_for_problem($problem, $counciluser, 'Name', 'in progress text', 0, 'confirmed', 'in progress');
$mech->create_comment_for_problem($problem, $counciluser, 'Title', 'text', 0, 'confirmed', 'closed');
}
@@ -80,9 +83,15 @@ my $categories = scraper {
},
};
+my $UPLOAD_DIR = tempdir( CLEANUP => 1 );
+
FixMyStreet::override_config {
ALLOWED_COBRANDS => 'no2fa',
+ COBRAND_FEATURES => { category_groups => { no2fa => 1 } },
MAPIT_URL => 'http://mapit.uk/',
+ PHOTO_STORAGE_OPTIONS => {
+ UPLOAD_DIR => $UPLOAD_DIR,
+ },
}, sub {
subtest 'not logged in, redirected to login' => sub {
@@ -173,13 +182,14 @@ FixMyStreet::override_config {
subtest 'export as csv' => sub {
$mech->create_problems_for_body(1, $body->id, 'Title', {
detail => "this report\nis split across\nseveral lines",
+ category => 'Problem one',
areas => ",$alt_area_id,2651,",
});
$mech->get_ok('/dashboard?export=1');
my @rows = $mech->content_as_csv;
is scalar @rows, 19, '1 (header) + 18 (reports) = 19 lines';
- is scalar @{$rows[0]}, 20, '20 columns present';
+ is scalar @{$rows[0]}, 21, '21 columns present';
is_deeply $rows[0],
[
@@ -188,6 +198,7 @@ FixMyStreet::override_config {
'Detail',
'User Name',
'Category',
+ 'Subcategory',
'Created',
'Confirmed',
'Acknowledged',
@@ -206,15 +217,15 @@ FixMyStreet::override_config {
],
'Column headers look correct';
- is $rows[5]->[14], 'Trowbridge', 'Ward column is name not ID';
- is $rows[5]->[15], '529025', 'Correct Easting conversion';
- is $rows[5]->[16], '179716', 'Correct Northing conversion';
+ is $rows[5]->[15], 'Trowbridge', 'Ward column is name not ID';
+ is $rows[5]->[16], '529025', 'Correct Easting conversion';
+ is $rows[5]->[17], '179716', 'Correct Northing conversion';
};
subtest 'export updates as csv' => sub {
$mech->get_ok('/dashboard?updates=1&export=1');
my @rows = $mech->content_as_csv;
- is scalar @rows, 15, '1 (header) + 14 (updates) = 15 lines';
+ is scalar @rows, 18, '1 (header) + 17 (updates) = 18 lines';
is scalar @{$rows[0]}, 8, '8 columns present';
is_deeply $rows[0],
@@ -235,19 +246,50 @@ FixMyStreet::override_config {
subtest 'export as csv using token' => sub {
$mech->log_out_ok;
- $counciluser->set_extra_metadata('access_token', '1234567890abcdefgh');
+ my $u = FixMyStreet::DB->resultset("User")->new({ password => '1234567890abcdefgh' });
+ $counciluser->set_extra_metadata('access_token', $u->password);
$counciluser->update();
$mech->get_ok('/dashboard?export=1');
like $mech->res->header('Content-type'), qr'text/html';
$mech->content_lacks('Report ID');
- $mech->add_header('Authorization', 'Bearer 1234567890abcdefgh');
+ $mech->add_header('Authorization', 'Bearer ' . $counciluser->id . '-1234567890abcdefgh');
$mech->get_ok('/dashboard?export=1');
like $mech->res->header('Content-type'), qr'text/csv';
$mech->content_contains('Report ID');
$mech->delete_header('Authorization');
+
+ my $token = 'access_token=' . $counciluser->id . '-1234567890abcdefgh';
+ $mech->get_ok("/dashboard?export=2&$token");
+ is $mech->res->code, 202;
+ my $loc = $mech->res->header('Location');
+ like $loc, qr{/dashboard/csv/.*\.csv$};
+ $mech->get_ok("$loc?$token");
+ like $mech->res->header('Content-type'), qr'text/csv';
+ $mech->content_contains('Report ID');
};
+
+ subtest 'view status page' => sub {
+ # Simulate a partly done file
+ my $f = Path::Tiny->tempfile(SUFFIX => '.csv-part', DIR => path($UPLOAD_DIR, 'dashboard_csv', $counciluser->id));
+ (my $name = $f->basename) =~ s/-part$//;;
+
+ my $token = 'access_token=' . $counciluser->id . '-1234567890abcdefgh';
+ $mech->get_ok("/dashboard/csv/$name?$token");
+ is $mech->res->code, 202;
+
+ $mech->log_in_ok( $counciluser->email );
+ $mech->get_ok('/dashboard/status');
+ $mech->content_contains('/dashboard/csv/www.example.org-body-' . $body->id . '-start_date-2014-01-02.csv');
+ $mech->content_like(qr/$name\s*<br>0KB\s*<i>In progress/);
+
+ $f->remove;
+ $mech->get_ok('/dashboard/status');
+ $mech->content_contains('/dashboard/csv/www.example.org-body-' . $body->id . '-start_date-2014-01-02.csv');
+ $mech->content_lacks('In progress');
+ $mech->content_lacks('setTimeout');
+ }
};
FixMyStreet::override_config {
diff --git a/t/app/controller/moderate.t b/t/app/controller/moderate.t
index 8e84bd392..43ae1c980 100644
--- a/t/app/controller/moderate.t
+++ b/t/app/controller/moderate.t
@@ -51,7 +51,7 @@ sub create_report {
longitude => '0.007831',
user_id => $user2->id,
photo => '74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg',
- extra => { moon => 'waxing full' },
+ extra => { moon => 'waxing full', sent_to => [ 'authority@example.org' ] },
});
}
my $report = create_report();
@@ -115,6 +115,7 @@ subtest 'Problem moderation' => sub {
}});
$mech->base_like( qr{\Q$REPORT_URL\E} );
$mech->content_like(qr/Moderated by Bromley Council/);
+ $mech->content_lacks('sent_to = ARRAY(0x');
$report->discard_changes;
is $report->title, 'Good good';
diff --git a/t/app/controller/my.t b/t/app/controller/my.t
index 673addf0c..85902ae1a 100644
--- a/t/app/controller/my.t
+++ b/t/app/controller/my.t
@@ -14,17 +14,12 @@ my $other_user = FixMyStreet::DB->resultset('User')->find_or_create({ email => '
my @other = $mech->create_problems_for_body(1, 1234, 'Another Title', { user => $other_user });
my $user = $mech->log_in_ok( 'test@example.com' );
-$mech->get_ok('/my');
-is $mech->uri->path, '/my', "stayed on '/my' page";
-
-$mech->content_contains('Test Title');
-$mech->content_lacks('Another Title');
-
my @update;
my $i = 0;
+my $staff_text = '<p>this is <script>how did this happen</script> <strong>an update</strong></p><ul><li>With</li><li>A</li><li>List</li></ul>';
foreach ($user, $user, $other_user) {
$update[$i] = FixMyStreet::DB->resultset('Comment')->create({
- text => 'this is an update',
+ text => $staff_text,
user => $_,
state => 'confirmed',
problem => $problems[0],
@@ -35,6 +30,20 @@ foreach ($user, $user, $other_user) {
$i++;
}
+subtest 'Check loading of /my page' => sub {
+ $mech->get_ok('/my');
+ is $mech->uri->path, '/my', "stayed on '/my' page";
+
+ $mech->content_contains('Test Title');
+ $mech->content_lacks('Another Title');
+ $mech->content_contains('&lt;p&gt;this is');
+ $mech->content_lacks('<p>this is <strong>an update</strong></p><ul><li>With');
+
+ $update[0]->update({ extra => { is_superuser => 1 } });
+ $mech->get_ok('/my');
+ $mech->content_contains('<p>this is <strong>an update</strong></p><ul><li>With');
+};
+
foreach (
{ type => 'problem', id => 0, result => 404, desc => 'nothing' },
{ type => 'problem', obj => $problems[0], result => 200, desc => 'own report' },
diff --git a/t/app/controller/offline.t b/t/app/controller/offline.t
index 876475264..d48af676f 100644
--- a/t/app/controller/offline.t
+++ b/t/app/controller/offline.t
@@ -54,6 +54,7 @@ FixMyStreet::override_config {
subtest 'service worker' => sub {
$mech->get_ok('/service-worker.js');
+ is $mech->res->header('Cache-Control'), 'max-age=0', 'service worker is not cached';
$mech->content_contains('translation_strings');
$mech->content_contains('offline/fallback');
};
diff --git a/t/app/controller/questionnaire.t b/t/app/controller/questionnaire.t
index b561b271a..592507288 100644
--- a/t/app/controller/questionnaire.t
+++ b/t/app/controller/questionnaire.t
@@ -351,7 +351,7 @@ my $comment = FixMyStreet::DB->resultset('Comment')->find_or_create(
user_id => $user->id,
name => 'A User',
mark_fixed => 'false',
- text => 'This is some update text',
+ text => 'This is some <strong>update</strong> text',
state => 'confirmed',
confirmed => $sent_time,
anonymous => 'f',
@@ -360,7 +360,12 @@ my $comment = FixMyStreet::DB->resultset('Comment')->find_or_create(
subtest 'Check updates are shown correctly on questionnaire page' => sub {
$mech->get_ok("/Q/" . $token->token);
$mech->content_contains( 'Show all updates' );
- $mech->content_contains( 'This is some update text' );
+ $mech->content_contains( 'This is some &lt;strong&gt;update&lt;/strong&gt; text' );
+};
+subtest 'Check staff update is shown correctly on questionnaire page' => sub {
+ $comment->update({ extra => { is_superuser => 1 } });
+ $mech->get_ok("/Q/" . $token->token);
+ $mech->content_contains( 'This is some <strong>update</strong> text' );
};
for my $test (
diff --git a/t/app/controller/report_display.t b/t/app/controller/report_display.t
index 4bd0fc991..00c7bf19b 100644
--- a/t/app/controller/report_display.t
+++ b/t/app/controller/report_display.t
@@ -109,7 +109,7 @@ subtest "test a good report" => sub {
my %fields = (
name => '',
- username => '',
+ username_register => '',
update => '',
add_alert => 1, # defaults to true
fixed => undef
diff --git a/t/app/controller/report_import.t b/t/app/controller/report_import.t
index b2e15330a..7b5ede7a9 100644
--- a/t/app/controller/report_import.t
+++ b/t/app/controller/report_import.t
@@ -376,7 +376,7 @@ subtest "Submit a correct entry (with location) to cobrand" => sub {
photo2 => '',
photo3 => '',
phone => '',
- username => 'test-ll@example.com',
+ username_register => 'test-ll@example.com',
},
"check imported fields are shown"
or diag Dumper( $mech->visible_form_values ); use Data::Dumper;
diff --git a/t/app/controller/report_inspect.t b/t/app/controller/report_inspect.t
index 8deb2667e..3f267a086 100644
--- a/t/app/controller/report_inspect.t
+++ b/t/app/controller/report_inspect.t
@@ -1,5 +1,6 @@
use FixMyStreet::TestMech;
use Test::MockModule;
+use Path::Class;
my $mech = FixMyStreet::TestMech->new;
@@ -7,7 +8,7 @@ my $brum = $mech->create_body_ok(2514, 'Birmingham City Council');
my $oxon = $mech->create_body_ok(2237, 'Oxfordshire County Council', { can_be_devolved => 1 } );
my $contact = $mech->create_contact_ok( body_id => $oxon->id, category => 'Cows', email => 'cows@example.net' );
my $contact2 = $mech->create_contact_ok( body_id => $oxon->id, category => 'Sheep', email => 'SHEEP', send_method => 'Open311' );
-my $contact3 = $mech->create_contact_ok( body_id => $oxon->id, category => 'Badgers', email => 'badgers@example.net' );
+my $contact3 = $mech->create_contact_ok( body_id => $oxon->id, category => 'Badgers & Voles', email => 'badgers@example.net' );
my $rp = FixMyStreet::DB->resultset("ResponsePriority")->create({
body => $oxon,
name => 'High Priority',
@@ -16,6 +17,11 @@ my $rp2 = FixMyStreet::DB->resultset("ResponsePriority")->create({
body => $oxon,
name => 'Low Priority',
});
+my $rp3 = FixMyStreet::DB->resultset("ResponsePriority")->create({
+ body => $oxon,
+ name => 'Deleted Priority',
+ deleted => 1,
+});
FixMyStreet::DB->resultset("ContactResponsePriority")->create({
contact => $contact,
response_priority => $rp,
@@ -42,6 +48,9 @@ my $user = $mech->log_in_ok('body@example.com');
$user->set_extra_metadata('categories', [ $contact->id ]);
$user->update( { from_body => $oxon } );
+my $sample_file = file(__FILE__)->parent->file("sample.jpg")->stringify;
+ok -e $sample_file, "sample file $sample_file exists";
+
FixMyStreet::override_config {
MAPIT_URL => 'http://mapit.uk/',
ALLOWED_COBRANDS => 'fixmystreet',
@@ -51,15 +60,15 @@ FixMyStreet::override_config {
$mech->content_lacks('Save changes');
$mech->content_lacks('Private');
$mech->content_lacks('Priority');
- $mech->content_lacks('Traffic management');
+ $mech->content_lacks('Change asset');
$mech->content_lacks('/admin/report_edit/'.$report_id.'">admin</a>)');
$user->user_body_permissions->create({ body => $oxon, permission_type => 'report_mark_private' });
$mech->get_ok("/report/$report_id");
$mech->content_contains('Private');
$mech->content_contains('Save changes');
+ $mech->content_lacks('Change asset');
$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' });
@@ -67,7 +76,7 @@ FixMyStreet::override_config {
$mech->content_contains('Private');
$mech->content_contains('Save changes');
$mech->content_contains('Priority');
- $mech->content_lacks('Traffic management');
+ $mech->content_lacks('Change asset');
$mech->content_lacks('/admin/report_edit/'.$report_id.'">admin</a>)');
$user->user_body_permissions->create({ body => $oxon, permission_type => 'report_inspect' });
@@ -75,7 +84,7 @@ FixMyStreet::override_config {
$mech->content_contains('Save changes');
$mech->content_contains('Private');
$mech->content_contains('Priority');
- $mech->content_contains('Traffic management');
+ $mech->content_contains('Change asset');
$mech->content_lacks('/admin/report_edit/'.$report_id.'">admin</a>)');
};
@@ -197,14 +206,14 @@ FixMyStreet::override_config {
$user->user_body_permissions->create({ body => $oxon, permission_type => 'report_inspect' });
$mech->get_ok("/report/$report_id");
- $mech->submit_form_ok({ button => 'save', with_fields => { traffic_information => 'Yes', state => 'Action scheduled', include_update => undef } });
+ $mech->submit_form_ok({ button => 'save', with_fields => { detailed_information => 'Info', state => 'Action scheduled', include_update => undef } });
$report->discard_changes;
my $alert = FixMyStreet::DB->resultset('Alert')->find(
{ user => $user, alert_type => 'new_updates', confirmed => 1, }
);
is $report->state, 'action scheduled', 'report state changed';
- is $report->get_extra_metadata('traffic_information'), 'Yes', 'report data changed';
+ is $report->get_extra_metadata('detailed_information'), 'Info', 'report data changed';
ok defined( $alert ) , 'sign up for alerts';
};
@@ -233,7 +242,7 @@ FixMyStreet::override_config {
$user->update;
};
- subtest "test update is required when instructing" => sub {
+ subtest "test public update is required if include_update is checked" => sub {
$report->update;
$report->comments->delete_all;
$mech->get_ok("/report/$report_id");
@@ -439,6 +448,7 @@ FixMyStreet::override_config {
subtest "default response priorities display correctly" => sub {
$mech->get_ok("/report/$report_id");
$mech->content_contains('Priority</label', 'report priority list present');
+ $mech->content_lacks('Deleted Priority');
like $mech->content, qr/<select name="priority" id="problem_priority" class="form-control">[^<]*<option value="" selecte/s, 'blank priority option is selected';
$mech->content_lacks('value="' . $rp->id . '" selected>High', 'non default priority not selected');
@@ -448,6 +458,12 @@ FixMyStreet::override_config {
$mech->content_contains('value="' . $rp->id . '" selected>High', 'default priority selected');
};
+ subtest "check when report has deleted priority" => sub {
+ $report->update({ response_priority => $rp3 });
+ $mech->get_ok("/report/$report_id");
+ $mech->content_contains('value="' . $rp3->id . '" selected>Deleted Priority');
+ };
+
foreach my $test (
{ type => 'report_edit_priority', priority => 1 },
{ type => 'report_edit_category', category => 1 },
@@ -589,7 +605,27 @@ FixMyStreet::override_config {
$mech->get_ok("/report/$report_id");
$mech->content_contains('Nearest calculated address', 'Address displayed');
$mech->content_contains('Constitution Hill, London, SW1A', 'Correct address displayed');
- }
+ };
+
+ subtest "test upload photo with public updates" => sub {
+ $user->user_body_permissions->delete;
+ $user->user_body_permissions->create({ body => $oxon, permission_type => 'report_inspect' });
+
+ $report->state('confirmed');
+ $report->update;
+ $mech->get_ok("/report/$report_id");
+ $mech->submit_form_ok({ button => 'save', with_fields => {
+ public_update => "This is a public update.", include_update => "1",
+ state => 'action scheduled',
+ photo1 => [ [ $sample_file, undef, Content_Type => 'image/jpeg' ], 1 ],
+ } });
+ $report->discard_changes;
+ my $comment = $report->comments(undef, { rows => 1, order_by => { -desc => "id" }})->first;
+ is $comment->photo, '74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg', 'photo added to comment';
+ $mech->get_ok("/report/$report_id");
+ $mech->content_contains("/photo/c/" . $comment->id . ".0.jpeg");
+ };
+
};
foreach my $test (
@@ -663,15 +699,6 @@ FixMyStreet::override_config {
return $perms;
});
- subtest "Oxfordshire-specific traffic management options are shown" => sub {
- $report->update({ state => 'confirmed' });
- $mech->get_ok("/report/$report_id");
- $mech->submit_form_ok({ button => 'save', with_fields => { traffic_information => 'Signs and Cones', state => 'Action scheduled', include_update => undef } });
- $report->discard_changes;
- is $report->state, 'action scheduled', 'report state changed';
- 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' });
@@ -683,19 +710,20 @@ FixMyStreet::override_config {
FixMyStreet::override_config {
MAPIT_URL => 'http://mapit.uk/',
- ALLOWED_COBRANDS => 'fixmystreet',
+ ALLOWED_COBRANDS => 'oxfordshire',
}, sub {
subtest "test category not updated if fail to include public update" => sub {
$mech->get_ok("/report/$report_id");
- $mech->submit_form(button => 'save', with_fields => { category => 'Badgers' });
+ $mech->submit_form(button => 'save', with_fields => { category => 'Badgers & Voles' });
$report->discard_changes;
is $report->category, "Cows", "Report in correct category";
- $mech->content_contains('Badgers" selected', 'Changed category still selected');
+ $mech->content_contains('Badgers &amp; Voles" selected', 'Changed category still selected');
};
subtest "test invalid form maintains Category and priority" => sub {
$mech->get_ok("/report/$report_id");
+ $mech->content_like(qr/data-priorities='[^']*?Low Priority/);
my $expected_fields = {
state => 'action scheduled',
category => 'Cows',
@@ -704,14 +732,16 @@ FixMyStreet::override_config {
priority => $rp->id,
include_update => '1',
detailed_information => 'XXX164XXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
- traffic_information => ''
+ photo1 => '',
+ photo2 => '',
+ photo3 => '',
};
my $values = $mech->visible_form_values('report_inspect_form');
is_deeply $values, $expected_fields, 'correct form fields present';
- $mech->submit_form(button => 'save', with_fields => { category => 'Badgers', priority => $rp2->id });
+ $mech->submit_form(button => 'save', with_fields => { category => 'Badgers & Voles', priority => $rp2->id });
- $expected_fields->{category} = 'Badgers';
+ $expected_fields->{category} = 'Badgers & Voles';
$expected_fields->{priority} = $rp2->id;
my $new_values = $mech->visible_form_values('report_inspect_form');
@@ -724,15 +754,15 @@ FixMyStreet::override_config {
$mech->submit_form(
button => 'save',
with_fields => {
- category => 'Badgers',
+ category => 'Badgers & Voles',
include_update => 1,
public_update => 'This is a public update',
});
$report->discard_changes;
- is $report->category, "Badgers", "Report in correct category";
+ is $report->category, "Badgers & Voles", "Report in correct category";
is $report->comments->count, 1, "Only leaves one update";
- like $report->comments->first->text, qr/Category changed.*Badgers/, 'update text included category change';
+ like $report->comments->first->text, qr/Category changed.*Badgers & Voles/, 'update text included category change';
};
subtest "test non-public changing" => sub {
@@ -779,10 +809,10 @@ FixMyStreet::override_config {
});
subtest "test report not resent when category changes if send_method doesn't change" => sub {
$mech->get_ok("/report/$report3_id");
- $mech->submit_form(button => 'save', with_fields => { category => 'Badgers', include_update => undef, });
+ $mech->submit_form(button => 'save', with_fields => { category => 'Badgers & Voles', include_update => undef, });
$report3->discard_changes;
- is $report3->category, "Badgers", "Report in correct category";
+ is $report3->category, "Badgers & Voles", "Report in correct category";
isnt $report3->whensent, undef, "Report not marked as unsent";
is $report3->bodies_str, $oxon->id, "Reported to OCC";
};
@@ -822,7 +852,91 @@ FixMyStreet::override_config {
};
};
+FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => 'oxfordshire',
+}, sub {
+ subtest 'test relevant staff user display' => sub {
+ $user->user_body_permissions->create({ body => $oxon, permission_type => 'planned_reports' });
+ $user->user_body_permissions->create({ body => $oxon, permission_type => 'moderate' });
+ $mech->log_in_ok('body@example.com');
-END {
- done_testing();
-}
+ # First, check user can see staff things on reports 2 and 3
+ $mech->get_ok("/report/$report2_id");
+ $mech->content_contains('<select class="form-control" name="state" id="state">');
+ $mech->content_contains('<div class="inspect-section">');
+ $mech->get_ok("/report/$report3_id");
+ $mech->content_contains('<select class="form-control" name="state" id="state">');
+ $mech->content_contains('<div class="inspect-section">');
+
+ # User's categories are ["Cows"], which is currently report 2
+ # So should be able to see staff things on 2, but no longer on 3
+ $user->set_extra_metadata(assigned_categories_only => 1);
+ $user->update;
+ $mech->get_ok("/report/$report2_id");
+ $mech->content_contains('<select class="form-control" name="state" id="state">');
+ $mech->content_contains('<div class="inspect-section">');
+ $mech->get_ok("/report/$report3_id");
+ $mech->content_lacks('<select class="form-control" name="state" id="state">');
+ $mech->content_lacks('<div class="inspect-section">');
+ $mech->content_lacks('Moderate this report');
+ $mech->content_lacks('shortlist');
+ $user->unset_extra_metadata('assigned_categories_only');
+ $user->update;
+
+ # Contact 2 is "Sheep", which is currently report 3
+ # So again, should be able to see staff things on 2, but no longer on 3
+ $contact2->set_extra_metadata(assigned_users_only => 1);
+ $contact2->update;
+ $mech->get_ok("/report/$report2_id");
+ $mech->content_contains('<select class="form-control" name="state" id="state">');
+ $mech->content_contains('<div class="inspect-section">');
+ $mech->get_ok("/report/$report3_id");
+ $mech->content_lacks('<select class="form-control" name="state" id="state">');
+ $mech->content_lacks('<div class="inspect-section">');
+ $mech->content_lacks('Moderate this report');
+ $mech->content_lacks('shortlist');
+ $contact2->unset_extra_metadata('assigned_users_only');
+ $contact2->update;
+ };
+
+ subtest 'instruct defect' => sub {
+ $user->user_body_permissions->create({ body => $oxon, permission_type => 'report_instruct' });
+ $mech->get_ok("/report/$report2_id");
+ $mech->submit_form_ok({ button => 'save', with_fields => {
+ public_update => "This is a public update.", include_update => "1",
+ traffic_information => 'Signs and cones',
+ state => 'action scheduled', raise_defect => 1,
+ defect_item_category => 'Kerbing',
+ } });
+ $report2->discard_changes;
+ is $report2->get_extra_metadata('inspected'), 1, 'report marked as inspected';
+ $mech->get_ok("/report/$report2_id");
+ $mech->content_like(qr/Defect category<\/dt>\s*<dd>Kerbing/);
+ my $meta = $mech->extract_update_metas;
+ like $meta->[0], qr/State changed to: Action scheduled/, 'First update mentions action scheduled';
+ like $meta->[1], qr/Posted by .*defect raised/, 'Update mentions defect raised';
+ my $log_entry = $report2->inspection_log_entry;
+ is $log_entry->object_id, $report2_id, 'Log entry has correct ID';
+ is $log_entry->object_type, 'problem', 'Log entry has correct type';
+ is $log_entry->action, 'inspected', 'Log entry has correct action';
+ };
+
+ subtest "test update is required when instructing defect" => sub {
+ $report2->unset_extra_metadata('inspected');
+ $report2->update;
+ $report2->inspection_log_entry->delete;
+ $report2->comments->delete_all;
+ $mech->get_ok("/report/$report2_id");
+ $mech->submit_form_ok({ button => 'save', with_fields => {
+ public_update => "", include_update => "0",
+ state => 'action scheduled', raise_defect => 1,
+ } });
+ is_deeply $mech->page_errors, [ "Please provide a public update for this report." ], 'errors match';
+ $report2->discard_changes;
+ is $report2->comments->count, 0, "Update wasn't created";
+ is $report2->get_extra_metadata('inspected'), undef, 'report not marked as inspected';
+ };
+};
+
+done_testing();
diff --git a/t/app/controller/report_new.t b/t/app/controller/report_new.t
index d2da75f2c..77eb4fefb 100644
--- a/t/app/controller/report_new.t
+++ b/t/app/controller/report_new.t
@@ -149,14 +149,14 @@ foreach my $test (
$mech->submit_form_ok(
{
- button => 'submit_register',
+ button => 'submit_register_mobile',
with_fields => {
title => 'Test Report',
detail => 'Test report details.',
photo1 => '',
name => 'Joe Bloggs',
may_show_name => '1',
- username => 'test-1@example.com',
+ username_register => 'test-1@example.com',
phone => '07903 123 456',
category => 'Street lighting',
password_register => $test->{password} ? 'secret' : '',
@@ -641,10 +641,10 @@ subtest "category groups" => sub {
}
}, sub {
$contact2->update( { extra => { group => ['Roads','Pavements'] } } );
- $contact9->update( { extra => { group => 'Roads' } } );
+ $contact9->update( { extra => { group => 'Pavements' } } );
$contact10->update( { extra => { group => 'Roads' } } );
$mech->get_ok("/report/new?lat=$saved_lat&lon=$saved_lon");
- $mech->content_like(qr{<optgroup label="Pavements">\s*<option value='Potholes'>Potholes</option></optgroup>});
+ $mech->content_like(qr{<optgroup label="Pavements">\s*<option value='Potholes'>Potholes</option>\s*<option value='Street lighting'>Street lighting</option></optgroup>});
$mech->content_like(qr{<optgroup label="Roads">\s*<option value='Potholes'>Potholes</option>\s*<option value='Street lighting'>Street lighting</option></optgroup>});
};
};
@@ -680,7 +680,7 @@ subtest "test report creation for a category that is non public" => sub {
title => 'Test Report',
detail => 'Test report details.',
photo1 => '',
- username => $user->email,
+ username_register => $user->email,
name => 'Joe Bloggs',
category => 'Street lighting',
}
@@ -940,7 +940,7 @@ for my $test (
title => "Test Report",
detail => 'Test report details.',
photo1 => '',
- username => 'firstlast@example.com',
+ username_register => 'firstlast@example.com',
may_show_name => '1',
phone => '07903 123 456',
category => 'Trees',
@@ -1085,7 +1085,7 @@ subtest "test Hart" => sub {
$mech->submit_form_ok( { with_fields => { pc => 'GU51 4AE' } }, "submit location" );
$mech->follow_link_ok( { text_regex => qr/skip this step/i, }, "follow 'skip this step' link" );
my %optional_fields = $test->{confirm} ? () :
- ( username => $test_email, phone => '07903 123 456' );
+ ( username_register => $test_email, phone => '07903 123 456' );
# we do this as otherwise test::www::mechanize::catalyst
# goes to the value set in ->host above irregardless and
@@ -1279,7 +1279,7 @@ subtest "extra google analytics code displayed on email confirmation problem cre
title => "Test Report",
detail => 'Test report details.',
photo1 => '',
- username => 'firstlast@example.com',
+ username_register => 'firstlast@example.com',
name => 'Test User',
may_show_name => '1',
phone => '07903 123 456',
diff --git a/t/app/controller/report_new_anon.t b/t/app/controller/report_new_anon.t
index d86bc8134..cba360f05 100644
--- a/t/app/controller/report_new_anon.t
+++ b/t/app/controller/report_new_anon.t
@@ -17,6 +17,14 @@ sub allow_anonymous_reports {
}
sub anonymous_account { { email => 'anoncategory@example.org', name => 'Anonymous Category' } }
+package FixMyStreet::Cobrand::AnonAllowedByCategory;
+use parent 'FixMyStreet::Cobrand::UKCouncils';
+sub council_url { 'anonbycategory' }
+sub council_name { 'Edinburgh City Council' }
+sub council_area { 'Edinburgh' }
+sub council_area_id { 2651 }
+sub anonymous_account { { email => 'anoncategory@example.org', name => 'Anonymous Category' } }
+
package main;
use FixMyStreet::TestMech;
@@ -269,4 +277,71 @@ subtest "test report creation anonymously by button, per category" => sub {
};
+$contact2->set_extra_metadata( anonymous_allowed => 1 );
+$contact2->update;
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'anonallowedbycategory',
+ MAPIT_URL => 'http://mapit.uk/',
+}, sub {
+
+subtest "test report creation anonymously by button, per category from metadata" => sub {
+ $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_category_part_only',
+ with_fields => {
+ category => 'Street lighting',
+ }
+ }, "submit category with no anonymous reporting");
+ $mech->content_lacks('<button name="report_anonymously" value="yes" class="btn btn--block">'); # non-JS button, JS button always there
+ $mech->submit_form_ok({
+ button => 'submit_register',
+ with_fields => {
+ category => 'Trees',
+ }
+ }, "submit category with anonymous reporting");
+
+ $mech->submit_form_ok({
+ button => 'report_anonymously',
+ with_fields => {
+ title => 'Test Report',
+ detail => 'Test report details.',
+ }
+ }, "submit good details");
+ $mech->content_contains('Your issue is on its way to the council');
+
+ my $report = FixMyStreet::DB->resultset("Problem")->search({}, { order_by => { -desc => 'id' } })->first;
+ ok $report, "Found the report";
+
+ is $report->state, 'confirmed', "report confirmed";
+ is $report->bodies_str, $body->id;
+ is $report->name, 'Anonymous Category';
+ is $report->anonymous, 1; # Doesn't change behaviour here, but uses anon account's name always
+ is $report->get_extra_metadata('contributed_as'), 'anonymous_user';
+};
+
+};
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ { fixmystreet => '.' } ],
+ BASE_URL => 'https://www.fixmystreet.com',
+ MAPIT_URL => 'http://mapit.uk/',
+}, sub {
+subtest "test anonymously by button, per category from metadata limited to cobrand" => sub {
+ $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_category_part_only',
+ with_fields => {
+ category => 'Trees',
+ }
+ }, "submit category with no anonymous reporting");
+ $mech->content_lacks('<button name="report_anonymously" value="yes" class="btn btn--block">'); # non-JS button, JS button always there
+};
+
+};
+
done_testing();
diff --git a/t/app/controller/report_new_errors.t b/t/app/controller/report_new_errors.t
index f45f13c1e..470cb7d79 100644
--- a/t/app/controller/report_new_errors.t
+++ b/t/app/controller/report_new_errors.t
@@ -112,6 +112,7 @@ foreach my $test (
photo3 => '',
name => '',
may_show_name => '1',
+ username_register => '',
username => '',
phone => '',
password_sign_in => '',
@@ -137,6 +138,7 @@ foreach my $test (
photo3 => '',
name => '',
may_show_name => '1',
+ username_register => '',
username => '',
phone => '',
category => 'Something bad',
@@ -165,6 +167,7 @@ foreach my $test (
photo3 => '',
name => '',
may_show_name => '1',
+ username_register => '',
username => '',
phone => '',
category => 'Street lighting',
@@ -190,6 +193,7 @@ foreach my $test (
photo3 => '',
name => '',
may_show_name => undef,
+ username_register => '',
username => '',
phone => '',
category => 'Street lighting',
@@ -215,6 +219,7 @@ foreach my $test (
photo3 => '',
name => 'Bob Jones',
may_show_name => undef,
+ username_register => '',
username => '',
phone => '',
category => 'Street lighting',
@@ -239,6 +244,7 @@ foreach my $test (
photo3 => '',
name => 'Bob Jones',
may_show_name => '1',
+ username_register => '',
username => '',
phone => '',
category => 'Street lighting',
@@ -263,6 +269,7 @@ foreach my $test (
photo3 => '',
name => 'Bob Jones',
may_show_name => '1',
+ username_register => '',
username => '',
phone => '',
category => 'Street lighting',
@@ -287,6 +294,7 @@ foreach my $test (
photo3 => '',
name => 'DUDE',
may_show_name => '1',
+ username_register => '',
username => '',
phone => '',
category => 'Street lighting',
@@ -310,6 +318,7 @@ foreach my $test (
photo3 => '',
name => 'anonymous',
may_show_name => '1',
+ username_register => '',
username => '',
phone => '',
category => 'Street lighting',
@@ -333,13 +342,14 @@ foreach my $test (
photo3 => '',
name => 'Joe Smith',
may_show_name => '1',
- username => 'not an email',
+ username_register => 'not an email',
+ username => '',
phone => '',
category => 'Street lighting',
password_sign_in => '',
password_register => '',
},
- changes => { username => 'notanemail' },
+ changes => {},
errors => [ 'Please enter a valid email', ],
},
{
@@ -353,6 +363,7 @@ foreach my $test (
photo3 => '',
name => '',
may_show_name => '1',
+ username_register => '',
username => '',
phone => '',
category => 'Street lighting',
@@ -379,7 +390,8 @@ foreach my $test (
photo3 => '',
name => ' Bob Jones ',
may_show_name => '1',
- username => ' BOB @ExAmplE.COM ',
+ username_register => ' BOB @ExAmplE.COM ',
+ username => '',
phone => '',
category => 'Street lighting',
password_sign_in => '',
@@ -387,7 +399,6 @@ foreach my $test (
},
changes => {
name => 'Bob Jones',
- username => 'bob@example.com',
},
errors => [ 'Please enter a subject', 'Please enter some details', ],
},
@@ -402,7 +413,8 @@ foreach my $test (
photo3 => '',
name => 'Bob Jones',
may_show_name => '1',
- username => 'bob@example.com',
+ username_register => 'bob@example.com',
+ username => '',
phone => '',
category => 'Street lighting',
password_sign_in => '',
@@ -424,7 +436,8 @@ foreach my $test (
photo3 => '',
name => 'Bob Jones',
may_show_name => '1',
- username => 'bob@example.com',
+ username_register => 'bob@example.com',
+ username => '',
phone => '',
category => 'Street lighting',
password_sign_in => '',
@@ -446,7 +459,8 @@ foreach my $test (
photo3 => '',
name => 'Bob Jones',
may_show_name => '1',
- username => 'bob@example.com',
+ username_register => 'bob@example.com',
+ username => '',
phone => '',
category => 'Street lighting',
password_sign_in => '',
@@ -468,14 +482,14 @@ foreach my $test (
photo3 => '',
name => 'Joe Smith',
may_show_name => '1',
- username => 'user@example.com',
+ username_register => 'user@example.com',
+ username => '',
phone => '',
category => 'Street lighting',
password_sign_in => '',
password_register => '',
},
changes => {
- username => 'user@example.com',
title => 'User@example.com'
},
errors => [ 'Please make sure you are not including an email address', ],
@@ -492,7 +506,8 @@ foreach my $test (
photo3 => '',
name => 'Bob Example',
may_show_name => '1',
- username => 'bob@example.com',
+ username_register => 'bob@example.com',
+ username => '',
phone => '',
category => 'Trees',
password_sign_in => '',
@@ -512,7 +527,8 @@ foreach my $test (
photo3 => '',
name => 'Bob Example',
may_show_name => '1',
- username => 'bob@example.com',
+ username_register => 'bob@example.com',
+ username => '',
phone => '',
category => 'Trees',
password_sign_in => '',
@@ -532,7 +548,8 @@ foreach my $test (
photo3 => '',
name => 'Bob Example',
may_show_name => '1',
- username => 'bob@example.com',
+ username_register => 'bob@example.com',
+ username => '',
phone => '123456789 12345678910',
category => 'Trees',
password_sign_in => '',
@@ -552,7 +569,8 @@ foreach my $test (
photo3 => '',
name => 'This is a very long name that should fail validation',
may_show_name => '1',
- username => 'bob@example.com',
+ username_register => 'bob@example.com',
+ username => '',
phone => '',
category => 'Street lighting',
password_sign_in => '',
@@ -572,7 +590,8 @@ foreach my $test (
photo3 => '',
name => 'This is a very long name that should fail validation',
may_show_name => '1',
- username => 'bob@example.com',
+ username_register => 'bob@example.com',
+ username => '',
phone => '',
category => 'Trees',
password_sign_in => '',
@@ -592,7 +611,8 @@ foreach my $test (
photo3 => '',
name => 'This is a really extraordinarily long name that definitely should fail validation',
may_show_name => '1',
- username => 'bob.has.a.very.long.email@thisisalonghostname.example.com',
+ username_register => 'bob.has.a.very.long.email@thisisalonghostname.example.com',
+ username => '',
phone => '01234 5678910 09876 54321 ext 203',
category => 'Trees',
password_sign_in => '',
@@ -612,7 +632,8 @@ foreach my $test (
photo3 => '',
name => 'A User',
may_show_name => '1',
- username => 'user@example.org',
+ username_register => 'user@example.org',
+ username => '',
phone => '',
category => 'Trees',
password_sign_in => '',
@@ -632,7 +653,8 @@ foreach my $test (
photo3 => '',
name => 'A User',
may_show_name => '1',
- username => 'user@example.org',
+ username_register => 'user@example.org',
+ username => '',
phone => '',
category => 'Trees',
password_sign_in => '',
@@ -702,6 +724,26 @@ subtest "test password errors for a user who is signing in as they report" => su
title => 'Test Report',
detail => 'Test report details.',
photo1 => '',
+ username => 'test-2',
+ password_sign_in => 'secret1',
+ category => 'Street lighting',
+ }
+ },
+ "submit with wrong password"
+ );
+
+ is_deeply $mech->page_errors, [
+ "Please enter a valid email",
+ "There was a problem with your login information. If you cannot remember your password, or do not have one, please fill in the \x{2018}No\x{2019} section of the form.",
+ ], "check there were errors";
+
+ $mech->submit_form_ok(
+ {
+ button => 'submit_sign_in',
+ with_fields => {
+ title => 'Test Report',
+ detail => 'Test report details.',
+ photo1 => '',
username => 'test-2@example.com',
password_sign_in => 'secret1',
category => 'Street lighting',
diff --git a/t/app/controller/report_new_open311.t b/t/app/controller/report_new_open311.t
index 08435fb2b..ebbb06567 100644
--- a/t/app/controller/report_new_open311.t
+++ b/t/app/controller/report_new_open311.t
@@ -108,7 +108,8 @@ my $empty_form = {
photo3 => '',
name => '',
may_show_name => '1',
- username => '',
+ username_register => '',
+ username => '',
phone => '',
category => '',
password_sign_in => '',
@@ -130,14 +131,14 @@ foreach my $test (
'This information is required',
'Please enter a subject',
'Please enter some details',
- 'Please enter your email',
'Please enter your name',
+ 'Please enter your email',
],
submit_with => {
title => 'test',
detail => 'test detail',
name => 'Test User',
- username => 'testopen311@example.com',
+ username_register => 'testopen311@example.com',
category => 'Street lighting',
number => 27,
type => 'old',
@@ -170,14 +171,14 @@ foreach my $test (
'This information is required',
'Please enter a subject',
'Please enter some details',
- 'Please enter your email',
'Please enter your name',
+ 'Please enter your email',
],
submit_with => {
title => 'test',
detail => 'test detail',
name => 'Test User',
- username => 'testopen311@example.com',
+ username_register => 'testopen311@example.com',
size => 'big',
colour => 'red',
},
@@ -201,7 +202,7 @@ foreach my $test (
$mech->clear_emails_ok;
# check that the user does not exist
- my $test_email = $test->{submit_with}->{username};
+ my $test_email = $test->{submit_with}->{username_register};
my $user = FixMyStreet::DB->resultset('User')->find( { email => $test_email } );
if ( $user ) {
$user->problems->delete;
@@ -394,6 +395,14 @@ subtest "Category extras includes form disabling string" => sub {
$contact4->push_extra_fields({ datatype_description => 'Please please ring', description => 'Is it dangerous?', code => 'dangerous',
variable => 'true', order => '0', values => [ { name => 'Yes', key => 'yes', disable => 1 }, { name => 'No', key => 'no' } ]
});
+ $contact4->push_extra_fields({ datatype_description => 'Please ring different numbers', description => 'What sort of dangerous?', code => 'danger_type',
+ variable => 'true', order => '0', values => [
+ { name => 'slightly', key => 'slightly', disable => 1, disable_message => 'Ring the slightly number' },
+ { name => 'very', key => 'very', disable => 1, disable_message => 'Ring the very number' },
+ { name => 'extremely', key => 'extremely', disable => 1, disable_message => 'Ring the very number' },
+ { name => 'No', key => 'no' }
+ ]
+ });
$contact4->update;
for (
{ url => '/report/new/ajax?' },
@@ -401,6 +410,7 @@ subtest "Category extras includes form disabling string" => sub {
) {
my $json = $mech->get_ok_json($_->{url} . '&latitude=55.952055&longitude=-3.189579');
my $output = $json->{by_category} ? $json->{by_category}{Pothole}{disable_form} : $json->{disable_form};
+ $output->{questions} = [ sort { $a->{message} cmp $b->{message} } @{ $output->{questions} } ];
is_deeply $output, {
all => 'Please ring us!',
questions => [
@@ -409,6 +419,16 @@ subtest "Category extras includes form disabling string" => sub {
code => 'dangerous',
answers => [ 'yes' ],
},
+ {
+ message => 'Ring the slightly number',
+ code => 'danger_type',
+ answers => [ 'slightly' ],
+ },
+ {
+ message => 'Ring the very number',
+ code => 'danger_type',
+ answers => [ 'very', 'extremely' ],
+ },
],
};
}
@@ -433,7 +453,7 @@ subtest "Category extras includes form disabling string" => sub {
# Test submission of whole form, switching back to a blocked category at the same time
$mech->submit_form_ok({ with_fields => {
category => 'Pothole', title => 'Title', detail => 'Detail',
- username => 'testing@example.org', name => 'Testing Example',
+ username_register => 'testing@example.org', name => 'Testing Example',
} });
$mech->content_contains('<div id="js-category-stopper" class="box-warning" role="alert" aria-live="assertive">');
$mech->content_contains('Please ring us!');
diff --git a/t/app/controller/report_new_text.t b/t/app/controller/report_new_text.t
index 852cdac76..fa012c6ae 100644
--- a/t/app/controller/report_new_text.t
+++ b/t/app/controller/report_new_text.t
@@ -15,20 +15,46 @@ $mech->create_contact_ok( body_id => $body->id, category => 'Street lighting', e
$mech->create_contact_ok( body_id => $body->id, category => 'Trees', email => 'trees@example.com' );
# test that phone number validation works okay
+my %defaults = (
+ title => 'Title', detail => 'Detail', name => 'Bob Jones',
+ category => 'Street lighting', may_show_name => 1,
+ photo1 => '', photo2 => '', photo3 => '',
+ password_register => '', password_sign_in => '',
+);
foreach my $test (
{
+ msg => 'missing update method',
+ pc => 'EH1 1BB',
+ fields => {
+ update_method => undef, phone => '', email => '',
+ %defaults,
+ },
+ changes => {
+ username => '',
+ },
+ errors => [ 'Please enter your email', 'Please pick your update preference' ],
+ },
+ {
+ msg => 'email method',
+ pc => 'EH1 1BB',
+ fields => {
+ update_method => 'email', phone => '', email => 'bademail',
+ %defaults,
+ },
+ changes => {
+ username => '',
+ },
+ errors => [ 'Please enter a valid email' ],
+ },
+ {
msg => 'invalid number',
pc => 'EH1 1BB',
fields => {
- username => '0121 4960000000', email => '', phone => '',
- title => 'Title', detail => 'Detail', name => 'Bob Jones',
- category => 'Street lighting',
- may_show_name => '1',
- photo1 => '', photo2 => '', photo3 => '',
- password_register => '', password_sign_in => '',
+ update_method => 'phone', phone => '0121 4960000000', email => '',
+ %defaults,
},
changes => {
- username => '01214960000000',
+ username => '',
phone => '01214960000000',
},
errors => [ 'Please check your phone number is correct' ],
@@ -37,19 +63,28 @@ foreach my $test (
msg => 'landline number',
pc => 'EH1 1BB',
fields => {
- username => '0121 4960000', email => '', phone => '',
- title => 'Title', detail => 'Detail', name => 'Bob Jones',
- category => 'Street lighting',
- may_show_name => '1',
- photo1 => '', photo2 => '', photo3 => '',
- password_register => '', password_sign_in => '',
+ update_method => 'phone', phone => '0121 4960000', email => '',
+ %defaults,
},
changes => {
- username => '0121 496 0000',
+ username => '',
phone => '0121 496 0000',
},
errors => [ 'Please enter a mobile number', ],
},
+ {
+ msg => 'number that fails',
+ pc => 'EH1 1BB',
+ fields => {
+ update_method => 'phone', phone => '+18165550101', email => '',
+ %defaults,
+ },
+ changes => {
+ username => '',
+ phone => '+1 816-555-0101',
+ },
+ errors => [ 'Sending a confirmation text failed: "Unable to send (21408)"' ],
+ },
)
{
subtest "check form errors where $test->{msg}" => sub {
@@ -60,6 +95,7 @@ foreach my $test (
MAPIT_URL => 'http://mapit.uk/',
SMS_AUTHENTICATION => 1,
PHONE_COUNTRY => 'GB',
+ TWILIO_ACCOUNT_SID => 'AC123',
}, sub {
$mech->submit_form_ok( { with_fields => { pc => $test->{pc} } },
"submit location" );
@@ -142,7 +178,8 @@ foreach my $test (
title => 'Test Report', detail => 'Test report details.',
photo1 => '',
name => 'Joe Bloggs', may_show_name => '1',
- username => $test_phone,
+ update_method => 'phone',
+ phone => $test_phone,
category => 'Street lighting',
password_register => $test->{password} ? 'secret' : '',
}
diff --git a/t/app/controller/report_new_unresponsive.t b/t/app/controller/report_new_unresponsive.t
index 033475c25..211f7198d 100644
--- a/t/app/controller/report_new_unresponsive.t
+++ b/t/app/controller/report_new_unresponsive.t
@@ -107,7 +107,7 @@ sub make_report {
detail => 'Test report details.',
photo1 => '',
name => 'Joe Bloggs',
- username => $user->email,
+ username_register => $user->email,
may_show_name => '1',
phone => '07903 123 456',
category => 'Trees',
diff --git a/t/app/controller/report_new_update.t b/t/app/controller/report_new_update.t
index cbb31cea4..e20975c3a 100644
--- a/t/app/controller/report_new_update.t
+++ b/t/app/controller/report_new_update.t
@@ -1,4 +1,5 @@
use FixMyStreet::TestMech;
+use FixMyStreet::Script::Alerts;
# disable info logs for this test run
FixMyStreet::App->log->disable('info');
@@ -43,6 +44,9 @@ subtest "test report creation with initial auto-update" => sub {
is $comment->user->id, $comment_user->id;
is $comment->external_id, 'auto-internal';
is $comment->name, 'Glos Council';
+
+ FixMyStreet::Script::Alerts::send();
+ my $email = $mech->get_email;
};
done_testing;
diff --git a/t/app/controller/report_update_text.t b/t/app/controller/report_update_text.t
index 52f221264..fbf5ca0c6 100644
--- a/t/app/controller/report_update_text.t
+++ b/t/app/controller/report_update_text.t
@@ -58,21 +58,25 @@ my $comment = FixMyStreet::DB->resultset('Comment')->find_or_create( {
my $comment_id = $comment->id;
ok $comment, "created test update - $comment_id";
+my %defaults = (
+ username => '',
+ update => 'Update',
+ name => 'Name',
+ photo1 => '',
+ photo2 => '',
+ photo3 => '',
+ fixed => undef,
+ add_alert => 1,
+ may_show_name => undef,
+ password_sign_in => '',
+ password_register => '',
+);
for my $test (
{
desc => 'Invalid phone',
fields => {
- username => '01214960000000',
- update => 'Update',
- name => 'Name',
- photo1 => '',
- photo2 => '',
- photo3 => '',
- fixed => undef,
- add_alert => 1,
- may_show_name => undef,
- password_sign_in => '',
- password_register => '',
+ username_register => '01214960000000',
+ %defaults,
},
changes => {},
field_errors => [ 'Please check your phone number is correct' ]
@@ -80,23 +84,21 @@ for my $test (
{
desc => 'landline number',
fields => {
- username => '01214960000',
- update => 'Update',
- name => 'Name',
- photo1 => '',
- photo2 => '',
- photo3 => '',
- fixed => undef,
- add_alert => 1,
- may_show_name => undef,
- password_register => '',
- password_sign_in => '',
- },
- changes => {
- username => '0121 496 0000',
+ username_register => '01214960000',
+ %defaults,
},
+ changes => {},
field_errors => [ 'Please enter a mobile number' ]
},
+ {
+ desc => 'fails to send',
+ fields => {
+ username_register => '+18165550101',
+ %defaults,
+ },
+ changes => {},
+ field_errors => [ 'Sending a confirmation text failed: "Unable to send (21408)"' ]
+ },
)
{
subtest "submit an update - $test->{desc}" => sub {
@@ -104,6 +106,7 @@ for my $test (
FixMyStreet::override_config {
SMS_AUTHENTICATION => 1,
+ TWILIO_ACCOUNT_SID => 'AC123',
PHONE_COUNTRY => 'GB',
}, sub {
$mech->submit_form_ok( { with_fields => $test->{fields} }, 'submit update' );
@@ -126,7 +129,7 @@ for my $test (
desc => 'submit an update, unregistered, logged out',
form_values => {
submit_update => 1,
- username => $test_phone,
+ username_register => $test_phone,
update => 'Update from an unregistered user',
add_alert => undef,
name => 'Unreg User',
@@ -137,7 +140,7 @@ for my $test (
desc => 'submit an update, unregistered, logged out, sign up for alerts',
form_values => {
submit_update => 1,
- username => $test_phone,
+ username_register => $test_phone,
update => 'Update from an unregistered user',
add_alert => 1,
name => 'Unreg User',
@@ -149,7 +152,7 @@ for my $test (
registered => 1,
form_values => {
submit_update => 1,
- username => $test_phone,
+ username_register => $test_phone,
update => 'Update from a registered user',
add_alert => undef,
name => 'Reg User',
@@ -194,7 +197,7 @@ for my $test (
ok $update, 'found update in database';
is $update->state, 'unconfirmed', 'update unconfirmed';
my $details = $test->{form_values};
- is $update->user->phone, $details->{username}, 'update phone';
+ is $update->user->phone, $details->{username_register}, 'update phone';
is $update->user->phone_verified, 1;
is $update->text, $details->{update}, 'update text';
is $add_alerts, $details->{add_alert} ? 1 : 0, 'do not sign up for alerts';
@@ -211,7 +214,7 @@ for my $test (
ok $user->check_password( 'new_secret' ), 'password changed';
is $user->name, 'Reg User', 'name changed';
} else {
- $user = FixMyStreet::DB->resultset( 'User' )->find( { phone => $details->{username} } );
+ $user = FixMyStreet::DB->resultset( 'User' )->find( { phone => $details->{username_register} } );
ok $user, 'found user';
}
diff --git a/t/app/controller/report_updates.t b/t/app/controller/report_updates.t
index 07ee48587..2b60867b8 100644
--- a/t/app/controller/report_updates.t
+++ b/t/app/controller/report_updates.t
@@ -22,6 +22,8 @@ my $user2 = $mech->create_user_ok('commenter@example.com', name => 'Commenter');
my $body = $mech->create_body_ok(2504, 'Westminster City Council');
+my $contact = $mech->create_contact_ok( body_id => $body->id, category => 'Other', email => 'other' );
+
my $dt = DateTime->new(
year => 2011,
month => 04,
@@ -270,7 +272,8 @@ for my $test (
{
desc => 'No email, no message',
fields => {
- username => '',
+ username_register => '',
+ username => '',
update => '',
name => '',
photo1 => '',
@@ -283,12 +286,13 @@ for my $test (
password_sign_in => '',
},
changes => {},
- field_errors => [ 'Please enter a message', 'Please enter your email', 'Please enter your name' ]
+ field_errors => [ 'Please enter a message', 'Please enter your name', 'Please enter your email' ]
},
{
desc => 'Invalid email, no message',
fields => {
- username => 'test',
+ username_register => 'test',
+ username => '',
update => '',
name => '',
photo1 => '',
@@ -301,12 +305,13 @@ for my $test (
password_register => '',
},
changes => {},
- field_errors => [ 'Please enter a message', 'Please enter a valid email', 'Please enter your name' ]
+ field_errors => [ 'Please enter a message', 'Please enter your name', 'Please enter a valid email' ]
},
{
desc => 'email with spaces, no message',
fields => {
- username => 'test @ example. com',
+ username_register => 'test @ example. com',
+ username => '',
update => '',
name => '',
photo1 => '',
@@ -318,15 +323,14 @@ for my $test (
password_register => '',
password_sign_in => '',
},
- changes => {
- username => 'test@example.com',
- },
+ changes => {},
field_errors => [ 'Please enter a message', 'Please enter your name' ]
},
{
desc => 'email with uppercase, no message',
fields => {
- username => 'test@EXAMPLE.COM',
+ username_register => 'test@EXAMPLE.COM',
+ username => '',
update => '',
name => '',
photo1 => '',
@@ -338,9 +342,7 @@ for my $test (
password_register => '',
password_sign_in => '',
},
- changes => {
- username => 'test@example.com',
- },
+ changes => {},
field_errors => [ 'Please enter a message', 'Please enter your name' ]
},
)
@@ -367,6 +369,7 @@ for my $test (
desc => 'submit an update for a non registered user',
initial_values => {
name => '',
+ username_register => '',
username => '',
may_show_name => undef,
add_alert => 1,
@@ -380,7 +383,7 @@ for my $test (
},
form_values => {
submit_update => 1,
- username => 'unregistered@example.com',
+ username_register => 'unregistered@example.com',
update => 'Update from an unregistered user',
add_alert => undef,
name => 'Unreg User',
@@ -392,6 +395,7 @@ for my $test (
desc => 'submit an update for a non registered user and sign up',
initial_values => {
name => '',
+ username_register => '',
username => '',
may_show_name => undef,
add_alert => 1,
@@ -405,7 +409,7 @@ for my $test (
},
form_values => {
submit_update => 1,
- username => 'unregistered@example.com',
+ username_register => 'unregistered@example.com',
update => "update from an\r\n\r\nunregistered user",
add_alert => 1,
name => 'Unreg User',
@@ -463,14 +467,14 @@ for my $test (
ok $update, 'found update in database';
is $update->state, 'unconfirmed', 'update unconfirmed';
- is $update->user->email, $details->{username}, 'update email';
+ is $update->user->email, $details->{username_register}, 'update email';
is $update->text, $details->{update}, 'update text';
is $add_alerts, $details->{add_alert} ? 1 : 0, 'do not sign up for alerts';
$mech->get_ok( $url );
$mech->content_contains("/report/$report_id#update_$update_id");
- my $unreg_user = FixMyStreet::DB->resultset( 'User' )->find( { email => $details->{username} } );
+ my $unreg_user = FixMyStreet::DB->resultset( 'User' )->find( { email => $details->{username_register} } );
ok $unreg_user, 'found user';
@@ -495,6 +499,7 @@ for my $test (
desc => 'overriding email confirmation allows report confirmation with no email sent',
initial_values => {
name => '',
+ username_register => '',
username => '',
may_show_name => undef,
add_alert => 1,
@@ -508,7 +513,7 @@ for my $test (
},
form_values => {
submit_update => 1,
- username => 'unregistered@example.com',
+ username_register => 'unregistered@example.com',
update => "update no email confirm",
add_alert => 1,
name => 'Unreg User',
@@ -560,10 +565,10 @@ for my $test (
ok $update, 'found update in database';
is $update->state, 'confirmed', 'update confirmed';
- is $update->user->email, $details->{username}, 'update email';
+ is $update->user->email, $details->{username_register}, 'update email';
is $update->text, $details->{update}, 'update text';
- my $unreg_user = FixMyStreet::DB->resultset( 'User' )->find( { email => $details->{username} } );
+ my $unreg_user = FixMyStreet::DB->resultset( 'User' )->find( { email => $details->{username_register} } );
ok $unreg_user, 'found user';
@@ -842,8 +847,9 @@ subtest "check comment with no status change has not status in meta" => sub {
$user->from_body( undef );
$user->update;
+ $report->update( { state => 'fixed - user' } );
my $comment = $report->comments->first;
- $comment->update( { mark_fixed => 1, problem_state => 'fixed - council' } );
+ $comment->update( { mark_fixed => 1, problem_state => 'fixed - user' } );
$mech->get_ok("/report/$report_id");
@@ -869,8 +875,8 @@ subtest "check comment with no status change has not status in meta" => sub {
my $update = pop @updates;
- is $report->state, 'fixed - council', 'correct report state';
- is $update->problem_state, 'fixed - council', 'correct update state';
+ is $report->state, 'fixed - user', 'correct report state';
+ is $update->problem_state, 'fixed - user', 'correct update state';
my $update_meta = $mech->extract_update_metas;
unlike $update_meta->[1], qr/State changed to/, 'update meta does not include state change';
@@ -905,6 +911,7 @@ subtest "check comment with no status change has not status in meta" => sub {
is $report->state, 'investigating', 'correct report state';
is $update->problem_state, 'investigating', 'correct update state';
+ is $update->get_extra_metadata('is_body_user'), $body->id, 'correct metadata';
$update_meta = $mech->extract_update_metas;
like $update_meta->[0], qr/fixed/i, 'first update meta says fixed';
unlike $update_meta->[2], qr/State changed to/, 'second update meta does not include state change';
@@ -1094,10 +1101,10 @@ subtest $test->{desc} => sub {
unlike $update_meta->[1], qr/Commenter/, 'commenter name not included';
like $update_meta->[0], qr/investigating/i, 'update meta includes state change';
- if ($test->{body} || $test->{bodyuser}) {
- like $update_meta->[1], qr/Westminster/, 'body user update uses body name';
- } elsif ($test->{superuser}) {
+ if ($test->{superuser}) {
like $update_meta->[1], qr/an administrator/, 'superuser update says an administrator';
+ } elsif ($test->{body} || $test->{bodyuser}) {
+ like $update_meta->[1], qr/Westminster/, 'body user update uses body name';
}
ok $user->user_body_permissions->create({
@@ -1219,6 +1226,21 @@ $report->comments->delete;
for my $test (
{
+ desc => 'submit an update with bad email and password',
+ form_values => {
+ submit_update => 1,
+ username => 'registered@',
+ update => 'Update from a user',
+ add_alert => undef,
+ password_sign_in => 'secret',
+ },
+ field_errors => [
+ 'Please enter a valid email',
+ "There was a problem with your login information. If you cannot remember your password, or do not have one, please fill in the \x{2018}No\x{2019} section of the form.",
+ 'Please enter your name', # FIXME Not really necessary error
+ ],
+ },
+ {
desc => 'submit an update for a registered user, signing in with wrong password',
form_values => {
submit_update => 1,
@@ -1304,7 +1326,7 @@ subtest 'submit an update for a registered user, creating update by email' => su
$mech->submit_form_ok( {
with_fields => {
submit_update => 1,
- username => $user->email,
+ username_register => $user->email,
update => 'Update from a user',
add_alert => undef,
name => 'New Name',
@@ -1753,7 +1775,7 @@ for my $test (
fields => {
submit_update => 1,
name => 'Test User',
- username => $report->user->email,
+ username_register => $report->user->email,
may_show_name => 1,
update => 'update from owner',
add_alert => undef,
@@ -1775,7 +1797,7 @@ for my $test (
submit_update => 1,
name => 'Test User',
may_show_name => 1,
- username => $report->user->email,
+ username_register => $report->user->email,
update => 'update from owner',
add_alert => undef,
fixed => 1,
@@ -1840,7 +1862,7 @@ for my $test (
my $update = $report->comments->first;
ok $update, 'found update';
is $update->text, $results->{update}, 'update text';
- is $update->user->email, $test->{fields}->{username}, 'update user';
+ is $update->user->email, $test->{fields}->{username_register}, 'update user';
is $update->state, 'unconfirmed', 'update confirmed';
is $update->anonymous, $test->{anonymous}, 'user anonymous';
@@ -1893,6 +1915,18 @@ for my $test (
};
}
+$mech->log_in_ok( $report->user->email );
+
+my %standard_fields = (
+ name => $report->user->name,
+ update => 'update text',
+ photo1 => '',
+ photo2 => '',
+ photo3 => '',
+ may_show_name => 1,
+ add_alert => 1,
+);
+
for my $test (
{
desc => 'update confirmed without marking as fixed leaves state unchanged',
@@ -2094,18 +2128,6 @@ for my $test (
},
) {
subtest $test->{desc} => sub {
- $mech->log_in_ok( $report->user->email );
-
- my %standard_fields = (
- name => $report->user->name,
- update => 'update text',
- photo1 => '',
- photo2 => '',
- photo3 => '',
- may_show_name => 1,
- add_alert => 1,
- );
-
my %expected_fields = (
%standard_fields,
%{ $test->{expected_form_fields} },
@@ -2143,6 +2165,17 @@ for my $test (
};
}
+subtest 'check disabling of reopening' => sub {
+ $report->state('fixed - council');
+ $report->update;
+ $mech->get_ok("/report/$report_id");
+ $mech->content_contains('This problem has not been fixed');
+ $contact->set_extra_metadata( reopening_disallowed => 1 );
+ $contact->update;
+ $mech->get_ok("/report/$report_id");
+ $mech->content_lacks('This problem has not been fixed');
+};
+
subtest 'check have to be logged in for creator fixed questionnaire' => sub {
$mech->log_out_ok();
@@ -2178,4 +2211,98 @@ FixMyStreet::override_config {
};
};
+subtest 'check disabling of updates per category' => sub {
+ $contact->set_extra_metadata( updates_disallowed => 1 );
+ $contact->update;
+ $mech->get_ok("/report/$report_id");
+ $mech->content_lacks('Provide an update');
+};
+
+subtest 'check that only staff can display HTML in updates' => sub {
+ $report->comments->delete;
+ $user->update({ from_body => undef, is_superuser => 0 });
+
+ my @lines = (
+ "This update contains:",
+ "1. <strong>some staff-allowed HTML</strong>",
+ "2. *some Markdown-style italics*",
+ "3. <script>some disallowed HTML</script>",
+ "4. An automatic link: https://myfancylink.fixmystreet.com/",
+ "5. A block-level element: <p>This is its own para</p>",
+ ""
+ );
+ my $comment = FixMyStreet::DB->resultset('Comment')->create(
+ {
+ user => $user,
+ problem_id => $report->id,
+ text => join("\n\n", @lines),
+ confirmed => DateTime->now( time_zone => 'local'),
+ problem_state => 'confirmed',
+ anonymous => 0,
+ mark_open => 0,
+ mark_fixed => 0,
+ state => 'confirmed',
+ }
+ );
+
+ # First check that comments from a public user don't receive special treatment
+ $mech->get_ok( "/report/" . $report->id );
+
+ $mech->content_contains("1. &lt;strong&gt;some staff-allowed HTML&lt;/strong&gt;");
+ $mech->content_lacks("<strong>some staff-allowed HTML</strong>");
+
+ $mech->content_contains("2. *some Markdown-style italics*");
+ $mech->content_lacks("<i>some Markdown-style italics</i>");
+ $mech->content_lacks("&lt;i&gt;some Markdown-style italics&lt;/i&gt;");
+
+ $mech->content_contains("3. &lt;script&gt;some disallowed HTML&lt;/script&gt;");
+ $mech->content_lacks("<script>some disallowed HTML</script>");
+
+ $mech->content_contains('4. An automatic link: <a href="https://myfancylink.fixmystreet.com/">https://myfancylink.fixmystreet.com/</a>') or diag $mech->content;
+
+ $mech->content_contains("5. A block-level element: &lt;p&gt;This is its own para&lt;/p&gt;");
+ $mech->content_lacks("5. A block-level element: <p>This is its own para</p>");
+
+ # Now check that comments from a member of staff user do allow HTML/italic markup
+ $comment->set_extra_metadata(is_body_user => $body->id);
+ $comment->update;
+ $mech->get_ok( "/report/" . $report->id );
+
+ $mech->content_contains("1. <strong>some staff-allowed HTML</strong>");
+ $mech->content_lacks("&lt;strong&gt;some staff-allowed HTML&lt;/strong&gt;");
+
+ $mech->content_contains("2. <i>some Markdown-style italics</i>");
+ $mech->content_lacks("*some Markdown-style italics*");
+ $mech->content_lacks("&lt;i&gt;some Markdown-style italics&lt;/i&gt;");
+
+ $mech->content_lacks("some disallowed HTML");
+
+ $mech->content_contains('4. An automatic link: <a href="https://myfancylink.fixmystreet.com/">https://myfancylink.fixmystreet.com/</a>');
+
+ $mech->content_contains("5. A block-level element: <p>This is its own para</p>");
+ $mech->content_lacks("<p>\n5. A block-level element: <p>This is its own para</p></p>");
+
+ # and the same for superusers
+ $comment->unset_extra_metadata('is_body_user');
+ $comment->set_extra_metadata(is_superuser => 1);
+ $comment->update;
+ $mech->get_ok( "/report/" . $report->id );
+
+ $mech->content_contains("1. <strong>some staff-allowed HTML</strong>");
+ $mech->content_lacks("&lt;strong&gt;some staff-allowed HTML&lt;/strong&gt;");
+
+ $mech->content_contains("2. <i>some Markdown-style italics</i>");
+ $mech->content_lacks("*some Markdown-style italics*");
+ $mech->content_lacks("&lt;i&gt;some Markdown-style italics&lt;/i&gt;");
+
+ $mech->content_lacks("some disallowed HTML");
+
+ $mech->content_contains('4. An automatic link: <a href="https://myfancylink.fixmystreet.com/">https://myfancylink.fixmystreet.com/</a>');
+
+ $mech->content_contains("5. A block-level element: <p>This is its own para</p>");
+ $mech->content_lacks("<p>\n5. A block-level element: <p>This is its own para</p></p>");
+
+};
+
+
done_testing();
diff --git a/t/app/controller/waste.t b/t/app/controller/waste.t
new file mode 100644
index 000000000..748904995
--- /dev/null
+++ b/t/app/controller/waste.t
@@ -0,0 +1,211 @@
+use utf8;
+use Test::MockModule;
+use Test::MockTime qw(:all);
+use FixMyStreet::TestMech;
+use FixMyStreet::Script::Reports;
+
+FixMyStreet::App->log->disable('info');
+END { FixMyStreet::App->log->enable('info'); }
+
+# Mock fetching bank holidays
+my $uk = Test::MockModule->new('FixMyStreet::Cobrand::UK');
+$uk->mock('_fetch_url', sub { '{}' });
+
+my $mech = FixMyStreet::TestMech->new;
+
+my $body = $mech->create_body_ok(2482, 'Bromley Council');
+my $user = $mech->create_user_ok('test@example.net', name => 'Normal User');
+my $staff_user = $mech->create_user_ok('staff@example.org', from_body => $body, name => 'Staff User');
+$staff_user->user_body_permissions->create({ body => $body, permission_type => 'contribute_as_another_user' });
+$staff_user->user_body_permissions->create({ body => $body, permission_type => 'report_mark_private' });
+
+sub create_contact {
+ my ($params, @extra) = @_;
+ my $contact = $mech->create_contact_ok(body => $body, %$params);
+ $contact->set_extra_metadata(group => ['Waste']);
+ $contact->set_extra_fields(
+ { code => 'uprn', required => 1, automated => 'hidden_field' },
+ { code => 'property_id', required => 1, automated => 'hidden_field' },
+ { code => 'service_id', required => 0, automated => 'hidden_field' },
+ @extra,
+ );
+ $contact->update;
+}
+
+create_contact({ category => 'Report missed collection', email => 'missed@example.org' });
+create_contact({ category => 'Request new container', email => 'request@example.org' },
+ { code => 'Quantity', required => 1, automated => 'hidden_field' },
+ { code => 'Container_Type', required => 1, automated => 'hidden_field' },
+);
+create_contact({ category => 'General enquiry', email => 'general@example.org' },
+ { code => 'Notes', description => 'Notes', required => 1, datatype => 'text' });
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => ['bromley', 'fixmystreet'],
+ COBRAND_FEATURES => { echo => { bromley => { sample_data => 1 } }, waste => { bromley => 1 } },
+ MAPIT_URL => 'http://mapit.uk/',
+}, sub {
+ $mech->host('bromley.fixmystreet.com');
+ subtest 'Missing address lookup' => sub {
+ $mech->get_ok('/waste');
+ $mech->submit_form_ok({ with_fields => { postcode => 'BR1 1AA' } });
+ $mech->submit_form_ok({ with_fields => { address => 'missing' } });
+ $mech->content_contains('can’t find your address');
+ };
+ subtest 'Address lookup' => sub {
+ set_fixed_time('2020-05-28T17:00:00Z'); # After sample data collection
+ $mech->get_ok('/waste');
+ $mech->submit_form_ok({ with_fields => { postcode => 'BR1 1AA' } });
+ $mech->submit_form_ok({ with_fields => { address => '12345' } });
+ $mech->content_contains('2 Example Street');
+ $mech->content_contains('Food Waste');
+ };
+ subtest 'Thing already requested' => sub {
+ $mech->content_contains('A food waste collection has been reported as missed');
+ $mech->content_contains('A paper &amp; cardboard collection has been reported as missed'); # as part of service unit, not property
+ };
+ subtest 'Report a missed bin' => sub {
+ $mech->content_contains('service-101', 'Can report, last collection was 27th');
+ $mech->content_lacks('service-537', 'Cannot report, last collection was 27th but the service unit has a report');
+ $mech->content_lacks('service-535', 'Cannot report, last collection was 20th');
+ $mech->content_lacks('service-542', 'Cannot report, last collection was 18th');
+ $mech->follow_link_ok({ text => 'Report a missed collection' });
+ $mech->content_contains('service-101', 'Checkbox, last collection was 27th');
+ $mech->content_lacks('service-537', 'No checkbox, last collection was 27th but the service unit has a report');
+ $mech->content_lacks('service-535', 'No checkbox, last collection was 20th');
+ $mech->content_lacks('service-542', 'No checkbox, last collection was 18th');
+ $mech->submit_form_ok({ form_number => 2 });
+ $mech->content_contains('Please specify what was missed');
+ $mech->submit_form_ok({ with_fields => { 'service-101' => 1 } });
+ $mech->submit_form_ok({ with_fields => { name => "Test" } });
+ $mech->content_contains('Please enter your full name');
+ $mech->content_contains('Please specify at least one of phone or email');
+ $mech->submit_form_ok({ with_fields => { name => "Test McTest", email => 'test@example.org' } });
+ $mech->content_contains('Refuse collection');
+ $mech->content_contains('Test McTest');
+ $mech->content_contains('test@example.org');
+ $mech->submit_form_ok({ form_number => 3 });
+ $mech->submit_form_ok({ with_fields => { name => "Test McTest", email => $user->email } });
+ $mech->content_contains($user->email);
+ $mech->submit_form_ok({ with_fields => { process => 'summary' } });
+ $mech->content_contains('Your report has been sent');
+ FixMyStreet::Script::Reports::send();
+ my @emails = $mech->get_email;
+ is $emails[0]->header('To'), '"Bromley Council" <missed@example.org>';
+ is $emails[1]->header('To'), $user->email;
+ my $body = $mech->get_text_body_from_email($emails[1]);
+ like $body, qr/Your report to Bromley Council has been logged/;
+
+ is $user->alerts->count, 1;
+ };
+ subtest 'Check report visibility' => sub {
+ my $report = FixMyStreet::DB->resultset("Problem")->first;
+ my $res = $mech->get('/report/' . $report->id);
+ is $res->code, 403;
+ $mech->log_in_ok($user->email);
+ $mech->get_ok('/report/' . $report->id);
+ $mech->content_lacks('Provide an update');
+ $report->update({ state => 'fixed - council' });
+ $mech->log_in_ok($staff_user->email);
+ $mech->get_ok('/report/' . $report->id);
+ $mech->content_lacks('Provide an update');
+ $mech->content_contains( '<a href="/waste/12345">See your bin collections</a>' );
+
+ $mech->host('www.fixmystreet.com');
+ $res = $mech->get('/report/' . $report->id);
+ is $res->code, 404;
+ $mech->log_in_ok($user->email);
+ $res = $mech->get('/report/' . $report->id);
+ is $res->code, 404;
+ $mech->log_in_ok($staff_user->email);
+ $res = $mech->get('/report/' . $report->id);
+ is $res->code, 404;
+ $mech->host('bromley.fixmystreet.com');
+ };
+ subtest 'Request a new container' => sub {
+ $mech->get_ok('/waste/12345/request');
+ $mech->submit_form_ok({ form_number => 2 });
+ $mech->content_contains('Please specify what you need');
+ $mech->submit_form_ok({ with_fields => { 'container-1' => 1 } });
+ $mech->content_contains('Quantity field is required');
+ $mech->submit_form_ok({ with_fields => { 'container-1' => 1, 'quantity-1' => 2 } });
+ $mech->submit_form_ok({ with_fields => { name => "Test McTest", email => $user->email } });
+ $mech->content_contains('Green Box');
+ $mech->content_contains('Test McTest');
+ $mech->content_contains($user->email);
+ $mech->submit_form_ok({ with_fields => { process => 'summary' } });
+ $mech->content_contains('Your request has been sent');
+ my $report = FixMyStreet::DB->resultset("Problem")->search(undef, { order_by => { -desc => 'id' } })->first;
+ is $report->get_extra_field_value('uprn'), 1000000002;
+ is $report->get_extra_field_value('Quantity'), 2;
+ is $report->get_extra_field_value('Container_Type'), 1;
+ };
+ subtest 'Thing already requested' => sub {
+ $mech->get_ok('/waste/12345');
+ $mech->content_contains('A new paper &amp; cardboard container request has been made');
+ };
+ subtest 'General enquiry, bad data' => sub {
+ $mech->get_ok('/waste/12345/enquiry');
+ is $mech->uri->path, '/waste/12345';
+ $mech->get_ok('/waste/12345/enquiry?category=Bad');
+ is $mech->uri->path, '/waste/12345';
+ $mech->get_ok('/waste/12345/enquiry?service=1');
+ is $mech->uri->path, '/waste/12345';
+ };
+ subtest 'Checking calendar' => sub {
+ $mech->follow_link_ok({ text => 'Add to your calendar (.ics file)' });
+ $mech->content_contains('BEGIN:VCALENDAR');
+ my @events = split /BEGIN:VEVENT/, $mech->encoded_content;
+ shift @events; # Header
+ my $i = 0;
+ foreach (@events) {
+ $i++ if /DTSTART;VALUE=DATE:20200701/ && /SUMMARY:Refuse collection/;
+ $i++ if /DTSTART;VALUE=DATE:20200708/ && /SUMMARY:Paper & Cardboard/;
+ }
+ is $i, 2, 'Two events from the sample data in the calendar';
+ };
+ subtest 'General enquiry, on behalf of someone else' => sub {
+ $mech->log_in_ok($staff_user->email);
+ $mech->get_ok('/waste/12345/enquiry?category=General+enquiry&service_id=537');
+ $mech->submit_form_ok({ with_fields => { extra_Notes => 'Some notes' } });
+ $mech->submit_form_ok({ with_fields => { name => "Test McTest", email => $user->email } });
+ $mech->content_contains('Some notes');
+ $mech->content_contains('Test McTest');
+ $mech->content_contains($user->email);
+ $mech->submit_form_ok({ with_fields => { process => 'summary' } });
+ $mech->content_contains('Your enquiry has been sent');
+ my $report = FixMyStreet::DB->resultset("Problem")->search(undef, { order_by => { -desc => 'id' } })->first;
+ is $report->get_extra_field_value('Notes'), 'Some notes';
+ is $report->user->email, $user->email;
+ is $report->get_extra_metadata('contributed_by'), $staff_user->id;
+ };
+};
+
+package SOAP::Result;
+sub result { return $_[0]->{result}; }
+sub new { my $c = shift; bless { @_ }, $c; }
+
+package main;
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'bromley',
+ COBRAND_FEATURES => { echo => { bromley => { url => 'http://example.org' } }, waste => { bromley => 1 } },
+}, sub {
+ subtest 'Address lookup, mocking SOAP call' => sub {
+ my $integ = Test::MockModule->new('SOAP::Lite');
+ $integ->mock(call => sub {
+ return SOAP::Result->new(result => {
+ PointInfo => [
+ { Description => '1 Example Street', Id => '11345', SharedRef => { Value => { anyType => 1000000001 } } },
+ { Description => '2 Example Street', Id => '12345', SharedRef => { Value => { anyType => 1000000002 } } },
+ ],
+ });
+ });
+
+ $mech->get_ok('/waste');
+ $mech->submit_form_ok({ with_fields => { postcode => 'BR1 1AA' } });
+ $mech->content_contains('2 Example Street');
+ };
+};
+
+done_testing;
diff --git a/t/app/model/comment.t b/t/app/model/comment.t
index 3f30b3a1e..dd9af9eb9 100644
--- a/t/app/model/comment.t
+++ b/t/app/model/comment.t
@@ -1,20 +1,27 @@
use FixMyStreet::Test;
-my $comment_rs = FixMyStreet::DB->resultset('Comment');
+my $user = FixMyStreet::DB->resultset('User')->new({ name => 'Test User', is_superuser => 1 });
+my $comment_rs = FixMyStreet::DB->resultset('Comment');
my $comment = $comment_rs->new(
{
- user_id => 1,
+ user => $user,
problem_id => 1,
text => '',
- state => 'confirmed',
- anonymous => 0,
- mark_fixed => 0,
- cobrand => 'default',
- cobrand_data => '',
}
);
-is $comment->confirmed, undef, 'inflating null confirmed ok';
-is $comment->created, undef, 'inflating null confirmed ok';
+is $comment->created, undef, 'inflating null created ok';
+is $comment->mark_fixed, 0, 'mark fixed default set';
+is $comment->state, 'confirmed', 'state default is confirmed';
+is $comment->name, 'an administrator';
+
+$user->is_superuser(0);
+$comment = $comment_rs->new({
+ user => $user,
+ problem_id => 1,
+ text => '',
+});
+is $comment->name, 'Test User';
+
done_testing();
diff --git a/t/app/model/problem.t b/t/app/model/problem.t
index 661a8827f..be949054b 100644
--- a/t/app/model/problem.t
+++ b/t/app/model/problem.t
@@ -2,6 +2,7 @@ use FixMyStreet::TestMech;
use FixMyStreet;
use FixMyStreet::DB;
use FixMyStreet::Script::Reports;
+use Open311::GetUpdates;
use Sub::Override;
my $problem_rs = FixMyStreet::DB->resultset('Problem');
@@ -133,6 +134,7 @@ $problem->anonymous(1);
$problem->insert;
my $tz_local = DateTime::TimeZone->new( name => 'local' );
+my $comment_time = DateTime->now->set_time_zone( $tz_local );
my $body = FixMyStreet::DB->resultset('Body')->new({
name => 'Edinburgh City Council'
@@ -140,52 +142,32 @@ my $body = FixMyStreet::DB->resultset('Body')->new({
for my $test (
{
- desc => 'request older than problem ignored',
- lastupdate => '',
+ desc => 'request after problem created',
request => {
- updated_datetime => DateTime::Format::W3CDTF->new()->format_datetime( DateTime->now()->set_time_zone( $tz_local )->subtract( days => 2 ) ),
- },
- created => 0,
- },
- {
- desc => 'request newer than problem created',
- lastupdate => '',
- request => {
- updated_datetime => DateTime::Format::W3CDTF->new()->format_datetime( DateTime->now()->set_time_zone( $tz_local ) ),
status => 'open',
- status_notes => 'this is an update from the council',
+ comment_time => $comment_time,
+ description => 'this is an update from the council',
},
- created => 1,
state => 'confirmed',
- mark_fixed => 0,
- mark_open => 0,
},
{
desc => 'update with state of closed fixes problem',
- lastupdate => '',
request => {
- updated_datetime => DateTime::Format::W3CDTF->new()->format_datetime( DateTime->now()->set_time_zone( $tz_local ) ),
+ comment_time => $comment_time,
status => 'closed',
- status_notes => 'the council have fixed this',
+ description => 'the council have fixed this',
},
- created => 1,
- state => 'fixed',
- mark_fixed => 1,
- mark_open => 0,
+ state => 'fixed - council',
},
{
- desc => 'update with state of open leaves problem as fixed',
- lastupdate => '',
+ desc => 'update with state of open reopens problem',
request => {
- updated_datetime => DateTime::Format::W3CDTF->new()->format_datetime( DateTime->now()->set_time_zone( $tz_local ) ),
+ comment_time => $comment_time,
status => 'open',
- status_notes => 'the council do not think this is fixed',
+ description => 'the council do not think this is fixed',
},
- created => 1,
- start_state => 'fixed',
- state => 'fixed',
- mark_fixed => 0,
- mark_open => 0,
+ start_state => 'fixed - council',
+ state => 'confirmed',
},
) {
subtest $test->{desc} => sub {
@@ -197,23 +179,20 @@ for my $test (
$problem->update;
my $w3c = DateTime::Format::W3CDTF->new();
- my $ret = $problem->update_from_open311_service_request( $test->{request}, $body, $user );
- is $ret, $test->{created}, 'return value';
-
- return unless $test->{created};
+ my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1 );
+ my $updates = Open311::GetUpdates->new(
+ current_open311 => $o,
+ current_body => $body,
+ system_user => $user,
+ );
+ my $update = $updates->process_update($test->{request}, $problem);
$problem->discard_changes;
- is $problem->lastupdate, $w3c->parse_datetime($test->{request}->{updated_datetime}), 'lastupdate time';
-
- my $update = $problem->comments->first;
+ is $problem->lastupdate, $test->{request}->{comment_time}, 'lastupdate time';
ok $update, 'updated created';
-
is $problem->state, $test->{state}, 'problem state';
-
- is $update->text, $test->{request}->{status_notes}, 'update text';
- is $update->mark_open, $test->{mark_open}, 'update mark_open flag';
- is $update->mark_fixed, $test->{mark_fixed}, 'update mark_fixed flag';
+ is $update->text, $test->{request}->{description}, 'update text';
};
}
diff --git a/t/app/model/responsepriority.t b/t/app/model/responsepriority.t
index bd09c2da0..0ecce1529 100644
--- a/t/app/model/responsepriority.t
+++ b/t/app/model/responsepriority.t
@@ -12,6 +12,7 @@ my $oxfordshire = $mech->create_body_ok($area_id, 'Oxfordshire County Council');
my $other_body = $mech->create_body_ok($area_id, 'Some Other Council');
my $potholes_contact = $mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Potholes', email => 'potholes@example.com' );
my $traffic_lights_contact =$mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Traffic lights', email => 'lights@example.com' );
+my @contacts = FixMyStreet::DB->resultset('Contact')->not_deleted->search( { body_id => [ $oxfordshire->id ] } )->all;
my $potholes_response_priority = FixMyStreet::DB->resultset('ResponsePriority')->find_or_create(
{
@@ -32,25 +33,42 @@ my $general_response_priority = FixMyStreet::DB->resultset('ResponsePriority')->
}
);
-subtest 'for_bodies returns correct results' => sub {
+my $deleted1_response_priority = FixMyStreet::DB->resultset('ResponsePriority')->find_or_create(
+ {
+ body_id => $oxfordshire->id,
+ name => 'Deleted priority 1',
+ description => 'This priority has been deleted',
+ deleted => 1,
+ }
+);
+
+my $deleted2_response_priority = FixMyStreet::DB->resultset('ResponsePriority')->find_or_create(
+ {
+ body_id => $oxfordshire->id,
+ name => 'Deleted priority 2',
+ description => 'This priority has been deleted',
+ deleted => 1,
+ }
+);
+
+subtest 'for_bodies returns correct results (including deleted)' => sub {
my $priorities = FixMyStreet::DB->resultset('ResponsePriority')->for_bodies(
[ $oxfordshire->id ],
'Potholes'
);
- is $priorities->count, 2, 'Both priorities are included for Potholes category';
+ is $priorities->count, 4, 'all priorities are included for Potholes category';
$priorities = FixMyStreet::DB->resultset('ResponsePriority')->for_bodies(
[ $oxfordshire->id ],
'Traffic lights'
);
- is $priorities->count, 1, 'Only 1 priority is included for Traffic lights category';
+ is $priorities->count, 3, 'Pothole-only priority ignored for Traffic lights category';
is $priorities->first->name, $general_response_priority->name, 'Correct priority is returned for Traffic lights category';
};
-subtest 'by_categories returns all response priorities grouped by category' => sub {
- my @contacts = FixMyStreet::DB->resultset('Contact')->not_deleted->search( { body_id => [ $oxfordshire->id ] } )->all;
+subtest 'by_categories returns all undeleted response priorities grouped by category' => sub {
my $priorities = FixMyStreet::DB->resultset('ResponsePriority')->by_categories(\@contacts, body_id => $oxfordshire->id);
my $potholes = decode_json($priorities->{Potholes});
my $traffic_lights = decode_json($priorities->{'Traffic lights'});
@@ -59,7 +77,7 @@ subtest 'by_categories returns all response priorities grouped by category' => s
is scalar @$traffic_lights, 1, 'Traffic lights have 1 defect type';
};
-subtest 'by_categories returns all response priorities for an area with multiple bodies' => sub {
+subtest 'by_categories returns all undeleted response priorities for an area with multiple bodies' => sub {
my $other_response_priority = FixMyStreet::DB->resultset('ResponsePriority')->find_or_create(
{
body_id => $other_body->id,
@@ -68,7 +86,6 @@ subtest 'by_categories returns all response priorities for an area with multiple
}
);
- my @contacts = FixMyStreet::DB->resultset('Contact')->not_deleted->search( { body_id => [ $oxfordshire->id ] } )->all;
my $priorities = FixMyStreet::DB->resultset('ResponsePriority')->by_categories(\@contacts, area_id => $area_id);
my $potholes = decode_json($priorities->{Potholes});
my $traffic_lights = decode_json($priorities->{'Traffic lights'});
@@ -77,8 +94,16 @@ subtest 'by_categories returns all response priorities for an area with multiple
is scalar @$traffic_lights, 2, 'Traffic lights have 2 defect types';
};
-END {
- $mech->delete_body( $other_body );
- $mech->delete_body( $oxfordshire );
- done_testing();
-}
+subtest 'test with existing problem' => sub {
+ my ($problem) = $mech->create_problems_for_body(1, $oxfordshire->id, 'Title', {
+ response_priority => $deleted1_response_priority,
+ });
+ my $priorities = FixMyStreet::DB->resultset('ResponsePriority')->by_categories(\@contacts,
+ area_id => $area_id, problem => $problem);
+ my $potholes = decode_json($priorities->{Potholes});
+ my $traffic_lights = decode_json($priorities->{'Traffic lights'});
+ is scalar @$potholes, 4, 'Potholes have 4 defect types, deleted is included';
+ is scalar @$traffic_lights, 3, 'Traffic lights have 3 defect types, deleted is included';
+};
+
+done_testing();
diff --git a/t/app/model/responsetemplate.t b/t/app/model/responsetemplate.t
index 9efc7e3b4..29c41a0e0 100644
--- a/t/app/model/responsetemplate.t
+++ b/t/app/model/responsetemplate.t
@@ -1,3 +1,4 @@
+use utf8;
use FixMyStreet::TestMech;
use JSON::MaybeXS;
@@ -7,7 +8,7 @@ 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 $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);
@@ -17,12 +18,13 @@ my @contacts = FixMyStreet::DB->resultset('Contact')->not_deleted->search( { bod
subtest 'by_categories returns allresponse templates grouped by category' => sub {
my $templates = FixMyStreet::DB->resultset('ResponseTemplate')->by_categories(\@contacts, body_id => $body->id);
- my $potholes = decode_json($templates->{Potholes});
- my $graffiti = decode_json($templates->{Graffiti});
+ my $potholes = JSON::MaybeXS->new->decode($templates->{Potholes});
+ my $graffiti = JSON::MaybeXS->new->decode($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';
+ is $potholes->[0]->{id}, 'Text 1 ⛄', 'Pothole first template has right text';
};
done_testing;
diff --git a/t/app/sendreport/email.t b/t/app/sendreport/email.t
index cfd70a097..c9363b787 100644
--- a/t/app/sendreport/email.t
+++ b/t/app/sendreport/email.t
@@ -20,8 +20,6 @@ my $contact = $mech->create_contact_ok(
);
my $row = FixMyStreet::DB->resultset('Problem')->new( {
- latitude => 51.023569,
- longitude => -3.099055,
bodies_str => '1000',
category => 'category',
cobrand => '',
@@ -70,18 +68,4 @@ foreach my $test ( {
};
}
-$body->update({ name => 'Somerset West and Taunton Council' });
-
-subtest 'Test special behaviour' => sub {
- my $e = FixMyStreet::SendReport::Email->new;
- $contact->update( { state => 'confirmed', email => 'SPECIAL' } );
- $e->add_body( $body );
- FixMyStreet::override_config {
- MAPIT_URL => 'http://mapit.uk/'
- }, sub {
- my ($e) = $e->build_recipient_list( $row, {} );
- like $e->[0], qr/tauntondeane/, 'correct recipient';
- };
-};
-
done_testing();
diff --git a/t/app/sendreport/email/highways.t b/t/app/sendreport/email/highways.t
index b9a71f23f..6f6c65eb5 100644
--- a/t/app/sendreport/email/highways.t
+++ b/t/app/sendreport/email/highways.t
@@ -34,7 +34,15 @@ is $e->build_recipient_list($row), 1, 'correct recipient list count';
is_deeply $e->to, [ [ 'highways@example.com', 'Highways England' ] ], 'correct To line';
FixMyStreet::override_config {
- COBRAND_FEATURES => { open311_email => { highwaysengland => { area_seven => 'a7@example.com' } } }
+ COBRAND_FEATURES => {}
+}, sub {
+ $row->set_extra_fields( { name => 'area_name', value => 'Area 7' } );
+ is $e->build_recipient_list($row), 1, 'correct recipient list count';
+ is_deeply $e->to, [ [ 'highways@example.com', 'Highways England' ] ], 'correct To line';
+};
+
+FixMyStreet::override_config {
+ COBRAND_FEATURES => { open311_email => { highwaysengland => { 'Area 7' => 'a7@example.com' } } }
}, sub {
$row->set_extra_fields( { name => 'area_name', value => 'Area 7' } );
is $e->build_recipient_list($row), 1, 'correct recipient list count';
diff --git a/t/cobrand/bexley.t b/t/cobrand/bexley.t
index 352e61389..46a25d923 100644
--- a/t/cobrand/bexley.t
+++ b/t/cobrand/bexley.t
@@ -50,14 +50,17 @@ FixMyStreet::override_config {
ALLOWED_COBRANDS => [ 'bexley' ],
MAPIT_URL => 'http://mapit.uk/',
STAGING_FLAGS => { send_reports => 1, skip_checks => 0 },
- COBRAND_FEATURES => { open311_email => { bexley => {
- p1 => 'p1@bexley',
- p1confirm => 'p1confirm@bexley',
- lighting => 'thirdparty@notbexley.example.com,another@notbexley.example.com',
- outofhours => 'outofhours@bexley,ooh2@bexley',
- flooding => 'flooding@bexley',
- eh => 'eh@bexley',
- } } },
+ COBRAND_FEATURES => {
+ open311_email => { bexley => {
+ p1 => 'p1@bexley',
+ p1confirm => 'p1confirm@bexley',
+ lighting => 'thirdparty@notbexley.example.com,another@notbexley.example.com',
+ outofhours => 'outofhours@bexley,ooh2@bexley',
+ flooding => 'flooding@bexley',
+ eh => 'eh@bexley',
+ } },
+ category_groups => { bexley => 1 },
+ },
}, sub {
subtest 'cobrand displays council name' => sub {
@@ -144,7 +147,7 @@ FixMyStreet::override_config {
subtest 'resend is disabled in admin' => sub {
my $user = $mech->log_in_ok('super@example.org');
- $user->update({ from_body => $body, is_superuser => 1 });
+ $user->update({ from_body => $body, is_superuser => 1, name => 'Staff User' });
$mech->get_ok('/admin/report_edit/' . $report->id);
$mech->content_contains('View report on site');
$mech->content_lacks('Resend report');
@@ -199,6 +202,16 @@ FixMyStreet::override_config {
], 'Request had multiple photos';
};
+ subtest 'anonymous update message' => sub {
+ my $report = FixMyStreet::DB->resultset("Problem")->first;
+ my $staffuser = $mech->create_user_ok('super@example.org');
+ $mech->create_comment_for_problem($report, $report->user, 'Commenter', 'Normal update', 't', 'confirmed', 'confirmed');
+ $mech->create_comment_for_problem($report, $staffuser, 'Staff user', 'Staff update', 'f', 'confirmed', 'confirmed');
+ $mech->get_ok('/report/' . $report->id);
+ $mech->content_contains('Posted by <strong>London Borough of Bexley</strong>');
+ $mech->content_contains('Posted anonymously by a non-staff user');
+ };
+
};
subtest 'nearest road returns correct road' => sub {
@@ -253,9 +266,10 @@ subtest 'geocoder' => sub {
] };
};
-my $bex = Test::MockModule->new('FixMyStreet::Cobrand::Bexley');
-$bex->mock('get', sub {
- return <<EOF
+subtest 'out of hours' => sub {
+ my $lwp = Test::MockModule->new('LWP::UserAgent');
+ $lwp->mock('get', sub {
+ HTTP::Response->new(200, 'OK', [], <<EOF);
{
"england-and-wales": {
"events": [
@@ -264,9 +278,8 @@ $bex->mock('get', sub {
}
}
EOF
-});
+ });
-subtest 'out of hours' => sub {
my $cobrand = FixMyStreet::Cobrand::Bexley->new;
set_fixed_time('2019-10-16T12:00:00Z');
is $cobrand->_is_out_of_hours(), 0, 'not out of hours in the day';
diff --git a/t/cobrand/bristol.t b/t/cobrand/bristol.t
index d4770b6ee..eacb65ce9 100644
--- a/t/cobrand/bristol.t
+++ b/t/cobrand/bristol.t
@@ -14,6 +14,12 @@ my $open311_contact = $mech->create_contact_ok(
category => 'Street Lighting',
email => 'LIGHT',
);
+my $open311_edited_contact = $mech->create_contact_ok(
+ body_id => $body->id,
+ category => 'Flooding',
+ email => 'FLOOD',
+ send_method => '',
+);
my $email_contact = $mech->create_contact_ok(
body_id => $body->id,
category => 'Potholes',
@@ -38,6 +44,7 @@ subtest 'Only Open311 categories are shown on Bristol cobrand', sub {
}, sub {
$mech->get_ok("/report/new/ajax?latitude=51.494885&longitude=-2.602237");
$mech->content_contains($open311_contact->category);
+ $mech->content_contains($open311_edited_contact->category);
$mech->content_lacks($email_contact->category);
};
};
@@ -49,6 +56,7 @@ subtest 'All categories are shown on FMS cobrand', sub {
}, sub {
$mech->get_ok("/report/new/ajax?latitude=51.494885&longitude=-2.602237");
$mech->content_contains($open311_contact->category);
+ $mech->content_contains($open311_edited_contact->category);
$mech->content_contains($email_contact->category);
};
};
diff --git a/t/cobrand/bromley.t b/t/cobrand/bromley.t
index 71180cd3e..561b5b283 100644
--- a/t/cobrand/bromley.t
+++ b/t/cobrand/bromley.t
@@ -1,11 +1,19 @@
use CGI::Simple;
+use Test::MockModule;
+use Test::MockTime qw(:all);
+use Test::Output;
use FixMyStreet::TestMech;
use FixMyStreet::Script::Reports;
my $mech = FixMyStreet::TestMech->new;
+# Mock fetching bank holidays
+my $uk = Test::MockModule->new('FixMyStreet::Cobrand::UK');
+$uk->mock('_fetch_url', sub { '{}' });
+
# Create test data
my $user = $mech->create_user_ok( 'bromley@example.com', name => 'Bromley' );
-my $body = $mech->create_body_ok( 2482, 'Bromley Council');
+my $body = $mech->create_body_ok( 2482, 'Bromley Council',
+ { can_be_devolved => 1, send_extended_statuses => 1, comment_user => $user });
my $contact = $mech->create_contact_ok(
body_id => $body->id,
category => 'Other',
@@ -26,6 +34,16 @@ $mech->create_contact_ok(
email => 'tfl@example.org',
);
+my $waste = $mech->create_contact_ok(
+ body => $body,
+ category => 'Report missed collection',
+ email => 'missed',
+ send_method => 'Open311',
+ endpoint => 'waste-endpoint',
+);
+$waste->set_extra_metadata(group => ['Waste']);
+$waste->update;
+
my @reports = $mech->create_problems_for_body( 1, $body->id, 'Test', {
latitude => 51.402096,
longitude => 0.015784,
@@ -123,7 +141,7 @@ for my $test (
cobrand => 'bromley',
fields => {
submit_update => 1,
- username => 'unregistered@example.com',
+ username_register => 'unregistered@example.com',
update => 'Update from an unregistered user',
add_alert => undef,
first_name => 'Unreg',
@@ -136,7 +154,7 @@ for my $test (
cobrand => 'fixmystreet',
fields => {
submit_update => 1,
- username => 'unregistered@example.com',
+ username_register => 'unregistered@example.com',
update => 'Update from an unregistered user',
add_alert => undef,
name => 'Unreg User',
@@ -177,7 +195,7 @@ for my $test (
};
}
-subtest 'check display of TfL reports' => sub {
+subtest 'check display of TfL and waste reports' => sub {
$mech->create_problems_for_body( 1, $tfl->id, 'TfL Test', {
latitude => 51.402096,
longitude => 0.015784,
@@ -193,6 +211,7 @@ subtest 'check display of TfL reports' => sub {
};
$mech->content_like(qr{<a title="TfL Test[^>]*www.example.org[^>]*><img[^>]*grey});
$mech->content_like(qr{<a title="Test Test[^>]*href="/[^>]*><img[^>]*yellow});
+ $mech->content_lacks('Report missed collection');
};
subtest 'check geolocation overrides' => sub {
@@ -220,6 +239,7 @@ subtest 'check special subcategories in admin' => sub {
ALLOWED_COBRANDS => 'bromley',
MAPIT_URL => 'http://mapit.uk/',
}, sub {
+ $mech->get_ok('/admin/templates/' . $body->id . '/new');
$mech->get_ok('/admin/users/' . $user->id);
$mech->submit_form_ok({ with_fields => { 'contacts['.$contact->id.']' => 1, 'contacts[BLUE]' => 1 } });
};
@@ -241,4 +261,289 @@ subtest 'check heatmap page' => sub {
};
};
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'bromley',
+ COBRAND_FEATURES => {
+ echo => { bromley => { sample_data => 1 } },
+ waste => { bromley => 1 }
+ },
+}, sub {
+ subtest 'test open enquiries' => sub {
+ set_fixed_time('2020-05-19T12:00:00Z'); # After sample food waste collection
+ $mech->get_ok('/waste/12345');
+ $mech->content_like(qr/Mixed Recycling.*?Next collection<\/dt>\s*<dd[^>]*>\s*Wednesday, 20th May\s+\(this collection has been adjusted/s);
+ $mech->follow_link_ok({ text => 'Report a problem with a food waste collection' });
+ $mech->content_contains('Waste spillage');
+ $mech->content_lacks('Gate not closed');
+ restore_time();
+ };
+
+ subtest 'test crew reported issue' => sub {
+ set_fixed_time('2020-05-21T12:00:00Z'); # After sample container mix
+ $mech->get_ok('/waste/12345');
+ $mech->content_like(qr/Mixed Recycling.*?Last collection<\/dt>\s*<dd[^>]*>\s*Wednesday, 20th May\s+\(this collection has been adjusted/s);
+ $mech->content_contains('A missed collection cannot be reported, please see the last collection status above.');
+ $mech->content_lacks('Report a mixed recycling ');
+ restore_time();
+ };
+
+ subtest 'test reporting before/after completion' => sub {
+ set_fixed_time('2020-05-27T11:00:00Z');
+ $mech->get_ok('/waste/12345');
+ $mech->content_like(qr/Refuse collection.*?Last collection<\/dt>\s*<dd[^>]*>\s*Wednesday, 27th May\s+\(completed at 10:00am\)\s*<p>\s*Wrong Bin Out/s);
+ $mech->content_like(qr/Paper &amp; Cardboard.*?Next collection<\/dt>\s*<dd[^>]*>\s*Wednesday, 27th May\s+\(in progress\)/s);
+ $mech->follow_link_ok({ text => 'Report a problem with a paper & cardboard collection' });
+ $mech->content_lacks('Waste spillage');
+
+ set_fixed_time('2020-05-27T19:00:00Z');
+ $mech->get_ok('/waste/12345');
+ $mech->content_like(qr/Refuse collection.*?Last collection<\/dt>\s*<dd[^>]*>\s*Wednesday, 27th May\s+\(completed at 10:00am\)\s*<p>\s*Wrong Bin Out/s);
+ $mech->content_like(qr/Paper &amp; Cardboard.*?Last collection<\/dt>\s*<dd[^>]*>\s*Wednesday, 27th May\s*<\/dd>/s);
+ $mech->follow_link_ok({ text => 'Report a problem with a paper & cardboard collection' });
+ $mech->content_contains('Waste spillage');
+ };
+
+ subtest 'test template creation' => sub {
+ $mech->log_in_ok('superuser@example.com');
+ $mech->get_ok('/admin/templates/' . $body->id . '/new');
+ $mech->submit_form_ok({ with_fields => {
+ title => 'Wrong bin',
+ text => 'We could not collect your waste as it was not correctly presented.',
+ resolution_code => 187,
+ task_type => 3216,
+ task_state => 'Completed',
+ } });
+ $mech->log_out_ok;
+ };
+
+ subtest 'test reporting before/after completion' => sub {
+ $mech->get_ok('/waste/12345');
+ $mech->content_contains('(completed at 10:00am)');
+ $mech->content_contains('We could not collect your waste as it was not correctly presented.');
+ $mech->content_lacks('Report a paper &amp; cardboard collection');
+ $mech->content_contains('Report a refuse collection');
+ set_fixed_time('2020-05-28T12:00:00Z');
+ $mech->get_ok('/waste/12345');
+ $mech->content_contains('Report a refuse collection');
+ set_fixed_time('2020-05-29T12:00:00Z');
+ $mech->get_ok('/waste/12345');
+ $mech->content_contains('Report a refuse collection');
+ set_fixed_time('2020-05-30T12:00:00Z');
+ $mech->get_ok('/waste/12345');
+ $mech->content_lacks('Report a refuse collection');
+ restore_time();
+ };
+};
+
+subtest 'test waste max-per-day' => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'bromley',
+ COBRAND_FEATURES => {
+ echo => { bromley => { max_per_day => 1, sample_data => 1 } },
+ waste => { bromley => 1 }
+ },
+ }, sub {
+ SKIP: {
+ skip( "No memcached", 2 ) unless Memcached::increment('bromley-test');
+ Memcached::delete("bromley-test");
+ $mech->get_ok('/waste/12345');
+ $mech->get('/waste/12345');
+ is $mech->res->code, 403, 'Now forbidden';
+ }
+ };
+
+};
+
+package SOAP::Result;
+sub result { return $_[0]->{result}; }
+sub new { my $c = shift; bless { @_ }, $c; }
+
+package main;
+
+subtest 'updating of waste reports' => sub {
+ my $integ = Test::MockModule->new('SOAP::Lite');
+ $integ->mock(call => sub {
+ my ($cls, @args) = @_;
+ my $method = $args[0]->name;
+ if ($method eq 'GetEvent') {
+ my ($key, $type, $value) = ${$args[3]->value}->value;
+ my $external_id = ${$value->value}->value->value;
+ my ($waste, $event_state_id, $resolution_code) = split /-/, $external_id;
+ return SOAP::Result->new(result => {
+ EventStateId => $event_state_id,
+ EventTypeId => '2104',
+ LastUpdatedDate => { OffsetMinutes => 60, DateTime => '2020-06-24T14:00:00Z' },
+ ResolutionCodeId => $resolution_code,
+ });
+ } elsif ($method eq 'GetEventType') {
+ return SOAP::Result->new(result => {
+ Workflow => { States => { State => [
+ { CoreState => 'New', Name => 'New', Id => 15001 },
+ { CoreState => 'Pending', Name => 'Unallocated', Id => 15002 },
+ { CoreState => 'Pending', Name => 'Allocated to Crew', Id => 15003 },
+ { CoreState => 'Closed', Name => 'Completed', Id => 15004,
+ ResolutionCodes => { StateResolutionCode => [
+ { ResolutionCodeId => 201, Name => '' },
+ { ResolutionCodeId => 202, Name => 'Spillage on Arrival' },
+ ] } },
+ { CoreState => 'Closed', Name => 'Not Completed', Id => 15005,
+ ResolutionCodes => { StateResolutionCode => [
+ { ResolutionCodeId => 203, Name => 'Nothing Found' },
+ { ResolutionCodeId => 204, Name => 'Too Heavy' },
+ { ResolutionCodeId => 205, Name => 'Inclement Weather' },
+ ] } },
+ { CoreState => 'Closed', Name => 'Rejected', Id => 15006,
+ ResolutionCodes => { StateResolutionCode => [
+ { ResolutionCodeId => 206, Name => 'Out of Time' },
+ { ResolutionCodeId => 207, Name => 'Duplicate' },
+ ] } },
+ ] } },
+ });
+ } else {
+ is $method, 'UNKNOWN';
+ }
+ });
+
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'bromley',
+ COBRAND_FEATURES => {
+ echo => { bromley => { url => 'https://www.example.org/' } },
+ waste => { bromley => 1 }
+ },
+ }, sub {
+ @reports = $mech->create_problems_for_body(2, $body->id, 'Report missed collection', {
+ category => 'Report missed collection',
+ cobrand_data => 'waste',
+ });
+ $reports[1]->update({ external_id => 'something-else' }); # To test loop
+ $report = $reports[0];
+ my $cobrand = FixMyStreet::Cobrand::Bromley->new;
+
+ $report->update({ external_id => 'waste-15001-' });
+ stdout_like {
+ $cobrand->waste_fetch_events(1);
+ } qr/Fetching data for report/;
+ $report->discard_changes;
+ is $report->comments->count, 0, 'No new update';
+ is $report->state, 'confirmed', 'No state change';
+
+ $report->update({ external_id => 'waste-15003-' });
+ stdout_like {
+ $cobrand->waste_fetch_events(1);
+ } qr/Updating report to state action scheduled, Allocated to Crew/;
+ $report->discard_changes;
+ is $report->comments->count, 1, 'A new update';
+ is $report->state, 'action scheduled', 'A state change';
+
+ $report->update({ external_id => 'waste-15003-' });
+ stdout_like {
+ $cobrand->waste_fetch_events(1);
+ } qr/Latest update matches fetched state/;
+ $report->discard_changes;
+ is $report->comments->count, 1, 'No new update';
+ is $report->state, 'action scheduled', 'State unchanged';
+
+ $report->update({ external_id => 'waste-15004-201' });
+ stdout_like {
+ $cobrand->waste_fetch_events(1);
+ } qr/Updating report to state fixed - council, Completed/;
+ $report->discard_changes;
+ is $report->comments->count, 2, 'A new update';
+ is $report->state, 'fixed - council', 'Changed to fixed';
+
+ $reports[1]->update({ state => 'fixed - council' });
+ stdout_like {
+ $cobrand->waste_fetch_events(1);
+ } qr/^$/, 'No open reports';
+
+ $report->update({ external_id => 'waste-15005-205', state => 'confirmed' });
+ stdout_like {
+ $cobrand->waste_fetch_events(1);
+ } qr/Updating report to state unable to fix, Inclement Weather/;
+ $report->discard_changes;
+ is $report->comments->count, 3, 'A new update';
+ is $report->state, 'unable to fix', 'A state change';
+ };
+
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'bromley',
+ COBRAND_FEATURES => {
+ echo => { bromley => {
+ url => 'https://www.example.org/',
+ receive_action => 'action',
+ receive_username => 'un',
+ receive_password => 'password',
+ } },
+ waste => { bromley => 1 }
+ },
+ }, sub {
+ FixMyStreet::App->log->disable('info');
+
+ $mech->get('/waste/echo');
+ is $mech->res->code, 405, 'Cannot GET';
+
+ $mech->post('/waste/echo', Content_Type => 'text/xml');
+ is $mech->res->code, 400, 'No body';
+
+ my $in = '<Envelope><Header><Action>bad-action</Action></Header><Body></Body></Envelope>';
+ $mech->post('/waste/echo', Content_Type => 'text/xml', Content => $in);
+ is $mech->res->code, 400, 'Bad action';
+
+ $in = '<Envelope><Header><Action>action</Action><Security><UsernameToken><Username></Username><Password></Password></UsernameToken></Security></Header><Body></Body></Envelope>';
+ $mech->post('/waste/echo', Content_Type => 'text/xml', Content => $in);
+ is $mech->res->code, 400, 'Bad auth';
+
+ $in = <<EOF;
+<?xml version="1.0" encoding="UTF-8"?>
+<Envelope>
+ <Header>
+ <Action>action</Action>
+ <Security><UsernameToken><Username>un</Username><Password>password</Password></UsernameToken></Security>
+ </Header>
+ <Body>
+ <NotifyEventUpdated>
+ <event>
+ <Guid>waste-15005-XXX</Guid>
+ <EventTypeId>2104</EventTypeId>
+ <EventStateId>15006</EventStateId>
+ <ResolutionCodeId>207</ResolutionCodeId>
+ </event>
+ </NotifyEventUpdated>
+ </Body>
+</Envelope>
+EOF
+
+ $mech->post('/waste/echo', Content_Type => 'text/xml', Content => $in);
+ is $mech->res->code, 200, 'OK response, even though event does not exist';
+ is $report->comments->count, 3, 'No new update';
+
+ $in = <<EOF;
+<?xml version="1.0" encoding="UTF-8"?>
+<Envelope>
+ <Header>
+ <Action>action</Action>
+ <Security><UsernameToken><Username>un</Username><Password>password</Password></UsernameToken></Security>
+ </Header>
+ <Body>
+ <NotifyEventUpdated>
+ <event>
+ <Guid>waste-15005-205</Guid>
+ <EventTypeId>2104</EventTypeId>
+ <EventStateId>15006</EventStateId>
+ <ResolutionCodeId>207</ResolutionCodeId>
+ </event>
+ </NotifyEventUpdated>
+ </Body>
+</Envelope>
+EOF
+ $mech->post('/waste/echo', Content_Type => 'text/xml', Content => $in);
+ #$report->update({ external_id => 'waste-15005-205', state => 'confirmed' });
+ is $report->comments->count, 4, 'A new update';
+ $report->discard_changes;
+ is $report->state, 'closed', 'A state change';
+
+ FixMyStreet::App->log->enable('info');
+ };
+};
+
done_testing();
diff --git a/t/cobrand/bucks.t b/t/cobrand/bucks.t
index 230a52f99..8d99178f5 100644
--- a/t/cobrand/bucks.t
+++ b/t/cobrand/bucks.t
@@ -112,7 +112,6 @@ subtest 'pothole on road not sent to extra email, only confirm sent' => sub {
is $report->external_id, 248, 'Report has right external ID';
};
-
# report made in Flytipping category off road should get moved to other category
subtest 'Flytipping not on a road gets recategorised' => sub {
$mech->log_in_ok($publicuser->email);
@@ -129,13 +128,48 @@ subtest 'Flytipping not on a road gets recategorised' => sub {
my $report = FixMyStreet::DB->resultset("Problem")->search(undef, { order_by => { -desc => 'id' } })->first;
ok $report, "Found the report";
is $report->category, "Flytipping (off-road)", 'Report was recategorised correctly';
+};
+
+subtest 'Flytipping not on a road on .com gets recategorised' => sub {
+ ok $mech->host("www.fixmystreet.com"), "change host to www";
+ $mech->get_ok('/report/new?latitude=51.615559&longitude=-0.556903&category=Flytipping');
+ $mech->submit_form_ok({
+ with_fields => {
+ title => "Test Report",
+ detail => 'Test report details.',
+ category => 'Flytipping',
+ 'road-placement' => 'off-road',
+ }
+ }, "submit details");
+ $mech->content_contains('on its way to the council right now');
+ my $report = FixMyStreet::DB->resultset("Problem")->search(undef, { order_by => { -desc => 'id' } })->first;
+ ok $report, "Found the report";
+ is $report->category, "Flytipping (off-road)", 'Report was recategorised correctly';
+ ok $mech->host("buckinghamshire.fixmystreet.com"), "change host to bucks";
+};
+
+subtest 'Flytipping not on a road going to HE does not get recategorised' => sub {
+ $mech->get_ok('/report/new?latitude=51.615559&longitude=-0.556903&category=Flytipping');
+ $mech->submit_form_ok({
+ with_fields => {
+ single_body_only => 'Highways England',
+ title => "Test Report",
+ detail => 'Test report details.',
+ category => 'Flytipping',
+ 'road-placement' => 'off-road',
+ }
+ }, "submit details");
+ $mech->content_contains('We don&rsquo;t handle this type of problem');
+ my $report = FixMyStreet::DB->resultset("Problem")->search(undef, { order_by => { -desc => 'id' } })->first;
+ ok $report, "Found the report";
+ is $report->category, "Flytipping", 'Report was not recategorised';
$mech->log_out_ok;
};
subtest 'Ex-district reports are sent to correct emails' => sub {
FixMyStreet::Script::Reports::send();
- $mech->email_count_is(2); # one for council, one confirmation for user
+ $mech->email_count_is(4); # (one for council, one confirmation for user) x 2
my @email = $mech->get_email;
is $email[0]->header('To'), 'Buckinghamshire <flytipping@chiltern>';
};
@@ -229,7 +263,7 @@ subtest 'extra CSV columns are present' => sub {
$mech->get_ok('/dashboard?export=1');
my @rows = $mech->content_as_csv;
- is scalar @rows, 5, '1 (header) + 4 (reports) = 5 lines';
+ is scalar @rows, 6, '1 (header) + 4 (reports) = 6 lines';
is scalar @{$rows[0]}, 21, '21 columns present';
is_deeply $rows[0],
diff --git a/t/cobrand/form_extras.t b/t/cobrand/form_extras.t
index 3807dd56a..72c725d75 100644
--- a/t/cobrand/form_extras.t
+++ b/t/cobrand/form_extras.t
@@ -41,7 +41,7 @@ FixMyStreet::override_config {
detail => 'Test report details.',
name => 'Joe Bloggs',
may_show_name => '1',
- username => 'test-1@example.com',
+ username_register => 'test-1@example.com',
password_register => '',
}
},
diff --git a/t/cobrand/get_body_sender.t b/t/cobrand/get_body_sender.t
index 06ffb42a5..a1e8f2320 100644
--- a/t/cobrand/get_body_sender.t
+++ b/t/cobrand/get_body_sender.t
@@ -6,31 +6,21 @@ use_ok 'FixMyStreet::Cobrand';
my $c = FixMyStreet::Cobrand::FixMyStreet->new();
-FixMyStreet::DB->resultset('BodyArea')->search( { body_id => 1000 } )->delete;
-FixMyStreet::DB->resultset('Body')->search( { name => 'Body of a Thousand' } )->delete;
-
my $body = FixMyStreet::DB->resultset('Body')->find_or_create({
id => 1000,
name => 'Body of a Thousand',
});
-my $body_area = $body->body_areas->find_or_create({ area_id => 1000 });
+
+my $problem = FixMyStreet::DB->resultset('Problem')->new({});
FixMyStreet::override_config {
MAPIT_TYPES => [ 'LBO' ],
MAPIT_URL => 'http://mapit.uk/', # Not actually used as no special casing at present
}, sub {
- is_deeply $c->get_body_sender( $body ), { method => 'Email', contact => undef }, 'defaults to email';
- $body_area->update({ area_id => 2481 }); # Croydon LBO
- is_deeply $c->get_body_sender( $body ), { method => 'Email', contact => undef }, 'still email if London borough';
+ is_deeply $c->get_body_sender( $body, $problem ), { method => 'Email', contact => undef }, 'defaults to email';
};
$body->send_method( 'TestMethod' );
-is $c->get_body_sender( $body )->{ method }, 'TestMethod', 'uses send_method in preference to London';
-
-$body_area->update({ area_id => 1000 }); # Nothing
-is $c->get_body_sender( $body )->{ method }, 'TestMethod', 'uses send_method in preference to Email';
-
-$body_area->delete;
-$body->delete;
+is $c->get_body_sender( $body, $problem )->{ method }, 'TestMethod', 'uses send_method in preference to Email';
done_testing();
diff --git a/t/cobrand/hackney.t b/t/cobrand/hackney.t
new file mode 100644
index 000000000..bdfcceef8
--- /dev/null
+++ b/t/cobrand/hackney.t
@@ -0,0 +1,325 @@
+use utf8;
+use CGI::Simple;
+use DateTime;
+use Test::MockModule;
+use FixMyStreet::TestMech;
+use Open311;
+use Open311::GetServiceRequests;
+use Open311::GetServiceRequestUpdates;
+use Open311::PostServiceRequestUpdates;
+use FixMyStreet::Script::Alerts;
+use FixMyStreet::Script::Reports;
+
+# disable info logs for this test run
+FixMyStreet::App->log->disable('info');
+END { FixMyStreet::App->log->enable('info'); }
+
+ok( my $mech = FixMyStreet::TestMech->new, 'Created mech object' );
+
+my $params = {
+ send_method => 'Open311',
+ send_comments => 1,
+ api_key => 'KEY',
+ endpoint => 'endpoint',
+ jurisdiction => 'home',
+ can_be_devolved => 1,
+};
+
+my $hackney = $mech->create_body_ok(2508, 'Hackney Council', $params);
+my $contact = $mech->create_contact_ok(
+ body_id => $hackney->id,
+ category => 'Potholes & stuff',
+ email => 'pothole@example.org',
+);
+$contact->set_extra_fields( ( {
+ code => 'urgent',
+ datatype => 'string',
+ description => 'question',
+ variable => 'true',
+ required => 'false',
+ order => 1,
+ datatype_description => 'datatype',
+} ) );
+$contact->update;
+
+my $user = $mech->create_user_ok('user@example.org', name => 'Test User');
+my $hackney_user = $mech->create_user_ok('hackney_user@example.org', name => 'Hackney User', from_body => $hackney);
+$hackney_user->user_body_permissions->create({
+ body => $hackney,
+ permission_type => 'moderate',
+});
+$hackney_user->user_body_permissions->create({
+ body => $hackney,
+ permission_type => 'category_edit',
+});
+
+my $contact2 = $mech->create_contact_ok(
+ body_id => $hackney->id,
+ category => 'Roads',
+ email => 'roads@example.org',
+ send_method => 'Email',
+);
+
+my $admin_user = $mech->create_user_ok('admin-user@example.org', name => 'Admin User', from_body => $hackney);
+
+my @reports = $mech->create_problems_for_body(1, $hackney->id, 'A Hackney report', {
+ confirmed => '2019-10-25 09:00',
+ lastupdate => '2019-10-25 09:00',
+ latitude => 51.552267,
+ longitude => -0.063316,
+ user => $user,
+ external_id => 101202303
+});
+
+subtest "check clicking all reports link" => sub {
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => ['hackney'],
+ }, sub {
+ $mech->get_ok('/');
+ $mech->follow_link_ok({ text => 'All reports' });
+ };
+
+ $mech->content_contains("A Hackney report", "Hackney report there");
+ $mech->content_contains("Hackney Council", "is still on cobrand");
+};
+
+subtest "check moderation label uses correct name" => sub {
+ my $REPORT_URL = '/report/' . $reports[0]->id;
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => ['hackney'],
+ COBRAND_FEATURES => {
+ do_not_reply_email => {
+ hackney => 'fms-hackney-DO-NOT-REPLY@hackney-example.com',
+ },
+ verp_email_domain => {
+ hackney => 'hackney-example.com',
+ },
+ },
+ }, sub {
+ $mech->log_out_ok;
+ $mech->log_in_ok( $hackney_user->email );
+ $mech->get_ok($REPORT_URL);
+ $mech->content_lacks('show-moderation');
+ $mech->follow_link_ok({ text_regex => qr/^Moderate$/ });
+ $mech->content_contains('show-moderation');
+ $mech->submit_form_ok({ with_fields => {
+ problem_title => 'Good good',
+ problem_detail => 'Good good improved',
+ }});
+ $mech->base_like( qr{\Q$REPORT_URL\E} );
+ $mech->content_like(qr/Moderated by Hackney Council/);
+ };
+};
+
+$_->delete for @reports;
+
+my $system_user = $mech->create_user_ok('system_user@example.org');
+
+my ($p) = $mech->create_problems_for_body(1, $hackney->id, '', { cobrand => 'hackney' });
+my $alert = FixMyStreet::DB->resultset('Alert')->create( {
+ parameter => $p->id,
+ alert_type => 'new_updates',
+ user => $user,
+ cobrand => 'hackney',
+} )->confirm;
+
+subtest "sends branded alert emails" => sub {
+ $mech->create_comment_for_problem($p, $system_user, 'Other User', 'This is some update text', 'f', 'confirmed', undef);
+ $mech->clear_emails_ok;
+
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => ['hackney','fixmystreet'],
+ COBRAND_FEATURES => {
+ do_not_reply_email => { hackney => 'fms-hackney-DO-NOT-REPLY@hackney-example.com' },
+ },
+ }, sub {
+ FixMyStreet::Script::Alerts::send();
+ };
+
+ my $email = $mech->get_email;
+ ok $email, "got an email";
+ like $mech->get_text_body_from_email($email), qr/Hackney Council/, "emails are branded";
+};
+
+$p->comments->delete;
+$p->delete;
+
+subtest "sends branded confirmation emails" => sub {
+ $mech->log_out_ok;
+ $mech->clear_emails_ok;
+ $mech->get_ok('/?filter_category=Potholes+%26+stuff');
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'hackney' ],
+ MAPIT_URL => 'http://mapit.uk/',
+ COBRAND_FEATURES => {
+ do_not_reply_email => {
+ hackney => 'fms-hackney-DO-NOT-REPLY@hackney-example.com',
+ },
+ verp_email_domain => {
+ hackney => 'hackney-example.com',
+ },
+ },
+ }, sub {
+ $mech->submit_form_ok( { with_fields => { pc => 'E8 1DY', } },
+ "submit location" );
+
+ # While we're here, check the category with an ampersand (regression test)
+ $mech->content_contains('<option value="Potholes &amp; stuff" selected>');
+
+ # click through to the report page
+ $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 => {
+ title => 'Test Report',
+ detail => 'Test report details.',
+ photo1 => '',
+ name => 'Joe Bloggs',
+ username_register => 'test-1@example.com',
+ category => 'Roads',
+ }
+ },
+ "submit good details"
+ );
+
+ my $email = $mech->get_email;
+ ok $email, "got an email";
+ like $mech->get_text_body_from_email($email), qr/Hackney Council/, "emails are branded";
+
+ my $url = $mech->get_link_from_email($email);
+ $mech->get_ok($url);
+ $mech->clear_emails_ok;
+ };
+};
+
+FixMyStreet::override_config {
+ STAGING_FLAGS => { send_reports => 1 },
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => ['hackney', 'fixmystreet'],
+}, sub {
+ subtest "special send handling" => sub {
+ my $cbr = Test::MockModule->new('FixMyStreet::Cobrand::Hackney');
+ my $p = FixMyStreet::DB->resultset("Problem")->search(undef, { order_by => { -desc => 'id' } })->first;
+ $contact2->update({ email => 'park:parks@example;estate:estates@example;other:OTHER', send_method => '' });
+
+ subtest 'in a park' => sub {
+ $cbr->mock('_fetch_features', sub {
+ my ($self, $cfg, $x, $y) = @_;
+ return [{
+ properties => { park_id => 'park' },
+ geometry => {
+ type => 'Polygon',
+ coordinates => [ [ [ $x-1, $y-1 ], [ $x+1, $y+1 ] ] ],
+ }
+ }] if $cfg->{typename} eq 'greenspaces:hackney_park';
+ });
+ FixMyStreet::Script::Reports::send();
+ my $email = $mech->get_email;
+ is $email->header('To'), '"Hackney Council" <parks@example>';
+ $mech->clear_emails_ok;
+ $p->discard_changes;
+ $p->update({ whensent => undef });
+ };
+
+ subtest 'in an estate' => sub {
+ $cbr->mock('_fetch_features', sub {
+ my ($self, $cfg, $x, $y) = @_;
+ return [{
+ properties => { id => 'estate' },
+ geometry => {
+ type => 'Polygon',
+ coordinates => [ [ [ $x-1, $y-1 ], [ $x+1, $y+1 ] ] ],
+ }
+ }] if $cfg->{typename} eq 'housing:lbh_estate';
+ });
+ FixMyStreet::Script::Reports::send();
+ my $email = $mech->get_email;
+ is $email->header('To'), '"Hackney Council" <estates@example>';
+ $mech->clear_emails_ok;
+ $p->discard_changes;
+ $p->update({ whensent => undef });
+ };
+
+ subtest 'elsewhere' => sub {
+ $cbr->mock('_fetch_features', sub {
+ my ($self, $cfg, $x, $y) = @_;
+ return []; # Not in park or estate
+ });
+ my $test_data = FixMyStreet::Script::Reports::send();
+ my $req = $test_data->{test_req_used};
+ my $c = CGI::Simple->new($req->content);
+ is $c->param('service_code'), 'OTHER';
+ };
+ };
+};
+
+#subtest "sends branded report sent emails" => sub {
+ #$mech->clear_emails_ok;
+ #FixMyStreet::override_config {
+ #STAGING_FLAGS => { send_reports => 1 },
+ #MAPIT_URL => 'http://mapit.uk/',
+ #ALLOWED_COBRANDS => ['hackney','fixmystreet'],
+ #}, sub {
+ #FixMyStreet::Script::Reports::send();
+ #};
+ #my $email = $mech->get_email;
+ #ok $email, "got an email";
+ #like $mech->get_text_body_from_email($email), qr/Hackney Council/, "emails are branded";
+#};
+
+subtest "check category extra uses correct name" => sub {
+ my @extras = ( {
+ code => 'test',
+ datatype => 'string',
+ description => 'question',
+ variable => 'true',
+ required => 'false',
+ order => 1,
+ datatype_description => 'datatype',
+ } );
+ $contact2->set_extra_fields( @extras );
+ $contact2->update;
+
+ my $extra_details;
+
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => ['hackney','fixmystreet'],
+ }, sub {
+ $extra_details = $mech->get_ok_json('/report/new/category_extras?category=Roads&latitude=51.552267&longitude=-0.063316');
+ };
+
+ like $extra_details->{category_extra}, qr/Hackney Council/, 'correct name in category extras';
+};
+
+subtest "can edit special destination email addresses" => sub {
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => ['hackney'],
+ COBRAND_FEATURES => { anonymous_account => { hackney => 'anonymous' } },
+ }, sub {
+ $contact2->update({ send_method => 'Email' });
+ $mech->log_in_ok( $hackney_user->email );
+ $mech->get_ok("/admin/body/" . $hackney->id . "/" . $contact2->category);
+ $mech->submit_form_ok( { with_fields => { email => 'park:parks@example.com;estate:estates@example;other:new@example.org' } },
+ "submit valid new email address");
+ $mech->content_lacks("Please enter a valid email");
+ $contact2->discard_changes;
+ is $contact2->email, 'park:parks@example.com;estate:estates@example;other:new@example.org', "New email addresses saved";
+
+ $mech->get_ok("/admin/body/" . $hackney->id . "/" . $contact2->category);
+ $mech->submit_form_ok( { with_fields => { email => 'invalid' } },
+ "submit invalid new email address");
+ $mech->content_contains("Please enter a valid email");
+ $contact2->discard_changes;
+ is $contact2->email, 'park:parks@example.com;estate:estates@example;other:new@example.org', "Invalid email addresses not saved";
+ };
+};
+
+done_testing();
diff --git a/t/cobrand/highwaysengland.t b/t/cobrand/highwaysengland.t
index f6400ea7c..0b71c613f 100644
--- a/t/cobrand/highwaysengland.t
+++ b/t/cobrand/highwaysengland.t
@@ -29,12 +29,11 @@ my $highways = $mech->create_body_ok(2234, 'Highways England');
$mech->create_contact_ok(email => 'highways@example.com', body_id => $highways->id, category => 'Pothole');
-# Br1 3UH
-subtest "check where heard from saved" => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => 'highwaysengland',
- MAPIT_URL => 'http://mapit.uk/',
- }, sub {
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'highwaysengland',
+ MAPIT_URL => 'http://mapit.uk/',
+}, sub {
+ subtest "check where heard from saved" => sub {
$mech->get_ok('/around');
$mech->submit_form_ok( { with_fields => { pc => 'M1, J16', } }, "submit location" );
$mech->follow_link_ok( { text_regex => qr/skip this step/i, },
@@ -64,7 +63,12 @@ subtest "check where heard from saved" => sub {
like $mech->get_text_body_from_email($email), qr/Heard from: Facebook/, 'where hear included in email'
};
-};
+ subtest "check anonymous display" => sub {
+ my ($problem) = $mech->create_problems_for_body(1, $highways->id, 'Title');
+ $mech->get_ok('/report/' . $problem->id);
+ $mech->content_lacks('Reported by Test User at');
+ };
+};
done_testing();
diff --git a/t/cobrand/hounslow.t b/t/cobrand/hounslow.t
index 91c1cb455..e58309925 100644
--- a/t/cobrand/hounslow.t
+++ b/t/cobrand/hounslow.t
@@ -38,6 +38,15 @@ my ($report) = $mech->create_problems_for_body(1, $hounslow_id, 'A brand new pro
cobrand => 'fixmystreet'
});
+subtest "showing the front page" => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'hounslow',
+ }, sub {
+ $mech->get_ok('/');
+ $mech->content_contains('completed in past month');
+ };
+};
+
subtest "it still shows old reports on fixmystreet.com" => sub {
FixMyStreet::override_config {
MAPIT_URL => 'http://mapit.uk/',
diff --git a/t/cobrand/isleofwight.t b/t/cobrand/isleofwight.t
index 3cac710da..ad9017e26 100644
--- a/t/cobrand/isleofwight.t
+++ b/t/cobrand/isleofwight.t
@@ -116,13 +116,24 @@ subtest "only original reporter can comment" => sub {
};
};
+subtest "only original reporter can comment" => sub {
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => 'fixmystreet',
+ COBRAND_FEATURES => { updates_allowed => { fixmystreet => { 'Isle of Wight' => 'reporter' } } },
+ }, sub {
+ $mech->log_out_ok;
+ $mech->get_ok('/report/' . $reports[0]->id);
+ $mech->content_contains('Only the original reporter may leave updates');
+ };
+};
+
subtest "check moderation label uses correct name" => sub {
my $REPORT_URL = '/report/' . $reports[0]->id;
FixMyStreet::override_config {
MAPIT_URL => 'http://mapit.uk/',
ALLOWED_COBRANDS => ['isleofwight'],
}, sub {
- $mech->log_out_ok;
$mech->log_in_ok( $iow_user->email );
$mech->get_ok($REPORT_URL);
$mech->content_lacks('show-moderation');
@@ -470,7 +481,7 @@ subtest "sends branded confirmation emails" => sub {
detail => 'Test report details.',
photo1 => '',
name => 'Joe Bloggs',
- username => 'test-1@example.com',
+ username_register => 'test-1@example.com',
category => 'Roads',
}
},
diff --git a/t/cobrand/northamptonshire.t b/t/cobrand/northamptonshire.t
index 57fe319a9..36a2c4638 100644
--- a/t/cobrand/northamptonshire.t
+++ b/t/cobrand/northamptonshire.t
@@ -52,7 +52,7 @@ $ncc->update( { comment_user_id => $counciluser->id } );
subtest 'Check district categories hidden on cobrand' => sub {
FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { northamptonshire => '.' } ],
+ ALLOWED_COBRANDS=> 'northamptonshire',
MAPIT_URL => 'http://mapit.uk/',
}, sub {
$mech->get_ok( '/around' );
@@ -70,7 +70,7 @@ subtest 'Check district categories hidden on cobrand' => sub {
subtest 'Check updates not sent for defects' => sub {
FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { northamptonshire => '.' } ],
+ ALLOWED_COBRANDS=> 'northamptonshire',
MAPIT_URL => 'http://mapit.uk/',
}, sub {
my $updates = Open311::PostServiceRequestUpdates->new();
@@ -86,7 +86,7 @@ $report->update({ user => $user });
$comment->update({ extra => undef });
subtest 'check updates sent for non defects' => sub {
FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { northamptonshire => '.' } ],
+ ALLOWED_COBRANDS=> 'northamptonshire',
MAPIT_URL => 'http://mapit.uk/',
}, sub {
my $updates = Open311::PostServiceRequestUpdates->new();
@@ -107,6 +107,182 @@ subtest 'check updates disallowed correctly' => sub {
is $cobrand->updates_disallowed($report), 1;
};
+subtest 'check further investigation state' => sub {
+ $comment->problem_state('investigating');
+ $comment->update();
+
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS=> 'northamptonshire',
+ MAPIT_URL => 'http://mapit.uk/',
+ COBRAND_FEATURES => {
+ extra_state_mapping => {
+ northamptonshire => {
+ investigating => {
+ further => 'Under further investigation'
+ }
+ }
+ }
+ }
+ }, sub {
+ $mech->get_ok('/report/' . $comment->problem_id);
+ };
+
+ $mech->content_lacks('Under further investigation');
+
+ $comment->set_extra_metadata('external_status_code' => 'further');
+ $comment->update;
+
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS=> 'northamptonshire',
+ MAPIT_URL => 'http://mapit.uk/',
+ COBRAND_FEATURES => {
+ extra_state_mapping => {
+ northamptonshire => {
+ investigating => {
+ further => 'Under further investigation'
+ }
+ }
+ }
+ }
+ }, sub {
+ $mech->get_ok('/report/' . $comment->problem_id);
+ };
+
+ $mech->content_contains('Under further investigation');
+
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS=> 'northamptonshire',
+ MAPIT_URL => 'http://mapit.uk/',
+ COBRAND_FEATURES => {
+ extra_state_mapping => {
+ northamptonshire => {
+ fixed => {
+ further => 'Under further investigation'
+ }
+ },
+ fixmystreet => {
+ 'Northamptonshire County Council' => {
+ fixed => {
+ further => 'Under further investigation'
+ }
+ }
+ }
+ }
+ }
+ }, sub {
+ $mech->get_ok('/report/' . $comment->problem_id);
+ };
+
+ $mech->content_contains('Investigating');
+ $mech->content_lacks('Under further investigation');
+
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS=> 'northamptonshire',
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $mech->get_ok('/report/' . $comment->problem_id);
+ };
+
+ $mech->content_contains('Investigating');
+ $mech->content_lacks('Under further investigation');
+
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS=> 'fixmystreet',
+ MAPIT_URL => 'http://mapit.uk/',
+ COBRAND_FEATURES => {
+ extra_state_mapping => {
+ northamptonshire => {
+ investigating => {
+ further => 'Under further investigation'
+ }
+ },
+ fixmystreet => {
+ 'Northamptonshire County Council' => {
+ investigating => {
+ further => 'Under further investigation'
+ }
+ }
+ }
+ }
+ }
+ }, sub {
+ $mech->get_ok('/report/' . $comment->problem_id);
+ };
+
+ $mech->content_contains('Under further investigation');
+
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS=> 'fixmystreet',
+ MAPIT_URL => 'http://mapit.uk/',
+ COBRAND_FEATURES => {
+ extra_state_mapping => {
+ northamptonshire => {
+ fixed => {
+ further => 'Under further investigation'
+ }
+ },
+ fixmystreet => {
+ 'Northamptonshire County Council' => {
+ fixed => {
+ further => 'Under further investigation'
+ }
+ }
+ }
+ }
+ }
+ }, sub {
+ $mech->get_ok('/report/' . $comment->problem_id);
+ };
+
+ $mech->content_contains('Investigating');
+ $mech->content_lacks('Under further investigation');
+
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS=> 'fixmystreet',
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $mech->get_ok('/report/' . $comment->problem_id);
+ };
+
+ $mech->content_contains('Investigating');
+ $mech->content_lacks('Under further investigation');
+
+ $comment->set_extra_metadata('external_status_code' => '');
+ $comment->update;
+ my $comment2 = FixMyStreet::DB->resultset('Comment')->create( {
+ mark_fixed => 0,
+ user => $user,
+ problem => $report,
+ anonymous => 0,
+ text => 'this is a comment',
+ confirmed => DateTime->now,
+ state => 'confirmed',
+ problem_state => 'investigating',
+ cobrand => 'default',
+ } );
+ $comment2->set_extra_metadata('external_status_code' => 'further');
+ $comment2->update;
+
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS=> 'northamptonshire',
+ MAPIT_URL => 'http://mapit.uk/',
+ COBRAND_FEATURES => {
+ extra_state_mapping => {
+ northamptonshire => {
+ investigating => {
+ further => 'Under further investigation'
+ }
+ }
+ }
+ }
+ }, sub {
+ $mech->get_ok('/report/' . $comment->problem_id);
+ };
+
+ $mech->content_contains('Investigating');
+ $mech->content_contains('Under further investigation');
+};
+
subtest 'check pin colour / reference shown' => sub {
FixMyStreet::override_config {
ALLOWED_COBRANDS => 'northamptonshire',
diff --git a/t/cobrand/oxfordshire.t b/t/cobrand/oxfordshire.t
index 65c6a3864..a1c842e2d 100644
--- a/t/cobrand/oxfordshire.t
+++ b/t/cobrand/oxfordshire.t
@@ -1,7 +1,10 @@
use Test::MockModule;
+use CGI::Simple;
use FixMyStreet::TestMech;
use FixMyStreet::Script::Alerts;
+use FixMyStreet::Script::Reports;
+use Open311;
my $mech = FixMyStreet::TestMech->new;
my $oxon = $mech->create_body_ok(2237, 'Oxfordshire County Council');
@@ -50,6 +53,7 @@ subtest 'check /around?ajax defaults to open reports only' => sub {
my @problems = FixMyStreet::DB->resultset('Problem')->search({}, { rows => 3, order_by => 'id' })->all;
FixMyStreet::override_config {
+ STAGING_FLAGS => { send_reports => 1, skip_checks => 1 },
ALLOWED_COBRANDS => 'oxfordshire',
MAPIT_URL => 'http://mapit.uk/',
}, sub {
@@ -63,10 +67,10 @@ FixMyStreet::override_config {
is $mech->uri->path, '/report/' . $problem->id, 'redirects to report';
};
- subtest 'check unable to fix label' => sub {
- my $user = $mech->create_user_ok( 'user@example.com', name => 'Test User' );
- my $user2 = $mech->create_user_ok( 'user2@example.com', name => 'Test User2' );
+ my $user = $mech->create_user_ok( 'user@example.com', name => 'Test User' );
+ my $user2 = $mech->create_user_ok( 'user2@example.com', name => 'Test User2' );
+ subtest 'check unable to fix label' => sub {
my $problem = $problems[0];
$problem->state( 'unable to fix' );
$problem->update;
@@ -128,6 +132,103 @@ FixMyStreet::override_config {
is $rows[2]->[20], '', 'Report without HIAMS ref has empty ref field';
is $rows[3]->[20], '123098123', 'Older Exor report has correct ref';
};
+
+ $oxon->update({
+ send_method => 'Open311',
+ endpoint => 'endpoint',
+ api_key => 'key',
+ jurisdiction => 'home',
+ });
+ my $contact = $mech->create_contact_ok( body_id => $oxon->id, category => 'Gullies and Catchpits', email => 'GC' );
+ $contact->set_extra_fields( (
+ { code => 'feature_id', datatype => 'hidden', variable => 'true' },
+ { code => 'usrn', datatype => 'hidden', variable => 'true' },
+ ) );
+ $contact->update;
+ FixMyStreet::Script::Reports::send(); # Make sure no waiting reports
+
+ for my $test (
+ {
+ field => 'feature_id',
+ value => '12345',
+ text => 'Asset Id',
+ },
+ ) {
+ subtest 'Check special Open311 request handling of ' . $test->{text}, sub {
+ my ($p) = $mech->create_problems_for_body( 1, $oxon->id, 'Test', {
+ cobrand => 'oxfordshire',
+ category => 'Gullies and Catchpits',
+ user => $user,
+ latitude => 51.754926,
+ longitude => -1.256179,
+ });
+ $p->set_extra_fields({ name => $test->{field}, value => $test->{value}});
+ $p->update;
+
+ my $test_data = FixMyStreet::Script::Reports::send();
+
+ $p->discard_changes;
+ ok $p->whensent, 'Report marked as sent';
+ is $p->send_method_used, 'Open311', 'Report sent via Open311';
+ is $p->external_id, 248, 'Report has right external ID';
+ unlike $p->detail, qr/$test->{text}:/, $test->{text} . ' not saved to report detail';
+
+ my $req = $test_data->{test_req_used};
+ my $c = CGI::Simple->new($req->content);
+ like $c->param('description'), qr/$test->{text}: $test->{value}/, $test->{text} . ' included in body';
+ };
+ }
+
+ subtest 'extra data sent with defect update' => sub {
+ my $comment = FixMyStreet::DB->resultset('Comment')->first;
+ $comment->set_extra_metadata(defect_raised => 1);
+ $comment->update;
+ $comment->problem->external_id('hey');
+ $comment->problem->set_extra_metadata(defect_location_description => 'Location');
+ $comment->problem->set_extra_metadata(defect_item_category => 'Kerbing');
+ $comment->problem->set_extra_metadata(defect_item_type => 'Damaged');
+ $comment->problem->set_extra_metadata(defect_item_detail => '1 kerb unit or 1 linear m');
+ $comment->problem->set_extra_metadata(traffic_information => 'Signs and Cones');
+ $comment->problem->set_extra_metadata(detailed_information => '100x100');
+ $comment->problem->update;
+
+ my $cbr = Test::MockModule->new('FixMyStreet::Cobrand::Oxfordshire');
+ $cbr->mock('_fetch_features', sub {
+ my ($self, $cfg, $x, $y) = @_;
+ [ {
+ type => 'Feature',
+ geometry => { type => 'LineString', coordinates => [ [ 1, 2 ], [ 3, 4 ] ] },
+ properties => { TYPE1_2_USRN => 13579 },
+ } ];
+ });
+ my $test_res = HTTP::Response->new();
+ $test_res->code(200);
+ $test_res->message('OK');
+ $test_res->content('<?xml version="1.0" encoding="utf-8"?><service_request_updates><request_update><update_id>248</update_id></request_update></service_request_updates>');
+
+ my $o = Open311->new(
+ fixmystreet_body => $oxon,
+ test_mode => 1,
+ test_get_returns => { 'servicerequestupdates.xml' => $test_res },
+ );
+
+ $o->post_service_request_update($comment);
+ my $cgi = CGI::Simple->new($o->test_req_used->content);
+ is $cgi->param('attribute[usrn]'), 13579, 'USRN sent with update';
+ is $cgi->param('attribute[raise_defect]'), 1, 'Defect flag sent with update';
+ is $cgi->param('attribute[defect_item_category]'), 'Kerbing';
+ is $cgi->param('attribute[extra_details]'), $user2->email . ' TM1 Damaged 100x100';
+
+ # Now set a USRN on the problem (found at submission)
+ $comment->problem->push_extra_fields({ name => 'usrn', value => '12345' });
+ $comment->problem->update;
+
+ $o->post_service_request_update($comment);
+ $cgi = CGI::Simple->new($o->test_req_used->content);
+ is $cgi->param('attribute[usrn]'), 12345, 'USRN sent with update';
+ is $cgi->param('attribute[raise_defect]'), 1, 'Defect flag sent with update';
+ };
+
};
done_testing();
diff --git a/t/cobrand/peterborough.t b/t/cobrand/peterborough.t
index 5d07acb9f..f7e45f190 100644
--- a/t/cobrand/peterborough.t
+++ b/t/cobrand/peterborough.t
@@ -64,7 +64,7 @@ subtest "extra update params are sent to open311" => sub {
test_get_returns => { 'servicerequestupdates.xml' => $test_res },
);
- my ($p) = $mech->create_problems_for_body(1, $peterborough->id, 'Title', { external_id => 1, category => 'Trees' });
+ my ($p) = $mech->create_problems_for_body(1, $peterborough->id, 'Title', { external_id => 1, category => 'Trees', whensent => DateTime->now });
my $c = FixMyStreet::DB->resultset('Comment')->create({
problem => $p, user => $p->user, anonymous => 't', text => 'Update text',
@@ -81,4 +81,83 @@ subtest "extra update params are sent to open311" => sub {
};
};
+subtest "bartec report with no gecode handled correctly" => sub {
+ FixMyStreet::override_config {
+ STAGING_FLAGS => { send_reports => 1 },
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => 'peterborough',
+ }, sub {
+ my $contact = $mech->create_contact_ok(body_id => $peterborough->id, category => 'Bins', email => 'Bartec-Bins');
+ my ($p) = $mech->create_problems_for_body(1, $peterborough->id, 'Title', { category => 'Bins', latitude => 52.5608, longitude => 0.2405, cobrand => 'peterborough' });
+
+ my $test_data = FixMyStreet::Script::Reports::send();
+
+ $p->discard_changes;
+ ok $p->whensent, 'Report marked as sent';
+
+ my $req = $test_data->{test_req_used};
+ my $cgi = CGI::Simple->new($req->content);
+ is $cgi->param('attribute[postcode]'), undef, 'postcode param not set';
+ is $cgi->param('attribute[house_no]'), undef, 'house_no param not set';
+ is $cgi->param('attribute[street]'), undef, 'street param not set';
+ };
+};
+
+subtest "extra bartec params are sent to open311" => sub {
+ FixMyStreet::override_config {
+ STAGING_FLAGS => { send_reports => 1 },
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => 'peterborough',
+ }, sub {
+ my ($p) = $mech->create_problems_for_body(1, $peterborough->id, 'Title', {
+ category => 'Bins',
+ latitude => 52.5608,
+ longitude => 0.2405,
+ cobrand => 'peterborough',
+ geocode => {
+ resourceSets => [ {
+ resources => [ {
+ name => '12 A Street, XX1 1SZ',
+ address => {
+ addressLine => '12 A Street',
+ postalCode => 'XX1 1XZ'
+ }
+ } ]
+ } ]
+ },
+ extra => {
+ _fields => [
+ { name => 'site_code', value => '12345', },
+ ],
+ },
+ } );
+
+ my $test_data = FixMyStreet::Script::Reports::send();
+
+ $p->discard_changes;
+ ok $p->whensent, 'Report marked as sent';
+
+ my $req = $test_data->{test_req_used};
+ my $cgi = CGI::Simple->new($req->content);
+ is $cgi->param('attribute[postcode]'), 'XX1 1XZ', 'postcode param sent';
+ is $cgi->param('attribute[house_no]'), '12', 'house_no param sent';
+ is $cgi->param('attribute[street]'), 'A Street', 'street param sent';
+ };
+};
+
+subtest 'Dashboard CSV extra columns' => sub {
+ my $staffuser = $mech->create_user_ok('counciluser@example.com', name => 'Council User',
+ from_body => $peterborough, password => 'password');
+ $mech->log_in_ok( $staffuser->email );
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => 'peterborough',
+ }, sub {
+ $mech->get_ok('/dashboard?export=1');
+ };
+ $mech->content_contains('"Reported As",USRN,"Nearest address"');
+ $mech->content_contains('peterborough,,12345,"12 A Street, XX1 1SZ"');
+};
+
+
done_testing;
diff --git a/t/cobrand/tfl.t b/t/cobrand/tfl.t
index 8ddc3d671..142c7c14e 100644
--- a/t/cobrand/tfl.t
+++ b/t/cobrand/tfl.t
@@ -23,6 +23,10 @@ FixMyStreet::DB->resultset('BodyArea')->find_or_create({
area_id => 2457, # Epsom Ewell, outside London, for bus stop test
body_id => $body->id,
});
+FixMyStreet::DB->resultset('BodyArea')->find_or_create({
+ area_id => 2508, # Hackney
+ body_id => $body->id,
+});
my $superuser = $mech->create_user_ok('superuser@example.com', name => 'Super User', is_superuser => 1);
my $staffuser = $mech->create_user_ok('counciluser@example.com', name => 'Council User', from_body => $body, password => 'password');
$staffuser->user_body_permissions->create({
@@ -58,6 +62,13 @@ my $bromley_flytipping = $mech->create_contact_ok(
$bromley_flytipping->set_extra_metadata(group => [ 'Street cleaning' ]);
$bromley_flytipping->update;
+my $hackney = $mech->create_body_ok(2508, 'Hackney Council');
+$mech->create_contact_ok(
+ body_id => $hackney->id,
+ category => 'Abandoned Vehicle',
+ email => 'av-hackney@example.com',
+);
+
my $contact1 = $mech->create_contact_ok(
body_id => $body->id,
category => 'Bus stops',
@@ -188,6 +199,7 @@ FixMyStreet::override_config {
ALLOWED_COBRANDS => [ 'tfl', 'bromley', 'fixmystreet'],
MAPIT_URL => 'http://mapit.uk/',
COBRAND_FEATURES => {
+ category_groups => { tfl => 1 },
internal_ips => { tfl => [ '127.0.0.1' ] },
base_url => {
tfl => 'https://street.tfl'
@@ -413,6 +425,7 @@ subtest 'Dashboard CSV extra columns' => sub {
$mech->get_ok('/dashboard?export=1&category=Bus+stops');
$mech->content_contains('Category,Subcategory');
$mech->content_contains('Query,Borough');
+ $mech->content_contains(',Acknowledged,"Action scheduled",Fixed');
$mech->content_contains(',"Safety critical","Delivered to","Closure email at","Reassigned at","Reassigned by","Is the pole leaning?"');
$mech->content_contains('"Bus things","Bus stops"');
$mech->content_contains('"BR1 3UH",Bromley,');
@@ -430,10 +443,17 @@ subtest 'Dashboard CSV extra columns' => sub {
admin_user => $staffuser->name,
user => $staffuser,
});
+ FixMyStreet::DB->resultset('Comment')->create({
+ problem => $report, user => $report->user, anonymous => 't', text => 'Update text',
+ problem_state => 'action scheduled', state => 'confirmed', mark_fixed => 0,
+ confirmed => $dt,
+ });
$mech->get_ok('/dashboard?export=1');
$mech->content_contains('Query,Borough');
+ $mech->content_contains(',Acknowledged,"Action scheduled",Fixed');
$mech->content_contains(',"Safety critical","Delivered to","Closure email at","Reassigned at","Reassigned by"');
$mech->content_contains('(anonymous ' . $report->id . ')');
+ $mech->content_contains($dt . ',,,confirmed,51.4021');
$mech->content_contains(',,,yes,busstops@example.com,,' . $dt . ',"Council User"');
};
@@ -442,7 +462,8 @@ subtest 'Inspect form state choices' => sub {
my $id = $report->id;
$mech->get_ok("/report/$id");
$mech->content_lacks('for triage');
- $mech->content_lacks('action scheduled');
+ $mech->content_lacks('planned');
+ $mech->content_lacks('investigating');
};
subtest "change category, report resent to new location" => sub {
@@ -747,7 +768,7 @@ subtest 'Test no questionnaire sending' => sub {
};
FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'tfl', 'bromley', 'fixmystreet' ],
+ ALLOWED_COBRANDS => [ 'tfl', 'bromley', 'fixmystreet', 'hackney' ],
MAPIT_URL => 'http://mapit.uk/',
COBRAND_FEATURES => {
internal_ips => { tfl => [ '127.0.0.1' ] },
@@ -863,6 +884,21 @@ for my $test (
'Trees'
],
},
+ {
+ host => 'hackney.fixmystreet.com',
+ name => "test no hackney categories on red route",
+ lat => 51.552287,
+ lon => -0.063326,
+ expected => [
+ 'Bus stops',
+ 'Flooding',
+ 'Grit bins',
+ 'Pothole',
+ 'Timings',
+ 'Traffic lights',
+ 'Trees'
+ ],
+ },
) {
subtest $test->{name} . ' on ' . $test->{host} => sub {
$mech->host($test->{host});
diff --git a/t/cobrand/zurich.t b/t/cobrand/zurich.t
index 8c5acddca..c73bd01e1 100644
--- a/t/cobrand/zurich.t
+++ b/t/cobrand/zurich.t
@@ -14,6 +14,9 @@ use FixMyStreet::Script::Reports;
use FixMyStreet::TestMech;
my $mech = FixMyStreet::TestMech->new;
+FixMyStreet::App->log->disable('info');
+END { FixMyStreet::App->log->enable('info'); }
+
# Check that you have the required locale installed - the following
# should return a line with de_CH.utf8 in. If not install that locale.
#
@@ -98,7 +101,7 @@ my $superuser;
subtest "set up superuser" => sub {
$superuser = $mech->log_in_ok( 'super@example.org' );
# a user from body $zurich is a superuser, as $zurich has no parent id!
- $superuser->update({ from_body => $zurich->id });
+ $superuser->update({ name => 'Superuser', from_body => $zurich->id });
$EXISTING_REPORT_COUNT = get_export_rows_count($mech);
$mech->log_out_ok;
};
@@ -747,29 +750,74 @@ subtest "superuser and dm can see stats" => sub {
$user = $mech->log_in_ok( 'dm1@example.org' );
$mech->get( '/admin/stats' );
is $mech->res->code, 200, "dm can now also see stats page";
- $mech->log_out_ok;
};
subtest "only superuser can edit bodies" => sub {
- $user = $mech->log_in_ok( 'dm1@example.org' );
$mech->get( '/admin/body/' . $zurich->id );
is $mech->res->code, 403, "only superuser should be able to edit bodies";
- $mech->log_out_ok;
};
subtest "only superuser can see 'Add body' form" => sub {
- $user = $mech->log_in_ok( 'dm1@example.org' );
$mech->get_ok( '/admin/bodies' );
$mech->content_contains('External Body');
$mech->content_lacks( '<form method="post" action="bodies"' );
- $mech->log_out_ok;
};
subtest "phone number is mandatory" => sub {
- $user = $mech->log_in_ok( 'dm1@example.org' );
$mech->get_ok( '/report/new?lat=47.381817&lon=8.529156' );
$mech->submit_form( with_fields => { phone => "" } );
$mech->content_contains( 'Diese Information wird benötigt' );
+};
+
+my $internal;
+subtest 'test flagged users make internal reports' => sub {
+ $user->update({ flagged => 1 });
+ $mech->submit_form( with_fields => { phone => "01234", category => 'Cat1', detail => 'Details' } );
+ $internal = FixMyStreet::DB->resultset('Problem')->search(undef, { order_by => { -desc => 'id' }, rows => 1 })->single;
+ is $internal->non_public, 1;
+ $mech->clear_emails_ok;
+};
+
+subtest 'internal report admin display' => sub {
+ $mech->get_ok('/admin/summary');
+ $mech->content_lacks('href="report_edit/' . $internal->id);
+ $mech->get_ok('/admin/summary?internal=1');
+ $mech->content_contains('href="report_edit/' . $internal->id);
+};
+
+subtest 'test no email sent if closed' => sub {
+ $internal->state('feedback pending');
+ $internal->set_extra_metadata('email_confirmed' => 1);
+ $internal->update;
+
+ $mech->get_ok( '/admin/report_edit/' . $internal->id );
+ $mech->submit_form_ok( {
+ button => 'publish_response',
+ with_fields => {
+ status_update => 'Testing no email sent',
+ } });
+
+ $internal->discard_changes;
+ is $internal->state, 'fixed - council';
+ $mech->email_count_is(0);
+};
+
+subtest 'SDM closing internal report' => sub {
+ $mech->log_in_ok('sdm1@example.org');
+ $internal->update({ bodies_str => $subdivision->id, state => 'confirmed' });
+ $mech->get_ok('/admin/report_edit/' . $internal->id);
+ $mech->submit_form_ok( { form_number => 2, button => 'no_more_updates' } );
+ $internal->discard_changes;
+ is $internal->state, 'fixed - council', 'State updated';
+};
+
+subtest 'remove internal flag' => sub {
+ $internal->update({ bodies_str => $subdivision->id, state => 'confirmed' });
+ $mech->get_ok('/admin/report_edit/' . $internal->id);
+ $mech->submit_form_ok( { form_number => 2, button => 'stop_internal' } );
+ $internal->discard_changes;
+ is $internal->non_public, 0;
+ $internal->delete;
$mech->log_out_ok;
};
@@ -859,7 +907,7 @@ subtest "photo must be supplied for categories that require it" => sub {
$mech->get_ok('/report/new?lat=47.381817&lon=8.529156');
$mech->submit_form_ok({ with_fields => {
detail => 'Problem-Bericht',
- username => 'user@example.org',
+ username_register => 'user@example.org',
category => 'Graffiti - photo required',
}});
is $mech->res->code, 200, "missing photo shouldn't return anything but 200";
@@ -995,6 +1043,15 @@ $mech->log_out_ok;
subtest 'users at the top level can be edited' => sub {
$mech->log_in_ok( $superuser->email );
$mech->get_ok('/admin/users/' . $superuser->id );
+ $mech->content_contains('name="flagged">');
+ $mech->submit_form_ok({ with_fields => { flagged => 1 } });
+ $superuser->discard_changes;
+ is $superuser->flagged, 1, 'Marked as flagged';
+ $mech->get_ok('/admin/users/' . $superuser->id );
+ $mech->content_contains('name="flagged" checked');
+ $mech->submit_form_ok({ with_fields => { flagged => 0 } });
+ $superuser->discard_changes;
+ is $superuser->flagged, 0, 'Unmarked';
};
subtest 'A visit to /reports is okay' => sub {
diff --git a/t/email.t b/t/email.t
index 7e8e60a8a..ec86af288 100644
--- a/t/email.t
+++ b/t/email.t
@@ -14,4 +14,10 @@ my ($type, $id) = FixMyStreet::Email::check_verp_token($token);
is $type, "report", 'Correct type from token';
is $id, 123, 'Correct ID from token';
+my $verpid = FixMyStreet::Email::unique_verp_id([ "report", 123 ]);
+is $verpid, 'fms-report-123-8fb274c6@example.org', 'VERP id okay';
+
+$verpid = FixMyStreet::Email::unique_verp_id([ "report", 123 ], "example.net");
+is $verpid, 'fms-report-123-8fb274c6@example.net', 'VERP id okay with custom domain';
+
done_testing();
diff --git a/t/geocode/bing.t b/t/geocode/bing.t
new file mode 100644
index 000000000..156f983e1
--- /dev/null
+++ b/t/geocode/bing.t
@@ -0,0 +1,30 @@
+use FixMyStreet::Test;
+use FixMyStreet::Geocode::Bing;
+use Catalyst::Test 'FixMyStreet::App';
+use t::Mock::Bing;
+
+my $c = ctx_request('/');
+
+FixMyStreet::override_config {
+ GEOCODING_DISAMBIGUATION => { bing_culture => 'en-GB' }
+}, sub {
+ my $r = FixMyStreet::Geocode::Bing->string('a result', $c);
+ ok $r->{latitude};
+ ok $r->{longitude};
+};
+
+FixMyStreet::override_config {
+ GEOCODING_DISAMBIGUATION => { bing_country => 'United Kingdom' }
+}, sub {
+ my $r = FixMyStreet::Geocode::Bing->string('two results', $c);
+ is scalar @{$r->{error}}, 2;
+ is $r->{error}[1]{address}, 'Constitution Hill again, London';
+};
+
+my $r = FixMyStreet::Geocode::Bing->string('two results andalow', $c);
+is scalar @{$r->{error}}, 2;
+
+$r = FixMyStreet::Geocode::Bing->string('two results onlylow', $c);
+is scalar @{$r->{error}}, 3;
+
+done_testing;
diff --git a/t/map/bing.t b/t/map/bing.t
new file mode 100644
index 000000000..ae8391871
--- /dev/null
+++ b/t/map/bing.t
@@ -0,0 +1,12 @@
+use Test::More;
+use FixMyStreet::Map::Bing;
+
+my $tiles = FixMyStreet::Map::Bing->map_tiles(x_tile => 8105, y_tile => 5375, zoom_act => 14);
+$tiles = [ map { m{ch/([^?]*)}; $1; } @$tiles ];
+is_deeply $tiles, [ '03131132323220', '03131132323221', '03131132323222', '03131132323223' ];
+
+$tiles = FixMyStreet::Map::Bing->map_tiles(x_tile => 8105, y_tile => 5375, zoom_act => 14, aerial => 1);
+$tiles = [ map { m{ch/([^?]*)\?.*A,G,L}; $1; } @$tiles ];
+is_deeply $tiles, [ '03131132323220', '03131132323221', '03131132323222', '03131132323223' ];
+
+done_testing();
diff --git a/t/map/fms.t b/t/map/fms.t
new file mode 100644
index 000000000..3a562db26
--- /dev/null
+++ b/t/map/fms.t
@@ -0,0 +1,55 @@
+use Test::More;
+use FixMyStreet::Map::FMS;
+
+# Z NI Aerial
+my $expected = {
+ 10 => {
+ 0 => {
+ 0 => 'ch/1010100100.*?=G,L',
+ 1 => 'ch/1010100100.*?A,G,L',
+ },
+ 1 => {
+ 0 => 'ch/1010100100.*?=G,L',
+ 1 => 'ch/1010100100.*?A,G,L',
+ },
+ },
+ 13 => {
+ 0 => {
+ 0 => 'r3131010100100.*?mmOS',
+ 1 => 'ch/3131010100100.*?A,G,L',
+ },
+ 1 => {
+ 0 => 'ch/3131010100100.*?=G,L',
+ 1 => 'ch/3131010100100.*?A,G,L',
+ },
+ },
+ 16 => {
+ 0 => {
+ 0 => 'oml/16/32420/21504',
+ 1 => 'ch/0313131010100100.*?A,G,L',
+ },
+ 1 => {
+ 0 => 'ch/0313131010100100.*?=G,L',
+ 1 => 'ch/0313131010100100.*?A,G,L',
+ },
+ },
+};
+
+subtest "Correct tiles with various parameters" => sub {
+ for my $aerial (0, 1) {
+ for my $ni (0, 1) {
+ for my $zoom (qw(10 13 16)) {
+ my $tiles = FixMyStreet::Map::FMS->map_tiles(
+ x_tile => 32421, y_tile => 21505, zoom_act => $zoom,
+ aerial => $aerial,
+ latitude => $ni ? 55 : 51,
+ longitude => $ni ? -6 : -2,
+ );
+ my $wanted = $expected->{$zoom}{$ni}{$aerial};
+ like $tiles->[0], qr/$wanted/, "with zoom $zoom, NI $ni, aerial $aerial";
+ }
+ }
+ }
+};
+
+done_testing();
diff --git a/t/map/google.t b/t/map/google.t
index e2877f53c..e97279072 100644
--- a/t/map/google.t
+++ b/t/map/google.t
@@ -13,7 +13,7 @@ is_deeply $c->stash->{map}, {
type => 'google',
zoom => 15,
zoomOffset => 0,
- numZoomLevels => 19,
+ numZoomLevels => 20,
zoom_act => 15,
};
diff --git a/t/map/tests.t b/t/map/tests.t
index 7d7efab22..e6de55b8f 100644
--- a/t/map/tests.t
+++ b/t/map/tests.t
@@ -18,7 +18,6 @@ my $requires = {
'MasterMap' => 'map-mastermap.js',
'Northamptonshire' => 'map-wms-northamptonshire.js',
'CycleMap' => 'OpenStreetMap.js',
- 'MapQuest' => 'OpenStreetMap.js',
'StreetView' => 'map-streetview.js',
'TonerLite' => 'map-toner-lite.js',
'Zurich' => 'map-wmts-zurich.js',
diff --git a/t/open311.t b/t/open311.t
index 9524006b8..941e35f7e 100644
--- a/t/open311.t
+++ b/t/open311.t
@@ -402,6 +402,7 @@ subtest 'Hounslow update description is correct for a different user' => sub {
my $comment = make_comment('hounslow');
$comment->user($user2);
+ $comment->name($user2->name);
my $results;
FixMyStreet::override_config {
ALLOWED_COBRANDS => 'hounslow',
diff --git a/t/open311/getservicerequests.t b/t/open311/getservicerequests.t
index 672459f3f..7a69d0ff6 100644
--- a/t/open311/getservicerequests.t
+++ b/t/open311/getservicerequests.t
@@ -534,6 +534,46 @@ subtest "non_public contacts result in non_public reports" => sub {
};
+subtest "staff and non_public contacts result in non_public reports" => sub {
+
+ $contact->update({
+ non_public => 1,
+ state => 'staff'
+ });
+ my $o = Open311->new(
+ jurisdiction => 'mysociety',
+ endpoint => 'http://example.com',
+ test_mode => 1,
+ test_get_returns => { 'requests.xml' => prepare_xml( {} ) }
+ );
+
+ my $update = Open311::GetServiceRequests->new(
+ system_user => $user,
+ start_date => $start_date,
+ end_date => $end_date
+ );
+
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $update->create_problems( $o, $body );
+ };
+
+ my $p = FixMyStreet::DB->resultset('Problem')->search(
+ { external_id => 123456, category => $contact->category }
+ )->first;
+
+ ok $p, 'problem created';
+ is $p->non_public, 1, "report non_public is set correctly";
+
+ $p->delete;
+ $contact->update({
+ non_public => 0,
+ state => 'confirmed'
+ });
+
+};
+
for my $test (
{
test_desc => 'filters out phone numbers',
diff --git a/t/open311/getupdates.t b/t/open311/getupdates.t
index 351f17f6f..c1e51d380 100644
--- a/t/open311/getupdates.t
+++ b/t/open311/getupdates.t
@@ -18,9 +18,6 @@ my $body = FixMyStreet::DB->resultset('Body')->new( {
name => 'Test Body',
} );
-my $updates = Open311::GetUpdates->new( system_user => $user );
-ok $updates, 'created object';
-
my $requests_xml = qq{<?xml version="1.0" encoding="utf-8"?>
<service_requests>
<request>
@@ -101,7 +98,12 @@ for my $test (
my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'requests.xml' => $local_requests_xml } );
- ok $updates->update_reports( [ 638344 ], $o, $body ), 'Updated reports';
+ my $updates = Open311::GetUpdates->new(
+ system_user => $user,
+ current_open311 => $o,
+ current_body => $body,
+ );
+ $updates->update_reports( [ $problem ] );
my @parts = uri_split($o->test_uri_used);
is $parts[2], '/requests.xml', 'path matches';
my @qs = sort split '&', $parts[3];
@@ -179,7 +181,13 @@ subtest 'update with two requests' => sub {
my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'requests.xml' => $local_requests_xml } );
- ok $updates->update_reports( [ 638344,638345 ], $o, $body ), 'Updated reports';
+ my $updates = Open311::GetUpdates->new(
+ system_user => $user,
+ current_open311 => $o,
+ current_body => $body,
+ );
+
+ $updates->update_reports( [ $problem, $problem2 ] );
my @parts = uri_split($o->test_uri_used);
is $parts[2], '/requests.xml', 'path matches';
my @qs = sort split '&', $parts[3];
@@ -227,7 +235,7 @@ my $problem3 = $problem_rs->create( {
external_id => 638346,
} );
-subtest 'test translation of auto-added comment from old-style Open311 update' => sub {
+subtest 'test auto-added comment from old-style Open311 update' => sub {
my $dt = sprintf( '<updated_datetime>%s</updated_datetime>', DateTime->now );
$requests_xml =~ s/UPDATED_DATETIME/$dt/;
@@ -236,7 +244,13 @@ subtest 'test translation of auto-added comment from old-style Open311 update' =
FixMyStreet::override_config {
ALLOWED_COBRANDS => [ 'fixamingata' ],
}, sub {
- ok $updates->update_reports( [ 638346 ], $o, $body ), 'Updated reports';
+ my $updates = Open311::GetUpdates->new(
+ system_user => $user,
+ current_open311 => $o,
+ current_body => $body,
+ blank_updates_permitted => 1,
+ );
+ $updates->update_reports( [ $problem3 ] );
};
my @parts = uri_split($o->test_uri_used);
is $parts[2], '/requests.xml', 'path matches';
@@ -244,7 +258,8 @@ subtest 'test translation of auto-added comment from old-style Open311 update' =
is_deeply(\@qs, [ 'jurisdiction_id=mysociety', 'service_request_id=638346' ], 'query string matches');
is $problem3->comments->count, 1, 'added a comment';
- is $problem3->comments->first->text, "Stängd av kommunen", 'correct comment text';
+ is $problem3->comments->first->problem_state, 'fixed - council';
+ is $problem3->comments->first->text, '', 'correct comment text';
};
END {
diff --git a/t/open311/populate-service-list.t b/t/open311/populate-service-list.t
index bd837f203..20f092da4 100644
--- a/t/open311/populate-service-list.t
+++ b/t/open311/populate-service-list.t
@@ -175,33 +175,53 @@ subtest "set multiple groups with groups element" => sub {
is_deeply $contact->get_extra->{group}, ['sanitation & cleaning','street'], "groups set correctly";
};
-subtest 'check non open311 contacts marked as deleted' => sub {
- FixMyStreet::DB->resultset('Contact')->search( { body_id => $body->id } )->delete();
+$body->update({ can_be_devolved => 1 });
+for my $test (
+ {
+ test => 'check non open311 contacts marked as deleted',
+ contact_params => {
+ email => 'contact@example.com',
+ },
+ deleted => 1,
+ },
+ {
+ test => 'check devolved non open311 contacts not marked as deleted',
+ contact_params => {
+ email => 'contact',
+ send_method => 'Open311',
+ },
+ deleted => 0,
+ },
+) {
+ subtest $test->{test} => sub {
+ FixMyStreet::DB->resultset('Contact')->search( { body_id => $body->id } )->delete();
- my $contact = FixMyStreet::DB->resultset('Contact')->create(
- {
- body_id => $body->id,
- email => 'contact@example.com',
- category => 'An old category',
- state => 'confirmed',
- editor => $0,
- whenedited => \'current_timestamp',
- note => 'test contact',
- }
- );
+ my $contact = FixMyStreet::DB->resultset('Contact')->create(
+ {
+ body_id => $body->id,
+ category => 'An old category',
+ state => 'confirmed',
+ editor => $0,
+ whenedited => \'current_timestamp',
+ note => 'test contact',
+ %{$test->{contact_params}},
+ }
+ );
- my $service_list = get_xml_simple_object( get_standard_xml() );
+ my $service_list = get_xml_simple_object( get_standard_xml() );
- my $processor = Open311::PopulateServiceList->new();
- $processor->_current_body( $body );
- $processor->process_services( $service_list );
+ my $processor = Open311::PopulateServiceList->new();
+ $processor->_current_body( $body );
+ $processor->process_services( $service_list );
- my $contact_count = FixMyStreet::DB->resultset('Contact')->search( { body_id => $body->id } )->count();
- is $contact_count, 4, 'correct number of contacts';
+ my $contact_count = FixMyStreet::DB->resultset('Contact')->search( { body_id => $body->id } )->count();
+ is $contact_count, 4, 'correct number of contacts';
- $contact_count = FixMyStreet::DB->resultset('Contact')->search( { body_id => $body->id, state => 'deleted' } )->count();
- is $contact_count, 1, 'correct number of deleted contacts';
-};
+ $contact_count = FixMyStreet::DB->resultset('Contact')->search( { body_id => $body->id, state => 'deleted' } )->count();
+ is $contact_count, $test->{deleted}, 'correct number of deleted contacts';
+ };
+}
+$body->update({ can_be_devolved => 0 });
subtest 'check email changed if matching category' => sub {
FixMyStreet::DB->resultset('Contact')->search( { body_id => $body->id } )->delete();
diff --git a/t/open311/post-service-request-updates.t b/t/open311/post-service-request-updates.t
index adfd4e3c5..03fcbeae4 100644
--- a/t/open311/post-service-request-updates.t
+++ b/t/open311/post-service-request-updates.t
@@ -1,12 +1,13 @@
#!/usr/bin/env perl
use FixMyStreet::TestMech;
+use Test::Output;
my $mech = FixMyStreet::TestMech->new;
use_ok( 'Open311::PostServiceRequestUpdates' );
-my $o = Open311::PostServiceRequestUpdates->new( site => 'fixmystreet.com' );
+my $o = Open311::PostServiceRequestUpdates->new;
my $params = {
send_method => 'Open311',
@@ -15,7 +16,10 @@ my $params = {
endpoint => 'endpoint',
jurisdiction => 'home',
};
-my $bromley = $mech->create_body_ok(2482, 'Bromley', { %$params, send_extended_statuses => 1 });
+my $bromley = $mech->create_body_ok(2482, 'Bromley', { %$params,
+ endpoint => 'www.bromley.gov.uk',
+ send_extended_statuses => 1,
+ can_be_devolved => 1 });
my $oxon = $mech->create_body_ok(2237, 'Oxfordshire', { %$params, id => "5" . $bromley->id });
my $bucks = $mech->create_body_ok(2217, 'Buckinghamshire', $params);
my $lewisham = $mech->create_body_ok(2492, 'Lewisham', $params);
@@ -33,6 +37,7 @@ subtest 'Check Open311 params' => sub {
my %conf = $o->open311_params($bromley);
is_deeply \%conf, {
%$result,
+ endpoint => 'www.bromley.gov.uk',
extended_statuses => 1,
endpoints => { service_request_updates => 'update.xml', update => 'update.xml' },
fixmystreet_body => $bromley,
@@ -130,8 +135,16 @@ subtest 'Oxfordshire gets an ID' => sub {
$o->send;
$c2->discard_changes;
is $c2->send_fail_count, 1, 'Oxfordshire update tried to send, failed';
+ stdout_like { $o->summary_failures } qr/The following updates failed sending/;
};
};
+subtest 'Devolved contact' => sub {
+ $mech->create_contact_ok(body_id => $bromley->id, category => 'Other', email => "OTHER", send_method => 'Open311', endpoint => '/devolved-endpoint/');
+ $c1->update({ send_fail_count => 0 });
+ $o->send;
+ $c1->discard_changes;
+ like $c1->send_fail_reason, qr/devolved-endpoint/, 'Failure message contains correct endpoint';
+};
done_testing();
diff --git a/t/roles/translatable.t b/t/roles/translatable.t
index 9f8c67394..beddb7182 100644
--- a/t/roles/translatable.t
+++ b/t/roles/translatable.t
@@ -77,8 +77,9 @@ FixMyStreet::override_config {
subtest 'Check display_name override' => sub {
$contact->set_extra_metadata( display_name => 'Override name' );
$contact->update;
- is $contact->category_display, "Override name";
- is $problem->category_display, "Override name";
+ is $contact->category_display, "Override name", 'Contact uses display_name';
+ $problem->discard_changes;
+ is $problem->category_display, "Override name", 'Problem uses display_name';
};
done_testing;
diff --git a/t/script/tfl/autoclose.t b/t/script/tfl/autoclose.t
new file mode 100644
index 000000000..91f46867c
--- /dev/null
+++ b/t/script/tfl/autoclose.t
@@ -0,0 +1,216 @@
+use FixMyStreet::TestMech;
+use DateTime;
+use Test::Output;
+
+use_ok 'FixMyStreet::Script::TfL::AutoClose';
+
+my $close = FixMyStreet::Script::TfL::AutoClose->new( commit => 1 );
+my $no_commit = FixMyStreet::Script::TfL::AutoClose->new();
+my $mech = FixMyStreet::TestMech->new;
+
+
+my $area_id = 2651;
+my $body = $mech->create_body_ok($area_id, 'TfL');
+my $body_user = $mech->create_user_ok('tfl@example.com', name => 'TfL', from_body => $body);
+$body->update( { comment_user_id => $body_user->id } );
+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 $c3 = $mech->create_contact_ok(category => 'Flytipping', body_id => $body->id, email => 'f');
+my $t1 = FixMyStreet::DB->resultset('ResponseTemplate')->create({
+ body_id => $body->id, title => "Not auto closed", text => "Text 1 ⛄", state => "fixed - council" }
+);
+my $t2 = FixMyStreet::DB->resultset('ResponseTemplate')->create({
+ body_id => $body->id, title => "Auto closed", text => "Text 2", state => "fixed - council", auto_response => 1
+});
+my $t3 = FixMyStreet::DB->resultset('ResponseTemplate')->create({
+ body_id => $body->id, title => "Investigating", text => "Text 3", state => "investigating", auto_response => 1
+});
+$t1->add_to_contacts($c1);
+$t2->add_to_contacts($c2);
+$t3->add_to_contacts($c3);
+
+is_deeply keys %{ $close->categories }, ("Graffiti"), "fetches correct category list";
+
+my $now = DateTime->now;
+
+my %problems;
+for my $p (
+ {
+ category => 'Grafitti',
+ state => 'in progress',
+ test => 'category_not_state',
+ date => $now->clone->add( days => -30 ),
+ },
+ {
+ category => 'Grafitti',
+ state => 'action scheduled',
+ test => 'category_state',
+ date => $now->clone->add( days => -30 ),
+ },
+ {
+ category => 'Potholes',
+ state => 'action scheduled',
+ test => 'not_category_state',
+ date => $now->clone->add( days => -30 ),
+ },
+ {
+ category => 'Grafitti',
+ state => 'action scheduled',
+ test => 'category_state_not_old',
+ date => $now->clone->add( days => -20 ),
+ }
+) {
+ my $k = delete $p->{test};
+ my $d = delete $p->{date};
+ $p->{confirmed} = $d;
+ $p->{lastupdate} = $d;
+ ($problems{$k}) = $mech->create_problems_for_body( 1, $body->id, 'Title', $p);
+ my $c = FixMyStreet::DB->resultset('Comment')->create({
+ problem => $problems{$k},
+ text => 'comment',
+ state => 'confirmed',
+ problem_state => $p->{state},
+ user => $body_user,
+ confirmed => $p->{lastupdate}
+ });
+ is $problems{$k}->comments->count, 1, "comment added";
+}
+
+subtest "check that nothing saved without commit arg" => sub {
+ ok $no_commit->close_reports({ 'Grafitti' => $t2 }), "close reports ran";
+ $_->discard_changes for values %problems;
+
+ is $problems{category_not_state}->state, 'in progress', 'ignores incorrect state';
+ is $problems{category_state}->state, 'action scheduled', 'not updated to fixed';
+ is $problems{not_category_state}->state, 'action scheduled', 'ignores incorrect category';
+ is $problems{category_state_not_old}->state, 'action scheduled', 'ignores newer reports';
+
+ is $problems{category_state}->comments->count, 1, "no comment added";
+};
+
+subtest "check that reports are updated" => sub {
+ ok $close->close_reports({ 'Grafitti' => $t2 }), "close reports ran";
+
+ $_->discard_changes for values %problems;
+
+ is $problems{category_not_state}->state, 'in progress', 'ignores incorrect state';
+ is $problems{category_state}->state, 'fixed - council', 'updates to fixed';
+ is $problems{not_category_state}->state, 'action scheduled', 'ignores incorrect category';
+ is $problems{category_state_not_old}->state, 'action scheduled', 'ignores newer reports';
+
+ my $comment = ( $problems{category_state}->comments->search({}, { order_by => 'id' })->all )[-1];
+ is $comment->text, "Text 2", "correct template used when closing";
+};
+
+subtest "check that days argument works" => sub {
+ my $close_newer = FixMyStreet::Script::TfL::AutoClose->new( days => 19, commit => 1 );
+ ok $close_newer->close_reports({ 'Grafitti' => $t2 }), "close reports ran";
+
+ $problems{category_state_not_old}->discard_changes;
+ is $problems{category_state_not_old}->state, 'fixed - council', 'updates to fixed';
+};
+
+subtest 'check that uses oldest comment for time' => sub {
+ my $latest = $now->clone->add( days => -20 );
+ my $oldest = $now->clone->add( days => -30 );
+ my ($p) = $mech->create_problems_for_body( 1, $body->id, 'Title', {
+ category => 'Grafitti',
+ state => 'action scheduled',
+ user => $body_user,
+ lastupdate => $latest,
+ confirmed => $latest,
+ });
+
+ my $first = FixMyStreet::DB->resultset('Comment')->create({
+ problem => $p,
+ problem_state => 'investigating',
+ text => 'comment',
+ state => 'confirmed',
+ user => $body_user,
+ confirmed => $oldest
+ });
+
+ FixMyStreet::DB->resultset('Comment')->create({
+ problem => $p,
+ text => 'comment',
+ state => 'confirmed',
+ problem_state => 'action scheduled',
+ user => $body_user,
+ confirmed => $latest
+ });
+
+ ok $close->close_reports({ 'Grafitti' => $t2 }), "close reports ran";
+
+ $p->discard_changes;
+ is $p->state, 'action scheduled', 'ignores comments with wrong state';
+
+
+ $first->update( { problem_state => 'action scheduled' });
+ ok $close->close_reports({ 'Grafitti' => $t2 }), "close reports ran";
+
+ $p->discard_changes;
+ is $p->state, 'fixed - council', 'updates to fixed';
+};
+
+subtest 'check that changing state accounted for' => sub {
+ my $latest = $now->clone->add( days => -20 );
+ my $oldest = $now->clone->add( days => -30 );
+ my ($p) = $mech->create_problems_for_body( 1, $body->id, 'Title', {
+ category => 'Grafitti',
+ state => 'action scheduled',
+ user => $body_user,
+ lastupdate => $latest,
+ confirmed => $latest,
+ });
+
+ my $investigating = FixMyStreet::DB->resultset('Comment')->create({
+ problem => $p,
+ problem_state => 'investigating',
+ text => 'comment',
+ state => 'confirmed',
+ user => $body_user,
+ confirmed => $latest
+ });
+
+ FixMyStreet::DB->resultset('Comment')->create({
+ problem => $p,
+ text => 'comment',
+ state => 'confirmed',
+ problem_state => 'action scheduled',
+ user => $body_user,
+ confirmed => $oldest
+ });
+
+ FixMyStreet::DB->resultset('Comment')->create({
+ problem => $p,
+ text => 'comment',
+ state => 'confirmed',
+ problem_state => 'action scheduled',
+ user => $body_user,
+ confirmed => $now
+ });
+
+ ok $close->close_reports({ 'Grafitti' => $t2 }), "close reports ran";
+
+ $p->discard_changes;
+ is $p->state, 'action scheduled', 'change of state resets time';
+
+
+ $investigating->update( { problem_state => 'action scheduled' });
+ ok $close->close_reports({ 'Grafitti' => $t2 }), "close reports ran";
+
+ $p->discard_changes;
+ is $p->state, 'fixed - council', 'updates to fixed';
+};
+subtest 'check verbose works' => sub {
+ my $verbose = FixMyStreet::Script::TfL::AutoClose->new( commit => 1, verbose => 1 );
+ stdout_is { $close->close_reports({ 'Grafitti' => $t2 }) } "", "No message displayed with verbose";
+ stdout_is { $verbose->close_reports({ 'Grafitti' => $t2 }) } "0 reports closed\n", "Message displayed with verbose";
+};
+
+subtest 'check dry run warning displayed' => sub {
+ stderr_is { $no_commit->close() } "DRY RUN: use --commit to close reports\n", "Dry run warning message displayed without commit";
+ stderr_is { $close->close() } "", "No warning displayed with commit";
+};
+
+done_testing;
diff --git a/t/workingdays.t b/t/workingdays.t
new file mode 100644
index 000000000..326cf05c9
--- /dev/null
+++ b/t/workingdays.t
@@ -0,0 +1,21 @@
+use Test::More;
+use DateTime;
+
+use_ok 'FixMyStreet::WorkingDays';
+
+
+my $wd = FixMyStreet::WorkingDays->new(
+ public_holidays => [
+ '2020-09-21',
+ '2020-09-15',
+ ],
+);
+
+my $dt = DateTime->new(year => 2020, month => 9, day => 19);
+
+is $wd->add_days($dt, 1)->ymd, '2020-09-22';
+is $wd->sub_days($dt, 5)->ymd, '2020-09-11';
+is $wd->is_public_holiday($dt), undef;
+is $wd->is_weekend($dt), 1;
+
+done_testing;