aboutsummaryrefslogtreecommitdiffstats
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/Mock/MapIt.pm33
-rw-r--r--t/Mock/OpenIDConnect.pm77
-rw-r--r--t/Mock/Tilma.pm52
-rw-r--r--t/app/01app.t42
-rw-r--r--t/app/controller/about.t9
-rw-r--r--t/app/controller/admin.t28
-rw-r--r--t/app/controller/admin/bodies.t129
-rw-r--r--t/app/controller/admin/defecttypes.t21
-rw-r--r--t/app/controller/admin/manifesttheme.t340
-rw-r--r--t/app/controller/admin/permissions.t8
-rw-r--r--t/app/controller/admin/priorities.t43
-rw-r--r--t/app/controller/admin/report_edit.t25
-rw-r--r--t/app/controller/admin/reportextrafields.t131
-rw-r--r--t/app/controller/admin/roles.t139
-rw-r--r--t/app/controller/admin/search.t6
-rw-r--r--t/app/controller/admin/templates.t159
-rw-r--r--t/app/controller/admin/translations.t2
-rw-r--r--t/app/controller/admin/triage.t126
-rw-r--r--t/app/controller/admin/update_edit.t30
-rw-r--r--t/app/controller/admin/users.t159
-rw-r--r--t/app/controller/admin/users_import.t34
-rw-r--r--t/app/controller/alert_new.t179
-rw-r--r--t/app/controller/around.t100
-rw-r--r--t/app/controller/auth.t171
-rw-r--r--t/app/controller/auth_phone.t2
-rw-r--r--t/app/controller/auth_profile.t111
-rw-r--r--t/app/controller/auth_social.t246
-rw-r--r--t/app/controller/contact.t102
-rw-r--r--t/app/controller/contact_enquiry.t267
-rw-r--r--t/app/controller/dashboard.t43
-rw-r--r--t/app/controller/index.t9
-rw-r--r--t/app/controller/moderate.t65
-rw-r--r--t/app/controller/my.t2
-rw-r--r--t/app/controller/my_planned.t8
-rw-r--r--t/app/controller/offline.t67
-rw-r--r--t/app/controller/open311.t10
-rw-r--r--t/app/controller/open311_updates.t99
-rw-r--r--t/app/controller/photo.t72
-rw-r--r--t/app/controller/questionnaire.t25
-rw-r--r--t/app/controller/report_as_other.t62
-rw-r--r--t/app/controller/report_display.t82
-rw-r--r--t/app/controller/report_import.t9
-rw-r--r--t/app/controller/report_inspect.t164
-rw-r--r--t/app/controller/report_interest_count.t2
-rw-r--r--t/app/controller/report_new.t1143
-rw-r--r--t/app/controller/report_new_anon.t272
-rw-r--r--t/app/controller/report_new_errors.t745
-rw-r--r--t/app/controller/report_new_mobile.t5
-rw-r--r--t/app/controller/report_new_open311.t216
-rw-r--r--t/app/controller/report_new_staff.t268
-rw-r--r--t/app/controller/report_new_text.t12
-rw-r--r--t/app/controller/report_new_unresponsive.t122
-rw-r--r--t/app/controller/report_new_update.t71
-rw-r--r--t/app/controller/report_non_public.t87
-rw-r--r--t/app/controller/report_update_text.t12
-rw-r--r--t/app/controller/report_updates.t71
-rw-r--r--t/app/controller/reports.t7
-rw-r--r--t/app/controller/root.t12
-rw-r--r--t/app/controller/rss.t20
-rw-r--r--t/app/controller/sample.pdfbin0 -> 12501 bytes
-rw-r--r--t/app/controller/token.t4
-rw-r--r--t/app/helpers/send_email.t12
-rw-r--r--t/app/helpers/send_email_sample.txt2
-rw-r--r--t/app/helpers/send_email_sample_mime.txt2
-rw-r--r--t/app/model/alert_type.t38
-rw-r--r--t/app/model/defecttype.t15
-rw-r--r--t/app/model/extra.t72
-rw-r--r--t/app/model/problem.t17
-rw-r--r--t/app/model/responsepriority.t17
-rw-r--r--t/app/model/responsetemplate.t2
-rw-r--r--t/app/model/session.t4
-rw-r--r--t/app/model/state.t8
-rw-r--r--t/app/model/user.t43
-rw-r--r--t/app/sendreport/email.t8
-rw-r--r--t/app/sendreport/email/highways.t13
-rw-r--r--t/app/sendreport/email/tfl.t32
-rw-r--r--t/app/sendreport/inspection_required.t100
-rw-r--r--t/app/sendreport/open311.t74
-rw-r--r--t/cobrand/bathnes.t42
-rw-r--r--t/cobrand/bexley.t281
-rw-r--r--t/cobrand/bristol.t10
-rw-r--r--t/cobrand/bromley.t7
-rw-r--r--t/cobrand/bucks.t121
-rw-r--r--t/cobrand/cheshireeast.t129
-rw-r--r--t/cobrand/councils.t68
-rw-r--r--t/cobrand/eastsussex.t42
-rw-r--r--t/cobrand/features.t20
-rw-r--r--t/cobrand/fixmystreet.t31
-rw-r--r--t/cobrand/form_extras.t2
-rw-r--r--t/cobrand/greenwich.t25
-rw-r--r--t/cobrand/highwaysengland.t70
-rw-r--r--t/cobrand/hounslow.t101
-rw-r--r--t/cobrand/isleofwight.t628
-rw-r--r--t/cobrand/national_assets.t1
-rw-r--r--t/cobrand/northamptonshire.t126
-rw-r--r--t/cobrand/oxfordshire.t223
-rw-r--r--t/cobrand/peterborough.t84
-rw-r--r--t/cobrand/restriction.t5
-rw-r--r--t/cobrand/staging.t18
-rw-r--r--t/cobrand/tfl.t1089
-rw-r--r--t/cobrand/westminster.t259
-rw-r--r--t/cobrand/zurich.t1100
-rw-r--r--t/cobrand/zurich_attachments.txt4
-rw-r--r--t/geocode/google.t4
-rw-r--r--t/geocode/highwaysengland.t108
-rw-r--r--t/geocode/roads.sqlitebin0 -> 62464 bytes
-rw-r--r--t/i18n.t32
-rw-r--r--t/map/cheshireeast.t18
-rw-r--r--t/map/mastermap.t22
-rw-r--r--t/map/tests.t15
-rw-r--r--t/open311.t96
-rw-r--r--t/open311/getservicerequests.t149
-rw-r--r--t/open311/getservicerequestupdates.t397
-rw-r--r--t/open311/getupdates.t9
-rw-r--r--t/open311/populate-service-list.t403
-rw-r--r--t/open311/post-service-request-updates.t31
-rw-r--r--t/roles/translatable.t7
-rw-r--r--t/script/createsuperuser.t23
-rw-r--r--t/script/inactive.t81
-rw-r--r--t/sendreport/open311.t63
-rw-r--r--t/template.t39
121 files changed, 10044 insertions, 2955 deletions
diff --git a/t/Mock/MapIt.pm b/t/Mock/MapIt.pm
index ea1f5b259..d49294a6a 100644
--- a/t/Mock/MapIt.pm
+++ b/t/Mock/MapIt.pm
@@ -27,23 +27,37 @@ my @PLACES = (
[ 'EH1 1BB', 55.952055, -3.189579, 2651, 'Edinburgh City Council', 'UTA', 20728, 'City Centre', 'UTE' ],
[ 'BS10 5EE', 51.494885, -2.602237, 2561, 'Bristol City Council', 'UTA', 148646, 'Bedminster', 'UTW' ],
[ 'BS20 5EE', 51.496194, -2.603439, 2608, 'Borsetshire County Council', 'CTY', 148646, 'Bedminster', 'UTW' ],
- [ 'SL9 0NX', 51.615559, -0.556903, 2217, 'Buckinghamshire County Council', 'CTY', 2257, 'Chiltern District Council', 'DIS' ],
+ [ 'SL9 0NX', 51.615559, -0.556903, 2217, 'Buckinghamshire Council', 'CTY', 2257, 'Chiltern District Council', 'DIS' ],
+ [ '?', 51.615499, -0.556667, 2217, 'Buckinghamshire Council', 'CTY', 2257, 'Chiltern District Council', 'DIS' ],
+ [ '?', 51.615439, -0.558362, 2217, 'Buckinghamshire Council', 'CTY', 2257, 'Chiltern District Council', 'DIS' ],
[ 'SW1A 1AA', 51.501009, -0.141588, 2504, 'Westminster City Council', 'LBO' ],
[ 'GL50 2PR', 51.896268, -2.093063, 2226, 'Gloucestershire County Council', 'CTY', 2326, 'Cheltenham Borough Council', 'DIS', 4544, 'Lansdown', 'DIW', 143641, 'Lansdown and Park', 'CED' ],
[ 'OX20 1SZ', 51.754926, -1.256179, 2237, 'Oxfordshire County Council', 'CTY', 2421, 'Oxford City Council', 'DIS' ],
[ 'OX16 9UP', 52.038712, -1.346397, 2237, 'Oxfordshire County Council', 'CTY', 2419, 'Cherwell District Council', 'DIS', 151767, "Banbury, Calthorpe & Easington", "DIW" ],
- [ 'RG9 6TL', 51.561705, -0.868388, 2217, 'Buckinghamshire County Council', 'CTY'],
+ [ 'RG9 6TL', 51.561705, -0.868388, 2217, 'Buckinghamshire Council', 'CTY'],
[ 'PE9 2GX', 52.656144, -0.502566, 2232, 'Lincolnshire County Council', 'CTY'],
[ 'LE15 0GJ', 52.670447, -0.727877, 2600, 'Rutland County Council', 'CTY'],
[ 'BR1 3UH', 51.4021, 0.01578, 2482, 'Bromley Council', 'LBO' ],
[ 'BR1 3UH', 51.402096, 0.015784, 2482, 'Bromley Council', 'LBO' ],
- [ 'NN1 1NS', 52.236251, 0.892052, 2234, 'Northamptonshire County Council', 'CTY' ],
+ [ 'BR1 3EF', 51.4039, 0.018697, 2482, 'Bromley Council', 'LBO' ],
+ [ 'NN1 1NS', 52.236251, -0.892052, 2234, 'Northamptonshire County Council', 'CTY', 2397, 'Northampton Borough Council', 'DIS' ],
+ [ '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' ],
+ [ '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' ],
+ [ 'PE1 1HF', 52.57146, -0.24201, 2566, 'Peterborough City Council', 'UTA' ],
[ 'OX28 4DS', 51.784721, -1.494453 ],
[ 'E14 2DN', 51.508536, '0.000001' ],
+ [ '?', 52.51093, -1.86514, 11809, 'West Midlands', 'EUR' ],
# Norway
[ '3290', 59, 10, 709, 'Larvik', 'NKO', 7, 'Vestfold', 'NFY' ],
[ '0045', "59.9", "10.9", 301, 'Oslo', 'NKO', 3, 'Oslo', 'NFY' ],
@@ -89,8 +103,8 @@ sub dispatch_request {
}
}
my $response = {
- "63999" => {"parent_area" => 2245, "generation_high" => 25, "all_names" => {}, "id" => 63999, "codes" => {"ons" => "00HYNS", "gss" => "E05008366", "unit_id" => "44025"}, "name" => "Kington", "country" => "E", "type_name" => "Unitary Authority electoral division (UTE)", "generation_low" => 12, "country_name" => "England", "type" => "UTE"},
- "2245" => {"parent_area" => undef, "generation_high" => 25, "all_names" => {}, "id" => 2245, "codes" => {"ons" => "00HY", "gss" => "E06000054", "unit_id" => "43925"}, "name" => "Wiltshire Council", "country" => "E", "type_name" => "Unitary Authority", "generation_low" => 11, "country_name" => "England", "type" => "UTA"}
+ "153255" => {"parent_area" => 2608, "generation_high" => 36, "all_names" => {}, "id" => 153255, "codes" => {"gss" => "E05012110", "unit_id" => "174450"}, "name" => "Chipping Sodbury & Cotswold Edge", "country" => "E", "type_name" => "Unitary Authority ward (UTW)", "generation_low" => 36, "country_name" => "England", "type" => "UTW"},
+ "2608" => {"parent_area" => undef, "generation_high" => 36, "all_names" => {}, "id" => 2608, "codes" => {"ons" => "00HD", "gss" => "E06000025", "unit_id" => "25559"}, "name" => "South Gloucestershire Council", "country" => "E", "type_name" => "Unitary Authority", "generation_low" => 1, "country_name" => "England", "type" => "UTA"}
};
return $self->output($response);
},
@@ -107,6 +121,15 @@ 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 'GRE') {
+ $self->output({2493 => {parent_area => undef, id => 2493, name => "Greenwich Borough Council", type => "LBO"}});
+ } elsif ($areas eq 'LBO') {
+ $self->output({
+ 2482 => {parent_area => undef, id => 2482, name => "Bromley Borough Council", type => "LBO"},
+ 2483 => {parent_area => undef, id => 2483, name => "Hounslow Borough Council", type => "LBO"},
+ });
+ } elsif ($areas eq 60705) {
+ $self->output({60705 => {parent_area => 2245, id => 60705, name => "Trowbridge", type => "CPC"}});
}
},
diff --git a/t/Mock/OpenIDConnect.pm b/t/Mock/OpenIDConnect.pm
new file mode 100644
index 000000000..ba7d03b1d
--- /dev/null
+++ b/t/Mock/OpenIDConnect.pm
@@ -0,0 +1,77 @@
+package t::Mock::OpenIDConnect;
+
+use JSON::MaybeXS;
+use Web::Simple;
+use DateTime;
+use MIME::Base64 qw(encode_base64);
+use MooX::Types::MooseLike::Base qw(:all);
+
+has json => (
+ is => 'lazy',
+ default => sub {
+ JSON->new->pretty->allow_blessed->convert_blessed;
+ },
+);
+
+has returns_email => (
+ is => 'rw',
+ isa => Bool,
+ default => 1,
+);
+
+sub dispatch_request {
+ my $self = shift;
+
+ sub (GET + /oauth2/v2.0/authorize + ?*) {
+ 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' ] ];
+ },
+
+ sub (POST + /oauth2/v2.0/token + ?*) {
+ my ($self) = @_;
+ my $header = {
+ typ => "JWT",
+ alg => "RS256",
+ kid => "XXXfakeKEY1234",
+ };
+ my $now = DateTime->now->epoch;
+ my $payload = {
+ exp => $now + 3600,
+ nbf => $now,
+ ver => "1.0",
+ iss => "https://login.example.org/12345-6789-4321-abcd-12309812309/v2.0/",
+ sub => "my_cool_user_id",
+ aud => "example_client_id",
+ iat => $now,
+ auth_time => $now,
+ given_name => "Andy",
+ family_name => "Dwyer",
+ tfp => "B2C_1_default",
+ extension_CrmContactId => "1c304134-ef12-c128-9212-123908123901",
+ nonce => 'MyAwesomeRandomValue',
+ };
+ $payload->{emails} = ['pkg-tappcontrollerauth_socialt-oidc@example.org'] 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
new file mode 100644
index 000000000..7542b1f5e
--- /dev/null
+++ b/t/Mock/Tilma.pm
@@ -0,0 +1,52 @@
+package t::Mock::Tilma;
+
+use JSON::MaybeXS;
+use Web::Simple;
+
+has json => (
+ is => 'lazy',
+ default => sub {
+ JSON->new->utf8->pretty->allow_blessed->convert_blessed;
+ },
+);
+
+sub as_json {
+ my ($self, $features) = @_;
+ my $json = mySociety::Locale::in_gb_locale {
+ $self->json->encode({
+ type => "FeatureCollection",
+ crs => { type => "name", properties => { name => "urn:ogc:def:crs:EPSG::27700" } },
+ features => $features,
+ });
+ };
+ return $json;
+}
+
+sub dispatch_request {
+ my $self = shift;
+
+ sub (GET + /mapserver/tfl + ?*) {
+ my ($self, $args) = @_;
+ my $features = [];
+ if ($args->{Filter} =~ /540512,169141/) {
+ $features = [
+ { type => "Feature", properties => { HA_ID => "19" }, geometry => { type => "Polygon", coordinates => [ [
+ [ 539408.94, 170607.58 ],
+ [ 539432.81, 170627.93 ],
+ [ 539437.24, 170623.48 ],
+ [ 539408.94, 170607.58 ],
+ ] ] } } ];
+ }
+ my $json = $self->as_json($features);
+ return [ 200, [ 'Content-Type' => 'application/json' ], [ $json ] ];
+ },
+
+ sub (GET + /mapserver/highways + ?*) {
+ my ($self, $args) = @_;
+ my $json = $self->as_json([]);
+ return [ 200, [ 'Content-Type' => 'application/json' ], [ $json ] ];
+ },
+
+}
+
+__PACKAGE__->run_if_script;
diff --git a/t/app/01app.t b/t/app/01app.t
index df562b829..50617d491 100644
--- a/t/app/01app.t
+++ b/t/app/01app.t
@@ -2,30 +2,56 @@
use strict;
use warnings;
+use utf8;
package FixMyStreet::Cobrand::Tester;
-use parent 'FixMyStreet::Cobrand::FiksGataMi';
+use parent 'FixMyStreet::Cobrand::FixaMinGata';
sub front_stats_data { { new => 0, fixed => 0, updates => 12345 } }
package main;
+use Encode;
use Test::More;
use Catalyst::Test 'FixMyStreet::App';
use charnames ':full';
-use Encode qw(encode);
ok( request('/')->is_success, 'Request should succeed' );
-SKIP: {
FixMyStreet::override_config {
ALLOWED_COBRANDS => [ 'tester' ],
}, sub {
- skip 'Test will not pass on Mac OS', 1 if $^O eq 'darwin';
-
- my $page = get('/');
- my $num = encode('UTF-8', "12\N{NO-BREAK SPACE}345");
+ my $page = decode_utf8(get('/'));
+ my $num = "12( | )345";
like $page, qr/$num/;
};
-}
+
+subtest 'CSP header' => sub {
+ my $res = request('/');
+ is $res->header('Content-Security-Policy'), undef, 'None by default';
+
+ FixMyStreet::override_config {
+ CONTENT_SECURITY_POLICY => 1,
+ }, sub {
+ my $res = request('/');
+ like $res->header('Content-Security-Policy'), qr/script-src 'self' 'unsafe-inline' 'nonce-[^']*' ; object-src 'none'; base-uri 'none'/,
+ 'Default CSP header if requested';
+ };
+
+ FixMyStreet::override_config {
+ CONTENT_SECURITY_POLICY => 'www.example.org',
+ }, sub {
+ my $res = request('/');
+ like $res->header('Content-Security-Policy'), qr/script-src 'self' 'unsafe-inline' 'nonce-[^']*' www.example.org; object-src 'none'; base-uri 'none'/,
+ 'With 3P domains if given';
+ };
+
+ FixMyStreet::override_config {
+ CONTENT_SECURITY_POLICY => [ 'www.example.org' ],
+ }, sub {
+ my $res = request('/');
+ like $res->header('Content-Security-Policy'), qr/script-src 'self' 'unsafe-inline' 'nonce-[^']*' www.example.org; object-src 'none'; base-uri 'none'/,
+ 'With 3P domains if given';
+ };
+};
done_testing();
diff --git a/t/app/controller/about.t b/t/app/controller/about.t
index 04d902bc5..e1ffc34bb 100644
--- a/t/app/controller/about.t
+++ b/t/app/controller/about.t
@@ -4,6 +4,7 @@ sub path_to_web_templates { [ FixMyStreet->path_to( 't', 'app', 'controller', 't
package main;
+use utf8;
use FixMyStreet::TestMech;
ok( my $mech = FixMyStreet::TestMech->new, 'Created mech object' );
@@ -23,12 +24,12 @@ ok !$mech->res->is_success(), "want a bad response";
is $mech->res->code, 404, "got 404";
FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'fiksgatami' ],
+ ALLOWED_COBRANDS => [ 'fixamingata' ],
}, sub {
- ok $mech->host("www.fiksgatami.no"), 'host to fiksgatami';
+ ok $mech->host("www.fixamingata.se"), 'host to fixamingata';
$mech->get_ok('/faq');
- $mech->content_like(qr{Ofte spurte spørsmål ::});
- $mech->content_contains('html class="no-js" lang="nb"');
+ $mech->content_like(qr{Vanliga frågor ::});
+ $mech->content_contains('html class="no-js" lang="sv"');
};
$mech->get_ok('/');
diff --git a/t/app/controller/admin.t b/t/app/controller/admin.t
index d50702086..5607f2dc3 100644
--- a/t/app/controller/admin.t
+++ b/t/app/controller/admin.t
@@ -25,7 +25,7 @@ my $dt = DateTime->new(
second => 23
);
-my $report = FixMyStreet::App->model('DB::Problem')->find_or_create(
+my $report = FixMyStreet::DB->resultset('Problem')->find_or_create(
{
postcode => 'SW1A 1AA',
bodies_str => '2504',
@@ -53,7 +53,7 @@ my $report = FixMyStreet::App->model('DB::Problem')->find_or_create(
my $report_id = $report->id;
ok $report, "created test report - $report_id";
-my $alert = FixMyStreet::App->model('DB::Alert')->find_or_create(
+my $alert = FixMyStreet::DB->resultset('Alert')->find_or_create(
{
alert_type => 'area_problems',
parameter => 2482,
@@ -65,34 +65,34 @@ my $alert = FixMyStreet::App->model('DB::Alert')->find_or_create(
$mech->log_in_ok( $superuser->email );
subtest 'check summary counts' => sub {
- my $problems = FixMyStreet::App->model('DB::Problem')->search( { state => { -in => [qw/confirmed fixed closed investigating planned/, 'in progress', 'fixed - user', 'fixed - council'] } } );
+ my $problems = FixMyStreet::DB->resultset('Problem')->search( { state => { -in => [qw/confirmed fixed closed investigating planned/, 'in progress', 'fixed - user', 'fixed - council'] } } );
ok $mech->host('www.fixmystreet.com');
my $problem_count = $problems->count;
$problems->update( { cobrand => '' } );
- FixMyStreet::App->model('DB::Problem')->search( { bodies_str => 2489 } )->update( { bodies_str => 1 } );
+ FixMyStreet::DB->resultset('Problem')->search( { bodies_str => 2489 } )->update( { bodies_str => 1 } );
- my $q = FixMyStreet::App->model('DB::Questionnaire')->find_or_new( { problem => $report, });
+ my $q = FixMyStreet::DB->resultset('Questionnaire')->find_or_new( { problem => $report, });
$q->whensent( \'current_timestamp' );
$q->in_storage ? $q->update : $q->insert;
- my $alerts = FixMyStreet::App->model('DB::Alert')->search( { confirmed => { '>' => 0 } } );
+ my $alerts = FixMyStreet::DB->resultset('Alert')->search( { confirmed => { '>' => 0 } } );
my $a_count = $alerts->count;
FixMyStreet::override_config {
ALLOWED_COBRANDS => [ 'fixmystreet' ],
}, sub {
- $mech->get_ok('/admin');
+ $mech->get_ok('/admin/stats');
};
- $mech->title_like(qr/Summary/);
+ $mech->title_like(qr/Stats/);
$mech->content_contains( "$problem_count</strong> live problems" );
$mech->content_contains( "$a_count confirmed alerts" );
- my $questionnaires = FixMyStreet::App->model('DB::Questionnaire')->search( { whensent => { -not => undef } } );
+ my $questionnaires = FixMyStreet::DB->resultset('Questionnaire')->search( { whensent => { -not => undef } } );
my $q_count = $questionnaires->count();
$mech->content_contains( "$q_count questionnaires sent" );
@@ -102,8 +102,8 @@ subtest 'check summary counts' => sub {
}, sub {
ok $mech->host('oxfordshire.fixmystreet.com');
- $mech->get_ok('/admin');
- $mech->title_like(qr/Summary/);
+ $mech->get_ok('/admin/stats');
+ $mech->title_like(qr/Stats/);
my ($num_live) = $mech->content =~ /(\d+)<\/strong> live problems/;
my ($num_alerts) = $mech->content =~ /(\d+) confirmed alerts/;
@@ -116,7 +116,7 @@ subtest 'check summary counts' => sub {
$alert->cobrand('oxfordshire');
$alert->update;
- $mech->get_ok('/admin');
+ $mech->get_ok('/admin/stats');
$mech->content_contains( ($num_live+1) . "</strong> live problems" );
$mech->content_contains( ($num_alerts+1) . " confirmed alerts" );
@@ -130,12 +130,12 @@ subtest 'check summary counts' => sub {
$alert->update;
};
- FixMyStreet::App->model('DB::Problem')->search( { bodies_str => 1 } )->update( { bodies_str => 2489 } );
+ FixMyStreet::DB->resultset('Problem')->search( { bodies_str => 1 } )->update( { bodies_str => 2489 } );
ok $mech->host('www.fixmystreet.com');
};
subtest "Check admin_base_url" => sub {
- my $rs = FixMyStreet::App->model('DB::Problem');
+ my $rs = FixMyStreet::DB->resultset('Problem');
my $cobrand = $report->get_cobrand_logged;
is ($report->admin_url($cobrand),
diff --git a/t/app/controller/admin/bodies.t b/t/app/controller/admin/bodies.t
index f67e45bf6..c73a90da1 100644
--- a/t/app/controller/admin/bodies.t
+++ b/t/app/controller/admin/bodies.t
@@ -1,10 +1,3 @@
-package FixMyStreet::Cobrand::Tester;
-
-use parent 'FixMyStreet::Cobrand::Default';
-
-sub enable_category_groups { 1 }
-
-package main;
use FixMyStreet::TestMech;
my $mech = FixMyStreet::TestMech->new;
@@ -58,7 +51,7 @@ subtest 'check contact creation' => sub {
non_public => 'on',
} } );
$mech->get_ok('/admin/body/' . $body->id . '/test/category');
- $mech->content_contains('<h1>test/category</h1>');
+ $mech->content_contains('test/category');
};
subtest 'check contact editing' => sub {
@@ -98,6 +91,21 @@ subtest 'check contact editing' => sub {
$mech->content_contains( '<td><strong>test2@example.com' );
};
+subtest 'check contact renaming' => sub {
+ my ($report) = $mech->create_problems_for_body(1, $body->id, 'Title', { category => 'test category' });
+ $mech->get_ok('/admin/body/' . $body->id .'/test%20category');
+ $mech->submit_form_ok( { with_fields => { category => 'private category' } } );
+ $mech->content_contains('You cannot rename');
+ $mech->submit_form_ok( { with_fields => { category => 'testing category' } } );
+ $mech->content_contains( 'testing category' );
+ $mech->get('/admin/body/' . $body->id . '/test%20category');
+ is $mech->res->code, 404;
+ $mech->get_ok('/admin/body/' . $body->id . '/testing%20category');
+ $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);
@@ -134,7 +142,7 @@ subtest 'check open311 configuring' => sub {
$mech->content_contains('Council contacts configured via Open311');
$mech->content_contains('Values updated');
- my $conf = FixMyStreet::App->model('DB::Body')->find( $body->id );
+ my $conf = FixMyStreet::DB->resultset('Body')->find( $body->id );
is $conf->endpoint, 'http://example.com/open311', 'endpoint configured';
is $conf->api_key, 'api key', 'api key configured';
is $conf->jurisdiction, 'mySociety', 'jurisdiction configures';
@@ -154,7 +162,7 @@ subtest 'check open311 configuring' => sub {
$mech->content_contains('Values updated');
- $conf = FixMyStreet::App->model('DB::Body')->find( $body->id );
+ $conf = FixMyStreet::DB->resultset('Body')->find( $body->id );
is $conf->endpoint, 'http://example.org/open311', 'endpoint updated';
is $conf->api_key, 'new api key', 'api key updated';
is $conf->jurisdiction, 'open311', 'jurisdiction configures';
@@ -169,14 +177,14 @@ subtest 'check open311 configuring' => sub {
jurisdiction => 'open311',
send_comments => 0,
send_method => 'Open311',
- fetch_all_problems => 1,
+ 'extra[fetch_all_problems]' => 1,
}
}
);
$mech->content_contains('Values updated');
- $conf = FixMyStreet::App->model('DB::Body')->find( $body->id );
+ $conf = FixMyStreet::DB->resultset('Body')->find( $body->id );
ok $conf->get_extra_metadata('fetch_all_problems'), 'fetch all problems set';
$mech->form_number(3);
@@ -188,17 +196,35 @@ subtest 'check open311 configuring' => sub {
jurisdiction => 'open311',
send_comments => 0,
send_method => 'Open311',
- fetch_all_problems => 0,
+ 'extra[fetch_all_problems]' => 0,
+ can_be_devolved => 1, # for next test
}
}
);
$mech->content_contains('Values updated');
- $conf = FixMyStreet::App->model('DB::Body')->find( $body->id );
+ $conf = FixMyStreet::DB->resultset('Body')->find( $body->id );
ok !$conf->get_extra_metadata('fetch_all_problems'), 'fetch all problems unset';
};
+subtest 'check open311 devolved editing' => sub {
+ $mech->get_ok('/admin/body/' . $body->id . '/test%20category');
+ $mech->submit_form_ok( { with_fields => {
+ send_method => 'Email',
+ email => 'testing@example.org',
+ note => 'Updating contact to email',
+ } } );
+ $mech->content_contains('Values updated');
+ $mech->get_ok('/admin/body/' . $body->id . '/test%20category');
+ $mech->submit_form_ok( { with_fields => {
+ send_method => '',
+ email => 'open311-code',
+ note => 'Removing email send method',
+ } } );
+ $mech->content_contains('Values updated');
+};
+
subtest 'check text output' => sub {
$mech->get_ok('/admin/body/' . $body->id . '?text=1');
is $mech->content_type, 'text/plain';
@@ -206,18 +232,49 @@ subtest 'check text output' => sub {
$mech->content_lacks('<body');
};
+subtest 'disable form message editing' => sub {
+ $mech->get_ok('/admin/body/' . $body->id . '/test%20category');
+ $mech->submit_form_ok( { with_fields => {
+ disable => 1,
+ disable_message => '<em>Please</em> <u>ring</u> us on <a href="tel:01234">01234</a>, click <a href="javascript:bad">bad</a>',
+ note => 'Adding emergency message',
+ } } );
+ $mech->content_contains('Values updated');
+ my $contact = $body->contacts->find({ category => 'test category' });
+ is_deeply $contact->get_extra_fields, [{
+ description => '<em>Please</em> ring us on <a href="tel:01234">01234</a>, click <a>bad</a>',
+ code => '_fms_disable_',
+ protected => 'true',
+ variable => 'false',
+ disable_form => 'true',
+ }], 'right message added';
+};
+
+subtest 'open311 protection editing' => sub {
+ $mech->get_ok('/admin/body/' . $body->id . '/test%20category');
+ $mech->submit_form_ok( { with_fields => {
+ open311_protect => 1,
+ note => 'Protected from Open311 changes',
+ } } );
+ $mech->content_contains('Values updated');
+ my $contact = $body->contacts->find({ category => 'test category' });
+ is $contact->get_extra_metadata('open311_protect'), 1, 'Open311 protect flag set';
+};
+
}; # END of override wrap
FixMyStreet::override_config {
- ALLOWED_COBRANDS => ['tester'],
MAPIT_URL => 'http://mapit.uk/',
MAPIT_TYPES => [ 'UTA' ],
BASE_URL => 'http://www.example.org',
+ COBRAND_FEATURES => {
+ category_groups => { default => 1 },
+ }
}, sub {
subtest 'group editing works' => sub {
$mech->get_ok('/admin/body/' . $body->id);
- $mech->content_contains( 'group</strong> is used for the top-level category' );
+ $mech->content_contains('Parent categories');
$mech->submit_form_ok( { with_fields => {
category => 'grouped category',
@@ -229,12 +286,12 @@ FixMyStreet::override_config {
} } );
my $contact = $body->contacts->find({ category => 'grouped category' });
- is $contact->get_extra_metadata('group'), 'group a', "group stored correctly";
+ is_deeply $contact->get_extra_metadata('group'), ['group a'], "group stored correctly";
};
subtest 'group can be unset' => sub {
$mech->get_ok('/admin/body/' . $body->id);
- $mech->content_contains( 'group</strong> is used for the top-level category' );
+ $mech->content_contains('Parent categories');
$mech->submit_form_ok( { with_fields => {
category => 'grouped category',
@@ -251,5 +308,41 @@ FixMyStreet::override_config {
};
+FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ MAPIT_TYPES => [ 'UTA' ],
+ BASE_URL => 'http://www.example.org',
+ COBRAND_FEATURES => {
+ category_groups => { default => 1 },
+ }
+}, sub {
+ subtest 'multi group editing works' => sub {
+ $mech->get_ok('/admin/body/' . $body->id);
+ $mech->content_contains('Parent categories');
+
+ # have to do this as a post as adding a second group requires
+ # javascript
+ $mech->post_ok( '/admin/body/' . $body->id, {
+ posted => 'new',
+ token => $mech->form_id('category_edit')->value('token'),
+ category => 'grouped category',
+ email => 'test@example.com',
+ note => 'test note',
+ 'group' => [ 'group a', 'group b'],
+ non_public => undef,
+ state => 'unconfirmed',
+ } );
+
+ my $contact = $body->contacts->find({ category => 'grouped category' });
+ is_deeply $contact->get_extra_metadata('group'), ['group a', 'group b'], "group stored correctly";
+ };
+};
+
+subtest 'check log of the above' => sub {
+ $mech->get_ok('/admin/users/' . $superuser->id . '/log');
+ $mech->content_contains('Added category <a href="/admin/body/' . $body->id . '/test/category">test/category</a>');
+ $mech->content_contains('Edited category <a href="/admin/body/' . $body->id . '/test category">test category</a>');
+ $mech->content_contains('Edited body <a href="/admin/body/' . $body->id . '">Aberdeen City Council</a>');
+};
done_testing();
diff --git a/t/app/controller/admin/defecttypes.t b/t/app/controller/admin/defecttypes.t
index 12ae8948c..15fdac2f8 100644
--- a/t/app/controller/admin/defecttypes.t
+++ b/t/app/controller/admin/defecttypes.t
@@ -1,5 +1,4 @@
use FixMyStreet::TestMech;
-use Test::MockModule;
my $mech = FixMyStreet::TestMech->new;
@@ -27,16 +26,6 @@ FixMyStreet::override_config { ALLOWED_COBRANDS => ['bromley'], }, sub {
FixMyStreet::override_config { ALLOWED_COBRANDS => ['oxfordshire'], }, sub {
- my $cobrand = Test::MockModule->new('FixMyStreet::Cobrand::Oxfordshire');
- $cobrand->mock('available_permissions', sub {
- my $self = shift;
-
- my $perms = FixMyStreet::Cobrand::Default->available_permissions;
- $perms->{Bodies}->{defect_type_edit} = "Add/edit defect types";
-
- return $perms;
- });
-
my $body = $mech->create_body_ok( 2237, 'Oxfordshire County Council' );
subtest 'check defect types menu available to superusers' => sub {
@@ -107,7 +96,7 @@ FixMyStreet::override_config { ALLOWED_COBRANDS => ['oxfordshire'], }, sub {
};
subtest 'check editing a defect type' => sub {
- my $defect = FixMyStreet::App->model('DB::DefectType')->search( {
+ my $defect = FixMyStreet::DB->resultset('DefectType')->search( {
name => 'A defect',
body_id => $body->id
} )->first;
@@ -126,7 +115,7 @@ FixMyStreet::override_config { ALLOWED_COBRANDS => ['oxfordshire'], }, sub {
$mech->content_lacks('A defect');
$mech->content_contains('Updated defect');
- my $defects = FixMyStreet::App->model('DB::DefectType')->search( {
+ my $defects = FixMyStreet::DB->resultset('DefectType')->search( {
body_id => $body->id
} );
@@ -134,7 +123,7 @@ FixMyStreet::override_config { ALLOWED_COBRANDS => ['oxfordshire'], }, sub {
};
subtest 'check adding a category to a defect' => sub {
- my $defect = FixMyStreet::App->model('DB::DefectType')->search( {
+ my $defect = FixMyStreet::DB->resultset('DefectType')->search( {
name => 'Updated defect',
body_id => $body->id
} )->first;
@@ -163,7 +152,7 @@ FixMyStreet::override_config { ALLOWED_COBRANDS => ['oxfordshire'], }, sub {
};
subtest 'check removing category from a defect' => sub {
- my $defect = FixMyStreet::App->model('DB::DefectType')->search( {
+ my $defect = FixMyStreet::DB->resultset('DefectType')->search( {
name => 'Updated defect',
body_id => $body->id
} )->first;
@@ -191,7 +180,7 @@ FixMyStreet::override_config { ALLOWED_COBRANDS => ['oxfordshire'], }, sub {
};
subtest 'check adding codes to a defect' => sub {
- my $defect = FixMyStreet::App->model('DB::DefectType')->search( {
+ my $defect = FixMyStreet::DB->resultset('DefectType')->search( {
name => 'Updated defect',
body_id => $body->id
} )->first;
diff --git a/t/app/controller/admin/manifesttheme.t b/t/app/controller/admin/manifesttheme.t
new file mode 100644
index 000000000..c1b2d4542
--- /dev/null
+++ b/t/app/controller/admin/manifesttheme.t
@@ -0,0 +1,340 @@
+use Path::Tiny;
+use FixMyStreet::DB;
+use FixMyStreet::TestMech;
+
+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 );
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'lincolnshire', 'tfl', 'fixmystreet' ],
+}, sub {
+
+ok $mech->host('lincolnshire.fixmystreet.com');
+
+subtest "theme link on cobrand admin goes to create form if no theme exists" => sub {
+ is( FixMyStreet::DB->resultset('ManifestTheme')->count, 0, "no themes yet" );
+
+ $mech->get_ok("/admin");
+ $mech->follow_link_ok({ text => "Manifest Theme" });
+
+ is $mech->res->previous->code, 302, "got 302 for redirect";
+ is $mech->res->previous->base->path, "/admin/manifesttheme", "redirected from index";
+ is $mech->uri->path, '/admin/manifesttheme/create', "redirected to create page";
+};
+
+subtest "name and short_name are required fields" => sub {
+ is( FixMyStreet::DB->resultset('ManifestTheme')->count, 0, "no themes yet" );
+
+ $mech->get_ok("/admin/manifesttheme/create");
+ $mech->content_lacks("Delete theme");
+
+ $mech->submit_form_ok({});
+ is $mech->uri->path, '/admin/manifesttheme/create', "stayed on create page";
+ $mech->content_contains("field is required");
+ is( FixMyStreet::DB->resultset('ManifestTheme')->count, 0, "theme not created" );
+
+ $mech->get_ok("/admin/manifesttheme/create");
+ $mech->submit_form_ok({ with_fields => { short_name => "Lincs FMS" } });
+ is $mech->uri->path, '/admin/manifesttheme/create', "stayed on create page";
+ $mech->content_contains("field is required", "name is required");
+ is( FixMyStreet::DB->resultset('ManifestTheme')->count, 0, "theme not created" );
+
+ $mech->get_ok("/admin/manifesttheme/create");
+ $mech->submit_form_ok({ with_fields => { name => "Lincolnshire FixMyStreet" } });
+ is $mech->uri->path, '/admin/manifesttheme/create', "stayed on create page";
+ $mech->content_contains("field is required", "short_name is required");
+ is( FixMyStreet::DB->resultset('ManifestTheme')->count, 0, "theme not created" );
+};
+
+subtest "cobrand admin lets you create a new theme" => sub {
+ is( FixMyStreet::DB->resultset('ManifestTheme')->count, 0, "no themes yet" );
+
+ $mech->get_ok("/admin/manifesttheme/create");
+ $mech->content_lacks("Delete theme");
+
+ my $fields = {
+ name => "Lincolnshire FixMyStreet",
+ short_name => "Lincs FMS",
+ };
+ $mech->submit_form_ok( { with_fields => $fields } );
+ is $mech->uri->path, '/admin/manifesttheme/lincolnshire', "redirected to edit page";
+ is( FixMyStreet::DB->resultset('ManifestTheme')->count, 1, "theme was created" );
+
+ my $theme = FixMyStreet::DB->resultset('ManifestTheme')->find({ cobrand => 'lincolnshire' });
+ is $theme->name, "Lincolnshire FixMyStreet";
+ is $theme->short_name, "Lincs FMS";
+ is $theme->background_colour, undef;
+
+ my $log = $superuser->admin_logs->search({}, { order_by => { -desc => 'id' } })->first;
+ is $log->object_id, $theme->id;
+ is $log->action, "add";
+ is $log->object_summary, "lincolnshire";
+ is $log->link, "/admin/manifesttheme/lincolnshire";
+};
+
+subtest "cobrand admin lets you update an existing theme" => sub {
+ $mech->get_ok("/admin/manifesttheme/lincolnshire");
+
+ my $fields = {
+ background_colour => "#663399",
+ theme_colour => "rgb(102, 51, 153)",
+ };
+ $mech->submit_form_ok( { with_fields => $fields } );
+
+ my $theme = FixMyStreet::DB->resultset('ManifestTheme')->find({ cobrand => 'lincolnshire' });
+ is $theme->background_colour, "#663399";
+ is $theme->theme_colour, "rgb(102, 51, 153)";
+
+ my $log = $superuser->admin_logs->search({}, { order_by => { -desc => 'id' } })->first;
+ is $log->object_id, $theme->id;
+ is $log->action, "edit";
+};
+
+subtest "cobrand admin lets you add an icon to an existing theme" => sub {
+ $mech->get_ok("/admin/manifesttheme/lincolnshire");
+
+ my $sample_jpeg = path(__FILE__)->parent->parent->child("sample.jpg");
+ ok $sample_jpeg->exists, "sample image $sample_jpeg exists";
+ my $icon_filename = '74e3362283b6ef0c48686fb0e161da4043bbcc97.jpg';
+
+ $mech->post( '/admin/manifesttheme/lincolnshire',
+ Content_Type => 'form-data',
+ Content => {
+ name => "Lincolnshire FixMyStreet",
+ short_name => "Lincs FMS",
+ background_colour => "#663399",
+ theme_colour => "rgb(102, 51, 153)",
+ cobrand => 'lincolnshire',
+ icon => [ $sample_jpeg, undef, Content_Type => 'image/jpeg' ],
+ },
+ );
+ ok $mech->success, 'Posted request successfully';
+
+ is $mech->uri->path, '/admin/manifesttheme/lincolnshire', "redirected back to edit page";
+ $mech->content_contains("<img src=\"/theme/lincolnshire/" . $icon_filename);
+ $mech->content_contains("<td class=\"icon-size\">133x100</td>");
+ my $icon_dest = path(FixMyStreet->path_to('web/theme/lincolnshire/', $icon_filename));
+ ok $icon_dest->exists, "Icon stored on disk";
+};
+
+subtest "cobrand admin lets you delete an icon from an existing theme" => sub {
+ my $icon_filename = '74e3362283b6ef0c48686fb0e161da4043bbcc97.jpg';
+ my $icon_dest = path(FixMyStreet->path_to('web/theme/lincolnshire/', $icon_filename));
+ ok $icon_dest->exists, "Icon exists on disk";
+
+ $mech->get_ok("/admin/manifesttheme/lincolnshire");
+ my $fields = {
+ delete_icon => "/theme/lincolnshire/$icon_filename",
+ };
+ $mech->submit_form_ok( { with_fields => $fields } );
+
+ is $mech->uri->path, '/admin/manifesttheme/lincolnshire', "redirected back to edit page";
+ $mech->content_lacks("<img src=\"/theme/lincolnshire/" . $icon_filename);
+ $mech->content_lacks("<td class=\"icon-size\">133x100</td>");
+ ok !$icon_dest->exists, "Icon removed from disk";
+};
+
+subtest "cobrand admin rejects non-images" => sub {
+ $mech->get_ok("/admin/manifesttheme/lincolnshire");
+
+ my $sample_pdf = path(__FILE__)->parent->parent->child("sample.pdf");
+ ok $sample_pdf->exists, "sample image $sample_pdf exists";
+
+ $mech->post( '/admin/manifesttheme/lincolnshire',
+ Content_Type => 'form-data',
+ Content => {
+ name => "Lincolnshire FixMyStreet",
+ short_name => "Lincs FMS",
+ background_colour => "#663399",
+ theme_colour => "rgb(102, 51, 153)",
+ cobrand => 'lincolnshire',
+ icon => [ $sample_pdf, undef, Content_Type => 'application/pdf' ],
+ },
+ );
+ ok $mech->success, 'Posted request successfully';
+
+ is $mech->uri->path, '/admin/manifesttheme/lincolnshire', "redirected back to edit page";
+ $mech->content_lacks("90f7a64043fb458d58de1a0703a6355e2856b15e.pdf");
+ $mech->content_contains("File type not recognised. Please upload an image.");
+};
+
+subtest "theme link on cobrand admin goes to edit form when theme exists" => sub {
+ is( FixMyStreet::DB->resultset('ManifestTheme')->count, 1, "theme exists" );
+
+ $mech->get_ok("/admin");
+ $mech->follow_link_ok({ text => "Manifest Theme" });
+
+ is $mech->res->previous->code, 302, "got 302 for redirect";
+ is $mech->res->previous->base->path, "/admin/manifesttheme", "redirected from index";
+ is $mech->uri->path, '/admin/manifesttheme/lincolnshire', "redirected to edit page";
+};
+
+subtest "create page on cobrand admin redirects to edit form when theme exists" => sub {
+ is( FixMyStreet::DB->resultset('ManifestTheme')->count, 1, "theme exists" );
+
+ $mech->get_ok("/admin/manifesttheme/create");
+
+ is $mech->res->previous->code, 302, "got 302 for redirect";
+ is $mech->uri->path, '/admin/manifesttheme/lincolnshire', "redirected to edit page";
+};
+
+subtest "can delete theme" => sub {
+ is( FixMyStreet::DB->resultset('ManifestTheme')->count, 1, "theme exists" );
+
+ my $theme_id = FixMyStreet::DB->resultset('ManifestTheme')->find({ cobrand => 'lincolnshire' })->id;
+
+ # Add an icon so we can test it gets deleted when the theme is deleted
+ my $sample_jpeg = path(__FILE__)->parent->parent->child("sample.jpg");
+ ok $sample_jpeg->exists, "sample image $sample_jpeg exists";
+ my $icon_filename = '74e3362283b6ef0c48686fb0e161da4043bbcc97.jpg';
+
+ $mech->post( '/admin/manifesttheme/lincolnshire',
+ Content_Type => 'form-data',
+ Content => {
+ name => "Lincolnshire FixMyStreet",
+ short_name => "Lincs FMS",
+ background_colour => "#663399",
+ theme_colour => "rgb(102, 51, 153)",
+ cobrand => "lincolnshire",
+ icon => [ $sample_jpeg, undef, Content_Type => 'image/jpeg' ],
+ },
+ );
+ ok $mech->success, 'Posted request successfully';
+
+ is $mech->uri->path, '/admin/manifesttheme/lincolnshire', "redirected back to edit page";
+ my $icon_dest = path(FixMyStreet->path_to('web/theme/lincolnshire/', $icon_filename));
+ ok $icon_dest->exists, "Icon stored on disk";
+
+ $mech->submit_form_ok({ button => 'delete_theme' });
+ is $mech->uri->path, '/admin/manifesttheme/create', "redirected to create page";
+
+ is( FixMyStreet::DB->resultset('ManifestTheme')->count, 0, "theme deleted" );
+ ok !$icon_dest->exists, "Icon removed from disk";
+
+ my $log = $superuser->admin_logs->search({}, { order_by => { -desc => 'id' } })->first;
+ is $log->object_id, $theme_id;
+ is $log->action, "delete";
+};
+
+subtest "can't edit another cobrand's theme" => sub {
+ FixMyStreet::DB->resultset('ManifestTheme')->create({
+ cobrand => "tfl",
+ name => "Transport for London Street Care",
+ short_name => "TfL Street Care",
+ });
+
+ $mech->get("/admin/manifesttheme/tfl");
+ ok !$mech->res->is_success(), "want a bad response";
+ is $mech->res->code, 404, "got 404";
+};
+
+ok $mech->host('www.fixmystreet.com');
+
+subtest "fms cobrand lets you view all manifest themes" => sub {
+ is( FixMyStreet::DB->resultset('ManifestTheme')->count, 1, "theme already exists" );
+
+ $mech->get_ok("/admin");
+ $mech->follow_link_ok({ text => "Manifest Theme" });
+
+ is $mech->uri->path, '/admin/manifesttheme', "taken to list page";
+
+ $mech->content_contains("Transport for London Street Care");
+ $mech->content_contains("TfL Street Care");
+
+};
+
+subtest "fms cobrand lets you edit a cobrand's manifest theme" => sub {
+ $mech->get_ok("/admin/manifesttheme");
+ $mech->follow_link_ok({ url => "manifesttheme/tfl" }) or diag $mech->content;
+
+ my $fields = {
+ name => "Transport for London Report It",
+ };
+ $mech->submit_form_ok( { with_fields => $fields } );
+ is $mech->uri->path, '/admin/manifesttheme', "redirected back to list page";
+
+ my $theme = FixMyStreet::DB->resultset('ManifestTheme')->find({ cobrand => 'tfl' });
+ is $theme->name, "Transport for London Report It";
+
+};
+
+subtest "fms cobrand lets you create a new manifest theme" => sub {
+ $mech->get_ok("/admin/manifesttheme");
+ $mech->follow_link_ok({ text => "Create" });
+
+ my $fields = {
+ name => "FixMyStreet Pro",
+ short_name => "FMS Pro",
+ cobrand => "fixmystreet",
+ };
+ $mech->submit_form_ok( { with_fields => $fields } );
+ is $mech->uri->path, '/admin/manifesttheme', "redirected to list page";
+
+ is( FixMyStreet::DB->resultset('ManifestTheme')->count, 2, "theme added" );
+ my $theme = FixMyStreet::DB->resultset('ManifestTheme')->find({ cobrand => 'fixmystreet' });
+ is $theme->name, "FixMyStreet Pro";
+};
+
+subtest "fms cobrand prevents you creating a duplicate theme" => sub {
+ $mech->get_ok("/admin/manifesttheme");
+ $mech->follow_link_ok({ text => "Create" });
+
+ my $fields = {
+ name => "FixMyStreet Pro",
+ short_name => "FMS Pro",
+ cobrand => "fixmystreet",
+ };
+ $mech->submit_form_ok( { with_fields => $fields } );
+ is $mech->uri->path, '/admin/manifesttheme/create', "stayed on create form";
+
+ is( FixMyStreet::DB->resultset('ManifestTheme')->count, 2, "theme not added" );
+};
+
+subtest "fms cobrand prevents creating a duplicate by editing" => sub {
+ $mech->get_ok("/admin/manifesttheme");
+ $mech->follow_link_ok({ url => "manifesttheme/tfl" });
+
+ my $fields = {
+ cobrand => "fixmystreet",
+ };
+ $mech->submit_form_ok( { with_fields => $fields } );
+ is $mech->uri->path, '/admin/manifesttheme/tfl', "stayed on edit page";
+};
+
+};
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'fixamingata' ],
+}, sub {
+
+ok $mech->host("www.fixamingata.se"), "change host to FixaMinGata";
+
+subtest "single cobrand behaves correctly" => sub {
+ FixMyStreet::DB->resultset('ManifestTheme')->delete_all;
+ is( FixMyStreet::DB->resultset('ManifestTheme')->count, 0, "themes all deleted" );
+
+ $mech->get_ok("/admin/manifesttheme");
+ is $mech->uri->path, '/admin/manifesttheme/create', "redirected to create page";
+
+ my $fields = {
+ name => "FixaMinGata Theme Test",
+ short_name => "FixaMinGata Short Name",
+ cobrand => "fixamingata",
+ };
+ $mech->submit_form_ok( { with_fields => $fields } );
+ is $mech->uri->path, '/admin/manifesttheme/fixamingata', "redirected to edit form page";
+ $mech->content_contains("FixaMinGata Theme Test");
+ $mech->content_contains("FixaMinGata Short Name");
+
+ is( FixMyStreet::DB->resultset('ManifestTheme')->count, 1, "theme added" );
+ my $theme = FixMyStreet::DB->resultset('ManifestTheme')->find({ cobrand => 'fixamingata' });
+ is $theme->name, "FixaMinGata Theme Test";
+};
+
+
+};
+
+done_testing();
diff --git a/t/app/controller/admin/permissions.t b/t/app/controller/admin/permissions.t
index ff5a8ec4f..b7bffaaa5 100644
--- a/t/app/controller/admin/permissions.t
+++ b/t/app/controller/admin/permissions.t
@@ -1,5 +1,4 @@
use FixMyStreet::TestMech;
-use Test::MockModule;
my $mech = FixMyStreet::TestMech->new;
@@ -29,13 +28,6 @@ ok $report, "created test report - $report_id";
$mech->log_in_ok( $oxfordshireuser->email );
-my $cobrand = Test::MockModule->new('FixMyStreet::Cobrand::Oxfordshire');
-$cobrand->mock('available_permissions', sub {
- my $self = shift;
-
- return FixMyStreet::Cobrand::Default->available_permissions;
-});
-
subtest "Users can't edit report without report_edit permission" => sub {
FixMyStreet::override_config {
ALLOWED_COBRANDS => [ 'oxfordshire' ],
diff --git a/t/app/controller/admin/priorities.t b/t/app/controller/admin/priorities.t
index 4eff20be7..8341e212d 100644
--- a/t/app/controller/admin/priorities.t
+++ b/t/app/controller/admin/priorities.t
@@ -16,14 +16,14 @@ $mech->log_in_ok( $superuser->email );
subtest "response priorities can be added" => sub {
is $oxfordshire->response_priorities->count, 0, "No response priorities yet";
- $mech->get_ok( "/admin/responsepriorities/" . $oxfordshire->id . "/new" );
+ $mech->get_ok( "/admin/responsepriorities/" . $oxfordshire->id . "/create" );
my $fields = {
name => "Cat 1A",
description => "Fixed within 24 hours",
deleted => undef,
is_default => undef,
- "contacts[".$oxfordshirecontact->id."]" => 1,
+ contacts => $oxfordshirecontact->id,
};
$mech->submit_form_ok( { with_fields => $fields } );
@@ -41,7 +41,7 @@ subtest "response priorities can set to default" => sub {
description => "Fixed within 24 hours",
deleted => undef,
is_default => 1,
- "contacts[".$oxfordshirecontact->id."]" => 1,
+ contacts => $oxfordshirecontact->id,
};
$mech->submit_form_ok( { with_fields => $fields } );
@@ -51,49 +51,36 @@ subtest "response priorities can set to default" => sub {
};
subtest "response priorities can be listed" => sub {
- $mech->get_ok( "/admin/responsepriorities/" . $oxfordshire->id );
+ $mech->get_ok( "/admin/responsepriorities" );
$mech->content_contains( $oxfordshire->response_priorities->first->name );
$mech->content_contains( $oxfordshire->response_priorities->first->description );
};
-subtest "response priorities are limited by body" => sub {
- my $bromleypriority = $bromley->response_priorities->create( {
- deleted => 0,
- name => "Bromley Cat 0",
- } );
-
- is $bromley->response_priorities->count, 1, "Response priority was added to Bromley";
- is $oxfordshire->response_priorities->count, 1, "Response priority wasn't added to Oxfordshire";
-
- $mech->get_ok( "/admin/responsepriorities/" . $oxfordshire->id );
- $mech->content_lacks( $bromleypriority->name );
-
- $mech->get_ok( "/admin/responsepriorities/" . $bromley->id );
- $mech->content_contains( $bromleypriority->name );
-};
-
$mech->log_out_ok;
subtest "response priorities can't be viewed across councils" => sub {
FixMyStreet::override_config {
ALLOWED_COBRANDS => [ 'oxfordshire' ],
}, sub {
+ my $bromley_priority = $bromley->response_priorities->create( {
+ deleted => 0,
+ name => "Bromley Cat 0",
+ } );
+
+ is $bromley->response_priorities->count, 1, "Response priority was added to Bromley";
+ is $oxfordshire->response_priorities->count, 1, "Response priority wasn't added to Oxfordshire";
+
$oxfordshireuser->user_body_permissions->create({
body => $oxfordshire,
permission_type => 'responsepriority_edit',
});
$mech->log_in_ok( $oxfordshireuser->email );
- $mech->get_ok( "/admin/responsepriorities/" . $oxfordshire->id );
+ $mech->get_ok( "/admin/responsepriorities" );
$mech->content_contains( $oxfordshire->response_priorities->first->name );
+ $mech->content_lacks( $bromley_priority->name );
-
- $mech->get( "/admin/responsepriorities/" . $bromley->id );
- ok !$mech->res->is_success(), "want a bad response";
- is $mech->res->code, 404, "got 404";
-
- my $bromley_priority_id = $bromley->response_priorities->first->id;
- $mech->get( "/admin/responsepriorities/" . $bromley->id . "/" . $bromley_priority_id );
+ $mech->get( "/admin/responsepriorities/" . $bromley->id . "/" . $bromley_priority->id );
ok !$mech->res->is_success(), "want a bad response";
is $mech->res->code, 404, "got 404";
};
diff --git a/t/app/controller/admin/report_edit.t b/t/app/controller/admin/report_edit.t
index c6e03ff7e..438bcc241 100644
--- a/t/app/controller/admin/report_edit.t
+++ b/t/app/controller/admin/report_edit.t
@@ -24,7 +24,7 @@ my $dt = DateTime->new(
second => 23
);
-my $report = FixMyStreet::App->model('DB::Problem')->find_or_create(
+my $report = FixMyStreet::DB->resultset('Problem')->find_or_create(
{
postcode => 'SW1A 1AA',
bodies_str => '2504',
@@ -52,7 +52,7 @@ my $report = FixMyStreet::App->model('DB::Problem')->find_or_create(
$mech->log_in_ok( $superuser->email );
-my $log_entries = FixMyStreet::App->model('DB::AdminLog')->search(
+my $log_entries = FixMyStreet::DB->resultset('AdminLog')->search(
{
object_type => 'problem',
object_id => $report->id
@@ -353,7 +353,7 @@ foreach my $test (
user_body => $oxfordshire,
changes => { state => 'in progress', category => 'Potholes' },
log_entries => [
- qw/edit state_change edit state_change edit edit resend edit state_change edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/
+ 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/
],
resend => 0,
},
@@ -412,6 +412,13 @@ foreach my $test (
delete $test->{changes}->{closed_updates};
}
+ if ($test->{changes}{title} || $test->{changes}{detail} || $test->{changes}{anonymous}) {
+ $mech->get_ok("/report/$report_id");
+ $mech->content_contains("Anonymous: <del style='background-color:#fcc'>No</del><ins style='background-color:#cfc'>Yes</ins>") if $test->{changes}{anonymous};
+ $mech->content_contains("Details: <ins style='background-color:#cfc'>Edited </ins>Detail<del style='background-color:#fcc'> for Report to Edit</del>") if $test->{changes}{detail};
+ $mech->content_contains("Subject: <ins style='background-color:#cfc'>Edited </ins>Repor<del style='background-color:#fcc'>t to Edi</del>") if $test->{changes}{title};
+ }
+
is $report->$_, $test->{changes}->{$_}, "$_ updated" for grep { $_ ne 'username' } keys %{ $test->{changes} };
if ( $test->{user} ) {
@@ -504,7 +511,7 @@ subtest 'change email to new user' => sub {
username => 'test3@example.com'
};
- my $user3 = FixMyStreet::App->model('DB::User')->find( { email => 'test3@example.com' } );
+ my $user3 = FixMyStreet::DB->resultset('User')->find( { email => 'test3@example.com' } );
ok !$user3, 'user not in database';
@@ -523,7 +530,7 @@ subtest 'change email to new user' => sub {
is $log_entries->first->action, 'edit', 'log action';
is_deeply( $mech->visible_form_values(), $new_fields, 'changed form values' );
- $user3 = FixMyStreet::App->model('DB::User')->find( { email => 'test3@example.com' } );
+ $user3 = FixMyStreet::DB->resultset('User')->find( { email => 'test3@example.com' } );
$report->discard_changes;
@@ -534,7 +541,7 @@ subtest 'change email to new user' => sub {
subtest 'adding email to abuse list from report page' => sub {
my $email = $report->user->email;
- my $abuse = FixMyStreet::App->model('DB::Abuse')->find( { email => $email } );
+ my $abuse = FixMyStreet::DB->resultset('Abuse')->find( { email => $email } );
$abuse->delete if $abuse;
$mech->get_ok( '/admin/report_edit/' . $report->id );
@@ -545,7 +552,7 @@ subtest 'adding email to abuse list from report page' => sub {
$mech->content_contains('User added to abuse list');
$mech->content_contains('<small>User in abuse table</small>');
- $abuse = FixMyStreet::App->model('DB::Abuse')->find( { email => $email } );
+ $abuse = FixMyStreet::DB->resultset('Abuse')->find( { email => $email } );
ok $abuse, 'entry created in abuse table';
$mech->get_ok( '/admin/report_edit/' . $report->id );
@@ -612,7 +619,7 @@ subtest "Test alert count display" => sub {
$mech->get_ok("/admin/report_edit/$report_id");
$mech->content_contains('Alerts: 0');
- my $alert = FixMyStreet::App->model('DB::Alert')->find_or_create(
+ my $alert = FixMyStreet::DB->resultset('Alert')->find_or_create(
{
alert_type => 'new_updates',
parameter => $report_id,
@@ -634,7 +641,7 @@ subtest "Test alert count display" => sub {
$alert->delete;
};
-my $report2 = FixMyStreet::App->model('DB::Problem')->find_or_create(
+my $report2 = FixMyStreet::DB->resultset('Problem')->find_or_create(
{
postcode => 'SW1A 1AA',
bodies_str => '2504',
diff --git a/t/app/controller/admin/reportextrafields.t b/t/app/controller/admin/reportextrafields.t
index e02df864f..dede25207 100644
--- a/t/app/controller/admin/reportextrafields.t
+++ b/t/app/controller/admin/reportextrafields.t
@@ -9,6 +9,8 @@ sub allow_report_extra_fields { 1 }
sub area_types { [ 'UTA' ] }
+sub must_have_2fa { 0 }
+
package FixMyStreet::Cobrand::SecondTester;
@@ -62,13 +64,12 @@ FixMyStreet::override_config {
$mech->get_ok("/admin/body/" . $body->id . "/" . $contact->category);
$mech->submit_form_ok( { with_fields => {
- "metadata[0].order" => "1",
- "metadata[0].code" => "string_test",
- "metadata[0].required" => "on",
- "metadata[0].notice" => "",
- "metadata[0].description" => "this is a test description",
- "metadata[0].datatype_description" => "hint here",
- "metadata[0].datatype" => "string",
+ "metadata[9999].order" => "1",
+ "metadata[9999].code" => "string_test",
+ "metadata[9999].required" => 1,
+ "metadata[9999].behaviour" => "question",
+ "metadata[9999].description" => "<div style='foo'>this is a test description</div>",
+ "metadata[9999].datatype" => "string",
"note" => "Added extra field",
}});
$mech->content_contains('Values updated');
@@ -78,25 +79,23 @@ FixMyStreet::override_config {
code => "string_test",
required => "true",
variable => "true",
+ protected => "false",
description => "this is a test description",
- datatype_description => "hint here",
datatype => "string",
};
$contact->discard_changes;
is_deeply $contact->get_extra_fields, $contact_extra_fields, 'new string field was added';
-
$mech->get_ok("/admin/body/" . $body->id . "/" . $contact->category);
$mech->submit_form_ok( { with_fields => {
- "metadata[1].order" => "2",
- "metadata[1].code" => "list_test",
- "metadata[1].required" => undef,
- "metadata[1].notice" => "",
- "metadata[1].description" => "this field is a list",
- "metadata[1].datatype_description" => "",
- "metadata[1].datatype" => "list",
- "metadata[1].values[0].key" => "key1",
- "metadata[1].values[0].name" => "name1",
+ "metadata[9999].order" => "2",
+ "metadata[9999].code" => "list_test",
+ "metadata[9999].required" => undef,
+ "metadata[9999].behaviour" => "question",
+ "metadata[9999].description" => "this field is a list",
+ "metadata[9999].datatype" => "singlevaluelist",
+ "metadata[9999].values[8888].key" => "key1",
+ "metadata[9999].values[8888].name" => "name1",
"note" => "Added extra list field",
}});
$mech->content_contains('Values updated');
@@ -106,8 +105,8 @@ FixMyStreet::override_config {
code => "list_test",
required => "false",
variable => "true",
+ protected => "false",
description => "this field is a list",
- datatype_description => "",
datatype => "singlevaluelist",
values => [
{ name => "name1", key => "key1" },
@@ -116,6 +115,28 @@ FixMyStreet::override_config {
$contact->discard_changes;
is_deeply $contact->get_extra_fields, $contact_extra_fields, 'new list field was added';
+ $mech->get_ok("/admin/body/" . $body->id . "/" . $contact->category);
+ $mech->submit_form_ok( { with_fields => {
+ "metadata[9999].order" => "3",
+ "metadata[9999].code" => "emergency",
+ "metadata[9999].behaviour" => "notice",
+ "metadata[9999].disable_form" => "1",
+ "metadata[9999].description" => "please ring",
+ "note" => "Added notice field",
+ }});
+ $mech->content_contains('Values updated');
+
+ push @$contact_extra_fields, {
+ order => "3",
+ code => "emergency",
+ protected => "false",
+ description => "please ring",
+ disable_form => 'true',
+ variable => 'false',
+ };
+ $contact->discard_changes;
+ is_deeply $contact->get_extra_fields, $contact_extra_fields, 'new field was added';
+
$contact->set_extra_fields();
$contact->update;
};
@@ -137,11 +158,7 @@ FixMyStreet::override_config {
is $contact->email, 'test4@example.com', 'contact updated';
is_deeply $meta_data, [ {
order => 0,
- datatype => 'string',
- datatype_description => '',
- description => '',
- required => 'false',
- variable => 'true',
+ protected => 'false',
code => 'POT',
automated => 'server_set'
} ], "automated fields not unset";
@@ -151,7 +168,7 @@ FixMyStreet::override_config {
subtest 'Create and update new ReportExtraFields' => sub {
my $extra_fields = [];
- my $model = FixMyStreet::App->model('DB::ReportExtraField');
+ my $model = FixMyStreet::DB->resultset('ReportExtraField');
is $model->count, 0, 'no ReportExtraFields yet';
$mech->get_ok("/admin/reportextrafields");
@@ -161,13 +178,12 @@ FixMyStreet::override_config {
name => "Test extra fields",
cobrand => "tester",
language => undef,
- "metadata[0].order" => "1",
- "metadata[0].code" => "string_test",
- "metadata[0].required" => "on",
- "metadata[0].notice" => "",
- "metadata[0].description" => "this is a test description",
- "metadata[0].datatype_description" => "hint here",
- "metadata[0].datatype" => "string",
+ "metadata[9999].order" => "1",
+ "metadata[9999].code" => "string_test",
+ "metadata[9999].required" => 1,
+ "metadata[9999].behaviour" => "question",
+ "metadata[9999].description" => "this is a test description",
+ "metadata[9999].datatype" => "string",
}});
is $model->count, 1, 'new ReportExtraFields created';
@@ -177,8 +193,8 @@ FixMyStreet::override_config {
code => "string_test",
required => "true",
variable => "true",
+ protected => "false",
description => "this is a test description",
- datatype_description => "hint here",
datatype => "string",
};
is_deeply $object->get_extra_fields, $extra_fields, 'new string field was added';
@@ -188,15 +204,14 @@ FixMyStreet::override_config {
$mech->get_ok("/admin/reportextrafields/" . $object->id);
$mech->submit_form_ok( { with_fields => {
"language" => "en-gb",
- "metadata[1].order" => "2",
- "metadata[1].code" => "list_test",
- "metadata[1].required" => undef,
- "metadata[1].notice" => "",
- "metadata[1].description" => "this field is a list",
- "metadata[1].datatype_description" => "",
- "metadata[1].datatype" => "list",
- "metadata[1].values[0].key" => "key1",
- "metadata[1].values[0].name" => "name1",
+ "metadata[9999].order" => "2",
+ "metadata[9999].code" => "list_test",
+ "metadata[9999].required" => undef,
+ "metadata[9999].behaviour" => "question",
+ "metadata[9999].description" => "this field is a list",
+ "metadata[9999].datatype" => "singlevaluelist",
+ "metadata[9999].values[8888].key" => "key1",
+ "metadata[9999].values[8888].name" => "name1",
}});
push @$extra_fields, {
@@ -204,8 +219,8 @@ FixMyStreet::override_config {
code => "list_test",
required => "false",
variable => "true",
+ protected => "false",
description => "this field is a list",
- datatype_description => "",
datatype => "singlevaluelist",
values => [
{ name => "name1", key => "key1" },
@@ -218,24 +233,16 @@ FixMyStreet::override_config {
$mech->get_ok("/admin/reportextrafields/" . $object->id);
$mech->submit_form_ok({ with_fields => {
- "metadata[2].order" => "3",
- "metadata[2].code" => "automated_test",
- "metadata[2].required" => undef,
- "metadata[2].notice" => "",
- "metadata[2].description" => "",
- "metadata[2].datatype_description" => "",
- "metadata[2].datatype" => "string",
- "metadata[2].automated" => "server_set",
+ "metadata[9999].order" => "3",
+ "metadata[9999].code" => "automated_test",
+ "metadata[9999].required" => undef,
+ "metadata[9999].behaviour" => "server",
}});
push @$extra_fields, {
order => "3",
code => "automated_test",
- required => "false",
- variable => "true",
- description => "",
- datatype_description => "",
- datatype => "string",
+ protected => "false",
automated => "server_set",
};
@@ -245,8 +252,8 @@ FixMyStreet::override_config {
$mech->get_ok("/admin/reportextrafields/" . $object->id);
$mech->submit_form_ok( { with_fields => {
- "metadata[1].values[1].key" => "key2",
- "metadata[1].values[1].name" => "name2",
+ "metadata[1].values[8888].key" => "key2",
+ "metadata[1].values[8888].name" => "name2",
}});
push @{$extra_fields->[1]->{values}}, { name => "name2", key => "key2" };
@@ -291,7 +298,7 @@ FixMyStreet::override_config {
LANGUAGES => [ 'en-gb,English,en_GB' ]
}, sub {
subtest "Extra fields are missing from cobrand that doesn't allow them" => sub {
- my $object = FixMyStreet::App->model('DB::ReportExtraField')->first;
+ my $object = FixMyStreet::DB->resultset('ReportExtraField')->first;
$object->update({ language => "", cobrand => ""});
$mech->get_ok("/report/new?longitude=-1.351488&latitude=51.847235&category=" . $contact->category);
@@ -300,7 +307,7 @@ FixMyStreet::override_config {
};
};
-FixMyStreet::App->model('DB::ReportExtraField')->delete_all;
+FixMyStreet::DB->resultset('ReportExtraField')->delete_all;
$mech->log_out_ok;
subtest 'Reports are created with correct extra metadata' => sub {
@@ -308,7 +315,7 @@ subtest 'Reports are created with correct extra metadata' => sub {
ALLOWED_COBRANDS => [ 'tester' ],
MAPIT_URL => 'http://mapit.uk/',
}, sub {
- my $model = FixMyStreet::App->model('DB::ReportExtraField');
+ my $model = FixMyStreet::DB->resultset('ReportExtraField');
my $extra_fields = $model->find_or_create({
name => "Test extra fields",
language => "",
@@ -320,7 +327,6 @@ subtest 'Reports are created with correct extra metadata' => sub {
required => "true",
variable => "true",
description => "this is a test description",
- datatype_description => "hint here",
datatype => "string",
});
$extra_fields->push_extra_fields({
@@ -329,7 +335,6 @@ subtest 'Reports are created with correct extra metadata' => sub {
required => "false",
variable => "true",
description => "this field is a list",
- datatype_description => "",
datatype => "singlevaluelist",
values => [
{ name => "name1", key => "key1" },
diff --git a/t/app/controller/admin/roles.t b/t/app/controller/admin/roles.t
new file mode 100644
index 000000000..bc8371404
--- /dev/null
+++ b/t/app/controller/admin/roles.t
@@ -0,0 +1,139 @@
+use FixMyStreet::TestMech;
+
+my $mech = FixMyStreet::TestMech->new;
+
+my $superuser = $mech->create_user_ok('superuser@example.com', name => 'Super User', is_superuser => 1);
+
+my $body = $mech->create_body_ok(2237, 'Oxfordshire County Council');
+my $body2 = $mech->create_body_ok(2482, 'Bromley Council');
+my $editor = $mech->create_user_ok('counciluser@example.com', name => 'Council User', from_body => $body);
+my $user = $mech->create_user_ok('staffuser@example.com', name => 'Other Council User', from_body => $body);
+
+$editor->user_body_permissions->create({
+ body => $body,
+ permission_type => 'user_edit',
+});
+$editor->user_body_permissions->create({
+ body => $body,
+ permission_type => 'user_manage_permissions',
+});
+$user->user_body_permissions->create({
+ body => $body,
+ permission_type => 'report_edit_priority',
+});
+
+my $role_a = FixMyStreet::DB->resultset("Role")->create({
+ body => $body,
+ name => 'Role A',
+ permissions => ['moderate', 'user_edit'],
+});
+FixMyStreet::DB->resultset("Role")->create({
+ body => $body2,
+ name => 'Role Z',
+ permissions => ['report_inspect', 'planned_reports'],
+});
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'oxfordshire',
+ MAPIT_URL => 'http://mapit.uk',
+}, sub {
+
+ $mech->log_in_ok( $editor->email );
+
+ subtest 'role index page' => sub {
+ $mech->get_ok("/admin/roles");
+ $mech->content_contains('Role A');
+ $mech->content_contains('Moderate report details');
+ $mech->content_lacks('Role Z');
+ $mech->content_lacks('Manage shortlist');
+ $mech->content_lacks('Add/edit response templates'); # About to be added
+ };
+
+ subtest 'create a role' => sub {
+ $mech->follow_link_ok({ text => 'Create' });
+ $mech->content_lacks('Body');
+ $mech->submit_form_ok({ with_fields => { name => 'Role A' }});
+ $mech->content_contains('Role names must be unique');
+ $mech->submit_form_ok({ with_fields => {
+ name => 'Role B',
+ permissions => [ ['template_edit', 'user_manage_permissions'] ],
+ }});
+
+ $mech->content_contains('Role B');
+ $mech->content_contains('Add/edit response templates');
+ };
+
+ subtest 'editing a role preselects correct options' => sub {
+ $mech->follow_link_ok({ text => 'Edit' });
+ $mech->content_like(qr/value="moderate"[^>]*checked/);
+ $mech->content_like(qr/value="user_edit"[^>]*checked/);
+ };
+
+ subtest 'editing a role to same name as another fails' => sub {
+ $mech->submit_form_ok({ with_fields => { name => 'Role B' }});
+ $mech->content_contains('Role names must be unique');
+ };
+
+ subtest 'delete a role' => sub {
+ $mech->submit_form_ok({ button => 'delete_role' });
+ $mech->content_lacks('Role A');
+ };
+
+ subtest 'assign a user to a role' => sub {
+ $mech->get_ok('/admin/users/' . $user->id);
+ $mech->content_contains('Role B');
+ $mech->content_lacks('Role Z');
+ $mech->submit_form_ok({ with_fields => {
+ roles => 'Role B',
+ }});
+ $mech->content_like(qr/<option[^>]*selected>Role B/);
+ $mech->content_like(qr/<input[^>]*checkbox[^>]*template_edit[^>]*checked/);
+ is $user->roles->count, 1, 'in one role';
+ is $user->user_body_permissions->count, 0, 'permissions removed';
+ };
+
+ subtest 'check user has the permissions of the role' => sub {
+ $mech->log_in_ok($user->email);
+ $mech->get_ok('/admin/templates');
+ };
+
+ subtest 'remove user from role' => sub {
+ $mech->log_in_ok( $editor->email );
+ $mech->get_ok('/admin/users/' . $user->id);
+ $mech->submit_form_ok({ with_fields => {
+ roles => undef,
+ }}, 'remove role');
+ };
+};
+
+subtest 'superuser can see all bodies' => sub {
+ $mech->log_in_ok( $superuser->email );
+
+ $mech->get_ok("/admin/roles");
+ $mech->content_contains('Oxfordshire');
+ $mech->content_contains('Bromley');
+ $mech->content_contains('Role B');
+ $mech->content_contains('Role Z');
+ $mech->follow_link_ok({ text => 'Create' });
+ $mech->content_contains('Body');
+ $mech->content_contains('Bromley');
+
+ $mech->submit_form_ok({ with_fields => { body => $body->id, name => 'Role B' }});
+ $mech->content_contains('Role names must be unique');
+
+ $mech->submit_form_ok({ with_fields => {
+ name => 'Role C',
+ body => $body2->id,
+ permissions => 'contribute_as_body',
+ }});
+ $mech->content_contains('Role C');
+};
+
+subtest 'check log of the above' => sub {
+ my $id = FixMyStreet::DB->resultset("Role")->find({ name => "Role B" })->id;
+ $mech->get_ok('/admin/users/' . $editor->id . '/log');
+ $mech->content_contains('Added role <a href="/admin/roles/' . $id . '">Role B</a>');
+ $mech->content_contains('Deleted role ' . $role_a->id);
+};
+
+done_testing();
diff --git a/t/app/controller/admin/search.t b/t/app/controller/admin/search.t
index f8e70cb7a..d46843799 100644
--- a/t/app/controller/admin/search.t
+++ b/t/app/controller/admin/search.t
@@ -20,7 +20,7 @@ $mech->create_contact_ok( body_id => $oxford->id, category => 'Graffiti', email
my $bromley = $mech->create_body_ok(2482, 'Bromley Council');
-my $user3 = FixMyStreet::App->model('DB::User')->create( { email => 'test3@example.com' } );
+my $user3 = FixMyStreet::DB->resultset('User')->create( { email => 'test3@example.com' } );
my $dt = DateTime->new(
year => 2011,
@@ -31,7 +31,7 @@ my $dt = DateTime->new(
second => 23
);
-my $report = FixMyStreet::App->model('DB::Problem')->find_or_create(
+my $report = FixMyStreet::DB->resultset('Problem')->find_or_create(
{
postcode => 'SW1A 1AA',
bodies_str => '2504',
@@ -68,7 +68,7 @@ subtest 'show flagged entries' => sub {
$mech->content_contains( $report->title );
};
-my $update = FixMyStreet::App->model('DB::Comment')->create(
+my $update = FixMyStreet::DB->resultset('Comment')->create(
{
text => 'this is an update',
user => $user,
diff --git a/t/app/controller/admin/templates.t b/t/app/controller/admin/templates.t
index 0d4430cad..ad5b3e77b 100644
--- a/t/app/controller/admin/templates.t
+++ b/t/app/controller/admin/templates.t
@@ -8,18 +8,36 @@ my $superuser = $mech->create_user_ok('superuser@example.com', name => 'Super Us
my $oxfordshire = $mech->create_body_ok(2237, 'Oxfordshire County Council');
my $oxfordshirecontact = $mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Potholes', email => 'potholes@example.com' );
+my $oxfordshirecontact2 = $mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Flytipping', email => 'flytipping@example.com' );
my $oxfordshireuser = $mech->create_user_ok('counciluser@example.com', name => 'Council User', from_body => $oxfordshire);
-my $dt = DateTime->new(
- year => 2011,
- month => 04,
- day => 16,
- hour => 15,
- minute => 47,
- second => 23
-);
-
-my $report = FixMyStreet::App->model('DB::Problem')->find_or_create(
+my $bromley = $mech->create_body_ok(2482, 'Bromley Borough Council');
+my $bromleycontact = $mech->create_contact_ok( body_id => $bromley->id, category => 'Potholes', email => 'potholes@example.com' );
+my $bromleyuser = $mech->create_user_ok('bromleyuser@example.com', name => 'Council User', from_body => $bromley);
+$bromleyuser->user_body_permissions->find_or_create({
+ body => $bromley,
+ permission_type => 'report_inspect',
+});
+my $bromleytemplate = $bromley->response_templates->create({
+ title => "Bromley-specific response template.",
+ text => "This template will only appear on the Bromley cobrand.",
+});
+
+my $tfl = $mech->create_body_ok(2482, 'TfL');
+my $tflcontact = $mech->create_contact_ok( body_id => $tfl->id, category => 'Potholes', email => 'potholes@example.com' );
+my $tfluser = $mech->create_user_ok('tfluser@example.com', name => 'Council User', from_body => $tfl);
+$tfluser->user_body_permissions->find_or_create({
+ body => $tfl,
+ permission_type => 'report_inspect',
+});
+my $tfltemplate = $tfl->response_templates->create({
+ title => "TfL-specific response template.",
+ text => "This template will only appear on the TfL cobrand.",
+});
+
+my $dt = DateTime->now();
+
+my $report = FixMyStreet::DB->resultset('Problem')->find_or_create(
{
postcode => 'SW1A 1AA',
bodies_str => '2504',
@@ -45,8 +63,6 @@ my $report = FixMyStreet::App->model('DB::Problem')->find_or_create(
}
);
-$mech->log_in_ok( $superuser->email );
-
my $report_id = $report->id;
ok $report, "created test report - $report_id";
@@ -63,7 +79,37 @@ subtest "response templates can be added" => sub {
};
$mech->submit_form_ok( { with_fields => $fields } );
- is $oxfordshire->response_templates->count, 1, "Response template was added";
+ is $oxfordshire->response_templates->count, 1, "Response template was added";
+};
+
+subtest 'check log of the above' => sub {
+ my $template_id = $oxfordshire->response_templates->first->id;
+ $mech->get_ok('/admin/users/' . $superuser->id . '/log');
+ $mech->content_contains('Added template <a href="/admin/templates/' . $oxfordshire->id . '/' . $template_id . '">Report acknowledgement</a>');
+};
+
+subtest "but not another with the same title" => sub {
+ my $fields = {
+ title => "Report acknowledgement",
+ text => "Another report acknowledgement.",
+ auto_response => undef,
+ "contacts[".$oxfordshirecontact->id."]" => 1,
+ };
+ my $list_url = "/admin/templates/" . $oxfordshire->id;
+ $mech->get_ok( "$list_url/new" );
+ $mech->submit_form_ok( { with_fields => $fields } );
+ is $mech->uri->path, "$list_url/new", 'not redirected';
+ $mech->content_contains( 'Please correct the errors below' );
+ $mech->content_contains( 'There is already a template with that title.' );
+
+ my @ts = $oxfordshire->response_templates->all;
+ is @ts, 1, "No new response template was added";
+
+ my $url = "$list_url/" . $ts[0]->id;
+ $mech->get_ok($url);
+ $mech->submit_form_ok( { with_fields => $fields } );
+ is $mech->uri->path, $list_url, 'redirected';
+ is $oxfordshire->response_templates->count, 1, "No new response template was added";
};
subtest "response templates are included on page" => sub {
@@ -193,7 +239,6 @@ subtest "auto-response templates that duplicate external_status_code can't be ad
});
is $oxfordshire->response_templates->count, 1, "Initial response template was created";
-
$mech->log_in_ok( $superuser->email );
$mech->get_ok( "/admin/templates/" . $oxfordshire->id . "/new" );
@@ -231,4 +276,90 @@ subtest "templates that set state and external_status_code can't be added" => su
is $oxfordshire->response_templates->count, 0, "Invalid response template wasn't added";
};
+subtest "category groups are shown" => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'oxfordshire' ],
+ COBRAND_FEATURES => {
+ category_groups => {
+ oxfordshire => 1,
+ },
+ multiple_category_groups => {
+ oxfordshire => 1,
+ },
+ },
+ }, sub {
+
+ $mech->log_in_ok( $superuser->email );
+
+ $mech->get_ok( "/admin/templates/" . $oxfordshire->id . "/new" );
+ $mech->content_contains("No Group") or diag $mech->content;
+ $mech->content_lacks("Multiple Groups");
+ $mech->content_lacks("These categories appear in more than one group:");
+
+ $oxfordshirecontact->set_extra_metadata( group => [ 'Highways' ] );
+ $oxfordshirecontact->update;
+ $oxfordshirecontact2->set_extra_metadata( group => [ 'Street Cleaning' ] );
+ $oxfordshirecontact2->update;
+ $mech->get_ok( "/admin/templates/" . $oxfordshire->id . "/new" );
+ $mech->content_lacks("No Group");
+ $mech->content_lacks("Multiple Groups");
+ $mech->content_lacks("These categories appear in more than one group:");
+ $mech->content_contains("Highways");
+ $mech->content_contains("Street Cleaning");
+
+ $oxfordshirecontact->set_extra_metadata( group => [ 'Highways', 'Roads & Pavements' ] );
+ $oxfordshirecontact->update;
+ $oxfordshirecontact2->set_extra_metadata( group => [ 'Street Cleaning' ] );
+ $oxfordshirecontact2->update;
+ $mech->get_ok( "/admin/templates/" . $oxfordshire->id . "/new" );
+ $mech->content_lacks("No Group");
+ $mech->content_contains("Multiple Groups");
+ $mech->content_contains("These categories appear in more than one group:");
+ $mech->content_contains("Highways; Roads &amp; Pavements");
+ $mech->content_contains("Street Cleaning");
+ };
+};
+
+subtest "TfL cobrand only shows TfL templates" => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'tfl' ],
+ COBRAND_FEATURES => { internal_ips => { tfl => [ '127.0.0.1' ] } },
+ }, sub {
+ $report->update({
+ category => $tflcontact->category,
+ bodies_str => $tfl->id,
+ latitude => 51.402096,
+ longitude => 0.015784,
+ state => 'confirmed',
+ areas => ',2482,',
+ });
+ $mech->log_in_ok( $tfluser->email );
+
+ $mech->get_ok("/report/" . $report->id);
+ $mech->content_contains( $tfltemplate->text );
+ $mech->content_contains( $tfltemplate->title );
+ $mech->content_lacks( $bromleytemplate->text );
+ $mech->content_lacks( $bromleytemplate->title );
+
+ $mech->log_out_ok;
+ };
+};
+
+subtest "Bromley cobrand only shows Bromley templates" => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'bromley', 'tfl' ],
+ }, sub {
+ $report->update({ category => $bromleycontact->category, bodies_str => $bromley->id });
+ $mech->log_in_ok( $bromleyuser->email );
+
+ $mech->get_ok("/report/" . $report->id);
+ $mech->content_contains( $bromleytemplate->text );
+ $mech->content_contains( $bromleytemplate->title );
+ $mech->content_lacks( $tfltemplate->text );
+ $mech->content_lacks( $tfltemplate->title );
+
+ $mech->log_out_ok;
+ };
+};
+
done_testing();
diff --git a/t/app/controller/admin/translations.t b/t/app/controller/admin/translations.t
index f5c32baa6..442be68d5 100644
--- a/t/app/controller/admin/translations.t
+++ b/t/app/controller/admin/translations.t
@@ -59,7 +59,7 @@ subtest 'check add category with translation' => sub {
$mech->submit_form_ok( { with_fields => {
category => 'Potholes',
translation_de => 'DE potholes',
- email => 'potholes@example.org',
+ email => 'potholes',
} } );
# check that error page includes translations
diff --git a/t/app/controller/admin/triage.t b/t/app/controller/admin/triage.t
new file mode 100644
index 000000000..6e134ff67
--- /dev/null
+++ b/t/app/controller/admin/triage.t
@@ -0,0 +1,126 @@
+use FixMyStreet::TestMech;
+use FixMyStreet::Script::Alerts;
+
+my $mech = FixMyStreet::TestMech->new;
+
+my $user = $mech->create_user_ok('test@example.com', name => 'Test User');
+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 $iow = $mech->create_body_ok(2636, 'Isle of Wight Council', { can_be_devolved => 1 } );
+my $iow_contact = $mech->create_contact_ok(
+ body_id => $iow->id,
+ category => 'Potholes',
+ email => 'potholes@example.com',
+ send_method => 'Triage'
+);
+$mech->create_contact_ok(
+ body_id => $iow->id,
+ category => 'Traffic lights',
+ email => 'lights@example.com'
+);
+
+my $dt = DateTime->now();
+
+my ($report) = $mech->create_problems_for_body(
+ 1,
+ $iow->id,
+ 'TITLE',
+ {
+ areas => 2636,
+ category => 'Potholes',
+ whensent => $dt,
+ latitude => 50.71086,
+ longitude => -1.29573,
+ send_method_used => 'Triage',
+ }
+);
+
+FixMyStreet::override_config {
+ STAGING_FLAGS => { send_reports => 1, skip_checks => 0 },
+ ALLOWED_COBRANDS => [ 'isleofwight' ],
+ MAPIT_URL => 'http://mapit.uk/',
+}, sub {
+ subtest "user can access triage page with triage permission" => sub {
+ $user->update({ from_body => $iow });
+ $mech->log_out_ok;
+ $mech->get_ok('/admin/triage');
+
+ $mech->log_in_ok($user->email);
+ $mech->get('/admin/triage');
+ is $mech->res->code, 403, 'permission denied';
+
+ $user->user_body_permissions->create( { body => $iow, permission_type => 'triage' } );
+ $mech->get_ok('/admin/triage');
+ };
+
+ subtest "reports marked for triage show triage interface" => sub {
+ $mech->log_out_ok;
+ $mech->log_in_ok( $user->email );
+
+ $mech->get_ok('/report/' . $report->id);
+ $mech->content_lacks('CONFIRM Subject');
+
+ $report->update( { state => 'for triage' } );
+
+ $mech->get_ok('/report/' . $report->id);
+ $mech->content_contains('CONFIRM Subject');
+ };
+
+ subtest "changing report category marks report as confirmed" => sub {
+ my $report_url = '/report/' . $report->id;
+ $mech->get_ok($report_url);
+
+ my $alert = FixMyStreet::DB->resultset('Alert')->create(
+ {
+ user => $user2,
+ alert_type => 'new_updates',
+ parameter => $report->id,
+ parameter2 => '',
+ confirmed => 1,
+ }
+ );
+
+ $mech->content_contains('Traffic lights');
+
+ $mech->submit_form_ok( {
+ with_fields => {
+ category => 'Traffic lights',
+ include_update => 0,
+ }
+ },
+ 'triage form submitted'
+ );
+
+ $mech->content_contains('Potholes');
+
+ $report->discard_changes;
+ is $report->state, 'confirmed', 'report marked as confirmed';
+ ok !$report->whensent, 'report marked to resend';
+
+ my @comments = $report->comments;
+ my $comment = $comments[0];
+ my $extra = $comment->get_extra_metadata();
+ is $extra->{triage_report}, 1, 'comment indicates it is for triage in extra';
+ is $extra->{holding_category}, 'Potholes', 'comment extra has previous category';
+ is $extra->{new_category}, 'Traffic lights', 'comment extra has new category';
+ ok $comment->whensent, 'comment is marked as sent';
+
+ $mech->get_ok($report_url);
+ $mech->content_contains('Report triaged from Potholes to Traffic lights');
+
+ $mech->log_out_ok;
+ $mech->get_ok($report_url);
+ $mech->content_lacks('Report triaged from Potholes to Traffic lights');
+
+ $mech->clear_emails_ok;
+ FixMyStreet::Script::Alerts::send();
+ $mech->email_count_is(0);
+ };
+};
+
+done_testing();
diff --git a/t/app/controller/admin/update_edit.t b/t/app/controller/admin/update_edit.t
index 6ddbdbdfc..57c8973d4 100644
--- a/t/app/controller/admin/update_edit.t
+++ b/t/app/controller/admin/update_edit.t
@@ -10,7 +10,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 $user3 = FixMyStreet::App->model('DB::User')->create( { email => 'test3@example.com' } );
+my $user3 = FixMyStreet::DB->resultset('User')->create( { email => 'test3@example.com' } );
my $dt = DateTime->new(
year => 2011,
@@ -21,7 +21,7 @@ my $dt = DateTime->new(
second => 23
);
-my $report = FixMyStreet::App->model('DB::Problem')->find_or_create(
+my $report = FixMyStreet::DB->resultset('Problem')->find_or_create(
{
postcode => 'SW1A 1AA',
bodies_str => '2504',
@@ -52,7 +52,7 @@ $mech->log_in_ok( $superuser->email );
my $report_id = $report->id;
ok $report, "created test report - $report_id";
-my $update = FixMyStreet::App->model('DB::Comment')->create(
+my $update = FixMyStreet::DB->resultset('Comment')->create(
{
text => 'this is an update',
user => $user,
@@ -63,7 +63,7 @@ my $update = FixMyStreet::App->model('DB::Comment')->create(
}
);
-my $log_entries = FixMyStreet::App->model('DB::AdminLog')->search(
+my $log_entries = FixMyStreet::DB->resultset('AdminLog')->search(
{
object_type => 'update',
object_id => $update->id
@@ -83,7 +83,7 @@ for my $test (
state => 'confirmed',
name => '',
anonymous => 1,
- username => 'test@example.com',
+ username => $update->user->email,
},
changes => {
text => 'this is a changed update',
@@ -98,7 +98,7 @@ for my $test (
state => 'confirmed',
name => '',
anonymous => 1,
- username => 'test@example.com',
+ username => $update->user->email,
},
changes => {
name => 'A User',
@@ -113,7 +113,7 @@ for my $test (
state => 'confirmed',
name => 'A User',
anonymous => 1,
- username => 'test@example.com',
+ username => $update->user->email,
},
changes => {
anonymous => 0,
@@ -128,10 +128,10 @@ for my $test (
state => 'confirmed',
name => 'A User',
anonymous => 0,
- username => 'test@example.com',
+ username => $update->user->email,
},
changes => {
- username => 'test2@example.com',
+ username => $user2->email,
},
log_count => 4,
log_entries => [qw/edit edit edit edit/],
@@ -144,7 +144,7 @@ for my $test (
state => 'confirmed',
name => 'A User',
anonymous => 0,
- username => 'test2@example.com',
+ username => $user2->email,
},
changes => {
state => 'unconfirmed',
@@ -159,7 +159,7 @@ for my $test (
state => 'unconfirmed',
name => 'A User',
anonymous => 0,
- username => 'test2@example.com',
+ username => $user2->email,
},
changes => {
text => 'this is a twice changed update',
@@ -275,7 +275,7 @@ for my $test (
}
subtest 'editing update email creates new user if required' => sub {
- my $user = FixMyStreet::App->model('DB::User')->find( { email => 'test4@example.com' } );
+ my $user = FixMyStreet::DB->resultset('User')->find( { email => 'test4@example.com' } );
$user->delete if $user;
@@ -289,7 +289,7 @@ subtest 'editing update email creates new user if required' => sub {
$mech->submit_form_ok( { with_fields => $fields } );
- $user = FixMyStreet::App->model('DB::User')->find( { email => 'test4@example.com' } );
+ $user = FixMyStreet::DB->resultset('User')->find( { email => 'test4@example.com' } );
is_deeply $mech->visible_form_values, $fields, 'submitted form values';
@@ -302,7 +302,7 @@ subtest 'editing update email creates new user if required' => sub {
subtest 'adding email to abuse list from update page' => sub {
my $email = $update->user->email;
- my $abuse = FixMyStreet::App->model('DB::Abuse')->find( { email => $email } );
+ my $abuse = FixMyStreet::DB->resultset('Abuse')->find( { email => $email } );
$abuse->delete if $abuse;
$mech->get_ok( '/admin/update_edit/' . $update->id );
@@ -313,7 +313,7 @@ subtest 'adding email to abuse list from update page' => sub {
$mech->content_contains('User added to abuse list');
$mech->content_contains('<small>User in abuse table</small>');
- $abuse = FixMyStreet::App->model('DB::Abuse')->find( { email => $email } );
+ $abuse = FixMyStreet::DB->resultset('Abuse')->find( { email => $email } );
ok $abuse, 'entry created in abuse table';
$mech->get_ok( '/admin/update_edit/' . $update->id );
diff --git a/t/app/controller/admin/users.t b/t/app/controller/admin/users.t
index e2c922a23..4f0298103 100644
--- a/t/app/controller/admin/users.t
+++ b/t/app/controller/admin/users.t
@@ -3,6 +3,9 @@ use FixMyStreet::TestMech;
my $mech = FixMyStreet::TestMech->new;
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 $superuser = $mech->create_user_ok('superuser@example.com', name => 'Super User', is_superuser => 1);
@@ -13,7 +16,7 @@ my $southend = $mech->create_body_ok(2607, 'Southend-on-Sea Borough Council');
$mech->log_in_ok( $superuser->email );
subtest 'search abuse' => sub {
- my $abuse = FixMyStreet::App->model('DB::Abuse')->find_or_create( { email => $user->email } );
+ my $abuse = FixMyStreet::DB->resultset('Abuse')->find_or_create( { email => $user->email } );
$mech->get_ok( '/admin/users?search=example' );
$mech->content_like(qr{test\@example.com.*</td>\s*<td>.*?</td>\s*<td>User in abuse table}s);
};
@@ -24,26 +27,26 @@ subtest 'remove user from abuse list from edit user page' => sub {
$mech->click_ok('unban');
- my $abuse = FixMyStreet::App->model('DB::Abuse')->find( { email => $user->email } );
+ my $abuse = FixMyStreet::DB->resultset('Abuse')->find( { email => $user->email } );
ok !$abuse, 'record removed from abuse table';
};
subtest 'remove user with phone account from abuse list from edit user page' => sub {
my $abuse_user = $mech->create_user_ok('01234 456789');
- my $abuse = FixMyStreet::App->model('DB::Abuse')->find_or_create( { email => $abuse_user->phone } );
+ my $abuse = FixMyStreet::DB->resultset('Abuse')->find_or_create( { email => $abuse_user->phone } );
$mech->get_ok( '/admin/users/' . $abuse_user->id );
$mech->content_contains('User in abuse table');
- my $abuse_found = FixMyStreet::App->model('DB::Abuse')->find( { email => $abuse_user->phone } );
+ my $abuse_found = FixMyStreet::DB->resultset('Abuse')->find( { email => $abuse_user->phone } );
ok $abuse_found, 'user in abuse table';
$mech->click_ok('unban');
- $abuse = FixMyStreet::App->model('DB::Abuse')->find( { email => $user->phone } );
+ $abuse = FixMyStreet::DB->resultset('Abuse')->find( { email => $user->phone } );
ok !$abuse, 'record removed from abuse table';
};
subtest 'no option to remove user already in abuse list' => sub {
- my $abuse = FixMyStreet::App->model('DB::Abuse')->find( { email => $user->email } );
+ my $abuse = FixMyStreet::DB->resultset('Abuse')->find( { email => $user->email } );
$abuse->delete if $abuse;
$mech->get_ok( '/admin/users/' . $user->id );
$mech->content_lacks('User in abuse table');
@@ -60,6 +63,7 @@ subtest 'show flagged entries' => sub {
$user->update;
};
+my $role;
subtest 'user search' => sub {
$mech->get_ok('/admin/users');
$mech->get_ok('/admin/users?search=' . $user->name);
@@ -74,17 +78,37 @@ subtest 'user search' => sub {
$user->from_body($haringey->id);
$user->update;
+ $role = $user->roles->create({
+ body => $haringey,
+ name => 'Role A',
+ permissions => ['moderate', 'user_edit'],
+ });
+ $user->add_to_roles($role);
$mech->get_ok('/admin/users?search=' . $haringey->id );
- $mech->content_contains('Haringey');
+ $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');
+};
+
+subtest 'user assign role' => sub {
+ $user->remove_from_roles($role);
+ is $user->roles->count, 0;
+ $mech->get_ok('/admin/users');
+ $mech->submit_form_ok({ with_fields => { uid => $user->id, roles => $role->id } });
+ is $user->roles->count, 1;
};
subtest 'search does not show user from another council' => sub {
FixMyStreet::override_config {
ALLOWED_COBRANDS => [ 'oxfordshire' ],
}, sub {
+ $superuser->update({ from_body => $oxfordshire->id });
$mech->get_ok('/admin/users');
- $mech->get_ok('/admin/users?search=' . $user->name);
+ $mech->content_lacks('Super User');
+ $superuser->update({ from_body => undef });
+ $mech->get_ok('/admin/users?search=' . $user->name);
$mech->content_contains( "Searching found no users." );
$mech->get_ok('/admin/users?search=' . $user->email);
@@ -102,6 +126,71 @@ subtest 'user_edit does not show user from another council' => sub {
};
};
+$mech->log_out_ok;
+
+subtest 'user_edit redirects appropriately' => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'oxfordshire' ],
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $user2->update({ from_body => $oxfordshire->id });
+ $user3->update({ from_body => $oxfordshire->id });
+ $user3->user_body_permissions->create( {
+ body => $oxfordshire,
+ permission_type => 'user_edit',
+ } );
+ $user3->user_body_permissions->create( {
+ body => $oxfordshire,
+ permission_type => 'user_assign_body',
+ } );
+ $mech->log_in_ok( $user3->email );
+
+ $mech->get_ok('/admin/users/' . $user2->id);
+ $mech->submit_form_ok( { with_fields => {
+ name => "Updated Name"
+ } } );
+ $user2->discard_changes;
+ is $user2->name, "Updated Name", "Name set correctly";
+ is $mech->uri->path, '/admin/users/' . $user2->id, 'redirected back to user form';
+
+ $mech->get_ok('/admin/users/' . $user2->id);
+ $mech->submit_form_ok( { with_fields => {
+ body => undef
+ } } );
+ $user2->discard_changes;
+ is $user2->from_body, undef, "from_body unset";
+ is $mech->uri->path, '/admin/users', 'redirected back to users list';
+
+ $mech->log_out_ok;
+ };
+};
+
+subtest 'user categories are cleared when from_body is unset' => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'oxfordshire' ],
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $mech->log_in_ok( $user3->email );
+
+ my $cat1 = $mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Traffic lights', email => 'lights@example.com' );
+ my $cat2 = $mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Potholes', email => 'potholes@example.com' );
+ $user2->set_extra_metadata('categories', [ $cat1->id, $cat2->id ]);
+ $user2->from_body($oxfordshire->id);
+ $user2->update;
+
+ $mech->get_ok('/admin/users/' . $user2->id);
+ $mech->submit_form_ok( { with_fields => {
+ body => undef
+ } } );
+
+ $user2->discard_changes;
+ is $user2->from_body, undef, "from_body unset";
+ is $user2->get_extra_metadata('categories'), undef, "categories unset";
+ };
+};
+
+$mech->log_in_ok( $superuser->email );
+
for my $test (
{
desc => 'add user - blank form',
@@ -157,6 +246,7 @@ for my $test (
subtest $test->{desc} => sub {
$mech->get_ok('/admin/users');
$mech->submit_form_ok( { with_fields => $test->{fields} } );
+ $mech->content_contains('Norman') if $test->{fields}{name};
if ($test->{error}) {
$mech->content_contains($_) for @{$test->{error}};
} else {
@@ -166,7 +256,7 @@ for my $test (
}
my %default_perms = (
- "permissions[moderate]" => undef,
+ "permissions[moderate]" => 'on',
"permissions[planned_reports]" => undef,
"permissions[report_mark_private]" => undef,
"permissions[report_edit]" => undef,
@@ -180,14 +270,13 @@ my %default_perms = (
"permissions[contribute_as_body]" => undef,
"permissions[default_to_body]" => undef,
"permissions[view_body_contribute_details]" => undef,
- "permissions[user_edit]" => undef,
+ "permissions[user_edit]" => 'on',
"permissions[user_manage_permissions]" => undef,
"permissions[user_assign_body]" => undef,
"permissions[user_assign_areas]" => undef,
"permissions[template_edit]" => undef,
"permissions[responsepriority_edit]" => undef,
"permissions[category_edit]" => undef,
- trusted_bodies => undef,
);
# Start this section with user having no name
@@ -202,7 +291,7 @@ FixMyStreet::override_config {
desc => 'edit user name',
fields => {
name => '',
- email => 'test@example.com',
+ email => $user->email,
email_verified => 1,
body => $haringey->id,
phone => '',
@@ -211,6 +300,7 @@ FixMyStreet::override_config {
is_superuser => undef,
area_ids => undef,
%default_perms,
+ roles => $role->id,
},
changes => {
name => 'Changed User',
@@ -222,7 +312,7 @@ FixMyStreet::override_config {
desc => 'edit user email',
fields => {
name => 'Changed User',
- email => 'test@example.com',
+ email => $user->email,
email_verified => 1,
body => $haringey->id,
phone => '',
@@ -231,6 +321,7 @@ FixMyStreet::override_config {
is_superuser => undef,
area_ids => undef,
%default_perms,
+ roles => $role->id,
},
changes => {
email => 'changed@example.com',
@@ -251,10 +342,14 @@ FixMyStreet::override_config {
is_superuser => undef,
area_ids => undef,
%default_perms,
+ roles => $role->id,
},
changes => {
body => $southend->id,
},
+ removed => [
+ 'roles',
+ ],
log_count => 3,
log_entries => [qw/edit edit edit/],
},
@@ -339,6 +434,8 @@ FixMyStreet::override_config {
},
added => {
%default_perms,
+ 'permissions[moderate]' => undef,
+ 'permissions[user_edit]' => undef,
},
log_count => 5,
log_entries => [qw/edit edit edit edit edit/],
@@ -394,7 +491,7 @@ FixMyStreet::override_config {
$mech->create_problems_for_body(2, 2514, 'Title', { user => $existing_user });
my $count = FixMyStreet::DB->resultset('Problem')->search({ user_id => $user->id })->count;
$mech->get_ok( '/admin/users/' . $user->id );
- $mech->submit_form_ok( { with_fields => { email => 'existing@example.com' } }, 'submit email change' );
+ $mech->submit_form_ok( { with_fields => { email => $existing_user->email } }, 'submit email change' );
is $mech->uri->path, '/admin/users/' . $existing_user->id, 'redirected';
my $p = FixMyStreet::DB->resultset('Problem')->search({ user_id => $existing_user->id })->count;
is $p, $count + 2, 'reports merged';
@@ -448,7 +545,7 @@ subtest "Send login email from admin for unverified email" => sub {
is $email->header('Subject'), "Your FixMyStreet account details",
"subject is correct";
- is $email->header('To'), 'test@example.com', "to is correct";
+ is $email->header('To'), $user->email, "to is correct";
my $link = $mech->get_link_from_email($email);
@@ -470,7 +567,10 @@ subtest "Send login email from admin for unverified email" => sub {
};
subtest "Anonymizing user from admin" => sub {
- $mech->create_problems_for_body(4, 2237, 'Title');
+ my ($problem) = $mech->create_problems_for_body(4, 2237, 'Title');
+ $mech->create_comment_for_problem($problem, $user, $user->name, 'An update', 'f', 'confirmed', 'confirmed');
+ $mech->create_comment_for_problem($problem, $user, $user->name, '2nd update', 't', 'confirmed', 'fixed - user');
+ $mech->create_comment_for_problem($problem, $user, $user->name, '3rd update', 'f', 'unconfirmed', 'confirmed');
my $count_p = FixMyStreet::DB->resultset('Problem')->search({ user_id => $user->id })->count;
my $count_u = FixMyStreet::DB->resultset('Comment')->search({ user_id => $user->id })->count;
$mech->get_ok( '/admin/users/' . $user->id );
@@ -492,6 +592,12 @@ subtest "Hiding user's reports from admin" => sub {
is $c, $count_u;
};
+subtest "Hiding user with only unconfirmed updates does not error" => sub {
+ FixMyStreet::DB->resultset('Comment')->search({ user_id => $user->id, state => 'hidden' })->update({ state => 'unconfirmed' });
+ $mech->get_ok( '/admin/users/' . $user->id );
+ $mech->submit_form_ok({ button => 'hide_everywhere' });
+};
+
subtest "Logging user out" => sub {
my $mech2 = FixMyStreet::TestMech->new;
$mech2->log_in_ok($user->email);
@@ -580,4 +686,25 @@ subtest "View timeline" => sub {
$mech->get_ok('/admin/timeline');
};
+subtest 'View user log' => sub {
+ my $p = FixMyStreet::DB->resultset('Problem')->search({ user_id => $user->id })->first;
+ $user->add_to_planned_reports($p);
+
+ # User 1 created all the reports
+ my $id = $p->id;
+ $mech->get_ok('/admin/users?search=' . $user->email);
+ $mech->follow_link_ok({ text => 'Timeline', n => 2 });
+ $mech->content_like(qr/Problem.*?>$id<\/a> created/);
+ $mech->content_like(qr/Problem.*?>$id<\/a> added to shortlist/);
+
+ # User 3 edited user 2 above
+ $mech->get_ok('/admin/users/' . $user3->id . '/log');
+ $mech->content_like(qr/Edited user.*?test2\@example/);
+
+ # Superuser added a user, and merged one
+ $mech->get_ok('/admin/users/' . $superuser->id . '/log');
+ $mech->content_like(qr/Added user.*?0156/);
+ $mech->content_like(qr/Merged user $original_user_id/);
+};
+
done_testing();
diff --git a/t/app/controller/admin/users_import.t b/t/app/controller/admin/users_import.t
new file mode 100644
index 000000000..df8884797
--- /dev/null
+++ b/t/app/controller/admin/users_import.t
@@ -0,0 +1,34 @@
+use FixMyStreet::TestMech;
+
+my $mech = FixMyStreet::TestMech->new;
+
+my $superuser = $mech->create_user_ok('superuser@example.com', name => 'Super User', is_superuser => 1);
+my $body = $mech->create_body_ok(2509, 'Haringey Borough Council');
+
+$mech->log_in_ok( $superuser->email );
+
+my $body_id = $body->id;
+my $csv = <<EOF;
+name,email,from_body,permissions,roles
+Adrian,adrian\@example.org,$body_id,moderate:user_edit,
+Belinda,belinda\@example.org,$body_id,,Customer Service
+EOF
+
+FixMyStreet::DB->resultset("Role")->create({
+ body => $body,
+ name => 'Customer Service',
+});
+
+subtest 'import CSV file' => sub {
+ $mech->get_ok('/admin/users/import');
+ $mech->submit_form_ok({ with_fields => {
+ csvfile => [ [ undef, 'foo.csv', Content => $csv ], 1],
+ }});
+ $mech->content_contains('Created 2 new users');
+ my $a = FixMyStreet::DB->resultset("User")->find({ email => 'adrian@example.org' });
+ is $a->user_body_permissions->count, 2;
+ my $b = FixMyStreet::DB->resultset("User")->find({ email => 'belinda@example.org' });
+ is $b->roles->count, 1;
+};
+
+done_testing();
diff --git a/t/app/controller/alert_new.t b/t/app/controller/alert_new.t
index f77114d86..7eba90530 100644
--- a/t/app/controller/alert_new.t
+++ b/t/app/controller/alert_new.t
@@ -1,60 +1,61 @@
use FixMyStreet::TestMech;
-use FixMyStreet::App;
use FixMyStreet::Script::Alerts;
my $mech = FixMyStreet::TestMech->new;
-$mech->log_in_ok('test@example.com');
-$mech->get_ok('/alert/subscribe?id=1');
-my ($csrf) = $mech->content =~ /name="token" value="([^"]*)"/;
+my $user = FixMyStreet::App->model('DB::User')
+ ->new( { email => 'test@example.com' } );
+
+my $body = $mech->create_body_ok(2651, 'Edinburgh Council');
+my ($report) = $mech->create_problems_for_body(1, $body->id, 'Existing');
foreach my $test (
{
- email => 'test@example.com',
+ email => $user->email,
type => 'area_problems',
content => 'Click the link in our confirmation email to activate your alert',
email_text => "confirms that you'd like to receive an email",
uri =>
-'/alert/subscribe?type=local&rznvy=test@example.com&feed=area:1000:A_Location',
+'/alert/subscribe?type=local&rznvy=' . $user->email . '&feed=area:1000:A_Location',
param1 => 1000
},
{
- email => 'test@example.com',
+ email => $user->email,
type => 'council_problems',
content => 'Click the link in our confirmation email to activate your alert',
email_text => "confirms that you'd like to receive an email",
uri =>
-'/alert/subscribe?type=local&rznvy=test@example.com&feed=council:1000:A_Location',
+'/alert/subscribe?type=local&rznvy=' . $user->email . '&feed=council:1000:A_Location',
param1 => 1000,
param2 => 1000,
},
{
- email => 'test@example.com',
+ email => $user->email,
type => 'ward_problems',
content => 'Click the link in our confirmation email to activate your alert',
email_text => "confirms that you'd like to receive an email",
uri =>
-'/alert/subscribe?type=local&rznvy=test@example.com&feed=ward:1000:1001:A_Location:Diff_Location',
+'/alert/subscribe?type=local&rznvy=' . $user->email . '&feed=ward:1000:1001:A_Location:Diff_Location',
param1 => 1000,
param2 => 1001,
},
{
- email => 'test@example.com',
+ email => $user->email,
type => 'local_problems',
content => 'Click the link in our confirmation email to activate your alert',
email_text => "confirms that you'd like to receive an email",
uri =>
-'/alert/subscribe?type=local&rznvy=test@example.com&feed=local:10.2:20.1',
+'/alert/subscribe?type=local&rznvy=' . $user->email . '&feed=local:10.2:20.1',
param1 => 20.1,
param2 => 10.2,
},
{
- email => 'test@example.com',
+ email => $user->email,
type => 'new_updates',
content => 'Click the link in our confirmation email to activate your alert',
email_text => "confirms that you'd like to receive an email",
- uri => '/alert/subscribe?type=updates&rznvy=test@example.com&id=1',
- param1 => 1,
+ uri => '/alert/subscribe?type=updates&rznvy=' . $user->email . '&id=' . $report->id,
+ param1 => $report->id,
}
)
{
@@ -63,25 +64,19 @@ foreach my $test (
my $type = $test->{type};
- my $user =
- FixMyStreet::App->model('DB::User')
- ->find( { email => $test->{email} } );
-
- # we don't want an alert
- if ($user) {
- $mech->delete_user($user);
- }
+ $mech->get_ok('/alert/subscribe?id=' . $report->id);
+ my ($csrf) = $mech->content =~ /name="token" value="([^"]*)"/;
$mech->get_ok( $test->{uri} . "&token=$csrf" );
$mech->content_contains( $test->{content} );
- $user =
- FixMyStreet::App->model('DB::User')
+ my $user =
+ FixMyStreet::DB->resultset('User')
->find( { email => $test->{email} } );
ok $user, 'user created for alert';
- my $alert = FixMyStreet::App->model('DB::Alert')->find(
+ my $alert = FixMyStreet::DB->resultset('Alert')->find(
{
user => $user,
alert_type => $type,
@@ -101,7 +96,7 @@ foreach my $test (
my ($url_token) = $url =~ m{/A/(\S+)};
ok $url, "extracted confirm url '$url'";
- my $token = FixMyStreet::App->model('DB::Token')->find(
+ my $token = FixMyStreet::DB->resultset('Token')->find(
{
token => $url_token,
scope => 'alert'
@@ -121,7 +116,7 @@ foreach my $test (
($url_token) = $url =~ m{/A/(\S+)};
ok $url_token ne $existing_token, 'sent out a new token';
- $token = FixMyStreet::App->model('DB::Token')->find(
+ $token = FixMyStreet::DB->resultset('Token')->find(
{
token => $url_token,
scope => 'alert'
@@ -135,7 +130,7 @@ foreach my $test (
$mech->content_contains('alert created');
$alert =
- FixMyStreet::App->model('DB::Alert')->find( { id => $existing_id, } );
+ FixMyStreet::DB->resultset('Alert')->find( { id => $existing_id, } );
ok $alert->confirmed, 'alert set to confirmed';
$mech->delete_user($user);
@@ -154,7 +149,7 @@ foreach my $test (
my $user = $mech->create_user_ok('test-new@example.com');
- my $alert = FixMyStreet::App->model('DB::Alert')->find(
+ my $alert = FixMyStreet::DB->resultset('Alert')->find(
{
user => $user,
alert_type => $type
@@ -163,9 +158,12 @@ foreach my $test (
# clear existing data so we can be sure we're creating it
ok $alert->delete() if $alert && !$test->{exist};
- $mech->get_ok( '/alert/subscribe?type=local&rznvy=test-new@example.com&feed=area:1000:A_Location&token=' . $csrf );
+ $mech->get_ok('/alert/subscribe?id=' . $report->id);
+ my ($csrf) = $mech->content =~ /name="token" value="([^"]*)"/;
+
+ $mech->get_ok( '/alert/subscribe?type=local&rznvy=' . $user->email . '&feed=area:1000:A_Location&token=' . $csrf );
- $alert = FixMyStreet::App->model('DB::Alert')->find(
+ $alert = FixMyStreet::DB->resultset('Alert')->find(
{
user => $user,
alert_type => $type,
@@ -184,8 +182,6 @@ foreach my $test (
};
}
-my $body = $mech->create_body_ok(2651, 'Edinburgh Council');
-
foreach my $test (
{
desc => 'logged in user signing up',
@@ -206,7 +202,7 @@ foreach my $test (
$mech->clear_emails_ok;
FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { 'fixmystreet' => '.' } ],
+ ALLOWED_COBRANDS => 'fixmystreet',
MAPIT_URL => 'http://mapit.uk/',
}, sub {
$mech->get_ok('/alert/list?pc=EH11BB');
@@ -214,7 +210,7 @@ foreach my $test (
$mech->set_visible( [ radio => 'council:' . $body->id . ':City_of_Edinburgh' ] );
$mech->click('alert');
- my $alert = FixMyStreet::App->model('DB::Alert')->find(
+ my $alert = FixMyStreet::DB->resultset('Alert')->find(
{
user => $user,
alert_type => $type,
@@ -232,12 +228,12 @@ foreach my $test (
for my $test (
{
- email => 'test@example.com',
+ email => $user->email,
type => 'new_updates',
content => 'Click the link in our confirmation email to activate your alert',
email_text => 'confirm the alert',
- uri => '/alert/subscribe?type=updates&rznvy=test@example.com&id=1',
- param1 => 1,
+ uri => '/alert/subscribe?type=updates&rznvy=' . $user->email . '&id=' . $report->id,
+ param1 => $report->id,
}
)
{
@@ -247,7 +243,7 @@ for my $test (
my $type = $test->{type};
my $user =
- FixMyStreet::App->model('DB::User')
+ FixMyStreet::DB->resultset('User')
->find( { email => $test->{email} } );
# we don't want an alert
@@ -257,19 +253,22 @@ for my $test (
}
my $abuse =
- FixMyStreet::App->model('DB::Abuse')
+ FixMyStreet::DB->resultset('Abuse')
->find_or_create( { email => $test->{email} } );
+ $mech->get_ok('/alert/subscribe?id=' . $report->id);
+ my ($csrf) = $mech->content =~ /name="token" value="([^"]*)"/;
+
$mech->get_ok( $test->{uri} . "&token=$csrf" );
$mech->content_contains( $test->{content} );
$user =
- FixMyStreet::App->model('DB::User')
+ FixMyStreet::DB->resultset('User')
->find( { email => $test->{email} } );
ok $user, 'user created for alert';
- $alert = FixMyStreet::App->model('DB::Alert')->find(
+ $alert = FixMyStreet::DB->resultset('Alert')->find(
{
user => $user,
alert_type => $type,
@@ -290,6 +289,53 @@ for my $test (
};
}
+subtest 'Test body user signing someone else up for alerts' => sub {
+ my $staff_user = $mech->create_user_ok('astaffuser@example.com', name => 'A staff user', from_body => $body);
+ $mech->log_in_ok($staff_user->email);
+
+ $mech->get_ok('/alert/subscribe?id=' . $report->id);
+ my ($csrf) = $mech->content =~ /name="token" value="([^"]*)"/;
+ $mech->post_ok('/alert/subscribe', { rznvy => 'someoneelse@example.org', id => $report->id, type => 'updates', token => $csrf });
+
+ my $user = FixMyStreet::DB->resultset('User')->find({ email => 'someoneelse@example.org' });
+ is $user, undef, 'No user made by bad request';
+
+ my $alert = FixMyStreet::DB->resultset('Alert')->find({
+ user => $staff_user,
+ alert_type => 'new_updates',
+ parameter => $report->id,
+ confirmed => 1,
+ });
+ ok $alert, 'New alert created with logged in user';
+ $alert->delete;
+
+ $staff_user->user_body_permissions->create({ permission_type => 'contribute_as_another_user', body => $body });
+ $mech->get_ok('/alert/subscribe?id=' . $report->id);
+ $mech->submit_form_ok({ with_fields => { rznvy => 'someoneelse@example.org' } });
+ $mech->content_contains('Email alert created');
+
+ $user = FixMyStreet::DB->resultset('User')->find({ email => 'someoneelse@example.org' });
+ ok $user, 'user created for alert';
+
+ $alert = FixMyStreet::DB->resultset('Alert')->find({
+ user => $user,
+ alert_type => 'new_updates',
+ parameter => $report->id,
+ confirmed => 1,
+ });
+ ok $alert, 'New alert created for another user';
+
+ $alert = FixMyStreet::DB->resultset('Alert')->find({
+ user => $staff_user,
+ alert_type => 'new_updates',
+ parameter => $report->id,
+ confirmed => 1,
+ });
+ is $alert, undef, 'No alert created for staff user';
+};
+
+$report->delete; # Emails sent otherwise below
+
my $gloucester = $mech->create_body_ok(2226, 'Gloucestershire County Council');
$mech->create_body_ok(2326, 'Cheltenham Borough Council');
@@ -310,7 +356,7 @@ subtest "Test two-tier council alerts" => sub {
},
) {
FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { 'fixmystreet' => '.' } ],
+ ALLOWED_COBRANDS => 'fixmystreet',
MAPIT_URL => 'http://mapit.uk/',
}, sub {
$mech->get_ok( '/alert/list?pc=GL502PR' );
@@ -345,7 +391,7 @@ subtest "Test normal alert signups and that alerts are sent" => sub {
) {
$mech->get_ok( '/alert' );
FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { 'fixmystreet' => '.' } ],
+ ALLOWED_COBRANDS => 'fixmystreet',
MAPIT_URL => 'http://mapit.uk/',
}, sub {
$mech->submit_form_ok( { with_fields => { pc => 'EH11BB' } } );
@@ -358,7 +404,7 @@ subtest "Test normal alert signups and that alerts are sent" => sub {
my $url = $mech->get_link_from_email;
my ($url_token) = $url =~ m{/A/(\S+)};
$mech->clear_emails_ok;
- my $token = FixMyStreet::App->model('DB::Token')->find( { token => $url_token, scope => 'alert' } );
+ my $token = FixMyStreet::DB->resultset('Token')->find( { token => $url_token, scope => 'alert' } );
$mech->get_ok( $url );
$mech->content_contains('alert created');
} else {
@@ -414,6 +460,9 @@ subtest "Test normal alert signups and that alerts are sent" => sub {
is +(my $c = () = $email->as_string =~ /Other User/g), 2, 'Update name given, twice';
unlike $email->as_string, qr/Anonymous User/, 'Update name not given';
+ $report->discard_changes;
+ ok $report->get_extra_metadata('closure_alert_sent_at'), 'Closure time set';
+
# The update alert was to the problem reporter, so has a special update URL
$mech->log_out_ok;
$mech->get_ok( "/report/$report_id" );
@@ -449,14 +498,14 @@ subtest "Test alerts are not sent for no-text updates" => sub {
ok $report2, "created test report - $report2_id";
# Must be first
- my $alert2 = FixMyStreet::App->model('DB::Alert')->create( {
+ my $alert2 = FixMyStreet::DB->resultset('Alert')->create( {
parameter => $report2_id,
alert_type => 'new_updates',
user => $user2,
} )->confirm;
ok $alert2, 'created alert for other user';
- my $alert = FixMyStreet::App->model('DB::Alert')->create( {
+ my $alert = FixMyStreet::DB->resultset('Alert')->create( {
parameter => $report_id,
alert_type => 'new_updates',
user => $user2,
@@ -492,7 +541,7 @@ subtest "Test no marked as confirmed added to alerts" => sub {
my $report_id = $report->id;
ok $report, "created test report - $report_id";
- my $alert = FixMyStreet::App->model('DB::Alert')->create( {
+ my $alert = FixMyStreet::DB->resultset('Alert')->create( {
parameter => $report_id,
alert_type => 'new_updates',
user => $user2,
@@ -552,7 +601,7 @@ for my $test (
my $report_id = $report->id;
ok $report, "created test report - $report_id";
- my $alert = FixMyStreet::App->model('DB::Alert')->create( {
+ my $alert = FixMyStreet::DB->resultset('Alert')->create( {
parameter => $report_id,
alert_type => 'new_updates',
user => $user2,
@@ -597,7 +646,7 @@ subtest "Test signature template is used from cobrand" => sub {
my $report_id = $report->id;
ok $report, "created test report - $report_id";
- my $alert = FixMyStreet::App->model('DB::Alert')->create( {
+ my $alert = FixMyStreet::DB->resultset('Alert')->create( {
parameter => $report_id,
alert_type => 'new_updates',
user => $user1,
@@ -611,9 +660,9 @@ subtest "Test signature template is used from cobrand" => sub {
$mech->clear_emails_ok;
FixMyStreet::override_config {
MAPIT_URL => 'http://mapit.uk/',
- ALLOWED_COBRANDS => [ { 'fixmystreet' => '.' } ],
+ ALLOWED_COBRANDS => 'fixmystreet',
}, sub {
- FixMyStreet::App->model('DB::AlertType')->email_alerts();
+ FixMyStreet::DB->resultset('AlertType')->email_alerts();
};
my $email = $mech->get_text_body_from_email;
@@ -628,9 +677,9 @@ subtest "Test signature template is used from cobrand" => sub {
$mech->clear_emails_ok;
FixMyStreet::override_config {
MAPIT_URL => 'http://mapit.uk/',
- ALLOWED_COBRANDS => [ { 'fixmystreet' => '.' } ],
+ ALLOWED_COBRANDS => 'fixmystreet',
}, sub {
- FixMyStreet::App->model('DB::AlertType')->email_alerts();
+ FixMyStreet::DB->resultset('AlertType')->email_alerts();
};
$email = $mech->get_text_body_from_email;
@@ -686,7 +735,7 @@ for my $test (
$alert_params->{whensubscribed} = $dt;
$alert_params->{confirmed} = 1;
- my $alert_user1 = FixMyStreet::App->model('DB::Alert')->create( $alert_params );
+ my $alert_user1 = FixMyStreet::DB->resultset('Alert')->create( $alert_params );
ok $alert_user1, "alert created";
my ($report) = $mech->create_problems_for_body(1, $body->id, 'Testing', {
@@ -703,7 +752,7 @@ for my $test (
FixMyStreet::override_config {
MAPIT_URL => 'http://mapit.uk/',
}, sub {
- FixMyStreet::App->model('DB::AlertType')->email_alerts();
+ FixMyStreet::DB->resultset('AlertType')->email_alerts();
};
$mech->email_count_is(0);
@@ -711,7 +760,7 @@ for my $test (
FixMyStreet::override_config {
MAPIT_URL => 'http://mapit.uk/',
}, sub {
- FixMyStreet::App->model('DB::AlertType')->email_alerts();
+ FixMyStreet::DB->resultset('AlertType')->email_alerts();
};
my $email = $mech->get_text_body_from_email;
like $email, qr/Alert\s+test\s+for\s+non\s+public\s+reports/, 'alert contains public report';
@@ -736,7 +785,7 @@ subtest 'check new updates alerts for non public reports only go to report owner
$mech->create_comment_for_problem($report, $user3, 'Anonymous User', 'This is some more update text', 't', 'confirmed', undef, { confirmed => $r_dt->clone->add( minutes => 8 ) });
- my $alert_user1 = FixMyStreet::App->model('DB::Alert')->create( {
+ my $alert_user1 = FixMyStreet::DB->resultset('Alert')->create( {
user => $user1,
alert_type => 'new_updates',
parameter => $report->id,
@@ -746,10 +795,10 @@ subtest 'check new updates alerts for non public reports only go to report owner
ok $alert_user1, "alert created";
$mech->clear_emails_ok;
- FixMyStreet::App->model('DB::AlertType')->email_alerts();
+ FixMyStreet::DB->resultset('AlertType')->email_alerts();
$mech->email_count_is(0);
- my $alert_user2 = FixMyStreet::App->model('DB::Alert')->create( {
+ my $alert_user2 = FixMyStreet::DB->resultset('Alert')->create( {
user => $user2,
alert_type => 'new_updates',
parameter => $report->id,
@@ -758,13 +807,13 @@ subtest 'check new updates alerts for non public reports only go to report owner
} );
ok $alert_user2, "alert created";
- FixMyStreet::App->model('DB::AlertType')->email_alerts();
+ FixMyStreet::DB->resultset('AlertType')->email_alerts();
my $email = $mech->get_text_body_from_email;
like $email, qr/This is some more update text/, 'alert contains update text';
$mech->clear_emails_ok;
$report->update( { non_public => 0 } );
- FixMyStreet::App->model('DB::AlertType')->email_alerts();
+ FixMyStreet::DB->resultset('AlertType')->email_alerts();
$email = $mech->get_text_body_from_email;
like $email, qr/This is some more update text/, 'alert contains update text';
@@ -792,7 +841,7 @@ subtest 'check setting include dates in new updates cobrand option' => sub {
my $update = $mech->create_comment_for_problem($report, $user3, 'Anonymous User', 'This is some more update text', 't', 'confirmed', undef, { confirmed => $r_dt });
- my $alert_user1 = FixMyStreet::App->model('DB::Alert')->create( {
+ my $alert_user1 = FixMyStreet::DB->resultset('Alert')->create( {
user => $user1,
alert_type => 'new_updates',
parameter => $report->id,
@@ -803,7 +852,7 @@ subtest 'check setting include dates in new updates cobrand option' => sub {
$mech->clear_emails_ok;
- FixMyStreet::App->model('DB::AlertType')->email_alerts();
+ FixMyStreet::DB->resultset('AlertType')->email_alerts();
my $date_in_alert = Utils::prettify_dt( $update->confirmed );
my $email = $mech->get_text_body_from_email;
diff --git a/t/app/controller/around.t b/t/app/controller/around.t
index b123692fa..186b833fd 100644
--- a/t/app/controller/around.t
+++ b/t/app/controller/around.t
@@ -100,6 +100,16 @@ subtest 'check lookup by reference' => sub {
is $mech->uri->path, "/report/$id", "redirected to report page";
};
+subtest 'check lookup by reference does not show non_public reports' => sub {
+ $edinburgh_problems[0]->update({
+ non_public => 1
+ });
+ my $id = $edinburgh_problems[0]->id;
+ $mech->get_ok('/');
+ $mech->submit_form_ok( { with_fields => { pc => "ref:$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 {
@@ -127,6 +137,18 @@ subtest 'check non public reports are not displayed on around page' => sub {
'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->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 {
my $body = FixMyStreet::DB->resultset('Body')->find( $body_edin_id );
@@ -210,7 +232,11 @@ 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 ) {
- $mech->create_contact_ok( category => $category, body_id => $body->id, email => "$category\@example.org" );
+ my $contact = $mech->create_contact_ok( category => $category, body_id => $body->id, email => "$category\@example.org" );
+ if ($category ne 'Pothole') {
+ $contact->set_extra_metadata(group => ['Environment']);
+ $contact->update;
+ }
foreach my $state ( 'confirmed', 'fixed - user', 'fixed - council' ) {
my %report_params = (
%$params,
@@ -230,9 +256,14 @@ subtest 'check category, status and extra filtering works on /around' => sub {
FixMyStreet::override_config {
ALLOWED_COBRANDS => 'fixmystreet',
MAPIT_URL => 'http://mapit.uk/',
+ COBRAND_FEATURES => { category_groups => { fixmystreet => 1 } },
}, sub {
$mech->get_ok( '/around?filter_category=Pothole&bbox=' . $bbox );
$mech->content_contains('<option value="Pothole" selected>');
+ $mech->content_contains('<optgroup label="Environment">');
+
+ $mech->get_ok( '/around?filter_group=Environment&bbox=' . $bbox );
+ $mech->content_contains('<option value="Flytipping" selected>');
};
$json = $mech->get_ok_json( '/around?ajax=1&filter_category=Pothole&bbox=' . $bbox );
@@ -268,7 +299,7 @@ subtest 'check old problems not shown by default on around page' => sub {
my $pins = $json->{pins};
is scalar @$pins, 9, 'correct number of reports when no age';
- my $problems = FixMyStreet::App->model('DB::Problem')->to_body( $body->id );
+ my $problems = FixMyStreet::DB->resultset('Problem')->to_body( $body->id );
$problems->first->update( { confirmed => \"current_timestamp-'7 months'::interval" } );
$json = $mech->get_ok_json( '/around?ajax=1&bbox=' . $bbox );
@@ -282,7 +313,7 @@ subtest 'check old problems not shown by default on around page' => sub {
$problems->update( { confirmed => \"current_timestamp" } );
};
-subtest 'check sorting by update uses lastupdate to determine age' => sub {
+subtest 'check sorting' => sub {
my $params = {
postcode => 'OX20 1SZ',
latitude => 51.754926,
@@ -291,19 +322,31 @@ subtest 'check sorting by update uses lastupdate to determine age' => sub {
my $bbox = ($params->{longitude} - 0.01) . ',' . ($params->{latitude} - 0.01)
. ',' . ($params->{longitude} + 0.01) . ',' . ($params->{latitude} + 0.01);
- my $problems = FixMyStreet::App->model('DB::Problem')->to_body( $body->id );
- $problems->first->update( { confirmed => \"current_timestamp-'7 months'::interval" } );
+ subtest 'by update uses lastupdate to determine age' => sub {
+ my $problems = FixMyStreet::DB->resultset('Problem')->to_body( $body->id );
+ $problems->first->update( { confirmed => \"current_timestamp-'7 months'::interval" } );
- my $json = $mech->get_ok_json( '/around?ajax=1&bbox=' . $bbox );
- my $pins = $json->{pins};
- is scalar @$pins, 8, 'correct number of reports with default sorting';
+ my $json = $mech->get_ok_json( '/around?ajax=1&bbox=' . $bbox );
+ my $pins = $json->{pins};
+ is scalar @$pins, 8, 'correct number of reports with default sorting';
+ $json = $mech->get_ok_json( '/around?ajax=1&sort=updated-desc&bbox=' . $bbox );
+ $pins = $json->{pins};
+ is scalar @$pins, 9, 'correct number of reports with updated sort';
- $json = $mech->get_ok_json( '/around?ajax=1&sort=updated-desc&bbox=' . $bbox );
- $pins = $json->{pins};
- is scalar @$pins, 9, 'correct number of reports with updated sort';
+ $problems->update( { confirmed => \"current_timestamp" } );
+ };
- $problems->update( { confirmed => \"current_timestamp" } );
+ subtest 'by comment count' => sub {
+ my @problems = FixMyStreet::DB->resultset('Problem')->to_body( $body->id )->all;
+ $mech->create_comment_for_problem($problems[3], $problems[0]->user, 'Name', 'Text', 'f', 'confirmed', 'confirmed');
+ $mech->create_comment_for_problem($problems[3], $problems[0]->user, 'Name', 'Text', 'f', 'confirmed', 'confirmed');
+ $mech->create_comment_for_problem($problems[6], $problems[0]->user, 'Name', 'Text', 'f', 'confirmed', 'confirmed');
+ my $json = $mech->get_ok_json( '/around?ajax=1&sort=comments-desc&bbox=' . $bbox );
+ my $pins = $json->{pins};
+ is $pins->[0][3], $problems[3]->id, 'Report with two updates first';
+ is $pins->[1][3], $problems[6]->id, 'Report with one update second';
+ };
};
subtest 'check show old reports checkbox shown on around page' => sub {
@@ -314,7 +357,7 @@ subtest 'check show old reports checkbox shown on around page' => sub {
$mech->get_ok( '/around?pc=OX20+1SZ' );
$mech->content_contains('id="show_old_reports_wrapper" class="report-list-filters hidden"');
- my $problems = FixMyStreet::App->model('DB::Problem')->to_body( $body->id );
+ my $problems = FixMyStreet::DB->resultset('Problem')->to_body( $body->id );
$problems->first->update( { confirmed => \"current_timestamp-'7 months'::interval" } );
$mech->get_ok( '/around?pc=OX20+1SZ&status=all' );
@@ -366,7 +409,36 @@ subtest 'check map zoom level customisation' => sub {
subtest 'check nearby lookup' => sub {
my $p = FixMyStreet::DB->resultset("Problem")->search({ external_body => "Pothole-confirmed" })->first;
$mech->get_ok('/around/nearby?latitude=51.754926&longitude=-1.256179&filter_category=Pothole');
- $mech->content_contains('["51.754926","-1.256179","yellow",' . $p->id . ',"Around page Test 1 for ' . $body->id . '","small",false]');
+ $mech->content_contains('[51.754926,-1.256179,"yellow",' . $p->id . ',"Around page Test 1 for ' . $body->id . '","small",false]');
+};
+
+my $he = Test::MockModule->new('HighwaysEngland');
+$he->mock('_lookup_db', sub {
+ my ($road, $table, $thing, $thing_name) = @_;
+
+ if ($road eq 'M6' && $thing eq '11') {
+ return { latitude => 52.65866, longitude => -2.06447 };
+ } elsif ($road eq 'M5' && $thing eq '132.5') {
+ return { latitude => 51.5457, longitude => 2.57136 };
+ }
+});
+
+subtest 'junction lookup' => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'fixmystreet',
+ MAPIT_URL => 'http://mapit.uk',
+ MAPIT_TYPES => ['EUR'],
+ }, sub {
+ $mech->log_out_ok;
+
+ $mech->get_ok('/');
+ $mech->submit_form_ok({ with_fields => { pc => 'M6, Junction 11' } });
+ $mech->content_contains('52.65866');
+
+ $mech->get_ok('/');
+ $mech->submit_form_ok({ with_fields => { pc => 'M5 132.5' } });
+ $mech->content_contains('51.5457');
+ };
};
done_testing();
diff --git a/t/app/controller/auth.t b/t/app/controller/auth.t
index ffabc75f3..24deb8cab 100644
--- a/t/app/controller/auth.t
+++ b/t/app/controller/auth.t
@@ -1,3 +1,19 @@
+package FixMyStreet::Cobrand::Dummy;
+use parent 'FixMyStreet::Cobrand::Default';
+
+sub must_have_2fa {
+ my ($self, $user) = @_;
+ return 'skip' if $user->name eq 'skip';
+ return 1;
+}
+
+package FixMyStreet::Cobrand::Expiring;
+use parent 'FixMyStreet::Cobrand::Default';
+
+sub password_expiry { 86400 }
+
+package main;
+
use Test::MockModule;
use FixMyStreet::TestMech;
@@ -7,10 +23,6 @@ my $test_email = 'test@example.com';
my $test_email3 = 'newuser@example.org';
my $test_password = 'foobar123';
-END {
- done_testing();
-}
-
$mech->get_ok('/auth');
# check that we can't reach a page that is only available to authenticated users
@@ -81,7 +93,7 @@ $mech->not_logged_in_ok;
# check that the user does not exist
sub get_user {
- FixMyStreet::App->model('DB::User')->find( { email => $test_email } );
+ FixMyStreet::DB->resultset('User')->find( { email => $test_email } );
}
ok !get_user(), "no user exists";
@@ -92,8 +104,10 @@ $mech->not_logged_in_ok;
# visit the confirm link and check user is confirmed
$mech->get_ok($link);
- ok get_user(), "user created";
+ my $user = get_user();
+ ok $user, "user created";
is $mech->uri->path, '/my', "redirected to the 'my' section of site";
+ ok $user->get_extra_metadata('last_password_change'), 'password change set';
$mech->logged_in_ok;
# logout
@@ -154,7 +168,7 @@ subtest "sign in with uppercase email" => sub {
$mech->content_contains($test_email);
$mech->content_lacks($uc_test_email);
- my $count = FixMyStreet::App->model('DB::User')->search( { email => $uc_test_email } )->count;
+ my $count = FixMyStreet::DB->resultset('User')->search( { email => $uc_test_email } )->count;
is $count, 0, "uppercase user wasn't created";
};
@@ -178,7 +192,7 @@ FixMyStreet::override_config {
ok $mech->email_count_is(0);
- my $count = FixMyStreet::App->model('DB::User')->search( { email => $test_email3 } )->count;
+ my $count = FixMyStreet::DB->resultset('User')->search( { email => $test_email3 } )->count;
is $count, 0, "no user exists";
};
@@ -229,7 +243,7 @@ subtest "check logging in with token" => sub {
$mech->log_out_ok;
$mech->not_logged_in_ok;
- my $user = FixMyStreet::App->model('DB::User')->find( { email => $test_email } );
+ my $user = FixMyStreet::DB->resultset('User')->find( { email => $test_email } );
# token needs to be 18 characters
$user->set_extra_metadata('access_token', '1234567890abcdefgh');
$user->update();
@@ -281,6 +295,7 @@ subtest 'test forgotten password page' => sub {
fields => { username => $test_email, password_register => 'squirblewirble' },
button => 'sign_in_by_code',
});
+ $mech->clear_emails_ok;
};
subtest "Test two-factor authentication login" => sub {
@@ -289,8 +304,7 @@ subtest "Test two-factor authentication login" => sub {
my $code = $auth->code;
my $wrong_code = $auth->code(undef, time() - 120);
- my $user = FixMyStreet::App->model('DB::User')->find( { email => $test_email } );
- $user->is_superuser(1);
+ my $user = FixMyStreet::DB->resultset('User')->find( { email => $test_email } );
$user->password('password');
$user->set_extra_metadata('2fa_secret', $auth->secret32);
$user->update;
@@ -305,3 +319,138 @@ subtest "Test two-factor authentication login" => sub {
$mech->submit_form_ok({ with_fields => { '2fa_code' => $code } }, "provide correct 2FA code" );
$mech->logged_in_ok;
};
+
+subtest "Test enforced two-factor authentication" => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'dummy',
+ }, sub {
+ my $user = FixMyStreet::DB->resultset('User')->find( { email => $test_email } );
+ $user->unset_extra_metadata('2fa_secret');
+ $user->update;
+
+ $mech->get_ok('/auth');
+ $mech->submit_form_ok(
+ { with_fields => { username => $test_email, password_sign_in => 'password' } },
+ "sign in using form" );
+
+ $mech->content_contains('requires two-factor');
+ $mech->submit_form_ok({ with_fields => { '2fa_action' => 'activate' } }, "submit 2FA activation");
+ my ($token) = $mech->content =~ /name="secret32" value="([^"]*)">/;
+
+ use Auth::GoogleAuth;
+ my $auth = Auth::GoogleAuth->new({ secret32 => $token });
+ my $code = $auth->code;
+ my $wrong_code = $auth->code(undef, time() - 120);
+
+ $mech->submit_form_ok({ with_fields => { '2fa_code' => $wrong_code } }, "provide wrong 2FA code" );
+ $mech->content_contains('Try again');
+ $mech->submit_form_ok({ with_fields => { '2fa_code' => $code } }, "provide correct 2FA code" );
+ $mech->content_contains('successfully enabled two-factor authentication', "2FA activated");
+
+ $user->discard_changes();
+ my $user_token = $user->get_extra_metadata('2fa_secret');
+ is $token, $user_token, '2FA secret set';
+
+ $mech->logged_in_ok;
+
+ $user->name('skip');
+ $user->update;
+ $mech->get_ok('/auth');
+ $mech->submit_form_ok(
+ { with_fields => { username => $test_email, password_sign_in => 'password' } },
+ "sign in using form" );
+ $mech->content_contains('<h1>Your account');
+ };
+};
+
+subtest "Test enforced two-factor authentication, no password yet set" => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'dummy',
+ }, sub {
+ my $user = FixMyStreet::DB->resultset('User')->find( { email => $test_email } );
+ $user->unset_extra_metadata('2fa_secret');
+ $user->name('Test User');
+ $user->update;
+
+ $mech->clear_emails_ok;
+ $mech->get_ok('/auth');
+ $mech->submit_form_ok({
+ fields => { username => $test_email, password_register => $test_password },
+ button => 'sign_in_by_code',
+ }, "log in by email");
+
+ my $link = $mech->get_link_from_email;
+ $mech->get_ok($link);
+
+ $mech->content_contains('requires two-factor');
+ $mech->submit_form_ok({ with_fields => { '2fa_action' => 'activate' } }, "submit 2fa activation");
+ my ($token) = $mech->content =~ /name="secret32" value="([^"]*)">/;
+
+ my $auth = Auth::GoogleAuth->new({ secret32 => $token });
+ my $code = $auth->code;
+ $mech->submit_form_ok({ with_fields => { '2fa_code' => $code } }, "provide correct 2fa code" );
+
+ $user->discard_changes();
+ my $user_token = $user->get_extra_metadata('2fa_secret');
+ is $token, $user_token, '2FA secret set';
+
+ $mech->logged_in_ok;
+
+ $mech->get_ok($link);
+ $mech->content_contains('Please generate a two-factor code');
+ $mech->submit_form_ok({ with_fields => { '2fa_code' => $code } }, "provide correct 2FA code" );
+ $mech->content_lacks('requires two-factor');
+
+ $user->name('skip');
+ $user->update;
+ $mech->get_ok($link);
+ $mech->content_contains('Your account');
+ };
+};
+
+subtest "Check two-factor log in by email works" => sub {
+ use Auth::GoogleAuth;
+ my $auth = Auth::GoogleAuth->new;
+ my $code = $auth->code;
+
+ my $user = FixMyStreet::DB->resultset('User')->find( { email => $test_email } );
+ $user->set_extra_metadata('2fa_secret', $auth->secret32);
+ $user->update;
+
+ $mech->clear_emails_ok;
+ $mech->get_ok('/auth');
+ $mech->submit_form_ok({
+ fields => { username => $test_email, password_register => $test_password },
+ button => 'sign_in_by_code',
+ }, "log in by email");
+
+ my $link = $mech->get_link_from_email;
+ $mech->get_ok($link);
+ $mech->content_contains('Please generate a two-factor code');
+ $mech->submit_form_ok({ with_fields => { '2fa_code' => $code } }, "provide correct 2FA code" );
+ $mech->logged_in_ok;
+};
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'expiring'
+}, sub {
+ subtest 'Password expiry' => sub {
+ my $user = FixMyStreet::DB->resultset('User')->find( { email => $test_email } );
+ $user->set_extra_metadata('last_password_change', time() - 200000);
+ $user->unset_extra_metadata('2fa_secret');
+ $user->update;
+
+ $mech->get_ok('/');
+ $mech->content_contains('Password expired');
+ $mech->submit_form_ok(
+ { with_fields => { password_register => 'new-password' } },
+ "fill in reset form" );
+
+ my $link = $mech->get_link_from_email;
+ $mech->clear_emails_ok;
+ $mech->get_ok($link);
+ $mech->logged_in_ok;
+ };
+};
+
+done_testing();
diff --git a/t/app/controller/auth_phone.t b/t/app/controller/auth_phone.t
index dea1c3493..e5f49ed19 100644
--- a/t/app/controller/auth_phone.t
+++ b/t/app/controller/auth_phone.t
@@ -60,7 +60,7 @@ FixMyStreet::override_config {
with_fields => { code => $code }
}, 'submit correct code');
- my $user = FixMyStreet::App->model('DB::User')->find( { phone => '+18165550100' } );
+ my $user = FixMyStreet::DB->resultset('User')->find( { phone => '+18165550100' } );
ok $user, "user created";
is $mech->uri->path, '/my', "redirected to the 'my' section of site";
$mech->logged_in_ok;
diff --git a/t/app/controller/auth_profile.t b/t/app/controller/auth_profile.t
index 4be1be12c..e5dfe2764 100644
--- a/t/app/controller/auth_profile.t
+++ b/t/app/controller/auth_profile.t
@@ -1,6 +1,17 @@
+package FixMyStreet::Cobrand::Dummy;
+use parent 'FixMyStreet::Cobrand::Default';
+
+sub must_have_2fa { 1 }
+
+package main;
+
+use Test::MockModule;
use FixMyStreet::TestMech;
my $mech = FixMyStreet::TestMech->new;
+my $resolver = Test::MockModule->new('Email::Valid');
+$resolver->mock('address', sub { $_[1] });
+
use t::Mock::Twilio;
my $twilio = t::Mock::Twilio->new;
@@ -10,10 +21,6 @@ my $test_email = 'test@example.com';
my $test_email2 = 'test@example.net';
my $test_password = 'foobar123';
-END {
- done_testing();
-}
-
# get a sign in email and change password
subtest "Test change password page" => sub {
$mech->clear_emails_ok;
@@ -66,7 +73,7 @@ subtest "Test change password page" => sub {
$mech->content_contains( $test->{err}, "found expected error" );
}
- my $user = FixMyStreet::App->model('DB::User')->find( { email => $test_email } );
+ my $user = FixMyStreet::DB->resultset('User')->find( { email => $test_email } );
ok $user, "got a user";
ok !$user->password, "user has no password";
@@ -126,7 +133,7 @@ subtest "Test change password page with current password" => sub {
$mech->content_contains( $test->{err}, "found expected error" );
}
- my $user = FixMyStreet::App->model('DB::User')->find( { email => $test_email } );
+ my $user = FixMyStreet::DB->resultset('User')->find( { email => $test_email } );
ok $user, "got a user";
$mech->get_ok('/auth/change_password');
@@ -179,12 +186,12 @@ subtest "Test change email page" => sub {
$mech->get_ok($link);
is $mech->uri->path, '/my', "redirected to /my page";
$mech->content_contains('successfully confirmed');
- ok(FixMyStreet::App->model('DB::User')->find( { email => $test_email2 } ), "got a user");
+ ok(FixMyStreet::DB->resultset('User')->find( { email => $test_email2 } ), "got a user");
my $p = FixMyStreet::DB->resultset("Problem")->first;
is $p->user->email, $test_email2, 'problem user updated';
- my $user1 = FixMyStreet::App->model('DB::User')->create( { email => $test_email, email_verified => 1 } );
+ my $user1 = FixMyStreet::DB->resultset('User')->create( { email => $test_email, email_verified => 1 } );
ok($user1, "created old user");
$mech->create_problems_for_body(1, 2514, 'Title1', { user => $user1 } );
@@ -222,7 +229,7 @@ my $test_landline = '01214960000';
my $test_mobile = '+61491570156';
my $test_mobile2 = '+61491570157';
-my $user_mob2 = FixMyStreet::App->model('DB::User')->create( {
+my $user_mob2 = FixMyStreet::DB->resultset('User')->create( {
phone => $test_mobile,
phone_verified => 1,
name => 'Aus Mobile user',
@@ -284,7 +291,7 @@ subtest "Test add/verify/change phone page" => sub {
with_fields => { code => $code }
}, 'submit correct code');
- my $user = FixMyStreet::App->model('DB::User')->find( { phone => $test_mobile } );
+ my $user = FixMyStreet::DB->resultset('User')->find( { phone => $test_mobile } );
ok $user, "user exists";
is $user->email_verified, 1;
is $user->email, $test_email, 'email still same';
@@ -320,9 +327,9 @@ subtest "Test change phone to existing account" => sub {
my $code = $twilio->get_text_code;
$mech->submit_form_ok({ with_fields => { code => $code } }, 'submit correct code');
- my $user = FixMyStreet::App->model('DB::User')->find( { phone => $test_mobile } );
+ my $user = FixMyStreet::DB->resultset('User')->find( { phone => $test_mobile } );
ok !$user, 'old user does not exist';
- $user = FixMyStreet::App->model('DB::User')->find( { phone => $test_mobile2 } );
+ $user = FixMyStreet::DB->resultset('User')->find( { phone => $test_mobile2 } );
ok $user, "new mobile user exists";
is $user->email_verified, 1;
is $user->email, $test_email, 'email still same';
@@ -335,7 +342,7 @@ subtest "Test change phone to existing account" => sub {
};
subtest "Test superuser can access generate token page" => sub {
- my $user = FixMyStreet::App->model('DB::User')->find( { email => $test_email } );
+ my $user = FixMyStreet::DB->resultset('User')->find( { email => $test_email } );
ok $user->update({ is_superuser => 0 }), 'user not superuser';
$mech->log_out_ok;
@@ -359,8 +366,10 @@ subtest "Test superuser can access generate token page" => sub {
$mech->get_ok('/auth/generate_token');
};
+my $body = $mech->create_body_ok(2237, 'Oxfordshire');
+
subtest "Test staff user can access generate token page" => sub {
- my $user = FixMyStreet::App->model('DB::User')->find( { email => $test_email } );
+ my $user = FixMyStreet::DB->resultset('User')->find( { email => $test_email } );
ok $user->update({ is_superuser => 0 }), 'user not superuser';
$mech->log_out_ok;
@@ -374,8 +383,6 @@ subtest "Test staff user can access generate token page" => sub {
$mech->content_lacks('Security');
- my $body = $mech->create_body_ok(2237, 'Oxfordshire');
-
$mech->get('/auth/generate_token');
is $mech->res->code, 403, "access denied";
@@ -387,7 +394,7 @@ subtest "Test staff user can access generate token page" => sub {
};
subtest "Test generate token page" => sub {
- my $user = FixMyStreet::App->model('DB::User')->find( { email => $test_email } );
+ my $user = FixMyStreet::DB->resultset('User')->find( { email => $test_email } );
ok $user->update({ is_superuser => 1 }), 'user set to superuser';
$mech->log_out_ok;
@@ -425,28 +432,80 @@ subtest "Test generate token page" => sub {
$mech->log_out_ok;
$mech->add_header('Authorization', "Bearer $token");
$mech->logged_in_ok;
+ $mech->delete_header('Authorization');
};
subtest "Test two-factor authentication admin" => sub {
- my $user = FixMyStreet::App->model('DB::User')->find( { email => $test_email } );
- ok $user->update({ is_superuser => 1 }), 'user set to superuser';
+ for (0, 1) {
+ my $user = $mech->log_in_ok($test_email);
+ if ($_) {
+ ok $user->update({ is_superuser => 1, from_body => undef }), 'user set to superuser';
+ } else {
+ ok $user->update({ is_superuser => 0, from_body => $body }), 'user set to staff user';
+ }
- $mech->log_in_ok($test_email);
$mech->get_ok('/auth/generate_token');
ok !$user->get_extra_metadata('2fa_secret');
- $mech->submit_form_ok({ button => 'toggle_2fa' }, "submit 2FA activation");
+ $mech->submit_form_ok({ button => '2fa_activate' }, "submit 2FA activation");
+ my ($token) = $mech->content =~ /name="secret32" value="([^"]*)">/;
+
+ use Auth::GoogleAuth;
+ my $auth = Auth::GoogleAuth->new({ secret32 => $token });
+ my $code = $auth->code;
+ my $wrong_code = $auth->code(undef, time() - 120);
+
+ $mech->submit_form_ok({ with_fields => { '2fa_code' => $wrong_code } }, "provide wrong 2FA code" );
+ $mech->content_contains('Try again');
+ $mech->submit_form_ok({ with_fields => { '2fa_code' => $code } }, "provide correct 2FA code" );
+
$mech->content_contains('has been activated', "2FA activated");
$user->discard_changes();
- my $token = $user->get_extra_metadata('2fa_secret');
- ok $token, '2FA secret set';
-
- $mech->content_contains($token, 'secret displayed');
+ my $user_token = $user->get_extra_metadata('2fa_secret');
+ is $token, $user_token, '2FA secret set';
$mech->get_ok('/auth/generate_token');
$mech->content_lacks($token, 'secret no longer displayed');
- $mech->submit_form_ok({ button => 'toggle_2fa' }, "submit 2FA deactivation");
+ $mech->submit_form_ok({ button => '2fa_deactivate' }, "submit 2FA deactivation");
$mech->content_contains('has been deactivated', "2FA deactivated");
+ }
};
+
+subtest "Test enforced two-factor authentication" => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'dummy',
+ }, sub {
+ use Auth::GoogleAuth;
+ my $auth = Auth::GoogleAuth->new;
+ my $code = $auth->code;
+
+ # Sign in with 2FA
+ my $user = FixMyStreet::DB->resultset('User')->find( { email => $test_email } );
+ $user->password('password');
+ $user->set_extra_metadata('2fa_secret', $auth->secret32);
+ $user->update;
+
+ $mech->get_ok('/auth');
+ $mech->submit_form_ok(
+ { with_fields => { username => $test_email, password_sign_in => 'password' } },
+ "sign in using form" );
+ $mech->content_contains('Please generate a two-factor code');
+ $mech->submit_form_ok({ with_fields => { '2fa_code' => $code } }, "provide correct 2FA code" );
+
+ $mech->get_ok('/auth/generate_token');
+ $mech->content_contains('Change two-factor');
+ $mech->content_lacks('Deactivate two-factor');
+
+ my ($csrf) = $mech->content =~ /meta content="([^"]*)" name="csrf-token"/;
+ $mech->post_ok('/auth/generate_token', {
+ '2fa_deactivate' => 1,
+ 'token' => $csrf,
+ });
+ $mech->content_lacks('has been deactivated', "2FA not deactivated");
+ $mech->content_contains('Please scan this image', 'Change 2FA page shown instead');
+ };
+};
+
+done_testing();
diff --git a/t/app/controller/auth_social.t b/t/app/controller/auth_social.t
index ac3d98b15..200863029 100644
--- a/t/app/controller/auth_social.t
+++ b/t/app/controller/auth_social.t
@@ -5,54 +5,133 @@ use JSON::MaybeXS;
use t::Mock::Facebook;
use t::Mock::Twitter;
+use t::Mock::OpenIDConnect;
use FixMyStreet::TestMech;
my $mech = FixMyStreet::TestMech->new;
-
+
# disable info logs for this test run
FixMyStreet::App->log->disable('info');
END { FixMyStreet::App->log->enable('info'); }
-my ($report) = $mech->create_problems_for_body(1, '2345', 'Test');
+my $body = $mech->create_body_ok(2504, 'Westminster City Council');
-FixMyStreet::override_config {
- FACEBOOK_APP_ID => 'facebook-app-id',
- TWITTER_KEY => 'twitter-key',
- ALLOWED_COBRANDS => [ { fixmystreet => '.' } ],
- MAPIT_URL => 'http://mapit.uk/',
-}, sub {
+my ($report) = $mech->create_problems_for_body(1, $body->id, 'My Test Report');
+my $test_email = $report->user->email;
-my $fb_email = 'facebook@example.org';
-my $fb_uid = 123456789;
+my $contact = $mech->create_contact_ok(
+ body_id => $body->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',
+);
my $resolver = Test::MockModule->new('Email::Valid');
-$resolver->mock('address', sub { 'facebook@example.org' });
+my $social = Test::MockModule->new('FixMyStreet::App::Controller::Auth::Social');
+$social->mock('generate_nonce', sub { 'MyAwesomeRandomValue' });
+
+for my $test (
+ {
+ type => 'facebook',
+ config => {
+ FACEBOOK_APP_ID => 'facebook-app-id',
+ ALLOWED_COBRANDS => [ { fixmystreet => '.' } ],
+ MAPIT_URL => 'http://mapit.uk/',
+ },
+ update => 1,
+ email => $mech->uniquify_email('facebook@example.org'),
+ uid => 123456789,
+ mock => 't::Mock::Facebook',
+ mock_hosts => ['www.facebook.com', 'graph.facebook.com'],
+ host => 'www.facebook.com',
+ error_callback => '/auth/Facebook?error_code=ERROR',
+ success_callback => '/auth/Facebook?code=response-code',
+ redirect_pattern => qr{facebook\.com.*dialog/oauth.*facebook-app-id},
+}, {
+ type => 'oidc',
+ config => {
+ ALLOWED_COBRANDS => 'westminster',
+ MAPIT_URL => 'http://mapit.uk/',
+ COBRAND_FEATURES => {
+ anonymous_account => {
+ westminster => 'test',
+ },
+ oidc_login => {
+ westminster => {
+ client_id => 'example_client_id',
+ secret => 'example_secret_key',
+ auth_uri => 'http://oidc.example.org/oauth2/v2.0/authorize',
+ token_uri => 'http://oidc.example.org/oauth2/v2.0/token',
+ logout_uri => 'http://oidc.example.org/oauth2/v2.0/logout',
+ password_change_uri => 'http://oidc.example.org/oauth2/v2.0/password_change',
+ display_name => 'MyWestminster'
+ }
+ }
+ }
+ },
+ email => $mech->uniquify_email('oidc@example.org'),
+ uid => "westminster:example_client_id:my_cool_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},
+ logout_redirect_pattern => qr{oidc\.example\.org/oauth2/v2\.0/logout},
+ password_change_pattern => qr{oidc\.example\.org/oauth2/v2\.0/password_change},
+ user_extras => [
+ [westminster_account_id => "1c304134-ef12-c128-9212-123908123901"],
+ ],
+}
+) {
+
+FixMyStreet::override_config $test->{config}, sub {
-for my $fb_state ( 'refused', 'no email', 'existing UID', 'okay' ) {
+$resolver->mock('address', sub { $test->{email} });
+
+for my $state ( 'refused', 'no email', 'existing UID', 'okay' ) {
for my $page ( 'my', 'report', 'update' ) {
- subtest "test FB '$fb_state' login for page '$page'" => sub {
+ next if $page eq 'update' && !$test->{update};
+
+ subtest "test $test->{type} '$state' login for page '$page'" => sub {
# 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;
$mech->cookie_jar({});
- if ($fb_state eq 'existing UID') {
- my $user = $mech->create_user_ok($fb_email);
- $user->update({ facebook_id => $fb_uid });
+ if ($state eq 'existing UID') {
+ my $user = $mech->create_user_ok($test->{email});
+ if ($test->{type} eq 'facebook') {
+ $user->update({ facebook_id => $test->{uid} });
+ } elsif ($test->{type} eq 'oidc') {
+ $user->update({ oidc_ids => [ $test->{uid} ] });
+ }
+ } else {
+ $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 });
} else {
- $mech->delete_user($fb_email);
+ $report->update({ user_id => FixMyStreet::DB->resultset( 'User' )->find( { email => $test_email } )->id });
}
- # Set up a mock to catch (most, see below) requests to Facebook
- my $fb = t::Mock::Facebook->new;
- $fb->returns_email(0) if $fb_state eq 'no email' || $fb_state eq 'existing UID';
- LWP::Protocol::PSGI->register($fb->to_psgi_app, host => 'www.facebook.com');
- LWP::Protocol::PSGI->register($fb->to_psgi_app, host => 'graph.facebook.com');
+ # Set up a mock to catch (most, see below) requests to the OAuth API
+ my $mock_api = $test->{mock}->new;
+ $mock_api->returns_email(0) if $state eq 'no email' || $state eq 'existing UID';
+ for my $host (@{ $test->{mock_hosts} }) {
+ LWP::Protocol::PSGI->register($mock_api->to_psgi_app, host => $host);
+ }
# Due to https://metacpan.org/pod/Test::WWW::Mechanize::Catalyst#External-Redirects-and-allow_external
- # the redirect to Facebook's OAuth page can mess up the session
- # cookie. So let's pretend we always on www.facebook.com, which
+ # the redirect to the OAuth page can mess up the session
+ # cookie. So let's pretend we're always on the API host, which
# sorts that out.
- $mech->host('www.facebook.com');
+ $mech->host($test->{host});
# Fetch the page with the form via which we wish to log in
my $fields;
@@ -62,9 +141,13 @@ for my $fb_state ( 'refused', 'no email', 'existing UID', 'okay' ) {
$mech->get_ok('/');
$mech->submit_form_ok( { with_fields => { pc => 'SW1A1AA' } }, "submit location" );
$mech->follow_link_ok( { text_regex => qr/skip this step/i, }, "follow 'skip this step' link" );
- $fields = {
+ $mech->submit_form(with_fields => {
+ category => 'Damaged bin',
title => 'Test title',
detail => 'Test detail',
+ });
+ $fields = {
+ bin_type => 'Salt bin',
};
} else {
$mech->get_ok('/report/' . $report->id);
@@ -72,37 +155,41 @@ for my $fb_state ( 'refused', 'no email', 'existing UID', 'okay' ) {
update => 'Test update',
};
}
- $mech->submit_form(with_fields => $fields, button => 'facebook_sign_in');
+ $mech->submit_form(with_fields => $fields, button => 'social_sign_in');
# As well as the cookie issue above, caused by this external
# redirect rewriting the host, the redirect gets handled directly
# by Catalyst, not our mocked handler, so will be a 404. Check
# the redirect happened instead.
- is $mech->res->previous->code, 302, 'FB button redirected';
- like $mech->res->previous->header('Location'), qr{facebook\.com.*dialog/oauth.*facebook-app-id}, 'FB redirect to oauth URL';
-
- # Okay, now call the callback Facebook would send us to
- if ($fb_state eq 'refused') {
- $mech->get_ok('/auth/Facebook?error_code=ERROR');
+ is $mech->res->previous->code, 302, "$test->{type} button redirected";
+ like $mech->res->previous->header('Location'), $test->{redirect_pattern}, "$test->{type} redirect to oauth URL";
+
+ # Okay, now call the callback we'd be sent to
+ # NB: for OIDC these should be post_ok, but that doesn't work because
+ # the session cookie doesn't seem to be included (related to the
+ # cookie issue above perhaps).
+ if ($state eq 'refused') {
+ $mech->get_ok($test->{error_callback});
} else {
- $mech->get_ok('/auth/Facebook?code=response-code');
+ $mech->get_ok($test->{success_callback});
}
# Check we're showing the right form, regardless of what came back
if ($page eq 'report') {
$mech->content_contains('/report/new');
+ $mech->content_contains('Salt bin');
} elsif ($page eq 'update') {
$mech->content_contains('/report/update');
}
- if ($fb_state eq 'refused') {
- $mech->content_contains('Sorry, we could not log you in. Please fill in the form below.');
+ if ($state eq 'refused') {
+ $mech->content_contains('Sorry, we could not log you in.');
$mech->not_logged_in_ok;
- } elsif ($fb_state eq 'no email') {
+ } elsif ($state eq '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} = $fb_email;
+ $fields->{username} = $test->{email};
$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');
@@ -111,32 +198,86 @@ for my $fb_state ( 'refused', 'no email', 'existing UID', 'okay' ) {
$mech->clear_emails_ok;
ok $url, "extracted confirm url '$url'";
- my $user = FixMyStreet::App->model( 'DB::User' )->find( { email => $fb_email } );
+ my $user = FixMyStreet::DB->resultset( 'User' )->find( { email => $test->{email} } );
if ($page eq 'my') {
is $user, undef, 'No user yet exists';
} else {
- is $user->facebook_id, undef, 'User has no facebook ID';
+ if ($test->{type} eq 'facebook') {
+ is $user->facebook_id, undef, 'User has no facebook ID';
+ } elsif ($test->{type} eq 'oidc') {
+ is $user->oidc_ids, undef, 'User has no OIDC IDs';
+ }
}
$mech->get_ok( $url );
- $user = FixMyStreet::App->model( 'DB::User' )->find( { email => $fb_email } );
- is $user->facebook_id, $fb_uid, 'User now has correct facebook ID';
+ $user = FixMyStreet::DB->resultset( 'User' )->find( { email => $test->{email} } );
+ if ($test->{type} eq 'facebook') {
+ is $user->facebook_id, $test->{uid}, 'User now has correct facebook ID';
+ } elsif ($test->{type} eq 'oidc') {
+ is_deeply $user->oidc_ids, [ $test->{uid} ], 'User now has correct OIDC IDs';
+ }
+ if ($test->{user_extras}) {
+ for my $extra (@{ $test->{user_extras} }) {
+ my ($k, $v) = @$extra;
+ is $user->get_extra_metadata($k), $v, "User has correct $k extra field";
+ }
+ }
} elsif ($page ne 'my') {
# /my auth login goes directly there, no message like this
$mech->content_contains('You have successfully signed in; please check and confirm your details are accurate');
$mech->logged_in_ok;
+ if ($test->{user_extras}) {
+ my $user = FixMyStreet::DB->resultset( 'User' )->find( { email => $test->{email} } );
+ for my $extra (@{ $test->{user_extras} }) {
+ my ($k, $v) = @$extra;
+ is $user->get_extra_metadata($k), $v, "User has correct $k extra field";
+ }
+ }
} else {
is $mech->uri->path, '/my', 'Successfully on /my page';
+ if ($test->{user_extras}) {
+ my $user = FixMyStreet::DB->resultset( 'User' )->find( { email => $test->{email} } );
+ for my $extra (@{ $test->{user_extras} }) {
+ my ($k, $v) = @$extra;
+ is $user->get_extra_metadata($k), $v, "User has correct $k extra field";
+ }
+ }
+ if ($state eq 'existing UID') {
+ my $report_id = $report->id;
+ $mech->content_contains( $report->title );
+ $mech->content_contains( "/report/$report_id" );
+ }
+ if ($test->{type} eq 'oidc') {
+ 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') {
+ # 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.
+ is $mech->res->previous->code, 302, "$test->{type} sign out redirected";
+ like $mech->res->previous->header('Location'), $test->{logout_redirect_pattern}, "$test->{type} sign out redirect to oauth logout URL";
+ }
+ $mech->not_logged_in_ok;
}
}
}
+}
+};
-$resolver->mock('address', sub { 'twitter@example.org' });
+FixMyStreet::override_config {
+ TWITTER_KEY => 'twitter-key',
+ ALLOWED_COBRANDS => [ { fixmystreet => '.' } ],
+ MAPIT_URL => 'http://mapit.uk/',
+}, sub {
-my $tw_email = 'twitter@example.org';
+my $tw_email = $mech->uniquify_email('twitter@example.org');
my $tw_uid = 987654321;
+$resolver->mock('address', sub { $tw_email });
+
# Twitter has no way of getting the email, so no "okay" state here
for my $tw_state ( 'refused', 'existing UID', 'no email' ) {
for my $page ( 'my', 'report', 'update' ) {
@@ -170,9 +311,13 @@ for my $tw_state ( 'refused', 'existing UID', 'no email' ) {
$mech->get_ok('/');
$mech->submit_form_ok( { with_fields => { pc => 'SW1A1AA' } }, "submit location" );
$mech->follow_link_ok( { text_regex => qr/skip this step/i, }, "follow 'skip this step' link" );
- $fields = {
+ $mech->submit_form(with_fields => {
+ category => 'Damaged bin',
title => 'Test title',
detail => 'Test detail',
+ });
+ $fields = {
+ bin_type => 'Salt bin',
};
} else {
$mech->get_ok('/report/' . $report->id);
@@ -180,7 +325,7 @@ for my $tw_state ( 'refused', 'existing UID', 'no email' ) {
update => 'Test update',
};
}
- $mech->submit_form(with_fields => $fields, button => 'twitter_sign_in');
+ $mech->submit_form(with_fields => $fields, button => 'social_sign_in');
# As well as the cookie issue above, caused by this external
# redirect rewriting the host, the redirect gets handled directly
@@ -199,6 +344,7 @@ for my $tw_state ( 'refused', 'existing UID', 'no email' ) {
# Check we're showing the right form, regardless of what came back
if ($page eq 'report') {
$mech->content_contains('/report/new');
+ $mech->content_contains('Salt bin');
} elsif ($page eq 'update') {
$mech->content_contains('/report/update');
}
@@ -219,14 +365,14 @@ for my $tw_state ( 'refused', 'existing UID', 'no email' ) {
$mech->clear_emails_ok;
ok $url, "extracted confirm url '$url'";
- my $user = FixMyStreet::App->model( 'DB::User' )->find( { email => $tw_email } );
+ my $user = FixMyStreet::DB->resultset( 'User' )->find( { email => $tw_email } );
if ($page eq 'my') {
is $user, undef, 'No user yet exists';
} else {
is $user->twitter_id, undef, 'User has no twitter ID';
}
$mech->get_ok( $url );
- $user = FixMyStreet::App->model( 'DB::User' )->find( { email => $tw_email } );
+ $user = FixMyStreet::DB->resultset( 'User' )->find( { email => $tw_email } );
is $user->twitter_id, $tw_uid, 'User now has correct twitter ID';
} elsif ($page ne 'my') {
@@ -242,6 +388,4 @@ for my $tw_state ( 'refused', 'existing UID', 'no email' ) {
};
-END {
- done_testing();
-}
+done_testing();
diff --git a/t/app/controller/contact.t b/t/app/controller/contact.t
index 842f27dd5..d6e56e7cc 100644
--- a/t/app/controller/contact.t
+++ b/t/app/controller/contact.t
@@ -6,6 +6,16 @@ sub abuse_reports_only { 1; }
1;
+package FixMyStreet::Cobrand::GeneralEnquiries;
+
+use base 'FixMyStreet::Cobrand::Default';
+
+sub abuse_reports_only { 1 }
+
+sub setup_general_enquiries_stash { 1 }
+
+1;
+
package main;
use FixMyStreet::TestMech;
@@ -104,7 +114,7 @@ for my $test (
subtest 'check reporting a problem displays correctly' => sub {
my $user = $mech->create_user_ok($test->{email}, name => $test->{name});
- my $problem = FixMyStreet::App->model('DB::Problem')->create(
+ my $problem = FixMyStreet::DB->resultset('Problem')->create(
{
title => $test->{title},
detail => $test->{detail},
@@ -128,7 +138,7 @@ for my $test (
my $update_user = $mech->create_user_ok($update_info->{email},
name => $update_info->{name});
- $update = FixMyStreet::App->model('DB::Comment')->create(
+ $update = FixMyStreet::DB->resultset('Comment')->create(
{
problem_id => $update_info->{other_problem} ? $problem_main->id : $problem->id,
user => $update_user,
@@ -327,6 +337,71 @@ for my $test (
}
for my $test (
+ { fields => \%common }
+ )
+{
+ subtest 'check email contains user details' => sub {
+ my $user = $mech->create_user_ok(
+ $test->{fields}->{em},
+ name => $test->{fields}->{name}
+ );
+
+ my $older_unhidden_problem = FixMyStreet::DB->resultset('Problem')->create(
+ {
+ title => 'Some problem or other',
+ detail => 'More detail on the problem',
+ postcode => 'EH99 1SP',
+ confirmed => '2011-05-04 10:44:28.145168',
+ anonymous => 0,
+ name => $test->{fields}->{name},
+ state => 'confirmed',
+ user => $user,
+ latitude => 0,
+ longitude => 0,
+ areas => 0,
+ used_map => 0,
+ }
+ );
+
+ my $newer_hidden_problem = FixMyStreet::DB->resultset('Problem')->create(
+ {
+ title => 'A hidden problem',
+ detail => 'Shhhh secret',
+ postcode => 'EH99 1SP',
+ confirmed => '2012-06-05 10:44:28.145168',
+ anonymous => 0,
+ name => $test->{fields}->{name},
+ state => 'hidden',
+ user => $user,
+ latitude => 0,
+ longitude => 0,
+ areas => 0,
+ used_map => 0,
+ }
+ );
+
+ $mech->clear_emails_ok;
+ $mech->get_ok('/contact');
+ $test->{fields}{em} = $user->email;
+ $mech->submit_form_ok( { with_fields => $test->{fields} } );
+
+ my $email = $mech->get_email;
+ my $body = $mech->get_text_body_from_email($email);
+
+ my $user_id = $user->id;
+ my $user_email = $user->email;
+ my $older_unhidden_problem_id = $older_unhidden_problem->id;
+ my $newer_hidden_problem_id = $newer_hidden_problem->id;
+
+ like $body, qr/admin\/users\/$user_id/, 'email contains admin link to edit user';
+ like $body, qr/admin\/reports\?search=$user_email/, 'email contains admin link to show users reports';
+ like $body, qr/admin\/report_edit\/$older_unhidden_problem_id/, 'email contains admin link for users latest unhidden report';
+ unlike $body, qr/admin\/report_edit\/$newer_hidden_problem_id/, 'email does not link to hidden reports';
+
+ };
+}
+
+for my $test (
{
fields => { %common, dest => undef },
page_errors =>
@@ -482,7 +557,28 @@ subtest 'check can limit contact to abuse reports' => sub {
is $mech->res->code, 404, 'cannot visit contact page';
$mech->get_ok( '/contact?id=' . $problem_main->id, 'can visit for abuse report' );
- my $token = FixMyStreet::App->model("DB::Token")->create({
+ my $token = FixMyStreet::DB->resultset("Token")->create({
+ scope => 'moderation',
+ data => { id => $problem_main->id }
+ });
+
+ $mech->get_ok( '/contact?m=' . $token->token, 'can visit for moderation complaint' );
+
+ }
+};
+
+subtest 'check redirected to correct form for general enquiries cobrand' => sub {
+ FixMyStreet::override_config {
+ 'ALLOWED_COBRANDS' => [ 'generalenquiries' ],
+ }, sub {
+ $mech->get( '/contact' );
+ is $mech->res->code, 200, "got 200 for final destination";
+ is $mech->res->previous->code, 302, "got 302 for redirect";
+ is $mech->uri->path, '/contact/enquiry';
+
+ $mech->get_ok( '/contact?id=' . $problem_main->id, 'can visit for abuse report' );
+
+ my $token = FixMyStreet::DB->resultset("Token")->create({
scope => 'moderation',
data => { id => $problem_main->id }
});
diff --git a/t/app/controller/contact_enquiry.t b/t/app/controller/contact_enquiry.t
new file mode 100644
index 000000000..af249ec6c
--- /dev/null
+++ b/t/app/controller/contact_enquiry.t
@@ -0,0 +1,267 @@
+use utf8;
+use Encode;
+use FixMyStreet::TestMech;
+use Path::Tiny;
+use File::Temp 'tempdir';
+use FixMyStreet::Script::Reports;
+use Test::MockModule;
+
+# disable info logs for this test run
+FixMyStreet::App->log->disable('info');
+END { FixMyStreet::App->log->enable('info'); }
+
+my $mech = FixMyStreet::TestMech->new;
+
+my $body = $mech->create_body_ok( 2483, 'Hounslow Borough Council', {
+ send_method => 'Open311',
+ endpoint => 'endpoint',
+ api_key => 'key',
+ jurisdiction => 'hounslow',
+});
+my $contact = $mech->create_contact_ok(
+ body_id => $body->id,
+ category => 'General Enquiry',
+ email => 'genenq@example.com',
+ non_public => 1,
+);
+my $contact2 = $mech->create_contact_ok(
+ body_id => $body->id,
+ category => 'FOI Request',
+ email => 'foi@example.com',
+ non_public => 1,
+);
+my $contact3 = $mech->create_contact_ok(
+ body_id => $body->id,
+ category => 'Other',
+ email => 'other@example.com',
+);
+my $contact4 = $mech->create_contact_ok(
+ body_id => $body->id,
+ category => 'Carriageway Defect',
+ email => 'potholes@example.com',
+);
+$contact->update( { extra => { group => 'General Enquiries' } } );
+$contact2->update( { extra => { group => 'General Enquiries' } } );
+$contact3->update( { extra => { group => 'Other' } } );
+
+FixMyStreet::override_config { ALLOWED_COBRANDS => ['bromley'], }, sub {
+ subtest 'redirected to / if general enquiries not enabled' => sub {
+ $mech->get( '/contact/enquiry' );
+ is $mech->res->code, 200, "got 200 for final destination";
+ is $mech->res->previous->code, 302, "got 302 for redirect";
+ is $mech->uri->path, '/';
+ };
+};
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => ['hounslow'],
+ MAPIT_URL => 'http://mapit.uk/',
+}, sub {
+ subtest 'Non-general enquiries category not shown' => sub {
+ $mech->get_ok( '/contact/enquiry' );
+ $mech->content_lacks('Carriageway Defect');
+ $mech->content_contains('FOI Request');
+ };
+
+ subtest 'Enquiry can be submitted when logged out' => sub {
+ my $problems = FixMyStreet::DB->resultset('Problem')->to_body( $body->id );
+
+ $mech->get_ok( '/contact/enquiry' );
+ $mech->submit_form_ok( {
+ with_fields => {
+ name => 'Test User',
+ username => 'testuser@example.org',
+ category => 'Other',
+ detail => 'This is a general enquiry',
+ }
+ } );
+ is $mech->uri->path, '/contact/enquiry/submit';
+ $mech->content_contains("Thank you for your enquiry");
+
+ is $problems->count, 1, 'problem created';
+ my $problem = $problems->first;
+ is $problem->category, 'Other', 'problem has correct category';
+ is $problem->detail, 'This is a general enquiry', 'problem has correct detail';
+ is $problem->non_public, 1, 'problem created non_public';
+ is $problem->postcode, '';
+ is $problem->used_map, 0;
+ is $problem->latitude, 51.469, 'Problem has correct latitude';
+ is $problem->longitude, -0.35, 'Problem has correct longitude';
+ ok $problem->confirmed, 'problem confirmed';
+ is $problem->user->name, undef, 'User created without name';
+ is $problem->name, 'Test User', 'Report created with correct name';
+ is $problem->user->email, 'testuser@example.org', 'User created with correct email';
+ };
+
+ subtest 'Enquiry can be submitted when logged in' => sub {
+ my $problems = FixMyStreet::DB->resultset('Problem')->to_body( $body->id );
+ my $prob_user = $problems->first->user;
+ $problems->delete_all;
+
+ my $user = $mech->log_in_ok( $prob_user->email );
+
+ $mech->get_ok( '/contact/enquiry' );
+ $mech->submit_form_ok( {
+ with_fields => {
+ name => 'Test User',
+ category => 'FOI Request',
+ detail => 'This is a general enquiry',
+ }
+ } );
+ is $mech->uri->path, '/contact/enquiry/submit';
+ $mech->content_contains("Thank you for your enquiry");
+
+ is $problems->count, 1, 'problem created';
+ my $problem = $problems->first;
+ is $problem->category, 'FOI Request', 'problem has correct category';
+ is $problem->detail, 'This is a general enquiry', 'problem has correct detail';
+ is $problem->non_public, 1, 'problem created non_public';
+ is $problem->postcode, '';
+ is $problem->used_map, 0;
+ is $problem->latitude, 51.469, 'Problem has correct latitude';
+ is $problem->longitude, -0.35, 'Problem has correct longitude';
+ ok $problem->confirmed, 'problem confirmed';
+ is $problem->name, 'Test User', 'Report created with correct name';
+ is $problem->user->name, 'Test User', 'User name updated in DB';
+ is $problem->user->email, $user->email, 'Report user has correct email';
+
+ $mech->log_out_ok;
+ };
+
+ subtest 'User name not changed if logged out when making report' => sub {
+ my $problems = FixMyStreet::DB->resultset('Problem')->to_body( $body->id );
+ my $user = $problems->first->user;
+ $problems->delete_all;
+
+ is $user->name, 'Test User', 'User has correct name';
+
+ $mech->get_ok( '/contact/enquiry' );
+ $mech->submit_form_ok( {
+ with_fields => {
+ name => 'Simon Neil',
+ username => $user->email,
+ category => 'General Enquiry',
+ detail => 'This is a general enquiry',
+ }
+ } );
+ is $mech->uri->path, '/contact/enquiry/submit';
+ $mech->content_contains("Thank you for your enquiry");
+
+ is $problems->count, 1, 'problem created';
+ my $problem = $problems->first;
+ is $problem->category, 'General Enquiry', 'problem has correct category';
+ is $problem->detail, 'This is a general enquiry', 'problem has correct detail';
+ is $problem->non_public, 1, 'problem created non_public';
+ is $problem->postcode, '';
+ is $problem->used_map, 0;
+ is $problem->latitude, 51.469, 'Problem has correct latitude';
+ is $problem->longitude, -0.35, 'Problem has correct longitude';
+ ok $problem->confirmed, 'problem confirmed';
+ is $problem->name, 'Simon Neil', 'Report created with correct name';
+ is $problem->user->email, $user->email, 'Report user has correct email';
+ $user->discard_changes;
+ is $user->name, 'Test User', 'User name in DB not changed';
+
+ $mech->log_out_ok;
+ };
+
+};
+
+my $sample_jpeg = path(__FILE__)->parent->child("sample.jpg");
+ok $sample_jpeg->exists, "sample image $sample_jpeg exists";
+my $sample_pdf = path(__FILE__)->parent->child("sample.pdf");
+ok $sample_pdf->exists, "sample PDF $sample_pdf exists";
+
+my $UPLOAD_DIR = tempdir( CLEANUP => 1 );
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'hounslow' ],
+ STAGING_FLAGS => { send_reports => 1 },
+ MAPIT_URL => 'http://mapit.uk/',
+ PHOTO_STORAGE_BACKEND => 'FileSystem',
+ PHOTO_STORAGE_OPTIONS => {
+ UPLOAD_DIR => $UPLOAD_DIR,
+ },
+}, sub {
+
+ my $pdf_hash = '90f7a64043fb458d58de1a0703a6355e2856b15e.pdf';
+ my $image_hash = '74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg';
+
+ subtest "Check photo & file upload works" => sub {
+ my $problems = FixMyStreet::DB->resultset('Problem')->to_body( $body->id );
+ $problems->delete_all;
+
+
+ $mech->get_ok('/contact/enquiry');
+ my ($csrf) = $mech->content =~ /name="token" value="([^"]*)"/;
+
+ $mech->post( '/contact/enquiry/submit',
+ Content_Type => 'form-data',
+ Content =>
+ {
+ submit_problem => 1,
+ token => $csrf,
+ name => 'Test User',
+ username => 'testuser@example.org',
+ category => 'Other',
+ detail => encode_utf8('This is a general enquiry‽'),
+ photo1 => [ $sample_jpeg, undef, Content_Type => 'image/jpeg' ],
+ photo2 => [ $sample_pdf, undef, Content_Type => 'application/pdf' ],
+ }
+ );
+ ok $mech->success, 'Made request with two files uploaded';
+
+ is $problems->count, 1, 'problem created';
+ my $problem = $problems->first;
+ is $problem->detail, 'This is a general enquiry‽', 'problem has correct detail';
+ is $problem->non_public, 1, 'problem created non_public';
+ is $problem->postcode, '';
+ is $problem->used_map, 0;
+ is $problem->latitude, 51.469, 'Problem has correct latitude';
+ is $problem->longitude, -0.35, 'Problem has correct longitude';
+ ok $problem->confirmed, 'problem confirmed';
+
+ my $image_file = path($UPLOAD_DIR, $image_hash);
+ ok $image_file->exists, 'Photo uploaded to temp';
+
+ my $photoset = $problem->get_photoset();
+ is $photoset->num_images, 1, 'Found just 1 image';
+ is $photoset->data, $image_hash;
+
+ my $pdf_file = path($UPLOAD_DIR, 'enquiry_files', $pdf_hash);
+ ok $pdf_file->exists, 'PDF uploaded to temp';
+
+ is_deeply $problem->get_extra_metadata('enquiry_files'), {
+ $pdf_hash => 'sample.pdf'
+ }, 'enquiry file info stored OK';
+ };
+
+ subtest 'Check Open311 sending of the above report' => sub {
+ my $module = Test::MockModule->new('FixMyStreet::Cobrand::UKCouncils');
+ $module->mock(get => sub ($) { '{}' });
+ my $test_data = FixMyStreet::Script::Reports::send();
+ my $req = $test_data->{test_req_used};
+ my $found = 0;
+ foreach ($req->parts) {
+ my $cd = $_->header('Content-Disposition');
+ if ($cd =~ /attribute\[description\]/) {
+ is decode_utf8($_->content), 'This is a general enquiry‽', 'Correct description';
+ $found++;
+ }
+ if ($cd =~ /sample.pdf/) {
+ is $cd, 'form-data; name="file_' . $pdf_hash . '"; filename="sample.pdf"', 'Correct PDF header';
+ is $_->header('Content-Type'), 'application/pdf', 'Correct PDF content type';
+ $found++;
+ }
+ if ($cd =~ /jpeg/) {
+ is $cd, 'form-data; name="photo1"; filename="' . $image_hash . '"', 'Correct image header';
+ is $_->header('Content-Type'), 'image/jpeg', 'Correct image content type';
+ $found++;
+ }
+ }
+ is $found, 3, 'Found all tested headers';
+ };
+
+};
+
+done_testing();
diff --git a/t/app/controller/dashboard.t b/t/app/controller/dashboard.t
index ff8d1a9d5..72fc00128 100644
--- a/t/app/controller/dashboard.t
+++ b/t/app/controller/dashboard.t
@@ -1,5 +1,9 @@
use Test::MockTime ':all';
+package FixMyStreet::Cobrand::No2FA;
+use parent 'FixMyStreet::Cobrand::FixMyStreet';
+sub must_have_2fa { 0 }
+
package FixMyStreet::Cobrand::Tester;
use parent 'FixMyStreet::Cobrand::Default';
# Allow access if CSV export for a body, otherwise deny
@@ -26,7 +30,11 @@ my $other_body = $mech->create_body_ok(1234, 'Some Other Council');
my $body = $mech->create_body_ok(2651, 'City of Edinburgh Council');
my @cats = ('Litter', 'Other', 'Potholes', 'Traffic lights');
for my $contact ( @cats ) {
- $mech->create_contact_ok(body_id => $body->id, category => $contact, email => "$contact\@example.org");
+ my $c = $mech->create_contact_ok(body_id => $body->id, category => $contact, email => "$contact\@example.org");
+ if ($contact eq 'Potholes') {
+ $c->set_extra_metadata(group => ['Road']);
+ $c->update;
+ }
}
my $superuser = $mech->create_user_ok('superuser@example.com', name => 'Super User', is_superuser => 1);
@@ -38,17 +46,21 @@ my $area_id = '60705';
my $alt_area_id = '62883';
my $last_month = DateTime->now->subtract(months => 2);
-$mech->create_problems_for_body(2, $body->id, 'Title', { areas => ",$area_id,2651,", category => 'Potholes', cobrand => 'fixmystreet' });
-$mech->create_problems_for_body(3, $body->id, 'Title', { areas => ",$area_id,2651,", category => 'Traffic lights', cobrand => 'fixmystreet', dt => $last_month });
-$mech->create_problems_for_body(1, $body->id, 'Title', { areas => ",$alt_area_id,2651,", category => 'Litter', cobrand => 'fixmystreet' });
+$mech->create_problems_for_body(2, $body->id, 'Title', { areas => ",$area_id,2651,", category => 'Potholes', cobrand => 'no2fat' });
+$mech->create_problems_for_body(3, $body->id, 'Title', { areas => ",$area_id,2651,", category => 'Traffic lights', cobrand => 'no2fa', dt => $last_month });
+$mech->create_problems_for_body(1, $body->id, 'Title', { areas => ",$alt_area_id,2651,", category => 'Litter', cobrand => 'no2fa' });
-my @scheduled_problems = $mech->create_problems_for_body(7, $body->id, 'Title', { areas => ",$area_id,2651,", category => 'Traffic lights', cobrand => 'fixmystreet' });
-my @fixed_problems = $mech->create_problems_for_body(4, $body->id, 'Title', { areas => ",$area_id,2651,", category => 'Potholes', cobrand => 'fixmystreet' });
-my @closed_problems = $mech->create_problems_for_body(3, $body->id, 'Title', { areas => ",$area_id,2651,", category => 'Traffic lights', cobrand => 'fixmystreet' });
+my @scheduled_problems = $mech->create_problems_for_body(7, $body->id, 'Title', { areas => ",$area_id,2651,", category => 'Traffic lights', cobrand => 'no2fa' });
+my @fixed_problems = $mech->create_problems_for_body(4, $body->id, 'Title', { areas => ",$area_id,2651,", category => 'Potholes', cobrand => 'no2fa' });
+my @closed_problems = $mech->create_problems_for_body(3, $body->id, 'Title', { areas => ",$area_id,2651,", category => 'Traffic lights', cobrand => 'no2fa' });
+my $first_problem_id;
+my $first_update_id;
foreach my $problem (@scheduled_problems) {
$problem->update({ state => 'action scheduled' });
- $mech->create_comment_for_problem($problem, $counciluser, 'Title', 'text', 0, 'confirmed', 'action scheduled');
+ my ($update) = $mech->create_comment_for_problem($problem, $counciluser, 'Title', 'text', 0, 'confirmed', 'action scheduled');
+ $first_problem_id = $problem->id unless $first_problem_id;
+ $first_update_id = $update->id unless $first_update_id;
}
foreach my $problem (@fixed_problems) {
@@ -56,24 +68,20 @@ foreach my $problem (@fixed_problems) {
$mech->create_comment_for_problem($problem, $counciluser, 'Title', 'text', 0, 'confirmed', 'fixed');
}
-my $first_problem_id;
-my $first_update_id;
foreach my $problem (@closed_problems) {
$problem->update({ state => 'closed' });
- my ($update) = $mech->create_comment_for_problem($problem, $counciluser, 'Title', 'text', 0, 'confirmed', 'closed', { confirmed => \'current_timestamp' });
- $first_problem_id = $problem->id unless $first_problem_id;
- $first_update_id = $update->id unless $first_update_id;
+ $mech->create_comment_for_problem($problem, $counciluser, 'Title', 'text', 0, 'confirmed', 'closed');
}
my $categories = scraper {
- process "select[name=category] > option", 'cats[]' => 'TEXT',
+ process "select[name=category] option", 'cats[]' => 'TEXT',
process "table[id=overview] > tr", 'rows[]' => scraper {
process 'td', 'cols[]' => 'TEXT'
},
};
FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { fixmystreet => '.' } ],
+ ALLOWED_COBRANDS => 'no2fa',
MAPIT_URL => 'http://mapit.uk/',
}, sub {
@@ -131,8 +139,9 @@ FixMyStreet::override_config {
subtest 'The correct categories and totals shown by default' => sub {
$mech->get_ok("/dashboard");
- my $expected_cats = [ 'All', @cats ];
+ my $expected_cats = [ 'All', 'Litter', 'Other', 'Traffic lights', 'Potholes' ];
my $res = $categories->scrape( $mech->content );
+ $mech->content_contains('<optgroup label="Road">');
is_deeply( $res->{cats}, $expected_cats, 'correct list of categories' );
# Three missing as more than a month ago
test_table($mech->content, 1, 0, 0, 1, 0, 0, 0, 0, 2, 0, 4, 6, 7, 3, 0, 10, 10, 3, 4, 17);
@@ -218,7 +227,7 @@ FixMyStreet::override_config {
is $rows[1]->[0], $first_problem_id, 'Correct report ID';
is $rows[1]->[1], $first_update_id, 'Correct update ID';
is $rows[1]->[3], 'confirmed', 'Correct state';
- is $rows[1]->[4], 'closed', 'Correct problem state';
+ is $rows[1]->[4], 'action scheduled', 'Correct problem state';
is $rows[1]->[5], 'text', 'Correct text';
is $rows[1]->[6], 'Title', 'Correct name';
};
diff --git a/t/app/controller/index.t b/t/app/controller/index.t
index bd268b3d7..56f91ded7 100644
--- a/t/app/controller/index.t
+++ b/t/app/controller/index.t
@@ -58,7 +58,7 @@ subtest "does pc, (x,y), (e,n) or (lat,lon) go to /around" => sub {
}
};
-my $problem_rs = FixMyStreet::App->model('DB::Problem');
+my $problem_rs = FixMyStreet::DB->resultset('Problem');
my $num = $problem_rs->count;
my @edinburgh_problems = $mech->create_problems_for_body(5, 2651, 'Front page');
@@ -91,6 +91,13 @@ subtest "prefilters /around if user has categories" => sub {
$mech->content_contains("Cows,Potholes");
};
+subtest "prefilters /around if filter_category given in URL" => sub {
+ $mech->get_ok('/?filter_category=MyUniqueTestCategory&filter_group=MyUniqueTestGroup');
+ # NB can't use visible_form_values because fields are hidden
+ $mech->content_contains("MyUniqueTestCategory");
+ $mech->content_contains("MyUniqueTestGroup");
+};
+
END {
done_testing();
}
diff --git a/t/app/controller/moderate.t b/t/app/controller/moderate.t
index 7ef24bbe8..8e84bd392 100644
--- a/t/app/controller/moderate.t
+++ b/t/app/controller/moderate.t
@@ -12,9 +12,9 @@ sub moderate_permission_title { 0 }
package main;
+use Path::Tiny;
+use File::Temp 'tempdir';
use FixMyStreet::TestMech;
-use FixMyStreet::App;
-use Data::Dumper;
my $mech = FixMyStreet::TestMech->new;
$mech->host('www.example.org');
@@ -29,7 +29,7 @@ my $user = $mech->create_user_ok('test-moderation@example.com', name => 'Test Us
my $user2 = $mech->create_user_ok('test-moderation2@example.com', name => 'Test User 2');
sub create_report {
- FixMyStreet::App->model('DB::Problem')->create(
+ FixMyStreet::DB->resultset('Problem')->create(
{
postcode => 'BR1 3SB',
bodies_str => $body->id,
@@ -174,23 +174,42 @@ subtest 'Problem moderation' => sub {
};
subtest 'Hide photo' => sub {
- $mech->content_contains('Photo of this report');
+ my $UPLOAD_DIR = tempdir( CLEANUP => 1 );
- $mech->submit_form_ok({ with_fields => {
- %problem_prepopulated,
- problem_photo => 0,
- }});
- $mech->base_like( qr{\Q$REPORT_URL\E} );
+ FixMyStreet::override_config {
+ PHOTO_STORAGE_BACKEND => 'FileSystem',
+ PHOTO_STORAGE_OPTIONS => {
+ UPLOAD_DIR => $UPLOAD_DIR,
+ },
+ }, sub {
+ my $image_path = path('t/app/controller/sample.jpg');
+ $image_path->copy( path($UPLOAD_DIR, '74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg') );
- $mech->content_lacks('Photo of this report');
+ $mech->get_ok('/photo/' . $report->id . '.0.jpeg');
- $mech->submit_form_ok({ with_fields => {
- %problem_prepopulated,
- problem_photo => 1,
- }});
- $mech->base_like( qr{\Q$REPORT_URL\E} );
+ $mech->get_ok($REPORT_URL);
+ $mech->content_contains('Photo of this report');
- $mech->content_contains('Photo of this report');
+ $mech->submit_form_ok({ with_fields => {
+ %problem_prepopulated,
+ problem_photo => 0,
+ }});
+ $mech->base_like( qr{\Q$REPORT_URL\E} );
+
+ my $res = $mech->get('/photo/' . $report->id . '.0.jpeg');
+ is $res->code, 404, 'got 404';
+
+ $mech->get_ok($REPORT_URL);
+ $mech->content_lacks('Photo of this report');
+
+ $mech->submit_form_ok({ with_fields => {
+ %problem_prepopulated,
+ problem_photo => 1,
+ }});
+ $mech->base_like( qr{\Q$REPORT_URL\E} );
+
+ $mech->content_contains('Photo of this report');
+ };
};
subtest 'Hide report' => sub {
@@ -206,7 +225,7 @@ subtest 'Problem moderation' => sub {
is $report->state, 'hidden', 'Is hidden';
my $email = $mech->get_email;
- is $email->header('To'), '"Test User 2" <test-moderation2@example.com>', 'Sent to correct email';
+ is $email->header('To'), '"Test User 2" <' . $user2->email . '>', 'Sent to correct email';
my $url = $mech->get_link_from_email($email);
ok $url, "extracted complain url '$url'";
@@ -477,8 +496,6 @@ subtest 'updates' => sub {
}});
$mech->content_lacks('update good good bad good');
};
-
- $update->moderation_original_data->delete;
};
my $update2 = create_update();
@@ -517,4 +534,14 @@ subtest 'And do it as a superuser' => sub {
subtest 'Check moderation history in admin' => sub {
$mech->get_ok('/admin/report_edit/' . $report->id);
};
+
+subtest 'Check moderation in user log' => sub {
+ $mech->get_ok('/admin/users/' . $user->id . '/log');
+ my $report_id = $report->id;
+ $mech->content_like(qr/Moderated report.*?$report_id/);
+ my $update_id = $update->id;
+ $mech->content_like(qr/Moderated update.*?$update_id/);
+};
+
+
done_testing();
diff --git a/t/app/controller/my.t b/t/app/controller/my.t
index 8b4a25c26..673addf0c 100644
--- a/t/app/controller/my.t
+++ b/t/app/controller/my.t
@@ -23,7 +23,7 @@ $mech->content_lacks('Another Title');
my @update;
my $i = 0;
foreach ($user, $user, $other_user) {
- $update[$i] = FixMyStreet::App->model('DB::Comment')->create({
+ $update[$i] = FixMyStreet::DB->resultset('Comment')->create({
text => 'this is an update',
user => $_,
state => 'confirmed',
diff --git a/t/app/controller/my_planned.t b/t/app/controller/my_planned.t
index a6a47a798..67d59e148 100644
--- a/t/app/controller/my_planned.t
+++ b/t/app/controller/my_planned.t
@@ -1,5 +1,4 @@
use FixMyStreet::TestMech;
-use Test::MockModule;
my $mech = FixMyStreet::TestMech->new;
$mech->get_ok('/my/planned');
@@ -188,13 +187,6 @@ FixMyStreet::override_config {
ALLOWED_COBRANDS => [ 'oxfordshire' ],
BASE_URL => 'http://oxfordshire.fixmystreet.site',
}, sub {
- my $cobrand = Test::MockModule->new('FixMyStreet::Cobrand::Oxfordshire');
- $cobrand->mock('available_permissions', sub {
- my $self = shift;
-
- return FixMyStreet::Cobrand::Default->available_permissions;
- });
-
subtest "can remove problems not displayed in cobrand from shortlist" => sub {
$user->user_planned_reports->remove();
my ($problem1) = $mech->create_problems_for_body(2, $body->id, 'New Problem');
diff --git a/t/app/controller/offline.t b/t/app/controller/offline.t
new file mode 100644
index 000000000..876475264
--- /dev/null
+++ b/t/app/controller/offline.t
@@ -0,0 +1,67 @@
+use FixMyStreet::TestMech;
+use FixMyStreet::DB;
+use Path::Tiny;
+use Memcached;
+
+my $mech = FixMyStreet::TestMech->new;
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'test'
+}, sub {
+ my $theme_dir = path(FixMyStreet->path_to('web/theme/test'));
+ $theme_dir->mkpath;
+ my $image_path = path('t/app/controller/sample.jpg');
+ $image_path->copy($theme_dir->child('sample.jpg'));
+ subtest 'manifest' => sub {
+ Memcached::delete("manifest_theme:test");
+ my $j = $mech->get_ok_json('/.well-known/manifest.webmanifest');
+ is $j->{name}, 'FixMyStreet', 'correct name';
+ is $j->{theme_color}, '#ffd000', 'correct theme colour';
+ is_deeply $j->{icons}[0], {
+ type => 'image/jpeg',
+ src => '/theme/test/sample.jpg',
+ sizes => '133x100'
+ }, 'correct icon';
+ };
+ subtest 'themed manifest' => sub {
+ Memcached::delete("manifest_theme:test");
+ FixMyStreet::DB->resultset('ManifestTheme')->create({
+ cobrand => "test",
+ name => "My Test Cobrand FMS",
+ short_name => "Test FMS",
+ background_colour => "#ff00ff",
+ theme_colour => "#ffffff",
+ });
+
+ my $j = $mech->get_ok_json('/.well-known/manifest.webmanifest');
+ is $j->{name}, 'My Test Cobrand FMS', 'correctly overridden name';
+ is $j->{short_name}, 'Test FMS', 'correctly overridden short_name';
+ is $j->{background_color}, '#ff00ff', 'correctly overridden background colour';
+ is $j->{theme_color}, '#ffffff', 'correctly overridden theme colour';
+ };
+ $theme_dir->remove_tree;
+};
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'fixmystreet'
+}, sub {
+ subtest '.com manifest' => sub {
+ my $j = $mech->get_ok_json('/.well-known/manifest.webmanifest');
+ is $j->{related_applications}[0]{platform}, 'play', 'correct app';
+ is $j->{icons}[0]{sizes}, '192x192', 'correct fallback size';
+ };
+};
+
+subtest 'service worker' => sub {
+ $mech->get_ok('/service-worker.js');
+ $mech->content_contains('translation_strings');
+ $mech->content_contains('offline/fallback');
+};
+
+subtest 'offline fallback page' => sub {
+ $mech->get_ok('/offline/fallback');
+ $mech->content_contains('Offline');
+ $mech->content_contains('offline_list');
+};
+
+done_testing(); \ No newline at end of file
diff --git a/t/app/controller/open311.t b/t/app/controller/open311.t
index 79fe159a3..c052605c7 100644
--- a/t/app/controller/open311.t
+++ b/t/app/controller/open311.t
@@ -14,7 +14,7 @@ $mech->content_contains('<status>open</status>');
$mech->get_ok('/open311/v2/requests.json?jurisdiction_id=foo&status=open&agency_responsible=2237');
my $json = decode_json($mech->content);
-my $problems = $json->{requests}[0]{request};
+my $problems = $json->{service_requests};
is @$problems, 2;
like $problems->[0]{description}, qr/Around page Test/;
@@ -25,7 +25,7 @@ subtest "non_public reports aren't available" => sub {
});
$mech->get_ok('/open311/v2/requests.json?jurisdiction_id=foo');
$json = decode_json($mech->content);
- $problems = $json->{requests}[0]{request};
+ $problems = $json->{service_requests};
is @$problems, 1;
like $problems->[0]{description}, qr/Around page Test/;
$mech->content_lacks('This report is now private');
@@ -33,7 +33,7 @@ subtest "non_public reports aren't available" => sub {
my $problem_id = $problem1->id;
$mech->get_ok("/open311/v2/requests/$problem_id.json?jurisdiction_id=foo");
$json = decode_json($mech->content);
- $problems = $json->{requests}[0]{request};
+ $problems = $json->{service_requests};
is @$problems, 0;
};
@@ -45,7 +45,7 @@ subtest "hidden reports aren't available" => sub {
});
$mech->get_ok('/open311/v2/requests.json?jurisdiction_id=foo');
$json = decode_json($mech->content);
- $problems = $json->{requests}[0]{request};
+ $problems = $json->{service_requests};
is @$problems, 1;
like $problems->[0]{description}, qr/Around page Test/;
$mech->content_lacks('This report is now hidden');
@@ -53,7 +53,7 @@ subtest "hidden reports aren't available" => sub {
my $problem_id = $problem1->id;
$mech->get_ok("/open311/v2/requests/$problem_id.json?jurisdiction_id=foo");
$json = decode_json($mech->content);
- $problems = $json->{requests}[0]{request};
+ $problems = $json->{service_requests};
is @$problems, 0;
};
diff --git a/t/app/controller/open311_updates.t b/t/app/controller/open311_updates.t
new file mode 100644
index 000000000..f2db0a02b
--- /dev/null
+++ b/t/app/controller/open311_updates.t
@@ -0,0 +1,99 @@
+use XML::Simple;
+use FixMyStreet::TestMech;
+my $mech = FixMyStreet::TestMech->new;
+
+my $user = $mech->create_user_ok('commentuser@example.com');
+my $body = $mech->create_body_ok(2237, 'Oxfordshire County Council', {
+ comment_user => $user,
+ api_key => 'sending-key',
+ jurisdiction => 'none',
+ endpoint => 'endpoint',
+});
+my ($problem) = $mech->create_problems_for_body(1, $body->id, 'Open311 updates', { external_id => 'p123' });
+
+subtest 'bad requests do not get through' => sub {
+ $mech->get('/open311/v2/servicerequestupdates.xml');
+ is $mech->response->code, 400, 'Is bad request';
+ $mech->content_contains('<description>Bad request: POST</description>');
+
+ $mech->post('/open311/v2/servicerequestupdates.xml');
+ is $mech->response->code, 400, 'Is bad request';
+ my $xml = _get_xml_object($mech->content);
+ is $xml->{error}[0]{description}, 'Bad request: jurisdiction_id';
+};
+
+subtest 'cobrand gets jurisdiction, but needs a token' => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'oxfordshire',
+ }, sub {
+ $mech->post('/open311/v2/servicerequestupdates.xml');
+ is $mech->response->code, 400, 'Is bad request';
+ my $xml = _get_xml_object($mech->content);
+ is $xml->{error}[0]{description}, 'Bad request: api_key';
+ };
+
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'oxfordshire',
+ COBRAND_FEATURES => { open311_token => { oxfordshire => 'wrong-token' } },
+ }, sub {
+ $mech->post('/open311/v2/servicerequestupdates.xml');
+ is $mech->response->code, 400, 'Is bad request';
+ my $xml = _get_xml_object($mech->content);
+ is $xml->{error}[0]{description}, 'Bad request: api_key';
+ };
+};
+
+subtest 'With all data, an update is added' => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'oxfordshire',
+ COBRAND_FEATURES => { open311_token => { oxfordshire => 'receiving-token' } },
+ }, sub {
+ $mech->post_ok('/open311/v2/servicerequestupdates.xml', {
+ api_key => 'receiving-token',
+ service_request_id => $problem->external_id,
+ update_id => 'c123',
+ updated_datetime => $problem->confirmed->clone->add(hours => 2),
+ status => 'CLOSED',
+ description => 'This report has been fixed',
+ });
+ };
+
+ $problem->discard_changes;
+ is $problem->state, 'fixed - council', 'problem updated';
+ is $problem->comments->count, 1, 'One comment created';
+
+ my $comment = $problem->comments->first;
+ is $comment->text, 'This report has been fixed', 'correct text';
+ is $comment->user_id, $user->id, 'correct user';
+ is $comment->problem_state, 'fixed - council', 'correct state';
+ is $comment->external_id, 'c123', 'correct external id';
+
+ my $xml = _get_xml_object($mech->content);
+ my $response = $xml->{request_update};
+ is $response->[0]->{update_id}, $comment->id, 'correct id in response';
+};
+
+done_testing();
+
+sub _get_xml_object {
+ my ($xml) = @_;
+
+ # Of these, services/service_requests/service_request_updates are root
+ # elements, so GroupTags has no effect, but this is used in ForceArray too.
+ my $group_tags = {
+ services => 'service',
+ attributes => 'attribute',
+ values => 'value',
+ service_requests => 'request',
+ errors => 'error',
+ service_request_updates => 'request_update',
+ };
+ my $simple = XML::Simple->new(
+ ForceArray => [ values %$group_tags ],
+ KeyAttr => {},
+ GroupTags => $group_tags,
+ SuppressEmpty => undef,
+ );
+ my $obj = $simple->parse_string($xml);
+ return $obj;
+}
diff --git a/t/app/controller/photo.t b/t/app/controller/photo.t
index 842daa0dc..8884d432c 100644
--- a/t/app/controller/photo.t
+++ b/t/app/controller/photo.t
@@ -1,5 +1,4 @@
use FixMyStreet::TestMech;
-use FixMyStreet::App;
use Web::Scraper;
use Path::Tiny;
use File::Temp 'tempdir';
@@ -13,7 +12,7 @@ my $mech = FixMyStreet::TestMech->new;
my $sample_file = path(__FILE__)->parent->child("sample.jpg");
ok $sample_file->exists, "sample file $sample_file exists";
-my $westminster = $mech->create_body_ok(2527, 'Liverpool City Council');
+my $body = $mech->create_body_ok(2527, 'Liverpool City Council');
subtest "Check multiple upload worked" => sub {
$mech->get_ok('/around');
@@ -112,4 +111,73 @@ subtest "Check photo uploading URL and endpoints work" => sub {
};
};
+subtest "Check no access to update photos on hidden reports" => sub {
+ my $UPLOAD_DIR = tempdir( CLEANUP => 1 );
+
+ my ($report) = $mech->create_problems_for_body(1, $body->id, 'Title');
+ my $update = $mech->create_comment_for_problem($report, $report->user, $report->name, 'Text', $report->anonymous, 'confirmed', 'confirmed', { photo => $report->photo });
+
+ FixMyStreet::override_config {
+ PHOTO_STORAGE_BACKEND => 'FileSystem',
+ PHOTO_STORAGE_OPTIONS => {
+ UPLOAD_DIR => $UPLOAD_DIR,
+ },
+ }, sub {
+ my $image_path = path('t/app/controller/sample.jpg');
+ $image_path->copy( path($UPLOAD_DIR, '74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg') );
+
+ $mech->get_ok('/photo/c/' . $update->id . '.0.jpeg');
+
+ $report->update({ state => 'hidden' });
+ $report->get_photoset->delete_cached(plus_updates => 1);
+
+ my $res = $mech->get('/photo/c/' . $update->id . '.0.jpeg');
+ is $res->code, 404, 'got 404';
+ };
+};
+
+subtest 'non_public photos only viewable by correct people' => sub {
+ my $UPLOAD_DIR = tempdir( CLEANUP => 1 );
+ path(FixMyStreet->path_to('web/photo'))->remove_tree({ keep_root => 1 });
+
+ my ($report) = $mech->create_problems_for_body(1, $body->id, 'Title', {
+ non_public => 1,
+ });
+
+ FixMyStreet::override_config {
+ PHOTO_STORAGE_BACKEND => 'FileSystem',
+ PHOTO_STORAGE_OPTIONS => {
+ UPLOAD_DIR => $UPLOAD_DIR,
+ },
+ }, sub {
+ my $image_path = path('t/app/controller/sample.jpg');
+ $image_path->copy( path($UPLOAD_DIR, '74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg') );
+
+ $mech->log_out_ok;
+ my $i = '/photo/' . $report->id . '.0.jpeg';
+ my $res = $mech->get($i);
+ is $res->code, 404, 'got 404';
+
+ $mech->log_in_ok('test@example.com');
+ $i = '/photo/' . $report->id . '.0.jpeg';
+ $mech->get_ok($i);
+ my $image_file = FixMyStreet->path_to("web$i");
+ ok !-e $image_file, 'File not cached out';
+
+ my $user = $mech->log_in_ok('someoneelse@example.com');
+ $i = '/photo/' . $report->id . '.0.jpeg';
+ $res = $mech->get($i);
+ is $res->code, 404, 'got 404';
+
+ $user->update({ from_body => $body });
+ $user->user_body_permissions->create({ body => $body, permission_type => 'report_inspect' });
+ $i = '/photo/' . $report->id . '.0.jpeg';
+ $mech->get_ok($i);
+
+ $user->update({ from_body => undef, is_superuser => 1 });
+ $i = '/photo/' . $report->id . '.0.jpeg';
+ $mech->get_ok($i);
+ };
+};
+
done_testing();
diff --git a/t/app/controller/questionnaire.t b/t/app/controller/questionnaire.t
index 05aed7262..b561b271a 100644
--- a/t/app/controller/questionnaire.t
+++ b/t/app/controller/questionnaire.t
@@ -1,7 +1,6 @@
use DateTime;
use FixMyStreet::TestMech;
-use FixMyStreet::App::Controller::Questionnaire;
ok( my $mech = FixMyStreet::TestMech->new, 'Created mech object' );
@@ -12,7 +11,7 @@ my $report_time = $dt->ymd . ' ' . $dt->hms;
my $sent = $dt->add( minutes => 5 );
my $sent_time = $sent->ymd . ' ' . $sent->hms;
-my $report = FixMyStreet::App->model('DB::Problem')->find_or_create(
+my $report = FixMyStreet::DB->resultset('Problem')->find_or_create(
{
postcode => 'EH1 1BB',
bodies_str => '2651',
@@ -47,7 +46,7 @@ foreach my $state (
subtest "questionnaire not sent for $state state" => sub {
$report->update( { send_questionnaire => 1, state => $state } );
$report->questionnaires->delete;
- FixMyStreet::App->model('DB::Questionnaire')->send_questionnaires( {
+ FixMyStreet::DB->resultset('Questionnaire')->send_questionnaires( {
site => 'fixmystreet'
} );
@@ -61,7 +60,7 @@ $report->update( { send_questionnaire => 1, state => 'confirmed' } );
$report->questionnaires->delete;
# Call the questionaire sending function...
-FixMyStreet::App->model('DB::Questionnaire')->send_questionnaires( {
+FixMyStreet::DB->resultset('Questionnaire')->send_questionnaires( {
site => 'fixmystreet'
} );
my $email = $mech->get_email;
@@ -80,12 +79,12 @@ $mech->clear_emails_ok;
$report->discard_changes;
is $report->send_questionnaire, 0;
-$token = FixMyStreet::App->model("DB::Token")->find( {
+$token = FixMyStreet::DB->resultset("Token")->find( {
scope => 'questionnaire', token => $token
} );
ok $token, 'found token for questionnaire';
-my $questionnaire = FixMyStreet::App->model('DB::Questionnaire')->find( {
+my $questionnaire = FixMyStreet::DB->resultset('Questionnaire')->find( {
id => $token->data
} );
ok $questionnaire, 'found questionnaire';
@@ -317,7 +316,7 @@ foreach my $test (
is $questionnaire->new_state, $result;
is $questionnaire->ever_reported, $test->{fields}{reported} eq 'Yes' ? 1 : 0;
if ($test->{fields}{update} || $test->{comment}) {
- my $c = FixMyStreet::App->model("DB::Comment")->find(
+ my $c = FixMyStreet::DB->resultset("Comment")->find(
{ problem_id => $report->id }
);
is $c->text, $test->{fields}{update} || $test->{comment};
@@ -346,7 +345,7 @@ foreach my $test (
};
}
-my $comment = FixMyStreet::App->model('DB::Comment')->find_or_create(
+my $comment = FixMyStreet::DB->resultset('Comment')->find_or_create(
{
problem_id => $report->id,
user_id => $user->id,
@@ -436,7 +435,7 @@ FixMyStreet::override_config {
$report->update;
$questionnaire->delete;
- FixMyStreet::App->model('DB::Questionnaire')->send_questionnaires();
+ FixMyStreet::DB->resultset('Questionnaire')->send_questionnaires();
my $email = $mech->get_email;
my $body = $mech->get_text_body_from_email($email);
@@ -449,7 +448,7 @@ FixMyStreet::override_config {
# Test already answered the ever reported question, so not shown again
$dt = $dt->add( weeks => 4 );
- my $questionnaire2 = FixMyStreet::App->model('DB::Questionnaire')->find_or_create(
+ my $questionnaire2 = FixMyStreet::DB->resultset('Questionnaire')->find_or_create(
{
problem_id => $report->id,
whensent => $dt->ymd . ' ' . $dt->hms,
@@ -462,9 +461,9 @@ FixMyStreet::override_config {
$mech->content_contains( 'Has this problem been fixed?' );
$mech->content_lacks( 'ever reported' );
- $token = FixMyStreet::App->model("DB::Token")->find( { scope => 'questionnaire', token => $token } );
+ $token = FixMyStreet::DB->resultset("Token")->find( { scope => 'questionnaire', token => $token } );
ok $token, 'found token for questionnaire';
- $questionnaire = FixMyStreet::App->model('DB::Questionnaire')->find( { id => $token->data } );
+ $questionnaire = FixMyStreet::DB->resultset('Questionnaire')->find( { id => $token->data } );
ok $questionnaire, 'found questionnaire';
$questionnaire2->delete;
@@ -479,7 +478,7 @@ FixMyStreet::override_config {
$report->cobrand( 'fiksgatami' );
$report->update;
$questionnaire->delete;
- FixMyStreet::App->model('DB::Questionnaire')->send_questionnaires();
+ FixMyStreet::DB->resultset('Questionnaire')->send_questionnaires();
$email = $mech->get_email;
ok $email, "got an email";
$mech->clear_emails_ok;
diff --git a/t/app/controller/report_as_other.t b/t/app/controller/report_as_other.t
index 0c8b7d995..377de27bd 100644
--- a/t/app/controller/report_as_other.t
+++ b/t/app/controller/report_as_other.t
@@ -1,5 +1,4 @@
use FixMyStreet::TestMech;
-use FixMyStreet::App;
use FixMyStreet::Script::Reports;
# disable info logs for this test run
@@ -41,7 +40,6 @@ subtest "Body user, has permission to add report as council" => sub {
is $report->anonymous, 0, 'report not anonymous';
};
-my @users;
subtest "Body user, has permission to add report as another user with email" => sub {
my $report = add_report(
'contribute_as_another_user',
@@ -57,7 +55,6 @@ subtest "Body user, has permission to add report as another user with email" =>
is $report->user->email, 'another@example.net', 'user email correct';
isnt $report->user->id, $user->id, 'user does not match';
like $mech->get_text_body_from_email, qr/Your report to Oxfordshire County Council has been logged/;
- push @users, $report->user;
};
subtest "Body user, has permission to add report as another user with mobile phone number" => sub {
@@ -78,7 +75,6 @@ subtest "Body user, has permission to add report as another user with mobile pho
is $report->user->email_verified, 0, 'user email not verified';
isnt $report->user->id, $user->id, 'user does not match';
$mech->email_count_is(0);
- push @users, $report->user;
};
subtest "Body user, has permission to add report as another user with landline number" => sub {
@@ -99,14 +95,30 @@ subtest "Body user, has permission to add report as another user with landline n
is $report->user->email_verified, 0, 'user email not verified';
isnt $report->user->id, $user->id, 'user does not match';
$mech->email_count_is(0);
- push @users, $report->user;
+};
+
+subtest "Body user, has permission to add report as another user with only name" => sub {
+ my $report = add_report(
+ 'contribute_as_another_user',
+ form_as => 'another_user',
+ title => "Test Report",
+ detail => 'Test report details.',
+ category => 'Potholes',
+ name => 'Another User',
+ username => '',
+ may_show_name => undef,
+ );
+ is $report->name, 'Another User', 'report name is name given';
+ is $report->user->name, 'Body User', 'user name unchanged';
+ is $report->user->id, $user->id, 'user matches';
+ is $report->anonymous, 1, 'report anonymous';
};
subtest "Body user, has permission to add report as another (existing) user with email" => sub {
FixMyStreet::Script::Reports::send();
$mech->clear_emails_ok;
- $mech->create_user_ok('existing@example.net', name => 'Existing User');
+ my $existing = $mech->create_user_ok('existing@example.net', name => 'Existing User');
my $report = add_report(
'contribute_as_another_user',
form_as => 'another_user',
@@ -114,14 +126,13 @@ subtest "Body user, has permission to add report as another (existing) user with
detail => 'Test report details.',
category => 'Potholes',
name => 'Existing Yooser',
- username => 'existing@example.net',
+ username => $existing->email,
);
is $report->name, 'Existing Yooser', 'report name is given name';
is $report->user->name, 'Existing User', 'user name remains same';
- is $report->user->email, 'existing@example.net', 'user email correct';
+ is $report->user->email, $existing->email, 'user email correct';
isnt $report->user->id, $user->id, 'user does not match';
like $mech->get_text_body_from_email, qr/Your report to Oxfordshire County Council has been logged/;
- push @users, $report->user;
my $send_confirmation_mail_override = Sub::Override->new(
"FixMyStreet::Cobrand::Default::report_sent_confirmation_email",
@@ -149,7 +160,6 @@ subtest "Body user, has permission to add report as another (existing) user with
is $report->user->phone, '+447906333333', 'user phone correct';
isnt $report->user->id, $user->id, 'user does not match';
$mech->email_count_is(0);
- push @users, $report->user;
};
subtest "Superuser, can add report as anonymous user" => sub {
@@ -168,6 +178,8 @@ subtest "Superuser, can add report as anonymous user" => sub {
is $report->user->name, 'Super', 'user name unchanged';
is $report->user->id, $user->id, 'user matches';
is $report->anonymous, 1, 'report anonymous';
+ is $report->get_extra_metadata('contributed_as'), 'anonymous_user';
+ is $report->get_extra_metadata('contributed_by'), undef;
my $send_confirmation_mail_override = Sub::Override->new(
"FixMyStreet::Cobrand::Default::report_sent_confirmation_email",
@@ -183,6 +195,28 @@ subtest "Superuser, can add report as anonymous user" => sub {
$mech->log_in_ok($test_email);
};
+subtest "Body user, can add report as anonymous user" => sub {
+ FixMyStreet::Script::Reports::send();
+ $mech->clear_emails_ok;
+
+ my $user = $mech->log_in_ok($user->email);
+ my $report = add_report(
+ 'contribute_as_anonymous_user',
+ form_as => 'anonymous_user',
+ title => "Test Report",
+ detail => 'Test report details.',
+ category => 'Street lighting',
+ );
+ is $report->name, $body->name, 'report name is OK';
+ is $report->user->name, 'Body User', 'user name unchanged';
+ is $report->user->id, $user->id, 'user matches';
+ is $report->anonymous, 1, 'report anonymous';
+ is $report->get_extra_metadata('contributed_as'), 'anonymous_user';
+ is $report->get_extra_metadata('contributed_by'), $user->id;
+
+ $mech->log_in_ok($test_email);
+};
+
subtest "Body user, has permission to add update as council" => sub {
my $update = add_update(
'contribute_as_body',
@@ -208,7 +242,6 @@ subtest "Body user, has permission to add update as another user with email" =>
is $update->user->email, 'another2@example.net', 'user email correct';
isnt $update->user->id, $user->id, 'user does not match';
like $mech->get_text_body_from_email, qr/Your update has been logged/;
- push @users, $update->user;
};
subtest "Body user, has permission to add update as another user with mobile phone" => sub {
@@ -224,7 +257,6 @@ subtest "Body user, has permission to add update as another user with mobile pho
is $update->user->phone, '+447906444444', 'user phone correct';
isnt $update->user->id, $user->id, 'user does not match';
$mech->email_count_is(0);
- push @users, $update->user;
};
subtest "Body user, has permission to add update as another user with landline phone" => sub {
@@ -240,20 +272,20 @@ subtest "Body user, has permission to add update as another user with landline p
is $update->user->phone, '+441685555555', 'user phone correct';
isnt $update->user->id, $user->id, 'user does not match';
$mech->email_count_is(0);
- push @users, $update->user;
};
subtest "Body user, has permission to add update as another (existing) user with email" => sub {
+ my $existing = $mech->create_user_ok('existing@example.net', name => 'Existing User');
my $update = add_update(
'contribute_as_another_user',
form_as => 'another_user',
update => 'Test Update',
name => 'Existing Yooser',
- username => 'existing@example.net',
+ username => $existing->email,
);
is $update->name, 'Existing Yooser', 'update name is given name';
is $update->user->name, 'Existing User', 'user name remains same';
- is $update->user->email, 'existing@example.net', 'user email correct';
+ is $update->user->email, $existing->email, 'user email correct';
isnt $update->user->id, $user->id, 'user does not match';
like $mech->get_text_body_from_email, qr/Your update has been logged/;
};
diff --git a/t/app/controller/report_display.t b/t/app/controller/report_display.t
index bde090dd1..4bd0fc991 100644
--- a/t/app/controller/report_display.t
+++ b/t/app/controller/report_display.t
@@ -73,32 +73,6 @@ subtest "change report to hidden and check for 410 status" => sub {
ok $report->update( { state => 'confirmed' } ), 'confirm report again';
};
-subtest "change report to non_public and check for 403 status" => sub {
- ok $report->update( { non_public => 1 } ), 'make report non public';
- ok $mech->get("/report/$report_id"), "get '/report/$report_id'";
- is $mech->res->code, 403, "access denied";
- is $mech->uri->path, "/report/$report_id", "at /report/$report_id";
- $mech->content_contains('That report cannot be viewed on FixMyStreet.');
- ok $report->update( { non_public => 0 } ), 'make report public';
-};
-
-subtest "check owner of report can view non public reports" => sub {
- ok $report->update( { non_public => 1 } ), 'make report non public';
- $mech->log_in_ok( $report->user->email );
- ok $mech->get("/report/$report_id"), "get '/report/$report_id'";
- is $mech->res->code, 200, "report can be viewed";
- is $mech->uri->path, "/report/$report_id", "at /report/$report_id";
- $mech->log_out_ok;
-
- $mech->log_in_ok( $user2->email );
- ok $mech->get("/report/$report_id"), "get '/report/$report_id'";
- is $mech->res->code, 403, "access denied to user who is not report creator";
- is $mech->uri->path, "/report/$report_id", "at /report/$report_id";
- $mech->content_contains('That report cannot be viewed on FixMyStreet.');
- $mech->log_out_ok;
- ok $report->update( { non_public => 0 } ), 'make report public';
-};
-
subtest "duplicate reports are signposted correctly" => sub {
$report2->set_extra_metadata(duplicate_of => $report->id);
$report2->state('duplicate');
@@ -249,6 +223,39 @@ for my $test (
fixed => 0
},
{
+ cobrand => 'fixmystreet',
+ description => 'old open311 report',
+ date => DateTime->new(
+ year => 2009,
+ month => 6,
+ day => 12,
+ hour => 9,
+ minute => 43,
+ second => 12
+ ),
+ state => 'confirmed',
+ send_method => 'Open311',
+ banner_id => undef,
+ banner_text => undef,
+ fixed => 0
+ },
+ {
+ cobrand => 'westminster',
+ description => 'old westminster report',
+ date => DateTime->new(
+ year => 2009,
+ month => 6,
+ day => 12,
+ hour => 9,
+ minute => 43,
+ second => 12
+ ),
+ state => 'confirmed',
+ banner_id => undef,
+ banner_text => undef,
+ fixed => 0
+ },
+ {
description => 'old fixed report',
date => DateTime->new(
year => 2009,
@@ -364,9 +371,16 @@ for my $test (
$report->confirmed( $test->{date}->ymd . ' ' . $test->{date}->hms );
$report->lastupdate( $test->{date}->ymd . ' ' . $test->{date}->hms );
$report->state( $test->{state} );
+ $report->send_method_used( $test->{send_method} || undef );
$report->update;
- $mech->get_ok("/report/$report_id");
+ my $cobrands = $test->{cobrand} ? [ $test->{cobrand} ] : [];
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => $cobrands,
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $mech->get_ok("/report/$report_id");
+ };
is $mech->uri->path, "/report/$report_id", "at /report/$report_id";
my $banner = $mech->extract_problem_banner;
if ( $banner->{text} ) {
@@ -395,6 +409,20 @@ for my $test (
};
}
+subtest "Correct OpenGraph image is used when report has no photo" => sub {
+ $report->update({ photo => undef });
+ $mech->get_ok("/report/$report_id");
+ $mech->content_contains("/cobrands/fixmystreet/images/fms-og_image.jpg", "site image is used");
+ $mech->content_lacks("/photo/$report_id.0.og", "report image is not present");
+};
+
+subtest "Correct OpenGraph image is used when report has a photo" => sub {
+ $report->update({ photo => '74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg' });
+ $mech->get_ok("/report/$report_id");
+ $mech->content_contains("/photo/$report_id.0.og.jpeg", "report opengraph image is present");
+ $mech->content_lacks("/cobrands/fixmystreet/images/fms-og_image.jpg", "site image is not used");
+};
+
my $body_westminster = $mech->create_body_ok(2504, 'Westminster City Council');
my $body_camden = $mech->create_body_ok(2505, 'Camden Borough Council');
diff --git a/t/app/controller/report_import.t b/t/app/controller/report_import.t
index 223979d1b..b2e15330a 100644
--- a/t/app/controller/report_import.t
+++ b/t/app/controller/report_import.t
@@ -1,5 +1,4 @@
use FixMyStreet::TestMech;
-use FixMyStreet::App;
use Web::Scraper;
use Path::Class;
use LWP::Protocol::PSGI;
@@ -17,7 +16,7 @@ ok -e $sample_file, "sample file $sample_file exists";
FixMyStreet::App->log->disable('info');
END { FixMyStreet::App->log->enable('info'); }
-my $body = $mech->create_body_ok(2245, 'Wiltshire Council');
+my $body = $mech->create_body_ok(2608, 'Borsetshire Council');
$mech->create_contact_ok(
body_id => $body->id,
category => 'Street lighting',
@@ -227,7 +226,7 @@ subtest "Submit a correct entry" => sub {
# check that report has been created
my $user =
- FixMyStreet::App->model('DB::User')
+ FixMyStreet::DB->resultset('User')
->find( { email => 'test@example.com' } );
ok $user, "Found a user";
@@ -315,7 +314,7 @@ subtest "Submit a correct entry (with location)" => sub {
# check that report has been created
my $user =
- FixMyStreet::App->model('DB::User')
+ FixMyStreet::DB->resultset('User')
->find( { email => 'test-ll@example.com' } );
ok $user, "Found a user";
@@ -382,7 +381,7 @@ subtest "Submit a correct entry (with location) to cobrand" => sub {
"check imported fields are shown"
or diag Dumper( $mech->visible_form_values ); use Data::Dumper;
- my $user = FixMyStreet::App->model('DB::User')->find( { email => 'test-ll@example.com' } );
+ my $user = FixMyStreet::DB->resultset('User')->find( { email => 'test-ll@example.com' } );
ok $user, "Found a user";
my $report = $user->problems->first;
diff --git a/t/app/controller/report_inspect.t b/t/app/controller/report_inspect.t
index ef05288c7..8deb2667e 100644
--- a/t/app/controller/report_inspect.t
+++ b/t/app/controller/report_inspect.t
@@ -8,14 +8,6 @@ my $oxon = $mech->create_body_ok(2237, 'Oxfordshire County Council', { can_be_de
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 $dt = FixMyStreet::DB->resultset("DefectType")->create({
- body => $oxon,
- name => 'Small Defect', description => "Teeny",
-});
-FixMyStreet::DB->resultset("ContactDefectType")->create({
- contact => $contact,
- defect_type => $dt,
-});
my $rp = FixMyStreet::DB->resultset("ResponsePriority")->create({
body => $oxon,
name => 'High Priority',
@@ -87,6 +79,87 @@ FixMyStreet::override_config {
$mech->content_lacks('/admin/report_edit/'.$report_id.'">admin</a>)');
};
+ for my $test (
+ {
+ name => "categories only",
+ area_ids => [],
+ categories => [ $contact->id ],
+ destination => "/reports/Oxfordshire",
+ previous => "/my/inspector_redirect",
+ query_form => { filter_category => $contact->category },
+ good_link => "/my/inspector_redirect",
+ bad_link => "/reports",
+ },
+ {
+ name => "categories and areas",
+ area_ids => [60705],
+ categories => [ $contact->id ],
+ destination => "/reports/Oxfordshire/Trowbridge",
+ previous => "/my/inspector_redirect",
+ query_form => { filter_category => $contact->category },
+ good_link => "/my/inspector_redirect",
+ bad_link => "/reports",
+ },
+ {
+ name => "areas only",
+ area_ids => [60705],
+ categories => undef,
+ destination => "/reports/Oxfordshire/Trowbridge",
+ previous => "/my/inspector_redirect",
+ query_form => {},
+ good_link => "/my/inspector_redirect",
+ bad_link => "/reports",
+ },
+ {
+ name => "no categories or areas",
+ area_ids => undef,
+ categories => undef,
+ destination => "/my",
+ query_form => {},
+ good_link => "/reports",
+ bad_link => "/my/inspector_redirect",
+ },
+ {
+ name => "categories but no from_body",
+ area_ids => undef,
+ categories => [ $contact->id ],
+ destination => "/my",
+ query_form => {},
+ good_link => "/reports",
+ bad_link => "/my/inspector_redirect",
+ unset_from_body => 1,
+ },
+ ) {
+ subtest "login destination and top-level nav for inspectors with " . $test->{name} => sub {
+ $mech->log_out_ok;
+
+ $user->area_ids($test->{area_ids});
+ $user->set_extra_metadata('categories', $test->{categories});
+ $user->from_body(undef) if $test->{unset_from_body};
+ $user->update;
+
+ # Can't use log_in_ok, as the call to logged_in_ok clobbers our post-login
+ # redirect.
+ $mech->get_ok('/auth');
+ $mech->submit_form_ok(
+ { with_fields => { username => $user->email, password_sign_in => 'secret' } },
+ "sign in using form" );
+ is $mech->res->code, 200, "got 200";
+ is $mech->uri->path, $test->{destination}, 'redirected to correct destination';
+ is_deeply { $mech->uri->query_form }, $test->{query_form}, 'destination query params set correctly';
+ if ($test->{previous}) {
+ is $mech->res->previous->code, 302, "got 302 for post-login redirect";
+ is $mech->res->previous->base->path, $test->{previous}, "previous URI correct";
+ }
+
+ $mech->get_ok("/");
+ ok $mech->find_link( text => 'All reports', url => $test->{good_link} );
+ ok !$mech->find_link( text => 'All reports', url => $test->{bad_link} );
+
+ $user->update( { from_body => $oxon } ) if $test->{unset_from_body};
+ };
+ }
+
subtest "council staff can't see admin report edit link on FMS.com" => sub {
my $report_edit_permission = $user->user_body_permissions->create({
body => $oxon, permission_type => 'report_edit' });
@@ -109,7 +182,7 @@ FixMyStreet::override_config {
$mech->get_ok("/report/$report_id");
$mech->submit_form_ok({ button => 'save', with_fields => { non_public => 1 } });
$report->discard_changes;
- my $alert = FixMyStreet::App->model('DB::Alert')->find(
+ my $alert = FixMyStreet::DB->resultset('Alert')->find(
{ user => $user, alert_type => 'new_updates', confirmed => 1, }
);
@@ -126,7 +199,7 @@ FixMyStreet::override_config {
$mech->get_ok("/report/$report_id");
$mech->submit_form_ok({ button => 'save', with_fields => { traffic_information => 'Yes', state => 'Action scheduled', include_update => undef } });
$report->discard_changes;
- my $alert = FixMyStreet::App->model('DB::Alert')->find(
+ my $alert = FixMyStreet::DB->resultset('Alert')->find(
{ user => $user, alert_type => 'new_updates', confirmed => 1, }
);
@@ -140,11 +213,10 @@ FixMyStreet::override_config {
$user->user_body_permissions->create({ body => $oxon, permission_type => 'planned_reports' });
$report->state('confirmed');
$report->update;
- my $reputation = $report->user->get_extra_metadata("reputation");
$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', raise_defect => 1,
+ state => 'action scheduled',
} });
$mech->get_ok("/report/$report_id");
$mech->submit_form_ok({ with_fields => {
@@ -153,28 +225,22 @@ FixMyStreet::override_config {
$report->discard_changes;
my $comment = ($report->comments( undef, { order_by => { -desc => 'id' } } )->all)[1]->text;
is $comment, "This is a public update.", 'Update was created';
- is $report->get_extra_metadata('inspected'), 1, 'report marked as inspected';
- is $report->user->get_extra_metadata('reputation'), $reputation, "User reputation wasn't changed";
$mech->get_ok("/report/$report_id");
my $meta = $mech->extract_update_metas;
like $meta->[0], qr/State changed to: Action scheduled/, 'First update mentions action scheduled';
- like $meta->[2], qr/Posted by .*defect raised/, 'Update mentions defect raised';
$user->unset_extra_metadata('categories');
$user->update;
};
subtest "test update is required when instructing" => sub {
- $report->unset_extra_metadata('inspected');
$report->update;
- $report->inspection_log_entry->delete;
$report->comments->delete_all;
$mech->get_ok("/report/$report_id");
$mech->submit_form_ok({ button => 'save', with_fields => { public_update => undef, include_update => "1" } });
is_deeply $mech->page_errors, [ "Please provide a public update for this report." ], 'errors match';
$report->discard_changes;
is $report->comments->count, 0, "Update wasn't created";
- is $report->get_extra_metadata('inspected'), undef, 'report not marked as inspected';
};
subtest "test location changes" => sub {
@@ -305,7 +371,7 @@ FixMyStreet::override_config {
$mech->get_ok("/report/$report_id");
$mech->submit_form_ok({ button => 'save', with_fields => { state => 'Investigating', public_update => "We're investigating.", include_update => "1" } });
- my $alert_count = FixMyStreet::App->model('DB::Alert')->search(
+ my $alert_count = FixMyStreet::DB->resultset('Alert')->search(
{ user_id => $user->id, alert_type => 'new_updates', confirmed => 1, parameter => $report_id }
)->count();
@@ -448,24 +514,6 @@ FixMyStreet::override_config {
is $report->response_priority->id, $rp->id, 'response priority set';
};
- subtest "check can set defect type for category when changing from category with no defect types" => sub {
- $report->update({ category => 'Sheep', defect_type_id => undef });
- $user->user_body_permissions->delete;
- $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 => {
- include_update => 0,
- defect_type => $dt->id,
- category => 'Cows',
- }
- });
- $report->discard_changes;
- is $report->defect_type->id, $dt->id, 'defect type set';
- $report->update({ defect_type_id => undef });
- };
-
subtest "check can't set priority that isn't for a category" => sub {
$report->discard_changes;
$report->update({ category => 'Cows', response_priority_id => $rp->id });
@@ -614,47 +662,6 @@ FixMyStreet::override_config {
return $perms;
});
- subtest "test negative reputation" => sub {
- my $reputation = $report->user->get_extra_metadata("reputation") || 0;
-
- $mech->get_ok("/report/$report_id");
- $mech->submit_form( button => 'remove_from_site' );
-
- $report->discard_changes;
- is $report->user->get_extra_metadata('reputation'), $reputation-1, "User reputation was decreased";
- $report->update({ state => 'confirmed' });
- };
-
- subtest "test positive reputation" => sub {
- $user->user_body_permissions->create({ body => $oxon, permission_type => 'report_instruct' });
- $report->unset_extra_metadata('inspected');
- $report->update;
- $report->inspection_log_entry->delete if $report->inspection_log_entry;
- my $reputation = $report->user->get_extra_metadata("reputation") || 0;
- $mech->get_ok("/report/$report_id");
- $mech->submit_form_ok({ button => 'save', with_fields => {
- state => 'in progress', include_update => undef,
- } });
- $report->discard_changes;
- is $report->get_extra_metadata('inspected'), undef, 'report not marked as inspected';
-
- $mech->submit_form_ok({ button => 'save', with_fields => {
- state => 'action scheduled', include_update => undef,
- } });
- $report->discard_changes;
- is $report->get_extra_metadata('inspected'), undef, 'report not marked as inspected';
- is $report->user->get_extra_metadata('reputation'), $reputation+1, "User reputation was increased";
-
- $mech->submit_form_ok({ button => 'save', with_fields => {
- state => 'action scheduled', include_update => undef,
- raise_defect => 1,
- } });
- $report->discard_changes;
- is $report->get_extra_metadata('inspected'), 1, 'report marked as inspected';
- $mech->get_ok("/report/$report_id");
- my $meta = $mech->extract_update_metas;
- like $meta->[-1], qr/Updated by .*defect raised/, 'Update mentions defect raised';
- };
subtest "Oxfordshire-specific traffic management options are shown" => sub {
$report->update({ state => 'confirmed' });
@@ -697,7 +704,6 @@ FixMyStreet::override_config {
priority => $rp->id,
include_update => '1',
detailed_information => 'XXX164XXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
- defect_type => '',
traffic_information => ''
};
my $values = $mech->visible_form_values('report_inspect_form');
diff --git a/t/app/controller/report_interest_count.t b/t/app/controller/report_interest_count.t
index 330d844d0..a9911c4ba 100644
--- a/t/app/controller/report_interest_count.t
+++ b/t/app/controller/report_interest_count.t
@@ -26,7 +26,7 @@ my $dt = DateTime->new(
second => 23
);
-my $report = FixMyStreet::App->model('DB::Problem')->find_or_create(
+my $report = FixMyStreet::DB->resultset('Problem')->find_or_create(
{
postcode => 'SW1A 1AA',
bodies_str => '2504',
diff --git a/t/app/controller/report_new.t b/t/app/controller/report_new.t
index af18c39b9..d2da75f2c 100644
--- a/t/app/controller/report_new.t
+++ b/t/app/controller/report_new.t
@@ -1,60 +1,32 @@
+package FixMyStreet::Cobrand::HounslowNoName;
+use base 'FixMyStreet::Cobrand::UK';
+
+sub council_area_id { 2483 };
+
+package main;
+
use Test::MockModule;
use FixMyStreet::TestMech;
-use FixMyStreet::App;
-use Web::Scraper;
-use Path::Class;
# disable info logs for this test run
FixMyStreet::App->log->disable('info');
END { FixMyStreet::App->log->enable('info'); }
my $mech = FixMyStreet::TestMech->new;
-$mech->get_ok('/report/new');
-
-my $sample_file = file(__FILE__)->parent->file("sample.jpg")->stringify;
-ok -e $sample_file, "sample file $sample_file exists";
-
-subtest "test that bare requests to /report/new get redirected" => sub {
-
- $mech->get_ok('/report/new');
- is $mech->uri->path, '/', "went to /";
- is_deeply { $mech->uri->query_form }, {}, "query empty";
-
- FixMyStreet::override_config {
- MAPIT_URL => 'http://mapit.uk/',
- }, sub {
- $mech->get_ok('/report/new?pc=SW1A%201AA');
- is $mech->uri->path, '/around', "went to /around";
- is_deeply { $mech->uri->query_form }, { pc => 'SW1A 1AA' },
- "pc correctly transferred";
-
- $mech->get_ok('/report/new?pc_override=SW1A%201AA&latitude=51&longitude=-2');
- is $mech->uri->path, '/around', "went to /around";
- is_deeply { $mech->uri->query_form }, { pc => 'SW1A 1AA' },
- "pc correctly transferred, lat/lon gone";
- };
-};
my %body_ids;
-my @bodies;
for my $body (
{ area_id => 2651, name => 'City of Edinburgh Council' },
{ area_id => 2226, name => 'Gloucestershire County Council' },
{ area_id => 2326, name => 'Cheltenham Borough Council' },
- { area_id => 2504, name => 'Westminster City Council' },
{ area_id => 2482, name => 'Bromley Council' },
{ area_id => 2227, name => 'Hampshire County Council' },
{ area_id => 2333, name => 'Hart Council' },
{ area_id => 2535, name => 'Sandwell Borough Council' },
{ area_id => 1000, name => 'Highways England' },
- { area_id => 2217, name => 'Buckinghamshire County Council' },
- { area_id => 2232, name => 'Lincolnshire County Council' },
- { area_id => 2237, name => 'Oxfordshire County Council' },
- { area_id => 2600, name => 'Rutland County Council' },
- { area_id => 2234, name => 'Northamptonshire County Council' },
+ { area_id => 2483, name => 'Hounslow Borough Council' },
) {
my $body_obj = $mech->create_body_ok($body->{area_id}, $body->{name});
- push @bodies, $body_obj;
$body_ids{$body->{area_id}} = $body_obj->id;
}
@@ -74,31 +46,26 @@ my $contact3 = $mech->create_contact_ok(
category => 'Trees',
email => 'trees@example.com',
);
-my $contact4 = $mech->create_contact_ok(
+$mech->create_contact_ok(
body_id => $body_ids{2482}, # Bromley
category => 'Trees',
email => 'trees@example.com',
);
-my $contact5 = $mech->create_contact_ok(
+$mech->create_contact_ok(
body_id => $body_ids{2651}, # Edinburgh
category => 'Trees',
email => 'trees@example.com',
);
-my $contact6 = $mech->create_contact_ok(
+$mech->create_contact_ok(
body_id => $body_ids{2333}, # Hart
category => 'Trees',
email => 'trees@example.com',
);
-my $contact7 = $mech->create_contact_ok(
+$mech->create_contact_ok(
body_id => $body_ids{2227}, # Hampshire
category => 'Street lighting',
email => 'highways@example.com',
);
-my $contact8 = $mech->create_contact_ok(
- body_id => $body_ids{2504},
- category => 'Street lighting',
- email => 'highways@example.com'
-);
my $contact9 = $mech->create_contact_ok(
body_id => $body_ids{2226}, # Gloucestershire
category => 'Street lighting',
@@ -109,573 +76,23 @@ my $contact10 = $mech->create_contact_ok(
category => 'Street lighting',
email => 'streetlights-2326@example.com',
);
-my $contact11 = $mech->create_contact_ok(
+$mech->create_contact_ok(
body_id => $body_ids{1000}, # Highways
category => 'Pothole',
email => 'pothole-1000@example.com',
);
-my $contact12 = $mech->create_contact_ok(
- body_id => $body_ids{2217}, # Buckinghamshire
- category => 'Street lighting',
- email => 'streetlights-2217@example.com',
-);
-my $contact13 = $mech->create_contact_ok(
- body_id => $body_ids{2232}, # Lincolnshire
+$mech->create_contact_ok(
+ body_id => $body_ids{2483}, # Hounslow
category => 'Trees',
- email => 'trees-2232@example.com',
+ email => 'trees-2483@example.com',
);
-my $contact14 = $mech->create_contact_ok(
- body_id => $body_ids{2237}, # Oxfordshire
- category => 'Trees',
- email => 'trees-2247@example.com',
-);
-my $contact15 = $mech->create_contact_ok(
- body_id => $body_ids{2600}, # Rutland
- category => 'Trees',
- email => 'trees-2600@example.com',
-);
-my $contact16 = $mech->create_contact_ok(
- body_id => $body_ids{2234}, # Northamptonshire
- category => 'Trees',
- email => 'trees-2234@example.com',
+$mech->create_contact_ok(
+ body_id => $body_ids{2483}, # Hounslow
+ category => 'General Enquiry',
+ email => 'general-enquiry-2483@example.com',
+ non_public => 1,
);
-# test that the various bit of form get filled in and errors correctly
-# generated.
-foreach my $test (
- {
- msg => 'all fields empty',
- pc => 'OX1 3DH',
- fields => {
- title => '',
- detail => '',
- photo1 => '',
- photo2 => '',
- photo3 => '',
- name => '',
- may_show_name => '1',
- username => '',
- phone => '',
- password_sign_in => '',
- password_register => '',
- },
- changes => {},
- errors => [
- 'Please enter a subject',
- 'Please enter some details',
- # No category error, as no categories for Oxon at all, so is skipped
- 'Please enter your email',
- 'Please enter your name',
- ],
- },
- {
- msg => 'all fields empty, bad category',
- pc => 'GL50 2PR',
- fields => {
- title => '',
- detail => '',
- photo1 => '',
- photo2 => '',
- photo3 => '',
- name => '',
- may_show_name => '1',
- username => '',
- phone => '',
- category => 'Something bad',
- password_sign_in => '',
- password_register => '',
- },
- changes => {
- category => '-- Pick a category --',
- },
- errors => [
- 'Please enter a subject',
- 'Please enter some details',
- 'Please choose a category',
- 'Please enter your email',
- 'Please enter your name',
- ],
- },
- {
- msg => 'all fields empty except category',
- pc => 'SW1A 1AA',
- fields => {
- title => '',
- detail => '',
- photo1 => '',
- photo2 => '',
- photo3 => '',
- name => '',
- may_show_name => '1',
- username => '',
- phone => '',
- category => 'Street lighting',
- password_sign_in => '',
- password_register => '',
- },
- changes => {},
- errors => [
- 'Please enter a subject',
- 'Please enter some details',
- 'Please enter your email',
- 'Please enter your name',
- ],
- },
- {
- msg => 'may_show_name is remembered',
- pc => 'SW1A 1AA',
- fields => {
- title => '',
- detail => '',
- photo1 => '',
- photo2 => '',
- photo3 => '',
- name => '',
- may_show_name => undef,
- username => '',
- phone => '',
- category => 'Street lighting',
- password_sign_in => '',
- password_register => '',
- },
- changes => {},
- errors => [
- 'Please enter a subject',
- 'Please enter some details',
- 'Please enter your email',
- 'Please enter your name',
- ],
- },
- {
- msg => 'may_show_name unchanged if name is present (stays false)',
- pc => 'SW1A 1AA',
- fields => {
- title => '',
- detail => '',
- photo1 => '',
- photo2 => '',
- photo3 => '',
- name => 'Bob Jones',
- may_show_name => undef,
- username => '',
- phone => '',
- category => 'Street lighting',
- password_sign_in => '',
- password_register => '',
- },
- changes => {},
- errors => [
- 'Please enter a subject',
- 'Please enter some details',
- 'Please enter your email',
- ],
- },
- {
- msg => 'may_show_name unchanged if name is present (stays true)',
- pc => 'SW1A 1AA',
- fields => {
- title => '',
- detail => '',
- photo1 => '',
- photo2 => '',
- photo3 => '',
- name => 'Bob Jones',
- may_show_name => '1',
- username => '',
- phone => '',
- category => 'Street lighting',
- password_sign_in => '',
- password_register => '',
- },
- changes => {},
- errors => [
- 'Please enter a subject',
- 'Please enter some details',
- 'Please enter your email',
- ],
- },
- {
- msg => 'title and details tidied up',
- pc => 'SW1A 1AA',
- fields => {
- title => "DOG SHIT\r\nON WALLS",
- detail => "on this portakabin -\r\n\r\nmore of a portaloo HEH!!",
- photo1 => '',
- photo2 => '',
- photo3 => '',
- name => 'Bob Jones',
- may_show_name => '1',
- username => '',
- phone => '',
- category => 'Street lighting',
- password_sign_in => '',
- password_register => '',
- },
- changes => {
- title => 'Dog poo on walls',
- detail =>
- "On this [portable cabin] -\n\nMore of a [portable loo] HEH!!",
- },
- errors => [ 'Please enter your email', ],
- },
- {
- msg => 'name too short',
- pc => 'SW1A 1AA',
- fields => {
- title => 'Test title',
- detail => 'Test detail',
- photo1 => '',
- photo2 => '',
- photo3 => '',
- name => 'DUDE',
- may_show_name => '1',
- username => '',
- phone => '',
- category => 'Street lighting',
- password_sign_in => '',
- password_register => '',
- },
- changes => {},
- errors => [
- 'Please enter your email',
-'Please enter your full name, councils need this information – if you do not wish your name to be shown on the site, untick the box below',
- ],
- },
- {
- msg => 'name is anonymous',
- pc => 'SW1A 1AA',
- fields => {
- title => 'Test title',
- detail => 'Test detail',
- photo1 => '',
- photo2 => '',
- photo3 => '',
- name => 'anonymous',
- may_show_name => '1',
- username => '',
- phone => '',
- category => 'Street lighting',
- password_sign_in => '',
- password_register => '',
- },
- changes => {},
- errors => [
- 'Please enter your email',
-'Please enter your full name, councils need this information – if you do not wish your name to be shown on the site, untick the box below',
- ],
- },
- {
- msg => 'email invalid',
- pc => 'SW1A 1AA',
- fields => {
- title => 'Test title',
- detail => 'Test detail',
- photo1 => '',
- photo2 => '',
- photo3 => '',
- name => 'Joe Smith',
- may_show_name => '1',
- username => 'not an email',
- phone => '',
- category => 'Street lighting',
- password_sign_in => '',
- password_register => '',
- },
- changes => { username => 'notanemail' },
- errors => [ 'Please enter a valid email', ],
- },
- {
- msg => 'cleanup title and detail',
- pc => 'SW1A 1AA',
- fields => {
- title => " Test title ",
- detail => " first line \n\n second\nline\n\n ",
- photo1 => '',
- photo2 => '',
- photo3 => '',
- name => '',
- may_show_name => '1',
- username => '',
- phone => '',
- category => 'Street lighting',
- password_sign_in => '',
- password_register => '',
- },
- changes => {
- title => 'Test title',
- detail => "First line\n\nSecond line",
- },
- errors => [
- 'Please enter your email',
- 'Please enter your name',
- ],
- },
- {
- msg => 'clean up name and email',
- pc => 'SW1A 1AA',
- fields => {
- title => '',
- detail => '',
- photo1 => '',
- photo2 => '',
- photo3 => '',
- name => ' Bob Jones ',
- may_show_name => '1',
- username => ' BOB @ExAmplE.COM ',
- phone => '',
- category => 'Street lighting',
- password_sign_in => '',
- password_register => '',
- },
- changes => {
- name => 'Bob Jones',
- username => 'bob@example.com',
- },
- errors => [ 'Please enter a subject', 'Please enter some details', ],
- },
- {
- msg => 'non-photo upload gives error',
- pc => 'SW1A 1AA',
- fields => {
- title => 'Title',
- detail => 'Detail',
- photo1 => [ [ undef, 'bad.txt', Content => 'This is not a JPEG', Content_Type => 'text/plain' ], 1 ],
- photo2 => '',
- photo3 => '',
- name => 'Bob Jones',
- may_show_name => '1',
- username => 'bob@example.com',
- phone => '',
- category => 'Street lighting',
- password_sign_in => '',
- password_register => '',
- },
- changes => {
- photo1 => '',
- },
- errors => [ "Please upload an image only" ],
- },
- {
- msg => 'bad photo upload gives error',
- pc => 'SW1A 1AA',
- fields => {
- title => 'Title',
- detail => 'Detail',
- photo1 => [ [ undef, 'fake.jpeg', Content => 'This is not a JPEG', Content_Type => 'image/jpeg' ], 1 ],
- photo2 => '',
- photo3 => '',
- name => 'Bob Jones',
- may_show_name => '1',
- username => 'bob@example.com',
- phone => '',
- category => 'Street lighting',
- password_sign_in => '',
- password_register => '',
- },
- changes => {
- photo1 => '',
- },
- errors => [ "That image doesn't appear to have uploaded correctly (Please upload an image only ), please try again." ],
- },
- {
- msg => 'photo with octet-stream gets through okay',
- pc => 'SW1A 1AA',
- fields => {
- title => '',
- detail => 'Detail',
- photo1 => [ [ $sample_file, undef, Content_Type => 'application/octet-stream' ], 1 ],
- photo2 => '',
- photo3 => '',
- name => 'Bob Jones',
- may_show_name => '1',
- username => 'bob@example.com',
- phone => '',
- category => 'Street lighting',
- password_sign_in => '',
- password_register => '',
- },
- changes => {
- photo1 => '',
- },
- errors => [ "Please enter a subject" ],
- },
- {
- msg => 'Bromley long detail',
- pc => 'BR1 3UH',
- fields => {
- fms_extra_title => 'MR',
- title => '',
- detail => 'X' . 'x' x 1751,
- photo1 => '',
- photo2 => '',
- photo3 => '',
- name => 'Bob Example',
- may_show_name => '1',
- username => 'bob@example.com',
- phone => '',
- category => 'Trees',
- password_sign_in => '',
- password_register => '',
- },
- changes => { },
- errors => [ 'Please enter a subject', 'Reports are limited to 1750 characters in length. Please shorten your report' ],
- },
- {
- msg => 'Oxfordshire long detail',
- pc => 'OX20 1SZ',
- fields => {
- title => '',
- detail => 'X' . 'x' x 1701,
- photo1 => '',
- photo2 => '',
- photo3 => '',
- name => 'Bob Example',
- may_show_name => '1',
- username => 'bob@example.com',
- phone => '',
- category => 'Trees',
- password_sign_in => '',
- password_register => '',
- },
- changes => { },
- errors => [ 'Please enter a subject', 'Reports are limited to 1700 characters in length. Please shorten your report' ],
- },
- {
- msg => 'Lincolnshire long phone',
- pc => 'PE9 2GX',
- fields => {
- title => '',
- detail => 'Detail',
- photo1 => '',
- photo2 => '',
- photo3 => '',
- name => 'Bob Example',
- may_show_name => '1',
- username => 'bob@example.com',
- phone => '123456789 12345678910',
- category => 'Trees',
- password_sign_in => '',
- password_register => '',
- },
- changes => { },
- errors => [ 'Please enter a subject', 'Phone numbers are limited to 20 characters in length.' ],
- },
- {
- msg => 'Buckinghamshire long name',
- pc => 'RG9 6TL',
- fields => {
- title => '',
- detail => '',
- photo1 => '',
- photo2 => '',
- photo3 => '',
- name => 'This is a very long name that should fail validation',
- may_show_name => '1',
- username => 'bob@example.com',
- phone => '',
- category => 'Street lighting',
- password_sign_in => '',
- password_register => '',
- },
- changes => { },
- errors => [ 'Please enter a subject', 'Please enter some details', 'Names are limited to 50 characters in length.' ],
- },
- {
- msg => 'Rutland long name',
- pc => 'LE15 0GJ',
- fields => {
- title => '',
- detail => '',
- photo1 => '',
- photo2 => '',
- photo3 => '',
- name => 'This is a very long name that should fail validation',
- may_show_name => '1',
- username => 'bob@example.com',
- phone => '',
- category => 'Trees',
- password_sign_in => '',
- password_register => '',
- },
- changes => { },
- errors => [ 'Please enter a subject', 'Please enter some details', 'Names are limited to 40 characters in length.' ],
- },
- {
- msg => 'Oxfordshire validation',
- pc => 'OX20 1SZ',
- fields => {
- title => '',
- detail => '',
- photo1 => '',
- photo2 => '',
- 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',
- phone => '01234 5678910 09876 54321 ext 203',
- category => 'Trees',
- password_sign_in => '',
- password_register => '',
- },
- changes => { },
- errors => [ 'Please enter a subject', 'Please enter some details', 'Emails are limited to 50 characters in length.', 'Phone numbers are limited to 20 characters in length.', 'Names are limited to 50 characters in length.'],
- },
- {
- msg => 'Northamptonshire validation',
- pc => 'NN1 1NS',
- fields => {
- title => 'This is a very long title that should fail the validation as it is really much too long to pass the validation of 120 characters',
- detail => '',
- photo1 => '',
- photo2 => '',
- photo3 => '',
- name => 'A User',
- may_show_name => '1',
- username => 'user@example.org',
- phone => '',
- category => 'Trees',
- password_sign_in => '',
- password_register => '',
- },
- changes => { },
- errors => [ 'Summaries are limited to 120 characters in length. Please shorten your summary', 'Please enter some details'],
- },
- )
-{
- subtest "check form errors where $test->{msg}" => sub {
- $mech->get_ok('/around');
-
- # submit initial pc form
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { fixmystreet => '.' }, 'bromley', 'oxfordshire', 'rutland', 'lincolnshire', 'buckinghamshire', 'northamptonshire' ],
- MAPIT_URL => 'http://mapit.uk/',
- }, sub {
- $mech->submit_form_ok( { with_fields => { pc => $test->{pc} } },
- "submit location" );
- is_deeply $mech->page_errors, [], "no errors for pc '$test->{pc}'";
-
- # click through to the report page
- $mech->follow_link_ok( { text_regex => qr/skip this step/i, },
- "follow 'skip this step' link" );
-
- # submit the main form
- $mech->submit_form_ok( { with_fields => $test->{fields} },
- "submit form" );
- };
-
- # check that we got the errors expected
- is_deeply [ sort @{$mech->page_errors} ], [ sort @{$test->{errors}} ], "check errors";
-
- # check that fields have changed as expected
- my $new_values = {
- %{ $test->{fields} }, # values added to form
- %{ $test->{changes} }, # changes we expect
- };
- is_deeply $mech->visible_form_values, $new_values,
- "values correctly changed";
- };
-}
-
my $first_user;
foreach my $test (
{
@@ -702,14 +119,14 @@ foreach my $test (
# check that the user does not exist
my $test_email = 'test-1@example.com';
if ($test->{user}) {
- my $user = FixMyStreet::App->model('DB::User')->find( { email => $test_email } );
+ my $user = FixMyStreet::DB->resultset('User')->find( { email => $test_email } );
ok $user, "test user does exist";
$user->problems->delete;
$user->name( 'Old Name' );
$user->password( 'old_password' );
$user->update;
} elsif (!$first_user) {
- ok !FixMyStreet::App->model('DB::User')->find( { email => $test_email } ),
+ ok !FixMyStreet::DB->resultset('User')->find( { email => $test_email } ),
"test user does not exist";
$first_user = 1;
} else {
@@ -754,7 +171,7 @@ foreach my $test (
# check that the user has been created/ not changed
my $user =
- FixMyStreet::App->model('DB::User')->find( { email => $test_email } );
+ FixMyStreet::DB->resultset('User')->find( { email => $test_email } );
ok $user, "user found";
if ($test->{user}) {
is $user->name, 'Old Name', 'name unchanged';
@@ -799,7 +216,7 @@ foreach my $test (
}
# check that the reporter has an alert
- my $alert = FixMyStreet::App->model('DB::Alert')->find( {
+ my $alert = FixMyStreet::DB->resultset('Alert')->find( {
user => $report->user,
alert_type => 'new_updates',
parameter => $report->id,
@@ -815,65 +232,10 @@ foreach my $test (
};
}
-# this test to make sure that we don't see spurious error messages about
-# the name being blank when there is a sign in error
-subtest "test password errors for a user who is signing in as they report" => sub {
- $mech->log_out_ok;
- $mech->clear_emails_ok;
-
- # check that the user does not exist
- my $test_email = 'test-2@example.com';
-
- my $user = $mech->create_user_ok($test_email);
-
- # setup the user.
- ok $user->update( {
- name => 'Joe Bloggs',
- phone => '01234 567 890',
- password => 'secret2',
- phone_verified => 1,
- } ), "set user details";
-
- # submit initial pc form
- $mech->get_ok('/around');
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { fixmystreet => '.' } ],
- MAPIT_URL => 'http://mapit.uk/',
- }, sub {
- $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB', } },
- "submit location" );
-
- # 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_sign_in',
- with_fields => {
- title => 'Test Report',
- detail => 'Test report details.',
- photo1 => '',
- username => 'test-2@example.com',
- password_sign_in => 'secret1',
- category => 'Street lighting',
- }
- },
- "submit with wrong password"
- );
- };
-
- # check that we got the errors expected
- is_deeply $mech->page_errors, [
- "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->content_lacks('1234', 'phone number not shown');
-};
-
foreach my $test (
- { two_factor => 0, desc => '', },
- { two_factor => 1, desc => ' with two-factor', },
+ { two_factor => '', desc => '', },
+ { two_factor => 'yes', desc => ' with two-factor', },
+ { two_factor => 'new', desc => ' with mandated two-factor, not yet set up', },
) {
subtest "test report creation for a user who is signing in as they report$test->{desc}" => sub {
$mech->log_out_ok;
@@ -890,21 +252,25 @@ foreach my $test (
name => 'Joe Bloggs',
phone => '01234 567 890',
password => 'secret2',
+ $test->{two_factor} ? (is_superuser => 1) : (),
} ), "set user details";
my $auth;
- if ($test->{two_factor}) {
+ my $mock;
+ if ($test->{two_factor} eq 'yes') {
use Auth::GoogleAuth;
$auth = Auth::GoogleAuth->new;
- $user->is_superuser(1);
$user->set_extra_metadata('2fa_secret', $auth->generate_secret32);
$user->update;
+ } elsif ($test->{two_factor} eq 'new') {
+ $mock = Test::MockModule->new('FixMyStreet::Cobrand::FixMyStreet');
+ $mock->mock(must_have_2fa => sub { 1 });
}
# submit initial pc form
$mech->get_ok('/around');
FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { fixmystreet => '.' } ],
+ ALLOWED_COBRANDS => 'fixmystreet',
MAPIT_URL => 'http://mapit.uk/',
}, sub {
$mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB', } },
@@ -921,7 +287,7 @@ foreach my $test (
title => 'Test Report',
detail => 'Test report details.',
photo1 => '',
- username => $test_email,
+ username => $user->email,
password_sign_in => 'secret2',
category => 'Street lighting',
}
@@ -929,13 +295,22 @@ foreach my $test (
"submit good details"
);
- if ($test->{two_factor}) {
+ if ($test->{two_factor} eq 'yes') {
my $code = $auth->code;
my $wrong_code = $auth->code(undef, time() - 120);
$mech->content_contains('Please generate a two-factor code');
$mech->submit_form_ok({ with_fields => { '2fa_code' => $wrong_code } }, "provide wrong 2FA code" );
$mech->content_contains('Try again');
$mech->submit_form_ok({ with_fields => { '2fa_code' => $code } }, "provide correct 2FA code" );
+ } elsif ($test->{two_factor} eq 'new') {
+ $mech->content_contains('requires two-factor');
+ $mech->submit_form_ok({ with_fields => { '2fa_action' => 'activate' } }, "submit 2FA activation");
+ my ($token) = $mech->content =~ /name="secret32" value="([^"]*)">/;
+
+ use Auth::GoogleAuth;
+ my $auth = Auth::GoogleAuth->new({ secret32 => $token });
+ my $code = $auth->code;
+ $mech->submit_form_ok({ with_fields => { '2fa_code' => $code } }, "provide correct 2FA code" );
}
# check that we got the message expected
@@ -956,7 +331,7 @@ foreach my $test (
my $report = $user->problems->first;
ok $report, "Found the report";
- if (!$test->{two_factor}) {
+ if ($test->{two_factor} eq '') {
# The superuser account will be immediately redirected
$mech->content_contains('Thank you for reporting this issue');
}
@@ -972,7 +347,7 @@ foreach my $test (
$mech->get_ok( '/report/' . $report->id );
# check that the reporter has an alert
- my $alert = FixMyStreet::App->model('DB::Alert')->find( {
+ my $alert = FixMyStreet::DB->resultset('Alert')->find( {
user => $report->user,
alert_type => 'new_updates',
parameter => $report->id,
@@ -1073,7 +448,7 @@ foreach my $test (
$mech->get_ok( '/report/' . $report->id );
# check that the reporter has an alert
- my $alert = FixMyStreet::App->model('DB::Alert')->find( {
+ my $alert = FixMyStreet::DB->resultset('Alert')->find( {
user => $report->user,
alert_type => 'new_updates',
parameter => $report->id,
@@ -1258,16 +633,18 @@ subtest "Test inactive categories" => sub {
};
subtest "category groups" => sub {
- my $cobrand = Test::MockModule->new('FixMyStreet::Cobrand::FixMyStreet');
- $cobrand->mock('enable_category_groups', sub { 1 });
FixMyStreet::override_config {
ALLOWED_COBRANDS => 'fixmystreet',
MAPIT_URL => 'http://mapit.uk/',
+ COBRAND_FEATURES => {
+ category_groups => { fixmystreet => 1 }
+ }
}, sub {
- $contact2->update( { extra => { group => 'Roads' } } );
+ $contact2->update( { extra => { group => ['Roads','Pavements'] } } );
$contact9->update( { extra => { group => 'Roads' } } );
$contact10->update( { extra => { group => 'Roads' } } );
$mech->get_ok("/report/new?lat=$saved_lat&lon=$saved_lon");
+ $mech->content_like(qr{<optgroup label="Pavements">\s*<option value='Potholes'>Potholes</option></optgroup>});
$mech->content_like(qr{<optgroup label="Roads">\s*<option value='Potholes'>Potholes</option>\s*<option value='Street lighting'>Street lighting</option></optgroup>});
};
};
@@ -1303,7 +680,7 @@ subtest "test report creation for a category that is non public" => sub {
title => 'Test Report',
detail => 'Test report details.',
photo1 => '',
- username => 'test-2@example.com',
+ username => $user->email,
name => 'Joe Bloggs',
category => 'Street lighting',
}
@@ -1343,7 +720,7 @@ subtest "test report creation for a category that is non public" => sub {
$contact1->update( { non_public => 0 } );
};
-$contact2->category( "Pothol\xc3\xa9s" );
+$contact2->category( "Pothol\x{00E9}s" );
$contact2->update;
subtest "check map click ajax response" => sub {
@@ -1387,48 +764,50 @@ subtest "check map click ajax response" => sub {
is $extra_details->{category}, '', 'category is empty for council with no contacts';
is_deeply $extra_details->{bodies}, [ "Sandwell Borough Council" ], 'correct bodies for council with no contacts';
ok !$extra_details->{extra_name_info}, 'no extra name info';
-};
-
-#### test uploading an image
-#### test completing a partial report (eq flickr upload)
-
-#### possibly manual testing
-# create report without using map
-# create report by clicking on map with javascript off
-# create report with images off
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'hounslow',
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=51.482286&longitude=-0.328163' );
+ };
+ is_deeply $extra_details->{display_names}, { 'Hounslow Borough Council' => 'Hounslow Highways' }, 'council display name mapping correct';
-subtest "check that a lat/lon off coast leads to /around" => sub {
- my $off_coast_latitude = 50.78301;
- my $off_coast_longitude = -0.646929;
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'hounslownoname',
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=51.482286&longitude=-0.328163' );
+ };
+ isnt defined $extra_details->{display_names}, 'no council display names if none defined';
FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'hounslow',
MAPIT_URL => 'http://mapit.uk/',
}, sub {
- $mech->get_ok( #
- "/report/new"
- . "?latitude=$off_coast_latitude"
- . "&longitude=$off_coast_longitude"
- );
+ $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=51.482286&longitude=-0.328163' );
};
+ ok $extra_details->{by_category}->{'General Enquiry'}->{non_public}, 'non_public set correctly for private category';
+ isnt defined $extra_details->{by_category}->{Tree}->{non_public}, 'non_public omitted for public category';
+};
- is $mech->uri->path, '/around', "redirected to '/around'";
+#### test uploading an image
- is_deeply #
- $mech->page_errors,
- [ 'That location does not appear to be covered by a council; perhaps it is offshore or outside the country. Please try again.' ],
- "Found location error";
+#### test completing a partial report (eq flickr upload)
-};
+#### possibly manual testing
+# create report without using map
+# create report by clicking on map with javascript off
+# create report with images off
subtest "check we load a partial report correctly" => sub {
- my $user = FixMyStreet::App->model('DB::User')->find_or_create(
+ my $user = FixMyStreet::DB->resultset('User')->find_or_create(
{
email => 'test-partial@example.com'
}
);
- my $report = FixMyStreet::App->model('DB::Problem')->create( {
+ my $report = FixMyStreet::DB->resultset('Problem')->create( {
name => '',
postcode => '',
category => 'Street lighting',
@@ -1447,7 +826,7 @@ subtest "check we load a partial report correctly" => sub {
my $report_id = $report->id;
- my $token = FixMyStreet::App->model("DB::Token")
+ my $token = FixMyStreet::DB->resultset("Token")
->create( { scope => 'partial', data => $report->id } );
my $token_code = $token->token;
@@ -1593,7 +972,7 @@ for my $test (
# confirm token in order to update the user details
$mech->get_ok($url);
- my $user = FixMyStreet::App->model('DB::User')->find( { email => 'firstlast@example.com' } );
+ my $user = FixMyStreet::DB->resultset('User')->find( { email => 'firstlast@example.com' } );
my $report = $user->problems->first;
ok $report, "Found the report";
@@ -1732,7 +1111,7 @@ subtest "test Hart" => sub {
# check that the user has been created/ not changed
$user =
- FixMyStreet::App->model('DB::User')->find( { email => $test_email } );
+ FixMyStreet::DB->resultset('User')->find( { email => $user ? $user->email : $test_email } );
ok $user, "user found";
# find the report
@@ -1822,151 +1201,6 @@ subtest "categories from deleted bodies shouldn't be visible for new reports" =>
};
};
-subtest "unresponsive body handling works" => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { fixmystreet => '.' } ],
- MAPIT_URL => 'http://mapit.uk/',
- }, sub {
- # Test body-level send method
- my $old_send = $contact1->body->send_method;
- $contact1->body->update( { send_method => 'Refused' } );
- my $body_id = $contact1->body->id;
- my $extra_details = $mech->get_ok_json('/report/new/ajax?latitude=55.952055&longitude=-3.189579');
- like $extra_details->{top_message}, qr{Edinburgh.*accept reports.*/unresponsive\?body=$body_id};
- is_deeply $extra_details->{unresponsive}, { $body_id => 1 }, "unresponsive json set";
- $extra_details = $mech->get_ok_json('/report/new/category_extras?category=Street%20lighting&latitude=55.952055&longitude=-3.189579');
- is_deeply $extra_details->{unresponsive}, { $body_id => 1 }, "unresponsive json set";
-
- my $test_email = 'test-2@example.com';
- $mech->log_out_ok;
- $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(
- {
- with_fields => {
- title => "Test Report at café",
- detail => 'Test report details.',
- photo1 => '',
- name => 'Joe Bloggs',
- username => $test_email,
- may_show_name => '1',
- phone => '07903 123 456',
- category => 'Trees',
- }
- },
- "submit good details"
- );
-
- my $user = FixMyStreet::App->model('DB::User')->find( { email => $test_email } );
- ok $user, "test user does exist";
-
- my $report = $user->problems->first;
- ok $report, "Found the report";
- is $report->bodies_str, undef, "Report not going anywhere";
-
- like $mech->get_text_body_from_email, qr/despite not being sent/i, "correct email sent";
-
- $user->problems->delete;
- $mech->clear_emails_ok;
-
- # Make sure the same behaviour occurs for reports from the mobile app
- $mech->log_out_ok;
- $mech->post_ok( '/report/new/mobile', {
- title => "Test Report at café",
- detail => 'Test report details.',
- photo1 => '',
- name => 'Joe Bloggs',
- email => $test_email,
- may_show_name => '1',
- phone => '07903 123 456',
- category => 'Trees',
- service => 'iOS',
- lat => 55.952055,
- lon => -3.189579,
- pc => '',
- used_map => '1',
- submit_register => '1',
- password_register => '',
- });
- my $res = $mech->response;
- ok $res->header('Content-Type') =~ m{^application/json\b}, 'response should be json';
-
- $user = FixMyStreet::App->model('DB::User')->find( { email => $test_email } );
- ok $user, "test user does exist";
-
- $report = $user->problems->first;
- ok $report, "Found the report";
- is $report->bodies_str, undef, "Report not going anywhere";
-
- like $mech->get_text_body_from_email, qr/despite not being sent/i, "correct email sent";
-
- $user->problems->delete;
- $mech->clear_emails_ok;
-
- $contact1->body->update( { send_method => $old_send } );
-
- # And test per-category refusing
- my $old_email = $contact3->email;
- $contact3->update( { email => 'REFUSED' } );
- $extra_details = $mech->get_ok_json('/report/new/ajax?latitude=51.896268&longitude=-2.093063');
- like $extra_details->{by_category}{$contact3->category}{category_extra}, qr/Cheltenham.*Trees.*unresponsive.*category=Trees/s;
- $extra_details = $mech->get_ok_json('/report/new/category_extras?category=Trees&latitude=51.896268&longitude=-2.093063');
- is_deeply $extra_details->{unresponsive}, { $contact3->body->id => 1 }, "unresponsive json set";
-
- $mech->get_ok('/around');
- $mech->submit_form_ok( { with_fields => { pc => 'GL50 2PR', } }, "submit location" );
- $mech->follow_link_ok( { text_regex => qr/skip this step/i, }, "follow 'skip this step' link" );
- $mech->submit_form_ok(
- {
- with_fields => {
- title => "Test Report at café",
- detail => 'Test report details.',
- photo1 => '',
- name => 'Joe Bloggs',
- username => $test_email,
- may_show_name => '1',
- phone => '07903 123 456',
- category => 'Trees',
- }
- },
- "submit good details"
- );
-
- $report = $user->problems->first;
- ok $report, "Found the report";
- is $report->bodies_str, undef, "Report not going anywhere";
-
- $contact3->update( { email => $old_email } );
- $mech->delete_user($user);
- };
-};
-
-subtest "unresponsive body page works" => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { fixmystreet => '.' } ],
- }, sub {
- my $old_send = $contact1->body->send_method;
- my $body_id = $contact1->body->id;
- my $url = "/unresponsive?body=$body_id";
- is $mech->get($url)->code, 404, "page not found";
- $contact1->body->update( { send_method => 'Refused' } );
- $mech->get_ok($url);
- $mech->content_contains('Edinburgh');
- $contact1->body->update( { send_method => $old_send } );
-
- my $old_email = $contact3->email;
- $body_id = $contact3->body->id;
- $url = "/unresponsive?body=$body_id;category=Trees";
- is $mech->get($url)->code, 404, "page not found";
- $contact3->update( { email => 'REFUSED' } );
- $mech->get_ok($url);
- $mech->content_contains('Cheltenham');
- $mech->content_contains('Trees');
- $contact3->update( { email => $old_email } );
- };
-};
-
subtest "extra google analytics code displayed on logged in problem creation" => sub {
FixMyStreet::override_config {
ALLOWED_COBRANDS => [ { fixmystreet => '.' } ],
@@ -2066,7 +1300,7 @@ subtest "extra google analytics code displayed on email confirmation problem cre
$mech->get_ok($url);
# find the report
- my $user = FixMyStreet::App->model('DB::User')->find( { email => 'firstlast@example.com' } );
+ my $user = FixMyStreet::DB->resultset('User')->find( { email => 'firstlast@example.com' } );
my $report = $user->problems->first;
ok $report, "Found the report";
@@ -2077,207 +1311,4 @@ subtest "extra google analytics code displayed on email confirmation problem cre
};
};
-
-my $private_perms = $mech->create_user_ok('private_perms@example.org', name => 'private', from_body => $bodies[0]);
-subtest "report_mark_private allows users to mark reports as private" => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { fixmystreet => '.' } ],
- BASE_URL => 'https://www.fixmystreet.com',
- MAPIT_URL => 'http://mapit.uk/',
- }, sub {
- $mech->log_out_ok;
-
- $private_perms->user_body_permissions->find_or_create({
- body => $bodies[0],
- permission_type => 'report_mark_private',
- });
-
- $mech->log_in_ok('private_perms@example.org');
- $mech->get_ok('/');
- $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(
- {
- with_fields => {
- title => "Private report",
- detail => 'Private report details.',
- photo1 => '',
- name => 'Joe Bloggs',
- may_show_name => '1',
- phone => '07903 123 456',
- category => 'Trees',
- non_public => 1,
- }
- },
- "submit good details"
- );
-
- $mech->content_contains('Great work. Now spread the word', 'shown confirmation page');
- }
-};
-
-my $inspector = $mech->create_user_ok('inspector@example.org', name => 'inspector', from_body => $bodies[0]);
-foreach my $test (
- { non_public => 0 },
- { non_public => 1 },
-) {
- subtest "inspectors get redirected directly to the report page, non_public=$test->{non_public}" => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { fixmystreet => '.' } ],
- BASE_URL => 'https://www.fixmystreet.com',
- MAPIT_URL => 'http://mapit.uk/',
- }, sub {
- $mech->log_out_ok;
-
- $inspector->user_body_permissions->find_or_create({
- body => $bodies[0],
- permission_type => 'planned_reports',
- });
- $inspector->user_body_permissions->find_or_create({
- body => $bodies[0],
- permission_type => 'report_inspect',
- });
-
- $mech->log_in_ok('inspector@example.org');
- $mech->get_ok('/');
- $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB' } },
- "submit location" );
- $mech->follow_link_ok(
- { text_regex => qr/skip this step/i, },
- "follow 'skip this step' link"
- );
-
- $mech->submit_form_ok(
- {
- with_fields => {
- title => "Inspector report",
- detail => 'Inspector report details.',
- photo1 => '',
- name => 'Joe Bloggs',
- may_show_name => '1',
- phone => '07903 123 456',
- category => 'Trees',
- non_public => $test->{non_public},
- }
- },
- "submit good details"
- );
-
- like $mech->uri->path, qr/\/report\/[0-9]+/, 'Redirects directly to report';
- }
- };
-}
-
-subtest "check map click ajax response for inspector" => sub {
- $mech->log_out_ok;
-
- my $extra_details;
- $inspector->user_body_permissions->find_or_create({
- body => $bodies[0],
- permission_type => 'planned_reports',
- });
- $inspector->user_body_permissions->find_or_create({
- body => $bodies[0],
- permission_type => 'report_inspect',
- });
-
- $mech->log_in_ok('inspector@example.org');
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { fixmystreet => '.' } ],
- MAPIT_URL => 'http://mapit.uk/',
- }, sub {
- $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=55.952055&longitude=-3.189579' );
- };
- like $extra_details->{category}, qr/data-prefill="0/, 'inspector prefill not set';
- ok !$extra_details->{contribute_as}, 'no contribute as section';
-};
-
-subtest "check map click ajax response for inspector and uk cobrand" => sub {
- $mech->log_out_ok;
-
- my $extra_details;
- $inspector->user_body_permissions->find_or_create({
- body => $bodies[4],
- permission_type => 'planned_reports',
- });
- $inspector->user_body_permissions->find_or_create({
- body => $bodies[4],
- permission_type => 'report_inspect',
- });
-
- $mech->log_in_ok('inspector@example.org');
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { bromley => '.' } ],
- MAPIT_URL => 'http://mapit.uk/',
- }, sub {
- $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=51.402096&longitude=0.015784' );
- };
- like $extra_details->{category}, qr/data-prefill="0/, 'inspector prefill not set';
-};
-
-for my $test (
- {
- desc => 'map click ajax for contribute_as_another_user',
- permissions => {
- contribute_as_another_user => 1,
- contribute_as_anonymous_user => undef,
- contribute_as_body => undef,
- }
- },
- {
- desc => 'map click ajax for contribute_as_anonymous_user',
- permissions => {
- contribute_as_another_user => undef,
- contribute_as_anonymous_user => 1,
- contribute_as_body => undef,
- }
- },
- {
- desc => 'map click ajax for contribute_as_body',
- permissions => {
- contribute_as_another_user => undef,
- contribute_as_anonymous_user => undef,
- contribute_as_body => 1,
- }
- },
-) {
- subtest $test->{desc} => sub {
- $mech->log_out_ok;
- my $extra_details;
- (my $name = $test->{desc}) =~ s/.*(contri.*)/$1/;
- my $user = $mech->create_user_ok("$name\@example.org", name => 'test user', from_body => $bodies[0]);
- for my $p ( keys %{$test->{permissions}} ) {
- next unless $test->{permissions}->{$p};
- $user->user_body_permissions->find_or_create({
- body => $bodies[0],
- permission_type => $p,
- });
- }
- $mech->log_in_ok("$name\@example.org");
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { fixmystreet => '.' } ],
- MAPIT_URL => 'http://mapit.uk/',
- }, sub {
- $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=55.952055&longitude=-3.189579' );
- };
- for my $p ( keys %{$test->{permissions}} ) {
- (my $key = $p) =~ s/contribute_as_//;
- is $extra_details->{contribute_as}->{$key}, $test->{permissions}->{$p}, "$key correctly set";
- }
-
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { fixmystreet => '.' } ],
- MAPIT_URL => 'http://mapit.uk/',
- }, sub {
- $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=51.754926&longitude=-1.256179' );
- };
- ok !$extra_details->{contribute_as}, 'no contribute as section for other council';
- };
-}
-
done_testing();
diff --git a/t/app/controller/report_new_anon.t b/t/app/controller/report_new_anon.t
new file mode 100644
index 000000000..d86bc8134
--- /dev/null
+++ b/t/app/controller/report_new_anon.t
@@ -0,0 +1,272 @@
+package FixMyStreet::Cobrand::AnonAllowed;
+use parent 'FixMyStreet::Cobrand::FixMyStreet';
+sub allow_anonymous_reports { 1 }
+sub anonymous_account { { email => 'anon@example.org', name => 'Anonymous' } }
+
+package FixMyStreet::Cobrand::AnonAllowedByButton;
+use parent 'FixMyStreet::Cobrand::FixMyStreet';
+sub allow_anonymous_reports { 'button' }
+sub anonymous_account { { email => 'anonbutton@example.org', name => 'Anonymous Button' } }
+
+package FixMyStreet::Cobrand::AnonAllowedForCategory;
+use parent 'FixMyStreet::Cobrand::FixMyStreet';
+sub allow_anonymous_reports {
+ my ($self, $category) = @_;
+ $category ||= $self->{c}->stash->{category};
+ return 'button' if $category eq 'Trees';
+}
+sub anonymous_account { { email => 'anoncategory@example.org', name => 'Anonymous Category' } }
+
+package main;
+
+use FixMyStreet::TestMech;
+
+# disable info logs for this test run
+FixMyStreet::App->log->disable('info');
+END { FixMyStreet::App->log->enable('info'); }
+
+my $mech = FixMyStreet::TestMech->new;
+
+my $body = $mech->create_body_ok(2651, 'Edinburgh');
+my $staffuser = $mech->create_user_ok('counciluser@example.com', name => 'Council User', from_body => $body);
+$staffuser->user_body_permissions->create({
+ body => $body,
+ permission_type => 'contribute_as_body',
+});
+$staffuser->user_body_permissions->create({
+ body => $body,
+ permission_type => 'default_to_body',
+});
+
+
+my $contact1 = $mech->create_contact_ok(
+ body_id => $body->id,
+ category => 'Street lighting',
+ email => 'highways@example.com',
+);
+my $contact2 = $mech->create_contact_ok(
+ body_id => $body->id,
+ category => 'Trees',
+ email => 'trees@example.com',
+);
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'anonallowed',
+ MAPIT_URL => 'http://mapit.uk/',
+}, sub {
+
+subtest "check form errors when anonymous account is on" => 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( { with_fields => { category => "Street lighting" } }, "submit form" );
+
+ my @errors = (
+ 'Please enter a subject',
+ 'Please enter some details',
+ # No user errors
+ );
+ is_deeply [ sort @{$mech->page_errors} ], [ sort @errors ], "check errors";
+};
+
+subtest "test report creation anonymously" => 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_register',
+ with_fields => {
+ title => 'Test Report',
+ detail => 'Test report details.',
+ name => 'Joe Bloggs',
+ may_show_name => '1',
+ category => 'Street lighting',
+ }
+ },
+ "submit good details"
+ );
+ $mech->content_contains('Thank you');
+
+ is_deeply $mech->page_errors, [], "check there were no errors";
+
+ my $report = FixMyStreet::DB->resultset("Problem")->first;
+ ok $report, "Found the report";
+
+ is $report->state, 'confirmed', "report confirmed";
+ $mech->get_ok( '/report/' . $report->id );
+
+ is $report->bodies_str, $body->id;
+ is $report->name, 'Anonymous';
+ is $report->anonymous, 0; # Doesn't change behaviour here, but uses anon account's name always
+
+ my $alert = FixMyStreet::DB->resultset('Alert')->find( {
+ user => $report->user,
+ alert_type => 'new_updates',
+ parameter => $report->id,
+ } );
+ is $alert, undef, "no alert created";
+
+ $mech->not_logged_in_ok;
+};
+
+};
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'anonallowedbybutton',
+ MAPIT_URL => 'http://mapit.uk/',
+}, sub {
+
+subtest "test report creation anonymously by button" => 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_register',
+ with_fields => {
+ title => 'Test Report',
+ detail => 'Test report details.',
+ name => 'Joe Bloggs',
+ may_show_name => '1',
+ category => 'Street lighting',
+ }
+ },
+ "submit good details"
+ );
+
+ is_deeply $mech->page_errors, [
+ 'Please enter your email'
+ ], "check there were no errors";
+
+ $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 => 'report_anonymously',
+ with_fields => {
+ title => 'Test Report',
+ detail => 'Test report details.',
+ category => 'Street lighting',
+ }
+ },
+ "submit good details"
+ );
+ $mech->content_contains('Thank you');
+
+ is_deeply $mech->page_errors, [], "check there were no errors";
+
+ my $report = FixMyStreet::DB->resultset("Problem")->search({}, { order_by => { -desc => 'id' } })->first;
+ ok $report, "Found the report";
+
+ is $report->state, 'confirmed', "report confirmed";
+ $mech->get_ok( '/report/' . $report->id );
+
+ is $report->bodies_str, $body->id;
+ is $report->name, 'Anonymous Button';
+ 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';
+
+ my $alert = FixMyStreet::DB->resultset('Alert')->find( {
+ user => $report->user,
+ alert_type => 'new_updates',
+ parameter => $report->id,
+ } );
+ is $alert, undef, "no alert created";
+
+ $mech->not_logged_in_ok;
+};
+
+subtest "test report creation anonymously by staff user" => sub {
+ FixMyStreet::DB->resultset("Problem")->delete_all;
+
+ $mech->log_in_ok( $staffuser->email );
+ $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 => 'report_anonymously',
+ with_fields => {
+ title => 'Test Report',
+ detail => 'Test report details.',
+ category => 'Street lighting',
+ }
+ },
+ "submit good details"
+ );
+ $mech->content_contains('Thank you');
+
+ is_deeply $mech->page_errors, [], "check there were no errors";
+
+ my $report = FixMyStreet::DB->resultset("Problem")->first;
+ ok $report, "Found the report";
+
+ is $report->state, 'confirmed', "report confirmed";
+ $mech->get_ok( '/report/' . $report->id );
+
+ is $report->bodies_str, $body->id;
+ is $report->name, 'Anonymous Button';
+ is $report->anonymous, 1;
+ is $report->get_extra_metadata('contributed_as'), 'anonymous_user';
+ is $report->get_extra_metadata('contributed_by'), $staffuser->id;
+
+ my $alert = FixMyStreet::DB->resultset('Alert')->find( {
+ user => $report->user,
+ alert_type => 'new_updates',
+ parameter => $report->id,
+ } );
+ is $alert, undef, "no alert created";
+
+ $mech->log_out_ok;
+};
+
+};
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'anonallowedforcategory',
+ MAPIT_URL => 'http://mapit.uk/',
+}, sub {
+
+subtest "test report creation anonymously by button, per category" => 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('Thank you');
+
+ 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';
+};
+
+};
+
+done_testing();
diff --git a/t/app/controller/report_new_errors.t b/t/app/controller/report_new_errors.t
new file mode 100644
index 000000000..f45f13c1e
--- /dev/null
+++ b/t/app/controller/report_new_errors.t
@@ -0,0 +1,745 @@
+use FixMyStreet::TestMech;
+use Path::Tiny;
+
+# disable info logs for this test run
+FixMyStreet::App->log->disable('info');
+END { FixMyStreet::App->log->enable('info'); }
+
+my $mech = FixMyStreet::TestMech->new;
+
+my $sample_file = path(__FILE__)->parent->child("sample.jpg");
+ok -e $sample_file, "sample file $sample_file exists";
+
+subtest "test that bare requests to /report/new get redirected" => sub {
+ $mech->get_ok('/report/new');
+ is $mech->uri->path, '/', "went to /";
+ is_deeply { $mech->uri->query_form }, {}, "query empty";
+
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $mech->get_ok('/report/new?pc=SW1A%201AA');
+ is $mech->uri->path, '/around', "went to /around";
+ is_deeply { $mech->uri->query_form }, { pc => 'SW1A 1AA' },
+ "pc correctly transferred";
+
+ $mech->get_ok('/report/new?pc_override=SW1A%201AA&latitude=51&longitude=-2');
+ is $mech->uri->path, '/around', "went to /around";
+ is_deeply { $mech->uri->query_form }, { pc => 'SW1A 1AA' },
+ "pc correctly transferred, lat/lon gone";
+ };
+};
+
+my %body_ids;
+for my $body (
+ { area_id => 2226, name => 'Gloucestershire County Council' },
+ { area_id => 2504, name => 'Westminster City Council' },
+ { area_id => 2482, name => 'Bromley Council' },
+ { area_id => 2217, name => 'Buckinghamshire Council' },
+ { area_id => 2232, name => 'Lincolnshire County Council' },
+ { area_id => 2237, name => 'Oxfordshire County Council' },
+ { area_id => 2600, name => 'Rutland County Council' },
+ { area_id => 2234, name => 'Northamptonshire County Council' },
+ { area_id => 2566, name => 'Peterborough City Council' },
+) {
+ my $body_obj = $mech->create_body_ok($body->{area_id}, $body->{name});
+ $body_ids{$body->{area_id}} = $body_obj->id;
+}
+
+# Let's make some contacts to send things to!
+$mech->create_contact_ok(
+ body_id => $body_ids{2226}, # Gloucestershire
+ category => 'Potholes',
+ email => 'potholes@example.com',
+);
+$mech->create_contact_ok(
+ body_id => $body_ids{2482}, # Bromley
+ category => 'Trees',
+ email => 'trees@example.com',
+);
+$mech->create_contact_ok(
+ body_id => $body_ids{2504},
+ category => 'Street lighting',
+ email => 'highways@example.com'
+);
+$mech->create_contact_ok(
+ body_id => $body_ids{2226}, # Gloucestershire
+ category => 'Street lighting',
+ email => 'streetlights-2226@example.com',
+);
+$mech->create_contact_ok(
+ body_id => $body_ids{2217}, # Buckinghamshire
+ category => 'Street lighting',
+ email => 'streetlights-2217@example.com',
+);
+$mech->create_contact_ok(
+ body_id => $body_ids{2232}, # Lincolnshire
+ category => 'Trees',
+ email => 'trees-2232@example.com',
+);
+$mech->create_contact_ok(
+ body_id => $body_ids{2237}, # Oxfordshire
+ category => 'Trees',
+ email => 'trees-2247@example.com',
+);
+$mech->create_contact_ok(
+ body_id => $body_ids{2600}, # Rutland
+ category => 'Trees',
+ email => 'trees-2600@example.com',
+);
+$mech->create_contact_ok(
+ body_id => $body_ids{2234}, # Northamptonshire
+ category => 'Trees',
+ email => 'trees-2234@example.com',
+);
+$mech->create_contact_ok(
+ body_id => $body_ids{2566}, # Peterborough
+ category => 'Trees',
+ email => 'trees-2566@example.com',
+);
+
+# test that the various bit of form get filled in and errors correctly
+# generated.
+foreach my $test (
+ {
+ msg => 'all fields empty',
+ pc => 'OX1 3DH',
+ fields => {
+ title => '',
+ detail => '',
+ photo1 => '',
+ photo2 => '',
+ photo3 => '',
+ name => '',
+ may_show_name => '1',
+ username => '',
+ phone => '',
+ password_sign_in => '',
+ password_register => '',
+ },
+ changes => {},
+ errors => [
+ 'Please enter a subject',
+ 'Please enter some details',
+ # No category error, as no categories for Oxon at all, so is skipped
+ 'Please enter your email',
+ 'Please enter your name',
+ ],
+ },
+ {
+ msg => 'all fields empty, bad category',
+ pc => 'GL50 2PR',
+ fields => {
+ title => '',
+ detail => '',
+ photo1 => '',
+ photo2 => '',
+ photo3 => '',
+ name => '',
+ may_show_name => '1',
+ username => '',
+ phone => '',
+ category => 'Something bad',
+ password_sign_in => '',
+ password_register => '',
+ },
+ changes => {
+ category => '-- Pick a category --',
+ },
+ errors => [
+ 'Please enter a subject',
+ 'Please enter some details',
+ 'Please choose a category',
+ 'Please enter your email',
+ 'Please enter your name',
+ ],
+ },
+ {
+ msg => 'all fields empty except category',
+ pc => 'SW1A 1AA',
+ fields => {
+ title => '',
+ detail => '',
+ photo1 => '',
+ photo2 => '',
+ photo3 => '',
+ name => '',
+ may_show_name => '1',
+ username => '',
+ phone => '',
+ category => 'Street lighting',
+ password_sign_in => '',
+ password_register => '',
+ },
+ changes => {},
+ errors => [
+ 'Please enter a subject',
+ 'Please enter some details',
+ 'Please enter your email',
+ 'Please enter your name',
+ ],
+ },
+ {
+ msg => 'may_show_name is remembered',
+ pc => 'SW1A 1AA',
+ fields => {
+ title => '',
+ detail => '',
+ photo1 => '',
+ photo2 => '',
+ photo3 => '',
+ name => '',
+ may_show_name => undef,
+ username => '',
+ phone => '',
+ category => 'Street lighting',
+ password_sign_in => '',
+ password_register => '',
+ },
+ changes => {},
+ errors => [
+ 'Please enter a subject',
+ 'Please enter some details',
+ 'Please enter your email',
+ 'Please enter your name',
+ ],
+ },
+ {
+ msg => 'may_show_name unchanged if name is present (stays false)',
+ pc => 'SW1A 1AA',
+ fields => {
+ title => '',
+ detail => '',
+ photo1 => '',
+ photo2 => '',
+ photo3 => '',
+ name => 'Bob Jones',
+ may_show_name => undef,
+ username => '',
+ phone => '',
+ category => 'Street lighting',
+ password_sign_in => '',
+ password_register => '',
+ },
+ changes => {},
+ errors => [
+ 'Please enter a subject',
+ 'Please enter some details',
+ 'Please enter your email',
+ ],
+ },
+ {
+ msg => 'may_show_name unchanged if name is present (stays true)',
+ pc => 'SW1A 1AA',
+ fields => {
+ title => '',
+ detail => '',
+ photo1 => '',
+ photo2 => '',
+ photo3 => '',
+ name => 'Bob Jones',
+ may_show_name => '1',
+ username => '',
+ phone => '',
+ category => 'Street lighting',
+ password_sign_in => '',
+ password_register => '',
+ },
+ changes => {},
+ errors => [
+ 'Please enter a subject',
+ 'Please enter some details',
+ 'Please enter your email',
+ ],
+ },
+ {
+ msg => 'title and details tidied up',
+ pc => 'SW1A 1AA',
+ fields => {
+ title => "DOG SHIT\r\nON WALLS",
+ detail => "on this portakabin -\r\n\r\nmore of a portaloo HEH!!",
+ photo1 => '',
+ photo2 => '',
+ photo3 => '',
+ name => 'Bob Jones',
+ may_show_name => '1',
+ username => '',
+ phone => '',
+ category => 'Street lighting',
+ password_sign_in => '',
+ password_register => '',
+ },
+ changes => {
+ title => 'Dog poo on walls',
+ detail =>
+ "On this [portable cabin] -\n\nMore of a [portable loo] HEH!!",
+ },
+ errors => [ 'Please enter your email', ],
+ },
+ {
+ msg => 'name too short',
+ pc => 'SW1A 1AA',
+ fields => {
+ title => 'Test title',
+ detail => 'Test detail',
+ photo1 => '',
+ photo2 => '',
+ photo3 => '',
+ name => 'DUDE',
+ may_show_name => '1',
+ username => '',
+ phone => '',
+ category => 'Street lighting',
+ password_sign_in => '',
+ password_register => '',
+ },
+ changes => {},
+ errors => [
+ 'Please enter your email',
+'Please enter your full name, councils need this information – if you do not wish your name to be shown on the site, untick the box below',
+ ],
+ },
+ {
+ msg => 'name is anonymous',
+ pc => 'SW1A 1AA',
+ fields => {
+ title => 'Test title',
+ detail => 'Test detail',
+ photo1 => '',
+ photo2 => '',
+ photo3 => '',
+ name => 'anonymous',
+ may_show_name => '1',
+ username => '',
+ phone => '',
+ category => 'Street lighting',
+ password_sign_in => '',
+ password_register => '',
+ },
+ changes => {},
+ errors => [
+ 'Please enter your email',
+'Please enter your full name, councils need this information – if you do not wish your name to be shown on the site, untick the box below',
+ ],
+ },
+ {
+ msg => 'email invalid',
+ pc => 'SW1A 1AA',
+ fields => {
+ title => 'Test title',
+ detail => 'Test detail',
+ photo1 => '',
+ photo2 => '',
+ photo3 => '',
+ name => 'Joe Smith',
+ may_show_name => '1',
+ username => 'not an email',
+ phone => '',
+ category => 'Street lighting',
+ password_sign_in => '',
+ password_register => '',
+ },
+ changes => { username => 'notanemail' },
+ errors => [ 'Please enter a valid email', ],
+ },
+ {
+ msg => 'cleanup title and detail',
+ pc => 'SW1A 1AA',
+ fields => {
+ title => " Test title ",
+ detail => " first line \n\n second\nline\n\n ",
+ photo1 => '',
+ photo2 => '',
+ photo3 => '',
+ name => '',
+ may_show_name => '1',
+ username => '',
+ phone => '',
+ category => 'Street lighting',
+ password_sign_in => '',
+ password_register => '',
+ },
+ changes => {
+ title => 'Test title',
+ detail => "First line\n\nSecond line",
+ },
+ errors => [
+ 'Please enter your email',
+ 'Please enter your name',
+ ],
+ },
+ {
+ msg => 'clean up name and email',
+ pc => 'SW1A 1AA',
+ fields => {
+ title => '',
+ detail => '',
+ photo1 => '',
+ photo2 => '',
+ photo3 => '',
+ name => ' Bob Jones ',
+ may_show_name => '1',
+ username => ' BOB @ExAmplE.COM ',
+ phone => '',
+ category => 'Street lighting',
+ password_sign_in => '',
+ password_register => '',
+ },
+ changes => {
+ name => 'Bob Jones',
+ username => 'bob@example.com',
+ },
+ errors => [ 'Please enter a subject', 'Please enter some details', ],
+ },
+ {
+ msg => 'non-photo upload gives error',
+ pc => 'SW1A 1AA',
+ fields => {
+ title => 'Title',
+ detail => 'Detail',
+ photo1 => [ [ undef, 'bad.txt', Content => 'This is not a JPEG', Content_Type => 'text/plain' ], 1 ],
+ photo2 => '',
+ photo3 => '',
+ name => 'Bob Jones',
+ may_show_name => '1',
+ username => 'bob@example.com',
+ phone => '',
+ category => 'Street lighting',
+ password_sign_in => '',
+ password_register => '',
+ },
+ changes => {
+ photo1 => '',
+ },
+ errors => [ "Please upload an image only" ],
+ },
+ {
+ msg => 'bad photo upload gives error',
+ pc => 'SW1A 1AA',
+ fields => {
+ title => 'Title',
+ detail => 'Detail',
+ photo1 => [ [ undef, 'fake.jpeg', Content => 'This is not a JPEG', Content_Type => 'image/jpeg' ], 1 ],
+ photo2 => '',
+ photo3 => '',
+ name => 'Bob Jones',
+ may_show_name => '1',
+ username => 'bob@example.com',
+ phone => '',
+ category => 'Street lighting',
+ password_sign_in => '',
+ password_register => '',
+ },
+ changes => {
+ photo1 => '',
+ },
+ errors => [ "That image doesn't appear to have uploaded correctly (Please upload an image only ), please try again." ],
+ },
+ {
+ msg => 'photo with octet-stream gets through okay',
+ pc => 'SW1A 1AA',
+ fields => {
+ title => '',
+ detail => 'Detail',
+ photo1 => [ [ $sample_file, undef, Content_Type => 'application/octet-stream' ], 1 ],
+ photo2 => '',
+ photo3 => '',
+ name => 'Bob Jones',
+ may_show_name => '1',
+ username => 'bob@example.com',
+ phone => '',
+ category => 'Street lighting',
+ password_sign_in => '',
+ password_register => '',
+ },
+ changes => {
+ photo1 => '',
+ },
+ errors => [ "Please enter a subject" ],
+ },
+ {
+ msg => 'email in title',
+ pc => 'SW1A 1AA',
+ fields => {
+ title => 'user@example.com',
+ detail => 'Test detail',
+ photo1 => '',
+ photo2 => '',
+ photo3 => '',
+ name => 'Joe Smith',
+ may_show_name => '1',
+ username => 'user@example.com',
+ 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', ],
+ },
+ {
+ msg => 'Bromley long detail',
+ pc => 'BR1 3UH',
+ fields => {
+ fms_extra_title => 'MR',
+ title => '',
+ detail => 'X' . 'x' x 1751,
+ photo1 => '',
+ photo2 => '',
+ photo3 => '',
+ name => 'Bob Example',
+ may_show_name => '1',
+ username => 'bob@example.com',
+ phone => '',
+ category => 'Trees',
+ password_sign_in => '',
+ password_register => '',
+ },
+ changes => { },
+ errors => [ 'Please enter a subject', 'Reports are limited to 1750 characters in length. Please shorten your report' ],
+ },
+ {
+ msg => 'Oxfordshire long detail',
+ pc => 'OX20 1SZ',
+ fields => {
+ title => '',
+ detail => 'X' . 'x' x 1701,
+ photo1 => '',
+ photo2 => '',
+ photo3 => '',
+ name => 'Bob Example',
+ may_show_name => '1',
+ username => 'bob@example.com',
+ phone => '',
+ category => 'Trees',
+ password_sign_in => '',
+ password_register => '',
+ },
+ changes => { },
+ errors => [ 'Please enter a subject', 'Reports are limited to 1700 characters in length. Please shorten your report' ],
+ },
+ {
+ msg => 'Lincolnshire long phone',
+ pc => 'PE9 2GX',
+ fields => {
+ title => '',
+ detail => 'Detail',
+ photo1 => '',
+ photo2 => '',
+ photo3 => '',
+ name => 'Bob Example',
+ may_show_name => '1',
+ username => 'bob@example.com',
+ phone => '123456789 12345678910',
+ category => 'Trees',
+ password_sign_in => '',
+ password_register => '',
+ },
+ changes => { },
+ errors => [ 'Please enter a subject', 'Phone numbers are limited to 20 characters in length.' ],
+ },
+ {
+ msg => 'Buckinghamshire long name',
+ pc => 'RG9 6TL',
+ fields => {
+ title => '',
+ detail => '',
+ photo1 => '',
+ photo2 => '',
+ photo3 => '',
+ name => 'This is a very long name that should fail validation',
+ may_show_name => '1',
+ username => 'bob@example.com',
+ phone => '',
+ category => 'Street lighting',
+ password_sign_in => '',
+ password_register => '',
+ },
+ changes => { },
+ errors => [ 'Please enter a subject', 'Please enter some details', 'Names are limited to 50 characters in length.' ],
+ },
+ {
+ msg => 'Rutland long name',
+ pc => 'LE15 0GJ',
+ fields => {
+ title => '',
+ detail => '',
+ photo1 => '',
+ photo2 => '',
+ photo3 => '',
+ name => 'This is a very long name that should fail validation',
+ may_show_name => '1',
+ username => 'bob@example.com',
+ phone => '',
+ category => 'Trees',
+ password_sign_in => '',
+ password_register => '',
+ },
+ changes => { },
+ errors => [ 'Please enter a subject', 'Please enter some details', 'Names are limited to 40 characters in length.' ],
+ },
+ {
+ msg => 'Oxfordshire validation',
+ pc => 'OX20 1SZ',
+ fields => {
+ title => '',
+ detail => '',
+ photo1 => '',
+ photo2 => '',
+ 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',
+ phone => '01234 5678910 09876 54321 ext 203',
+ category => 'Trees',
+ password_sign_in => '',
+ password_register => '',
+ },
+ changes => { },
+ errors => [ 'Please enter a subject', 'Please enter some details', 'Emails are limited to 50 characters in length.', 'Phone numbers are limited to 20 characters in length.', 'Names are limited to 50 characters in length.'],
+ },
+ {
+ msg => 'Northamptonshire validation',
+ pc => 'NN1 1NS',
+ fields => {
+ title => 'This is a very long title that should fail the validation as it is really much too long to pass the validation of 120 characters',
+ detail => '',
+ photo1 => '',
+ photo2 => '',
+ photo3 => '',
+ name => 'A User',
+ may_show_name => '1',
+ username => 'user@example.org',
+ phone => '',
+ category => 'Trees',
+ password_sign_in => '',
+ password_register => '',
+ },
+ changes => { },
+ errors => [ 'Summaries are limited to 120 characters in length. Please shorten your summary', 'Please enter some details'],
+ },
+ {
+ msg => 'Peterborough validation',
+ pc => 'PE1 1HF',
+ fields => {
+ title => 'This is a very long title that should fail the validation',
+ detail => '',
+ photo1 => '',
+ photo2 => '',
+ photo3 => '',
+ name => 'A User',
+ may_show_name => '1',
+ username => 'user@example.org',
+ phone => '',
+ category => 'Trees',
+ password_sign_in => '',
+ password_register => '',
+ },
+ changes => { },
+ errors => [ 'Summaries are limited to 50 characters in length. Please shorten your summary', 'Please enter some details'],
+ },
+ )
+{
+ subtest "check form errors where $test->{msg}" => sub {
+ $mech->get_ok('/around');
+
+ # submit initial pc form
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ { fixmystreet => '.' }, 'bromley', 'oxfordshire', 'rutland', 'lincolnshire', 'buckinghamshire', 'northamptonshire', 'peterborough' ],
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $mech->submit_form_ok( { with_fields => { pc => $test->{pc} } },
+ "submit location" );
+ is_deeply $mech->page_errors, [], "no errors for pc '$test->{pc}'";
+
+ # click through to the report page
+ $mech->follow_link_ok( { text_regex => qr/skip this step/i, },
+ "follow 'skip this step' link" );
+
+ # submit the main form
+ $mech->submit_form_ok( { with_fields => $test->{fields} },
+ "submit form" );
+ };
+
+ # check that we got the errors expected
+ is_deeply [ sort @{$mech->page_errors} ], [ sort @{$test->{errors}} ], "check errors";
+
+ # check that fields have changed as expected
+ my $new_values = {
+ %{ $test->{fields} }, # values added to form
+ %{ $test->{changes} }, # changes we expect
+ };
+ is_deeply $mech->visible_form_values, $new_values,
+ "values correctly changed";
+ };
+}
+
+# this test to make sure that we don't see spurious error messages about
+# the name being blank when there is a sign in error
+subtest "test password errors for a user who is signing in as they report" => sub {
+ my $user = $mech->create_user_ok('test-2@example.com',
+ name => 'Joe Bloggs',
+ phone => '01234 567 890',
+ password => 'secret2',
+ phone_verified => 1,
+ );
+
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'fixmystreet',
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $mech->get_ok('/around?pc=GL50+2PR');
+ $mech->follow_link_ok( { text_regex => qr/skip this step/i, },
+ "follow 'skip this step' link" );
+
+ $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',
+ }
+ },
+ "submit with wrong password"
+ );
+ };
+
+ # check that we got the errors expected
+ is_deeply $mech->page_errors, [
+ "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->content_lacks('1234 567', 'phone number not shown');
+};
+
+subtest "check that a lat/lon off coast leads to /around" => sub {
+ my $off_coast_latitude = 50.78301;
+ my $off_coast_longitude = -0.646929;
+
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $mech->get_ok(
+ "/report/new"
+ . "?latitude=$off_coast_latitude"
+ . "&longitude=$off_coast_longitude"
+ );
+ };
+
+ is $mech->uri->path, '/around', "redirected to '/around'";
+
+ is_deeply
+ $mech->page_errors,
+ [ 'That location does not appear to be covered by a council; perhaps it is offshore or outside the country. Please try again.' ],
+ "Found location error";
+
+};
+
+done_testing;
diff --git a/t/app/controller/report_new_mobile.t b/t/app/controller/report_new_mobile.t
index 296007ce3..def140a72 100644
--- a/t/app/controller/report_new_mobile.t
+++ b/t/app/controller/report_new_mobile.t
@@ -15,21 +15,20 @@ subtest "Check signed up for alert when logged in" => sub {
MAPIT_URL => 'http://mapit.zurich',
MAPIT_TYPES => [ 'O08' ],
}, sub {
- $mech->log_in_ok('user@example.org');
+ my $user = $mech->log_in_ok('user@example.org');
$mech->post_ok( '/report/new/mobile', {
service => 'iPhone',
title => 'Title',
detail => 'Problem detail',
lat => 47.381817,
lon => 8.529156,
- email => 'user@example.org',
+ email => $user->email,
pc => '',
name => 'Name',
});
my $res = $mech->response;
ok $res->header('Content-Type') =~ m{^application/json\b}, 'response should be json';
- my $user = FixMyStreet::DB->resultset('User')->search({ email => 'user@example.org' })->first;
my $a = FixMyStreet::DB->resultset('Alert')->search({ user_id => $user->id })->first;
isnt $a, undef, 'User is signed up for alert';
};
diff --git a/t/app/controller/report_new_open311.t b/t/app/controller/report_new_open311.t
index dc9a26791..08435fb2b 100644
--- a/t/app/controller/report_new_open311.t
+++ b/t/app/controller/report_new_open311.t
@@ -1,5 +1,4 @@
use FixMyStreet::TestMech;
-use FixMyStreet::App;
use Test::LongString;
use Web::Scraper;
@@ -9,7 +8,7 @@ END { FixMyStreet::App->log->enable('info'); }
my $mech = FixMyStreet::TestMech->new;
-my $body = $mech->create_body_ok(2245, 'Wiltshire Council');
+my $body = $mech->create_body_ok(2608, 'Borsetshire Council');
$body->update({
endpoint => 'http://example.com/open311',
jurisdiction => 'mySociety',
@@ -45,6 +44,7 @@ $mech->create_contact_ok(
category => 'Ball lighting',
email => '102',
extra => { _fields => [
+ { description => 'Message', code => 'message', required => 'false', variable => 'false', order => '0' },
{ description => 'Size', code => 'size', required => 'True', automated => '' },
{ description => 'Speed', code => 'speed', required => 'True', automated => 'server_set' },
{ description => 'Colour', code => 'colour', required => 'True', automated => 'hidden_field' },
@@ -61,6 +61,42 @@ my $contact4 = $mech->create_contact_ok(
{ description => 'Asset ID', code => 'central_asset_id', required => 'true', automated => 'hidden_field', variable => 'true', order => '2' },
] },
);
+# Another one to switch to in disable form test
+$mech->create_contact_ok(
+ body_id => $body2->id, # Edinburgh
+ category => 'Something Other',
+ email => '104',
+);
+$mech->create_contact_ok(
+ body_id => $body2->id, # Edinburgh
+ category => 'Abandoned vehicle',
+ email => '105',
+ extra => { _fields => [
+ { description => 'This is a warning message.', code => 'notice', required => 'false', variable => 'false', order => '0' },
+ { description => 'USRN', code => 'usrn', required => 'false', automated => 'hidden_field' },
+ ] },
+);
+$mech->create_contact_ok(
+ body_id => $body2->id, # Edinburgh
+ category => 'Traffic signals',
+ email => '106',
+ extra => { _fields => [
+ { description => 'This is a warning message for traffic signals.', code => 'notice', required => 'false', variable => 'false', order => '0' },
+ ] },
+);
+
+my $staff_user = $mech->create_user_ok('staff@example.org', name => 'staff', from_body => $body->id);
+
+my $body3 = $mech->create_body_ok(2234, 'Northamptonshire County Council');
+my $ncc_staff_user = $mech->create_user_ok('ncc_staff@example.org', name => 'ncc staff', from_body => $body3->id);
+$mech->create_contact_ok(
+ body_id => $body3->id,
+ category => 'Flooding',
+ email => '104',
+ extra => { _fields => [
+ { description => 'Please ring us!', code => 'ring', variable => 'false', order => '0', disable_form => 'true' }
+ ] },
+);
# test that the various bit of form get filled in and errors correctly
# generated.
@@ -166,7 +202,7 @@ foreach my $test (
# check that the user does not exist
my $test_email = $test->{submit_with}->{username};
- my $user = FixMyStreet::App->model('DB::User')->find( { email => $test_email } );
+ my $user = FixMyStreet::DB->resultset('User')->find( { email => $test_email } );
if ( $user ) {
$user->problems->delete;
$user->comments->delete;
@@ -196,6 +232,8 @@ foreach my $test (
# check that we got the errors expected
is_deeply $mech->page_errors, $test->{errors}, "check errors";
+ $mech->content_contains('Help <strong>Borsetshire Council</strong> resolve your problem quicker');
+
# check that fields have changed as expected
my $new_values = {
%{ $test->{fields} }, # values added to form
@@ -230,7 +268,7 @@ foreach my $test (
$mech->submit_form_ok( { with_fields => $new_values } );
};
- $user = FixMyStreet::App->model('DB::User')->find( { email => $test_email } );
+ $user = FixMyStreet::DB->resultset('User')->find( { email => $test_email } );
ok $user, 'created user';
my $prob = $user->problems->first;
ok $prob, 'problem created';
@@ -262,6 +300,42 @@ subtest "Category extras omits description label when all fields are hidden" =>
};
};
+subtest "Category extras omits preamble when all fields are notices" => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ { fixmystreet => '.' } ],
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ for (
+ { url => '/report/new/ajax?' },
+ { url => '/report/new/category_extras?category=Traffic+signals' },
+ ) {
+ my $json = $mech->get_ok_json($_->{url} . '&latitude=55.952055&longitude=-3.189579');
+ my $category_extra = $json->{by_category} ? $json->{by_category}{'Traffic signals'}{category_extra} : $json->{category_extra};
+ contains_string($category_extra, "This is a warning message for traffic signals.");
+ lacks_string($category_extra, "resolve your problem quicker, by providing some extra detail", "Lacks description text");
+ }
+ };
+};
+
+subtest "Category extras omits preamble when fields are only notices and hidden" => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ { fixmystreet => '.' } ],
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ for (
+ { url => '/report/new/ajax?' },
+ { url => '/report/new/category_extras?category=Abandoned+vehicle' },
+ ) {
+ my $json = $mech->get_ok_json($_->{url} . '&latitude=55.952055&longitude=-3.189579');
+ my $category_extra = $json->{by_category} ? $json->{by_category}{'Abandoned vehicle'}{category_extra} : $json->{category_extra};
+ contains_string($category_extra, "This is a warning message.");
+ contains_string($category_extra, "usrn");
+ lacks_string($category_extra, "USRN", "Lacks 'USRN' label");
+ lacks_string($category_extra, "resolve your problem quicker, by providing some extra detail", "Lacks description text");
+ }
+ };
+};
+
subtest "Category extras includes description label for user" => sub {
FixMyStreet::override_config {
ALLOWED_COBRANDS => [ { fixmystreet => '.' } ],
@@ -286,4 +360,138 @@ subtest "Category extras includes description label for user" => sub {
};
};
+subtest "Category extras are correct even if category has an ampersand in it" => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ { fixmystreet => '.' } ],
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ for (
+ { url => '/report/new/ajax?' },
+ { url => '/report/new/category_extras?category=Potholes+%26+Road+Defects' },
+ ) {
+ my $category = "Potholes & Road Defects";
+ $contact4->update({ category => $category });
+ my $json = $mech->get_ok_json($_->{url} . '&latitude=55.952055&longitude=-3.189579');
+ my $category_extra = $json->{by_category} ? $json->{by_category}{$category}{category_extra} : $json->{category_extra};
+ contains_string($category_extra, "usrn") or diag $mech->content;
+ contains_string($category_extra, "central_asset_id");
+ lacks_string($category_extra, "USRN", "Lacks 'USRN' label");
+ lacks_string($category_extra, "Asset ID", "Lacks 'Asset ID' label");
+ contains_string($category_extra, "Size?");
+ lacks_string($category_extra, '<option value=""');
+ contains_string($category_extra, "resolve your problem quicker, by providing some extra detail", "Contains description text");
+ $contact4->update({ category => "Pothole" });
+ }
+ };
+};
+
+subtest "Category extras includes form disabling string" => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'fixmystreet',
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $contact4->push_extra_fields({ description => 'Please ring us!', code => 'ring', variable => 'false', order => '0', disable_form => 'true' });
+ $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->update;
+ for (
+ { url => '/report/new/ajax?' },
+ { url => '/report/new/category_extras?category=Pothole' },
+ ) {
+ 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};
+ is_deeply $output, {
+ all => 'Please ring us!',
+ questions => [
+ {
+ message => 'Please please ring',
+ code => 'dangerous',
+ answers => [ 'yes' ],
+ },
+ ],
+ };
+ }
+
+ # Test new non-JS form disabling flow
+ $mech->get_ok('/report/new?latitude=55.952055&longitude=-3.189579');
+ $mech->content_contains('name="submit_category_part_only"');
+ $mech->submit_form_ok({ with_fields => { category => 'Pothole' } });
+ $mech->content_contains('<div id="js-category-stopper" class="box-warning" role="alert" aria-live="assertive">');
+ $mech->content_contains('Please ring us!');
+ # Switch to another, okay, category
+ $mech->submit_form_ok({ with_fields => { category => 'Something Other' } });
+ $mech->content_lacks('<div id="js-category-stopper" class="box-warning" role="alert" aria-live="assertive">');
+ $mech->content_lacks('Please ring us!');
+
+ # Remove the required extra field so its error checking doesn't get in the way
+ my $extra = $contact4->get_extra_fields;
+ @$extra = grep { $_->{code} ne 'size' } @$extra;
+ $contact4->set_extra_fields(@$extra);
+ $contact4->update;
+
+ # 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',
+ } });
+ $mech->content_contains('<div id="js-category-stopper" class="box-warning" role="alert" aria-live="assertive">');
+ $mech->content_contains('Please ring us!');
+
+ # Test special answer disabling of form
+ $extra = $contact4->get_extra_fields;
+ @$extra = grep { $_->{code} ne 'ring' } @$extra; # Remove that all-category one
+ $contact4->set_extra_fields(@$extra);
+ $contact4->update;
+ $mech->get_ok('/report/new?latitude=55.952055&longitude=-3.189579');
+ $mech->content_contains('name="submit_category_part_only"');
+ $mech->submit_form_ok({ with_fields => { category => 'Pothole' } });
+ $mech->content_contains('name="submit_category_part_only"');
+ $mech->submit_form_ok({ with_fields => { dangerous => 'no' } });
+ $mech->content_lacks('<div id="js-category-stopper" class="box-warning" role="alert" aria-live="assertive">');
+ $mech->content_lacks('Please please ring');
+ $mech->submit_form_ok({ with_fields => { dangerous => 'yes' } });
+ $mech->content_contains('<div id="js-category-stopper" class="box-warning" role="alert" aria-live="assertive">');
+ $mech->content_contains('Please please ring');
+ };
+};
+
+subtest "Staff users still see disable form categories" => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'borsetshire',
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+
+ $mech->log_in_ok($staff_user->email);
+
+ $contact2->push_extra_fields({ description => 'Please ring us!', code => 'ring', variable => 'false', order => '0', disable_form => 'true' });
+ $contact2->update;
+
+ # Test new non-JS form disabling flow
+ $mech->get_ok('/report/new?latitude=51.496194&longitude=-2.603439');
+ $mech->submit_form_ok({ with_fields => { category => 'Graffiti Removal' } });
+ $mech->content_contains('<div id="js-category-stopper" class="box-warning" role="alert" aria-live="assertive">');
+ $mech->content_contains('Please ring us!');
+ };
+};
+
+subtest "Staff users disable form categories" => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'northamptonshire',
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $mech->log_out_ok;
+ $mech->log_in_ok($ncc_staff_user->email);
+
+ $mech->get_ok('/report/new?latitude=52.236251&longitude=-0.892052');
+ $mech->submit_form_ok({ with_fields => {
+ category => 'Flooding', title => 'Title', detail => 'Detail',
+ } });
+
+ my $prob = $ncc_staff_user->problems->first;
+ ok $prob, 'problem created';
+ is $prob->title, "Title", 'Report title correct';
+ };
+};
+
done_testing();
diff --git a/t/app/controller/report_new_staff.t b/t/app/controller/report_new_staff.t
new file mode 100644
index 000000000..3817cdf3a
--- /dev/null
+++ b/t/app/controller/report_new_staff.t
@@ -0,0 +1,268 @@
+use FixMyStreet::TestMech;
+
+# disable info logs for this test run
+FixMyStreet::App->log->disable('info');
+END { FixMyStreet::App->log->enable('info'); }
+
+my $mech = FixMyStreet::TestMech->new;
+
+my %body_ids;
+for my $body (
+ { area_id => 2651, name => 'City of Edinburgh Council' },
+ { area_id => 2482, name => 'Bromley Council' },
+ { area_id => 2237, name => 'Oxfordshire County Council' },
+) {
+ my $body_obj = $mech->create_body_ok($body->{area_id}, $body->{name});
+ $body_ids{$body->{area_id}} = $body_obj->id;
+}
+
+# Let's make some contacts to send things to!
+$mech->create_contact_ok( body_id => $body_ids{2651}, category => 'Street lighting', email => 'highways@example.com' );
+my $edin_trees = $mech->create_contact_ok( body_id => $body_ids{2651}, category => 'Trees', email => 'trees@example.com' );
+$mech->create_contact_ok( body_id => $body_ids{2482}, category => 'Trees', email => 'trees@example.com' );
+$mech->create_contact_ok( body_id => $body_ids{2237}, category => 'Trees', email => 'trees-2247@example.com' );
+
+my $private_perms = $mech->create_user_ok('private_perms@example.org', name => 'private', from_body => $body_ids{2651});
+subtest "report_mark_private allows users to mark reports as private" => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'fixmystreet',
+ BASE_URL => 'https://www.fixmystreet.com',
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $mech->log_out_ok;
+
+ $private_perms->user_body_permissions->find_or_create({
+ body_id => $body_ids{2651},
+ permission_type => 'report_mark_private',
+ });
+
+ $mech->log_in_ok('private_perms@example.org');
+ $mech->get_ok('/');
+ $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"
+ );
+
+ my $edin_cats = $mech->create_contact_ok( body_id => $body_ids{2651}, category => 'Cats', email => 'cats@example.com', non_public => 1 );
+ $mech->submit_form_ok({
+ button => 'submit_category_part_only',
+ with_fields => { category => 'Cats' }
+ });
+ $mech->content_contains('id="form_non_public" value="1" checked disabled');
+ $edin_cats->delete;
+
+ $mech->submit_form_ok(
+ {
+ with_fields => {
+ title => "Private report",
+ detail => 'Private report details.',
+ photo1 => '',
+ name => 'Joe Bloggs',
+ may_show_name => '1',
+ phone => '07903 123 456',
+ category => 'Trees',
+ non_public => 1,
+ }
+ },
+ "submit good details"
+ );
+
+ $mech->content_contains('Great work. Now spread the word', 'shown confirmation page');
+ }
+};
+
+my $inspector = $mech->create_user_ok('inspector@example.org', name => 'inspector', from_body => $body_ids{2651});
+foreach my $test (
+ { non_public => 0 },
+ { non_public => 1 },
+) {
+ subtest "inspectors get redirected directly to the report page, non_public=$test->{non_public}" => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'fixmystreet',
+ BASE_URL => 'https://www.fixmystreet.com',
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $mech->log_out_ok;
+
+ $inspector->user_body_permissions->find_or_create({
+ body_id => $body_ids{2651},
+ permission_type => 'planned_reports',
+ });
+ $inspector->user_body_permissions->find_or_create({
+ body_id => $body_ids{2651},
+ permission_type => 'report_inspect',
+ });
+
+ $mech->log_in_ok('inspector@example.org');
+ $mech->get_ok('/');
+ $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(
+ {
+ with_fields => {
+ title => "Inspector report",
+ detail => 'Inspector report details.',
+ photo1 => '',
+ name => 'Joe Bloggs',
+ may_show_name => '1',
+ phone => '07903 123 456',
+ category => 'Trees',
+ non_public => $test->{non_public},
+ }
+ },
+ "submit good details"
+ );
+
+ like $mech->uri->path, qr/\/report\/[0-9]+/, 'Redirects directly to report';
+ }
+ };
+}
+
+subtest "check map click ajax response for inspector" => sub {
+ $mech->log_out_ok;
+
+ my $extra_details;
+ $inspector->user_body_permissions->find_or_create({
+ body_id => $body_ids{2651},
+ permission_type => 'planned_reports',
+ });
+ $inspector->user_body_permissions->find_or_create({
+ body_id => $body_ids{2651},
+ permission_type => 'report_inspect',
+ });
+
+ $mech->log_in_ok('inspector@example.org');
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'fixmystreet',
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=55.952055&longitude=-3.189579' );
+ };
+ like $extra_details->{category}, qr/data-prefill="0/, 'inspector prefill not set';
+ ok !$extra_details->{contribute_as}, 'no contribute as section';
+};
+
+subtest "check map click ajax response for inspector and uk cobrand" => sub {
+ $mech->log_out_ok;
+
+ my $extra_details;
+ $inspector->user_body_permissions->find_or_create({
+ body_id => $body_ids{2482},
+ permission_type => 'planned_reports',
+ });
+ $inspector->user_body_permissions->find_or_create({
+ body_id => $body_ids{2482},
+ permission_type => 'report_inspect',
+ });
+
+ $mech->log_in_ok('inspector@example.org');
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'bromley',
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=51.402096&longitude=0.015784' );
+ };
+ like $extra_details->{category}, qr/data-prefill="0/, 'inspector prefill not set';
+};
+
+for my $test (
+ {
+ desc => 'map click ajax for contribute_as_another_user',
+ permissions => {
+ contribute_as_another_user => 1,
+ contribute_as_anonymous_user => undef,
+ contribute_as_body => undef,
+ }
+ },
+ {
+ desc => 'map click ajax for contribute_as_anonymous_user',
+ permissions => {
+ contribute_as_another_user => undef,
+ contribute_as_anonymous_user => 1,
+ contribute_as_body => undef,
+ }
+ },
+ {
+ desc => 'map click ajax for contribute_as_body',
+ permissions => {
+ contribute_as_another_user => undef,
+ contribute_as_anonymous_user => undef,
+ contribute_as_body => 1,
+ }
+ },
+) {
+ subtest $test->{desc} => sub {
+ $mech->log_out_ok;
+ my $extra_details;
+ (my $name = $test->{desc}) =~ s/.*(contri.*)/$1/;
+ my $user = $mech->create_user_ok("$name\@example.org", name => 'test user', from_body => $body_ids{2651});
+ for my $p ( keys %{$test->{permissions}} ) {
+ next unless $test->{permissions}->{$p};
+ $user->user_body_permissions->find_or_create({
+ body_id => $body_ids{2651},
+ permission_type => $p,
+ });
+ }
+ $mech->log_in_ok("$name\@example.org");
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'fixmystreet',
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=55.952055&longitude=-3.189579' );
+ };
+ for my $p ( keys %{$test->{permissions}} ) {
+ (my $key = $p) =~ s/contribute_as_//;
+ is $extra_details->{contribute_as}->{$key}, $test->{permissions}->{$p}, "$key correctly set";
+ }
+
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'fixmystreet',
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=51.754926&longitude=-1.256179' );
+ };
+ ok !$extra_details->{contribute_as}, 'no contribute as section for other council';
+ };
+}
+
+subtest 'staff-only categories when reporting' => sub {
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ MAPIT_TYPES => ['UTA'],
+ }, sub {
+ $inspector->update({ is_superuser => 1 });
+ $mech->log_in_ok('inspector@example.org');
+
+ $mech->get_ok('/admin/body/' . $body_ids{2651} . '/Trees');
+ $mech->submit_form_ok({ with_fields => { state => 'staff' } }, 'mark Trees as staff-only');
+ $edin_trees->discard_changes;
+ is $edin_trees->state, 'staff', 'category is staff only';
+
+ $mech->get_ok('/admin/templates/' . $body_ids{2651} . '/new');
+ $mech->content_contains('Trees');
+
+ my $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=55.952055&longitude=-3.189579' );
+ is_deeply [ sort keys %{$extra_details->{by_category}} ], [ 'Street lighting', 'Trees' ], 'Superuser can see staff-only category';
+
+ $inspector->update({ is_superuser => 0 });
+ $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=55.952055&longitude=-3.189579' );
+ is_deeply [ sort keys %{$extra_details->{by_category}} ], [ 'Street lighting', 'Trees' ], 'Body staff user can see staff-only category';
+
+ $inspector->update({ from_body => $body_ids{2482} });
+ $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=55.952055&longitude=-3.189579' );
+ is_deeply [ sort keys %{$extra_details->{by_category}} ], [ 'Street lighting' ], 'Different body staff user cannot see staff-only category';
+
+ $mech->log_out_ok;
+ $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=55.952055&longitude=-3.189579' );
+ is_deeply [ sort keys %{$extra_details->{by_category}} ], [ 'Street lighting' ], 'Normal user cannot see staff-only category';
+ };
+};
+
+done_testing;
diff --git a/t/app/controller/report_new_text.t b/t/app/controller/report_new_text.t
index fad7fb6ab..852cdac76 100644
--- a/t/app/controller/report_new_text.t
+++ b/t/app/controller/report_new_text.t
@@ -110,14 +110,14 @@ foreach my $test (
$mech->log_out_ok;
if ($test->{user}) {
- my $user = FixMyStreet::App->model('DB::User')->find( { phone => $test_phone } );
+ my $user = FixMyStreet::DB->resultset('User')->find( { phone => $test_phone } );
ok $user, "test user does exist";
$user->problems->delete;
$user->name( 'Old Name' );
$user->password( 'old_password' );
$user->update;
} elsif (!$first_user) {
- ok !FixMyStreet::App->model('DB::User')->find( { phone => $test_phone } ),
+ ok !FixMyStreet::DB->resultset('User')->find( { phone => $test_phone } ),
"test user does not exist";
$first_user = 1;
} else {
@@ -153,7 +153,7 @@ foreach my $test (
is_deeply $mech->page_errors, [], "check there were no errors";
- my $user = FixMyStreet::App->model('DB::User')->find( { phone => $test_phone } );
+ my $user = FixMyStreet::DB->resultset('User')->find( { phone => $test_phone } );
ok $user, "user found";
if ($test->{user}) {
is $user->name, 'Old Name', 'name unchanged';
@@ -189,7 +189,7 @@ foreach my $test (
}
# check that the reporter has an alert
- my $alert = FixMyStreet::App->model('DB::Alert')->find( {
+ my $alert = FixMyStreet::DB->resultset('Alert')->find( {
user => $report->user,
alert_type => 'new_updates',
parameter => $report->id,
@@ -300,7 +300,7 @@ subtest "test report creation for a user who is signing in as they report" => su
is $report->bodies_str, $body->id;
is $report->state, 'confirmed', "report is now confirmed";
$mech->get_ok( '/report/' . $report->id );
- my $alert = FixMyStreet::App->model('DB::Alert')->find( {
+ my $alert = FixMyStreet::DB->resultset('Alert')->find( {
user => $report->user,
alert_type => 'new_updates',
parameter => $report->id,
@@ -356,7 +356,7 @@ subtest "test report creation for a user who is logged in" => sub {
$mech->content_contains('Thank you for reporting this issue');
is $report->state, 'confirmed', "report is now confirmed";
$mech->get_ok( '/report/' . $report->id );
- my $alert = FixMyStreet::App->model('DB::Alert')->find( {
+ my $alert = FixMyStreet::DB->resultset('Alert')->find( {
user => $report->user,
alert_type => 'new_updates',
parameter => $report->id,
diff --git a/t/app/controller/report_new_unresponsive.t b/t/app/controller/report_new_unresponsive.t
new file mode 100644
index 000000000..033475c25
--- /dev/null
+++ b/t/app/controller/report_new_unresponsive.t
@@ -0,0 +1,122 @@
+use FixMyStreet::TestMech;
+
+# disable info logs for this test run
+FixMyStreet::App->log->disable('info');
+END { FixMyStreet::App->log->enable('info'); }
+
+my $mech = FixMyStreet::TestMech->new;
+
+my $body_edin = $mech->create_body_ok(2651, 'City of Edinburgh Council', { send_method => 'Refused' });
+my $body_chelt = $mech->create_body_ok(2326, 'Cheltenham Borough Council');
+$mech->create_contact_ok(body_id => $body_edin->id, category => 'Street lighting', email => 'highways@example.com');
+my $contact = $mech->create_contact_ok(body_id => $body_chelt->id, category => 'Trees', email => 'trees@example.org');
+$mech->create_contact_ok(body_id => $body_edin->id, category => 'Trees', email => 'trees@example.com');
+my $user = $mech->create_user_ok('test-2@example.com');
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'fixmystreet',
+ MAPIT_URL => 'http://mapit.uk/',
+}, sub {
+ subtest "unresponsive body handling, body-level send method" => sub {
+ my $body_id = $body_edin->id;
+ my $extra_details = $mech->get_ok_json('/report/new/ajax?latitude=55.952055&longitude=-3.189579');
+ like $extra_details->{top_message}, qr{Edinburgh.*accept reports.*/unresponsive\?body=$body_id};
+ is_deeply $extra_details->{unresponsive}, { $body_id => 1 }, "unresponsive json set";
+ $extra_details = $mech->get_ok_json('/report/new/category_extras?category=Street%20lighting&latitude=55.952055&longitude=-3.189579');
+ is_deeply $extra_details->{unresponsive}, { $body_id => 1 }, "unresponsive json set";
+
+ make_report('EH1 1BB');
+
+ like $mech->get_text_body_from_email, qr/despite not being sent/i, "correct email sent";
+
+ $user->problems->delete;
+ };
+
+ subtest "unresponsive body handling from mobile app" => sub {
+ $mech->log_out_ok;
+ $mech->post_ok( '/report/new/mobile', {
+ title => "Test Report at café",
+ detail => 'Test report details.',
+ photo1 => '',
+ name => 'Joe Bloggs',
+ email => $user->email,
+ may_show_name => '1',
+ phone => '07903 123 456',
+ category => 'Trees',
+ service => 'iOS',
+ lat => 55.952055,
+ lon => -3.189579,
+ pc => '',
+ used_map => '1',
+ submit_register => '1',
+ password_register => '',
+ });
+ my $res = $mech->response;
+ ok $res->header('Content-Type') =~ m{^application/json\b}, 'response should be json';
+
+ my $report = $user->problems->first;
+ ok $report, "Found the report";
+ is $report->bodies_str, undef, "Report not going anywhere";
+
+ like $mech->get_text_body_from_email, qr/despite not being sent/i, "correct email sent";
+
+ $body_edin->update({ send_method => undef });
+ $user->problems->delete;
+ };
+
+ subtest "unresponsive body handling, per-category refusing" => sub {
+ $contact->update({ email => 'REFUSED' });
+ my $extra_details = $mech->get_ok_json('/report/new/ajax?latitude=51.896268&longitude=-2.093063');
+ like $extra_details->{by_category}{Trees}{category_extra}, qr/Cheltenham.*Trees.*unresponsive.*category=Trees/s;
+ $extra_details = $mech->get_ok_json('/report/new/category_extras?category=Trees&latitude=51.896268&longitude=-2.093063');
+ is_deeply $extra_details->{unresponsive}, { $body_chelt->id => 1 }, "unresponsive json set";
+
+ make_report('GL50 2PR');
+
+ $contact->update({ email => 'trees@example.org' });
+ };
+
+ subtest "unresponsive body page works" => sub {
+ my $url = "/unresponsive?body=" . $body_edin->id;
+ is $mech->get($url)->code, 404, "page not found";
+ $body_edin->update({ send_method => 'Refused' });
+ $mech->get_ok($url);
+ $mech->content_contains('Edinburgh');
+ $body_edin->update({ send_method => undef });
+
+ $url = "/unresponsive?body=" . $body_chelt->id . ";category=Trees";
+ is $mech->get($url)->code, 404, "page not found";
+ $contact->update({ email => 'REFUSED' });
+ $mech->get_ok($url);
+ $mech->content_contains('Cheltenham');
+ $mech->content_contains('Trees');
+ };
+};
+
+done_testing;
+
+sub make_report {
+ my $pc = shift;
+ $mech->get_ok('/around');
+ $mech->submit_form_ok( { with_fields => { pc => $pc } }, "submit location" );
+ $mech->follow_link_ok( { text_regex => qr/skip this step/i, }, "follow 'skip this step' link" );
+ $mech->submit_form_ok(
+ {
+ with_fields => {
+ title => "Test Report at café",
+ detail => 'Test report details.',
+ photo1 => '',
+ name => 'Joe Bloggs',
+ username => $user->email,
+ may_show_name => '1',
+ phone => '07903 123 456',
+ category => 'Trees',
+ }
+ },
+ "submit good details"
+ );
+
+ my $report = $user->problems->first;
+ ok $report, "Found the report";
+ is $report->bodies_str, undef, "Report not going anywhere";
+}
diff --git a/t/app/controller/report_new_update.t b/t/app/controller/report_new_update.t
new file mode 100644
index 000000000..cbb31cea4
--- /dev/null
+++ b/t/app/controller/report_new_update.t
@@ -0,0 +1,71 @@
+use FixMyStreet::TestMech;
+
+# disable info logs for this test run
+FixMyStreet::App->log->disable('info');
+END { FixMyStreet::App->log->enable('info'); }
+
+my $mech = FixMyStreet::TestMech->new;
+
+my $comment_user = $mech->create_user_ok('systemuser@example.org', name => 'Glos Council');
+my $body = $mech->create_body_ok(2226, 'Gloucestershire County Council', {
+ comment_user => $comment_user,
+});
+
+$mech->create_contact_ok(
+ body_id => $body->id,
+ category => 'Potholes',
+ email => 'potholes@example.com',
+);
+
+my $user = $mech->log_in_ok('test-2@example.com');
+
+subtest "test report creation with no initial auto-update" => sub {
+ my $report = make_report();
+ my $comment = FixMyStreet::DB->resultset('Comment')->count;
+ is $comment, 0, 'No comments left';
+ $report->delete;
+};
+
+my $template = FixMyStreet::DB->resultset("ResponseTemplate")->create({
+ body => $body,
+ state => 'confirmed',
+ title => 'Initial email response',
+ text => 'Thanks for your report. We will investigate within 5 working days.',
+ auto_response => 1,
+});
+ok $template, 'Template created';
+
+subtest "test report creation with initial auto-update" => sub {
+ my $report = make_report();
+ my $comment = FixMyStreet::DB->resultset('Comment')->single;
+ is $comment->text, 'Thanks for your report. We will investigate within 5 working days.';
+ is $comment->problem->id, $report->id;
+ is $comment->user->id, $comment_user->id;
+ is $comment->external_id, 'auto-internal';
+ is $comment->name, 'Glos Council';
+};
+
+done_testing;
+
+sub make_report {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'fixmystreet',
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $mech->get_ok('/around?pc=GL50+2PR');
+ $mech->follow_link_ok({ text_regex => qr/skip this step/i, }, "follow 'skip this step' link" );
+ $mech->submit_form_ok({
+ with_fields => {
+ title => "Test Report",
+ detail => 'Test report details.',
+ name => 'Joe Bloggs',
+ category => 'Potholes',
+ }
+ }, "submit good details");
+ };
+
+ my $report = $user->problems->first;
+ ok $report, "Found the report";
+
+ return $report;
+}
diff --git a/t/app/controller/report_non_public.t b/t/app/controller/report_non_public.t
new file mode 100644
index 000000000..d1aa1943c
--- /dev/null
+++ b/t/app/controller/report_non_public.t
@@ -0,0 +1,87 @@
+use FixMyStreet::TestMech;
+
+# disable info logs for this test run
+FixMyStreet::App->log->disable('info');
+END { FixMyStreet::App->log->enable('info'); }
+
+my $mech = FixMyStreet::TestMech->new;
+
+my $body = $mech->create_body_ok(2237, 'Oxfordshire County Council');
+$mech->create_contact_ok( body_id => $body->id, category => 'Potholes', email => 'potholes@example.com' );
+
+my $staffuser = $mech->create_user_ok('body-user@example.net', name => 'Body User', from_body => $body->id);
+$staffuser->user_body_permissions->create({ body => $body, permission_type => 'contribute_as_another_user' });
+$staffuser->user_body_permissions->create({ body => $body, permission_type => 'report_mark_private' });
+
+my $user = $mech->create_user_ok('test@example.com', name => 'Test User');
+my $user2 = $mech->create_user_ok('test2@example.com', name => 'Other User');
+
+my ($report) = $mech->create_problems_for_body(1, $body->id, "Example", {
+ user => $user,
+ non_public => 1,
+});
+my $report_id = $report->id;
+
+subtest "check cannot view non_public report by default" => sub {
+ ok $mech->get("/report/$report_id"), "get '/report/$report_id'";
+ is $mech->res->code, 403, "access denied";
+ is $mech->uri->path, "/report/$report_id", "at /report/$report_id";
+ $mech->content_contains('permission to do that. If you are the problem reporter');
+ $mech->content_lacks('Report another problem here');
+ $mech->content_lacks($report->latitude);
+ $mech->content_lacks($report->longitude);
+};
+
+subtest "check owner of report can view non public reports" => sub {
+ $mech->log_in_ok( $report->user->email );
+ ok $mech->get("/report/$report_id"), "get '/report/$report_id'";
+ is $mech->res->code, 200, "report can be viewed";
+ is $mech->uri->path, "/report/$report_id", "at /report/$report_id";
+ $mech->log_out_ok;
+
+ $mech->log_in_ok( $user2->email );
+ ok $mech->get("/report/$report_id"), "get '/report/$report_id'";
+ is $mech->res->code, 403, "access denied to user who is not report creator";
+ is $mech->uri->path, "/report/$report_id", "at /report/$report_id";
+ $mech->content_contains('permission to do that. If you are the problem reporter');
+ $mech->content_lacks('Report another problem here');
+ $mech->content_lacks($report->latitude);
+ $mech->content_lacks($report->longitude);
+ $mech->log_out_ok;
+};
+
+subtest "Logged email working on private report" => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'fixmystreet',
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $mech->log_in_ok($staffuser->email);
+ $mech->get_ok('/report/new?latitude=51.7549262252&longitude=-1.25617899435');
+ $mech->submit_form_ok({
+ with_fields => {
+ form_as => 'another_user',
+ title => "Test Report",
+ detail => 'Test report details.',
+ category => 'Potholes',
+ name => 'Another User',
+ username => 'another@example.net',
+ non_public => 1,
+ }
+ }, "submit details");
+ };
+ $mech->content_contains('Thank you for reporting this issue');
+ my $report = FixMyStreet::DB->resultset("Problem")->search(undef, { order_by => { -desc => 'id' } })->first;
+ ok $report, "Found the report";
+ is $report->state, 'confirmed', "report is now confirmed";
+ is $report->non_public, 1;
+
+ my $email = $mech->get_email;
+ my $body = $mech->get_text_body_from_email($email);
+ my $url = $mech->get_link_from_email($email);
+ like $body, qr/Your report to Oxfordshire County Council has been logged/;
+ $mech->get_ok($url);
+ $mech->content_lacks('Get updates');
+ $mech->content_contains('To provide an update, please');
+};
+
+done_testing();
diff --git a/t/app/controller/report_update_text.t b/t/app/controller/report_update_text.t
index 4ab8e4bae..52f221264 100644
--- a/t/app/controller/report_update_text.t
+++ b/t/app/controller/report_update_text.t
@@ -18,7 +18,7 @@ my $dt = DateTime->new(
second => 23
);
-my $report = FixMyStreet::App->model('DB::Problem')->find_or_create(
+my $report = FixMyStreet::DB->resultset('Problem')->find_or_create(
{
postcode => 'SW1A 1AA',
bodies_str => $body->id,
@@ -44,7 +44,7 @@ my $report = FixMyStreet::App->model('DB::Problem')->find_or_create(
my $report_id = $report->id;
ok $report, "created test report - $report_id";
-my $comment = FixMyStreet::App->model('DB::Comment')->find_or_create( {
+my $comment = FixMyStreet::DB->resultset('Comment')->find_or_create( {
problem_id => $report_id,
user_id => $user2->id,
name => 'Other User',
@@ -181,7 +181,7 @@ for my $test (
}
my ($token) = $mech->content =~ /name="token" value="([^"]*)"/;
- $token = FixMyStreet::App->model('DB::Token')->find({
+ $token = FixMyStreet::DB->resultset('Token')->find({
token => $token,
scope => 'comment'
});
@@ -189,7 +189,7 @@ for my $test (
my $update_id = $token->data->{id};
my $add_alerts = $token->data->{add_alert};
- my $update = FixMyStreet::App->model('DB::Comment')->find( { id => $update_id } );
+ my $update = FixMyStreet::DB->resultset('Comment')->find( { id => $update_id } );
ok $update, 'found update in database';
is $update->state, 'unconfirmed', 'update unconfirmed';
@@ -211,11 +211,11 @@ for my $test (
ok $user->check_password( 'new_secret' ), 'password changed';
is $user->name, 'Reg User', 'name changed';
} else {
- $user = FixMyStreet::App->model( 'DB::User' )->find( { phone => $details->{username} } );
+ $user = FixMyStreet::DB->resultset( 'User' )->find( { phone => $details->{username} } );
ok $user, 'found user';
}
- my $alert = FixMyStreet::App->model( 'DB::Alert' )->find(
+ my $alert = FixMyStreet::DB->resultset( 'Alert' )->find(
{ user => $user, alert_type => 'new_updates', confirmed => 1, }
);
diff --git a/t/app/controller/report_updates.t b/t/app/controller/report_updates.t
index 8ff5b4d24..07ee48587 100644
--- a/t/app/controller/report_updates.t
+++ b/t/app/controller/report_updates.t
@@ -31,7 +31,7 @@ my $dt = DateTime->new(
second => 23
);
-my $report = FixMyStreet::App->model('DB::Problem')->find_or_create(
+my $report = FixMyStreet::DB->resultset('Problem')->find_or_create(
{
postcode => 'SW1A 1AA',
bodies_str => $body->id,
@@ -57,7 +57,7 @@ my $report = FixMyStreet::App->model('DB::Problem')->find_or_create(
my $report_id = $report->id;
ok $report, "created test report - $report_id";
-my $comment = FixMyStreet::App->model('DB::Comment')->find_or_create(
+my $comment = FixMyStreet::DB->resultset('Comment')->find_or_create(
{
problem_id => $report_id,
user_id => $user2->id,
@@ -201,7 +201,7 @@ subtest "several updates shown in correct order" => sub {
new_state => 'fixed - user',
},
) {
- my $q = FixMyStreet::App->model('DB::Questionnaire')->find_or_create(
+ my $q = FixMyStreet::DB->resultset('Questionnaire')->find_or_create(
$fields
);
push @qs, $q;
@@ -238,7 +238,7 @@ subtest "several updates shown in correct order" => sub {
confirmed => '2011-03-15 08:12:36',
}
) {
- my $comment = FixMyStreet::App->model('DB::Comment')->find_or_create(
+ my $comment = FixMyStreet::DB->resultset('Comment')->find_or_create(
$fields
);
if ($fields->{text} eq 'Second update') {
@@ -443,7 +443,7 @@ for my $test (
my ($url_token) = $url =~ m{/C/(\S+)};
ok $url, "extracted confirm url '$url'";
- my $token = FixMyStreet::App->model('DB::Token')->find(
+ my $token = FixMyStreet::DB->resultset('Token')->find(
{
token => $url_token,
scope => 'comment'
@@ -454,7 +454,7 @@ for my $test (
my $update_id = $token->data->{id};
my $add_alerts = $token->data->{add_alert};
my $update =
- FixMyStreet::App->model('DB::Comment')->find( { id => $update_id } );
+ FixMyStreet::DB->resultset('Comment')->find( { id => $update_id } );
my $details = {
%{ $test->{form_values} },
@@ -470,11 +470,11 @@ for my $test (
$mech->get_ok( $url );
$mech->content_contains("/report/$report_id#update_$update_id");
- my $unreg_user = FixMyStreet::App->model( 'DB::User' )->find( { email => $details->{username} } );
+ my $unreg_user = FixMyStreet::DB->resultset( 'User' )->find( { email => $details->{username} } );
ok $unreg_user, 'found user';
- my $alert = FixMyStreet::App->model( 'DB::Alert' )->find(
+ my $alert = FixMyStreet::DB->resultset( 'Alert' )->find(
{ user => $unreg_user, alert_type => 'new_updates', confirmed => 1, }
);
@@ -548,7 +548,7 @@ for my $test (
my $email = $mech->email_count_is(0);
my $update =
- FixMyStreet::App->model('DB::Comment')->find( { problem_id => $report_id, text => 'Update no email confirm' } );
+ FixMyStreet::DB->resultset('Comment')->find( { problem_id => $report_id, text => 'Update no email confirm' } );
my $update_id = $update->id;
$mech->content_contains('name="update_' . $update_id . '"');
@@ -563,7 +563,7 @@ for my $test (
is $update->user->email, $details->{username}, 'update email';
is $update->text, $details->{update}, 'update text';
- my $unreg_user = FixMyStreet::App->model( 'DB::User' )->find( { email => $details->{username} } );
+ my $unreg_user = FixMyStreet::DB->resultset( 'User' )->find( { email => $details->{username} } );
ok $unreg_user, 'found user';
@@ -790,7 +790,7 @@ for my $test (
subtest 'check meta correct for comments marked confirmed but not marked open' => sub {
$report->comments->delete;
- my $comment = FixMyStreet::App->model('DB::Comment')->create(
+ my $comment = FixMyStreet::DB->resultset('Comment')->create(
{
user => $user,
problem_id => $report->id,
@@ -911,7 +911,7 @@ subtest "check comment with no status change has not status in meta" => sub {
like $update_meta->[3], qr/investigating/i, 'third update meta says investigating';
my $dt = DateTime->now( time_zone => "local" )->add( seconds => 1 );
- $comment = FixMyStreet::App->model('DB::Comment')->find_or_create(
+ $comment = FixMyStreet::DB->resultset('Comment')->find_or_create(
{
problem_id => $report_id,
user_id => $user->id,
@@ -943,7 +943,7 @@ subtest "check comment with no status change has not status in meta" => sub {
subtest 'check meta correct for second comment marking as reopened' => sub {
$report->comments->delete;
- my $comment = FixMyStreet::App->model('DB::Comment')->create(
+ my $comment = FixMyStreet::DB->resultset('Comment')->create(
{
user => $user,
problem_id => $report->id,
@@ -961,7 +961,7 @@ subtest 'check meta correct for second comment marking as reopened' => sub {
my $update_meta = $mech->extract_update_metas;
like $update_meta->[0], qr/fixed/i, 'update meta says fixed';
- $comment = FixMyStreet::App->model('DB::Comment')->create(
+ $comment = FixMyStreet::DB->resultset('Comment')->create(
{
user => $user,
problem_id => $report->id,
@@ -982,7 +982,7 @@ subtest 'check meta correct for second comment marking as reopened' => sub {
subtest 'check meta correct for comment after mark_fixed with not problem_state' => sub {
$report->comments->delete;
- my $comment = FixMyStreet::App->model('DB::Comment')->create(
+ my $comment = FixMyStreet::DB->resultset('Comment')->create(
{
user => $user,
problem_id => $report->id,
@@ -1000,7 +1000,7 @@ subtest 'check meta correct for comment after mark_fixed with not problem_state'
my $update_meta = $mech->extract_update_metas;
like $update_meta->[0], qr/fixed/i, 'update meta says fixed';
- $comment = FixMyStreet::App->model('DB::Comment')->create(
+ $comment = FixMyStreet::DB->resultset('Comment')->create(
{
user => $user,
problem_id => $report->id,
@@ -1066,7 +1066,7 @@ subtest $test->{desc} => sub {
$report->comments->delete;
- my $comment = FixMyStreet::App->model('DB::Comment')->create(
+ my $comment = FixMyStreet::DB->resultset('Comment')->create(
{
user => $test->{user},
name => $test->{name},
@@ -1130,7 +1130,7 @@ subtest $test->{desc} => sub {
$report->comments->delete;
- my $comment = FixMyStreet::App->model('DB::Comment')->create(
+ my $comment = FixMyStreet::DB->resultset('Comment')->create(
{
user => $user2,
name => 'an administrator',
@@ -1182,7 +1182,7 @@ subtest $test->{desc} => sub {
$report->comments->delete;
for my $state (@{$test->{problem_states}}) {
- my $comment = FixMyStreet::App->model('DB::Comment')->create(
+ my $comment = FixMyStreet::DB->resultset('Comment')->create(
{
user => $user2,
name => 'an administrator',
@@ -1247,6 +1247,7 @@ for my $test (
subtest $test->{desc} => sub {
# Set things up
my $user = $mech->create_user_ok( $test->{form_values}->{username} );
+ $test->{form_values}{username} = $user->email;
my $pw = 'secret2';
$user->update( { name => 'Mr Reg', password => $pw } );
$report->comments->delete;
@@ -1303,7 +1304,7 @@ subtest 'submit an update for a registered user, creating update by email' => su
$mech->submit_form_ok( {
with_fields => {
submit_update => 1,
- username => 'registered@example.com',
+ username => $user->email,
update => 'Update from a user',
add_alert => undef,
name => 'New Name',
@@ -1326,7 +1327,7 @@ subtest 'submit an update for a registered user, creating update by email' => su
my ($url_token) = $url =~ m{/C/(\S+)};
ok $url, "extracted confirm url '$url'";
- my $token = FixMyStreet::App->model('DB::Token')->find( {
+ my $token = FixMyStreet::DB->resultset('Token')->find( {
token => $url_token,
scope => 'comment'
} );
@@ -1334,11 +1335,11 @@ subtest 'submit an update for a registered user, creating update by email' => su
my $update_id = $token->data->{id};
my $add_alerts = $token->data->{add_alert};
- my $update = FixMyStreet::App->model('DB::Comment')->find( { id => $update_id } );
+ my $update = FixMyStreet::DB->resultset('Comment')->find( { id => $update_id } );
ok $update, 'found update in database';
is $update->state, 'unconfirmed', 'update unconfirmed';
- is $update->user->email, 'registered@example.com', 'update email';
+ is $update->user->email, $user->email, 'update email';
is $update->text, 'Update from a user', 'update text';
$mech->get_ok( $url );
@@ -1505,7 +1506,7 @@ for my $test (
$mech->clear_emails_ok();
- $mech->log_in_ok( $test->{email} );
+ my $user = $mech->log_in_ok( $test->{email} );
$mech->get_ok("/report/$report_id");
my $values = $mech->visible_form_values( 'updateForm' );
@@ -1548,12 +1549,12 @@ for my $test (
};
is $update->text, $results->{update}, 'update text';
- is $update->user->email, $test->{email}, 'update user';
+ is $update->user->email, $user->email, 'update user';
is $update->state, 'confirmed', 'update confirmed';
is $update->anonymous, $test->{anonymous}, 'user anonymous';
my $alert =
- FixMyStreet::App->model('DB::Alert')
+ FixMyStreet::DB->resultset('Alert')
->find( { user => $update->user, alert_type => 'new_updates', confirmed => 1, whendisabled => undef } );
ok $test->{alert} ? $alert : !$alert, 'not signed up for alerts';
@@ -1663,7 +1664,7 @@ foreach my $test (
my $questionnaire;
if ( $test->{answered} ) {
$questionnaire =
- FixMyStreet::App->model('DB::Questionnaire')->create(
+ FixMyStreet::DB->resultset('Questionnaire')->create(
{
problem_id => $report_id,
ever_reported => 'y',
@@ -1678,7 +1679,7 @@ foreach my $test (
$mech->clear_emails_ok();
- $mech->log_in_ok( $test->{email} );
+ my $user = $mech->log_in_ok( $test->{email} );
$mech->get_ok("/report/$report_id");
my $values = $mech->visible_form_values('updateForm');
@@ -1708,7 +1709,7 @@ foreach my $test (
my $update = $report->comments->first;
ok $update, 'found update';
is $update->text, $results->{update}, 'update text';
- is $update->user->email, $test->{email}, 'update user';
+ is $update->user->email, $user->email, 'update user';
is $update->state, 'confirmed', 'update confirmed';
is $update->anonymous, $test->{anonymous}, 'user anonymous';
@@ -1728,7 +1729,7 @@ foreach my $test (
$mech->content_contains( $report->title );
$mech->content_contains( 'Thank you for updating this issue' );
- $questionnaire = FixMyStreet::App->model( 'DB::Questionnaire' )->find(
+ $questionnaire = FixMyStreet::DB->resultset( 'Questionnaire' )->find(
{ problem_id => $report_id }
);
@@ -1752,7 +1753,7 @@ for my $test (
fields => {
submit_update => 1,
name => 'Test User',
- username => 'test@example.com',
+ username => $report->user->email,
may_show_name => 1,
update => 'update from owner',
add_alert => undef,
@@ -1774,7 +1775,7 @@ for my $test (
submit_update => 1,
name => 'Test User',
may_show_name => 1,
- username => 'test@example.com',
+ username => $report->user->email,
update => 'update from owner',
add_alert => undef,
fixed => 1,
@@ -1805,7 +1806,7 @@ for my $test (
my $questionnaire;
if ( $test->{answered} ) {
$questionnaire =
- FixMyStreet::App->model('DB::Questionnaire')->create(
+ FixMyStreet::DB->resultset('Questionnaire')->create(
{
problem_id => $report_id,
ever_reported => 'y',
@@ -1851,7 +1852,7 @@ for my $test (
my ($url_token) = $url =~ m{/C/(\S+)};
ok $url, "extracted confirm url '$url'";
- my $token = FixMyStreet::App->model('DB::Token')->find(
+ my $token = FixMyStreet::DB->resultset('Token')->find(
{
token => $url_token,
scope => 'comment'
@@ -1877,7 +1878,7 @@ for my $test (
$mech->content_contains( $report->title );
$mech->content_contains( 'Thank you for updating this issue' );
- $questionnaire = FixMyStreet::App->model( 'DB::Questionnaire' )->find(
+ $questionnaire = FixMyStreet::DB->resultset( 'Questionnaire' )->find(
{ problem_id => $report_id }
);
diff --git a/t/app/controller/reports.t b/t/app/controller/reports.t
index ac230ef95..1d9c8d216 100644
--- a/t/app/controller/reports.t
+++ b/t/app/controller/reports.t
@@ -18,6 +18,9 @@ my $body_west_id = $mech->create_body_ok(2504, 'Westminster City Council')->id;
my $body_fife_id = $mech->create_body_ok(2649, 'Fife Council')->id;
my $body_slash_id = $mech->create_body_ok(10000, 'Electricity/Gas Council')->id;
+$mech->create_contact_ok(body_id => $body_edin_id, category => 'Potholes', email => 'potholes@example.org');
+$mech->create_contact_ok(body_id => $body_west_id, category => 'Graffiti', email => 'graffiti@example.org');
+$mech->create_contact_ok(body_id => $body_fife_id, category => 'Flytipping', email => 'flytipping@example.org');
my @edinburgh_problems = $mech->create_problems_for_body(3, $body_edin_id, 'All reports', { category => 'Potholes' });
my @westminster_problems = $mech->create_problems_for_body(5, $body_west_id, 'All reports', { category => 'Graffiti' });
my @fife_problems = $mech->create_problems_for_body(15, $body_fife_id, 'All reports', { category => 'Flytipping' });
@@ -128,9 +131,11 @@ $mech->content_contains('2,3,4,4');
FixMyStreet::override_config {
ALLOWED_COBRANDS => 'fixmystreet',
MAPIT_URL => 'http://mapit.uk/',
+ COBRAND_FEATURES => { category_groups => { fixmystreet => 1 } },
}, sub {
$mech->submit_form_ok( { with_fields => { body => $body_edin_id } }, 'Submitted dropdown okay' );
is $mech->uri->path, '/reports/City+of+Edinburgh';
+ $mech->content_contains('<optgroup label="">');
subtest "test ward pages" => sub {
$mech->get_ok('/reports/Birmingham/Bad-Ward');
@@ -139,7 +144,7 @@ FixMyStreet::override_config {
is $mech->uri->path, '/reports/Birmingham/Bordesley+and+Highgate';
$mech->get_ok('/reports/Birmingham/Bordesley+and+Highgate|Birchfield');
is $mech->uri->path, '/reports/Birmingham/Bordesley+and+Highgate%7CBirchfield';
- $mech->content_contains('Birchfield, Bordesley & Highgate');
+ $mech->content_contains('Birchfield, Bordesley &amp; Highgate');
};
$mech->get_ok('/reports/Westminster');
diff --git a/t/app/controller/root.t b/t/app/controller/root.t
index 85119da24..0263b65d7 100644
--- a/t/app/controller/root.t
+++ b/t/app/controller/root.t
@@ -60,18 +60,6 @@ FixMyStreet::override_config {
is $mech->res->previous, undef, 'No redirect';
}
};
-
- subtest 'LOGIN_REQUIRED = 1 404s blacklisted URLs' => sub {
- my @blacklist = (
- '/offline/appcache',
- );
-
- foreach my $url (@blacklist) {
- $mech->get($url);
- ok !$mech->res->is_success(), "want a bad response";
- is $mech->res->code, 404, "got 404";
- }
- };
};
subtest "check_login_disallowed cobrand hook" => sub {
diff --git a/t/app/controller/rss.t b/t/app/controller/rss.t
index a8101b593..37543ad4f 100644
--- a/t/app/controller/rss.t
+++ b/t/app/controller/rss.t
@@ -1,3 +1,4 @@
+use utf8;
use open ':std', ':locale';
use FixMyStreet::TestMech;
use FixMyStreet::App;
@@ -97,7 +98,7 @@ $report->geocode(
'estimatedTotal' => 1
}
],
- 'copyright' => "Copyright \x{a9} 2011 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.",
+ 'copyright' => "Copyright © 2011 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.",
'statusCode' => 200,
'authenticationResultCode' => 'ValidCredentials'
}
@@ -150,4 +151,21 @@ subtest "check RSS feeds on cobrand have correct URLs for non-cobrand reports" =
$mech->content_contains($expected2, 'cobrand area report point to cobrand url');
};
+subtest 'Check XSL' => sub {
+ $mech->host('www.fixmystreet.com');
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'fixmystreet',
+ }, sub {
+ $mech->get_ok('/rss/xsl');
+ };
+ $mech->content_contains('/cobrands/fixmystreet.com/images/email-logo.gif');
+ $mech->content_contains('FixMyStreet');
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'bexley',
+ }, sub {
+ $mech->get_ok('/rss/xsl');
+ };
+ $mech->content_contains('/cobrands/bexley/images/logo.png');
+};
+
done_testing();
diff --git a/t/app/controller/sample.pdf b/t/app/controller/sample.pdf
new file mode 100644
index 000000000..9ac5be44b
--- /dev/null
+++ b/t/app/controller/sample.pdf
Binary files differ
diff --git a/t/app/controller/token.t b/t/app/controller/token.t
index 858838865..f7dec1a31 100644
--- a/t/app/controller/token.t
+++ b/t/app/controller/token.t
@@ -1,5 +1,4 @@
use FixMyStreet::TestMech;
-use FixMyStreet::App;
my $mech = FixMyStreet::TestMech->new;
my $user = $mech->create_user_ok('bob@example.com', name => 'Bob');
@@ -8,7 +7,6 @@ subtest 'Zurich special case for C::Tokens->problem_confirm' => sub {
FixMyStreet::override_config {
ALLOWED_COBRANDS => ['zurich'],
}, sub {
- my $c = FixMyStreet::App->new;
my $zurich = $mech->create_body_ok( 1, 'Zurich' );
my ($report) = $mech->create_problems_for_body(
1, $zurich->id,
@@ -19,7 +17,7 @@ subtest 'Zurich special case for C::Tokens->problem_confirm' => sub {
});
is $report->get_extra_metadata('email_confirmed'), undef, 'email_confirmed not yet set (sanity)';
- my $token = $c->model('DB::Token')->create({ scope => 'problem', data => $report->id });
+ my $token = FixMyStreet::DB->resultset('Token')->create({ scope => 'problem', data => $report->id });
$mech->get_ok('/P/' . $token->token);
$report->discard_changes;
diff --git a/t/app/helpers/send_email.t b/t/app/helpers/send_email.t
index a692fb6bc..522ee39d0 100644
--- a/t/app/helpers/send_email.t
+++ b/t/app/helpers/send_email.t
@@ -17,7 +17,7 @@ my $mech = FixMyStreet::TestMech->new;
my $c = ctx_request("/");
# set some values in the stash
-$c->stash->{foo} = 'bar';
+$c->stash->{foo} = 'bar <b>bold</b>';
# clear the email queue
$mech->clear_emails_ok;
@@ -40,7 +40,7 @@ my $email = Email::MIME->new($email_as_string);
my $expected_email_content = path(__FILE__)->parent->child('send_email_sample.txt')->slurp;
my $name = FixMyStreet->config('CONTACT_NAME');
-my $sender = '"' . $name . '" <' . FixMyStreet->config('DO_NOT_REPLY_EMAIL') . '>';
+my $sender = $name . ' <' . FixMyStreet->config('DO_NOT_REPLY_EMAIL') . '>';
$expected_email_content =~ s{CONTACT_EMAIL}{$sender};
my $expected_email = Email::MIME->new($expected_email_content);
@@ -118,6 +118,14 @@ subtest 'Inline emails!' => sub {
\ {10}\+\ text/plain.*\n
\ {10}\+\ text/html.*\n
\ {5}\+\ image/gif]x;
+ $email->walk_parts(sub {
+ my ($part) = @_;
+ if ($part->content_type =~ m[text/plain]i) {
+ like $part->body_str, qr/foo: bar <b>bold<\/b>/;
+ } elsif ($part->content_type =~ m[text/html]i) {
+ like $part->body_str, qr/foo: bar &lt;b&gt;bold&lt;\/b&gt;/;
+ }
+ });
$mech->clear_emails_ok;
};
diff --git a/t/app/helpers/send_email_sample.txt b/t/app/helpers/send_email_sample.txt
index 68fe61f0e..e14c536be 100644
--- a/t/app/helpers/send_email_sample.txt
+++ b/t/app/helpers/send_email_sample.txt
@@ -7,7 +7,7 @@ From: CONTACT_EMAIL
Hello,
-This is a test email where foo: bar.
+This is a test email where foo: bar <b>bold</b>.
utf8: =E6=88=91=E4=BB=AC=E5=BA=94=E8=AF=A5=E8=83=BD=E5=A4=9F=E6=97=A0=E7=BC=
=9D=E5=A4=84=E7=90=86UTF8=E7=BC=96=E7=A0=81
diff --git a/t/app/helpers/send_email_sample_mime.txt b/t/app/helpers/send_email_sample_mime.txt
index 7b4ce91f6..623874149 100644
--- a/t/app/helpers/send_email_sample_mime.txt
+++ b/t/app/helpers/send_email_sample_mime.txt
@@ -12,7 +12,7 @@ Content-Transfer-Encoding: quoted-printable
Hello,
-This is a test email where foo: bar.
+This is a test email where foo: bar <b>bold</b>.
utf8: =E6=88=91=E4=BB=AC=E5=BA=94=E8=AF=A5=E8=83=BD=E5=A4=9F=E6=97=A0=E7=BC=
=9D=E5=A4=84=E7=90=86UTF8=E7=BC=96=E7=A0=81
diff --git a/t/app/model/alert_type.t b/t/app/model/alert_type.t
index 124e838ee..42bed37eb 100644
--- a/t/app/model/alert_type.t
+++ b/t/app/model/alert_type.t
@@ -1,3 +1,4 @@
+use utf8;
use FixMyStreet::TestMech;
my $mech = FixMyStreet::TestMech->new();
@@ -253,7 +254,7 @@ $report->geocode(
'estimatedTotal' => 1
}
],
- 'copyright' => "Copyright \x{a9} 2011 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.",
+ 'copyright' => "Copyright © 2011 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.",
'statusCode' => 200,
'authenticationResultCode' => 'ValidCredentials'
}
@@ -336,6 +337,8 @@ foreach my $test (
};
}
+my $hart = $mech->create_body_ok(2333, 'Hart');
+
my $ward_alert = FixMyStreet::DB->resultset('Alert')->find_or_create(
{
user => $user,
@@ -350,7 +353,7 @@ my $ward_alert = FixMyStreet::DB->resultset('Alert')->find_or_create(
my $report_to_council = FixMyStreet::DB->resultset('Problem')->find_or_create(
{
postcode => 'WS13 6YY',
- bodies_str => '2434',
+ bodies_str => $hart->id,
areas => ',105255,11806,11828,2247,2504,7117,',
category => 'Other',
title => 'council report',
@@ -374,7 +377,7 @@ my $report_to_council = FixMyStreet::DB->resultset('Problem')->find_or_create(
my $report_to_county_council = FixMyStreet::DB->resultset('Problem')->find_or_create(
{
postcode => 'WS13 6YY',
- bodies_str => '2240',
+ bodies_str => '2227',
areas => ',105255,11806,11828,2247,2504,7117,',
category => 'Other',
title => 'county report',
@@ -429,21 +432,22 @@ subtest "check alerts from cobrand send main site url for alerts for different c
)->delete;
FixMyStreet::override_config {
+ ALLOWED_COBRANDS => ['hart', 'fixmystreet'],
+ BASE_URL => 'https://national.example.org',
MAPIT_URL => 'http://mapit.uk/',
}, sub {
FixMyStreet::DB->resultset('AlertType')->email_alerts();
- };
-
- my $body = $mech->get_text_body_from_email;
- my $expected1 = FixMyStreet->config('BASE_URL') . '/report/' . $report_to_county_council->id;
- my $expected3 = FixMyStreet->config('BASE_URL') . '/report/' . $report_outside_district->id;
- my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker('hart')->new();
- my $expected2 = $cobrand->base_url . '/report/' . $report_to_council->id;
+ my $body = $mech->get_text_body_from_email;
- like $body, qr#$expected1#, 'non cobrand area report point to fixmystreet.com';
- like $body, qr#$expected2#, 'cobrand area report point to cobrand url';
- like $body, qr#$expected3#, 'report outside district report point to fixmystreet.com';
+ my $expected1 = FixMyStreet->config('BASE_URL') . '/report/' . $report_to_county_council->id;
+ my $expected3 = FixMyStreet->config('BASE_URL') . '/report/' . $report_outside_district->id;
+ my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker('hart')->new();
+ my $expected2 = $cobrand->base_url . '/report/' . $report_to_council->id;
+ like $body, qr#$expected1#, 'non cobrand area report point to fixmystreet.com';
+ like $body, qr#$expected2#, 'cobrand area report point to cobrand url';
+ like $body, qr#$expected3#, 'report outside district report point to fixmystreet.com';
+ };
};
@@ -485,7 +489,7 @@ subtest "correct i18n-ed summary for state of closed" => sub {
$mech->clear_emails_ok;
$report->update( { state => 'closed' } );
- $alert->update( { lang => 'nb', cobrand => 'fiksgatami' } );
+ $alert->update( { lang => 'sv', cobrand => 'fixamingata' } );
FixMyStreet::DB->resultset('AlertSent')->search( {
alert_id => $alert->id,
@@ -493,14 +497,14 @@ subtest "correct i18n-ed summary for state of closed" => sub {
} )->delete;
FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'fiksgatami' ],
+ ALLOWED_COBRANDS => [ 'fixamingata' ],
}, sub {
FixMyStreet::DB->resultset('AlertType')->email_alerts();
};
my $body = $mech->get_text_body_from_email;
- my $msg = 'Denne rapporten er for tiden markert som lukket';
- like $body, qr/$msg/, 'email says problem is closed, in Norwegian';
+ my $msg = 'Den här rapporten är markerad som stängd';
+ like $body, qr/$msg/, 'email says problem is closed, in Swedish';
};
END {
diff --git a/t/app/model/defecttype.t b/t/app/model/defecttype.t
index e924129e2..3f1cc09b5 100644
--- a/t/app/model/defecttype.t
+++ b/t/app/model/defecttype.t
@@ -1,4 +1,3 @@
-use FixMyStreet::App;
use FixMyStreet::TestMech;
use JSON::MaybeXS;
@@ -11,7 +10,7 @@ my $potholes_contact = $mech->create_contact_ok( body_id => $oxfordshire->id, ca
my $traffic_lights_contact =$mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Traffic lights', email => 'lights@example.com' );
my $pavements_contact =$mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Pavements', email => 'pavements@example.com' );
-my $potholes_defect_type = FixMyStreet::App->model('DB::DefectType')->find_or_create(
+my $potholes_defect_type = FixMyStreet::DB->resultset('DefectType')->find_or_create(
{
body_id => $oxfordshire->id,
name => 'Potholes and Pavements',
@@ -27,7 +26,7 @@ $potholes_defect_type->contact_defect_types->find_or_create({
});
$potholes_defect_type->update();
-my $general_defect_type = FixMyStreet::App->model('DB::DefectType')->find_or_create(
+my $general_defect_type = FixMyStreet::DB->resultset('DefectType')->find_or_create(
{
body_id => $oxfordshire->id,
name => 'All categories',
@@ -37,14 +36,14 @@ my $general_defect_type = FixMyStreet::App->model('DB::DefectType')->find_or_cre
subtest 'for_bodies returns correct results' => sub {
- my $defect_types = FixMyStreet::App->model('DB::DefectType')->for_bodies(
+ my $defect_types = FixMyStreet::DB->resultset('DefectType')->for_bodies(
[ $oxfordshire->id ],
'Potholes'
);
is $defect_types->count, 2, 'Both defect types are included for Potholes category';
- $defect_types = FixMyStreet::App->model('DB::DefectType')->for_bodies(
+ $defect_types = FixMyStreet::DB->resultset('DefectType')->for_bodies(
[ $oxfordshire->id ],
'Traffic lights'
);
@@ -67,7 +66,7 @@ subtest 'Problem->defect_types behaves correctly' => sub {
subtest 'by_categories returns all defect types grouped by category' => sub {
my @contacts = FixMyStreet::DB->resultset('Contact')->not_deleted->search( { body_id => [ $oxfordshire->id ] } )->all;
- my $defect_types = FixMyStreet::App->model('DB::DefectType')->by_categories($area_id, @contacts);
+ my $defect_types = FixMyStreet::DB->resultset('DefectType')->by_categories(\@contacts, body_id => $oxfordshire->id);
my $potholes = decode_json($defect_types->{Potholes});
my $traffic_lights = decode_json($defect_types->{'Traffic lights'});
my $pavements = decode_json($defect_types->{Pavements});
@@ -80,7 +79,7 @@ subtest 'by_categories returns all defect types grouped by category' => sub {
};
subtest 'by_categories returns defect types for an area with multiple bodies' => sub {
- FixMyStreet::App->model('DB::DefectType')->find_or_create(
+ FixMyStreet::DB->resultset('DefectType')->find_or_create(
{
body_id => $other_body->id,
name => 'All categories',
@@ -89,7 +88,7 @@ subtest 'by_categories returns defect types for an area with multiple bodies' =>
);
my @contacts = FixMyStreet::DB->resultset('Contact')->not_deleted->search( { body_id => [ $oxfordshire->id ] } )->all;
- my $defect_types = FixMyStreet::App->model('DB::DefectType')->by_categories($area_id, @contacts);
+ my $defect_types = FixMyStreet::DB->resultset('DefectType')->by_categories(\@contacts, area_id => $area_id);
my $potholes = decode_json($defect_types->{Potholes});
my $traffic_lights = decode_json($defect_types->{'Traffic lights'});
my $pavements = decode_json($defect_types->{Pavements});
diff --git a/t/app/model/extra.t b/t/app/model/extra.t
index 55accb086..9adfb8f80 100644
--- a/t/app/model/extra.t
+++ b/t/app/model/extra.t
@@ -79,6 +79,31 @@ subtest 'Default hash layout' => sub {
is_deeply $contact->extra, { _fields => \@fields }, '(sanity check layout)';
};
+ subtest 'updating extra field' => sub {
+ my $contact = get_test_contact();
+ my @fields = ( { code => 'ABC', description => 'ABC', variable => 'false', }, { code => 'DEF', description => 'DEF', variable => 'true' } );
+ $contact->set_extra_fields(@fields);
+ is_deeply $contact->get_extra_fields, \@fields, 'extra fields set...';
+ my $new_field = { code => 'ABC', description => 'XYZ', variable => 'false' };
+ $contact->update_extra_field($new_field);
+ $fields[0] = $new_field;
+ is_deeply $contact->get_extra_fields, \@fields, 'extra fields changed';
+ $new_field = { code => 'GHI', description => 'GHI', variable => 'false' };
+ $contact->update_extra_field($new_field);
+ push @fields, $new_field;
+ is_deeply $contact->get_extra_fields, \@fields, 'extra fields changed';
+ };
+
+ subtest 'removing extra field' => sub {
+ my $contact = get_test_contact();
+ my @fields = ( { code => 'ABC', description => 'ABC', variable => 'false', }, { code => 'DEF', description => 'DEF', variable => 'true' } );
+ $contact->set_extra_fields(@fields);
+ is_deeply $contact->get_extra_fields, \@fields, 'extra fields set...';
+ $contact->remove_extra_field('DEF');
+ pop @fields;
+ is_deeply $contact->get_extra_fields(), \@fields, 'extra field removed';
+ };
+
subtest 'metadata' => sub {
my $contact = get_test_contact();
is_deeply $contact->get_extra_metadata, {}, 'No extra metadata';
@@ -139,6 +164,53 @@ subtest 'Get named field values' => sub {
is $report->get_extra_field_value("field1"), "value 1", "field1 has correct value";
is $report->get_extra_field_value("field 2"), "this is a test value", "field 2 has correct value";
+
+$report->delete;
+$user->delete;
+};
+
+subtest 'Get named fields' => sub {
+ my $user = $db->resultset('User')->create({
+ email => 'test-moderation@example.com',
+ email_verified => 1,
+ name => 'Test User'
+ });
+ my $report = $db->resultset('Problem')->create(
+ {
+ postcode => 'BR1 3SB',
+ bodies_str => "",
+ areas => "",
+ category => 'Other',
+ title => 'Good bad good',
+ detail => 'Good bad bad bad good bad',
+ used_map => 't',
+ name => 'Test User 2',
+ anonymous => 'f',
+ state => 'confirmed',
+ lang => 'en-gb',
+ service => '',
+ cobrand => 'default',
+ latitude => '51.4129',
+ longitude => '0.007831',
+ user_id => $user->id,
+ });
+
+ my @fields = ({
+ name => "field1",
+ description => "This is a test field",
+ value => "value 1",
+ },
+ {
+ code => "field 2",
+ description => "Another test",
+ value => "this is a test value",
+ });
+
+ $report->push_extra_fields(@fields);
+
+ is_deeply $report->get_extra_field(name => "field1"), $fields[0], "field1 has correct value";
+ is_deeply $report->get_extra_field(code => "field 2"), $fields[1], "field 2 has correct value";
+ is $report->get_extra_field(name => "field 2"), undef, "returns undef if no match";
};
done_testing();
diff --git a/t/app/model/problem.t b/t/app/model/problem.t
index 503fa9276..661a8827f 100644
--- a/t/app/model/problem.t
+++ b/t/app/model/problem.t
@@ -1,6 +1,5 @@
use FixMyStreet::TestMech;
use FixMyStreet;
-use FixMyStreet::App;
use FixMyStreet::DB;
use FixMyStreet::Script::Reports;
use Sub::Override;
@@ -106,15 +105,6 @@ for my $test (
}
},
{
- desc => 'bad category',
- changed => {
- category => '-- Pick a category --',
- },
- errors => {
- category => 'Please choose a category',
- }
- },
- {
desc => 'correct category',
changed => {
category => 'Horse!',
@@ -625,6 +615,8 @@ subtest 'check can set multiple emails as a single contact' => sub {
FixMyStreet::Script::Reports::send();
};
+ $problem->discard_changes;
+ is_deeply $problem->get_extra_metadata('sent_to'), [ '2636@example.com', '2636-2@example.com' ];
$mech->email_count_is(1);
my $email = $mech->get_email;
is $email->header('To'), '"City of Edinburgh Council" <2636@example.com>, "City of Edinburgh Council" <2636-2@example.com>', 'To contains two email addresses';
@@ -671,6 +663,7 @@ subtest 'check can turn on report sent email alerts' => sub {
$problem->discard_changes;
ok defined( $problem->whensent ), 'whensent set';
+ is_deeply $problem->get_extra_metadata('sent_to'), [ 'test@example.org' ];
$email = $emails[1];
like $email->header('Subject'), qr/FixMyStreet Report Sent/, 'report sent email title correct';
@@ -791,7 +784,7 @@ subtest 'generates a tokenised url for a user' => sub {
like $url, qr/\/M\//, 'problem generates tokenised url';
- my $token_obj = FixMyStreet::App->model('DB::Token')->find( {
+ my $token_obj = FixMyStreet::DB->resultset('Token')->find( {
scope => 'email_sign_in', token => $token
} );
is $token, $token_obj->token, 'token is generated in database with correct scope';
@@ -803,7 +796,7 @@ subtest 'stores params in a token' => sub {
my $url = $problem->tokenised_url($user, { foo => 'bar', baz => 'boo'});
(my $token = $url) =~ s/\/M\///g;
- my $token_obj = FixMyStreet::App->model('DB::Token')->find( {
+ my $token_obj = FixMyStreet::DB->resultset('Token')->find( {
scope => 'email_sign_in', token => $token
} );
diff --git a/t/app/model/responsepriority.t b/t/app/model/responsepriority.t
index 4e624bf07..bd09c2da0 100644
--- a/t/app/model/responsepriority.t
+++ b/t/app/model/responsepriority.t
@@ -2,7 +2,6 @@ use strict;
use warnings;
use Test::More;
-use FixMyStreet::App;
use FixMyStreet::TestMech;
use JSON::MaybeXS;
@@ -14,7 +13,7 @@ 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 $potholes_response_priority = FixMyStreet::App->model('DB::ResponsePriority')->find_or_create(
+my $potholes_response_priority = FixMyStreet::DB->resultset('ResponsePriority')->find_or_create(
{
body_id => $oxfordshire->id,
name => 'Potholes',
@@ -25,7 +24,7 @@ $potholes_response_priority->contact_response_priorities->find_or_create({
contact_id => $potholes_contact->id,
});
-my $general_response_priority = FixMyStreet::App->model('DB::ResponsePriority')->find_or_create(
+my $general_response_priority = FixMyStreet::DB->resultset('ResponsePriority')->find_or_create(
{
body_id => $oxfordshire->id,
name => 'All categories',
@@ -34,14 +33,14 @@ my $general_response_priority = FixMyStreet::App->model('DB::ResponsePriority')-
);
subtest 'for_bodies returns correct results' => sub {
- my $priorities = FixMyStreet::App->model('DB::ResponsePriority')->for_bodies(
+ my $priorities = FixMyStreet::DB->resultset('ResponsePriority')->for_bodies(
[ $oxfordshire->id ],
'Potholes'
);
is $priorities->count, 2, 'Both priorities are included for Potholes category';
- $priorities = FixMyStreet::App->model('DB::ResponsePriority')->for_bodies(
+ $priorities = FixMyStreet::DB->resultset('ResponsePriority')->for_bodies(
[ $oxfordshire->id ],
'Traffic lights'
);
@@ -50,9 +49,9 @@ subtest 'for_bodies returns correct results' => sub {
is $priorities->first->name, $general_response_priority->name, 'Correct priority is returned for Traffic lights category';
};
-subtest 'by_categories returns allresponse priorities grouped by category' => sub {
+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;
- my $priorities = FixMyStreet::App->model('DB::ResponsePriority')->by_categories($area_id, @contacts);
+ 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'});
@@ -61,7 +60,7 @@ subtest 'by_categories returns allresponse priorities grouped by category' => su
};
subtest 'by_categories returns all response priorities for an area with multiple bodies' => sub {
- my $other_response_priority = FixMyStreet::App->model('DB::ResponsePriority')->find_or_create(
+ my $other_response_priority = FixMyStreet::DB->resultset('ResponsePriority')->find_or_create(
{
body_id => $other_body->id,
name => 'All categories',
@@ -70,7 +69,7 @@ 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::App->model('DB::ResponsePriority')->by_categories($area_id, @contacts);
+ 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'});
diff --git a/t/app/model/responsetemplate.t b/t/app/model/responsetemplate.t
index fbabc1c12..9efc7e3b4 100644
--- a/t/app/model/responsetemplate.t
+++ b/t/app/model/responsetemplate.t
@@ -16,7 +16,7 @@ $t2->add_to_contacts($c2);
my @contacts = FixMyStreet::DB->resultset('Contact')->not_deleted->search( { body_id => [ $body->id ] } )->all;
subtest 'by_categories returns allresponse templates grouped by category' => sub {
- my $templates = FixMyStreet::App->model('DB::ResponseTemplate')->by_categories($area_id, @contacts);
+ my $templates = FixMyStreet::DB->resultset('ResponseTemplate')->by_categories(\@contacts, body_id => $body->id);
my $potholes = decode_json($templates->{Potholes});
my $graffiti = decode_json($templates->{Graffiti});
diff --git a/t/app/model/session.t b/t/app/model/session.t
index f76533727..f460204e5 100644
--- a/t/app/model/session.t
+++ b/t/app/model/session.t
@@ -2,13 +2,13 @@ use FixMyStreet::TestMech;
my $mech = FixMyStreet::TestMech->new;
-$mech->log_in_ok('test@example.com');
+my $user = $mech->log_in_ok('test@example.com');
my $session = FixMyStreet::DB->resultset("Session")->first;
my $id = $session->id;
$id =~ s/\s+$//;
is $id, "session:" . $session->id_code;
-is $session->user->email, 'test@example.com';
+is $session->user->email, $user->email;
done_testing;
diff --git a/t/app/model/state.t b/t/app/model/state.t
index 35f3d4fb3..f680cf3e8 100644
--- a/t/app/model/state.t
+++ b/t/app/model/state.t
@@ -66,14 +66,14 @@ is_deeply [ sort FixMyStreet::DB::Result::Problem->fixed_states ],
['fixed', 'fixed - council', 'fixed - user'], 'fixed states okay';
FixMyStreet::override_config {
- LANGUAGES => [ 'en-gb,English,en_GB', 'nb,Norwegian,nb_NO' ],
+ LANGUAGES => [ 'en-gb,English,en_GB', 'sv,Swedish,sv_SE' ],
}, sub {
subtest 'translation of open works both ways (file/db)' => sub {
# Note at this point the states have been cached
my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker('default')->new;
- my $lang = $cobrand->set_lang_and_domain('nb', 1, FixMyStreet->path_to('locale')->stringify);
- is $lang, 'nb';
- is $rs->display('confirmed'), "Åpen";
+ my $lang = $cobrand->set_lang_and_domain('sv', 1, FixMyStreet->path_to('locale')->stringify);
+ is $lang, 'sv';
+ is $rs->display('confirmed'), "Öppen";
$lang = $cobrand->set_lang_and_domain('en-gb', 1, FixMyStreet->path_to('locale')->stringify);
is $lang, 'en-gb';
is $rs->display('confirmed'), "Open Eng trans";
diff --git a/t/app/model/user.t b/t/app/model/user.t
index 5a9c898a2..929020d4b 100644
--- a/t/app/model/user.t
+++ b/t/app/model/user.t
@@ -1,5 +1,8 @@
use FixMyStreet::TestMech;
use FixMyStreet::DB;
+use Catalyst::Test 'FixMyStreet::App';
+use HTTP::Request::Common;
+use Test::Exception;
my $mech = FixMyStreet::TestMech->new();
$mech->log_in_ok('test@example.com');
@@ -63,14 +66,46 @@ FixMyStreet::override_config {
$mech->content_like(qr/may_show_name[^>c]*>/);
};
-END {
- done_testing();
-}
+subtest 'Check non-existent methods on user object die' => sub {
+ my $c = ctx_request(POST '/auth', { username => $problem->user->email, password_sign_in => 'secret' });
+ throws_ok(
+ sub { $c->user->is_super_user },
+ qr/Can't locate object method 'is_super_user'/,
+ 'attempt to call non-existent method'
+ );
+};
+
+subtest 'OIDC ids can be manipulated correctly' => sub {
+ my $user = $problem->user;
+
+ is $user->oidc_ids, undef, 'user starts with no OIDC ids';
+
+ $user->add_oidc_id("fixmystreet:1234:5678");
+ is_deeply $user->oidc_ids, ["fixmystreet:1234:5678"], 'OIDC id added correctly';
+
+ $user->add_oidc_id("mycobrand:0123:abcd");
+ is_deeply [ sort @{$user->oidc_ids} ], ["fixmystreet:1234:5678", "mycobrand:0123:abcd"], 'Second OIDC id added correctly';
+
+ $user->add_oidc_id("mycobrand:0123:abcd");
+ is_deeply [ sort @{$user->oidc_ids} ], ["fixmystreet:1234:5678", "mycobrand:0123:abcd"], 'Adding existing OIDC id does not add duplicate';
+
+ $user->remove_oidc_id("mycobrand:0123:abcd");
+ is_deeply $user->oidc_ids, ["fixmystreet:1234:5678"], 'OIDC id can be removed OK';
+
+ $user->remove_oidc_id("mycobrand:0123:abcd");
+ is_deeply $user->oidc_ids, ["fixmystreet:1234:5678"], 'Removing non-existent OIDC id has no effect';
+
+ $user->remove_oidc_id("fixmystreet:1234:5678");
+ is $user->oidc_ids, undef, 'Removing last OIDC id results in undef';
+
+};
+
+done_testing();
sub create_update {
my ($problem, %params) = @_;
my $dt = DateTime->now()->add(days => 1);
- return FixMyStreet::App->model('DB::Comment')->find_or_create({
+ return FixMyStreet::DB->resultset('Comment')->find_or_create({
problem_id => $problem->id,
user_id => $problem->user_id,
name => 'Other User',
diff --git a/t/app/sendreport/email.t b/t/app/sendreport/email.t
index 3e6db4f67..cfd70a097 100644
--- a/t/app/sendreport/email.t
+++ b/t/app/sendreport/email.t
@@ -63,14 +63,14 @@ foreach my $test ( {
is $e->build_recipient_list( $row, {} ), $test->{count}, 'correct recipient list count';
if ( $test->{unconfirmed} ) {
- is_deeply $e->unconfirmed_counts, { 'council@example.com' => { 'category' => 1 } }, 'correct unconfirmed_counts count';
- is_deeply $e->unconfirmed_notes, { 'council@example.com' => { 'category' => $test->{expected_note} } }, 'correct note used';
+ is_deeply $e->unconfirmed_data, { 'council@example.com' => {
+ 'category' => { 'count' => 1, 'note' => $test->{expected_note} }
+ } }, 'correct unconfirmed_data';
}
};
}
-$body->body_areas->delete;
-$body->body_areas->create({ area_id => 2429 });
+$body->update({ name => 'Somerset West and Taunton Council' });
subtest 'Test special behaviour' => sub {
my $e = FixMyStreet::SendReport::Email->new;
diff --git a/t/app/sendreport/email/highways.t b/t/app/sendreport/email/highways.t
index f53062336..b9a71f23f 100644
--- a/t/app/sendreport/email/highways.t
+++ b/t/app/sendreport/email/highways.t
@@ -11,6 +11,7 @@ $mech->create_contact_ok(email => 'council@example.com', body_id => $bromley->id
$mech->create_contact_ok(email => 'highways@example.com', body_id => $highways->id, category => 'Pothole');
my $row = FixMyStreet::DB->resultset('Problem')->new( {
+ id => 123,
bodies_str => '1000',
category => 'Pothole',
cobrand => '',
@@ -28,5 +29,17 @@ $e->add_body($highways);
is $e->build_recipient_list($row), 1, 'correct recipient list count';
is_deeply $e->to, [ [ 'highways@example.com', 'Highways England' ] ], 'correct To line';
+$row->set_extra_fields( { name => 'area_name', value => 'Area 6' } );
+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' } } }
+}, 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, [ [ 'a7@example.com', 'Highways England' ] ], 'correct To line';
+};
+
done_testing();
diff --git a/t/app/sendreport/email/tfl.t b/t/app/sendreport/email/tfl.t
deleted file mode 100644
index 0322de551..000000000
--- a/t/app/sendreport/email/tfl.t
+++ /dev/null
@@ -1,32 +0,0 @@
-use FixMyStreet::SendReport::Email::TfL;
-use FixMyStreet::TestMech;
-
-my $mech = FixMyStreet::TestMech->new;
-
-my $bromley = $mech->create_body_ok(2482, 'Bromley Council');
-my $tfl = $mech->create_body_ok(2482, 'TfL');
-
-$mech->create_contact_ok(email => 'council@example.com', body_id => $bromley->id, category => 'Graffiti');
-$mech->create_contact_ok(email => 'council@example.com', body_id => $bromley->id, category => 'Faulty street light');
-$mech->create_contact_ok(email => 'tfl@example.com', body_id => $tfl->id, category => 'Traffic lights');
-
-my $row = FixMyStreet::DB->resultset('Problem')->new( {
- bodies_str => '1000',
- category => 'Faulty street light',
- cobrand => '',
-} );
-
-my $e = FixMyStreet::SendReport::Email::TfL->new;
-is $e->build_recipient_list($row), undef, 'no recipients if no body';
-
-$e = FixMyStreet::SendReport::Email::TfL->new;
-$e->add_body($bromley);
-is $e->build_recipient_list($row), undef, 'no recipients if category missing';
-
-$e = FixMyStreet::SendReport::Email::TfL->new;
-$e->add_body($tfl);
-is $e->build_recipient_list($row), 1, 'correct recipient list count';
-is_deeply $e->to, [ [ 'tfl@example.com', 'TfL' ] ], 'correct To line';
-
-done_testing();
-
diff --git a/t/app/sendreport/inspection_required.t b/t/app/sendreport/inspection_required.t
deleted file mode 100644
index 64d6f70ee..000000000
--- a/t/app/sendreport/inspection_required.t
+++ /dev/null
@@ -1,100 +0,0 @@
-use FixMyStreet;
-use FixMyStreet::DB;
-use FixMyStreet::TestMech;
-use FixMyStreet::Script::Reports;
-
-ok( my $mech = FixMyStreet::TestMech->new, 'Created mech object' );
-
-my $user = $mech->create_user_ok( 'user@example.com' );
-
-my $body = $mech->create_body_ok( 2237, 'Oxfordshire County Council');
-# $body->update({ send_method => 'Email' });
-
-my $contact = $mech->create_contact_ok(
- body_id => $body->id,
- category => 'Pothole',
- email => 'test@example.org',
-);
-$contact->set_extra_metadata(inspection_required => 1);
-$contact->update;
-
-my @reports = $mech->create_problems_for_body( 1, $body->id, 'Test', {
- cobrand => 'oxfordshire',
- category => $contact->category,
- user => $user,
-});
-my $report = $reports[0];
-
-subtest "Report isn't sent if uninspected" => sub {
- $mech->clear_emails_ok;
-
- FixMyStreet::Script::Reports::send();
-
- $mech->email_count_is( 0 );
- is $report->whensent, undef, "Report hasn't been sent";
-};
-
-subtest 'Report is sent when inspected' => sub {
- $mech->clear_emails_ok;
- $report->set_extra_metadata(inspected => 1);
- $report->update;
-
- FixMyStreet::Script::Reports::send();
-
- $report->discard_changes;
- $mech->email_count_is( 1 );
- ok $report->whensent, 'Report marked as sent';
-};
-
-subtest 'Uninspected report is sent when made by trusted user' => sub {
- $mech->clear_emails_ok;
- $report->unset_extra_metadata('inspected');
- $report->whensent( undef );
- $report->update;
-
- $user->user_body_permissions->find_or_create({
- body => $body,
- permission_type => 'trusted',
- });
- ok $user->has_permission_to('trusted', $report->bodies_str_ids), 'User can make trusted reports';
-
- FixMyStreet::Script::Reports::send();
-
- $report->discard_changes;
- $mech->email_count_is( 1 );
- ok $report->whensent, 'Report marked as sent';
- is $report->get_extra_metadata('inspected'), undef, 'Report not marked as inspected';
-};
-
-subtest "Uninspected report isn't sent when user rep is too low" => sub {
- $mech->clear_emails_ok;
- $report->whensent( undef );
- $report->update;
-
- $user->user_body_permissions->delete;
- $user->set_extra_metadata(reputation => 15);
- $user->update;
-
- $contact->set_extra_metadata(reputation_threshold => 20);
- $contact->update;
-
- FixMyStreet::Script::Reports::send();
-
- $report->discard_changes;
- $mech->email_count_is( 0 );
- is $report->whensent, undef, "Report hasn't been sent";
-};
-
-subtest 'Uninspected report is sent when user rep is high enough' => sub {
- $user->set_extra_metadata(reputation => 21);
- $user->update;
-
- FixMyStreet::Script::Reports::send();
-
- $report->discard_changes;
- $mech->email_count_is( 1 );
- ok $report->whensent, 'Report marked as sent';
- is $report->get_extra_metadata('inspected'), undef, 'Report not marked as inspected';
-};
-
-done_testing();
diff --git a/t/app/sendreport/open311.t b/t/app/sendreport/open311.t
index 54aaa39d0..4e3c179c2 100644
--- a/t/app/sendreport/open311.t
+++ b/t/app/sendreport/open311.t
@@ -1,5 +1,6 @@
use FixMyStreet::Test;
+use Test::MockModule;
use Test::Deep;
use Open311;
@@ -8,6 +9,13 @@ use FixMyStreet::DB;
use Data::Dumper;
+my $ukc = Test::MockModule->new('FixMyStreet::Cobrand::UKCouncils');
+$ukc->mock('lookup_site_code', sub {
+ my ($self, $row, $buffer) = @_;
+ is $row->latitude, 100, 'Correct latitude';
+ return "Road ID";
+});
+
package main;
sub test_overrides; # defined below
@@ -32,7 +40,7 @@ my %standard_open311_parameters = (
test_overrides oxfordshire =>
{
body_name => 'Oxfordshire',
- body_id => 2237,
+ area_id => 2237,
row_data => {
postcode => 'OX1 1AA',
},
@@ -44,7 +52,6 @@ test_overrides oxfordshire =>
},
superhashof({
handler => isa('FixMyStreet::Cobrand::Oxfordshire'),
- discard_changes => 1,
'open311' => noclass(superhashof({
%standard_open311_parameters,
'extended_description' => 'oxfordshire',
@@ -60,7 +67,6 @@ test_overrides oxfordshire =>
my $bromley_check =
superhashof({
handler => isa('FixMyStreet::Cobrand::Bromley'),
- discard_changes => 1,
'open311' => noclass(superhashof({
%standard_open311_parameters,
'send_notpinpointed' => 1,
@@ -75,6 +81,7 @@ my $bromley_check =
{ name => 'email_alerts_requested', value => 'FALSE' },
{ name => 'requested_datetime', value => re(qr/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)/) },
{ name => 'email', value => TEST_USER_EMAIL },
+ { name => 'fms_extra_title', value => 'MR' },
{ name => 'last_name', value => 'Bloggs' },
),
});
@@ -82,7 +89,7 @@ my $bromley_check =
test_overrides bromley =>
{
body_name => 'Bromley',
- body_id => 2482,
+ area_id => 2482,
row_data => {
postcode => 'BR1 1AA',
extra => [ { name => 'last_name', value => 'Bloggs' } ],
@@ -91,14 +98,16 @@ test_overrides bromley =>
northing => 100,
easting => 100,
url => 'http://example.com/1234',
+ prow_reference => 'ABC',
},
},
- $bromley_check;
+ $bromley_check,
+ [ { name => 'last_name', value => 'Bloggs' } ];
test_overrides fixmystreet =>
{
body_name => 'Bromley',
- body_id => 2482,
+ area_id => 2482,
row_data => {
postcode => 'BR1 1AA',
# NB: we don't pass last_name here, as main cobrand doesn't know to do this!
@@ -114,7 +123,7 @@ test_overrides fixmystreet =>
test_overrides greenwich =>
{
body_name => 'Greenwich',
- body_id => 2493,
+ area_id => 2493,
},
superhashof({
handler => isa('FixMyStreet::Cobrand::Greenwich'),
@@ -129,7 +138,7 @@ test_overrides greenwich =>
test_overrides fixmystreet =>
{
body_name => 'West Berkshire',
- body_id => 2619,
+ area_id => 2619,
row_data => {
postcode => 'RG1 1AA',
},
@@ -145,20 +154,45 @@ test_overrides fixmystreet =>
})),
});
+test_overrides fixmystreet =>
+ {
+ body_name => 'Cheshire East',
+ area_id => 21069,
+ row_data => {
+ postcode => 'CW11 1HZ',
+ },
+ extra => {
+ url => 'http://example.com/1234',
+ },
+ },
+ superhashof({
+ handler => isa('FixMyStreet::Cobrand::CheshireEast'),
+ 'open311' => noclass(superhashof({
+ %standard_open311_parameters,
+ })),
+ problem_extra => bag(
+ { name => 'report_url' => value => 'http://example.com/1234' },
+ { name => 'title', value => 'Problem' },
+ { name => 'description', value => 'A big problem' },
+ { name => 'site_code', value => 'Road ID' },
+ ),
+ }),
+ [ { name => 'site_code', value => 'Road ID' } ];
+
sub test_overrides {
# NB: Open311 and ::SendReport::Open311 are mocked below in BEGIN { ... }
- my ($cobrand, $input, $expected_data) = @_;
+ my ($cobrand, $input, $expected_data, $end_extra) = @_;
subtest "$cobrand ($input->{body_name}) overrides" => sub {
FixMyStreet::override_config {
- ALLOWED_COBRANDS => ['fixmystreet', 'oxfordshire', 'bromley', 'westberkshire', 'greenwich'],
+ ALLOWED_COBRANDS => ['fixmystreet', 'oxfordshire', 'bromley', 'westberkshire', 'greenwich', 'cheshireeast'],
}, sub {
my $db = FixMyStreet::DB->schema;
#$db->txn_begin;
- my $params = { id => $input->{body_id}, name => $input->{body_name} };
+ my $params = { name => $input->{body_name} };
my $body = $db->resultset('Body')->find_or_create($params);
- $body->body_areas->find_or_create({ area_id => $input->{body_id} });
+ $body->body_areas->find_or_create({ area_id => $input->{area_id} });
ok $body, "found/created body " . $input->{body_name};
$body->update({ can_be_devolved => 1 });
@@ -171,7 +205,7 @@ sub test_overrides {
whenedited => DateTime->now,
jurisdiction => '1234',
api_key => 'SEEKRIT',
- body_id => $input->{body_id},
+ body_id => $body->id,
);
$contact->update({ send_method => 'Open311', endpoint => 'http://example.com/open311' });
@@ -179,6 +213,7 @@ sub test_overrides {
name => 'Fred Bloggs',
email => TEST_USER_EMAIL,
password => 'dummy',
+ title => 'MR',
});
my $row = $db->resultset('Problem')->create( {
@@ -188,8 +223,8 @@ sub test_overrides {
name => 'Fred Bloggs',
anonymous => 1,
state => 'unconfirmed',
- bodies_str => $input->{body_id},
- areas => (sprintf ',%d,', $input->{body_id}),
+ bodies_str => $body->id,
+ areas => (sprintf ',%d,', $input->{area_id}),
category => 'ZZ',
cobrand => $cobrand,
user => $user,
@@ -204,6 +239,8 @@ sub test_overrides {
$sr->add_body($body, $contact);
$sr->send( $row, $input->{extra} || {} );
+ my $new_extra = $row->get_extra_fields;
+ cmp_deeply $new_extra, $end_extra || [];
cmp_deeply (Open311->_get_test_data, $expected_data, 'Data as expected')
or diag Dumper( Open311->_get_test_data );
@@ -239,13 +276,6 @@ BEGIN {
sub _get_test_data { return +{ %data } }
sub _reset_test_data { %data = () }
- package FixMyStreet::DB::Result::Problem;
- use Class::Method::Modifiers; # is marked as immutable by Moose
- sub discard_changes {
- $data{discard_changes}++;
- # no need to actually discard, as we're in transaction anyway
- };
-
package FixMyStreet::DB::Result::Body;
use Class::Method::Modifiers; # is marked as immutable by Moose
around get_cobrand_handler => sub {
diff --git a/t/cobrand/bathnes.t b/t/cobrand/bathnes.t
index 6586dcb96..006dd757d 100644
--- a/t/cobrand/bathnes.t
+++ b/t/cobrand/bathnes.t
@@ -1,6 +1,10 @@
+use Test::MockModule;
use FixMyStreet::TestMech;
my $mech = FixMyStreet::TestMech->new;
+my $cobrand = Test::MockModule->new('FixMyStreet::Cobrand::BathNES');
+$cobrand->mock('area_types', sub { [ 'UTA' ] });
+
my $body = $mech->create_body_ok(2551, 'Bath and North East Somerset Council');
my @cats = ('Litter', 'Other', 'Potholes', 'Traffic lights');
for my $contact ( @cats ) {
@@ -11,7 +15,7 @@ my $counciluser = $mech->create_user_ok('counciluser@example.com', name => 'Coun
my $normaluser = $mech->create_user_ok('normaluser@example.com', name => 'Normal User');
$normaluser->update({ phone => "+447123456789" });
-$mech->create_problems_for_body(1, $body->id, 'Title', {
+my ($problem) = $mech->create_problems_for_body(1, $body->id, 'Title', {
areas => ",2651,", category => 'Potholes', cobrand => 'fixmystreet',
user => $normaluser, service => 'iOS', extra => {
_fields => [
@@ -59,6 +63,19 @@ subtest 'cobrand displays council name' => sub {
$mech->content_like( qr/Bath and North East Somerset\b/ );
};
+subtest 'check override contact display name' => sub {
+ $mech->log_in_ok( $superuser->email );
+ $mech->get_ok("/admin/body/" . $body->id . '/Litter');
+ $mech->content_contains('<h1>Litter</h1>');
+ $mech->content_contains('extra[display_name]');
+ $mech->submit_form_ok({ with_fields => {
+ 'extra[display_name]' => 'Wittering'
+ }});
+ $mech->get_ok('/reports/Bath+and+North+East+Somerset');
+ $mech->content_like(qr/Traffic lights<\/option>\s*<option value="Litter">\s*Wittering<\/option>/);
+ $mech->content_lacks('Litter</option>');
+};
+
subtest 'extra CSV columns are absent if permission not granted' => sub {
$mech->log_in_ok( $counciluser->email );
@@ -156,28 +173,28 @@ subtest 'extra CSV columns are present if permission granted' => sub {
is $rows[1]->[18], 'iOS', 'Site Used shows whether report made via app';
is $rows[1]->[19], '', 'Reported As is empty if not made on behalf of another user/body';
- is $rows[1]->[20], 'normaluser@example.com', 'User email is correct';
+ is $rows[1]->[20], $normaluser->email, 'User email is correct';
is $rows[1]->[21], '+447123456789', 'User phone number is correct';
is $rows[1]->[22], '', 'Staff User is empty if not made on behalf of another user';
is $rows[1]->[23], 'width = 10cm; depth = 25cm', 'Attribute Data is correct';
is $rows[2]->[18], 'bathnes', 'Site Used shows correct cobrand';
is $rows[2]->[19], 'body', 'Reported As is correct if made on behalf of body';
- is $rows[2]->[20], 'counciluser@example.com', 'User email is correct';
+ is $rows[2]->[20], $counciluser->email, 'User email is correct';
is $rows[2]->[21], '', 'User phone number is correct';
is $rows[2]->[22], '', 'Staff User is empty if not made on behalf of another user';
is $rows[2]->[23], '', 'Attribute Data is correct';
is $rows[3]->[18], 'bathnes', 'Site Used shows correct cobrand';
is $rows[3]->[19], 'another_user', 'Reported As is set if reported on behalf of another user';
- is $rows[3]->[20], 'normaluser@example.com', 'User email is correct';
+ is $rows[3]->[20], $normaluser->email, 'User email is correct';
is $rows[3]->[21], '+447123456789', 'User phone number is correct';
- is $rows[3]->[22], 'counciluser@example.com', 'Staff User is correct if made on behalf of another user';
+ is $rows[3]->[22], $counciluser->email, 'Staff User is correct if made on behalf of another user';
is $rows[3]->[23], '', 'Attribute Data is correct';
is $rows[4]->[18], 'bathnes', 'Site Used shows correct cobrand';
is $rows[4]->[19], 'anonymous_user', 'Reported As is set if reported on behalf of another user';
- is $rows[4]->[20], 'counciluser@example.com', 'User email is correct';
+ is $rows[4]->[20], $counciluser->email, 'User email is correct';
is $rows[4]->[21], '', 'User phone number is correct';
is $rows[4]->[22], '', 'Staff User is empty if not made on behalf of another user';
is $rows[4]->[23], '', 'Attribute Data is correct';
@@ -199,4 +216,17 @@ subtest 'extra CSV columns are present if permission granted' => sub {
};
+subtest 'check cobrand correctly reset on each request' => sub {
+ FixMyStreet::override_config {
+ 'ALLOWED_COBRANDS' => [ 'bathnes', 'fixmystreet' ],
+ }, sub {
+ $mech->log_in_ok( $superuser->email );
+ $mech->host('www.fixmystreet.com');
+ $mech->get_ok( '/contact?id=' . $problem->id );
+ $mech->host('bathnes.fixmystreet.com');
+ $mech->get_ok( '/contact?reject=1&id=' . $problem->id );
+ $mech->content_contains('Reject report');
+ }
+};
+
done_testing();
diff --git a/t/cobrand/bexley.t b/t/cobrand/bexley.t
new file mode 100644
index 000000000..352e61389
--- /dev/null
+++ b/t/cobrand/bexley.t
@@ -0,0 +1,281 @@
+use CGI::Simple;
+use Test::MockModule;
+use Test::MockTime qw(:all);
+use FixMyStreet::TestMech;
+use FixMyStreet::Script::Reports;
+use Catalyst::Test 'FixMyStreet::App';
+
+set_fixed_time('2019-10-16T17:00:00Z'); # Out of hours
+
+use_ok 'FixMyStreet::Cobrand::Bexley';
+use_ok 'FixMyStreet::Geocode::Bexley';
+
+my $ukc = Test::MockModule->new('FixMyStreet::Cobrand::UKCouncils');
+$ukc->mock('lookup_site_code', sub {
+ my ($self, $row, $buffer) = @_;
+ is $row->latitude, 51.408484, 'Correct latitude';
+ return "Road ID";
+});
+
+FixMyStreet::override_config {
+ COBRAND_FEATURES => {
+ contact_email => {
+ bexley => 'foo@bexley',
+ }
+ },
+}, sub {
+ my $cobrand = FixMyStreet::Cobrand::Bexley->new;
+ like $cobrand->contact_email, qr/bexley/;
+ is $cobrand->on_map_default_status, 'open';
+ is_deeply $cobrand->disambiguate_location->{bounds}, [ 51.408484, 0.074653, 51.515542, 0.2234676 ];
+};
+
+my $mech = FixMyStreet::TestMech->new;
+
+my $body = $mech->create_body_ok(2494, 'London Borough of Bexley', {
+ send_method => 'Open311', api_key => 'key', 'endpoint' => 'e', 'jurisdiction' => 'j' });
+$mech->create_contact_ok(body_id => $body->id, category => 'Abandoned and untaxed vehicles', email => "ConfirmABAN");
+$mech->create_contact_ok(body_id => $body->id, category => 'Lamp post', email => "StreetLightingLAMP");
+$mech->create_contact_ok(body_id => $body->id, category => 'Gulley covers', email => "GULL");
+$mech->create_contact_ok(body_id => $body->id, category => 'Damaged road', email => "ROAD");
+$mech->create_contact_ok(body_id => $body->id, category => 'Flooding in the road', email => "ConfirmFLOD");
+$mech->create_contact_ok(body_id => $body->id, category => 'Flytipping', email => "UniformFLY");
+$mech->create_contact_ok(body_id => $body->id, category => 'Dead animal', email => "ANIM");
+$mech->create_contact_ok(body_id => $body->id, category => 'Street cleaning and litter', email => "STREET");
+my $category = $mech->create_contact_ok(body_id => $body->id, category => 'Something dangerous', email => "DANG");
+$category->set_extra_metadata(group => 'Danger things');
+$category->update;
+
+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',
+ } } },
+}, sub {
+
+ subtest 'cobrand displays council name' => sub {
+ ok $mech->host("bexley.fixmystreet.com"), "change host to bexley";
+ $mech->get_ok('/');
+ $mech->content_contains('Bexley');
+ };
+
+ subtest 'cobrand displays council name' => sub {
+ $mech->get_ok('/reports/Bexley');
+ $mech->content_contains('Bexley');
+ };
+
+ my $report;
+ foreach my $test (
+ { category => 'Abandoned and untaxed vehicles', email => ['p1confirm'], code => 'ConfirmABAN',
+ extra => { 'name' => 'burnt', description => 'Was it burnt?', 'value' => 'Yes' } },
+ { category => 'Abandoned and untaxed vehicles', code => 'ConfirmABAN',
+ extra => { 'name' => 'burnt', description => 'Was it burnt?', 'value' => 'No' } },
+ { category => 'Dead animal', email => ['p1', 'outofhours', 'ooh2'], code => 'ANIM' },
+ { category => 'Something dangerous', email => ['p1', 'outofhours', 'ooh2'], code => 'DANG',
+ extra => { 'name' => 'dangerous', description => 'Was it dangerous?', 'value' => 'Yes' } },
+ { category => 'Something dangerous', code => 'DANG',
+ extra => { 'name' => 'dangerous', description => 'Was it dangerous?', 'value' => 'No' } },
+ { category => 'Street cleaning and litter', email => ['p1', 'outofhours', 'ooh2'], code => 'STREET',
+ extra => { 'name' => 'reportType', description => 'Type of report', 'value' => 'Oil spillage' } },
+ { category => 'Gulley covers', email => ['p1', 'outofhours', 'ooh2'], code => 'GULL',
+ extra => { 'name' => 'reportType', description => 'Type of report', 'value' => 'Cover missing' } },
+ { category => 'Gulley covers', code => 'GULL',
+ extra => { 'name' => 'reportType', description => 'Type of report', 'value' => 'Cover damaged' } },
+ { category => 'Gulley covers', email => ['p1', 'outofhours', 'ooh2'], code => 'GULL',
+ extra => { 'name' => 'dangerous', description => 'Was it dangerous?', 'value' => 'Yes' } },
+ { category => 'Damaged road', code => 'ROAD', email => ['p1', 'outofhours', 'ooh2'],
+ extra => { 'name' => 'dangerous', description => 'Was it dangerous?', 'value' => 'No' } },
+ { category => 'Damaged road', code => 'ROAD', email => ['p1', 'outofhours', 'ooh2'],
+ extra => { 'name' => 'dangerous', description => 'Was it dangerous?', 'value' => 'Yes' } },
+ { category => 'Lamp post', code => 'StreetLightingLAMP', email => ['thirdparty', 'another'],
+ extra => { 'name' => 'dangerous', description => 'Was it dangerous?', 'value' => 'No' } },
+ { category => 'Lamp post', code => 'StreetLightingLAMP', email => ['thirdparty', 'another'],
+ extra => { 'name' => 'dangerous', description => 'Was it dangerous?', 'value' => 'Yes' } },
+ { category => 'Flytipping', code => 'UniformFLY', email => ['eh'] },
+ { category => 'Flooding in the road', code => 'ConfirmFLOD', email => ['flooding'] },
+ ) {
+ ($report) = $mech->create_problems_for_body(1, $body->id, 'On Road', {
+ category => $test->{category}, cobrand => 'bexley',
+ latitude => 51.408484, longitude => 0.074653, areas => '2494',
+ });
+ if ($test->{extra}) {
+ $report->set_extra_fields(ref $test->{extra} eq 'ARRAY' ? @{$test->{extra}} : $test->{extra});
+ $report->update;
+ }
+
+ subtest 'NSGRef and correct email config' => sub {
+ 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'), $test->{code};
+ if ($test->{code} =~ /Confirm/) {
+ is $c->param('attribute[site_code]'), 'Road ID';
+ } elsif ($test->{code} =~ /Uniform/) {
+ is $c->param('attribute[uprn]'), 'Road ID';
+ } else {
+ is $c->param('attribute[NSGRef]'), 'Road ID';
+ }
+
+ if (my $t = $test->{email}) {
+ my $email = $mech->get_email;
+ $t = join('@[^@]*', @$t);
+ like $email->header('To'), qr/^[^@]*$t@[^@]*$/;
+ if ($test->{code} =~ /Confirm/) {
+ like $mech->get_text_body_from_email($email), qr/Site code: Road ID/;
+ } elsif ($test->{code} =~ /Uniform/) {
+ like $mech->get_text_body_from_email($email), qr/UPRN: Road ID/;
+ like $mech->get_text_body_from_email($email), qr/Uniform ID: 248/;
+ } else {
+ like $mech->get_text_body_from_email($email), qr/NSG Ref: Road ID/;
+ }
+ $mech->clear_emails_ok;
+ } else {
+ $mech->email_count_is(0);
+ }
+ };
+ }
+
+ subtest 'resend is disabled in admin' => sub {
+ my $user = $mech->log_in_ok('super@example.org');
+ $user->update({ from_body => $body, is_superuser => 1 });
+ $mech->get_ok('/admin/report_edit/' . $report->id);
+ $mech->content_contains('View report on site');
+ $mech->content_lacks('Resend report');
+ };
+
+ subtest "resending of reports by changing category" => sub {
+ $mech->get_ok('/admin/report_edit/' . $report->id);
+ $mech->submit_form_ok({ with_fields => { category => 'Damaged road' } });
+ 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'), 'ROAD', 'Report resent in new category';
+
+ $mech->submit_form_ok({ with_fields => { category => 'Gulley covers' } });
+ $test_data = FixMyStreet::Script::Reports::send();
+ is_deeply $test_data, {}, 'Report not resent';
+
+ $mech->submit_form_ok({ with_fields => { category => 'Lamp post' } });
+ $test_data = FixMyStreet::Script::Reports::send();
+ $req = $test_data->{test_req_used};
+ $c = CGI::Simple->new($req->content);
+ is $c->param('service_code'), 'StreetLightingLAMP', 'Report resent';
+ };
+
+ subtest 'extra CSV column present' => sub {
+ $mech->get_ok('/dashboard?export=1');
+ $mech->content_contains(',Category,Subcategory,');
+ $mech->content_contains('"Danger things","Something dangerous"');
+ };
+
+
+ subtest 'testing special Open311 behaviour', sub {
+ my @reports = $mech->create_problems_for_body( 1, $body->id, 'Test', {
+ category => 'Flooding in the road', cobrand => 'bexley',
+ latitude => 51.408484, longitude => 0.074653, areas => '2494',
+ photo => '74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg,74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg',
+ });
+ my $report = $reports[0];
+
+ my $test_data = FixMyStreet::Script::Reports::send();
+ $report->discard_changes;
+ ok $report->whensent, 'Report marked as sent';
+ is $report->send_method_used, 'Open311', 'Report sent via Open311';
+ is $report->external_id, 248, 'Report has right external ID';
+
+ my $req = $test_data->{test_req_used};
+ my $c = CGI::Simple->new($req->content);
+ is $c->param('attribute[title]'), 'Test Test 1 for ' . $body->id, 'Request had correct title';
+ is_deeply [ $c->param('media_url') ], [
+ 'http://bexley.example.org/photo/' . $report->id . '.0.full.jpeg?74e33622',
+ 'http://bexley.example.org/photo/' . $report->id . '.1.full.jpeg?74e33622',
+ ], 'Request had multiple photos';
+ };
+
+};
+
+subtest 'nearest road returns correct road' => sub {
+ my $cobrand = FixMyStreet::Cobrand::Bexley->new;
+ my $cfg = {
+ accept_feature => sub { 1 },
+ property => 'fid',
+ };
+ my $features = [
+ { geometry => { type => 'Polygon' } },
+ { geometry => { type => 'MultiLineString',
+ coordinates => [ [ [ 545499, 174361 ], [ 545420, 174359 ], [ 545321, 174352 ] ] ] },
+ properties => { fid => '20101226' } },
+ { geometry => { type => 'LineString',
+ coordinates => [ [ 545420, 174359 ], [ 545419, 174375 ], [ 545418, 174380 ], [ 545415, 174391 ] ] },
+ properties => { fid => '20100024' } },
+ ];
+ is $cobrand->_nearest_feature($cfg, 545451, 174380, $features), '20101226';
+};
+
+my $geo = Test::MockModule->new('FixMyStreet::Geocode');
+$geo->mock('cache', sub {
+ my $typ = shift;
+ return [] if $typ eq 'osm';
+ return {
+ features => [
+ {
+ properties => { ADDRESS => 'BRAMPTON ROAD', TOWN => 'BEXLEY' },
+ geometry => { type => 'LineString', coordinates => [ [ 1, 2 ], [ 3, 4] ] },
+ },
+ {
+ properties => { ADDRESS => 'FOOTPATH TO BRAMPTON ROAD', TOWN => 'BEXLEY' },
+ geometry => { type => 'MultiLineString', coordinates => [ [ [ 1, 2 ], [ 3, 4 ] ], [ [ 5, 6 ], [ 7, 8 ] ] ] },
+ },
+ ],
+ } if $typ eq 'bexley';
+});
+
+subtest 'geocoder' => sub {
+ my $c = ctx_request('/');
+ my $results = FixMyStreet::Geocode::Bexley->string("Brampton Road", $c);
+ is_deeply $results, { error => [
+ {
+ 'latitude' => '49.766844',
+ 'longitude' => '-7.557122',
+ 'address' => 'Brampton Road, Bexley'
+ }, {
+ 'address' => 'Footpath to Brampton Road, Bexley',
+ 'longitude' => '-7.557097',
+ 'latitude' => '49.766863'
+ }
+ ] };
+};
+
+my $bex = Test::MockModule->new('FixMyStreet::Cobrand::Bexley');
+$bex->mock('get', sub {
+ return <<EOF
+{
+ "england-and-wales": {
+ "events": [
+ { "date": "2019-12-25", "title": "Christmas Day", "notes": "", "bunting": true }
+ ]
+ }
+}
+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';
+ set_fixed_time('2019-10-16T04:00:00Z');
+ is $cobrand->_is_out_of_hours(), 1, 'out of hours early in the morning';
+ set_fixed_time('2019-10-13T12:00:00Z');
+ is $cobrand->_is_out_of_hours(), 1, 'out of hours at weekends';
+ set_fixed_time('2019-12-25T12:00:00Z');
+ is $cobrand->_is_out_of_hours(), 1, 'out of hours on bank holiday';
+};
+
+done_testing();
diff --git a/t/cobrand/bristol.t b/t/cobrand/bristol.t
index b2b8cff13..d4770b6ee 100644
--- a/t/cobrand/bristol.t
+++ b/t/cobrand/bristol.t
@@ -21,6 +21,16 @@ my $email_contact = $mech->create_contact_ok(
send_method => 'Email'
);
+subtest 'Reports page works with no reports', sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'bristol' ],
+ MAPIT_URL => 'http://mapit.uk/',
+ MAP_TYPE => 'Bristol',
+ }, sub {
+ $mech->get_ok("/reports");
+ };
+};
+
subtest 'Only Open311 categories are shown on Bristol cobrand', sub {
FixMyStreet::override_config {
ALLOWED_COBRANDS => [ 'bristol' ],
diff --git a/t/cobrand/bromley.t b/t/cobrand/bromley.t
index 6750d3183..71180cd3e 100644
--- a/t/cobrand/bromley.t
+++ b/t/cobrand/bromley.t
@@ -169,7 +169,7 @@ for my $test (
like $body, qr/This update will be sent to Bromley Council/i, "Email indicates problem will be sent to Bromley";
unlike $body, qr/Note that we do not send updates to/i, "Email does not say updates aren't sent to Bromley";
- my $unreg_user = FixMyStreet::App->model( 'DB::User' )->find( { email => 'unregistered@example.com' } );
+ my $unreg_user = FixMyStreet::DB->resultset('User')->find( { email => 'unregistered@example.com' } );
ok $unreg_user, 'found user';
@@ -233,10 +233,11 @@ subtest 'check heatmap page' => sub {
FixMyStreet::override_config {
ALLOWED_COBRANDS => 'bromley',
MAPIT_URL => 'http://mapit.uk/',
+ COBRAND_FEATURES => { category_groups => { bromley => 1 }, heatmap => { bromley => 1 } },
}, sub {
$mech->log_in_ok($user->email);
- $mech->get_ok('/about/heatmap?end_date=2018-12-31');
- $mech->get_ok('/about/heatmap?filter_category=RED&ajax=1');
+ $mech->get_ok('/dashboard/heatmap?end_date=2018-12-31');
+ $mech->get_ok('/dashboard/heatmap?filter_category=RED&ajax=1');
};
};
diff --git a/t/cobrand/bucks.t b/t/cobrand/bucks.t
index 965b90107..230a52f99 100644
--- a/t/cobrand/bucks.t
+++ b/t/cobrand/bucks.t
@@ -4,21 +4,38 @@ use FixMyStreet::Script::Reports;
my $mech = FixMyStreet::TestMech->new;
+# disable info logs for this test run
+FixMyStreet::App->log->disable('info');
+END { FixMyStreet::App->log->enable('info'); }
+
my $body = $mech->create_body_ok(2217, 'Buckinghamshire', {
- send_method => 'Open311', api_key => 'key', endpoint => 'endpoint', jurisdiction => 'fms' });
+ send_method => 'Open311', api_key => 'key', endpoint => 'endpoint', jurisdiction => 'fms', can_be_devolved => 1 });
my $counciluser = $mech->create_user_ok('counciluser@example.com', name => 'Council User', from_body => $body);
-
-$mech->create_contact_ok(body_id => $body->id, category => 'Flytipping', email => "FLY");
+my $publicuser = $mech->create_user_ok('fmsuser@example.org', name => 'Simon Neil');
+
+my $contact = $mech->create_contact_ok(body_id => $body->id, category => 'Flytipping', email => "FLY");
+$contact->set_extra_fields({
+ code => 'road-placement',
+ datatype => 'singlevaluelist',
+ description => 'Is the fly-tip located on',
+ order => 100,
+ required => 'true',
+ variable => 'true',
+ values => [
+ { key => 'road', name => 'The road' },
+ { key => 'off-road', name => 'Off the road/on a verge' },
+ ],
+});
+$contact->update;
$mech->create_contact_ok(body_id => $body->id, category => 'Potholes', email => "POT");
$mech->create_contact_ok(body_id => $body->id, category => 'Blocked drain', email => "DRA");
-
-my $district = $mech->create_body_ok(2257, 'Chiltern');
-$mech->create_contact_ok(body_id => $district->id, category => 'Flytipping', email => "flytipping\@chiltern");
-$mech->create_contact_ok(body_id => $district->id, category => 'Graffiti', email => "graffiti\@chiltern");
+$mech->create_contact_ok(body_id => $body->id, category => 'Car Parks', email => "car\@chiltern", send_method => 'Email');
+$mech->create_contact_ok(body_id => $body->id, category => 'Graffiti', email => "graffiti\@chiltern", send_method => 'Email');
+$mech->create_contact_ok(body_id => $body->id, category => 'Flytipping (off-road)', email => "districts_flytipping", send_method => 'Email');
my $cobrand = Test::MockModule->new('FixMyStreet::Cobrand::Buckinghamshire');
$cobrand->mock('lookup_site_code', sub {
- my ($self, $row, $buffer) = @_;
+ my ($self, $row) = @_;
return "Road ID" if $row->latitude == 51.812244;
});
@@ -26,6 +43,21 @@ FixMyStreet::override_config {
ALLOWED_COBRANDS => [ 'buckinghamshire', 'fixmystreet' ],
MAPIT_URL => 'http://mapit.uk/',
STAGING_FLAGS => { send_reports => 1, skip_checks => 0 },
+ COBRAND_FEATURES => {
+ open311_email => {
+ buckinghamshire => {
+ flytipping => 'flytipping@example.org',
+ flood => 'floods@example.org',
+ }
+ },
+ borough_email_addresses => {
+ buckinghamshire => {
+ districts_flytipping => [
+ { email => "flytipping\@chiltern", areas => [ 2257 ] },
+ ]
+ }
+ }
+ }
}, sub {
subtest 'cobrand displays council name' => sub {
@@ -36,24 +68,26 @@ subtest 'cobrand displays council name' => sub {
subtest 'cobrand displays correct categories' => sub {
my $json = $mech->get_ok_json('/report/new/ajax?latitude=51.615559&longitude=-0.556903');
- is @{$json->{bodies}}, 2, 'Both Chiltern and Bucks returned';
+ is @{$json->{bodies}}, 1, 'Bucks returned';
+ like $json->{category}, qr/Car Parks/, 'Car Parks displayed';
like $json->{category}, qr/Flytipping/, 'Flytipping displayed';
like $json->{category}, qr/Blocked drain/, 'Blocked drain displayed';
- unlike $json->{category}, qr/Graffiti/, 'Graffiti not displayed';
+ like $json->{category}, qr/Graffiti/, 'Graffiti displayed';
+ unlike $json->{category}, qr/Flytipping \(off-road\)/, 'Flytipping (off-road) not displayed';
$json = $mech->get_ok_json('/report/new/category_extras?latitude=51.615559&longitude=-0.556903');
- is @{$json->{bodies}}, 2, 'Still both Chiltern and Bucks returned';
+ is @{$json->{bodies}}, 1, 'Still Bucks returned';
};
my ($report) = $mech->create_problems_for_body(1, $body->id, 'On Road', {
category => 'Flytipping', cobrand => 'fixmystreet',
latitude => 51.812244, longitude => -0.827363,
+ dt => DateTime->now()->subtract(minutes => 10),
});
subtest 'flytipping on road sent to extra email' => sub {
FixMyStreet::Script::Reports::send();
my @email = $mech->get_email;
- my $tfb = join('', 'illegaldumpingcosts', '@', 'buckscc.gov.uk');
- is $email[0]->header('To'), '"TfB" <' . $tfb . '>';
+ is $email[0]->header('To'), 'TfB <flytipping@example.org>';
like $mech->get_text_body_from_email($email[1]), qr/report's reference number/;
$report->discard_changes;
is $report->external_id, 248, 'Report has right external ID';
@@ -66,6 +100,7 @@ subtest 'flytipping on road sent to extra email' => sub {
contributed_as => 'another_user',
contributed_by => $counciluser->id,
},
+ dt => DateTime->now()->subtract(minutes => 9),
});
subtest 'pothole on road not sent to extra email, only confirm sent' => sub {
@@ -77,58 +112,50 @@ subtest 'pothole on road not sent to extra email, only confirm sent' => sub {
is $report->external_id, 248, 'Report has right external ID';
};
-($report) = $mech->create_problems_for_body(1, $district->id, 'Off Road', {
- category => 'Flytipping', cobrand => 'buckinghamshire',
- latitude => 51.813173, longitude => -0.826741,
-});
-subtest 'flytipping off road sent to extra email' => sub {
+
+# 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);
+ $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('Your issue is on its way to the council.');
+ 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';
+
+ $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
my @email = $mech->get_email;
- is $email[0]->header('To'), '"Chiltern" <flytipping@chiltern>';
- like $mech->get_text_body_from_email($email[1]), qr/Please note that Buckinghamshire County Council is not responsible/;
- $report->discard_changes;
- is $report->external_id, undef, 'Report has right external ID';
+ is $email[0]->header('To'), 'Buckinghamshire <flytipping@chiltern>';
};
my ($report2) = $mech->create_problems_for_body(1, $body->id, 'Drainage problem', {
category => 'Blocked drain', cobrand => 'fixmystreet',
latitude => 51.812244, longitude => -0.827363,
+ dt => DateTime->now()->subtract(minutes => 8),
});
subtest 'blocked drain sent to extra email' => sub {
$mech->clear_emails_ok;
FixMyStreet::Script::Reports::send();
my @email = $mech->get_email;
- my $e = join('@', 'floodmanagement', 'buckscc.gov.uk');
- is $email[0]->header('To'), '"Flood Management" <' . $e . '>';
+ is $email[0]->header('To'), '"Flood Management" <floods@example.org>';
like $mech->get_text_body_from_email($email[1]), qr/report's reference number/;
};
$cobrand = FixMyStreet::Cobrand::Buckinghamshire->new();
-subtest 'Flytipping extra question used if necessary' => sub {
- my $errors = { 'road-placement' => 'This field is required' };
-
- $report->update({ bodies_str => $body->id });
- $cobrand->flytipping_body_fix($report, 'road', $errors);
- is $errors->{'road-placement'}, 'This field is required', 'Error stays if sent to county';
-
- $report->update({ bodies_str => $district->id });
- $report->discard_changes; # As e.g. ->bodies has been remembered.
- $cobrand->flytipping_body_fix($report, 'road', $errors);
- is $errors->{'road-placement'}, undef, 'Error removed if sent to district';
-
- $report->update({ bodies_str => $body->id . ',' . $district->id });
- $report->discard_changes; # As e.g. ->bodies has been remembered.
- $cobrand->flytipping_body_fix($report, 'road', $errors);
- is $report->bodies_str, $body->id, 'Sent to both becomes sent to county on-road';
-
- $report->update({ bodies_str => $district->id . ',' . $body->id });
- $report->discard_changes; # As e.g. ->bodies has been remembered.
- $cobrand->flytipping_body_fix($report, 'off-road', $errors);
- is $report->bodies_str, $district->id, 'Sent to both becomes sent to district off-road';
-};
-
for my $test (
{
desc => 'filters basic emails',
diff --git a/t/cobrand/cheshireeast.t b/t/cobrand/cheshireeast.t
new file mode 100644
index 000000000..4924a96ee
--- /dev/null
+++ b/t/cobrand/cheshireeast.t
@@ -0,0 +1,129 @@
+use CGI::Simple;
+use Test::MockModule;
+use FixMyStreet::TestMech;
+use FixMyStreet::Script::Alerts;
+use FixMyStreet::Script::Reports;
+
+FixMyStreet::App->log->disable('info');
+END { FixMyStreet::App->log->enable('info'); }
+
+my $mech = FixMyStreet::TestMech->new;
+
+my $body = $mech->create_body_ok( 21069, 'Cheshire East Council', {
+ send_method => 'Open311',
+ endpoint => 'endpoint',
+ api_key => 'key',
+ jurisdiction => 'cheshireeast_confirm',
+});
+
+my $contact = $mech->create_contact_ok(
+ body_id => $body->id,
+ category => 'Zebra Crossing',
+ email => 'ZEBRA',
+);
+
+my $cobrand = Test::MockModule->new('FixMyStreet::Cobrand::CheshireEast');
+$cobrand->mock('_fetch_features', sub {
+ return [];
+});
+
+use_ok 'FixMyStreet::Cobrand::CheshireEast';
+
+FixMyStreet::override_config {
+ COBRAND_FEATURES => {
+ contact_email => {
+ cheshireeast => 'foo@cheshireeast',
+ }
+ },
+}, sub {
+ my $cobrand = FixMyStreet::Cobrand::CheshireEast->new;
+ like $cobrand->contact_email, qr/cheshireeast/;
+ is_deeply $cobrand->disambiguate_location->{bounds}, [ 52.947150, -2.752929, 53.387445, -1.974789 ];
+};
+
+my @reports = $mech->create_problems_for_body( 1, $body->id, 'Test', {
+ category => 'Zebra Crossing',
+ photo => '74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg,74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg',
+});
+my $report = $reports[0];
+
+my $alert = FixMyStreet::DB->resultset("Alert")->create({
+ alert_type => 'new_updates',
+ cobrand => 'cheshireeast',
+ parameter => $report->id,
+ user => {
+ email => 'alert@example.com',
+ email_verified => 1,
+ },
+});
+$alert->confirm;
+
+$mech->create_comment_for_problem($report, $report->user, $report->name, 'blah', 0, 'confirmed', 'confirmed', {
+ confirmed => \'current_timestamp'
+});
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'cheshireeast',
+ MAPIT_URL => 'http://mapit.uk/',
+ STAGING_FLAGS => { skip_checks => 1, send_reports => 1 },
+}, sub {
+
+ subtest 'cobrand displays council name' => sub {
+ ok $mech->host("cheshireeast.fixmystreet.com"), "change host to cheshireeast";
+ $mech->get_ok('/');
+ $mech->content_contains('Cheshire East');
+ };
+
+ subtest 'testing special Open311 behaviour', sub {
+ my $test_data = FixMyStreet::Script::Reports::send();
+ $report->discard_changes;
+ ok $report->whensent, 'Report marked as sent';
+ is $report->send_method_used, 'Open311', 'Report sent via Open311';
+ is $report->external_id, 248, 'Report has right external ID';
+
+ my $req = $test_data->{test_req_used};
+ my $c = CGI::Simple->new($req->content);
+ is $c->param('attribute[title]'), 'Test Test 1 for ' . $body->id, 'Request had correct title';
+ is_deeply [ $c->param('media_url') ], [
+ 'http://www.example.org/photo/' . $report->id . '.0.full.jpeg?74e33622',
+ 'http://www.example.org/photo/' . $report->id . '.1.full.jpeg?74e33622',
+ ], 'Request had multiple photos';
+
+ };
+
+ subtest 'testing reference numbers shown' => sub {
+ $mech->get_ok('/report/' . $report->id);
+ $mech->content_contains('Council ref:&nbsp;' . $report->id);
+ FixMyStreet::Script::Alerts::send();
+ like $mech->get_text_body_from_email, qr/reference number is @{[$report->id]}/;
+ };
+
+ subtest 'contact page blocked', sub {
+ $mech->get('/contact');
+ is $mech->res->code, 404;
+ };
+
+ subtest 'check post-submission message', sub {
+ $mech->log_in_ok($report->user->email);
+ $mech->get_ok('/report/new?latitude=53.145324&longitude=-2.370437');
+ $mech->submit_form_ok({ with_fields => {
+ title => 'title',
+ detail => 'detail',
+ }});
+ my $report = FixMyStreet::DB->resultset('Problem')->search(undef, { order_by => { -desc => 'id' } })->first;
+ my $report_id = $report->id;
+ $mech->content_contains('0300 123 5020');
+ $mech->content_like(qr/quoting your reference number $report_id/);
+ };
+
+ subtest 'checking alert pages', sub {
+ $mech->get_ok('/alert');
+ $mech->content_contains('all reported problems');
+ $mech->submit_form_ok({ with_fields => { pc => 'CW11 1HZ' } });
+ $mech->content_contains('Reported problems within 10.0km');
+ $mech->content_contains('All reported problems');
+ $mech->content_contains('Reported problems within Sandbach Town');
+ };
+};
+
+done_testing();
diff --git a/t/cobrand/councils.t b/t/cobrand/councils.t
index c44605bd9..aac682b19 100644
--- a/t/cobrand/councils.t
+++ b/t/cobrand/councils.t
@@ -47,4 +47,72 @@ foreach my $test (
};
+subtest "Test update shown/not shown appropriately" => sub {
+ my $user = $mech->create_user_ok('test@example.com');
+ foreach my $cobrand ('oxfordshire', 'fixmystreet') {
+ foreach my $test (
+ # Three bools are logged out, reporter, staff user
+ { type => 'none', update => [0,0,0] },
+ { type => 'staff', update => [0,0,1] },
+ { type => 'reporter', update => [0,1,1] },
+ { type => 'reporter-open', state => 'closed', update => [0,0,0] },
+ { type => 'reporter-open', state => 'in progress', update => [0,1,1] },
+ { type => 'open', state => 'closed', update => [0,0,0] },
+ { type => 'open', state => 'in progress', update => [1,1,1] },
+ ) {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => $cobrand,
+ MAPIT_URL => 'http://mapit.uk/',
+ COBRAND_FEATURES => {
+ updates_allowed => {
+ oxfordshire => $test->{type},
+ fixmystreet => {
+ Oxfordshire => $test->{type},
+ }
+ }
+ },
+ }, sub {
+ subtest "$cobrand, $test->{type}" => sub {
+ $report->update({ state => $test->{state} || 'confirmed' });
+ $mech->log_out_ok;
+ $user->update({ from_body => undef });
+ $mech->get_ok("/report/$report_id");
+ $mech->contains_or_lacks($test->{update}[0], 'Provide an update');
+ $mech->log_in_ok('test@example.com');
+ $mech->get_ok("/report/$report_id");
+ $mech->contains_or_lacks($test->{update}[1], 'Provide an update');
+ $user->update({ from_body => $oxon->id });
+ $mech->get_ok("/report/$report_id");
+ $mech->contains_or_lacks($test->{update}[2], 'Provide an update');
+ };
+ };
+ }
+ }
+};
+
+subtest "CSP header from feature" => sub {
+ foreach my $cobrand (
+ { moniker => 'oxfordshire', test => 'oxon.analytics.example.org' },
+ { moniker =>'fixmystreet', test => '' },
+ { moniker => 'nonsecure', test => undef },
+ ) {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => $cobrand->{moniker},
+ COBRAND_FEATURES => {
+ content_security_policy => {
+ oxfordshire => 'oxon.analytics.example.org',
+ fixmystreet => 1,
+ }
+ },
+ }, sub {
+ $mech->get_ok("/");
+ if (defined $cobrand->{test}) {
+ like $mech->res->header('Content-Security-Policy'), qr/script-src 'self' 'unsafe-inline' 'nonce-[^']*' $cobrand->{test}/;
+ } else {
+ is $mech->res->header('Content-Security-Policy'), undef;
+ }
+ };
+ }
+};
+
done_testing();
diff --git a/t/cobrand/eastsussex.t b/t/cobrand/eastsussex.t
new file mode 100644
index 000000000..13383d44c
--- /dev/null
+++ b/t/cobrand/eastsussex.t
@@ -0,0 +1,42 @@
+use FixMyStreet::TestMech;
+use FixMyStreet::Script::Reports;
+use CGI::Simple;
+
+my $mech = FixMyStreet::TestMech->new;
+
+my $body = $mech->create_body_ok(2224, 'East Sussex Council',
+ { send_method => 'Open311', api_key => 'KEY', endpoint => 'endpoint', jurisdiction => 'eastsussex' });
+my $contact = $mech->create_contact_ok(body => $body, category => 'Pothole', email => 'POTHOLE');
+$contact->set_extra_fields(
+ { code => 'urgent', description => 'Is it urgent?', variable => 'true' },
+ { code => 'notice', description => 'This is a notice', variable => 'false' });
+$contact->update;
+my ($p) = $mech->create_problems_for_body(1, $body->id, 'East Sussex report', { category => 'Pothole' });
+$p->set_extra_fields({ name => 'urgent', value => 'no'});
+$p->update;
+
+subtest 'Check special Open311 request handling', sub {
+ my $orig_detail = $p->detail;
+ my $test_data;
+ FixMyStreet::override_config {
+ STAGING_FLAGS => { send_reports => 1 },
+ ALLOWED_COBRANDS => 'eastsussex',
+ BASE_URL => 'https://www.fixmystreet.com',
+ }, sub {
+ $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';
+ is $p->detail, $orig_detail, 'Detail in database not changed';
+
+ my $req = $test_data->{test_req_used};
+ my $c = CGI::Simple->new($req->content);
+ my $expected = join "\r\n", $p->title, '', $p->detail, '',
+ 'Is it urgent?', 'no', '', "https://www.fixmystreet.com" . $p->url, '';
+ is $c->param('description'), $expected, 'Correct description, with extra question and no notice text';
+};
+
+done_testing;
diff --git a/t/cobrand/features.t b/t/cobrand/features.t
new file mode 100644
index 000000000..45ea6336d
--- /dev/null
+++ b/t/cobrand/features.t
@@ -0,0 +1,20 @@
+use FixMyStreet::Test;
+use FixMyStreet::Cobrand;
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => ['bromley'],
+ COBRAND_FEATURES => {
+ foo => { tester => 1 },
+ bar => { default => 1 },
+ suggest_duplicates => { bromley => 1 },
+ }
+}, sub {
+ my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker('default')->new;
+ my $bromley = FixMyStreet::Cobrand->get_class_for_moniker('bromley')->new;
+
+ is $cobrand->feature('foo'), undef;
+ is $cobrand->feature('bar'), 1;
+ is $bromley->suggest_duplicates, 1;
+};
+
+done_testing();
diff --git a/t/cobrand/fixmystreet.t b/t/cobrand/fixmystreet.t
index b47269db4..a54e782f2 100644
--- a/t/cobrand/fixmystreet.t
+++ b/t/cobrand/fixmystreet.t
@@ -1,8 +1,13 @@
+use utf8;
use FixMyStreet::Script::UpdateAllReports;
+use Test::MockModule;
use FixMyStreet::TestMech;
my $mech = FixMyStreet::TestMech->new;
+my $resolver = Test::MockModule->new('Email::Valid');
+$resolver->mock('address', sub { $_[1] });
+
my $body = $mech->create_body_ok( 2514, 'Birmingham' );
my $contact = $mech->create_contact_ok(
@@ -53,7 +58,7 @@ FixMyStreet::override_config {
subtest 'check marketing dashboard csv' => sub {
$mech->log_in_ok('someone@birmingham.gov.uk');
- $mech->create_problems_for_body(105, $body->id, 'Title', {
+ $mech->create_problems_for_body(105, $body->id, 'Titlē', {
detail => "this report\nis split across\nseveral lines",
areas => ",2514,",
});
@@ -80,7 +85,7 @@ FixMyStreet::override_config {
'Column headers look correct';
my $body_id = $body->id;
- like $rows[1]->[1], qr/Title Test \d+ for $body_id/, 'problem title correct';
+ like $rows[1]->[1], qr/Titlē Test \d+ for $body_id/, 'problem title correct';
};
subtest 'check marketing dashboard contact listings' => sub {
@@ -106,6 +111,22 @@ FixMyStreet::override_config {
};
};
-END {
- done_testing();
-}
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'fixmystreet',
+}, sub {
+ subtest 'test enforced 2FA for superusers' => sub {
+ my $test_email = 'test@example.com';
+ my $user = FixMyStreet::DB->resultset('User')->find_or_create({ email => $test_email });
+ $user->password('password');
+ $user->is_superuser(1);
+ $user->update;
+
+ $mech->get_ok('/auth');
+ $mech->submit_form_ok(
+ { with_fields => { username => $test_email, password_sign_in => 'password' } },
+ "sign in using form" );
+ $mech->content_contains('requires two-factor');
+ };
+};
+
+done_testing();
diff --git a/t/cobrand/form_extras.t b/t/cobrand/form_extras.t
index df76ccbe1..3807dd56a 100644
--- a/t/cobrand/form_extras.t
+++ b/t/cobrand/form_extras.t
@@ -84,7 +84,7 @@ FixMyStreet::override_config {
);
$mech->content_contains('Now check your email');
- my $problem = FixMyStreet::DB->resultset('Problem')->search({}, { order_by => '-id' })->first;
+ my $problem = FixMyStreet::DB->resultset('Problem')->search({}, { order_by => { -desc => 'id' } })->first;
is $problem->get_extra_metadata('address'), 'My address', 'Address is stored';
is $problem->get_extra_metadata('passport'), 'P123456', 'Passport number is stored';
};
diff --git a/t/cobrand/greenwich.t b/t/cobrand/greenwich.t
index e6aaca973..14ddba9be 100644
--- a/t/cobrand/greenwich.t
+++ b/t/cobrand/greenwich.t
@@ -5,7 +5,7 @@ use Open311::PopulateServiceList;
my $mech = FixMyStreet::TestMech->new;
-my $body = $mech->create_body_ok( 2493, 'Greenwich Council', {
+my $body = $mech->create_body_ok( 2493, 'Royal Borough of Greenwich', {
send_method => 'Open311',
endpoint => 'endpoint',
api_key => 'key',
@@ -110,5 +110,26 @@ subtest 'testing special Open311 behaviour', sub {
is $c->param('attribute[easting]'), 529025, 'Request had correct easting';
};
-done_testing();
+subtest 'RSS feed on .com' => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'fixmystreet',
+ MAPIT_TYPES => ['GRE'],
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $mech->get_ok('/rss/reports/Greenwich');
+ is $mech->uri->path, '/rss/reports/Greenwich';
+ };
+};
+subtest 'RSS feed on Greenwich' => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'greenwich',
+ MAPIT_TYPES => ['GRE'],
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $mech->get_ok('/rss/reports/Greenwich');
+ is $mech->uri->path, '/rss/reports/Greenwich';
+ };
+};
+
+done_testing();
diff --git a/t/cobrand/highwaysengland.t b/t/cobrand/highwaysengland.t
new file mode 100644
index 000000000..f6400ea7c
--- /dev/null
+++ b/t/cobrand/highwaysengland.t
@@ -0,0 +1,70 @@
+use FixMyStreet::TestMech;
+use FixMyStreet::App;
+use FixMyStreet::Script::Reports;
+use FixMyStreet::Cobrand::HighwaysEngland;
+use HighwaysEngland;
+use Test::MockModule;
+
+my $he_mock = Test::MockModule->new('HighwaysEngland');
+$he_mock->mock('database_file', sub { FixMyStreet->path_to('t/geocode/roads.sqlite'); });
+
+# disable info logs for this test run
+FixMyStreet::App->log->disable('info');
+END { FixMyStreet::App->log->enable('info'); }
+
+
+my $he_mock_cobrand = Test::MockModule->new('FixMyStreet::Cobrand::HighwaysEngland');
+$he_mock_cobrand->mock('anonymous_account', sub { { email => 'anoncategory@example.org', name => 'Anonymous Category' } });
+
+my $he = FixMyStreet::Cobrand::HighwaysEngland->new();
+
+my $r = $he->geocode_postcode('M1');
+ok $r->{error}, "searching for road only generates error";
+
+$r = $he->geocode_postcode('m1');
+ok $r->{error}, "searching for lowecase road only generates error";
+
+my $mech = FixMyStreet::TestMech->new;
+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 {
+ $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, },
+ "follow 'skip this step' link" );
+ $mech->submit_form_ok(
+ {
+ button => 'report_anonymously',
+ with_fields => {
+ title => "Test Report for HE",
+ detail => 'Test report details.',
+ category => 'Pothole',
+ where_hear => 'Facebook',
+ }
+ },
+ "submit good details"
+ );
+ $mech->content_contains('Thank you');
+
+ my $report = FixMyStreet::DB->resultset("Problem")->first;
+ ok $report, "Found the report";
+ is $report->get_extra_metadata('where_hear'), 'Facebook', 'saved where hear';
+
+ $mech->clear_emails_ok;
+ FixMyStreet::Script::Reports::send();
+ $mech->email_count_is(1);
+ my $email = $mech->get_email;
+ like $mech->get_text_body_from_email($email), qr/Heard from: Facebook/, 'where hear included in email'
+
+ };
+};
+
+
+done_testing();
diff --git a/t/cobrand/hounslow.t b/t/cobrand/hounslow.t
new file mode 100644
index 000000000..91c1cb455
--- /dev/null
+++ b/t/cobrand/hounslow.t
@@ -0,0 +1,101 @@
+use FixMyStreet::TestMech;
+
+ok( my $mech = FixMyStreet::TestMech->new, 'Created mech object' );
+
+my $hounslow_id = $mech->create_body_ok(2483, 'Hounslow Borough Council')->id;
+$mech->create_contact_ok(
+ body_id => $hounslow_id,
+ category => 'Potholes',
+ email => 'pothole@example.org',
+);
+
+my $user = $mech->create_user_ok('staff@example.org', from_body => $hounslow_id);
+$user->user_body_permissions->create({ body_id => $hounslow_id, permission_type => 'user_edit' });
+
+my $tfl = $mech->create_body_ok( 2483, 'TfL');
+$mech->create_contact_ok(
+ body_id => $tfl->id,
+ category => 'Traffic lights',
+ email => 'tfl@example.org',
+);
+
+$mech->create_problems_for_body(1, $hounslow_id, 'An old problem made before Hounslow FMS launched', {
+ confirmed => '2018-12-25 09:00',
+ lastupdate => '2018-12-25 09:00',
+ latitude => 51.482286,
+ longitude => -0.328163,
+
+});
+$mech->create_problems_for_body(1, $hounslow_id, 'A brand new problem made on the Hounslow site', {
+ latitude => 51.482286,
+ longitude => -0.328163,
+ cobrand => 'hounslow'
+});
+my ($report) = $mech->create_problems_for_body(1, $hounslow_id, 'A brand new problem made on fixmystreet.com', {
+ latitude => 51.482286,
+ longitude => -0.328163,
+ external_id => 'ABC123',
+ cobrand => 'fixmystreet'
+});
+
+subtest "it still shows old reports on fixmystreet.com" => sub {
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => 'fixmystreet',
+ }, sub {
+ $mech->get_ok('/reports/Hounslow');
+
+ $mech->content_contains('An old problem made before Hounslow FMS launched');
+ $mech->content_contains('A brand new problem made on the Hounslow site');
+ $mech->content_contains('A brand new problem made on fixmystreet.com');
+ };
+};
+
+subtest "it does not show old reports on Hounslow" => sub {
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => 'hounslow',
+ }, sub {
+ $mech->get_ok('/reports/Hounslow');
+ $mech->content_lacks('An old problem made before Hounslow FMS launched');
+ $mech->content_contains('A brand new problem made on the Hounslow site') or diag $mech->content;
+ $mech->content_contains('A brand new problem made on fixmystreet.com');
+ };
+};
+
+subtest "it shows the right things on an /around page" => sub {
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => 'hounslow',
+ }, sub {
+ $mech->get_ok('/around?pc=TW7+5JN');
+ $mech->content_lacks('An old problem made before Hounslow FMS launched');
+ $mech->content_contains('A brand new problem made on the Hounslow site') or diag $mech->content;
+ $mech->content_contains('A brand new problem made on fixmystreet.com');
+ };
+};
+
+subtest "Shows external ID on report page to staff users only" => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'hounslow',
+ }, sub {
+ $mech->get_ok('/report/' . $report->id);
+ $mech->content_lacks('ABC123');
+ $mech->log_in_ok('staff@example.org');
+ $mech->get_ok('/report/' . $report->id);
+ $mech->content_contains('ABC123');
+ };
+};
+
+subtest "Admin searches right domains" => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'hounslow',
+ }, sub {
+ foreach ('hounslowhighways.org', 'hounslow.gov.uk') {
+ $mech->get_ok('/admin/users?search=xyz@' . $_);
+ $mech->content_contains('xyz@' . $_);
+ }
+ };
+};
+
+done_testing();
diff --git a/t/cobrand/isleofwight.t b/t/cobrand/isleofwight.t
new file mode 100644
index 000000000..3cac710da
--- /dev/null
+++ b/t/cobrand/isleofwight.t
@@ -0,0 +1,628 @@
+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'); }
+
+my $cobrand = Test::MockModule->new('FixMyStreet::Cobrand::IsleOfWight');
+$cobrand->mock('lookup_site_code', sub {
+ my ($self, $row) = @_;
+ return "Road ID" if $row->latitude == 50.7108;
+});
+
+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 $isleofwight = $mech->create_body_ok(2636, 'Isle of Wight Council', $params);
+my $contact = $mech->create_contact_ok(
+ body_id => $isleofwight->id,
+ category => 'Potholes',
+ 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 $iow_user = $mech->create_user_ok('iow_user@example.org', name => 'IoW User', from_body => $isleofwight);
+$iow_user->user_body_permissions->create({
+ body => $isleofwight,
+ permission_type => 'moderate',
+});
+
+my $contact2 = $mech->create_contact_ok(
+ body_id => $isleofwight->id,
+ category => 'Roads',
+ email => 'roads@example.org',
+ send_method => 'Triage',
+);
+
+my $admin_user = $mech->create_user_ok('admin-user@example.org', name => 'Admin User', from_body => $isleofwight);
+
+$admin_user->user_body_permissions->create({
+ body => $isleofwight,
+ permission_type => 'triage'
+});
+
+my @reports = $mech->create_problems_for_body(1, $isleofwight->id, 'An Isle of wight report', {
+ confirmed => '2019-10-25 09:00',
+ lastupdate => '2019-10-25 09:00',
+ latitude => 50.7108,
+ longitude => -1.29573,
+ user => $user,
+ external_id => 101202303
+});
+
+subtest "check clicking all reports link" => sub {
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => 'isleofwight',
+ }, sub {
+ $mech->get_ok('/');
+ $mech->follow_link_ok({ text => 'All reports' });
+ };
+
+ $mech->content_contains("An Isle of wight report", "Isle of Wight report there");
+ $mech->content_contains("Island Roads", "is still on cobrand");
+};
+
+subtest "use external id for reference number" => sub {
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => 'isleofwight',
+ }, sub {
+ $mech->get_ok('/report/' . $reports[0]->id);
+ };
+
+ $mech->content_contains("101202303", "Display external id as reference number");
+};
+
+subtest "only original reporter can comment" => sub {
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => 'isleofwight',
+ COBRAND_FEATURES => { updates_allowed => { isleofwight => 'reporter' } },
+ }, sub {
+ $mech->get_ok('/report/' . $reports[0]->id);
+ $mech->content_contains('Only the original reporter may leave updates');
+
+ $mech->log_in_ok('user@example.org');
+ $mech->get_ok('/report/' . $reports[0]->id);
+ $mech->content_lacks('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');
+ $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 Island Roads/);
+ };
+};
+
+subtest "front page summary uses report category not title" => sub {
+ my $category = $reports[0]->category;
+ ok $category, "category is not blank";
+ my $title = $reports[0]->title;
+ ok $title, "title is not blank";
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => ['isleofwight'],
+ }, sub {
+ $mech->log_out_ok;
+ $mech->get_ok('/');
+ $mech->content_like( qr/item-list__heading">$category/ );
+ $mech->content_unlike( qr/item-list__heading">$title/ );
+ };
+};
+
+$_->delete for @reports;
+
+my $system_user = $mech->create_user_ok('system_user@example.org');
+
+for my $status ( qw/ CLOSED FIXED DUPLICATE NOT_COUNCILS_RESPONSIBILITY NO_FURTHER_ACTION / ) {
+ subtest "updates which mark report as $status close it to comments" => sub {
+ my $dt = DateTime->now(formatter => DateTime::Format::W3CDTF->new)->add( minutes => -5 );
+ my ($p) = $mech->create_problems_for_body(1, $isleofwight->id, '', { lastupdate => $dt });
+ $p->update({ external_id => $p->id });
+
+ my $requests_xml = qq{<?xml version="1.0" encoding="utf-8"?>
+ <service_requests_updates>
+ <request_update>
+ <update_id>UPDATE_ID</update_id>
+ <service_request_id>SERVICE_ID</service_request_id>
+ <service_request_id_ext>ID_EXTERNAL</service_request_id_ext>
+ <status>STATUS</status>
+ <description>This is a note</description>
+ <updated_datetime>UPDATED_DATETIME</updated_datetime>
+ </request_update>
+ </service_requests_updates>
+ };
+
+ my $update_dt = DateTime->now(formatter => DateTime::Format::W3CDTF->new);
+
+ $requests_xml =~ s/STATUS/$status/;
+ $requests_xml =~ s/UPDATE_ID/@{[$p->id]}/;
+ $requests_xml =~ s/SERVICE_ID/@{[$p->id]}/;
+ $requests_xml =~ s/ID_EXTERNAL/@{[$p->id]}/;
+ $requests_xml =~ s/UPDATED_DATETIME/$update_dt/;
+
+ my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'servicerequestupdates.xml' => $requests_xml } );
+
+ my $update = Open311::GetServiceRequestUpdates->new(
+ system_user => $system_user,
+ current_open311 => $o,
+ current_body => $isleofwight,
+ );
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'isleofwight',
+ }, sub {
+ $update->process_body;
+ };
+
+ $mech->log_in_ok('user@example.org');
+ $mech->get_ok('/report/' . $p->id);
+ $mech->content_lacks('Provide an update', "No update form on report");
+
+ $p->discard_changes;
+ is $p->get_extra_metadata('closed_updates'), 1, "report closed to updates";
+ $p->comments->delete;
+ $p->delete;
+ };
+}
+
+subtest "fetched requests do not use the description text" => sub {
+ my $requests_xml = qq{<?xml version="1.0" encoding="utf-8"?>
+ <service_requests>
+ <request>
+ <service_request_id>638344</service_request_id>
+ <status>open</status>
+ <status_notes>This is a note.</status_notes>
+ <service_name>Potholes</service_name>
+ <service_code>potholes\@example.org</service_code>
+ <description>This the description of a pothole problem</description>
+ <agency_responsible></agency_responsible>
+ <service_notice></service_notice>
+ <requested_datetime>DATETIME</requested_datetime>
+ <updated_datetime>DATETIME</updated_datetime>
+ <expected_datetime>DATETIME</expected_datetime>
+ <lat>50.71086</lat>
+ <long>-1.29573</long>
+ </request>
+ </service_requests>
+ };
+
+ my $dt = DateTime->now(formatter => DateTime::Format::W3CDTF->new)->add( minutes => -5 );
+ $requests_xml =~ s/DATETIME/$dt/gm;
+
+ my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'requests.xml' => $requests_xml } );
+
+ my $update = Open311::GetServiceRequests->new(
+ system_user => $iow_user,
+ );
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => 'isleofwight',
+ }, sub {
+ $update->create_problems( $o, $isleofwight );
+ };
+
+ my $p = FixMyStreet::DB->resultset('Problem')->search(
+ { external_id => 638344 }
+ )->first;
+
+ ok $p, 'Found problem';
+ is $p->title, 'Potholes problem', 'correct problem title';
+ is $p->detail, 'Potholes problem', 'correct problem description';
+ $p->delete;
+};
+
+subtest "fixing passes along the correct message" => sub {
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => 'isleofwight',
+ }, sub {
+ 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 => $isleofwight,
+ test_mode => 1,
+ test_get_returns => { 'servicerequestupdates.xml' => $test_res },
+ );
+
+ my ($p) = $mech->create_problems_for_body(1, $isleofwight->id, 'Title', { external_id => 1 });
+
+ my $c = FixMyStreet::DB->resultset('Comment')->create({
+ problem => $p, user => $p->user, anonymous => 't', text => 'Update text',
+ problem_state => 'fixed - council', state => 'confirmed', mark_fixed => 0,
+ confirmed => DateTime->now(),
+ });
+
+ my $id = $o->post_service_request_update($c);
+ is $id, 248, 'correct update ID returned';
+ my $cgi = CGI::Simple->new($o->test_req_used->content);
+ like $cgi->param('description'), qr/^FMS-Update:/, 'FMS update prefix included';
+ unlike $cgi->param('description'), qr/The customer indicated that this issue had been fixed/, 'No fixed message included';
+
+ $c = $mech->create_comment_for_problem($p, $p->user, 'Name', 'Update text', 'f', 'confirmed', 'fixed - user');
+ $c->discard_changes; # Otherwise cannot set_nanosecond
+
+ $id = $o->post_service_request_update($c);
+ is $id, 248, 'correct update ID returned';
+ $cgi = CGI::Simple->new($o->test_req_used->content);
+ like $cgi->param('description'), qr/^FMS-Update: \[The customer indicated that this issue had been fixed/, 'Fixed message included';
+ $p->comments->delete;
+ $p->delete;
+ };
+};
+
+subtest 'Check special Open311 request handling', sub {
+ $mech->clear_emails_ok;
+ my ($p) = $mech->create_problems_for_body(1, $isleofwight->id, 'Title', { category => 'Potholes', latitude => 50.7108, longitude => -1.29573, cobrand => 'isleofwight' });
+ $p->set_extra_fields({ name => 'urgent', value => 'no'});
+ $p->update;
+
+ my $test_data;
+ FixMyStreet::override_config {
+ STAGING_FLAGS => { send_reports => 1 },
+ ALLOWED_COBRANDS => ['isleofwight' ],
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $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';
+
+ my $req = $test_data->{test_req_used};
+ my $c = CGI::Simple->new($req->content);
+ is $c->param('attribute[urgent]'), undef, 'no urgent param sent';
+ is $c->param('attribute[site_code]'), 'Road ID', 'road ID set';
+
+ $mech->email_count_is(1);
+ my $email = $mech->get_email;
+ ok $email, "got an email";
+ like $mech->get_text_body_from_email($email),
+ qr/your enquiry has been received by Island Roads/, "correct report send email text";
+};
+
+subtest "comment recording triage details is not sent" => sub {
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => [ 'isleofwight' ],
+ }, sub {
+ 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></service_request_updates>');
+
+ my $o = Open311->new(
+ fixmystreet_body => $isleofwight,
+ test_mode => 1,
+ test_get_returns => { 'servicerequestupdates.xml' => $test_res },
+ );
+
+ my ($p) = $mech->create_problems_for_body(
+ 1, $isleofwight->id, 'Title',
+ {
+ category => 'Roads',
+ areas => 2636,
+ latitude => 50.71086,
+ longitude => -1.29573,
+ whensent => DateTime->now->add( minutes => -5 ),
+ send_method_used => 'Triage',
+ state => 'for triage',
+ external_id => 1,
+ });
+
+ $mech->log_out_ok;
+ $mech->log_in_ok($admin_user->email);
+ my $report_url = '/report/' . $p->id;
+ $mech->get_ok($report_url);
+ $mech->submit_form_ok( {
+ with_fields => {
+ category => 'Potholes',
+ include_update => 0,
+ }
+ },
+ 'triage form submitted'
+ );
+
+ ok $p->comments->first, 'comment created for problem';
+
+ $p->update({
+ send_method_used => 'Open311',
+ whensent => DateTime->now->add( minutes => -5 ),
+ });
+
+ my $updates = Open311::PostServiceRequestUpdates->new(
+ current_open311 => $o,
+ );
+ my $id = $updates->process_body($isleofwight);
+ ok !$o->test_req_used, 'no open311 update sent';
+
+ $p->comments->delete;
+ $p->delete;
+ };
+};
+
+my ($p) = $mech->create_problems_for_body(1, $isleofwight->id, '', { cobrand => 'isleofwight' });
+my $alert = FixMyStreet::DB->resultset('Alert')->create( {
+ parameter => $p->id,
+ alert_type => 'new_updates',
+ user => $user,
+ cobrand => 'isleofwight',
+} )->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 => ['isleofwight','fixmystreet'],
+ }, sub {
+ FixMyStreet::Script::Alerts::send();
+ };
+
+ $mech->email_count_is(1);
+ my $email = $mech->get_email;
+ ok $email, "got an email";
+ like $mech->get_text_body_from_email($email), qr/Island Roads/, "emails are branded";
+};
+
+$p->comments->delete;
+$p->delete;
+
+subtest "check not responsible as correct text" => sub {
+ my ($p) = $mech->create_problems_for_body(
+ 1, $isleofwight->id, 'Title',
+ {
+ category => 'Roads',
+ areas => 2636,
+ latitude => 50.71086,
+ longitude => -1.29573,
+ whensent => DateTime->now->add( minutes => -5 ),
+ send_method_used => 'Open311',
+ state => 'not responsible',
+ external_id => 1,
+ });
+
+ my $c = FixMyStreet::DB->resultset('Comment')->create({
+ problem => $p, user => $p->user, anonymous => 't', text => 'Update text',
+ problem_state => 'not responsible', state => 'confirmed', mark_fixed => 0,
+ confirmed => DateTime->now(),
+ });
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => ['isleofwight'],
+ }, sub {
+ $mech->get_ok('/report/' . $p->id);
+ };
+
+ $mech->content_contains("not Island Roads’ responsibility", "not reponsible message contains correct text");
+ $p->comments->delete;
+ $p->delete;
+};
+
+subtest "sends branded confirmation emails" => sub {
+ $mech->log_out_ok;
+ $mech->clear_emails_ok;
+ $mech->get_ok('/around');
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'isleofwight' ],
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $mech->submit_form_ok( { with_fields => { pc => 'PO30 5XJ', } },
+ "submit location" );
+
+ # 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 => 'test-1@example.com',
+ category => 'Roads',
+ }
+ },
+ "submit good details"
+ );
+
+ $mech->email_count_is(1);
+ my $email = $mech->get_email;
+ ok $email, "got an email";
+ like $mech->get_text_body_from_email($email), qr/Island Roads/, "emails are branded";
+
+ my $url = $mech->get_link_from_email($email);
+ $mech->get_ok($url);
+ $mech->clear_emails_ok;
+ };
+};
+
+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 => ['isleofwight','fixmystreet'],
+ }, sub {
+ FixMyStreet::Script::Reports::send();
+ };
+ $mech->email_count_is(1);
+ my $email = $mech->get_email;
+ ok $email, "got an email";
+ like $mech->get_text_body_from_email($email), qr/Island Roads/, "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 => ['isleofwight','fixmystreet'],
+ }, sub {
+ $extra_details = $mech->get_ok_json('/report/new/category_extras?category=Roads&latitude=50.71086&longitude=-1.29573');
+ };
+
+ like $extra_details->{category_extra}, qr/Island Roads/, 'correct name in category extras';
+};
+
+subtest "reports are marked for triage upon submission" => sub {
+ $mech->log_out_ok;
+ $mech->clear_emails_ok;
+ $mech->log_in_ok($user->email);
+ $mech->get_ok('/around');
+ FixMyStreet::override_config {
+ STAGING_FLAGS => { send_reports => 1, skip_checks => 0 },
+ ALLOWED_COBRANDS => [ 'isleofwight' ],
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $mech->submit_form_ok( { with_fields => { pc => 'PO30 5XJ', } },
+ "submit location" );
+
+ # 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 => '',
+ category => 'Roads',
+ }
+ },
+ "submit good details"
+ );
+
+ my $report = $user->problems->first;
+ ok $report, "Found the report";
+ is $report->state, 'confirmed', 'report confirmed';
+
+ $mech->clear_emails_ok;
+
+ FixMyStreet::Script::Reports::send();
+ $report->discard_changes;
+ is $report->state, 'for triage', 'report marked as for triage';
+ ok $report->whensent, 'report marked as sent';
+
+ $mech->email_count_is(1);
+ my $email = $mech->get_email;
+ like $mech->get_text_body_from_email($email),
+ qr/submitted to Island Roads for review/, 'correct text for email sent for Triage';
+ };
+};
+
+for my $cobrand ( 'fixmystreet', 'isleofwight' ) {
+ subtest "only categories for Triage are displayed on " . $cobrand => sub {
+ $mech->log_out_ok;
+ $mech->get_ok('/around');
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ $cobrand ],
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $mech->submit_form_ok( { with_fields => { pc => 'PO30 5XJ', } },
+ "submit location" );
+
+ # click through to the report page
+ $mech->follow_link_ok( { text_regex => qr/skip this step/i, },
+ "follow 'skip this step' link" );
+
+ my $f = $mech->form_name('mapSkippedForm');
+ ok $f, 'found form';
+ my $cats = $f->find_input('category');
+ ok $cats, 'found category element';
+ my @values = $cats->possible_values;
+ is_deeply \@values, [ '-- Pick a category --', 'Roads' ], 'correct category list';
+ };
+ };
+
+ subtest "staff user can see non Triage categories on " . $cobrand => sub {
+ $mech->log_out_ok;
+ $mech->log_in_ok($admin_user->email);
+ $mech->get_ok('/around');
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ $cobrand ],
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $mech->submit_form_ok( { with_fields => { pc => 'PO30 5XJ', } },
+ "submit location" );
+
+ # click through to the report page
+ $mech->follow_link_ok( { text_regex => qr/skip this step/i, },
+ "follow 'skip this step' link" );
+
+ my $f = $mech->form_name('mapSkippedForm');
+ ok $f, 'found form';
+ my $cats = $f->find_input('category');
+ ok $cats, 'found category element';
+ my @values = $cats->possible_values;
+ is_deeply \@values, [ '-- Pick a category --', 'Potholes' ], 'correct category list';
+ };
+ };
+}
+
+done_testing();
diff --git a/t/cobrand/national_assets.t b/t/cobrand/national_assets.t
index 378425193..32e27079b 100644
--- a/t/cobrand/national_assets.t
+++ b/t/cobrand/national_assets.t
@@ -20,6 +20,7 @@ subtest 'cobrand assets includes not applied on cobrand sites', sub {
ALLOWED_COBRANDS => [ 'bathnes' ],
MAPIT_URL => 'http://mapit.uk/',
MAP_TYPE => 'FMS,OSM,BathNES,Buckinghamshire',
+ STAGING_FLAGS => { skip_checks => 1 },
}, sub {
$mech->get_ok("/report/new?latitude=51.494885&longitude=-2.602237");
$mech->content_lacks('buckinghamshire/assets.js');
diff --git a/t/cobrand/northamptonshire.t b/t/cobrand/northamptonshire.t
new file mode 100644
index 000000000..57fe319a9
--- /dev/null
+++ b/t/cobrand/northamptonshire.t
@@ -0,0 +1,126 @@
+use Test::MockModule;
+
+use FixMyStreet::TestMech;
+use Open311::PostServiceRequestUpdates;
+
+use_ok 'FixMyStreet::Cobrand::Northamptonshire';
+
+my $mech = FixMyStreet::TestMech->new;
+
+use open ':std', ':encoding(UTF-8)';
+
+my $ncc = $mech->create_body_ok(2234, 'Northamptonshire County Council', {
+ send_method => 'Open311', api_key => 'key', 'endpoint' => 'e', 'jurisdiction' => 'j', send_comments => 1 });
+my $nbc = $mech->create_body_ok(2397, 'Northampton Borough Council');
+
+my $counciluser = $mech->create_user_ok('counciluser@example.com', name => 'Council User', from_body => $ncc);
+my $user = $mech->create_user_ok('user@example.com', name => 'User');
+
+my $ncc_contact = $mech->create_contact_ok(
+ body_id => $ncc->id,
+ category => 'Trees',
+ email => 'trees-2234@example.com',
+);
+
+my $nbc_contact = $mech->create_contact_ok(
+ body_id => $nbc->id,
+ category => 'Flytipping',
+ email => 'flytipping-2397@example.com',
+);
+
+my ($report) = $mech->create_problems_for_body(1, $ncc->id, 'Defect Problem', {
+ whensent => DateTime->now()->subtract( minutes => 5 ),
+ external_id => 1,
+ send_method_used => 'Open311',
+ user => $counciluser
+});
+
+my $comment = 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 => 'confirmed',
+ cobrand => 'default',
+} );
+
+$ncc->update( { comment_user_id => $counciluser->id } );
+
+
+subtest 'Check district categories hidden on cobrand' => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ { northamptonshire => '.' } ],
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $mech->get_ok( '/around' );
+ $mech->submit_form_ok( { with_fields => { pc => 'NN1 1NS' } },
+ "submit location" );
+ is_deeply $mech->page_errors, [], "no errors for pc";
+
+ $mech->follow_link_ok( { text_regex => qr/skip this step/i, },
+ "follow 'skip this step' link" );
+
+ $mech->content_contains('Trees');
+ $mech->content_lacks('Flytipping');
+ };
+};
+
+subtest 'Check updates not sent for defects' => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ { northamptonshire => '.' } ],
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ my $updates = Open311::PostServiceRequestUpdates->new();
+ $updates->send;
+ };
+
+ $comment->discard_changes;
+ is $comment->send_fail_count, 0, "comment sending not attempted";
+ is $comment->get_extra_metadata('cobrand_skipped_sending'), 1, "skipped sending comment";
+};
+
+$report->update({ user => $user });
+$comment->update({ extra => undef });
+subtest 'check updates sent for non defects' => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ { northamptonshire => '.' } ],
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ my $updates = Open311::PostServiceRequestUpdates->new();
+ $updates->send;
+ };
+
+ $comment->discard_changes;
+ is $comment->send_fail_count, 1, "comment sending attempted";
+};
+
+my $cobrand = FixMyStreet::Cobrand::Northamptonshire->new;
+
+subtest 'check updates disallowed correctly' => sub {
+ is $cobrand->updates_disallowed($report), 0;
+ $report->update({ state => 'closed' });
+ is $cobrand->updates_disallowed($report), 1;
+ $report->update({ state => 'confirmed', user => $counciluser });
+ is $cobrand->updates_disallowed($report), 1;
+};
+
+subtest 'check pin colour / reference shown' => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'northamptonshire',
+ #MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ is $cobrand->pin_colour($report, 'around'), 'blue';
+ $mech->get_ok('/report/' . $report->id);
+ $mech->content_lacks('ref:&nbsp;' . $report->id);
+ $report->update({ user => $user });
+ is $cobrand->pin_colour($report, 'around'), 'yellow';
+ is $cobrand->pin_colour($report, 'my'), 'red';
+ $mech->get_ok('/report/' . $report->id);
+ $mech->content_contains('ref:&nbsp;' . $report->id);
+ };
+};
+
+done_testing();
diff --git a/t/cobrand/oxfordshire.t b/t/cobrand/oxfordshire.t
index 2625aa0d5..65c6a3864 100644
--- a/t/cobrand/oxfordshire.t
+++ b/t/cobrand/oxfordshire.t
@@ -1,11 +1,11 @@
-
use Test::MockModule;
-use FixMyStreet::Integrations::ExorRDI;
use FixMyStreet::TestMech;
+use FixMyStreet::Script::Alerts;
my $mech = FixMyStreet::TestMech->new;
my $oxon = $mech->create_body_ok(2237, 'Oxfordshire County Council');
+my $counciluser = $mech->create_user_ok('counciluser@example.com', name => 'Council User', from_body => $oxon);
subtest 'check /around?ajax defaults to open reports only' => sub {
my $categories = [ 'Bridges', 'Fences', 'Manhole' ];
@@ -31,7 +31,7 @@ subtest 'check /around?ajax defaults to open reports only' => sub {
}
FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { 'oxfordshire' => '.' } ],
+ ALLOWED_COBRANDS => 'oxfordshire',
}, sub {
my $json = $mech->get_ok_json( '/around?ajax=1&status=all&bbox=' . $bbox );
my $pins = $json->{pins};
@@ -47,160 +47,87 @@ subtest 'check /around?ajax defaults to open reports only' => sub {
}
};
-my $superuser = $mech->create_user_ok('superuser@example.com', name => 'Super User', is_superuser => 1);
-my $inspector = $mech->create_user_ok('inspector@example.com', name => 'Inspector');
-$inspector->user_body_permissions->create({ body => $oxon, permission_type => 'report_inspect' });
+my @problems = FixMyStreet::DB->resultset('Problem')->search({}, { rows => 3, order_by => 'id' })->all;
-my @problems = FixMyStreet::DB->resultset('Problem')->search({}, { rows => 3 })->all;
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'oxfordshire',
+ MAPIT_URL => 'http://mapit.uk/',
+}, sub {
-subtest 'Exor RDI download appears on Oxfordshire cobrand admin' => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { 'oxfordshire' => '.' } ],
- }, sub {
- $mech->log_in_ok( $superuser->email );
- $mech->get_ok('/admin');
- $mech->content_contains("Download Exor RDI");
- }
-};
+ subtest 'can use customer reference to search for reports' => sub {
+ my $problem = $problems[0];
+ $problem->set_extra_metadata( customer_reference => 'ENQ12456' );
+ $problem->update;
-subtest "Exor RDI download doesn't appear outside of Oxfordshire cobrand admin" => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ { 'fixmystreet' => '.' } ],
- }, sub {
- $mech->log_in_ok( $superuser->email );
- $mech->get_ok('/admin');
- $mech->content_lacks("Download Exor RDI");
- }
-};
+ $mech->get_ok('/around?pc=ENQ12456');
+ is $mech->uri->path, '/report/' . $problem->id, 'redirects to report';
+ };
-subtest 'Exor file looks okay' => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'oxfordshire' ],
- MAPIT_URL => 'http://mapit.uk/',
- }, sub {
- $mech->log_in_ok( $superuser->email );
- $mech->get_ok('/admin/exordefects');
- $mech->submit_form_ok( { with_fields => {
- start_date => '2017-05-05',
- end_date => '2017-05-05',
- user_id => $inspector->id,
- } }, 'submit download');
- $mech->content_contains("No inspections by that inspector in the selected date range");
-
- my $dt = FixMyStreet::DB->resultset('DefectType')->create({
- body => $oxon,
- name => 'Footpath',
- description => 'Footpath stuff',
- });
- $dt->set_extra_metadata(activity_code => 'FC');
- $dt->set_extra_metadata(defect_code => 'SFP1');
- $dt->update;
- my $dt2 = FixMyStreet::DB->resultset('DefectType')->create({
- body => $oxon,
- name => 'Accidental sign damage',
- description => 'Accidental sign damage',
- });
- $dt2->set_extra_metadata(activity_code => 'S');
- $dt2->set_extra_metadata(defect_code => 'ACC2');
- $dt2->update;
- my $i = 123;
- foreach my $problem (@problems) {
- $problem->update({ state => 'action scheduled', external_id => $i });
- $problem->update({ defect_type => $dt }) if $i == 123;
- $problem->set_extra_metadata(traffic_information => 'Signs and Cones') if $i == 124;
- $problem->update({ defect_type => $dt2 }) if $i == 124;
- FixMyStreet::DB->resultset('AdminLog')->create({
- admin_user => $inspector->name,
- user => $inspector,
- object_type => 'problem',
- action => 'inspected',
- object_id => $problem->id,
- whenedited => DateTime->new(year => 2017, month => 5, day => 5, hour => 12),
- });
- $i++;
- }
- $mech->submit_form_ok( { with_fields => {
- start_date => '2017-05-05',
- end_date => '2017-05-05',
- user_id => $inspector->id,
- } }, 'submit download');
- (my $rdi = $mech->content) =~ s/\r\n/\n/g;
- $rdi =~ s/(I,[FMS]C?,,)\d+/$1XXX/g; # Remove unique ID figures, unknown order
- is $rdi, <<EOF, "RDI file matches expected";
-"1,1.8,1.0.0.0,ENHN,"
-"G,1989169,,,XX,170505,1600,D,INS,N,,,,"
-"H,FC"
-"I,FC,,XXX,"434970E 209683N Nearest postcode: OX28 4DS.",1200,,,,,,,,"TM none","123 XX TM0 ""
-"J,SFP1,2,,,434970,209683,,,,,"
-"M,resolve,,,/CFC,,"
-"P,0,999999"
-"G,1989169,,,XX,170505,1600,D,INS,N,,,,"
-"H,MC"
-"I,MC,,XXX,"434970E 209683N Nearest postcode: OX28 4DS.",1200,,,,,,,,"TM none","125 XX TM0 ""
-"J,SFP2,2,,,434970,209683,,,,,"
-"M,resolve,,,/CMC,,"
-"P,0,999999"
-"G,1989169,,,XX,170505,1600,D,INS,N,,,,"
-"H,S"
-"I,S,,XXX,"434970E 209683N Nearest postcode: OX28 4DS.",1200,,,,,,,,"TM Signs and Cones","124 XX TM1 ""
-"J,ACC2,2,,,434970,209683,,,,,"
-"M,resolve,,,/CSI,,"
-"P,0,999999"
-"X,3,3,3,3,0,0,0,3,0,3,0,0,0"
-EOF
- foreach my $problem (@problems) {
- $problem->discard_changes;
- is $problem->get_extra_metadata('rdi_processed'), undef, "Problem was not logged as sent in RDI";
- }
+ 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 $problem = $problems[0];
+ $problem->state( 'unable to fix' );
+ $problem->update;
-subtest 'Reports are marked as inspected correctly' => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'oxfordshire' ],
- MAPIT_URL => 'http://mapit.uk/',
- }, sub {
- my $date = DateTime->new(year => 2017, month => 5, day => 5, hour => 12);
-
- my $now = DateTime->now(
- time_zone => FixMyStreet->time_zone || FixMyStreet->local_time_zone
- );
- my $datetime = Test::MockModule->new('DateTime');
- $datetime->mock('now', sub { $now });
-
- my $params = {
- start_date => $date,
- end_date => $date,
- inspection_date => $date,
- user => $inspector,
- mark_as_processed => 1,
- };
- my $rdi = FixMyStreet::Integrations::ExorRDI->new($params);
- $rdi->construct;
-
- foreach my $problem (@problems) {
- $problem->discard_changes;
- is $problem->get_extra_metadata('rdi_processed'), $now->strftime( '%Y-%m-%d %H:%M' ), "Problem was logged as sent in RDI";
- }
+ my $alert = FixMyStreet::DB->resultset('Alert')->create( {
+ parameter => $problem->id,
+ alert_type => 'new_updates',
+ cobrand => 'oxfordshire',
+ user => $user,
+ } )->confirm;
+
+ FixMyStreet::DB->resultset('Comment')->create( {
+ problem_state => 'unable to fix',
+ problem_id => $problem->id,
+ user_id => $user2->id,
+ name => 'User',
+ mark_fixed => 'f',
+ text => "this is an update",
+ state => 'confirmed',
+ confirmed => 'now()',
+ anonymous => 'f',
+ } );
+
+
+ $mech->get_ok('/report/' . $problem->id);
+ $mech->content_contains('Investigation complete');
+
+ FixMyStreet::Script::Alerts::send();
+ $mech->email_count_is(1);
+ my $email = $mech->get_email;
+ my $body = $mech->get_text_body_from_email($email);
+ like $body, qr/Investigation complete/, 'state correct in email';
};
-};
-subtest 'can use customer reference to search for reports' => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'oxfordshire' ],
- MAPIT_URL => 'http://mapit.uk/',
- }, sub {
- my $problem = $problems[0];
- $problem->set_extra_metadata( customer_reference => 'ENQ12456' );
- $problem->update;
+ subtest 'extra CSV columns are present' => sub {
- $mech->log_out_ok;
- $mech->get_ok('/around?pc=ENQ12456');
- is $mech->uri->path, '/report/' . $problem->id, 'redirects to report';
+ $problems[1]->update({ external_id => $problems[1]->id });
+ $problems[2]->update({ external_id => "123098123" });
+
+ $mech->log_in_ok( $counciluser->email );
+
+ $mech->get_ok('/dashboard?export=1');
+
+ my @rows = $mech->content_as_csv;
+ is scalar @rows, 7, '1 (header) + 6 (reports) = 7 lines';
+ is scalar @{$rows[0]}, 21, '21 columns present';
+
+ is_deeply $rows[0],
+ [
+ 'Report ID', 'Title', 'Detail', 'User Name', 'Category',
+ 'Created', 'Confirmed', 'Acknowledged', 'Fixed', 'Closed',
+ 'Status', 'Latitude', 'Longitude', 'Query', 'Ward',
+ 'Easting', 'Northing', 'Report URL', 'Site Used',
+ 'Reported As', 'HIAMS/Exor Ref',
+ ],
+ 'Column headers look correct';
+
+ is $rows[1]->[20], 'ENQ12456', 'HIAMS reference included in row';
+ is $rows[2]->[20], '', 'Report without HIAMS ref has empty ref field';
+ is $rows[3]->[20], '123098123', 'Older Exor report has correct ref';
};
};
-END {
- done_testing();
-}
+done_testing();
diff --git a/t/cobrand/peterborough.t b/t/cobrand/peterborough.t
new file mode 100644
index 000000000..5d07acb9f
--- /dev/null
+++ b/t/cobrand/peterborough.t
@@ -0,0 +1,84 @@
+use FixMyStreet::TestMech;
+use FixMyStreet::Script::Reports;
+use CGI::Simple;
+
+my $mech = FixMyStreet::TestMech->new;
+
+my $params = {
+ send_method => 'Open311',
+ send_comments => 1,
+ api_key => 'KEY',
+ endpoint => 'endpoint',
+ jurisdiction => 'home',
+ can_be_devolved => 1,
+};
+my $peterborough = $mech->create_body_ok(2566, 'Peterborough City Council', $params);
+
+subtest 'open311 request handling', sub {
+ FixMyStreet::override_config {
+ STAGING_FLAGS => { send_reports => 1 },
+ ALLOWED_COBRANDS => ['peterborough' ],
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ my $contact = $mech->create_contact_ok(body_id => $peterborough->id, category => 'Trees', email => 'TREES');
+ my ($p) = $mech->create_problems_for_body(1, $peterborough->id, 'Title', { category => 'Trees', latitude => 52.5608, longitude => 0.2405, cobrand => 'peterborough' });
+ $p->push_extra_fields({ name => 'emergency', value => 'no'});
+ $p->push_extra_fields({ name => 'private_land', value => 'no'});
+ $p->push_extra_fields({ name => 'PCC-light', value => 'whatever'});
+ $p->push_extra_fields({ name => 'PCC-skanska-csc-ref', value => '1234'});
+ $p->push_extra_fields({ name => 'tree_code', value => 'tree-42'});
+ $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 correct external ID';
+ is $p->get_extra_field_value('emergency'), 'no';
+
+ my $req = $test_data->{test_req_used};
+ my $c = CGI::Simple->new($req->content);
+ is $c->param('attribute[description]'), "Title Test 1 for " . $peterborough->id . " Detail\r\n\r\nSkanska CSC ref: 1234", 'Ref added to description';
+ is $c->param('attribute[emergency]'), undef, 'no emergency param sent';
+ is $c->param('attribute[private_land]'), undef, 'no private_land param sent';
+ is $c->param('attribute[PCC-light]'), undef, 'no pcc- param sent';
+ is $c->param('attribute[tree_code]'), 'tree-42', 'tree_code param sent';
+ };
+};
+
+subtest "extra update params are sent to open311" => sub {
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => 'peterborough',
+ }, sub {
+ my $contact = $mech->create_contact_ok(body_id => $peterborough->id, category => 'Trees', email => 'TREES');
+ 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>ezytreev-248</update_id></request_update></service_request_updates>');
+
+ my $o = Open311->new(
+ fixmystreet_body => $peterborough,
+ test_mode => 1,
+ test_get_returns => { 'servicerequestupdates.xml' => $test_res },
+ );
+
+ my ($p) = $mech->create_problems_for_body(1, $peterborough->id, 'Title', { external_id => 1, category => 'Trees' });
+
+ my $c = FixMyStreet::DB->resultset('Comment')->create({
+ problem => $p, user => $p->user, anonymous => 't', text => 'Update text',
+ problem_state => 'fixed - council', state => 'confirmed', mark_fixed => 0,
+ confirmed => DateTime->now(),
+ });
+
+ my $id = $o->post_service_request_update($c);
+ is $id, "ezytreev-248", 'correct update ID returned';
+ my $cgi = CGI::Simple->new($o->test_req_used->content);
+ is $cgi->param('description'), '[Customer FMS update] Update text', 'FMS update prefix included';
+ is $cgi->param('service_request_id_ext'), $p->id, 'Service request ID included';
+ is $cgi->param('service_code'), $contact->email, 'Service code included';
+ };
+};
+
+done_testing;
diff --git a/t/cobrand/restriction.t b/t/cobrand/restriction.t
index 63fe326b1..185f365c8 100644
--- a/t/cobrand/restriction.t
+++ b/t/cobrand/restriction.t
@@ -19,7 +19,10 @@ package main;
use FixMyStreet::TestMech;
-my $c = FixMyStreet::App->new;
+use Catalyst::Test 'FixMyStreet::App';
+
+my ($res, $c) = ctx_request('/');
+
my $cobrand = FixMyStreet::Cobrand::Tester->new({c => $c});
$c->stash->{cobrand} = $cobrand;
diff --git a/t/cobrand/staging.t b/t/cobrand/staging.t
new file mode 100644
index 000000000..5d79daa4b
--- /dev/null
+++ b/t/cobrand/staging.t
@@ -0,0 +1,18 @@
+use FixMyStreet::TestMech;
+my $mech = FixMyStreet::TestMech->new;
+
+subtest 'staging banner is visible by default on staging sites' => sub {
+ $mech->get_ok('/');
+ $mech->content_contains('<div class="dev-site-notice">');
+};
+
+FixMyStreet::override_config {
+ STAGING_FLAGS => { hide_staging_banner => 1 },
+}, sub {
+ subtest 'staging banner can be hidden through STAGING_FLAGS config' => sub {
+ $mech->get_ok('/');
+ $mech->content_lacks('<div class="dev-site-notice">');
+ };
+};
+
+done_testing();
diff --git a/t/cobrand/tfl.t b/t/cobrand/tfl.t
new file mode 100644
index 000000000..8ddc3d671
--- /dev/null
+++ b/t/cobrand/tfl.t
@@ -0,0 +1,1089 @@
+use FixMyStreet::TestMech;
+use FixMyStreet::App;
+use FixMyStreet::Script::Reports;
+use FixMyStreet::Script::Questionnaires;
+
+# disable info logs for this test run
+FixMyStreet::App->log->disable('info');
+END { FixMyStreet::App->log->enable('info'); }
+
+my $mech = FixMyStreet::TestMech->new;
+
+use t::Mock::Tilma;
+my $tilma = t::Mock::Tilma->new;
+LWP::Protocol::PSGI->register($tilma->to_psgi_app, host => 'tilma.mysociety.org');
+
+
+my $body = $mech->create_body_ok(2482, 'TfL');
+FixMyStreet::DB->resultset('BodyArea')->find_or_create({
+ area_id => 2483, # Hounslow
+ body_id => $body->id,
+});
+FixMyStreet::DB->resultset('BodyArea')->find_or_create({
+ area_id => 2457, # Epsom Ewell, outside London, for bus stop test
+ 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({
+ body => $body,
+ permission_type => 'contribute_as_body',
+});
+$staffuser->user_body_permissions->create({
+ body => $body,
+ permission_type => 'default_to_body',
+});
+my $user = $mech->create_user_ok('londonresident@example.com');
+
+my $bromley = $mech->create_body_ok(2482, 'Bromley');
+my $bromleyuser = $mech->create_user_ok('bromleyuser@bromley.example.com', name => 'Bromley Staff', from_body => $bromley);
+$mech->create_contact_ok(
+ body_id => $bromley->id,
+ category => 'Accumulated Litter',
+ email => 'litter-bromley@example.com',
+);
+my $bromley_flooding = $mech->create_contact_ok(
+ body_id => $bromley->id,
+ category => 'Flooding (Bromley)',
+ email => 'litter-bromley@example.com',
+);
+$bromley_flooding->set_extra_metadata(display_name => 'Flooding');
+$bromley_flooding->update;
+
+my $bromley_flytipping = $mech->create_contact_ok(
+ body_id => $bromley->id,
+ category => 'Flytipping (Bromley)',
+ email => 'flytipping-bromley@example.com',
+);
+$bromley_flytipping->set_extra_metadata(group => [ 'Street cleaning' ]);
+$bromley_flytipping->update;
+
+my $contact1 = $mech->create_contact_ok(
+ body_id => $body->id,
+ category => 'Bus stops',
+ email => 'busstops@example.com',
+);
+$contact1->set_extra_metadata(group => [ 'Bus things' ]);
+$contact1->set_extra_fields(
+ {
+ code => 'leaning',
+ description => 'Is the pole leaning?',
+ datatype => 'string',
+ },
+ {
+ code => 'stop_code',
+ description => 'Stop number',
+ datatype => 'string',
+ automated => 'hidden_field',
+ }
+);
+$contact1->update;
+my $contact2 = $mech->create_contact_ok(
+ body_id => $body->id,
+ category => 'Traffic lights',
+ email => 'trafficlights@example.com',
+);
+$contact2->set_extra_fields({
+ code => "safety_critical",
+ description => "Safety critical",
+ automated => "hidden_field",
+ order => 1,
+ datatype => "singlevaluelist",
+ values => [
+ {
+ name => "Yes",
+ key => "yes"
+ },
+ {
+ name => "No",
+ key => "no"
+ }
+ ]
+});
+$contact2->update;
+my $contact2b = $mech->create_contact_ok(
+ body_id => $body->id,
+ category => 'Timings',
+ email => 'trafficlighttimings@example.com',
+);
+
+my $contact3 = $mech->create_contact_ok(
+ body_id => $body->id,
+ category => 'Pothole',
+ email => 'pothole@example.com',
+);
+$contact3->set_extra_fields({
+ code => "safety_critical",
+ description => "Safety critical",
+ automated => "hidden_field",
+ order => 1,
+ datatype => "singlevaluelist",
+ values => [
+ {
+ name => "Yes",
+ key => "yes"
+ },
+ {
+ name => "No",
+ key => "no"
+ }
+ ]
+});
+$contact3->update;
+my $contact4 = $mech->create_contact_ok(
+ body_id => $body->id,
+ category => 'Flooding',
+ email => 'flooding@example.com',
+);
+$contact4->set_extra_fields(
+ {
+ code => "safety_critical",
+ description => "Safety critical",
+ automated => "hidden_field",
+ order => 1,
+ datatype => "singlevaluelist",
+ values => [
+ {
+ name => "Yes",
+ key => "yes"
+ },
+ {
+ name => "No",
+ key => "no"
+ }
+ ]
+ },
+ {
+ code => "location",
+ description => "Where is the flooding?",
+ variable => "true",
+ order => 1,
+ required => "true",
+ datatype => "singlevaluelist",
+ values => [
+ {
+ name => "Carriageway",
+ key => "carriageway"
+ },
+ {
+ name => "Footway",
+ key => "footway"
+ }
+ ]
+ }
+);
+$contact4->update;
+my $contact5 = $mech->create_contact_ok(
+ body_id => $body->id,
+ category => 'Trees',
+ email => 'AOAT',
+);
+my $contact6 = $mech->create_contact_ok(
+ body_id => $body->id,
+ category => 'Grit bins',
+ email => 'AOAT,gritbins@example.com',
+);
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'tfl', 'bromley', 'fixmystreet'],
+ MAPIT_URL => 'http://mapit.uk/',
+ COBRAND_FEATURES => {
+ internal_ips => { tfl => [ '127.0.0.1' ] },
+ base_url => {
+ tfl => 'https://street.tfl'
+ },
+ borough_email_addresses => { tfl => {
+ AOAT => [
+ {
+ email => 'hounslow@example.com',
+ areas => [ 2483 ],
+ },
+ {
+ email => 'bromley@example.com',
+ areas => [ 2482 ],
+ },
+ ],
+ } },
+ anonymous_account => {
+ tfl => 'anonymous'
+ },
+ contact_name => {
+ tfl => 'TfL Street Care',
+ },
+ do_not_reply_email => {
+ tfl => 'fms-tfl-DO-NOT-REPLY@example.com',
+ },
+ send_questionnaire => {
+ fixmystreet => {
+ TfL => 0,
+ }
+ },
+ },
+}, sub {
+
+$mech->host("tfl.fixmystreet.com");
+
+subtest "test report creation anonymously by button" => sub {
+ $mech->get_ok('/around');
+ $mech->submit_form_ok( { with_fields => { pc => 'BR1 3UH', } }, "submit location" );
+ $mech->follow_link_ok( { text_regex => qr/skip this step/i, }, "follow 'skip this step' link" );
+ $mech->submit_form_ok(
+ {
+ button => 'report_anonymously',
+ with_fields => {
+ title => 'Anonymous Test Report 1',
+ detail => 'Test report details.',
+ category => 'Bus stops',
+ }
+ },
+ "submit report anonymously"
+ );
+ my $report = FixMyStreet::DB->resultset("Problem")->find({ title => 'Anonymous Test Report 1'});
+ ok $report, "Found the report";
+
+ $mech->content_contains('Your issue is on its way to Transport for London');
+ $mech->content_contains('Your reference for this report is FMS' . $report->id) or diag $mech->content;
+
+ is_deeply $mech->page_errors, [], "check there were no errors";
+
+ is $report->state, 'confirmed', "report confirmed";
+ $mech->get_ok( '/report/' . $report->id );
+
+ is $report->bodies_str, $body->id;
+ is $report->name, 'Anonymous user';
+ is $report->user->email, 'anonymous@tfl.gov.uk';
+ 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';
+
+ my $alert = FixMyStreet::App->model('DB::Alert')->find( {
+ user => $report->user,
+ alert_type => 'new_updates',
+ parameter => $report->id,
+ } );
+ is $alert, undef, "no alert created";
+
+ $mech->not_logged_in_ok;
+};
+
+subtest "test report creation anonymously by staff user" => sub {
+ $mech->clear_emails_ok;
+ $mech->log_in_ok( $staffuser->email );
+ $mech->get_ok('/around');
+ $mech->submit_form_ok( { with_fields => { pc => 'BR1 3UH', } }, "submit location" );
+ $mech->follow_link_ok( { text_regex => qr/skip this step/i, }, "follow 'skip this step' link" );
+ $mech->submit_form_ok(
+ {
+ button => 'report_anonymously',
+ with_fields => {
+ title => 'Anonymous Test Report 2',
+ detail => 'Test report details.',
+ category => 'Bus stops',
+ }
+ },
+ "submit report"
+ );
+ is_deeply $mech->page_errors, [], "check there were no errors";
+
+ my $report = FixMyStreet::DB->resultset("Problem")->find({ title => 'Anonymous Test Report 2'});
+ ok $report, "Found the report";
+
+ $mech->content_contains('Your issue is on its way to Transport for London');
+ $mech->content_contains('Your reference for this report is FMS' . $report->id) or diag $mech->content;
+
+ is $report->state, 'confirmed', "report confirmed";
+ $mech->get_ok( '/report/' . $report->id );
+
+ $report->update({ state => 'fixed - council' });
+ my $json = $mech->get_ok_json('/around/nearby?latitude=' . $report->latitude . '&longitude=' . $report->longitude);
+ is @{$json->{pins}}, 2, 'right number of pins';
+
+ is $report->bodies_str, $body->id;
+ is $report->name, 'Anonymous user';
+ is $report->user->email, 'anonymous@tfl.gov.uk';
+ is $report->anonymous, 1;
+ is $report->get_extra_metadata('contributed_as'), 'anonymous_user';
+
+ my $alerts = FixMyStreet::App->model('DB::Alert')->search( {
+ alert_type => 'new_updates',
+ parameter => $report->id,
+ } );
+ is $alerts->count, 0, "no alerts created";
+ ok $mech->email_count_is(0), "no emails sent";
+
+ $mech->log_out_ok;
+};
+
+FixMyStreet::DB->resultset("Problem")->delete_all;
+
+subtest "test report creation and reference number" => sub {
+ $mech->log_in_ok( $user->email );
+ $mech->get_ok('/around');
+ $mech->submit_form_ok( { with_fields => { pc => 'BR1 3UH', } }, "submit location" );
+ $mech->follow_link_ok( { text_regex => qr/skip this step/i, }, "follow 'skip this step' link" );
+ $mech->submit_form_ok(
+ {
+ with_fields => {
+ title => 'Test Report 1',
+ detail => 'Test report details.',
+ name => 'Joe Bloggs',
+ may_show_name => '1',
+ category => 'Bus stops',
+ }
+ },
+ "submit good details"
+ );
+
+ my $report = FixMyStreet::DB->resultset("Problem")->find({ title => 'Test Report 1'});
+ ok $report, "Found the report";
+
+ $mech->content_contains('Your issue is on its way to Transport for London');
+ $mech->content_contains('Your reference for this report is FMS' . $report->id) or diag $mech->content;
+
+ is_deeply $mech->page_errors, [], "check there were no errors";
+
+ is $report->state, 'confirmed', "report confirmed";
+
+ is $report->bodies_str, $body->id;
+ is $report->name, 'Joe Bloggs';
+};
+
+subtest "test bus report creation outside London, .com" => sub {
+ $mech->host('www.fixmystreet.com');
+ $mech->get_ok('/report/new?latitude=51.345714&longitude=-0.227959');
+ $mech->content_lacks('Bus things');
+ $mech->host('tfl.fixmystreet.com');
+};
+
+subtest "test bus report creation outside London" => sub {
+ $mech->get_ok('/report/new?latitude=51.345714&longitude=-0.227959');
+ $mech->submit_form_ok(
+ {
+ with_fields => {
+ # A bus stop in East Ewell
+ latitude => 51.345714,
+ longitude => -0.227959,
+ title => 'Test outwith London',
+ detail => 'Test report details.',
+ name => 'Joe Bloggs',
+ may_show_name => '1',
+ category => 'Bus stops',
+ }
+ },
+ "submit good details"
+ );
+ $mech->content_contains('Your issue is on its way to Transport for London');
+ is_deeply $mech->page_errors, [], "check there were no errors";
+
+ my $report = FixMyStreet::DB->resultset("Problem")->find({ title => 'Test outwith London'});
+ ok $report, "Found the report";
+ is $report->state, 'confirmed', "report confirmed";
+ is $report->bodies_str, $body->id;
+ $report->delete;
+
+ $mech->log_out_ok;
+};
+
+subtest "extra information included in email" => sub {
+ my $report = FixMyStreet::DB->resultset("Problem")->find({ title => 'Test Report 1'});
+ $report->set_extra_fields({ name => 'stop_code', value => '12345678' });
+ $report->update;
+ my $id = $report->id;
+
+ $mech->clear_emails_ok;
+ FixMyStreet::Script::Reports::send();
+ my @email = $mech->get_email;
+ is $email[0]->header('To'), 'TfL <busstops@example.com>';
+ like $mech->get_text_body_from_email($email[0]), qr/Report reference: FMS$id/, "FMS-prefixed ID in TfL email";
+ like $mech->get_text_body_from_email($email[0]), qr/Stop number: 12345678/, "Bus stop code in TfL email";
+ is $email[1]->header('To'), $report->user->email;
+ is $email[1]->header('From'), '"TfL Street Care" <fms-tfl-DO-NOT-REPLY@example.com>';
+ like $mech->get_text_body_from_email($email[1]), qr/report's reference number is FMS$id/, "FMS-prefixed ID in reporter email";
+ $mech->clear_emails_ok;
+
+ $mech->get_ok( '/report/' . $report->id );
+ $mech->content_contains('FMS' . $report->id) or diag $mech->content;
+};
+
+subtest 'Dashboard CSV extra columns' => sub {
+ my $report = FixMyStreet::DB->resultset("Problem")->find({ title => 'Test Report 1'});
+ $report->set_extra_fields({ name => 'leaning', value => 'Yes' });
+ $report->update;
+
+ $mech->log_in_ok( $staffuser->email );
+ $mech->get_ok('/dashboard?export=1&category=Bus+stops');
+ $mech->content_contains('Category,Subcategory');
+ $mech->content_contains('Query,Borough');
+ $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,');
+ $mech->content_contains(',,,no,busstops@example.com,,,,Yes');
+
+ $report->set_extra_fields({ name => 'safety_critical', value => 'yes' });
+ $report->anonymous(1);
+ $report->update;
+ my $dt = DateTime->now();
+ FixMyStreet::DB->resultset("AdminLog")->create({
+ action => 'category_change',
+ whenedited => $dt,
+ object_id => $report->id,
+ object_type => 'problem',
+ admin_user => $staffuser->name,
+ user => $staffuser,
+ });
+ $mech->get_ok('/dashboard?export=1');
+ $mech->content_contains('Query,Borough');
+ $mech->content_contains(',"Safety critical","Delivered to","Closure email at","Reassigned at","Reassigned by"');
+ $mech->content_contains('(anonymous ' . $report->id . ')');
+ $mech->content_contains(',,,yes,busstops@example.com,,' . $dt . ',"Council User"');
+};
+
+subtest 'Inspect form state choices' => sub {
+ my $report = FixMyStreet::DB->resultset("Problem")->find({ title => 'Test Report 1'});
+ my $id = $report->id;
+ $mech->get_ok("/report/$id");
+ $mech->content_lacks('for triage');
+ $mech->content_lacks('action scheduled');
+};
+
+subtest "change category, report resent to new location" => sub {
+ my $report = FixMyStreet::DB->resultset("Problem")->find({ title => 'Test Report 1'});
+ my $id = $report->id;
+
+ $mech->log_in_ok( $superuser->email );
+ $mech->get_ok("/admin/report_edit/$id");
+ $mech->content_lacks('Timings');
+ $mech->submit_form_ok({ with_fields => { category => 'Traffic lights' } });
+
+ FixMyStreet::Script::Reports::send();
+ my @email = $mech->get_email;
+ is $email[0]->header('To'), 'TfL <trafficlights@example.com>';
+ $mech->clear_emails_ok;
+
+ $mech->log_out_ok;
+};
+
+for my $test (
+ [ 'BR1 3UH', 'tfl.fixmystreet.com', 'Trees', 'TfL <bromley@example.com>', 'Bromley borough team', 'reference number is FMS' ],
+ [ 'BR1 3UH', 'www.fixmystreet.com', 'Trees', 'TfL <bromley@example.com>', 'Bromley borough team', 'reference number is' ],
+ [ 'BR1 3UH', 'bromley.fixmystreet.com', 'Trees', 'TfL <bromley@example.com>', 'Bromley borough team', '' ],
+ [ 'TW7 5JN', 'tfl.fixmystreet.com', 'Trees', 'TfL <hounslow@example.com>', 'Hounslow borough team', 'reference number is FMS' ],
+ [ 'TW7 5JN', 'www.fixmystreet.com', 'Trees', 'TfL <hounslow@example.com>', 'Hounslow borough team', 'reference number is' ],
+ [ 'TW7 5JN', 'tfl.fixmystreet.com', 'Grit bins', 'TfL <hounslow@example.com>, TfL <gritbins@example.com>', 'Hounslow borough team and additional address', 'reference number is FMS' ],
+ [ 'TW7 5JN', 'www.fixmystreet.com', 'Grit bins', 'TfL <hounslow@example.com>, TfL <gritbins@example.com>', 'Hounslow borough team and additional address', 'reference number is' ],
+) {
+ my ($postcode, $host, $category, $to, $name, $ref ) = @$test;
+ subtest "test report is sent to $name on $host" => sub {
+ $mech->host($host);
+ $mech->log_in_ok( $user->email );
+ $mech->get_ok('/around');
+ $mech->submit_form_ok( { with_fields => { pc => $postcode, } }, "submit location" );
+ $mech->follow_link_ok( { text_regex => qr/skip this step/i, }, "follow 'skip this step' link" );
+ $mech->submit_form_ok(
+ {
+ with_fields => {
+ title => 'Test Report for borough team',
+ detail => 'Test report details.',
+ may_show_name => '1',
+ category => $category,
+ $host eq 'bromley.fixmystreet.com' ? (
+ fms_extra_title => 'DR',
+ first_name => "Joe",
+ last_name => "Bloggs",
+ ) : (
+ name => 'Joe Bloggs',
+ ),
+ }
+ },
+ "submit good details"
+ );
+
+ $mech->clear_emails_ok;
+ FixMyStreet::Script::Reports::send();
+ my @email = $mech->get_email;
+ is $email[0]->header('To'), $to, 'Sent to correct address';
+ like $email[0]->as_string, qr/iEYI87gX6Upb\+tKYzrSmN83pTnv606AOtahHTepSm/, 'Right logo';
+ like $mech->get_text_body_from_email($email[0]), qr/https:\/\/street.tfl/, 'Correct link';
+ like $mech->get_text_body_from_email($email[1]), qr/$ref/, "Correct reference number in reporter email" if $ref;
+ $mech->clear_emails_ok;
+ FixMyStreet::DB->resultset("Problem")->find({ title => 'Test Report for borough team'})->delete;
+ };
+}
+
+$mech->host("tfl.fixmystreet.com");
+
+subtest 'check lookup by reference' => sub {
+ my $id = FixMyStreet::DB->resultset("Problem")->first->id;
+
+ $mech->get_ok('/');
+ $mech->submit_form_ok( { with_fields => { pc => 'FMS12345' } }, 'bad ref');
+ $mech->content_contains('Searching found no reports');
+
+ $mech->get_ok('/');
+ $mech->submit_form_ok( { with_fields => { pc => "FMS$id" } }, 'good FMS-prefixed ref');
+ is $mech->uri->path, "/report/$id", "redirected to report page when using FMS-prefixed ref";
+
+ $mech->get_ok('/');
+ $mech->submit_form_ok( { with_fields => { pc => "fms $id" } }, 'good FMS-prefixed with a space ref');
+ is $mech->uri->path, "/report/$id", "redirected to report page when using FMS-prefixed ref";
+
+ $mech->get_ok('/');
+ $mech->submit_form_ok( { with_fields => { pc => "$id" } }, 'good ref');
+ is $mech->uri->path, "/report/$id", "redirected to report page when using non-prefixed ref";
+};
+
+for my $test (
+ {
+ states => [ 'confirmed' ],
+ colour => 'red'
+ },
+ {
+ states => ['action scheduled', 'in progress', 'investigating', 'planned'],
+ colour => 'orange'
+ },
+ {
+ states => [ FixMyStreet::DB::Result::Problem->fixed_states, FixMyStreet::DB::Result::Problem->closed_states ],
+ colour => 'green'
+ },
+) {
+ subtest 'check ' . $test->{colour} . ' pin states' => sub {
+ my $report = FixMyStreet::DB->resultset("Problem")->find({ title => 'Test Report 1'});
+ my $url = '/around?ajax=1&bbox=' . ($report->longitude - 0.01) . ',' . ($report->latitude - 0.01)
+ . ',' . ($report->longitude + 0.01) . ',' . ($report->latitude + 0.01);
+
+ for my $state ( @{ $test->{states} } ) {
+ $report->update({ state => $state });
+ my $json = $mech->get_ok_json( $url );
+ my $colour = $json->{pins}[0][2];
+ is $colour, $test->{colour}, 'correct ' . $test->{colour} . ' pin for state ' . $state;
+ }
+ };
+}
+
+subtest 'check correct base URL & title in AJAX pins' => sub {
+ my $report = FixMyStreet::DB->resultset("Problem")->find({ title => 'Test Report 1'});
+ my $url = '/around?ajax=1&bbox=' . ($report->longitude - 0.01) . ',' . ($report->latitude - 0.01)
+ . ',' . ($report->longitude + 0.01) . ',' . ($report->latitude + 0.01);
+
+ $report->update({ state => 'confirmed' });
+ $report->discard_changes;
+ is $report->cobrand, 'tfl', 'Report made on TfL cobrand';
+
+ $mech->host("fixmystreet.com");
+ my $json = $mech->get_ok_json( $url );
+ is $json->{pins}[0][4], $report->category . " problem", "category is used for title" or diag $mech->content;
+ is $json->{pins}[0][7], "https://street.tfl", "base_url is included and correct" or diag $mech->content;
+
+ $mech->host("tfl.fixmystreet.com");
+ $json = $mech->get_ok_json( $url );
+ is $json->{pins}[0][4], $report->title, "title is shown on TfL cobrand" or diag $mech->content;
+ is $json->{pins}[0][7], undef, "base_url is not present on TfL cobrand response";
+
+ $mech->host("fixmystreet.com");
+ $report->update({cobrand => 'fixmystreet'});
+ $json = $mech->get_ok_json( $url );
+ is $json->{pins}[0][4], $report->title, "title is shown if report made on fixmystreet cobrand" or diag $mech->content;
+ is $json->{pins}[0][7], undef, "base_url is not present if report made on fixmystreet cobrand";
+
+ $report->update({cobrand => 'tfl'});
+ $mech->host("tfl.fixmystreet.com");
+};
+
+subtest 'check report age on /around' => sub {
+ $mech->log_in_ok($staffuser->email);
+ my $report = FixMyStreet::DB->resultset("Problem")->find({ title => 'Test Report 1'});
+ $report->update({ state => 'confirmed' });
+
+ $mech->get_ok( '/around?lat=' . $report->latitude . '&lon=' . $report->longitude );
+ $mech->content_contains($report->title);
+ $mech->content_contains('item-list__item__borough">Bromley');
+
+ $report->update({
+ confirmed => \"current_timestamp-'7 weeks'::interval",
+ whensent => \"current_timestamp-'7 weeks'::interval",
+ lastupdate => \"current_timestamp-'7 weeks'::interval",
+ });
+
+ $mech->get_ok( '/around?lat=' . $report->latitude . '&lon=' . $report->longitude );
+ $mech->content_lacks($report->title);
+
+ $report->update({
+ confirmed => \"current_timestamp",
+ whensent => \"current_timestamp",
+ lastupdate => \"current_timestamp",
+ });
+};
+
+subtest 'check report age in general' => sub {
+ my $report = FixMyStreet::DB->resultset("Problem")->find({ title => 'Test Report 1'});
+ $report->update({ state => 'confirmed' });
+ $mech->get_ok('/report/' . $report->id);
+ $report->update({ lastupdate => \"current_timestamp-'4 years'::interval" });
+ $mech->get('/report/' . $report->id);
+ is $mech->res->code, 404;
+ $report->update({ lastupdate => \"current_timestamp" });
+};
+
+subtest 'TfL admin allows inspectors to be assigned to borough areas' => sub {
+ $mech->log_in_ok($superuser->email);
+
+ $mech->get_ok("/admin/users/" . $staffuser->id) or diag $mech->content;
+
+ $mech->submit_form_ok( { with_fields => {
+ area_ids => [2482],
+ } } );
+
+ $staffuser->discard_changes;
+ is_deeply $staffuser->area_ids, [2482], "User assigned to Bromley LBO area";
+
+ $staffuser->update({ area_ids => undef}); # so login below doesn't break
+};
+
+my $report = FixMyStreet::DB->resultset("Problem")->find({ title => 'Test Report 1'});
+$report->update({ cobrand => 'fixmystreet' });
+$staffuser->add_to_planned_reports($report);
+
+for my $host ( 'www.fixmystreet.com', 'tfl.fixmystreet.com' ) {
+ subtest "Leave an update on a shortlisted report on $host, get an email" => sub {
+ $mech->host($host);
+ $mech->log_in_ok( $user->email );
+ $mech->get_ok('/report/' . $report->id);
+ $mech->submit_form_ok({ with_fields => { update => 'This is an update' }});
+ my $email = $mech->get_email;
+ my $text = $mech->get_text_body_from_email;
+ like $text, qr/This is an update/, 'Right email';
+ like $text, qr/street.tfl/, 'Right url';
+ like $text, qr/Street Care/, 'Right name';
+ like $email->as_string, qr/iEYI87gX6Upb\+tKYzrSmN83pTnv606AOtahHTepSm/, 'Right logo';
+ };
+}
+
+subtest 'TfL staff can access TfL admin' => sub {
+ $mech->log_in_ok( $staffuser->email );
+ $mech->get_ok('/admin');
+ $mech->content_contains( 'This is the administration interface for' );
+ $mech->log_out_ok;
+};
+
+subtest 'Bromley staff cannot access TfL admin' => sub {
+ $mech->log_in_ok( $bromleyuser->email );
+ ok $mech->get('/admin');
+ is $mech->res->code, 403, "got 403";
+ $mech->log_out_ok;
+};
+
+subtest 'Test passwords work appropriately' => sub {
+ $mech->host('www.fixmystreet.com');
+ $mech->get_ok('/auth');
+ $user->password('dotcom');
+ $user->update;
+ $mech->submit_form_ok(
+ { with_fields => { username => $user->email, password_sign_in => 'dotcom' } },
+ "sign in using form" );
+ $mech->content_contains('Your account');
+ $mech->host('tfl.fixmystreet.com');
+ $mech->get_ok('/auth');
+ $mech->submit_form_ok(
+ { with_fields => { username => $user->email, password_sign_in => 'dotcom' } },
+ "sign in using form" );
+ $mech->content_lacks('Your account');
+
+ $user->password('tfl');
+ $user->update;
+ $mech->submit_form_ok(
+ { with_fields => { username => $user->email, password_sign_in => 'tfl' } },
+ "sign in using form" );
+ $mech->content_contains('Your account');
+ $mech->host('www.fixmystreet.com');
+ $mech->get_ok('/auth');
+ $mech->submit_form_ok(
+ { with_fields => { username => $user->email, password_sign_in => 'tfl' } },
+ "sign in using form" );
+ $mech->content_lacks('Your account');
+};
+
+my $tfl_report;
+subtest 'Test user reports are visible on cobrands appropriately' => sub {
+ ($tfl_report) = $mech->create_problems_for_body(1, $body->id, 'Test TfL report made on TfL', { cobrand => 'tfl' });
+ $mech->create_problems_for_body(1, $body->id, 'Test TfL report made on .com', { cobrand => 'fixmystreet' });
+ $mech->create_problems_for_body(1, $bromley->id, 'Test Bromley report made on .com', { cobrand => 'fixmystreet' });
+
+ $mech->log_in_ok('test@example.com');
+ $mech->get_ok('/my');
+ $mech->content_contains('1 to 2 of 2');
+ $mech->content_contains('Test TfL report made on .com');
+ $mech->content_lacks('Test TfL report made on TfL');
+ $mech->content_contains('Test Bromley report');
+
+ $mech->host('tfl.fixmystreet.com');
+ $mech->log_in_ok('test@example.com');
+ $mech->get_ok('/my');
+ $mech->content_contains('1 to 2 of 2');
+ $mech->content_contains('Test TfL report made on .com');
+ $mech->content_contains('Test TfL report made on TfL');
+ $mech->content_lacks('Test Bromley report');
+};
+
+subtest 'Test public reports are visible on cobrands appropriately' => sub {
+ $mech->get_ok('/around?pc=SW1A+1AA');
+ $mech->content_contains('Test TfL report made on .com');
+ $mech->content_contains('Test TfL report made on TfL');
+ $mech->content_lacks('Test Bromley report');
+
+ $mech->host('www.fixmystreet.com');
+ $mech->get_ok('/around?pc=SW1A+1AA');
+ $mech->content_contains('Test TfL report made on .com');
+ $mech->content_lacks('Test TfL report made on TfL');
+ $mech->content_contains('Test Bromley report');
+ $mech->content_contains('https://street.tfl/report/' . $tfl_report->id);
+ $mech->content_contains('Other problem');
+};
+
+subtest 'Test no questionnaire sending' => sub {
+ $report->update({ send_questionnaire => 1, whensent => \"current_timestamp-'7 weeks'::interval" });
+ FixMyStreet::Script::Questionnaires::send();
+ $mech->email_count_is(0);
+};
+
+};
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'tfl', 'bromley', 'fixmystreet' ],
+ MAPIT_URL => 'http://mapit.uk/',
+ COBRAND_FEATURES => {
+ internal_ips => { tfl => [ '127.0.0.1' ] },
+ safety_critical_categories => { tfl => {
+ Pothole => 1,
+ Flooding => {
+ location => [ "carriageway" ],
+ },
+ } },
+ anonymous_account => {
+ tfl => 'anonymous'
+ },
+ do_not_reply_email => {
+ tfl => 'fms-tfl-DO-NOT-REPLY@example.com',
+ },
+ },
+}, sub {
+
+for my $test (
+ {
+ host => 'www.fixmystreet.com',
+ name => "test red route categories",
+ lat => 51.4039,
+ lon => 0.018697,
+ expected => [
+ 'Accumulated Litter', # Tests TfL->_cleaning_categories
+ 'Bus stops',
+ 'Flooding',
+ 'Flytipping (Bromley)', # In the 'Street cleaning' group
+ 'Grit bins',
+ 'Pothole',
+ 'Timings',
+ 'Traffic lights',
+ 'Trees'
+ ],
+ },
+ {
+ host => 'www.fixmystreet.com',
+ name => "test non-red route categories",
+ lat => 51.4021,
+ lon => 0.01578,
+ expected => [
+ 'Accumulated Litter', # Tests TfL->_cleaning_categories
+ 'Bus stops',
+ 'Flooding (Bromley)',
+ 'Flytipping (Bromley)', # In the 'Street cleaning' group
+ 'Grit bins',
+ 'Timings',
+ 'Traffic lights',
+ 'Trees'
+ ],
+ },
+ {
+ host => 'tfl.fixmystreet.com',
+ name => "test red route categories",
+ lat => 51.4039,
+ lon => 0.018697,
+ expected => [
+ 'Bus stops',
+ 'Flooding',
+ 'Grit bins',
+ 'Pothole',
+ 'Timings',
+ 'Traffic lights',
+ 'Trees'
+ ],
+ },
+ {
+ host => 'tfl.fixmystreet.com',
+ name => "test non-red route categories",
+ lat => 51.4021,
+ lon => 0.01578,
+ expected => [
+ 'Bus stops',
+ 'Flooding',
+ 'Grit bins',
+ 'Pothole',
+ 'Timings',
+ 'Traffic lights',
+ 'Trees'
+ ],
+ },
+ {
+ host => 'bromley.fixmystreet.com',
+ name => "test red route categories",
+ lat => 51.4039,
+ lon => 0.018697,
+ expected => [
+ 'Accumulated Litter',
+ 'Bus stops',
+ 'Flooding',
+ 'Flytipping (Bromley)',
+ 'Grit bins',
+ 'Pothole',
+ 'Timings',
+ 'Traffic lights',
+ 'Trees'
+ ],
+ },
+ {
+ host => 'bromley.fixmystreet.com',
+ name => "test non-red route categories",
+ lat => 51.4021,
+ lon => 0.01578,
+ expected => [
+ 'Accumulated Litter',
+ 'Bus stops',
+ 'Flooding (Bromley)',
+ 'Flytipping (Bromley)',
+ 'Grit bins',
+ 'Timings',
+ 'Traffic lights',
+ 'Trees'
+ ],
+ },
+) {
+ subtest $test->{name} . ' on ' . $test->{host} => sub {
+ $mech->host($test->{host});
+ my $resp = $mech->get_ok_json( '/report/new/ajax?latitude=' . $test->{lat} . '&longitude=' . $test->{lon} );
+ my @actual = sort keys %{ $resp->{by_category} };
+ is_deeply \@actual, $test->{expected};
+ };
+}
+
+for my $host ( 'tfl.fixmystreet.com', 'www.fixmystreet.com', 'bromley.fixmystreet.com' ) {
+ for my $test (
+ {
+ name => "test non-safety critical category",
+ safety_critical => 'no',
+ category => "Traffic lights",
+ subject => "Problem Report: Test Report",
+ },
+ {
+ name => "test safety critical category",
+ safety_critical => 'yes',
+ category => "Pothole",
+ subject => "Dangerous Pothole Report: Test Report",
+ pc => "BR1 3EF", # this is on a red route (according to Mock::MapIt and Mock::Tilma anyway)
+ },
+ {
+ name => "test category extra field - safety critical",
+ safety_critical => 'yes',
+ category => "Flooding",
+ extra_fields => {
+ location => "carriageway",
+ },
+ subject => "Dangerous Flooding Report: Test Report",
+ pc => "BR1 3EF", # this is on a red route (according to Mock::MapIt and Mock::Tilma anyway)
+ },
+ {
+ name => "test category extra field - non-safety critical",
+ safety_critical => 'no',
+ category => "Flooding",
+ extra_fields => {
+ location => "footway",
+ },
+ subject => "Problem Report: Test Report",
+ pc => "BR1 3EF", # this is on a red route (according to Mock::MapIt and Mock::Tilma anyway)
+ },
+ ) {
+ subtest $test->{name} . ' on ' . $host => sub {
+ $mech->log_in_ok( $user->email );
+ $mech->host($host);
+ $mech->get_ok('/around');
+ my $pc = $test->{pc} || 'BR1 3UH';
+ $mech->submit_form_ok( { with_fields => { pc => $pc, } }, "submit location ($pc)" );
+ $mech->follow_link_ok( { text_regex => qr/skip this step/i, }, "follow 'skip this step' link" );
+ $mech->submit_form_ok(
+ {
+ with_fields => {
+ category => $test->{category}
+ },
+ button => 'submit_category_part_only',
+ }
+ );
+ $mech->submit_form_ok(
+ {
+ with_fields => {
+ title => 'Test Report',
+ detail => 'Test report details.',
+ may_show_name => '1',
+ category => $test->{category},
+ %{ $test->{extra_fields} || {} },
+ $host eq 'bromley.fixmystreet.com' ? (
+ fms_extra_title => 'DR',
+ first_name => "Joe",
+ last_name => "Bloggs",
+ ) : (
+ name => 'Joe Bloggs',
+ ),
+ }
+ },
+ "submit report form"
+ );
+
+ my $report = FixMyStreet::App->model('DB::Problem')->to_body( $body->id )->search(undef, {
+ order_by => { -desc => 'id' },
+ })->first;
+ ok $report, "Found the report";
+
+ is $report->get_extra_field_value('safety_critical'), $test->{safety_critical}, "safety critical flag set to " . $test->{safety_critical};
+
+ $mech->clear_emails_ok;
+ FixMyStreet::Script::Reports::send();
+ my @email = $mech->get_email;
+ is $email[0]->header('Subject'), $test->{subject};
+ if ($test->{safety_critical} eq 'yes') {
+ like $mech->get_text_body_from_email($email[0]), qr/This report is marked as safety critical./, "Safety critical message included in email body";
+ }
+ $mech->clear_emails_ok;
+
+
+ $mech->log_out_ok;
+ };
+ }
+}
+};
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'tfl',
+ MAPIT_URL => 'http://mapit.uk/',
+ COBRAND_FEATURES => { internal_ips => { tfl => [ '127.0.0.1' ] } },
+}, sub {
+ subtest 'On internal network, user not asked to sign up for 2FA' => sub {
+ $mech->get_ok('/auth');
+ $mech->submit_form_ok(
+ { with_fields => { username => $staffuser->email, password_sign_in => 'password' } },
+ "sign in using form" );
+ $mech->content_contains('Your account');
+ };
+ subtest 'On internal network, user with 2FA not asked to enter it' => sub {
+ use Auth::GoogleAuth;
+ my $auth = Auth::GoogleAuth->new;
+ my $code = $auth->code;
+
+ $staffuser->set_extra_metadata('2fa_secret', $auth->secret32);
+ $staffuser->update;
+ $mech->get_ok('/auth');
+ $mech->submit_form_ok(
+ { with_fields => { username => $staffuser->email, password_sign_in => 'password' } },
+ "sign in using form" );
+ $mech->content_lacks('generate a two-factor code');
+ $mech->content_contains('Your account');
+ };
+ subtest 'On internal network, cannot disable 2FA' => sub {
+ $mech->get_ok('/auth/generate_token');
+ $mech->content_contains('Change two-factor');
+ $mech->content_lacks('Deactivate two-factor');
+ $staffuser->unset_extra_metadata('2fa_secret');
+ $staffuser->update;
+ };
+};
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'tfl',
+ MAPIT_URL => 'http://mapit.uk/',
+}, sub {
+ subtest 'On external network, user asked to sign up for 2FA' => sub {
+ $mech->get_ok('/auth');
+ $mech->submit_form_ok(
+ { with_fields => { username => $staffuser->email, password_sign_in => 'password' } },
+ "sign in using form" );
+ $mech->content_contains('requires two-factor authentication');
+ };
+ subtest 'On external network, user with 2FA asked to enter it' => sub {
+ use Auth::GoogleAuth;
+ my $auth = Auth::GoogleAuth->new;
+ my $code = $auth->code;
+
+ $staffuser->set_extra_metadata('2fa_secret', $auth->secret32);
+ $staffuser->update;
+ $mech->get_ok('/auth');
+ $mech->submit_form_ok(
+ { with_fields => { username => $staffuser->email, password_sign_in => 'password' } },
+ "sign in using form" );
+ $mech->content_contains('Please generate a two-factor code');
+ $mech->submit_form_ok({ with_fields => { '2fa_code' => $code } }, "provide correct 2FA code" );
+ };
+ subtest 'On external network, cannot disable 2FA' => sub {
+ $mech->get_ok('/auth/generate_token');
+ $mech->content_contains('Change two-factor');
+ $mech->content_lacks('Deactivate two-factor');
+ $staffuser->unset_extra_metadata('2fa_secret');
+ $staffuser->update;
+ };
+
+ subtest 'RSS feed has correct name' => sub {
+ $mech->get_ok('/rss/xsl');
+ $mech->content_contains('RSS feed from the Street Care website');
+ $mech->content_lacks('FixMyStreet');
+ $mech->get_ok('/rss/problems');
+ $mech->content_contains('New problems on Street Care');
+ $mech->content_lacks('FixMyStreet');
+ };
+};
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'fixmystreet', 'tfl' ],
+ MAPIT_URL => 'http://mapit.uk/'
+}, sub {
+ foreach (qw(tfl.fixmystreet.com fixmystreet.com)) {
+ $mech->host($_);
+ my ($p) = $mech->create_problems_for_body(1, $body->id, 'NotResp');
+ my $c = FixMyStreet::DB->resultset('Comment')->create({
+ problem => $p, user => $p->user, anonymous => 't', text => 'Update text',
+ problem_state => 'not responsible', state => 'confirmed', mark_fixed => 0,
+ confirmed => DateTime->now(),
+ });
+ subtest "check not responsible as correct text on $_" => sub {
+ $mech->get_ok('/report/' . $p->id);
+ $mech->content_contains("not TfL’s responsibility", "not reponsible message contains correct text");
+ };
+ $p->comments->delete;
+ $p->delete;
+ }
+};
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'bromley',
+ MAPIT_URL => 'http://mapit.uk/'
+}, sub {
+
+subtest 'Bromley staff can access Bromley admin' => sub {
+ $mech->log_in_ok( $bromleyuser->email );
+ $mech->get_ok('/admin');
+ $mech->content_contains( 'This is the administration interface for' );
+ $mech->log_out_ok;
+};
+
+subtest 'TfL staff cannot access Bromley admin' => sub {
+ $mech->log_in_ok( $staffuser->email );
+ ok $mech->get('/admin');
+ is $mech->res->code, 403, "got 403";
+ $mech->log_out_ok;
+};
+
+};
+
+done_testing();
diff --git a/t/cobrand/westminster.t b/t/cobrand/westminster.t
new file mode 100644
index 000000000..54de5a160
--- /dev/null
+++ b/t/cobrand/westminster.t
@@ -0,0 +1,259 @@
+use CGI::Simple;
+use Test::MockModule;
+use FixMyStreet::TestMech;
+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 $cobrand = Test::MockModule->new('FixMyStreet::Cobrand::Westminster');
+$cobrand->mock('lookup_site_code', sub {
+ my ($self, $row) = @_;
+ return "My USRN" if $row->latitude == 51.501009;
+});
+
+my $body = $mech->create_body_ok(2504, 'Westminster City Council', {
+ send_method => 'Open311', api_key => 'key', 'endpoint' => 'e', 'jurisdiction' => 'j' });
+my $superuser = $mech->create_user_ok(
+ 'superuser@example.com',
+ name => 'Test Superuser',
+ is_superuser => 1
+);
+my $staff_user = $mech->create_user_ok(
+ 'westminster@example.com',
+ name => 'Test User',
+ from_body => $body
+);
+my $normal_user = $mech->create_user_ok(
+ 'westminster-resident@example.com',
+ name => 'Public User'
+);
+my ($report) = $mech->create_problems_for_body(1, $body->id, 'Title');
+my $comment1 = $mech->create_comment_for_problem($report, $normal_user, 'User', 'this update was left on the Westminster cobrand', 0, 'confirmed', 'confirmed', { cobrand => 'westminster' });
+my $comment2 = $mech->create_comment_for_problem($report, $normal_user, 'User', 'this update was left on the fixmystreet.com cobrand', 0, 'confirmed', 'confirmed', { cobrand => 'fixmystreet' });
+my $comment3 = $mech->create_comment_for_problem($report, $normal_user, 'User', 'this update was imported via Open311', 0, 'confirmed', 'confirmed', { cobrand => '' });
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'westminster',
+ MAPIT_URL => 'http://mapit.uk/',
+ COBRAND_FEATURES => {
+ updates_allowed => {
+ westminster => 'staff',
+ },
+ oidc_login => {
+ westminster => {
+ client_id => 'example_client_id',
+ secret => 'example_secret_key',
+ auth_uri => 'http://oidc.example.org/oauth2/v2.0/authorize',
+ token_uri => 'http://oidc.example.org/oauth2/v2.0/token',
+ display_name => 'MyWestminster'
+ }
+ }
+ }
+}, sub {
+ subtest 'Cobrand allows social auth' => sub {
+ my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker('westminster')->new();
+ ok $cobrand->social_auth_enabled;
+ };
+
+ subtest 'Login button displayed correctly' => sub {
+ $mech->get_ok("/auth");
+ $mech->content_contains("Sign in with MyWestminster");
+ };
+
+ subtest 'Reports do not have update form' => sub {
+ $mech->get_ok('/report/' . $report->id);
+ $mech->content_lacks('Provide an update');
+ };
+
+ subtest 'Reports show updates from Westminster cobrand' => sub {
+ $mech->get_ok('/report/' . $report->id);
+ $mech->content_contains($comment1->text);
+ };
+
+ subtest 'Reports show updates from Open311' => sub {
+ $mech->get_ok('/report/' . $report->id);
+ $mech->content_contains($comment3->text);
+ };
+
+ subtest "Reports don't show updates from fixmystreet.com cobrand" => sub {
+ $mech->get_ok('/report/' . $report->id);
+ $mech->content_lacks($comment2->text);
+ };
+};
+
+subtest 'Reports have an update form for superusers' => sub {
+ # Westminster cobrand disables email signin, so we have to
+ # login and *then* set the cobrand.
+ $mech->log_in_ok( $superuser->email );
+
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'westminster',
+ MAPIT_URL => 'http://mapit.uk/',
+ COBRAND_FEATURES => {
+ updates_allowed => {
+ westminster => 'staff',
+ },
+ },
+ }, sub {
+ $mech->get_ok('/report/' . $report->id);
+ $mech->content_contains('Provide an update');
+ };
+
+ $mech->log_out_ok();
+};
+
+subtest 'Reports have an update form for staff users' => sub {
+ $mech->log_in_ok( $staff_user->email );
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'westminster',
+ MAPIT_URL => 'http://mapit.uk/',
+ COBRAND_FEATURES => {
+ updates_allowed => {
+ westminster => 'staff',
+ },
+ },
+ }, sub {
+ $mech->get_ok('/report/' . $report->id);
+ $mech->content_contains('Provide an update');
+ };
+ $mech->log_out_ok();
+};
+
+for (
+ {
+ ALLOWED_COBRANDS => 'westminster',
+ MAPIT_URL => 'http://mapit.uk/',
+ COBRAND_FEATURES => {
+ oidc_login => {
+ westminster => 0
+ }
+ }
+ },
+ {
+ ALLOWED_COBRANDS => 'westminster',
+ MAPIT_URL => 'http://mapit.uk/',
+ COBRAND_FEATURES => {
+ oidc_login => {
+ hounslow => {
+ client_id => 'example_client_id',
+ secret => 'example_secret_key',
+ auth_uri => 'http://oidc.example.org/oauth2/v2.0/authorize',
+ token_uri => 'http://oidc.example.org/oauth2/v2.0/token',
+ display_name => 'MyHounslow'
+ }
+ }
+ }
+ },
+ {
+ ALLOWED_COBRANDS => 'westminster',
+ MAPIT_URL => 'http://mapit.uk/',
+ }
+) {
+ FixMyStreet::override_config $_, sub {
+ subtest 'Cobrand disallows social auth' => sub {
+ my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker('westminster')->new();
+ ok !$cobrand->social_auth_enabled;
+ };
+
+ subtest 'Login button not displayed' => sub {
+ $mech->get_ok("/auth");
+ $mech->content_lacks("Login with MyWestminster");
+ };
+ };
+}
+
+$mech->delete_problems_for_body($body->id);
+$mech->create_contact_ok(body_id => $body->id, category => 'Abandoned bike', email => "BIKE");
+($report) = $mech->create_problems_for_body(1, $body->id, 'Bike', {
+ category => "Abandoned bike", cobrand => 'westminster',
+ latitude => 51.501009, longitude => -0.141588, areas => '2504',
+});
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'westminster' ],
+ MAPIT_URL => 'http://mapit.uk/',
+ STAGING_FLAGS => { send_reports => 1, skip_checks => 0 },
+ COBRAND_FEATURES => { anonymous_account => { westminster => 'anon' } },
+}, sub {
+ subtest 'USRN set correctly' => sub {
+ 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'), 'BIKE';
+ is $c->param('attribute[USRN]'), 'My USRN';
+ };
+};
+
+for my $cobrand (qw(westminster fixmystreet)) {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => $cobrand,
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ subtest "No reporter alert created in $cobrand" => sub {
+ my $user = $mech->log_in_ok('test@example.org');
+ $mech->get_ok('/');
+ $mech->submit_form_ok( { with_fields => { pc => 'SW1A1AA' } }, "submit location" );
+ $mech->follow_link_ok( { text_regex => qr/skip this step/i, }, "follow 'skip this step' link" );
+ $mech->submit_form_ok( { with_fields => {
+ title => 'Title', detail => 'Detail', category => 'Abandoned bike', name => 'Test Example',
+ } }, 'submitted okay' );
+ is $user->alerts->count, 0;
+ };
+ };
+}
+
+my $westminster = FixMyStreet::Cobrand::Westminster->new;
+subtest 'correct config returned for USRN/UPRN lookup' => sub {
+ my $actual = $westminster->lookup_site_code_config('USRN');
+ delete $actual->{accept_feature}; # is_deeply doesn't like code
+ is_deeply $actual, {
+ buffer => 1000,
+ proxy_url => "https://tilma.mysociety.org/resource-proxy/proxy.php",
+ url => "https://westminster.assets/40/query",
+ property => 'USRN',
+ };
+ $actual = $westminster->lookup_site_code_config('UPRN');
+ delete $actual->{accept_feature}; # is_deeply doesn't like code
+ is_deeply $actual, {
+ buffer => 1000,
+ proxy_url => "https://tilma.mysociety.org/resource-proxy/proxy.php",
+ url => "https://westminster.assets/25/query",
+ property => 'UPRN',
+ accept_types => {
+ Point => 1
+ },
+ };
+};
+
+subtest 'nearest UPRN returns correct point' => sub {
+ my $cfg = {
+ accept_feature => sub { 1 },
+ property => 'UPRN',
+ accept_types => {
+ Point => 1,
+ },
+ };
+ my $features = [
+ # A couple of incorrect geometry types to check they're ignored...
+ { geometry => { type => 'Polygon' } },
+ { geometry => { type => 'LineString',
+ coordinates => [ [ 527735, 181004 ], [ 527755, 181004 ] ] },
+ properties => { fid => '20100024' } },
+ # And two points which are further away than the above linestring,
+ # the second of which is the closest to our testing point.
+ { geometry => { type => 'Point',
+ coordinates => [ 527795, 181024 ] },
+ properties => { UPRN => '10012387122' } },
+ { geometry => { type => 'Point',
+ coordinates => [ 527739, 181009 ] },
+ properties => { UPRN => '10012387123' } },
+ ];
+ is $westminster->_nearest_feature($cfg, 527745, 180994, $features), '10012387123';
+};
+
+
+done_testing();
diff --git a/t/cobrand/zurich.t b/t/cobrand/zurich.t
index ee2724a07..8c5acddca 100644
--- a/t/cobrand/zurich.t
+++ b/t/cobrand/zurich.t
@@ -1,11 +1,13 @@
# TODO
# Overdue alerts
+use utf8;
use DateTime;
use Email::MIME;
use File::Temp;
use LWP::Protocol::PSGI;
use Test::LongString;
+use Test::MockModule;
use Path::Tiny;
use t::Mock::MapItZurich;
use FixMyStreet::Script::Reports;
@@ -28,18 +30,8 @@ $cobrand->db_state_migration;
my $sample_file = path(__FILE__)->parent->parent->child("app/controller/sample.jpg");
ok $sample_file->exists, "sample file $sample_file exists";
-# This is a helper method that will send the reports but with the config
-# correctly set - notably STAGING_FLAGS send_reports needs to be true, and
-# zurich must be allowed cobrand if we want to be able to call cobrand
-# methods on it.
sub send_reports_for_zurich {
- FixMyStreet::override_config {
- STAGING_FLAGS => { send_reports => 1 },
- ALLOWED_COBRANDS => ['zurich']
- }, sub {
- # Actually send the report
- FixMyStreet::Script::Reports::send('zurich');
- };
+ FixMyStreet::Script::Reports::send();
}
sub reset_report_state {
my ($report, $created) = @_;
@@ -51,45 +43,47 @@ sub reset_report_state {
$report->whensent(undef);
$report->state('submitted');
$report->created($created) if $created;
+ $report->category('Other');
$report->update;
}
-# Front page test
-ok $mech->host("zurich.example.com"), "change host to Zurich";
+my $UPLOAD_DIR = File::Temp->newdir();
FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
+ STAGING_FLAGS => { send_reports => 1 },
+ BASE_URL => 'https://www.zurich',
+ ALLOWED_COBRANDS => 'zurich',
+ MAPIT_URL => 'http://mapit.zurich/',
+ MAPIT_TYPES => [ 'O08' ],
+ MAPIT_ID_WHITELIST => [ 423017 ],
+ MAP_TYPE => 'Zurich,OSM',
+ PHOTO_STORAGE_BACKEND => 'FileSystem',
+ PHOTO_STORAGE_OPTIONS => {
+ UPLOAD_DIR => $UPLOAD_DIR,
+ },
}, sub {
- $mech->get_ok('/');
-};
+
+# Front page test
+ok $mech->host("zurich.example.com"), "change host to Zurich";
+$mech->get_ok('/');
$mech->content_like( qr/zurich/i );
# Set up bodies
my $zurich = $mech->create_body_ok( 1, 'Zurich' );
-$zurich->parent( undef );
-$zurich->update;
-my $division = $mech->create_body_ok( 2, 'Division 1' );
-$division->parent( $zurich->id );
-$division->send_method( 'Zurich' );
-$division->endpoint( 'division@example.org' );
-$division->update;
-$division->body_areas->find_or_create({ area_id => 423017 });
-my $subdivision = $mech->create_body_ok( 3, 'Subdivision A' );
-$subdivision->parent( $division->id );
-$subdivision->send_method( 'Zurich' );
-$subdivision->endpoint( 'subdivision@example.org' );
-$subdivision->update;
-my $external_body = $mech->create_body_ok( 4, 'External Body' );
-$external_body->send_method( 'Zurich' );
-$external_body->endpoint( 'external_body@example.net' );
-$external_body->update;
+my $division = $mech->create_body_ok( 423017, 'Division 1', {
+ parent => $zurich->id, send_method => 'Zurich', endpoint => 'division@example.org' } );
+my $division2 = $mech->create_body_ok( 423017, 'Division 2', {
+ parent => $zurich->id, send_method => 'Zurich', endpoint => 'division2@example.org' } );
+my $subdivision = $mech->create_body_ok( 3, 'Subdivision A',
+ { parent => $division->id, send_method => 'Zurich', endpoint => 'subdivision@example.org' } );
+my $external_body = $mech->create_body_ok( 4, 'External Body',
+ { send_method => 'Zurich', endpoint => 'external_body@example.net' } );
+my $external_body2 = $mech->create_body_ok( 4, 'Another Body External',
+ { send_method => 'Zurich', endpoint => 'external_body2@example.net' } );
sub get_export_rows_count {
my $mech = shift;
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- }, sub {
- $mech->get_ok( '/admin/stats?export=1' );
- };
+ my $extra = shift || '';
+ $mech->get_ok( '/admin/stats?export=1' . $extra);
is $mech->res->code, 200, 'csv retrieved ok';
is $mech->content_type, 'text/csv', 'content_type correct' and do {
my @lines = split /\n/, $mech->content;
@@ -117,29 +111,24 @@ my @reports = $mech->create_problems_for_body( 1, $division->id, 'Test', {
});
my $report = $reports[0];
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
-}, sub {
- $mech->get_ok( '/report/' . $report->id );
-};
-$mech->content_contains('&Uuml;berpr&uuml;fung ausstehend')
+$mech->get_ok( '/report/' . $report->id );
+$mech->content_contains('Überprüfung ausstehend')
or die $mech->content;
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
-}, sub {
- my $json = $mech->get_ok_json( '/report/ajax/' . $report->id );
- is $json->{report}->{title}, "&Uuml;berpr&uuml;fung ausstehend", "correct title";
- is $json->{report}->{state}, "submitted", "correct state";
-};
+my $json = $mech->get_ok_json( '/report/ajax/' . $report->id );
+is $json->{report}->{title}, "Überprüfung ausstehend", "correct title";
+is $json->{report}->{state}, "submitted", "correct state";
+
+$report->state('fixed - council');
+$report->set_extra_metadata(public_response => 'Freundliche Grüsse');
+$report->update;
+$json = $mech->get_ok_json( '/report/ajax/' . $report->id );
+is $json->{report}->{state}, "closed", "correct state";
+is $json->{updates}->{details}, "Freundliche Grüsse", "correct public response";
+
+$report->update({ state => 'submitted' });
subtest "Banners are displayed correctly" => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
for my $test (
{
description => 'new report',
@@ -162,8 +151,8 @@ subtest "Banners are displayed correctly" => sub {
{
description => 'closed report',
state => 'external',
- banner_id => 'closed',
- banner_text => 'Extern',
+ banner_id => 'fixed',
+ banner_text => 'Beantwortet',
},
{
description => 'in progress report',
@@ -211,17 +200,14 @@ subtest "Banners are displayed correctly" => sub {
};
}
$report->update({ state => 'submitted' });
- };
};
-# Check logging in to deal with this report
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
-}, sub {
+my $user;
+subtest 'check logging in to deal with this report' => sub {
$mech->get_ok( '/admin' );
is $mech->uri->path, '/auth', "got sent to the sign in page";
- my $user = $mech->log_in_ok( 'dm1@example.org') ;
+ $user = $mech->log_in_ok( 'dm1@example.org') ;
$user->from_body( undef );
$user->update;
ok $mech->get( '/admin' );
@@ -230,12 +216,12 @@ FixMyStreet::override_config {
$user->update;
$mech->get_ok( '/admin' );
-};
-is $mech->uri->path, '/admin', "am logged in";
+ is $mech->uri->path, '/admin', "am logged in";
-$mech->content_contains( 'report_edit/' . $report->id );
-$mech->content_contains( DateTime->now->strftime("%d.%m.%Y") );
-$mech->content_contains( 'Erfasst' );
+ $mech->content_contains( 'report_edit/' . $report->id );
+ $mech->content_contains( DateTime->now->strftime("%d.%m.%Y") );
+ $mech->content_contains( 'Erfasst' );
+};
subtest "changing of categories" => sub {
# create a few categories (which are actually contacts)
@@ -260,13 +246,8 @@ subtest "changing of categories" => sub {
ok ( !$comments_rs->first, "There are no comments yet" );
# change the category via the web interface
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->submit_form_ok( { with_fields => { category => 'Cat2' } } );
- };
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->submit_form_ok( { with_fields => { category => 'Cat2' } } );
# check changes correctly saved
$report->discard_changes();
@@ -280,6 +261,38 @@ subtest "changing of categories" => sub {
$report->update({category => $original_category });
};
+subtest "private categories" => sub {
+ $mech->log_in_ok( 'super@example.org' );
+ $mech->get_ok('/admin/bodies');
+ $mech->follow_link_ok({ text => 'Division 1' });
+ $mech->submit_form_ok({ with_fields => {
+ category => 'Allgemein',
+ state => 'inactive',
+ email => 'allgemein@example.org',
+ 'extra[admin_label]' => 'StadtPeople',
+ 'extra[abbreviation]' => 'STA',
+ note => 'New',
+ }});
+ $mech->follow_link_ok({ text => 'Allgemein' });
+ $mech->content_contains('<option value="inactive" selected>');
+ $mech->content_like(qr/admin_label.*?StadtPeople/);
+
+ $mech->get_ok( '/around?lat=47.381817&lon=8.529156' );
+ $mech->content_lacks('StadtPeople');
+ $mech->content_contains('Allgemein');
+ $mech->get_ok( '/report/new?lat=47.381817&lon=8.529156' );
+ $mech->content_lacks('StadtPeople');
+ $mech->content_lacks('Allgemein');
+
+ $report->update({ category => 'Allgemein' });
+ $mech->get_ok('/report/' . $report->id);
+ $mech->content_lacks('StadtPeople');
+ $mech->content_contains('Allgemein');
+
+ $mech->get_ok('/admin/report_edit/' . $report->id);
+ $mech->content_contains('<option value="Allgemein">StadtPeople (STA)</option>');
+};
+
sub get_moderated_count {
# my %date_params = ( );
# my $moderated = FixMyStreet::DB->resultset('Problem')->search({
@@ -288,17 +301,12 @@ sub get_moderated_count {
# use a separate mech to avoid stomping on test state
my $mech = FixMyStreet::TestMech->new;
- my $user = $mech->log_in_ok( 'super@example.org' );
+ $mech->log_in_ok( 'super@example.org' );
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- }, sub {
- $mech->get( '/admin/stats' );
- };
+ $mech->get( '/admin/stats' );
if ($mech->content =~/Innerhalb eines Arbeitstages moderiert: (\d+)/) {
return $1;
- }
- else {
+ } else {
fail sprintf "Could not get moderation results (%d)", $mech->status;
return undef;
}
@@ -306,127 +314,112 @@ sub get_moderated_count {
subtest "report_edit" => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
+ reset_report_state($report);
+ ok ( ! $report->get_extra_metadata('moderated_overdue'), 'Report currently unmoderated' );
+ is get_moderated_count(), 0;
- reset_report_state($report);
- ok ( ! $report->get_extra_metadata('moderated_overdue'), 'Report currently unmoderated' );
- is get_moderated_count(), 0;
-
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->content_contains( 'Unbest&auml;tigt' ); # Unconfirmed email
- $mech->submit_form_ok( { with_fields => { state => 'confirmed' } } );
- $mech->get_ok( '/report/' . $report->id );
+ $mech->log_in_ok( 'dm1@example.org') ;
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->content_contains( 'Unbestätigt' ); # Unconfirmed email
+ $mech->submit_form_ok( { with_fields => { state => 'confirmed' } } );
+ $mech->get_ok( '/report/' . $report->id );
- $report->discard_changes();
+ $report->discard_changes();
- $mech->content_contains('Aufgenommen');
- $mech->content_contains('Test Test');
- $mech->content_lacks('photo/' . $report->id . '.0.jpeg');
- $mech->email_count_is(0);
+ $mech->content_contains('Aufgenommen');
+ $mech->content_contains('Test Test');
+ $mech->content_lacks('photo/' . $report->id . '.0.jpeg');
+ $mech->email_count_is(0);
- $report->discard_changes;
+ $report->discard_changes;
- is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Report now marked moderated' );
- is get_moderated_count(), 1;
+ is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Report now marked moderated' );
+ is get_moderated_count(), 1;
- # Set state back to 10 days ago so that report is overdue
- my $created = $report->created;
- reset_report_state($report, $created->clone->subtract(days => 10));
+ # Set state back to 10 days ago so that report is overdue
+ my $created = $report->created;
+ reset_report_state($report, $created->clone->subtract(days => 10));
- is get_moderated_count(), 0;
+ is get_moderated_count(), 0;
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->submit_form_ok( { with_fields => { state => 'confirmed' } } );
- $mech->get_ok( '/report/' . $report->id );
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->submit_form_ok( { with_fields => { state => 'confirmed' } } );
+ $mech->get_ok( '/report/' . $report->id );
- $report->discard_changes;
- is ( $report->get_extra_metadata('moderated_overdue'), 1, 'moderated_overdue set correctly when overdue' );
- is get_moderated_count(), 0, 'Moderated count not increased when overdue';
+ $report->discard_changes;
+ is ( $report->get_extra_metadata('moderated_overdue'), 1, 'moderated_overdue set correctly when overdue' );
+ is get_moderated_count(), 0, 'Moderated count not increased when overdue';
- reset_report_state($report, $created);
+ reset_report_state($report, $created);
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->submit_form_ok( { with_fields => { state => 'confirmed' } } );
- $mech->get_ok( '/report/' . $report->id );
- $report->discard_changes;
- is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Marking confirmed sets moderated_overdue' );
- is ( $report->get_extra_metadata('closed_overdue'), undef, 'Marking confirmed does NOT set closed_overdue' );
- is get_moderated_count(), 1;
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->submit_form_ok( { with_fields => { state => 'confirmed' } } );
+ $mech->get_ok( '/report/' . $report->id );
+ $report->discard_changes;
+ is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Marking confirmed sets moderated_overdue' );
+ is ( $report->get_extra_metadata('closed_overdue'), undef, 'Marking confirmed does NOT set closed_overdue' );
+ is get_moderated_count(), 1;
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->submit_form_ok( { with_fields => { state => 'hidden' } } );
- $mech->get_ok( '/report/' . $report->id, 'still visible as response not published yet' );
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->submit_form_ok( { with_fields => { state => 'hidden' } } );
+ $mech->get_ok( '/report/' . $report->id, 'still visible as response not published yet' );
- $report->discard_changes;
- is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Still marked moderated_overdue' );
- is ( $report->get_extra_metadata('closed_overdue'), undef, "Marking hidden doesn't set closed_overdue..." );
- is ( $report->state, 'feedback pending', 'Marking hidden actually sets state to feedback pending');
- is ( $report->get_extra_metadata('closure_status'), 'hidden', 'Marking hidden sets closure_status to hidden');
- is get_moderated_count(), 1, 'Check still counted moderated'
- or diag $report->get_column('extra');
-
- # publishing actually sets hidden
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->form_with_fields( 'status_update' );
- $mech->submit_form_ok( { button => 'publish_response' } );
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $report->discard_changes;
+ $report->discard_changes;
+ is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Still marked moderated_overdue' );
+ is ( $report->get_extra_metadata('closed_overdue'), undef, "Marking hidden doesn't set closed_overdue..." );
+ is ( $report->state, 'feedback pending', 'Marking hidden actually sets state to feedback pending');
+ is ( $report->get_extra_metadata('closure_status'), 'hidden', 'Marking hidden sets closure_status to hidden');
+ is get_moderated_count(), 1, 'Check still counted moderated'
+ or diag $report->get_column('extra');
+
+ # publishing actually sets hidden
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->form_with_fields( 'status_update' );
+ $mech->submit_form_ok( { button => 'publish_response' } );
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $report->discard_changes;
- is ( $report->get_extra_metadata('closed_overdue'), 0, "Closing as hidden sets closed_overdue..." );
- is ( $report->state, 'hidden', 'Closing as hidden sets state to hidden');
- is ( $report->get_extra_metadata('closure_status'), undef, 'Closing as hidden unsets closure_status');
+ is ( $report->get_extra_metadata('closed_overdue'), 0, "Closing as hidden sets closed_overdue..." );
+ is ( $report->state, 'hidden', 'Closing as hidden sets state to hidden');
+ is ( $report->get_extra_metadata('closure_status'), undef, 'Closing as hidden unsets closure_status');
- $mech->submit_form_ok( { with_fields => { new_internal_note => 'Initial internal note.' } } );
- $report->discard_changes;
- is ( $report->state, 'hidden', 'Another internal note does not reopen');
+ $mech->submit_form_ok( { with_fields => { new_internal_note => 'Initial internal note.' } } );
+ $report->discard_changes;
+ is ( $report->state, 'hidden', 'Another internal note does not reopen');
- $mech->get( '/report/' . $report->id);
- is $mech->res->code, 410;
+ $mech->get( '/report/' . $report->id);
+ is $mech->res->code, 410;
- reset_report_state($report);
- is ( $report->get_extra_metadata('moderated_overdue'), undef, 'Sanity check' );
- is get_moderated_count(), 0;
+ reset_report_state($report);
+ is ( $report->get_extra_metadata('moderated_overdue'), undef, 'Sanity check' );
+ is get_moderated_count(), 0;
- # Check that setting to 'hidden' also triggers moderation
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->submit_form_ok( { with_fields => { state => 'hidden' } } );
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->form_with_fields( 'status_update' );
- $mech->submit_form_ok( { button => 'publish_response' } );
+ # Check that setting to 'hidden' also triggers moderation
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->submit_form_ok( { with_fields => { state => 'hidden' } } );
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->form_with_fields( 'status_update' );
+ $mech->submit_form_ok( { button => 'publish_response' } );
- $report->discard_changes;
- is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Marking hidden from scratch sets moderated_overdue' );
- is ( $report->get_extra_metadata('closed_overdue'), 0, 'Marking hidden from scratch also set closed_overdue' );
- is get_moderated_count(), 1;
+ $report->discard_changes;
+ is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Marking hidden from scratch sets moderated_overdue' );
+ is ( $report->get_extra_metadata('closed_overdue'), 0, 'Marking hidden from scratch also set closed_overdue' );
+ is get_moderated_count(), 1;
- is ($cobrand->get_or_check_overdue($report), 0, 'sanity check');
- $report->update({ created => $created->clone->subtract(days => 10) });
- is ($cobrand->get_or_check_overdue($report), 0, 'overdue call not increased');
+ is ($cobrand->get_or_check_overdue($report), 0, 'sanity check');
+ $report->update({ created => $created->clone->subtract(days => 10) });
+ is ($cobrand->get_or_check_overdue($report), 0, 'overdue call not increased');
- reset_report_state($report, $created);
- }
+ reset_report_state($report, $created);
};
# Give the report three photos
-my $UPLOAD_DIR = File::Temp->newdir();
my @files = map { $_ x 40 . ".jpeg" } (1..3);
$sample_file->copy(path($UPLOAD_DIR, $_)) for @files;
$report->photo(join(',', @files));
$report->update;
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAPIT_URL => 'http://mapit.zurich/',
- MAP_TYPE => 'Zurich,OSM',
- PHOTO_STORAGE_BACKEND => 'FileSystem',
- PHOTO_STORAGE_OPTIONS => {
- UPLOAD_DIR => $UPLOAD_DIR,
- },
-}, sub {
- # Photo publishing
+subtest 'Photo publishing' => sub {
$mech->get_ok( '/admin/report_edit/' . $report->id );
$mech->submit_form_ok( { with_fields => { state => 'confirmed', publish_photo_1 => 1 } } );
$mech->get_ok( '/around?lat=' . $report->latitude . ';lon=' . $report->longitude);
@@ -469,50 +462,37 @@ $mech->log_out_ok;
subtest 'SDM' => sub {
my $user = $mech->log_in_ok( 'sdm1@example.org') ;
$user->update({ from_body => undef });
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- }, sub {
- ok $mech->get( '/admin' );
- };
+ ok $mech->get( '/admin' );
is $mech->res->code, 403, 'Got 403';
$user->from_body( $subdivision->id );
$user->update;
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- }, sub {
- $mech->get_ok( '/admin' );
- };
+ $mech->get_ok( '/admin' );
is $mech->uri->path, '/admin', "am logged in";
$mech->content_contains( 'report_edit/' . $report->id );
$mech->content_contains( DateTime->now->strftime("%d.%m.%Y") );
$mech->content_contains( 'In Bearbeitung' );
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->content_contains( 'Initial internal note' );
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->content_contains( 'Initial internal note' );
- $mech->submit_form_ok( { with_fields => { status_update => 'This is an update.' } } );
- is $mech->uri->path, '/admin/report_edit/' . $report->id, "still on edit page";
- $mech->content_contains('This is an update');
- ok $mech->form_with_fields( 'status_update' );
- $mech->submit_form_ok( { button => 'no_more_updates' } );
- is $mech->uri->path, '/admin/summary', "redirected now finished with report.";
+ $mech->submit_form_ok( { with_fields => { status_update => 'This is an update.' } } );
+ is $mech->uri->path, '/admin/report_edit/' . $report->id, "still on edit page";
+ $mech->content_contains('This is an update');
+ ok $mech->form_with_fields( 'status_update' );
+ $mech->submit_form_ok( { button => 'no_more_updates' } );
+ is $mech->uri->path, '/admin/summary', "redirected now finished with report.";
- # Can still view the edit page but can't change anything
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->content_contains('<input disabled');
- $mech->submit_form_ok( { with_fields => { status_update => 'This is a disallowed update.' } } );
- $mech->content_lacks('This is a disallowed update');
+ # Can still view the edit page but can't change anything
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->content_contains('<input disabled');
+ $mech->submit_form_ok( { with_fields => { status_update => 'This is a disallowed update.' } } );
+ $mech->content_lacks('This is a disallowed update');
- $mech->get_ok( '/report/' . $report->id );
- $mech->content_contains('In Bearbeitung');
- $mech->content_contains('Test Test');
- };
+ $mech->get_ok( '/report/' . $report->id );
+ $mech->content_contains('In Bearbeitung');
+ $mech->content_contains('Test Test');
send_reports_for_zurich();
$email = $mech->get_email;
@@ -524,119 +504,99 @@ subtest 'SDM' => sub {
is $report->state, 'feedback pending', 'Report now in feedback pending state';
subtest 'send_back' => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- $report->update({ bodies_str => $subdivision->id, state => 'in progress' });
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->submit_form_ok( { form_number => 2, button => 'send_back' } );
- $report->discard_changes;
- is $report->state, 'confirmed', 'Report sent back to confirmed state';
- is $report->bodies_str, $division->id, 'Report sent back to division';
- };
+ $report->update({ bodies_str => $subdivision->id, state => 'in progress' });
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->submit_form_ok( { form_number => 2, button => 'send_back' } );
+ $report->discard_changes;
+ is $report->state, 'confirmed', 'Report sent back to confirmed state';
+ is $report->bodies_str, $division->id, 'Report sent back to division';
};
subtest 'not contactable' => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- $report->update({ bodies_str => $subdivision->id, state => 'in progress' });
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->submit_form_ok( { button => 'not_contactable', form_number => 2 } );
- $report->discard_changes;
- is $report->state, 'feedback pending', 'Report sent back to Rueckmeldung ausstehend state';
- is $report->get_extra_metadata('closure_status'), 'not contactable', 'Report sent back to not_contactable state';
- is $report->bodies_str, $division->id, 'Report sent back to division';
- };
+ $report->update({ bodies_str => $subdivision->id, state => 'in progress' });
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->submit_form_ok( { button => 'not_contactable', form_number => 2 } );
+ $report->discard_changes;
+ is $report->state, 'feedback pending', 'Report sent back to Rueckmeldung ausstehend state';
+ is $report->get_extra_metadata('closure_status'), 'not contactable', 'Report sent back to not_contactable state';
+ is $report->bodies_str, $division->id, 'Report sent back to division';
};
$mech->log_out_ok;
};
-my $user = $mech->log_in_ok( 'dm1@example.org') ;
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
-}, sub {
+subtest 'Test publishing of final update by DM' => sub {
+ $user = $mech->log_in_ok( 'dm1@example.org');
$mech->get_ok( '/admin' );
-};
-reset_report_state($report);
-$report->update({ state => 'feedback pending' });
+ reset_report_state($report);
+ $report->update({ state => 'feedback pending' });
-$mech->content_contains( 'report_edit/' . $report->id );
-$mech->content_contains( DateTime->now->strftime("%d.%m.%Y") );
+ $mech->content_contains( 'report_edit/' . $report->id );
+ $mech->content_contains( DateTime->now->strftime("%d.%m.%Y") );
-# User confirms their email address
-$report->set_extra_metadata(email_confirmed => 1);
-$report->confirmed(DateTime->now);
-$report->update;
+ # User confirms their email address
+ $report->set_extra_metadata(email_confirmed => 1);
+ $report->confirmed(DateTime->now);
+ $report->update;
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
-}, sub {
# Quick RSS check here, while we have a report
$mech->get_ok('/rss/problems');
+ my $module = Test::MockModule->new('FixMyStreet::Geocode::Zurich');
+ $module->mock(admin_district => sub { 'Admin district' });
+
$mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->content_lacks( 'Unbest&auml;tigt' ); # Confirmed email
+
+ $mech->content_contains('Admin district');
+
+ $mech->content_lacks( 'Unbestätigt' ); # Confirmed email
$mech->submit_form_ok( { with_fields => { status_update => 'FINAL UPDATE' } } );
$mech->form_with_fields( 'status_update' );
$mech->submit_form_ok( { button => 'publish_response' } );
$mech->get_ok( '/report/' . $report->id );
+ $mech->content_contains('Beantwortet');
+ $mech->content_contains('Test Test');
+ $mech->content_contains('FINAL UPDATE');
+
+ $email = $mech->get_email;
+ like $email->header('To'), qr/test\@example.com/, 'to line looks correct';
+ like $email->header('From'), qr/do-not-reply\@example.org/, 'from line looks correct';
+ like $email->body, qr/FINAL UPDATE/, 'body looks correct';
+ $mech->clear_emails_ok;
};
-$mech->content_contains('Beantwortet');
-$mech->content_contains('Test Test');
-$mech->content_contains('FINAL UPDATE');
-
-$email = $mech->get_email;
-like $email->header('To'), qr/test\@example.com/, 'to line looks correct';
-like $email->header('From'), qr/do-not-reply\@example.org/, 'from line looks correct';
-like $email->body, qr/FINAL UPDATE/, 'body looks correct';
-$mech->clear_emails_ok;
-# Assign feedback pending (via confirmed), don't confirm email
-@reports = $mech->create_problems_for_body( 1, $division->id, 'Second', {
- state => 'submitted',
- confirmed => undef,
- cobrand => 'zurich',
- areas => ',423017,',
-});
-$report = $reports[0];
+subtest "Assign feedback pending (via confirmed), don't confirm email, no email sent" => sub {
+ @reports = $mech->create_problems_for_body( 1, $division->id, 'Second', {
+ state => 'submitted',
+ confirmed => undef,
+ cobrand => 'zurich',
+ areas => ',423017,',
+ });
+ $report = $reports[0];
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
-}, sub {
$mech->get_ok( '/admin/report_edit/' . $report->id );
$mech->submit_form_ok( { with_fields => { state => 'confirmed' } } );
$mech->get_ok( '/admin/report_edit/' . $report->id );
$mech->submit_form_ok( { with_fields => { state => 'feedback pending' } } );
$mech->get_ok( '/report/' . $report->id );
-};
-$mech->content_contains('In Bearbeitung');
-$mech->content_contains('Second Test');
+ $mech->content_contains('In Bearbeitung');
+ $mech->content_contains('Second Test');
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
-}, sub {
$mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->content_contains( 'Unbest&auml;tigt' );
+ $mech->content_contains( 'Unbestätigt' );
$report->discard_changes;
$mech->form_with_fields( 'status_update' );
$mech->submit_form_ok( { button => 'publish_response', with_fields => { status_update => 'FINAL UPDATE' } } );
$mech->get_ok( '/report/' . $report->id );
-};
-$mech->content_contains('Beantwortet');
-$mech->content_contains('Second Test');
-$mech->content_contains('FINAL UPDATE');
+ $mech->content_contains('Beantwortet');
+ $mech->content_contains('Second Test');
+ $mech->content_contains('FINAL UPDATE');
-$mech->email_count_is(0);
+ $mech->email_count_is(0);
+};
# Report assigned to third party
@@ -650,31 +610,27 @@ $report = $reports[0];
subtest "external report triggers email" => sub {
my $EXTERNAL_MESSAGE = 'Look Ma, no hands!';
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- # required to see body_external field
- $report->state('feedback pending');
- $report->set_extra_metadata('closure_status' => 'external');
- # Set the public_response manually here because the default one will have line breaks that get escaped as HTML, causing the comparison to fail.
- $report->set_extra_metadata('public_response' => 'Freundliche Gruesse Ihre Stadt Zuerich');
- $report->update;
+ # required to see body_external field
+ $report->state('feedback pending');
+ $report->set_extra_metadata('closure_status' => 'external');
+ # Set the public_response manually here because the default one will have line breaks that get escaped as HTML, causing the comparison to fail.
+ $report->set_extra_metadata('public_response' => 'Freundliche Gruesse Ihre Stadt Zuerich');
+ $report->update;
+
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->form_with_fields( 'publish_response' );
+ $mech->submit_form_ok( {
+ button => 'publish_response',
+ with_fields => {
+ body_external => $external_body->id,
+ external_message => $EXTERNAL_MESSAGE,
+ } });
+ $report->discard_changes;
+ $mech->get_ok( '/report/' . $report->id );
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->form_with_fields( 'publish_response' );
- $mech->submit_form_ok( {
- button => 'publish_response',
- with_fields => {
- body_external => $external_body->id,
- external_message => $EXTERNAL_MESSAGE,
- } });
- $report->discard_changes;
- $mech->get_ok( '/report/' . $report->id );
- };
is ($report->state, 'external', 'Report was closed correctly');
- $mech->content_contains('Extern')
+ $mech->content_contains('Beantwortet')
or die $mech->content;
$mech->content_contains('Third Test');
$mech->content_contains($report->get_extra_metadata('public_response')) or die $mech->content;
@@ -688,30 +644,25 @@ subtest "external report triggers email" => sub {
$mech->clear_emails_ok;
subtest "Test third_personal boolean setting" => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- $mech->get_ok( '/admin' );
- # required to see body_external field
- $report->state('feedback pending');
- $report->set_extra_metadata('closure_status' => 'external');
- $report->set_extra_metadata('public_response' => 'Freundliche Gruesse Ihre Stadt Zuerich');
- $report->update;
+ $mech->get_ok( '/admin' );
+ # required to see body_external field
+ $report->state('feedback pending');
+ $report->set_extra_metadata('closure_status' => 'external');
+ $report->set_extra_metadata('public_response' => 'Freundliche Gruesse Ihre Stadt Zuerich');
+ $report->update;
- is $mech->uri->path, '/admin', "am logged in";
- $mech->content_contains( 'report_edit/' . $report->id );
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->form_with_fields( 'publish_response' );
- $mech->submit_form_ok( {
- button => 'publish_response',
- with_fields => {
- body_external => $external_body->id,
- third_personal => 1,
- } });
- $mech->get_ok( '/report/' . $report->id );
- };
- $mech->content_contains('Extern');
+ is $mech->uri->path, '/admin', "am logged in";
+ $mech->content_contains( 'report_edit/' . $report->id );
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->form_with_fields( 'publish_response' );
+ $mech->submit_form_ok( {
+ button => 'publish_response',
+ with_fields => {
+ body_external => $external_body->id,
+ third_personal => 1,
+ } });
+ $mech->get_ok( '/report/' . $report->id );
+ $mech->content_contains('Beantwortet');
$mech->content_contains('Third Test');
$mech->content_contains($report->get_extra_metadata('public_response'));
send_reports_for_zurich();
@@ -724,30 +675,25 @@ subtest "external report triggers email" => sub {
};
subtest "Test external wish sending" => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- # set as wish
- $report->discard_changes;
- $report->state('feedback pending');
- $report->set_extra_metadata('closure_status' => 'wish');
- $report->update;
- is ($report->state, 'feedback pending', 'Sanity check') or die;
-
- $mech->get_ok( '/admin/report_edit/' . $report->id );
-
- $mech->form_with_fields( 'publish_response' );
- $mech->submit_form_ok( {
- button => 'publish_response',
- with_fields => {
- body_external => $external_body->id,
- external_message => $EXTERNAL_MESSAGE,
- } });
- # Wishes publicly viewable
- $mech->get_ok( '/report/' . $report->id );
- $mech->content_contains('Freundliche Gruesse Ihre Stadt Zuerich');
- };
+ # set as wish
+ $report->discard_changes;
+ $report->state('feedback pending');
+ $report->set_extra_metadata('closure_status' => 'wish');
+ $report->update;
+ is ($report->state, 'feedback pending', 'Sanity check') or die;
+
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+
+ $mech->form_with_fields( 'publish_response' );
+ $mech->submit_form_ok( {
+ button => 'publish_response',
+ with_fields => {
+ body_external => $external_body->id,
+ external_message => $EXTERNAL_MESSAGE,
+ } });
+ # Wishes publicly viewable
+ $mech->get_ok( '/report/' . $report->id );
+ $mech->content_contains('Freundliche Gruesse Ihre Stadt Zuerich');
send_reports_for_zurich();
$email = $mech->get_email;
like $email->header('Subject'), qr/Weitergeleitete Meldung/, 'subject looks okay';
@@ -760,30 +706,26 @@ subtest "external report triggers email" => sub {
subtest "Closure email includes public response" => sub {
my $PUBLIC_RESPONSE = "This is the public response to your report. Freundliche Gruesse.";
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- # set as extern
- reset_report_state($report);
- $report->state('feedback pending');
- $report->set_extra_metadata('closure_status' => 'external');
- $report->set_extra_metadata('email_confirmed' => 1);
- $report->unset_extra_metadata('public_response');
- $report->update;
- is ($report->state, 'feedback pending', 'Sanity check') or die;
-
- $mech->get_ok( '/admin/report_edit/' . $report->id );
-
- $mech->form_with_fields( 'publish_response' );
- $mech->submit_form_ok( {
- button => 'publish_response',
- with_fields => {
- body_external => $external_body->id,
- external_message => $EXTERNAL_MESSAGE,
- status_update => $PUBLIC_RESPONSE,
- } });
- };
+ # set as extern
+ reset_report_state($report);
+ $report->state('feedback pending');
+ $report->set_extra_metadata('closure_status' => 'external');
+ $report->set_extra_metadata('email_confirmed' => 1);
+ $report->unset_extra_metadata('public_response');
+ $report->update;
+ is ($report->state, 'feedback pending', 'Sanity check') or die;
+
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+
+ $mech->form_with_fields( 'publish_response' );
+ $mech->submit_form_ok( {
+ button => 'publish_response',
+ with_fields => {
+ body_external => $external_body->id,
+ external_message => $EXTERNAL_MESSAGE,
+ status_update => $PUBLIC_RESPONSE,
+ } });
+
$email = $mech->get_email;
my $report_id = $report->id;
like Encode::decode('MIME-Header', $email->header('Subject')), qr/Meldung #$report_id/, 'subject looks okay';
@@ -798,91 +740,89 @@ subtest "superuser and dm can see stats" => sub {
$mech->log_out_ok;
$user = $mech->log_in_ok( 'super@example.org' );
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- }, sub {
- $mech->get( '/admin/stats' );
- };
+ $mech->get( '/admin/stats' );
is $mech->res->code, 200, "superuser should be able to see stats page";
$mech->log_out_ok;
$user = $mech->log_in_ok( 'dm1@example.org' );
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- }, sub {
- $mech->get( '/admin/stats' );
- };
+ $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' );
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAPIT_URL => 'http://mapit.zurich/',
- }, sub {
- $mech->get( '/admin/body/' . $zurich->id );
- };
+ $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' );
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAPIT_URL => 'http://mapit.zurich/',
- MAPIT_TYPES => [ 'O08' ],
- MAPIT_ID_WHITELIST => [ 423017 ],
- }, sub {
- $mech->get_ok( '/admin/bodies' );
- };
+ $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 {
- FixMyStreet::override_config {
- MAPIT_TYPES => [ 'O08' ],
- MAPIT_URL => 'http://mapit.zurich/',
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAPIT_ID_WHITELIST => [ 423017 ],
- MAP_TYPE => 'Zurich,OSM',
- }, 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&ouml;tigt' );
- $mech->log_out_ok;
- };
+ $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' );
+ $mech->log_out_ok;
};
subtest "phone number is not mandatory for reports from mobile apps" => sub {
- FixMyStreet::override_config {
- MAPIT_TYPES => [ 'O08' ],
- MAPIT_URL => 'http://mapit.zurich/',
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAPIT_ID_WHITELIST => [ 423017 ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- $mech->post_ok( '/report/new/mobile?lat=47.381817&lon=8.529156' , {
- service => 'iPhone',
- detail => 'Problem-Bericht',
- lat => 47.381817,
- lon => 8.529156,
- email => 'user@example.org',
- pc => '',
- name => '',
- category => 'bad category',
- });
- my $res = $mech->response;
- ok $res->header('Content-Type') =~ m{^application/json\b}, 'response should be json';
- unlike $res->content, qr/Diese Information wird ben&ouml;tigt/, 'response should not contain phone error';
- # Clear out the mailq
- $mech->clear_emails_ok;
- };
+ $mech->post_ok( '/report/new/mobile?lat=47.381817&lon=8.529156' , {
+ service => 'iPhone',
+ detail => 'Problem-Bericht',
+ lat => 47.381817,
+ lon => 8.529156,
+ email => 'user@example.org',
+ pc => '',
+ name => '',
+ category => 'bad category',
+ });
+ my $res = $mech->response;
+ ok $res->header('Content-Type') =~ m{^application/json\b}, 'response should be json';
+ unlike $res->content, qr/Diese Information wird benötigt/, 'response should not contain phone error';
+ # Clear out the mailq
+ $mech->clear_emails_ok;
+};
+
+subtest "link external body to category" => sub {
+ $mech->log_in_ok( 'super@example.org' );
+ $mech->get_ok( '/admin/body/' . $zurich->id );
+ $mech->content_lacks('extra[category]');
+ $mech->get_ok( '/admin/body/' . $division->id );
+ $mech->content_lacks('extra[category]');
+ $mech->get_ok( '/admin/body/' . $subdivision->id );
+ $mech->content_lacks('extra[category]');
+ $mech->get_ok( '/admin/body/' . $external_body->id );
+ $mech->content_contains('extra[category]');
+ $mech->submit_form_ok({ with_fields => { 'extra[category]' => 'Cat1' } });
+ $mech->content_contains('<option value="Cat1" selected>');
+ $external_body->discard_changes;
+ is $external_body->get_extra_metadata('category'), 'Cat1';
+};
+
+subtest "shows correct external bodies" => sub {
+ $report->discard_changes;
+ $report->state('feedback pending');
+ $report->set_extra_metadata('closure_status' => 'external');
+ $report->update;
+ $user = $mech->log_in_ok( 'dm1@example.org' );
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->content_like(qr/<option[^>]*>External Body<\/option>\s*<option[^>]*>Another Body External<\/option>/); # Test order
+
+ $user = $mech->log_in_ok( 'dm2@example.org' );
+ $user->update({ from_body => $division2->id });
+ $report->update({ bodies_str => $division2->id });
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->content_contains('Another Body External');
+ $mech->content_lacks('External Body');
+ $report->update({ bodies_str => $division->id });
};
subtest "problems can't be assigned to deleted bodies" => sub {
@@ -891,30 +831,22 @@ subtest "problems can't be assigned to deleted bodies" => sub {
$user->update;
$report->state( 'confirmed' );
$report->update;
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAPIT_URL => 'http://mapit.zurich/',
- MAPIT_TYPES => [ 'O08' ],
- MAPIT_ID_WHITELIST => [ 423017 ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- $mech->get_ok( '/admin/body/' . $external_body->id );
- $mech->submit_form_ok( { with_fields => { deleted => 1 } } );
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->content_lacks( $external_body->name )
- or do {
- diag $mech->content;
- diag $external_body->name;
- die;
- };
- };
+ $mech->get_ok( '/admin/body/' . $external_body->id );
+ $mech->submit_form_ok( { with_fields => { deleted => 1 } } );
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->content_lacks( $external_body->name )
+ or do {
+ diag $mech->content;
+ diag $external_body->name;
+ die;
+ };
$user->from_body( $division->id );
$user->update;
$mech->log_out_ok;
};
subtest "photo must be supplied for categories that require it" => sub {
- FixMyStreet::App->model('DB::Contact')->find_or_create({
+ FixMyStreet::DB->resultset('Contact')->find_or_create({
body => $division,
category => "Graffiti - photo required",
email => "graffiti\@example.org",
@@ -924,44 +856,34 @@ subtest "photo must be supplied for categories that require it" => sub {
note => "note for graffiti",
extra => { photo_required => 1 }
});
- FixMyStreet::override_config {
- MAPIT_TYPES => [ 'O08' ],
- MAPIT_URL => 'http://mapit.zurich/',
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAPIT_ID_WHITELIST => [ 423017 ],
- MAP_TYPE => 'Zurich,OSM',
- }, 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',
- category => 'Graffiti - photo required',
- }});
- is $mech->res->code, 200, "missing photo shouldn't return anything but 200";
- $mech->content_contains(_("Photo is required."), 'response should contain photo error message');
- };
+ $mech->get_ok('/report/new?lat=47.381817&lon=8.529156');
+ $mech->submit_form_ok({ with_fields => {
+ detail => 'Problem-Bericht',
+ username => 'user@example.org',
+ category => 'Graffiti - photo required',
+ }});
+ is $mech->res->code, 200, "missing photo shouldn't return anything but 200";
+ $mech->content_contains(_("Photo is required."), 'response should contain photo error message');
};
subtest "test stats" => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- }, sub {
- $user = $mech->log_in_ok( 'super@example.org' );
-
- $mech->get_ok( '/admin/stats' );
- is $mech->res->code, 200, "superuser should be able to see stats page";
-
- $mech->content_contains('Innerhalb eines Arbeitstages moderiert: 3');
- $mech->content_contains('Innerhalb von f&uuml;nf Arbeitstagen abgeschlossen: 3');
- # my @data = $mech->content =~ /(?:moderiert|abgeschlossen): \d+/g;
- # diag Dumper(\@data); use Data::Dumper;
-
- my $export_count = get_export_rows_count($mech);
- if (defined $export_count) {
- is $export_count - $EXISTING_REPORT_COUNT, 3, 'Correct number of reports';
- $mech->content_contains('fixed - council');
- }
- };
+ $user = $mech->log_in_ok( 'super@example.org' );
+
+ $mech->get_ok( '/admin/stats' );
+ is $mech->res->code, 200, "superuser should be able to see stats page";
+
+ $mech->content_contains('Innerhalb eines Arbeitstages moderiert: 3');
+ $mech->content_contains('Innerhalb von fünf Arbeitstagen abgeschlossen: 3');
+ # my @data = $mech->content =~ /(?:moderiert|abgeschlossen): \d+/g;
+ # diag Dumper(\@data); use Data::Dumper;
+
+ my $export_count = get_export_rows_count($mech);
+ if (defined $export_count) {
+ is $export_count - $EXISTING_REPORT_COUNT, 3, 'Correct number of reports';
+ $mech->content_contains('fixed - council');
+ }
+ $export_count = get_export_rows_count($mech, '&ym=' . DateTime->now->strftime("%m.%Y"));
+ is $export_count - $EXISTING_REPORT_COUNT, 3, 'Correct number of reports when filtering by month';
};
subtest "test admin_log" => sub {
@@ -977,136 +899,108 @@ subtest "test admin_log" => sub {
};
subtest 'email images to external partners' => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- reset_report_state($report);
+ reset_report_state($report);
- my $photo = path(__FILE__)->parent->child('zurich-logo_portal.x.jpg')->slurp_raw;
- my $photoset = FixMyStreet::App::Model::PhotoSet->new({
- data_items => [ $photo ],
- });
- my $fileid = $photoset->data;
-
- $report->set_extra_metadata('publish_photo' => { 0 => 1 });
- # The below email comparison must not have an external message.
- $report->unset_extra_metadata('external_message');
- $report->update({
- state => 'external',
- photo => $fileid,
- external_body => $external_body->id,
- });
+ my $photo = path(__FILE__)->parent->child('zurich-logo_portal.x.jpg')->slurp_raw;
+ my $photoset = FixMyStreet::App::Model::PhotoSet->new({
+ data_items => [ $photo ],
+ });
+ my $fileid = $photoset->data;
+
+ $report->set_extra_metadata('publish_photo' => { 0 => 1 });
+ # The below email comparison must not have an external message.
+ $report->unset_extra_metadata('external_message');
+ $report->update({
+ state => 'external',
+ photo => $fileid,
+ external_body => $external_body->id,
+ });
- $mech->clear_emails_ok;
- send_reports_for_zurich();
+ $mech->clear_emails_ok;
+ send_reports_for_zurich();
- my @emails = $mech->get_email;
- my $email_as_string = $mech->get_first_email(@emails);
- my ($boundary) = $email_as_string =~ /boundary="([A-Za-z0-9.]*)"/ms;
- my $email = Email::MIME->new($email_as_string);
-
- my $expected_email_content = path(__FILE__)->parent->child('zurich_attachments.txt')->slurp;
-
- my $REPORT_ID = $report->id;
- $expected_email_content =~ s{Subject: (.*?)\r?\n}{
- my $subj = Encode::decode('MIME-Header', $1);
- $subj =~ s{REPORT_ID}{$REPORT_ID}g;
- 'Subject: ' . Email::MIME::Encode::mime_encode($subj, "utf-8") . "\n";
- }eg;
- $expected_email_content =~ s{REPORT_ID}{$REPORT_ID}g;
- $expected_email_content =~ s{BOUNDARY}{$boundary}g;
- my $expected_email = Email::MIME->new($expected_email_content);
-
- my @email_parts;
- $email->walk_parts(sub {
- my ($part) = @_;
- push @email_parts, [ { $part->header_pairs }, $part->body ];
- });
- my @expected_email_parts;
- $expected_email->walk_parts(sub {
- my ($part) = @_;
- push @expected_email_parts, [ { $part->header_pairs }, $part->body ];
- });
- is_deeply \@email_parts, \@expected_email_parts, 'MIME email text ok'
- or do {
- (my $test_name = $0) =~ s{/}{_}g;
- my $path = path("test-output-$test_name.tmp");
- $path->spew($email_as_string);
- diag "Saved output in $path";
- };
+ my @emails = $mech->get_email;
+ my $email_as_string = $mech->get_first_email(@emails);
+ my ($boundary) = $email_as_string =~ /boundary="([A-Za-z0-9.]*)"/ms;
+ my $email = Email::MIME->new($email_as_string);
+
+ my $expected_email_content = path(__FILE__)->parent->child('zurich_attachments.txt')->slurp;
+
+ my $REPORT_ID = $report->id;
+ $expected_email_content =~ s{Subject: (.*?)\r?\n}{
+ my $subj = Encode::decode('MIME-Header', $1);
+ $subj =~ s{REPORT_ID}{$REPORT_ID}g;
+ 'Subject: ' . Email::MIME::Encode::mime_encode($subj, "utf-8", 9) . "\n";
+ }eg;
+ $expected_email_content =~ s{REPORT_ID}{$REPORT_ID}g;
+ $expected_email_content =~ s{BOUNDARY}{$boundary}g;
+ my $expected_email = Email::MIME->new($expected_email_content);
+
+ my @email_parts;
+ $email->walk_parts(sub {
+ my ($part) = @_;
+ push @email_parts, [ { $part->header_pairs }, $part->body ];
+ });
+ my @expected_email_parts;
+ $expected_email->walk_parts(sub {
+ my ($part) = @_;
+ push @expected_email_parts, [ { $part->header_pairs }, $part->body ];
+ });
+ is_deeply \@email_parts, \@expected_email_parts, 'MIME email text ok'
+ or do {
+ (my $test_name = $0) =~ s{/}{_}g;
+ my $path = path("test-output-$test_name.tmp");
+ $path->spew($email_as_string);
+ diag "Saved output in $path";
};
};
subtest 'Status update shown as appropriate' => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- # ALL closed states must hide the public_response edit, and public ones
- # must show the answer in blue.
- for (['feedback pending', 1, 0, 0],
- ['fixed - council', 0, 1, 0],
- ['external', 0, 1, 0],
- ['hidden', 0, 0, 1])
- {
- my ($state, $update, $public, $user_response) = @$_;
- $report->update({ state => $state });
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->contains_or_lacks($update, "name='status_update'");
- $mech->contains_or_lacks($public || $user_response, '<div class="admin-official-answer">');
-
- if ($public) {
- $mech->get_ok( '/report/' . $report->id );
- $mech->content_contains('Antwort</h4>');
- }
- }
- };
+ # ALL closed states must hide the public_response edit, and public ones
+ # must show the answer in blue.
+ for (['feedback pending', 1, 0, 0],
+ ['fixed - council', 0, 1, 0],
+ ['external', 0, 1, 0],
+ ['hidden', 0, 0, 1])
+ {
+ my ($state, $update, $public, $user_response) = @$_;
+ $report->update({ state => $state });
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->contains_or_lacks($update, "name='status_update'");
+ $mech->contains_or_lacks($public || $user_response, '<div class="admin-official-answer">');
+
+ if ($public) {
+ $mech->get_ok( '/report/' . $report->id );
+ $mech->content_contains('Antwort</h4>');
+ }
+ }
};
subtest 'time_spent' => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- my $report = $reports[0];
-
- is $report->get_time_spent, 0, '0 minutes spent';
- $report->update({ state => 'in progress' });
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->form_with_fields( 'time_spent' );
- $mech->submit_form_ok( {
- with_fields => {
- time_spent => 10,
- } });
- is $report->get_time_spent, 10, '10 minutes spent';
- };
+ my $report = $reports[0];
+
+ is $report->get_time_spent, 0, '0 minutes spent';
+ $report->update({ state => 'in progress' });
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->form_with_fields( 'time_spent' );
+ $mech->submit_form_ok( {
+ with_fields => {
+ time_spent => 10,
+ } });
+ is $report->get_time_spent, 10, '10 minutes spent';
};
$mech->log_out_ok;
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAPIT_URL => 'http://mapit.zurich/',
- MAPIT_TYPES => [ 'ZZZ' ],
-}, sub {
- subtest 'users at the top level can be edited' => sub {
- $mech->log_in_ok( $superuser->email );
- $mech->get_ok('/admin/users/' . $superuser->id );
- };
+subtest 'users at the top level can be edited' => sub {
+ $mech->log_in_ok( $superuser->email );
+ $mech->get_ok('/admin/users/' . $superuser->id );
};
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
-}, sub {
- subtest 'A visit to /reports is okay' => sub {
- $mech->get_ok('/reports');
- };
+subtest 'A visit to /reports is okay' => sub {
+ $mech->get_ok('/reports');
};
-END {
- ok $mech->host("www.fixmystreet.com"), "change host back";
- done_testing();
-}
+};
-1;
+done_testing();
diff --git a/t/cobrand/zurich_attachments.txt b/t/cobrand/zurich_attachments.txt
index 25a1bacf0..e9b717618 100644
--- a/t/cobrand/zurich_attachments.txt
+++ b/t/cobrand/zurich_attachments.txt
@@ -3,7 +3,7 @@ Subject: =?iso-8859-1?Q?Z=FCri?= wie neu: Weitergeleitete Meldung #REPORT_ID
Content-Type: multipart/mixed; boundary="BOUNDARY"
To: "External Body" <external_body@example.net>
Content-Transfer-Encoding: 7bit
-From: "FixMyStreet" <division@example.org>
+From: FixMyStreet <division@example.org>
--BOUNDARY
@@ -12,7 +12,7 @@ Content-Transfer-Encoding: quoted-printable
Gr=C3=BCezi External Body,
-=C3=96ffentliche URL: http://www.example.org/report/REPORT_ID
+=C3=96ffentliche URL: https://www.zurich/report/REPORT_ID
Bei Fragen zu "Z=C3=BCri wie neu" wenden Sie sich bitte an =
gis-zentrum@zuerich.ch.=
diff --git a/t/geocode/google.t b/t/geocode/google.t
index ee3c15ea8..40e8caf9a 100644
--- a/t/geocode/google.t
+++ b/t/geocode/google.t
@@ -11,12 +11,12 @@ use Catalyst::Test 'FixMyStreet::App';
use t::Mock::GoogleGeocoder;
my $c = ctx_request('/');
-my $r = FixMyStreet::Geocode::Google::string("one result", $c);
+my $r = FixMyStreet::Geocode::Google->string("one result", $c);
ok $r->{latitude};
ok $r->{longitude};
$c->stash->{cobrand} = FixMyStreet::Cobrand::Tester->new;
-$r = FixMyStreet::Geocode::Google::string("two results", $c);
+$r = FixMyStreet::Geocode::Google->string("two results", $c);
is scalar @{$r->{error}}, 2;
done_testing;
diff --git a/t/geocode/highwaysengland.t b/t/geocode/highwaysengland.t
new file mode 100644
index 000000000..7380a8437
--- /dev/null
+++ b/t/geocode/highwaysengland.t
@@ -0,0 +1,108 @@
+use FixMyStreet::Test;
+use HighwaysEngland;
+use Test::MockModule;
+
+my $he = Test::MockModule->new('HighwaysEngland');
+$he->mock('database_file', sub { FixMyStreet->path_to('t/geocode/roads.sqlite'); });
+
+
+for my $test (
+ {
+ search => 'M1, Jct 16',
+ latitude => 52.2302496115401,
+ long => -1.01582565724738,
+ desc => 'junction number second'
+ },
+ {
+ search => 'Jct 16, M1',
+ latitude => 52.2302496115401,
+ long => -1.01582565724738,
+ desc => 'junction number first'
+ },
+ {
+ search => 'M1 Jct 16',
+ latitude => 52.2302496115401,
+ long => -1.01582565724738,
+ desc => 'no comma as separator'
+ },
+ {
+ search => 'M1 Jct16',
+ latitude => 52.2302496115401,
+ long => -1.01582565724738,
+ desc => 'no space in junction name'
+ },
+ {
+ search => 'M1 J16',
+ latitude => 52.2302496115401,
+ long => -1.01582565724738,
+ desc => 'J for junction'
+ },
+ {
+ search => 'M1 Junction 16',
+ latitude => 52.2302496115401,
+ long => -1.01582565724738,
+ desc => 'junction as word'
+ },
+ {
+ search => 'm1 j16',
+ latitude => 52.2302496115401,
+ long => -1.01582565724738,
+ desc => 'lower case search'
+ },
+ {
+ search => 'A1, B668',
+ latitude => 52.7323808633713,
+ long => -0.599568322474905,
+ desc => 'road with joining road second'
+ },
+ {
+ search => ' B668, A1',
+ latitude => 52.7323808633713,
+ long => -0.599568322474905,
+ desc => 'road with joining road first'
+ },
+ {
+ search => 'A1, A607',
+ latitude => 52.8975982569244,
+ long => -0.664016143160206,
+ desc => 'road with joining A road'
+ },
+ {
+ search => 'A1, Long Bennington',
+ latitude => 52.979716221406,
+ long => -0.746100037226323,
+ desc => 'road with junction town'
+ },
+ {
+ search => 'Long Bennington, A1',
+ latitude => 52.979716221406,
+ long => -0.746100037226323,
+ desc => 'road with junction town first'
+ },
+ {
+ search => 'A14, J2',
+ latitude => 52.3998144608558,
+ long => -0.916447519667833,
+ desc => 'road with more than one number'
+ },
+ {
+ search => 'Watford gap services',
+ latitude => 52.3068680406392,
+ long => -1.1219749609866,
+ desc => 'motorway services'
+ },
+ {
+ search => 'M1 42.1',
+ latitude => 51.7926609391213,
+ long => -0.411879446242646,
+ desc => 'road and distance'
+ },
+) {
+ subtest $test->{desc} => sub {
+ my $r = HighwaysEngland::junction_lookup($test->{search});
+ is $r->{latitude}, $test->{latitude}, 'correct latitude';
+ is $r->{longtude}, $test->{longtude}, 'correct longtude';
+ };
+}
+
+done_testing;
diff --git a/t/geocode/roads.sqlite b/t/geocode/roads.sqlite
new file mode 100644
index 000000000..09cd0c9a7
--- /dev/null
+++ b/t/geocode/roads.sqlite
Binary files differ
diff --git a/t/i18n.t b/t/i18n.t
index 54f0a0fc1..5eb65c9de 100644
--- a/t/i18n.t
+++ b/t/i18n.t
@@ -15,7 +15,7 @@ use mySociety::Locale;
die "You need to run 'commonlib/bin/gettext-makemo --quiet FixMyStreet' "
. "to generate the *.mo files needed."
unless -e FixMyStreet->path_to(
- 'locale/nb_NO.UTF-8/LC_MESSAGES/FixMyStreet.mo');
+ 'locale/sv_SE.UTF-8/LC_MESSAGES/FixMyStreet.mo');
# Test the language negotiation works
my $lang = mySociety::Locale::negotiate_language(
@@ -29,32 +29,32 @@ is $lang, 'es', 'Language negotiation works okay';
# Example strings
my $english = "Please enter a valid email";
-my $norwegian = "Legg til en gyldig e-post";
+my $swedish = "Skriv in en giltig epostadress";
# set english as the language
mySociety::Locale::negotiate_language( #
- 'en-gb,English,en_GB|nb,Norwegian,nb_NO', 'en_GB'
+ 'en-gb,English,en_GB|sv,Swedish,sv_SE', 'en_GB'
);
mySociety::Locale::gettext_domain( 'FixMyStreet', 1 );
mySociety::Locale::change();
is _($english), $english, "english to english";
-mySociety::Locale::change('nb');
-is _($english), $norwegian, "english to norwegian";
+mySociety::Locale::change('sv');
+is _($english), $swedish, "english to Swedish";
# check that being in a deep directory does not confuse the code
chdir FixMyStreet->path_to('t/app/controller') . '';
mySociety::Locale::gettext_domain( 'FixMyStreet', 1,
FixMyStreet->path_to('locale')->stringify );
-mySociety::Locale::change('nb');
-is _($english), $norwegian, "english to norwegian (deep directory)";
+mySociety::Locale::change('sv');
+is _($english), $swedish, "english to Swedish (deep directory)";
# test that sorting works as expected in the right circumstances...
-my @random_sorted = qw( Å Z Ø A );
-my @EN_sorted = qw( A Å Ø Z );
-my @NO_sorted = qw( A Z Ø Å );
-my @default_sorted = qw( A Z Å Ø );
+my @random_sorted = qw( Å Z Ö A );
+my @EN_sorted = qw( A Å Ö Z );
+my @SV_sorted = qw( A Z Å Ö );
+my @default_sorted = qw( A Z Å Ö );
SKIP: {
@@ -98,22 +98,20 @@ SKIP: {
}
SKIP: {
- skip 'Will not pass on Mac', 2 if $^O eq 'darwin';
-
mySociety::Locale::negotiate_language( #
- 'nb-no,Norwegian,nb_NO', 'nb_NO'
+ 'sv,Swedish,sv_SE', 'sv_SE'
);
mySociety::Locale::change();
use locale;
is_deeply( [ sort @random_sorted ],
- \@NO_sorted, "sort correctly with use locale 'nb_NO'" );
+ \@SV_sorted, "sort correctly with use locale 'sv_SE'" );
# is_deeply( [ keysort { $_ } @random_sorted ],
- # \@NO_sorted, "keysort correctly with use locale 'nb_NO'" );
+ # \@SV_sorted, "keysort correctly with use locale 'sv_SE'" );
is_deeply( [ sort { strcoll( $a, $b ) } @random_sorted ],
- \@NO_sorted, "sort strcoll correctly with use locale 'nb_NO'" );
+ \@SV_sorted, "sort strcoll correctly with use locale 'sv_SE'" );
}
subtest "check that code is only called once by in_gb_locale" => sub {
diff --git a/t/map/cheshireeast.t b/t/map/cheshireeast.t
new file mode 100644
index 000000000..a90a1606e
--- /dev/null
+++ b/t/map/cheshireeast.t
@@ -0,0 +1,18 @@
+use Test::More;
+use FixMyStreet::Map::CheshireEast;
+
+# https://maps-cache.cheshiresharedservices.gov.uk/maps/?wmts/CE_OS_AllBasemaps_COLOUR/oscce_grid/10/10187/8134.jpeg&KEY=3a3f5c60eca1404ea114e6941c9d3895
+my $tiles = FixMyStreet::Map::CheshireEast->map_tiles(x_tile => 10187, y_tile => 8134, zoom_act => 10);
+$tiles = [ map { m{(\d+/\d+/\d+)}; $1; } @$tiles ];
+is_deeply $tiles, [ '10/10186/8133', '10/10187/8133', '10/10186/8134', '10/10187/8134' ];
+
+use Data::Dumper;
+my ($x, $y) = FixMyStreet::Map::CheshireEast->latlon_to_tile_with_adjust(53.150624, -2.386809, 10);
+is $x, 10187;
+is $y, 8134;
+
+my ($lat, $lon) = FixMyStreet::Map::CheshireEast->tile_to_latlon(10187, 8134, 10);
+is sprintf("%.6f", $lat), 53.150624;
+is sprintf("%.6f", $lon), -2.386809;
+
+done_testing();
diff --git a/t/map/mastermap.t b/t/map/mastermap.t
new file mode 100644
index 000000000..79522cdea
--- /dev/null
+++ b/t/map/mastermap.t
@@ -0,0 +1,22 @@
+use FixMyStreet::TestMech;
+
+use FixMyStreet::Map::MasterMap;
+
+subtest 'correct map tiles used' => sub {
+ my %test = (
+ 16 => [ '-', 'oml' ],
+ 20 => [ '.', 'mastermap-staging' ]
+ );
+ foreach my $zoom (qw(16 20)) {
+ my $tiles = FixMyStreet::Map::MasterMap->map_tiles(x_tile => 123, y_tile => 456, zoom_act => $zoom);
+ my ($sep, $lyr) = @{$test{$zoom}};
+ is_deeply $tiles, [
+ "//a${sep}tilma.mysociety.org/$lyr/$zoom/122/455.png",
+ "//b${sep}tilma.mysociety.org/$lyr/$zoom/123/455.png",
+ "//c${sep}tilma.mysociety.org/$lyr/$zoom/122/456.png",
+ "//tilma.mysociety.org/$lyr/$zoom/123/456.png",
+ ];
+ }
+};
+
+done_testing();
diff --git a/t/map/tests.t b/t/map/tests.t
index 728aa5125..7d7efab22 100644
--- a/t/map/tests.t
+++ b/t/map/tests.t
@@ -2,16 +2,21 @@ use FixMyStreet::Map;
use Test::More;
my $requires = {
- 'BathNES' => 'bathnes/assets.js',
'Bing' => 'map-bing-ol.js',
- 'Bristol' => 'bristol/assets.js',
- 'Bromley' => 'bromley/assets.js',
- 'Buckinghamshire' => 'buckinghamshire/assets.js',
+ 'Bristol' => 'map-wmts-bristol.js',
+ 'Bromley' => 'map-fms.js',
+ 'Buckinghamshire' => 'map-wmts-buckinghamshire.js',
'Lincolnshire' => 'lincolnshire/assets.js',
+ 'CheshireEast' => 'map-cheshireeast.js',
'FMS' => 'map-fms.js',
'Google' => 'map-google.js',
'GoogleOL' => 'map-google-ol.js',
+ 'HighwaysEngland' => 'map-fms.js',
+ 'Hounslow' => 'map-wmts-hounslow.js',
+ 'IsleOfWight' => 'map-wmts-isleofwight.js',
'OSM' => 'OpenStreetMap.js',
+ 'MasterMap' => 'map-mastermap.js',
+ 'Northamptonshire' => 'map-wms-northamptonshire.js',
'CycleMap' => 'OpenStreetMap.js',
'MapQuest' => 'OpenStreetMap.js',
'StreetView' => 'map-streetview.js',
@@ -20,7 +25,7 @@ my $requires = {
};
foreach (FixMyStreet::Map->maps) {
- next if /WMTSBase/; # Only its subclasses have JS
+ next if /WMTSBase|UKCouncilWMTS|WMSBase|WMXBase/; # Only its subclasses have JS
my $js = $_->map_javascript;
my $test_file = $js->[-1];
s/.*:://;
diff --git a/t/open311.t b/t/open311.t
index 85176ff0d..9524006b8 100644
--- a/t/open311.t
+++ b/t/open311.t
@@ -263,6 +263,36 @@ for my $test (
};
}
+for my $test (
+ {
+ desc => 'account_id handled correctly when present',
+ account_id => '1c304134-ef12-c128-9212-123908123901',
+ },
+ {
+ desc => 'account_id handled correctly when 0',
+ account_id => '0'
+ },
+ {
+ desc => 'account_id handled correctly when missing',
+ account_id => undef
+ }
+) {
+ subtest $test->{desc} => sub {
+ $problem->extra( undef );
+ my $extra = {
+ url => 'http://example.com/report/1',
+ defined $test->{account_id} ? ( account_id => $test->{account_id} ) : ()
+ };
+
+ my $results = make_service_req( $problem, $extra, $problem->category,
+'<?xml version="1.0" encoding="utf-8"?><service_requests><request><service_request_id>248</service_request_id></request></service_requests>'
+ );
+ my $c = CGI::Simple->new( $results->{req}->content );
+
+ is $c->param( 'account_id' ), $test->{account_id}, 'correct account_id';
+ };
+}
+
subtest 'test always_send_email' => sub {
my $email = $user->email;
$user->email(undef);
@@ -302,14 +332,14 @@ subtest 'basic request update post parameters' => sub {
my $c = CGI::Simple->new( $results->{ req }->content );
- is $c->param('description'), 'this is a comment', 'email correct';
+ is $c->param('description'), 'this is a comment', 'description correct';
is $c->param('email'), 'test@example.com', 'email correct';
is $c->param('status'), 'OPEN', 'status correct';
is $c->param('service_request_id'), 81, 'request id correct';
is $c->param('updated_datetime'), DateTime::Format::W3CDTF->format_datetime($dt), 'correct date';
is $c->param('title'), 'Mr', 'correct title';
- is $c->param('last_name'), 'User', 'correct first name';
- is $c->param('first_name'), 'Test', 'correct second name';
+ is $c->param('first_name'), 'Test', 'correct first name';
+ is $c->param('last_name'), 'User', 'correct second name';
is $c->param('media_url'), undef, 'no media url';
};
@@ -326,7 +356,7 @@ subtest 'extended request update post parameters' => sub {
my $c = CGI::Simple->new( $results->{ req }->content );
- is $c->param('description'), 'this is a comment', 'email correct';
+ is $c->param('description'), 'this is a comment', 'description correct';
is $c->param('email'), 'test@example.com', 'email correct';
is $c->param('status'), 'OPEN', 'status correct';
is $c->param('service_request_id_ext'), 80, 'external request id correct';
@@ -334,12 +364,66 @@ subtest 'extended request update post parameters' => sub {
is $c->param('public_anonymity_required'), 'FALSE', 'anon status correct';
is $c->param('updated_datetime'), DateTime::Format::W3CDTF->format_datetime($dt), 'correct date';
is $c->param('title'), 'Mr', 'correct title';
- is $c->param('last_name'), 'User', 'correct first name';
- is $c->param('first_name'), 'Test', 'correct second name';
+ is $c->param('first_name'), 'Test', 'correct first name';
+ is $c->param('last_name'), 'User', 'correct second name';
is $c->param('email_alerts_requested'), 'FALSE', 'email alerts flag correct';
is $c->param('media_url'), undef, 'no media url';
};
+subtest 'Hounslow update description is correct for same user' => sub {
+ my $comment = make_comment('hounslow');
+ my $results;
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'hounslow',
+ }, sub {
+ $results = make_update_req( $comment, '<?xml version="1.0" encoding="utf-8"?><service_request_updates><request_update><update_id>248</update_id></request_update></service_request_updates>' );
+ };
+
+ is $results->{ res }, 248, 'got update id';
+
+ my $c = CGI::Simple->new( $results->{ req }->content );
+
+ is $c->param('description'), 'this is a comment', 'description correct';
+ is $c->param('email'), 'test@example.com', 'email correct';
+ is $c->param('status'), 'OPEN', 'status correct';
+ is $c->param('service_request_id'), 81, 'request id correct';
+ is $c->param('updated_datetime'), DateTime::Format::W3CDTF->format_datetime($dt), 'correct date';
+ is $c->param('title'), 'Mr', 'correct title';
+ is $c->param('first_name'), 'Test', 'correct first name';
+ is $c->param('last_name'), 'User', 'correct second name';
+ is $c->param('media_url'), undef, 'no media url';
+};
+
+subtest 'Hounslow update description is correct for a different user' => sub {
+ my $user2 = FixMyStreet::DB->resultset('User')->new( {
+ name => 'Another User',
+ email => 'another@example.org',
+ } );
+
+ my $comment = make_comment('hounslow');
+ $comment->user($user2);
+ my $results;
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'hounslow',
+ }, sub {
+ $results = make_update_req( $comment, '<?xml version="1.0" encoding="utf-8"?><service_request_updates><request_update><update_id>248</update_id></request_update></service_request_updates>' );
+ };
+
+ is $results->{ res }, 248, 'got update id';
+
+ my $c = CGI::Simple->new( $results->{ req }->content );
+
+ is $c->param('description'), "[This comment was not left by the original problem reporter] this is a comment", 'description correct';
+ is $c->param('email'), 'another@example.org', 'email correct';
+ is $c->param('status'), 'OPEN', 'status correct';
+ is $c->param('service_request_id'), 81, 'request id correct';
+ is $c->param('updated_datetime'), DateTime::Format::W3CDTF->format_datetime($dt), 'correct date';
+ is $c->param('title'), 'Mr', 'correct title';
+ is $c->param('first_name'), 'Another', 'correct first name';
+ is $c->param('last_name'), 'User', 'correct second name';
+ is $c->param('media_url'), undef, 'no media url';
+};
+
subtest 'check media url set' => sub {
my $UPLOAD_DIR = tempdir( CLEANUP => 1 );
diff --git a/t/open311/getservicerequests.t b/t/open311/getservicerequests.t
index 55bb9ba11..672459f3f 100644
--- a/t/open311/getservicerequests.t
+++ b/t/open311/getservicerequests.t
@@ -17,6 +17,9 @@ my $contact = $mech->create_contact_ok( body_id => $body->id, category => 'Sidew
my $body2 = $mech->create_body_ok(2217, 'Buckinghamshire');
my $contact2 = $mech->create_contact_ok( body_id => $body2->id, category => 'Sidewalk and Curb Issues', email => 'sidewalks' );
+my $hounslow = $mech->create_body_ok(2483, 'Hounslow');
+my $hounslowcontact = $mech->create_contact_ok( body_id => $hounslow->id, category => 'Sidewalk and Curb Issues', email => 'sidewalks' );
+
my $dtf = DateTime::Format::W3CDTF->new;
my $requests_xml = qq{<?xml version="1.0" encoding="utf-8"?>
@@ -208,48 +211,6 @@ my $date = DateTime->new(
for my $test (
{
- start_date => '1',
- end_date => '',
- desc => 'do not process if only a start_date',
- subs => {},
- },
- {
- start_date => '',
- end_date => '1',
- desc => 'do not process if only an end_date',
- subs => {},
- },
-) {
- subtest $test->{desc} => sub {
- my $xml = prepare_xml( $test->{subs} );
- my $o = Open311->new(
- jurisdiction => 'mysociety',
- endpoint => 'http://example.com',
- test_mode => 1,
- test_get_returns => { 'requests.xml' => $xml}
- );
-
- my $update = Open311::GetServiceRequests->new(
- start_date => $test->{start_date},
- end_date => $test->{end_date},
- system_user => $user,
- );
- my $ret = $update->create_problems( $o, $body );
-
- is $ret, 0, 'failed correctly'
- };
-}
-
-$date = DateTime->new(
- year => 2010,
- month => 4,
- day => 14,
- hour => 6,
- minute => 37
-);
-
-for my $test (
- {
start_date => $date->clone->add(hours => -2),
end_date => $date->clone->add(hours => -1),
desc => 'do not process if update time after end_date',
@@ -469,6 +430,110 @@ for my $test (
};
}
+my $hounslow_non_public_xml = qq[<?xml version="1.0" encoding="utf-8"?>
+<service_requests>
+<request>
+<service_request_id>123456</service_request_id>
+<status>open</status>
+<status_notes></status_notes>
+<service_name>Sidewalk and Curb Issues</service_name>
+<service_code>sidewalks</service_code>
+<description>this is a problem</description>
+<agency_responsible></agency_responsible>
+<service_notice></service_notice>
+<requested_datetime>2010-04-14T06:37:38-08:00</requested_datetime>
+<updated_datetime>2010-04-14T06:37:38-08:00</updated_datetime>
+<expected_datetime>2010-04-15T06:37:38-08:00</expected_datetime>
+<lat>51.482286</lat>
+<long>-0.328163</long>
+<non_public>1</non_public>
+</request>
+</service_requests>
+];
+
+for my $test (
+ {
+ desc => 'Hounslow non_public reports not created',
+ non_public => 1,
+ count => 0,
+ },
+ {
+ desc => 'Hounslow public reports are created',
+ non_public => 0,
+ count => 1,
+ },
+) {
+ subtest $test->{desc} => sub {
+ (my $xml = $hounslow_non_public_xml) =~ s/non_public>1/non_public>$test->{non_public}/;
+
+ my $o = Open311->new(
+ jurisdiction => 'mysociety',
+ endpoint => 'http://example.com',
+ test_mode => 1,
+ test_get_returns => { 'requests.xml' => $xml}
+ );
+
+ my $update = Open311::GetServiceRequests->new(
+ system_user => $user,
+ start_date => $start_date,
+ end_date => $end_date
+ );
+
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => [ 'hounslow' ],
+ }, sub {
+ $update->create_problems( $o, $hounslow );
+ };
+
+ my $q = FixMyStreet::DB->resultset('Problem')->search(
+ { external_id => 123456 }
+ );
+
+ is $q->count, $test->{count}, 'problem count is correct';
+
+ $q->first->delete if $test->{count};
+ };
+}
+
+subtest "non_public contacts result in non_public reports" => sub {
+
+ $contact->update({
+ non_public => 1
+ });
+ my $o = Open311->new(
+ jurisdiction => 'mysociety',
+ endpoint => 'http://example.com',
+ test_mode => 1,
+ test_get_returns => { 'requests.xml' => prepare_xml( {} ) }
+ );
+
+ my $update = Open311::GetServiceRequests->new(
+ system_user => $user,
+ start_date => $start_date,
+ end_date => $end_date
+ );
+
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $update->create_problems( $o, $body );
+ };
+
+ my $p = FixMyStreet::DB->resultset('Problem')->search(
+ { external_id => 123456 }
+ )->first;
+
+ ok $p, 'problem created';
+ is $p->non_public, 1, "report non_public is set correctly";
+
+ $p->delete;
+ $contact->update({
+ non_public => 0
+ });
+
+};
+
for my $test (
{
test_desc => 'filters out phone numbers',
diff --git a/t/open311/getservicerequestupdates.t b/t/open311/getservicerequestupdates.t
index f680985a4..4651c38b2 100644
--- a/t/open311/getservicerequestupdates.t
+++ b/t/open311/getservicerequestupdates.t
@@ -12,6 +12,7 @@ use_ok( 'Open311' );
use_ok( 'Open311::GetServiceRequestUpdates' );
use DateTime;
use DateTime::Format::W3CDTF;
+use File::Temp 'tempdir';
use FixMyStreet::DB;
my $user = FixMyStreet::DB->resultset('User')->find_or_create(
@@ -22,6 +23,8 @@ my $user = FixMyStreet::DB->resultset('User')->find_or_create(
my %bodies = (
2237 => FixMyStreet::DB->resultset("Body")->create({ name => 'Oxfordshire' }),
+ 2494 => FixMyStreet::DB->resultset("Body")->create({ name => 'Bexley' }),
+ 2636 => FixMyStreet::DB->resultset("Body")->create({ name => 'Isle of Wight' }),
2482 => FixMyStreet::DB->resultset("Body")->create({
name => 'Bromley',
send_method => 'Open311',
@@ -33,6 +36,8 @@ my %bodies = (
2651 => FixMyStreet::DB->resultset("Body")->create({ name => 'Edinburgh' }),
);
$bodies{2237}->body_areas->create({ area_id => 2237 });
+$bodies{2494}->body_areas->create({ area_id => 2494 });
+$bodies{2636}->body_areas->create({ area_id => 2636 });
my $response_template = $bodies{2482}->response_templates->create({
title => "investigating template",
@@ -129,8 +134,10 @@ subtest 'check extended request parsed correctly' => sub {
};
my $problem_rs = FixMyStreet::DB->resultset('Problem');
-my $problem = $problem_rs->new(
- {
+
+sub create_problem {
+ my ($body_id, $external_id) = @_;
+ my $problem = $problem_rs->create({
postcode => 'EH99 1SP',
latitude => 1,
longitude => 1,
@@ -139,7 +146,7 @@ my $problem = $problem_rs->new(
detail => '',
used_map => 1,
user_id => 1,
- name => '',
+ name => 'Test User',
state => 'confirmed',
service => '',
cobrand => 'default',
@@ -148,12 +155,13 @@ my $problem = $problem_rs->new(
created => DateTime->now()->subtract( days => 1 ),
lastupdate => DateTime->now()->subtract( days => 1 ),
anonymous => 1,
- external_id => int(rand(time())),
- bodies_str => $bodies{2482}->id,
- }
-);
+ external_id => $external_id || int(rand(time())),
+ bodies_str => $body_id,
+ });
+ return $problem;
+}
-$problem->insert;
+my $problem = create_problem($bodies{2482}->id);
for my $test (
{
@@ -447,27 +455,38 @@ for my $test (
};
}
-my $problemOx = $problem_rs->create({
- postcode => 'EH99 1SP',
- latitude => 1,
- longitude => 1,
- areas => 1,
- title => '',
- detail => '',
- used_map => 1,
- user_id => 1,
- name => '',
- state => 'confirmed',
- service => '',
- cobrand => 'default',
- cobrand_data => '',
- user => $user,
- created => DateTime->now()->subtract( days => 1 ),
- lastupdate => DateTime->now()->subtract( days => 1 ),
- anonymous => 1,
- external_id => int(rand(time())),
- bodies_str => $bodies{2237}->id,
+my $response_template_vars = $bodies{2482}->response_templates->create({
+ title => "a placeholder action scheduled template",
+ text => "We are investigating this report: {{description}}",
+ auto_response => 1,
+ state => "action scheduled"
});
+subtest 'Check template placeholders' => sub {
+ my $local_requests_xml = setup_xml($problem->external_id, $problem->id, 'ACTION_SCHEDULED', 'We will do this in the morning.');
+ my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', extended_statuses => undef, test_mode => 1, test_get_returns => { 'servicerequestupdates.xml' => $local_requests_xml } );
+
+ $problem->lastupdate( DateTime->now()->subtract( days => 1 ) );
+ $problem->state( 'fixed - council' );
+ $problem->update;
+
+ my $update = Open311::GetServiceRequestUpdates->new;
+ $update->fetch($o);
+
+ is $problem->comments->count, 1, 'comment count';
+ $problem->discard_changes;
+
+ my $c = FixMyStreet::DB->resultset('Comment')->search( { external_id => 638344 } )->first;
+ ok $c, 'comment exists';
+ is $c->text, "We are investigating this report: We will do this in the morning.", 'text correct';
+ is $c->mark_fixed, 0, 'mark_closed correct';
+ is $c->problem_state, 'action scheduled', 'problem_state correct';
+ is $c->mark_open, 0, 'mark_open correct';
+ is $c->state, 'confirmed', 'comment state correct';
+ is $problem->state, 'action scheduled', 'correct problem state';
+ $problem->comments->delete;
+};
+
+my $problemB = create_problem($bodies{2237}->id);
for my $test (
{
@@ -486,28 +505,68 @@ for my $test (
},
) {
subtest $test->{desc} => sub {
- my $local_requests_xml = setup_xml($problemOx->external_id, $problemOx->id, $test->{comment_status});
+ my $local_requests_xml = setup_xml($problemB->external_id, $problemB->id, $test->{comment_status});
my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'servicerequestupdates.xml' => $local_requests_xml } );
- $problemOx->lastupdate( DateTime->now()->subtract( days => 1 ) );
- $problemOx->state( $test->{start_state} );
- $problemOx->update;
+ $problemB->lastupdate( DateTime->now()->subtract( days => 1 ) );
+ $problemB->state( $test->{start_state} );
+ $problemB->update;
+
+ my $update = Open311::GetServiceRequestUpdates->new(
+ system_user => $user,
+ current_open311 => $o,
+ current_body => $bodies{2237},
+ );
+ $update->process_body;
- my $update = Open311::GetServiceRequestUpdates->new( system_user => $user );
- $update->update_comments( $o, $bodies{2237} );
- is $problemOx->comments->count, 1, 'comment count';
- $problemOx->discard_changes;
+ is $problemB->comments->count, 1, 'comment count';
+ $problemB->discard_changes;
my $c = FixMyStreet::DB->resultset('Comment')->search( { external_id => 638344 } )->first;
ok $c, 'comment exists';
is $c->problem_state, $test->{problem_state}, 'problem_state correct';
- is $problemOx->state, $test->{end_state}, 'correct problem state';
- $problemOx->comments->delete;
+ is $problemB->state, $test->{end_state}, 'correct problem state';
+ $problemB->comments->delete;
+ };
+}
+
+for (
+ { id => 2494, cobrand => 'bexley' },
+ { id => 2636, cobrand => 'isleofwight' }
+) {
+ subtest "Marking report as fixed closes it for updates ($_->{cobrand})" => sub {
+ my $local_requests_xml = setup_xml($problemB->external_id, $problemB->id, 'CLOSED');
+ my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'servicerequestupdates.xml' => $local_requests_xml } );
+
+ $problemB->update( { bodies_str => $bodies{$_->{id}}->id } );
+
+ my $update = Open311::GetServiceRequestUpdates->new(
+ system_user => $user,
+ current_open311 => $o,
+ current_body => $bodies{$_->{id}},
+ );
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => $_->{cobrand},
+ }, sub {
+ $update->process_body;
+ };
+
+ $problemB->discard_changes;
+ is $problemB->comments->count, 1, 'comment count';
+ is $problemB->get_extra_metadata('closed_updates'), 1;
+ $problemB->comments->delete;
};
}
subtest 'Update with media_url includes image in update' => sub {
+ my $UPLOAD_DIR = tempdir( CLEANUP => 1 );
+ FixMyStreet::override_config {
+ PHOTO_STORAGE_BACKEND => 'FileSystem',
+ PHOTO_STORAGE_OPTIONS => {
+ UPLOAD_DIR => $UPLOAD_DIR,
+ },
+ }, sub {
my $guard = LWP::Protocol::PSGI->register(t::Mock::Static->to_psgi_app, host => 'example.com');
my $local_requests_xml = setup_xml($problem->external_id, 1, "");
@@ -519,14 +578,19 @@ subtest 'Update with media_url includes image in update' => sub {
$problem->state('confirmed');
$problem->update;
- my $update = Open311::GetServiceRequestUpdates->new( system_user => $user );
- $update->update_comments( $o, $bodies{2482} );
+ my $update = Open311::GetServiceRequestUpdates->new(
+ system_user => $user,
+ current_open311 => $o,
+ current_body => $bodies{2482},
+ );
+ $update->process_body;
is $problem->comments->count, 1, 'comment count';
my $c = $problem->comments->first;
is $c->external_id, 638344;
is $c->photo, '74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg', 'photo exists';
$problem->comments->delete;
+ };
};
subtest 'Update with customer_reference adds reference to problem' => sub {
@@ -541,8 +605,12 @@ subtest 'Update with customer_reference adds reference to problem' => sub {
$problem->state('confirmed');
$problem->update;
- my $update = Open311::GetServiceRequestUpdates->new( system_user => $user );
- $update->update_comments( $o, $bodies{2482} );
+ my $update = Open311::GetServiceRequestUpdates->new(
+ system_user => $user,
+ current_open311 => $o,
+ current_body => $bodies{2482},
+ );
+ $update->process_body;
$problem->discard_changes;
is $problem->comments->count, 1, 'comment count';
@@ -556,11 +624,15 @@ subtest 'date for comment correct' => sub {
my $local_requests_xml = setup_xml($problem->external_id, $problem->id, "");
my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'servicerequestupdates.xml' => $local_requests_xml } );
- my $update = Open311::GetServiceRequestUpdates->new( system_user => $user );
+ my $update = Open311::GetServiceRequestUpdates->new(
+ system_user => $user,
+ current_open311 => $o,
+ current_body => $bodies{2482},
+ );
FixMyStreet::override_config {
TIME_ZONE => 'Australia/Sydney',
}, sub {
- $update->update_comments( $o, $bodies{2482} );
+ $update->process_body;
};
my $comment = $problem->comments->first;
@@ -569,29 +641,7 @@ subtest 'date for comment correct' => sub {
$problem->comments->delete;
};
-my $problem2 = $problem_rs->create(
- {
- postcode => 'EH99 1SP',
- latitude => 1,
- longitude => 1,
- areas => 1,
- title => '',
- detail => '',
- used_map => 1,
- user_id => 1,
- name => '',
- state => 'confirmed',
- service => '',
- cobrand => 'default',
- cobrand_data => '',
- user => $user,
- created => DateTime->now(),
- lastupdate => DateTime->now(),
- anonymous => 1,
- external_id => $problem->external_id,
- bodies_str => $bodies{2651}->id,
- }
-);
+my $problem2 = create_problem($bodies{2651}->id, $problem->external_id);
for my $test (
{
@@ -617,8 +667,12 @@ for my $test (
my $local_requests_xml = setup_xml($test->{request_id}, $test->{request_id_ext}, "");
my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'servicerequestupdates.xml' => $local_requests_xml } );
- my $update = Open311::GetServiceRequestUpdates->new( system_user => $user );
- $update->update_comments( $o, $bodies{$test->{area_id}} );
+ my $update = Open311::GetServiceRequestUpdates->new(
+ system_user => $user,
+ current_open311 => $o,
+ current_body => $bodies{$test->{area_id}},
+ );
+ $update->process_body;
is $problem->comments->count, $test->{p1_comments}, 'comment count for first problem';
is $problem2->comments->count, $test->{p2_comments}, 'comment count for second problem';
@@ -629,33 +683,19 @@ subtest 'using start and end date' => sub {
my $local_requests_xml = $requests_xml;
my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'servicerequestupdates.xml' => $local_requests_xml } );
- my $start_dt = DateTime->now();
+ my $start_dt = DateTime->now(formatter => DateTime::Format::W3CDTF->new);
+ my $end_dt = $start_dt->clone;
$start_dt->subtract( days => 1 );
- my $end_dt = DateTime->now();
my $update = Open311::GetServiceRequestUpdates->new(
system_user => $user,
start_date => $start_dt,
- );
-
- my $res = $update->update_comments( $o );
- is $res, 0, 'returns 0 if start but no end date';
-
- $update = Open311::GetServiceRequestUpdates->new(
- system_user => $user,
- end_date => $end_dt,
- );
-
- $res = $update->update_comments( $o );
- is $res, 0, 'returns 0 if end but no start date';
-
- $update = Open311::GetServiceRequestUpdates->new(
- system_user => $user,
- start_date => $start_dt,
end_date => $end_dt,
+ current_open311 => $o,
+ current_body => $bodies{2482},
);
- $update->update_comments( $o, $bodies{2482} );
+ $update->process_body;
my $start = $start_dt . '';
my $end = $end_dt . '';
@@ -713,19 +753,21 @@ subtest 'check that existing comments are not duplicated' => sub {
my $update = Open311::GetServiceRequestUpdates->new(
system_user => $user,
+ current_open311 => $o,
+ current_body => $bodies{2482},
);
- $update->update_comments( $o, $bodies{2482} );
+ $update->process_body;
$problem->discard_changes;
is $problem->comments->count, 2, 'two comments after fetching updates';
- $update->update_comments( $o, $bodies{2482} );
+ $update->process_body;
$problem->discard_changes;
is $problem->comments->count, 2, 're-fetching updates does not add comments';
$problem->comments->delete;
- $update->update_comments( $o, $bodies{2482} );
+ $update->process_body;
$problem->discard_changes;
is $problem->comments->count, 2, 'if comments are deleted then they are added';
};
@@ -804,9 +846,11 @@ subtest 'check that external_status_code is stored correctly' => sub {
my $update = Open311::GetServiceRequestUpdates->new(
system_user => $user,
+ current_open311 => $o,
+ current_body => $bodies{2482},
);
- $update->update_comments( $o, $bodies{2482} );
+ $update->process_body;
$problem->discard_changes;
is $problem->comments->count, 2, 'two comments after fetching updates';
@@ -818,6 +862,36 @@ subtest 'check that external_status_code is stored correctly' => sub {
is $problem->get_extra_metadata('external_status_code'), "101", "correct external status code";
+ $requests_xml = qq{<?xml version="1.0" encoding="utf-8"?>
+ <service_requests_updates>
+ <request_update>
+ <update_id>638364</update_id>
+ <service_request_id>@{[ $problem->external_id ]}</service_request_id>
+ <status>open</status>
+ <description>This is a note</description>
+ <updated_datetime>UPDATED_DATETIME</updated_datetime>
+ <external_status_code></external_status_code>
+ </request_update>
+ </service_requests_updates>
+ };
+
+ $problem->comments->delete;
+
+ my $dt3 = $dt->clone->add( minutes => 1 );
+ $requests_xml =~ s/UPDATED_DATETIME/$dt3/;
+
+ $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'servicerequestupdates.xml' => $requests_xml } );
+
+ $update = Open311::GetServiceRequestUpdates->new(
+ system_user => $user,
+ current_open311 => $o,
+ current_body => $bodies{2482},
+ );
+
+ $update->process_body;
+
+ $problem->discard_changes;
+ is $problem->get_extra_metadata('external_status_code'), '', "external status code unset";
};
subtest 'check that external_status_code triggers auto-responses' => sub {
@@ -849,15 +923,15 @@ subtest 'check that external_status_code triggers auto-responses' => sub {
my $update = Open311::GetServiceRequestUpdates->new(
system_user => $user,
+ current_open311 => $o,
+ current_body => $bodies{2482},
);
- $update->update_comments( $o, $bodies{2482} );
+ $update->process_body;
$problem->discard_changes;
is $problem->comments->count, 1, 'one comment after fetching updates';
- my $comment = $problem->comments->first;
-
is $problem->comments->first->text, "Thank you for your report. We will provide an update within 24 hours.", "correct external status code on first comment";
};
@@ -903,9 +977,11 @@ foreach my $test ( {
my $update = Open311::GetServiceRequestUpdates->new(
system_user => $user,
+ current_open311 => $o,
+ current_body => $bodies{2482},
);
- $update->update_comments( $o, $bodies{2482} );
+ $update->process_body;
$problem->discard_changes;
is $problem->comments->count, 2, 'two comments after fetching updates';
@@ -914,6 +990,117 @@ foreach my $test ( {
};
}
+my $response_template_in_progress = $bodies{2482}->response_templates->create({
+ title => "Acknowledgement 1",
+ text => "Thank you for your report. We will provide an update within 48 hours.",
+ auto_response => 1,
+ state => "in progress"
+});
+
+for my $test (
+ {
+ external_code => '090',
+ description => 'check numeric external status code in response template override state',
+ },
+ {
+ external_code => 'futher',
+ description => 'check alpha external status code in response template override state',
+ },
+) {
+ subtest $test->{description} => sub {
+ my $requests_xml = qq{<?xml version="1.0" encoding="utf-8"?>
+ <service_requests_updates>
+ <request_update>
+ <update_id>638344</update_id>
+ <service_request_id>@{[ $problem->external_id ]}</service_request_id>
+ <status>in_progress</status>
+ <description></description>
+ <updated_datetime>UPDATED_DATETIME</updated_datetime>
+ <external_status_code></external_status_code>
+ </request_update>
+ <request_update>
+ <update_id>638345</update_id>
+ <service_request_id>@{[ $problem->external_id ]}</service_request_id>
+ <status>in_progress</status>
+ <description></description>
+ <updated_datetime>UPDATED_DATETIME2</updated_datetime>
+ <external_status_code>@{[ $test->{external_code} ]}</external_status_code>
+ </request_update>
+ </service_requests_updates>
+ };
+
+ my $response_template = $bodies{2482}->response_templates->create({
+ # the default ordering uses the title of the report so
+ # make sure this comes second
+ title => "Acknowledgement 2",
+ text => "Thank you for your report. We will provide an update within 24 hours.",
+ auto_response => 1,
+ external_status_code => $test->{external_code}
+ });
+
+ $problem->comments->delete;
+
+ my $dt2 = $dt->clone->add( minutes => 1 );
+ $requests_xml =~ s/UPDATED_DATETIME/$dt/;
+ $requests_xml =~ s/UPDATED_DATETIME2/$dt2/;
+
+ my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'servicerequestupdates.xml' => $requests_xml } );
+
+ my $update = Open311::GetServiceRequestUpdates->new(
+ system_user => $user,
+ current_open311 => $o,
+ current_body => $bodies{2482},
+ );
+
+ $update->process_body;
+
+ $problem->discard_changes;
+ is $problem->comments->count, 2, 'two comment after fetching updates';
+
+ my @comments = $problem->comments->search(undef, { order_by => 'confirmed' });
+
+ is $comments[0]->text, "Thank you for your report. We will provide an update within 48 hours.", "correct external status code on first comment";
+ is $comments[1]->text, "Thank you for your report. We will provide an update within 24 hours.", "correct external status code on second comment";
+ $problem->comments->delete;
+ $response_template->delete;
+ };
+}
+
+subtest 'check that first comment always updates state' => sub {
+ my $requests_xml = qq{<?xml version="1.0" encoding="utf-8"?>
+ <service_requests_updates>
+ <request_update>
+ <update_id>638344</update_id>
+ <service_request_id>@{[ $problem->external_id ]}</service_request_id>
+ <status>in_progress</status>
+ <description>This is a note</description>
+ <updated_datetime>UPDATED_DATETIME</updated_datetime>
+ </request_update>
+ </service_requests_updates>
+ };
+
+ $problem->state( 'confirmed' );
+ $problem->lastupdate( $dt->clone->subtract( hours => 1 ) );
+ $problem->update;
+
+ $requests_xml =~ s/UPDATED_DATETIME/@{[$dt->clone->subtract( minutes => 62 )]}/;
+
+ my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'servicerequestupdates.xml' => $requests_xml } );
+
+ my $update = Open311::GetServiceRequestUpdates->new(
+ system_user => $user,
+ current_open311 => $o,
+ current_body => $bodies{2482},
+ );
+
+ $update->process_body;
+
+ $problem->discard_changes;
+ is $problem->comments->count, 1, 'one comment after fetching updates';
+ is $problem->state, 'in progress', 'correct problem status';
+ $problem->comments->delete;
+};
+
foreach my $test ( {
desc => 'normally alerts are not suppressed',
num_alerts => 1,
@@ -968,9 +1155,11 @@ foreach my $test ( {
my $update = Open311::GetServiceRequestUpdates->new(
system_user => $user,
suppress_alerts => $test->{suppress_alerts},
+ current_open311 => $o,
+ current_body => $bodies{2482},
);
- $update->update_comments( $o, $bodies{2482} );
+ $update->process_body;
$problem->discard_changes;
my $alerts_sent = FixMyStreet::DB->resultset('AlertSent')->search(
@@ -1030,12 +1219,14 @@ foreach my $test ( {
my $update = Open311::GetServiceRequestUpdates->new(
system_user => $user,
blank_updates_permitted => $test->{blank_updates_permitted},
+ current_open311 => $o,
+ current_body => $bodies{2482},
);
if ( $test->{blank_updates_permitted} ) {
- stderr_is { $update->update_comments( $o, $bodies{2482} ) } '', 'No error message'
+ stderr_is { $update->process_body } '', 'No error message'
} else {
- stderr_like { $update->update_comments( $o, $bodies{2482} ) } qr/Couldn't determine update text for/, 'Error message displayed'
+ stderr_like { $update->process_body } qr/Couldn't determine update text for/, 'Error message displayed'
}
$problem->discard_changes;
$problem->comments->delete;
@@ -1084,9 +1275,11 @@ subtest 'check matching on fixmystreet_id overrides service_request_id' => sub {
my $update = Open311::GetServiceRequestUpdates->new(
system_user => $user,
+ current_open311 => $o,
+ current_body => $bodies{2482},
);
- $update->update_comments( $o, $bodies{2482} );
+ $update->process_body;
$problem->discard_changes;
is $problem->comments->count, 2, 'two comments after fetching updates';
@@ -1119,10 +1312,12 @@ subtest 'check bad fixmystreet_id is handled' => sub {
my $update = Open311::GetServiceRequestUpdates->new(
system_user => $user,
+ current_open311 => $o,
+ current_body => $bodies{2482},
);
warning_like {
- $update->update_comments( $o, $bodies{2482} )
+ $update->process_body
}
qr/skipping bad fixmystreet id in updates for Bromley: \[123456 654321\], external id is 8888888888888/,
"warning emitted for bad fixmystreet id";
diff --git a/t/open311/getupdates.t b/t/open311/getupdates.t
index 1cbabc5ab..351f17f6f 100644
--- a/t/open311/getupdates.t
+++ b/t/open311/getupdates.t
@@ -1,5 +1,4 @@
-#!/usr/bin/env perl
-
+use utf8;
use FixMyStreet::Test;
use URI::Split qw(uri_split);
@@ -220,7 +219,7 @@ my $problem3 = $problem_rs->create( {
used_map => 1,
name => '',
state => 'confirmed',
- cobrand => 'fiksgatami',
+ cobrand => 'fixamingata',
user => $user,
created => DateTime->now()->subtract( days => 1 ),
lastupdate => DateTime->now()->subtract( days => 1 ),
@@ -235,7 +234,7 @@ subtest 'test translation of auto-added comment from old-style Open311 update' =
my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'requests.xml' => $requests_xml } );
FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'fiksgatami' ],
+ ALLOWED_COBRANDS => [ 'fixamingata' ],
}, sub {
ok $updates->update_reports( [ 638346 ], $o, $body ), 'Updated reports';
};
@@ -245,7 +244,7 @@ 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, "(ikke rapportert til administrasjonen)", 'correct comment text';
+ is $problem3->comments->first->text, "Stängd av kommunen", 'correct comment text';
};
END {
diff --git a/t/open311/populate-service-list.t b/t/open311/populate-service-list.t
index ff4c4cf9d..bd837f203 100644
--- a/t/open311/populate-service-list.t
+++ b/t/open311/populate-service-list.t
@@ -5,20 +5,11 @@ use parent 'FixMyStreet::Cobrand::Default';
sub council_area_id { 1 }
-
-package FixMyStreet::Cobrand::TesterGroups;
-
-use parent 'FixMyStreet::Cobrand::Default';
-
-sub council_area_id { 1 }
-
-sub enable_category_groups { 1 }
-
-
package main;
use FixMyStreet::Test;
use FixMyStreet::DB;
+use Test::Warn;
use utf8;
use_ok( 'Open311::PopulateServiceList' );
@@ -44,20 +35,23 @@ $bromley->body_areas->create({
} );
my $bucks = FixMyStreet::DB->resultset('Body')->create({
- name => 'Buckinghamshire County Council',
+ name => 'Buckinghamshire Council',
});
$bucks->body_areas->create({
area_id => 2217
});
for my $test (
- { desc => 'groups not set for new contacts', cobrand => 'tester', groups => 0, delete => 1 },
- { desc => 'groups set for new contacts', cobrand => 'testergroups', groups => 1, delete => 1},
- { desc => 'groups removed for existing contacts', cobrand => 'tester', groups => 0, delete => 0 },
- { desc => 'groups added for existing contacts', cobrand => 'testergroups', groups => 1, delete => 0},
+ { desc => 'groups not set for new contacts', enable_groups => 0, groups => 0, delete => 1 },
+ { desc => 'groups set for new contacts', enable_groups => 1, groups => 1, delete => 1},
+ { desc => 'groups removed for existing contacts', enable_groups => 0, groups => 0, delete => 0 },
+ { desc => 'groups added for existing contacts', enable_groups => 1, groups => 1, delete => 0},
) {
FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ $test->{cobrand} ],
+ ALLOWED_COBRANDS => [ 'tester' ],
+ COBRAND_FEATURES => {
+ category_groups => { tester => $test->{enable_groups} },
+ }
}, sub {
subtest 'check basic functionality, ' . $test->{desc} => sub {
FixMyStreet::DB->resultset('Contact')->search( { body_id => $body->id } )->delete() if $test->{delete};
@@ -83,6 +77,104 @@ for my $test (
};
}
+my $last_update = {};
+for my $test (
+ { desc => 'set multiple groups for contact', enable_multi => 1, groups => ['sanitation', 'street'] },
+ { desc => 'groups not edited if unchanged', enable_multi => 1, groups => ['sanitation', 'street'], unchanged => 1 },
+) {
+ subtest $test->{desc} => sub {
+ FixMyStreet::DB->resultset('Contact')->search( { body_id => $body->id } )->delete();
+
+ my $services_xml = '<?xml version="1.0" encoding="utf-8"?>
+ <services>
+ <service>
+ <service_code>100</service_code>
+ <service_name>Cans left out 24x7</service_name>
+ <description>Garbage or recycling cans that have been left out for more than 24 hours after collection. Violators will be cited.</description>
+ <metadata>false</metadata>
+ <type>realtime</type>
+ <keywords>lorem, ipsum, dolor</keywords>
+ <groups><group>sanitation</group><group>street</group></groups>
+ </service>
+ <service>
+ <service_code>002</service_code>
+ <metadata>false</metadata>
+ <type>realtime</type>
+ <keywords>lorem, ipsum, dolor</keywords>
+ <group>street</group>
+ <service_name>Construction plate shifted</service_name>
+ <description>Metal construction plate covering the street or sidewalk has been moved.</description>
+ </service>
+ </services>
+ ';
+
+ my $service_list = get_xml_simple_object($services_xml);
+
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'tester' ],
+ COBRAND_FEATURES => {
+ category_groups => { tester => 1 },
+ }
+ }, sub {
+ 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, 2, 'correct number of contacts';
+
+ my $contact = FixMyStreet::DB->resultset('Contact')->search( { body_id => $body->id, email => 100 } )->first;
+ is_deeply $contact->get_extra->{group}, $test->{groups}, "Multi groups set correctly";
+ if ($test->{unchanged}) {
+ is $contact->whenedited, $last_update->{100}, "contact unchanged";
+ }
+ $last_update->{100} = $contact->whenedited;
+
+ $contact = FixMyStreet::DB->resultset('Contact')->search( { body_id => $body->id, email => '002'} )->first;
+ is $contact->get_extra->{group}, 'street', "Single groups set correctly";
+ if ($test->{unchanged}) {
+ is $contact->whenedited, $last_update->{002}, "contact unchanged";
+ }
+ $last_update->{002} = $contact->whenedited;
+ };
+}
+
+subtest "set multiple groups with groups element" => sub {
+ FixMyStreet::DB->resultset('Contact')->search( { body_id => $body->id } )->delete();
+
+ my $services_xml = '<?xml version="1.0" encoding="utf-8"?>
+ <services>
+ <service>
+ <service_code>100</service_code>
+ <service_name>Cans left out 24x7</service_name>
+ <description>Garbage or recycling cans that have been left out for more than 24 hours after collection. Violators will be cited.</description>
+ <metadata>false</metadata>
+ <type>realtime</type>
+ <keywords>lorem, ipsum, dolor</keywords>
+ <groups><group>sanitation &amp; cleaning</group><group>street</group></groups>
+ </service>
+ </services>
+ ';
+
+ my $service_list = get_xml_simple_object($services_xml);
+
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'tester' ],
+ COBRAND_FEATURES => {
+ category_groups => { tester => 1 },
+ }
+ }, sub {
+ 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, 1, 'correct number of contacts';
+
+ my $contact = FixMyStreet::DB->resultset('Contact')->search( { body_id => $body->id, email => 100 } )->first;
+ 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();
@@ -225,6 +317,153 @@ subtest 'check conflicting contacts not changed' => sub {
is $contact_count, 4, 'correct number of contacts';
};
+subtest 'check new category marked non_public' => sub {
+ FixMyStreet::DB->resultset('Contact')->search( { body_id => $body->id } )->delete();
+
+ my $services_xml = '<?xml version="1.0" encoding="utf-8"?>
+ <services>
+ <service>
+ <service_code>100</service_code>
+ <service_name>Cans left out 24x7</service_name>
+ <description>Garbage or recycling cans that have been left out for more than 24 hours after collection. Violators will be cited.</description>
+ <metadata>false</metadata>
+ <type>realtime</type>
+ <keywords>private</keywords>
+ <group>sanitation</group>
+ </service>
+ </services>
+ ';
+
+ my $service_list = get_xml_simple_object( $services_xml );
+
+ 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, 1, 'correct number of contacts';
+
+ my $contact = FixMyStreet::DB->resultset('Contact')->search( { body_id => $body->id } )->first;
+ is $contact->email, '100', 'email correct';
+ is $contact->category, 'Cans left out 24x7', 'category correct';
+ is $contact->non_public, 1, 'contact marked as non_public';
+};
+
+subtest 'check protected categories do not have name/group overwritten' => sub {
+ my $contact = FixMyStreet::DB->resultset('Contact')->search( { body_id => $body->id } )->first;
+ $contact->set_extra_metadata('open311_protect', 1);
+ $contact->set_extra_metadata('group', [ 'sanitation' ]);
+ $contact->non_public(0);
+ $contact->update;
+
+ my $services_xml = '<?xml version="1.0" encoding="utf-8"?>
+ <services>
+ <service>
+ <service_code>100</service_code>
+ <service_name>Cans left out constantly</service_name>
+ <description>Garbage or recycling cans that have been left out for more than 24 hours after collection. Violators will be cited.</description>
+ <metadata>false</metadata>
+ <type>realtime</type>
+ <keywords>private</keywords>
+ <group>cleansing</group>
+ </service>
+ </services>
+ ';
+
+ my $service_list = get_xml_simple_object( $services_xml );
+
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'tester' ],
+ COBRAND_FEATURES => {
+ category_groups => { tester => 1 },
+ }
+ }, sub {
+ 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, 1, 'correct number of contacts';
+
+ $contact->discard_changes;
+ is $contact->email, '100', 'email correct';
+ is $contact->category, 'Cans left out 24x7', 'category unchanged';
+ is_deeply $contact->groups, ['sanitation'], 'group unchanged';
+ # test that something did change
+ is $contact->non_public, 1, 'contact marked as non_public';
+};
+
+
+subtest 'check existing category marked non_public' => sub {
+ my $contact = FixMyStreet::DB->resultset('Contact')->search( { body_id => $body->id } )->first;
+ $contact->update({
+ non_public => 0
+ });
+ is $contact->non_public, 0, 'contact not marked as non_public';
+
+ my $services_xml = '<?xml version="1.0" encoding="utf-8"?>
+ <services>
+ <service>
+ <service_code>100</service_code>
+ <service_name>Cans left out 24x7</service_name>
+ <description>Garbage or recycling cans that have been left out for more than 24 hours after collection. Violators will be cited.</description>
+ <metadata>false</metadata>
+ <type>realtime</type>
+ <keywords>private</keywords>
+ <group>sanitation</group>
+ </service>
+ </services>
+ ';
+
+ my $service_list = get_xml_simple_object( $services_xml );
+
+ 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, 1, 'correct number of contacts';
+
+ $contact->discard_changes;
+ is $contact->email, '100', 'email correct';
+ is $contact->category, 'Cans left out 24x7', 'category correct';
+ is $contact->non_public, 1, 'contact changed to non_public';
+};
+
+subtest 'check existing non_public category does not get marked public' => sub {
+ my $contact = FixMyStreet::DB->resultset('Contact')->search( { body_id => $body->id } )->first;
+ is $contact->non_public, 1, 'contact marked as non_public';
+
+ my $services_xml = '<?xml version="1.0" encoding="utf-8"?>
+ <services>
+ <service>
+ <service_code>100</service_code>
+ <service_name>Cans left out 24x7</service_name>
+ <description>Garbage or recycling cans that have been left out for more than 24 hours after collection. Violators will be cited.</description>
+ <metadata>false</metadata>
+ <type>realtime</type>
+ <keywords></keywords>
+ <group>sanitation</group>
+ </service>
+ </services>
+ ';
+
+ my $service_list = get_xml_simple_object( $services_xml );
+
+ 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, 1, 'correct number of contacts';
+
+ $contact->discard_changes;
+ is $contact->email, '100', 'email correct';
+ is $contact->category, 'Cans left out 24x7', 'category correct';
+ is $contact->non_public, 1, 'contact remains non_public';
+};
+
for my $test (
{
desc => 'check meta data added to existing contact',
@@ -237,7 +476,7 @@ for my $test (
required => 'true',
datatype_description => 'Type of bin',
order => 1,
- description => 'Type of bin'
+ description => 'Type of <b>bin</b>'
} ],
meta_xml => '<?xml version="1.0" encoding="utf-8"?>
@@ -251,7 +490,7 @@ for my $test (
<required>true</required>
<datatype_description>Type of bin</datatype_description>
<order>1</order>
- <description>Type of bin</description>
+ <description>&lt;type&gt;Type&lt;/type&gt; of &lt;b&gt;bin&lt;/b&gt;</description>
</attribute>
</attributes>
</service_definition>
@@ -370,6 +609,134 @@ for my $test (
',
},
{
+ desc => 'check protected meta data not overwritten',
+ has_meta => 1,
+ end_meta => [ {
+ variable => 'true',
+ code => 'type',
+ datatype => 'string',
+ required => 'true',
+ datatype_description => 'Bin type',
+ order => 1,
+ description => 'Bin type',
+ protected => 'true'
+
+ } ],
+ orig_meta => [ {
+ variable => 'true',
+ code => 'type',
+ datatype => 'string',
+ required => 'true',
+ datatype_description => 'Bin type',
+ order => 1,
+ description => 'Bin type',
+ protected => 'true'
+
+ } ],
+ meta_xml => '<?xml version="1.0" encoding="utf-8"?>
+ <service_definition>
+ <service_code>100</service_code>
+ <attributes>
+ <attribute>
+ <variable>true</variable>
+ <code>type</code>
+ <datatype>string</datatype>
+ <required>true</required>
+ <datatype_description>Type of bin</datatype_description>
+ <order>1</order>
+ <description>Type of bin</description>
+ </attribute>
+ </attributes>
+ </service_definition>
+ ',
+ },
+ {
+ desc => 'check protected meta data retained',
+ has_meta => 1,
+ end_meta => [
+ {
+ variable => 'true',
+ code => 'type2',
+ datatype => 'string',
+ required => 'true',
+ datatype_description => 'Type of bin',
+ order => 1,
+ description => 'Type of bin',
+
+ },
+ {
+ variable => 'true',
+ code => 'type',
+ datatype => 'string',
+ required => 'true',
+ datatype_description => 'Number of bin',
+ order => 1,
+ description => 'Number of bin',
+ protected => 'true'
+ },
+ ],
+ orig_meta => [ {
+ variable => 'true',
+ code => 'type',
+ datatype => 'string',
+ required => 'true',
+ datatype_description => 'Number of bin',
+ order => 1,
+ description => 'Number of bin',
+ protected => 'true'
+
+ } ],
+ meta_xml => '<?xml version="1.0" encoding="utf-8"?>
+ <service_definition>
+ <service_code>100</service_code>
+ <attributes>
+ <attribute>
+ <variable>true</variable>
+ <code>type2</code>
+ <datatype>string</datatype>
+ <required>true</required>
+ <datatype_description>Type of bin</datatype_description>
+ <order>1</order>
+ <description>Type of bin</description>
+ </attribute>
+ </attributes>
+ </service_definition>
+ ',
+ },
+ {
+ desc => 'check protected meta data retained on removal of all Open311 extras',
+ end_meta => [
+ {
+ variable => 'true',
+ code => 'type',
+ datatype => 'string',
+ required => 'true',
+ datatype_description => 'Number of bin',
+ order => 1,
+ description => 'Number of bin',
+ protected => 'true'
+ },
+ ],
+ orig_meta => [ {
+ variable => 'true',
+ code => 'type',
+ datatype => 'string',
+ required => 'true',
+ datatype_description => 'Number of bin',
+ order => 1,
+ description => 'Number of bin',
+ protected => 'true'
+
+ } ],
+ meta_xml => '<?xml version="1.0" encoding="utf-8"?>
+ <service_definition>
+ <service_code>100</service_code>
+ <attributes>
+ </attributes>
+ </service_definition>
+ ',
+ },
+ {
desc => 'check empty meta data handled',
has_meta => 1,
orig_meta => [],
diff --git a/t/open311/post-service-request-updates.t b/t/open311/post-service-request-updates.t
index 57b8f9a2a..adfd4e3c5 100644
--- a/t/open311/post-service-request-updates.t
+++ b/t/open311/post-service-request-updates.t
@@ -15,8 +15,8 @@ my $params = {
endpoint => 'endpoint',
jurisdiction => 'home',
};
-my $bromley = $mech->create_body_ok(2482, 'Bromley', { %$params, send_extended_statuses => 1, id => 5 });
-my $oxon = $mech->create_body_ok(2237, 'Oxfordshire', { %$params, id => 55 });
+my $bromley = $mech->create_body_ok(2482, 'Bromley', { %$params, send_extended_statuses => 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);
@@ -61,7 +61,8 @@ my $other_user = $mech->create_user_ok('test2@example.com', title => 'MRS');
sub c {
my ($p, $user) = @_;
- my $c = $mech->create_comment_for_problem($p, $user || $p->user, 'Name', 'Update text', 'f', 'confirmed', 'confirmed', { confirmed => \'current_timestamp' });
+ my $c = $mech->create_comment_for_problem($p, $user || $p->user, 'Name', 'Update text', 'f', 'confirmed', 'confirmed');
+ $c->discard_changes;
return $c;
}
@@ -96,6 +97,30 @@ subtest 'Send comments' => sub {
};
};
+subtest 'Check Bexley munging' => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => ['fixmystreet', 'bexley'],
+ }, sub {
+ my $bexley = $mech->create_body_ok(2494, 'Bexley', $params);
+ $mech->create_contact_ok(body_id => $bexley->id, category => 'Other', email => "OTHER");
+
+ 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 => $bexley,
+ test_mode => 1,
+ test_get_returns => { 'servicerequestupdates.xml' => $test_res },
+ );
+ my ($p5, $c5) = p_and_c($bexley);
+ my $id = $o->post_service_request_update($c5);
+ is $id, 248, 'correct update ID returned';
+ like $o->test_req_used->content, qr/service_code=OTHER/, 'Service code included';
+ };
+};
+
+
subtest 'Oxfordshire gets an ID' => sub {
FixMyStreet::override_config {
ALLOWED_COBRANDS => ['fixmystreet', 'bromley', 'buckinghamshire', 'lewisham', 'oxfordshire'],
diff --git a/t/roles/translatable.t b/t/roles/translatable.t
index e13f49fc6..9f8c67394 100644
--- a/t/roles/translatable.t
+++ b/t/roles/translatable.t
@@ -74,4 +74,11 @@ FixMyStreet::override_config {
$mech->content_contains('Hull i veien');
};
+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";
+};
+
done_testing;
diff --git a/t/script/createsuperuser.t b/t/script/createsuperuser.t
new file mode 100644
index 000000000..1d4826111
--- /dev/null
+++ b/t/script/createsuperuser.t
@@ -0,0 +1,23 @@
+use Test::More;
+use Test::Output;
+
+use_ok 'FixMyStreet::Script::CreateSuperuser';
+
+stderr_like { FixMyStreet::Script::CreateSuperuser::createsuperuser(); }
+ qr/Specify a single email address/, 'Email error shown';
+stderr_is { FixMyStreet::Script::CreateSuperuser::createsuperuser('test@example.org'); }
+ "Specify a password for this new user.\n", 'Password error shown';
+stdout_is { FixMyStreet::Script::CreateSuperuser::createsuperuser('test@example.org', 'password'); }
+ "test\@example.org is now a superuser.\n", 'Correct message shown';
+
+my $user = FixMyStreet::DB->resultset("User")->find({ email => 'test@example.org' });
+ok $user, 'user created';
+is $user->is_superuser, 1, 'is a superuser';
+
+$user->update({ is_superuser => 0 });
+stdout_is { FixMyStreet::Script::CreateSuperuser::createsuperuser('test@example.org'); }
+ "test\@example.org is now a superuser.\n", 'Correct message shown';
+$user->discard_changes;
+is $user->is_superuser, 1, 'is a superuser again';
+
+done_testing;
diff --git a/t/script/inactive.t b/t/script/inactive.t
index 4667c989b..5ef4073dd 100644
--- a/t/script/inactive.t
+++ b/t/script/inactive.t
@@ -1,16 +1,17 @@
use FixMyStreet::TestMech;
+use Test::Output;
use_ok 'FixMyStreet::Script::Inactive';
my $in = FixMyStreet::Script::Inactive->new( anonymize => 6, email => 3 );
my $mech = FixMyStreet::TestMech->new;
-my $user = FixMyStreet::DB->resultset("User")->find_or_create({ email => 'test@example.com' });
+my $user = $mech->create_user_ok('test@example.com');
my $t = DateTime->new(year => 2016, month => 1, day => 1, hour => 12);
$user->last_active($t);
$user->update;
-my $user_inactive = FixMyStreet::DB->resultset("User")->find_or_create({ email => 'inactive@example.com' });
+my $user_inactive = $mech->create_user_ok('inactive@example.com');
$t = DateTime->now->subtract(months => 4);
$user_inactive->last_active($t);
$user_inactive->update;
@@ -22,6 +23,7 @@ for (my $m = 1; $m <= 12; $m++) {
dt => $t,
lastupdate => "$t",
state => $m % 2 ? 'fixed - user' : 'confirmed',
+ cobrand => $m % 3 ? 'default' : 'bromley',
});
}
@@ -50,23 +52,90 @@ subtest 'Anonymization of inactive fixed/closed reports' => sub {
is $comment->user->email, 'removed-automatically@example.org', 'Comment user anonymized';
};
+subtest 'Test operating on one cobrand only' => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'bromley'
+ }, sub {
+ my $in = FixMyStreet::Script::Inactive->new( cobrand => 'bromley', close => 1 );
+ $in->reports;
+ # Reports not a multiple of 2 are fixed, reports a multiple of 3 are bromley
+ $problems[2]->discard_changes;
+ is $problems[2]->get_extra_metadata('closed_updates'), 1, 'Closed to updates';
+ $problems[4]->discard_changes;
+ is $problems[4]->get_extra_metadata('closed_updates'), undef, 'Not closed to updates';
+ $problems[6]->discard_changes;
+ is $problems[6]->get_extra_metadata('closed_updates'), undef, 'Not closed to updates';
+ $problems[8]->discard_changes;
+ is $problems[8]->get_extra_metadata('closed_updates'), 1, 'Closed to updates';
+ };
+};
+
subtest 'Closing updates on inactive fixed/closed reports' => sub {
my $in = FixMyStreet::Script::Inactive->new( close => 1 );
$in->reports;
- $problems[2]->discard_changes;
- is $problems[2]->get_extra_metadata('closed_updates'), 1, 'Closed to updates';
- $mech->get_ok("/report/" . $problems[2]->id);
+ $problems[4]->discard_changes;
+ is $problems[4]->get_extra_metadata('closed_updates'), 1, 'Closed to updates';
+ $mech->get_ok("/report/" . $problems[4]->id);
$mech->content_contains('now closed to updates');
};
+subtest 'Deleting reports' => sub {
+ my $in = FixMyStreet::Script::Inactive->new( delete => 6 );
+ $in->reports;
+
+ my $count = FixMyStreet::DB->resultset("Problem")->count;
+ is $count, 6, 'Six left';
+
+ $mech->get("/report/" . $problems[2]->id);
+ is $mech->res->code, 404;
+};
+
subtest 'Anonymization of inactive users' => sub {
- $in->users;
+ my $in = FixMyStreet::Script::Inactive->new( anonymize => 6, email => 3, verbose => 1 );
+ stdout_is { $in->users } "Anonymizing user #" . $user->id . "\nEmailing user #" . $user_inactive->id . "\n", 'users dealt with first time';
my $email = $mech->get_email;
like $email->as_string, qr/inactive\@example.com/, 'Inactive email sent';
+ $mech->clear_emails_ok;
$user->discard_changes;
is $user->email, 'removed-' . $user->id . '@example.org', 'User has been anonymized';
+
+ stdout_is { $in->users } '', 'No output second time';
+
+ $mech->email_count_is(0); # No further email sent
+
+ $user->discard_changes;
+ is $user->email, 'removed-' . $user->id . '@example.org', 'User has been anonymized';
+};
+
+subtest 'Test TfL deletion of safety critical reports' => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'tfl'
+ }, sub {
+ for (my $y = 2; $y <= 10; $y+=2) {
+ # 2 years, not safety; 4 years safety, 6 years not safety, 8 years safety, 10 years not safety
+ my $t = DateTime->now->subtract(years => $y);
+ my ($problem) = $mech->create_problems_for_body(1, 2237, 'Title', {
+ dt => $t,
+ lastupdate => "$t",
+ state => 'fixed - user',
+ cobrand => 'tfl',
+ });
+ $problem->update_extra_field({ name => 'safety_critical', value => $y % 4 ? 'no' : 'yes' });
+ $problem->update;
+ }
+
+ my $in = FixMyStreet::Script::Inactive->new( cobrand => 'tfl', delete => 36 );
+ $in->reports;
+ my $count = FixMyStreet::DB->resultset("Problem")->search({ cobrand => 'tfl' })->count;
+ is $count, 3, 'Three reports left, one too recent, two safety critical';
+
+ $in = FixMyStreet::Script::Inactive->new( cobrand => 'tfl', delete => 84 );
+ $in->reports;
+ $count = FixMyStreet::DB->resultset("Problem")->search({ cobrand => 'tfl' })->count;
+ is $count, 2, 'Two reports left, two too recent';
+ }
};
done_testing;
diff --git a/t/sendreport/open311.t b/t/sendreport/open311.t
index e68a0aa3c..1cec5dd68 100644
--- a/t/sendreport/open311.t
+++ b/t/sendreport/open311.t
@@ -11,6 +11,7 @@ package main;
use CGI::Simple;
use Path::Tiny;
+use Test::Warn;
use FixMyStreet::Script::Reports;
use FixMyStreet::TestMech;
my $mech = FixMyStreet::TestMech->new;
@@ -133,4 +134,66 @@ subtest 'test sending multiple photos', sub {
], 'Multiple photos in media_url';
};
+my ($bad_category_report) = $mech->create_problems_for_body( 1, $body->id, 'Test', {
+ cobrand => 'fixmystreet',
+ category => 'Flytipping',
+ user => $user,
+});
+
+subtest 'test handles bad category', sub {
+ $body->update( { send_method => 'Open311', endpoint => 'http://endpoint.example.com', jurisdiction => 'FMS', api_key => 'test' } );
+ my $test_data;
+ FixMyStreet::override_config {
+ STAGING_FLAGS => { send_reports => 1 },
+ ALLOWED_COBRANDS => [ 'fixmystreet' ],
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $test_data = FixMyStreet::Script::Reports::send();
+ };
+ $bad_category_report->discard_changes;
+ ok !$bad_category_report->whensent, 'Report not marked as sent';
+ like $bad_category_report->send_fail_reason, qr/Category Flytipping does not exist for body/, 'failure message set';
+};
+
+my $hounslow = $mech->create_body_ok( 2483, 'Hounslow Borough Council');
+my $contact2 = $mech->create_contact_ok( body_id => $hounslow->id, category => 'Graffiti', email => 'GRAF' );
+$contact2->set_extra_fields(
+ { code => 'easting', datatype => 'number' },
+ { code => 'northing', datatype => 'number' },
+ { code => 'fixmystreet_id', datatype => 'number' },
+);
+$contact2->update;
+
+my ($hounslow_report) = $mech->create_problems_for_body( 1, $hounslow->id, 'Test', {
+ cobrand => 'hounslow',
+ category => 'Graffiti',
+ user => $user,
+ latitude => 51.482286,
+ longitude => -0.328163,
+ cobrand => 'hounslow',
+});
+
+subtest 'Hounslow sends email upon Open311 submission', sub {
+ $hounslow->update( { send_method => 'Open311', endpoint => 'http://endpoint.example.com', jurisdiction => 'hounslow', api_key => 'test' } );
+ $mech->clear_emails_ok;
+ FixMyStreet::override_config {
+ STAGING_FLAGS => { send_reports => 1 },
+ ALLOWED_COBRANDS => [ 'hounslow' ],
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ FixMyStreet::Script::Reports::send();
+ };
+ $hounslow_report->discard_changes;
+ ok $hounslow_report->whensent, 'Report marked as sent';
+ ok $hounslow_report->get_extra_metadata('hounslow_email_sent'), "Enquiries inbox email marked as sent";
+ my ($hounslow_email, $user_email) = $mech->get_email;
+ my $body = $mech->get_text_body_from_email($hounslow_email);
+ like $body, qr/A user of FixMyStreet has submitted the following report/;
+ like $body, qr/Category: Graffiti/;
+ like $body, qr/Enquiry ref: 248/;
+ $body = $mech->get_text_body_from_email($user_email);
+ like $body, qr/reference number is 248/;
+};
+
+
done_testing();
diff --git a/t/template.t b/t/template.t
new file mode 100644
index 000000000..91e4ccc84
--- /dev/null
+++ b/t/template.t
@@ -0,0 +1,39 @@
+use FixMyStreet::Test;
+
+use_ok 'FixMyStreet::Template';
+
+my $tt = FixMyStreet::Template->new;
+
+my $output = '';
+$tt->process(\'[% s %] [% s | safe %] [% s | upper %] [% s | html %]', {
+ s => 'sp<i>l</i>it'
+}, \$output);
+is $output, 'sp&lt;i&gt;l&lt;/i&gt;it sp<i>l</i>it SP&lt;I&gt;L&lt;/I&gt;IT sp&lt;i&gt;l&lt;/i&gt;it';
+
+$output = '';
+$tt->process(\'[% s | html_para %]', { s => 'sp<i>l</i>it' }, \$output);
+is $output, "<p>\nsp&lt;i&gt;l&lt;/i&gt;it</p>\n";
+
+$output = '';
+$tt->process(\'[% loc("s") %] [% loc("s") | html_para %]', {}, \$output);
+is $output, "s <p>\ns</p>\n";
+
+$output = '';
+$tt->process(\'[% s.upper %] [% t = s %][% t %] [% t.upper %]', {
+ s => 'sp<i>l</i>it'
+}, \$output);
+is $output, 'SP&lt;I&gt;L&lt;/I&gt;IT sp&lt;i&gt;l&lt;/i&gt;it SP&lt;I&gt;L&lt;/I&gt;IT';
+
+$output = '';
+$tt->process(\'H: [% s.split(":").join(",") %]', {
+ s => '1:sp<i>l</i>it:3'
+}, \$output);
+is $output, 'H: 1,sp&lt;i&gt;l&lt;/i&gt;it,3';
+
+$output = '';
+$tt->process(\'[% size %] [% 100 / size %] [% size / 100 %]', {
+ size => 4
+}, \$output);
+is $output, '4 25 0.04';
+
+done_testing;