aboutsummaryrefslogtreecommitdiffstats
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/Mock/GoogleGeocoder.pm36
-rw-r--r--t/app/controller/admin.t1671
-rw-r--r--t/app/controller/admin/bodies.t165
-rw-r--r--t/app/controller/admin/defecttypes.t (renamed from t/app/controller/admin_defecttypes.t)0
-rw-r--r--t/app/controller/admin/permissions.t (renamed from t/app/controller/admin_permissions.t)0
-rw-r--r--t/app/controller/admin/priorities.t102
-rw-r--r--t/app/controller/admin/report_edit.t556
-rw-r--r--t/app/controller/admin/reportextrafields.t (renamed from t/app/controller/admin_reportextrafields.t)0
-rw-r--r--t/app/controller/admin/search.t121
-rw-r--r--t/app/controller/admin/states.t (renamed from t/app/controller/admin_states.t)0
-rw-r--r--t/app/controller/admin/stats.t12
-rw-r--r--t/app/controller/admin/templates.t183
-rw-r--r--t/app/controller/admin/translations.t (renamed from t/app/controller/admin_translations.t)0
-rw-r--r--t/app/controller/admin/update_edit.t383
-rw-r--r--t/app/controller/admin/users.t453
-rw-r--r--t/app/controller/around.t21
-rw-r--r--t/app/controller/auth.t48
-rw-r--r--t/app/controller/auth_profile.t115
-rw-r--r--t/app/controller/report_as_other.t140
-rw-r--r--t/app/controller/report_new.t42
-rw-r--r--t/app/controller/report_new_text.t4
-rw-r--r--t/app/controller/report_update_text.t2
-rw-r--r--t/app/controller/rss.t60
-rw-r--r--t/app/model/problem.t13
-rw-r--r--t/app/sendreport/inspection_required.t15
-rw-r--r--t/cobrand/bromley.t5
-rw-r--r--t/cobrand/fixamingata.t3
-rw-r--r--t/cobrand/zurich.t37
-rw-r--r--t/geocode/google.t22
-rw-r--r--t/images/12049724866_404b066875_z.jpgbin0 -> 144831 bytes
-rw-r--r--t/images/12205918375_f37f0b27a9_z.jpgbin0 -> 152674 bytes
-rw-r--r--t/images/14347396807_20737504f7_z.jpgbin0 -> 169141 bytes
-rw-r--r--t/images/14792525771_167bc20e3d_z.jpgbin0 -> 106463 bytes
-rw-r--r--t/images/19119222668_a3c866d7c8_z.jpgbin0 -> 127230 bytes
-rw-r--r--t/images/20515339175_f4ed9fc1d9_z.jpgbin0 -> 105014 bytes
-rw-r--r--t/images/22593395257_3d48f23bfa_z.jpgbin0 -> 212973 bytes
-rw-r--r--t/images/22998854352_17555b7536_z.jpgbin0 -> 96995 bytes
-rw-r--r--t/images/23222004240_273977b2b2_z.jpgbin0 -> 136915 bytes
-rw-r--r--t/images/27050321819_ac123400eb_z.jpgbin0 -> 158859 bytes
-rw-r--r--t/images/31889115854_01cdf38b0d_z.jpgbin0 -> 71055 bytes
-rw-r--r--t/images/33717571655_46dfc6f65f_z.jpgbin0 -> 214007 bytes
-rw-r--r--t/images/35732107202_b790c61f63_z.jpgbin0 -> 122716 bytes
-rw-r--r--t/images/36296226976_a83a118ff8_z.jpgbin0 -> 197974 bytes
-rw-r--r--t/images/3705226606_eac71cf195_z.jpgbin0 -> 90645 bytes
-rw-r--r--t/images/37855543925_9dbbbecf41_z.jpgbin0 -> 82708 bytes
-rw-r--r--t/images/38110448864_fd71227247_z.jpgbin0 -> 109570 bytes
-rw-r--r--t/images/6304445383_bd216ca892_z.jpgbin0 -> 199228 bytes
-rw-r--r--t/images/8895442578_376a9b0be0_z.jpgbin0 -> 127203 bytes
-rw-r--r--t/sendreport/open311.t3
-rw-r--r--t/utils.t4
50 files changed, 2428 insertions, 1788 deletions
diff --git a/t/Mock/GoogleGeocoder.pm b/t/Mock/GoogleGeocoder.pm
new file mode 100644
index 000000000..fd741c00e
--- /dev/null
+++ b/t/Mock/GoogleGeocoder.pm
@@ -0,0 +1,36 @@
+package t::Mock::GoogleGeocoder;
+
+use JSON::MaybeXS;
+use Web::Simple;
+use LWP::Protocol::PSGI;
+
+has json => (
+ is => 'lazy',
+ default => sub {
+ JSON->new->utf8->pretty->allow_blessed->convert_blessed;
+ },
+);
+
+sub dispatch_request {
+ my $self = shift;
+
+ sub (GET + /maps/api/geocode/json + ?*) {
+ my ($self, $args) = @_;
+ my $response = {};
+ if ($args->{address} =~ /result/) {
+ $response->{status} = 'OK';
+ push @{$response->{results}}, { formatted_address => 'High Street, Old Town, City of Edinburgh, Scotland', geometry => { location => { lng => -3.1858425, lat => 55.9504009 } } };
+ }
+ if ($args->{address} eq 'two results') {
+ push @{$response->{results}}, { geometry => { location => { lat => "55.8596449", "lng" => "-4.240377" } }, formatted_address => "High Street, Collegelands, Merchant City, Glasgow, Scotland" };
+ }
+ my $json = mySociety::Locale::in_gb_locale {
+ $self->json->encode($response);
+ };
+ return [ 200, [ 'Content-Type' => 'application/json' ], [ $json ] ];
+ },
+}
+
+LWP::Protocol::PSGI->register(t::Mock::GoogleGeocoder->to_psgi_app, host => 'maps.googleapis.com');
+
+__PACKAGE__->run_if_script;
diff --git a/t/app/controller/admin.t b/t/app/controller/admin.t
index 398ce8ea6..b69a711c8 100644
--- a/t/app/controller/admin.t
+++ b/t/app/controller/admin.t
@@ -1,27 +1,14 @@
use FixMyStreet::TestMech;
-# avoid wide character warnings from the category change message
-use open ':std', ':encoding(UTF-8)';
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 $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' );
-$mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Traffic lights', email => 'lights@example.com' );
my $oxfordshireuser = $mech->create_user_ok('counciluser@example.com', name => 'Council User', from_body => $oxfordshire);
-my $oxford = $mech->create_body_ok(2421, 'Oxford City Council');
-$mech->create_contact_ok( body_id => $oxford->id, category => 'Graffiti', email => 'graffiti@example.net' );
-
-my $bromley = $mech->create_body_ok(2482, 'Bromley Council');
-
-my $user3;
-
my $dt = DateTime->new(
year => 2011,
month => 04,
@@ -56,6 +43,8 @@ my $report = FixMyStreet::App->model('DB::Problem')->find_or_create(
whensent => $dt->ymd . ' ' . $dt->hms,
}
);
+my $report_id = $report->id;
+ok $report, "created test report - $report_id";
my $alert = FixMyStreet::App->model('DB::Alert')->find_or_create(
{
@@ -138,1433 +127,6 @@ subtest 'check summary counts' => sub {
ok $mech->host('www.fixmystreet.com');
};
-# This override is wrapped around ALL the /admin/body tests
-FixMyStreet::override_config {
- MAPIT_URL => 'http://mapit.uk/',
- MAPIT_TYPES => [ 'UTA' ],
- BASE_URL => 'http://www.example.org',
-}, sub {
-
-my $body = $mech->create_body_ok(2650, 'Aberdeen City Council');
-$mech->get_ok('/admin/body/' . $body->id);
-$mech->content_contains('Aberdeen City Council');
-$mech->content_like(qr{AB\d\d});
-$mech->content_contains("http://www.example.org/around");
-
-subtest 'check contact creation' => sub {
- $mech->get_ok('/admin/body/' . $body->id);
-
- $mech->submit_form_ok( { with_fields => {
- category => 'test category',
- email => 'test@example.com',
- note => 'test note',
- non_public => undef,
- state => 'unconfirmed',
- } } );
-
- $mech->content_contains( 'test category' );
- $mech->content_contains( 'test@example.com' );
- $mech->content_contains( '<td>test note' );
- $mech->content_like( qr/<td>\s*unconfirmed\s*<\/td>/ ); # No private
-
- $mech->submit_form_ok( { with_fields => {
- category => 'private category',
- email => 'test@example.com',
- note => 'test note',
- non_public => 'on',
- } } );
-
- $mech->content_contains( 'private category' );
- $mech->content_like( qr{test\@example.com\s*</td>\s*<td>\s*confirmed\s*<br>\s*<small>\s*Private\s*</small>\s*</td>} );
-
- $mech->submit_form_ok( { with_fields => {
- category => 'test/category',
- email => 'test@example.com',
- note => 'test/note',
- non_public => 'on',
- } } );
- $mech->get_ok('/admin/body/' . $body->id . '/test/category');
- $mech->content_contains('<h1>test/category</h1>');
-};
-
-subtest 'check contact editing' => sub {
- $mech->get_ok('/admin/body/' . $body->id .'/test%20category');
-
- $mech->submit_form_ok( { with_fields => {
- email => 'test2@example.com',
- note => 'test2 note',
- non_public => undef,
- } } );
-
- $mech->content_contains( 'test category' );
- $mech->content_like( qr{test2\@example.com\s*</td>\s*<td>\s*unconfirmed\s*</td>} );
- $mech->content_contains( '<td>test2 note' );
-
- $mech->get_ok('/admin/body/' . $body->id . '/test%20category');
- $mech->submit_form_ok( { with_fields => {
- email => 'test2@example.com, test3@example.com',
- note => 'test3 note',
- } } );
-
- $mech->content_contains( 'test2@example.com,test3@example.com' );
-
- $mech->get_ok('/admin/body/' . $body->id . '/test%20category');
- $mech->content_contains( '<td><strong>test2@example.com,test3@example.com' );
-
- $mech->submit_form_ok( { with_fields => {
- email => 'test2@example.com',
- note => 'test2 note',
- non_public => 'on',
- } } );
-
- $mech->content_like( qr{test2\@example.com\s*</td>\s*<td>\s*unconfirmed\s*<br>\s*<small>\s*Private\s*</small>\s*</td>} );
-
- $mech->get_ok('/admin/body/' . $body->id . '/test%20category');
- $mech->content_contains( '<td><strong>test2@example.com' );
-};
-
-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);
-
- $mech->get_ok('/admin/body/' . $body->id);
-
- $mech->form_number( 1 );
- $mech->tick( 'confirmed', 'test category' );
- $mech->submit_form_ok({form_number => 1});
-
- $mech->content_like(qr'test2@example.com</td>[^<]*<td>\s*confirmed's);
- $mech->get_ok('/admin/body/' . $body->id . '/test%20category');
- $mech->content_like(qr{test2\@example.com[^<]*</td>[^<]*<td><strong>confirmed}s);
-};
-
-$body->update({ send_method => undef });
-
-subtest 'check open311 configuring' => sub {
- $mech->get_ok('/admin/body/' . $body->id);
- $mech->content_lacks('Council contacts configured via Open311');
-
- $mech->form_number(3);
- $mech->submit_form_ok(
- {
- with_fields => {
- api_key => 'api key',
- endpoint => 'http://example.com/open311',
- jurisdiction => 'mySociety',
- send_comments => 0,
- send_method => 'Open311',
- }
- }
- );
- $mech->content_contains('Council contacts configured via Open311');
- $mech->content_contains('Values updated');
-
- my $conf = FixMyStreet::App->model('DB::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';
-
- $mech->form_number(3);
- $mech->submit_form_ok(
- {
- with_fields => {
- api_key => 'new api key',
- endpoint => 'http://example.org/open311',
- jurisdiction => 'open311',
- send_comments => 0,
- send_method => 'Open311',
- }
- }
- );
-
- $mech->content_contains('Values updated');
-
- $conf = FixMyStreet::App->model('DB::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';
-};
-
-subtest 'check text output' => sub {
- $mech->get_ok('/admin/body/' . $body->id . '?text=1');
- is $mech->content_type, 'text/plain';
- $mech->content_contains('test category');
- $mech->content_lacks('<body');
-};
-
-
-}; # END of override wrap
-
-
-my $log_entries = FixMyStreet::App->model('DB::AdminLog')->search(
- {
- object_type => 'problem',
- object_id => $report->id
- },
- {
- order_by => { -desc => 'id' },
- }
-);
-
-is $log_entries->count, 0, 'no admin log entries';
-
-my $report_id = $report->id;
-ok $report, "created test report - $report_id";
-
-foreach my $test (
- {
- description => 'edit report title',
- fields => {
- title => 'Report to Edit',
- detail => 'Detail for Report to Edit',
- state => 'confirmed',
- name => 'Test User',
- username => $user->email,
- anonymous => 0,
- flagged => undef,
- non_public => undef,
- },
- changes => { title => 'Edited Report', },
- log_entries => [qw/edit/],
- resend => 0,
- },
- {
- description => 'edit report description',
- fields => {
- title => 'Edited Report',
- detail => 'Detail for Report to Edit',
- state => 'confirmed',
- name => 'Test User',
- username => $user->email,
- anonymous => 0,
- flagged => undef,
- non_public => undef,
- },
- changes => { detail => 'Edited Detail', },
- log_entries => [qw/edit edit/],
- resend => 0,
- },
- {
- description => 'edit report user name',
- fields => {
- title => 'Edited Report',
- detail => 'Edited Detail',
- state => 'confirmed',
- name => 'Test User',
- username => $user->email,
- anonymous => 0,
- flagged => undef,
- non_public => undef,
- },
- changes => { name => 'Edited User', },
- log_entries => [qw/edit edit edit/],
- resend => 0,
- user => $user,
- },
- {
- description => 'edit report set flagged true',
- fields => {
- title => 'Edited Report',
- detail => 'Edited Detail',
- state => 'confirmed',
- name => 'Edited User',
- username => $user->email,
- anonymous => 0,
- flagged => undef,
- non_public => undef,
- },
- changes => {
- flagged => 'on',
- },
- log_entries => [qw/edit edit edit edit/],
- resend => 0,
- user => $user,
- },
- {
- description => 'edit report user email',
- fields => {
- title => 'Edited Report',
- detail => 'Edited Detail',
- state => 'confirmed',
- name => 'Edited User',
- username => $user->email,
- anonymous => 0,
- flagged => 'on',
- non_public => undef,
- },
- changes => { username => $user2->email, },
- log_entries => [qw/edit edit edit edit edit/],
- resend => 0,
- user => $user2,
- },
- {
- description => 'change state to unconfirmed',
- fields => {
- title => 'Edited Report',
- detail => 'Edited Detail',
- state => 'confirmed',
- name => 'Edited User',
- username => $user2->email,
- anonymous => 0,
- flagged => 'on',
- non_public => undef,
- },
- expect_comment => 1,
- changes => { state => 'unconfirmed' },
- log_entries => [qw/edit state_change edit edit edit edit edit/],
- resend => 0,
- },
- {
- description => 'change state to confirmed',
- fields => {
- title => 'Edited Report',
- detail => 'Edited Detail',
- state => 'unconfirmed',
- name => 'Edited User',
- username => $user2->email,
- anonymous => 0,
- flagged => 'on',
- non_public => undef,
- },
- expect_comment => 1,
- changes => { state => 'confirmed' },
- log_entries => [qw/edit state_change edit state_change edit edit edit edit edit/],
- resend => 0,
- },
- {
- description => 'change state to fixed',
- fields => {
- title => 'Edited Report',
- detail => 'Edited Detail',
- state => 'confirmed',
- name => 'Edited User',
- username => $user2->email,
- anonymous => 0,
- flagged => 'on',
- non_public => undef,
- },
- expect_comment => 1,
- changes => { state => 'fixed' },
- log_entries =>
- [qw/edit state_change edit state_change edit state_change edit edit edit edit edit/],
- resend => 0,
- },
- {
- description => 'change state to hidden',
- fields => {
- title => 'Edited Report',
- detail => 'Edited Detail',
- state => 'fixed',
- name => 'Edited User',
- username => $user2->email,
- anonymous => 0,
- flagged => 'on',
- non_public => undef,
- },
- expect_comment => 1,
- changes => { state => 'hidden' },
- log_entries => [
- qw/edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/
- ],
- resend => 0,
- },
- {
- description => 'edit and change state',
- fields => {
- title => 'Edited Report',
- detail => 'Edited Detail',
- state => 'hidden',
- name => 'Edited User',
- username => $user2->email,
- anonymous => 0,
- flagged => 'on',
- non_public => undef,
- },
- expect_comment => 1,
- changes => {
- state => 'confirmed',
- anonymous => 1,
- },
- log_entries => [
- qw/edit state_change edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/
- ],
- resend => 0,
- },
- {
- description => 'resend',
- fields => {
- title => 'Edited Report',
- detail => 'Edited Detail',
- state => 'confirmed',
- name => 'Edited User',
- username => $user2->email,
- anonymous => 1,
- flagged => 'on',
- non_public => undef,
- },
- changes => {},
- log_entries => [
- qw/resend edit state_change edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/
- ],
- resend => 1,
- },
- {
- description => 'non public',
- fields => {
- title => 'Edited Report',
- detail => 'Edited Detail',
- state => 'confirmed',
- name => 'Edited User',
- username => $user2->email,
- anonymous => 1,
- flagged => 'on',
- non_public => undef,
- },
- changes => {
- non_public => 'on',
- },
- log_entries => [
- qw/edit resend edit state_change edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/
- ],
- resend => 0,
- },
- {
- description => 'change state to investigating as body superuser',
- fields => {
- title => 'Edited Report',
- detail => 'Edited Detail',
- state => 'confirmed',
- name => 'Edited User',
- username => $user2->email,
- anonymous => 1,
- flagged => 'on',
- non_public => 'on',
- },
- expect_comment => 1,
- user_body => $oxfordshire,
- changes => { state => 'investigating' },
- log_entries => [
- qw/edit state_change edit resend edit state_change edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/
- ],
- resend => 0,
- },
- {
- description => 'change state to in progess and change category as body superuser',
- fields => {
- title => 'Edited Report',
- detail => 'Edited Detail',
- state => 'investigating',
- name => 'Edited User',
- username => $user2->email,
- anonymous => 1,
- flagged => 'on',
- non_public => 'on',
- },
- expect_comment => 1,
- expected_text => '*Category changed from ‘Other’ to ‘Potholes’*',
- user_body => $oxfordshire,
- changes => { state => 'in progress', category => 'Potholes' },
- log_entries => [
- qw/edit state_change edit state_change edit resend edit state_change edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/
- ],
- resend => 0,
- },
- )
-{
- subtest $test->{description} => sub {
- $report->comments->delete;
- $log_entries->reset;
-
- if ( $test->{user_body} ) {
- $superuser->from_body( $test->{user_body}->id );
- $superuser->update;
- }
-
- $mech->get_ok("/admin/report_edit/$report_id");
-
- @{$test->{fields}}{'external_id', 'external_body', 'external_team', 'category'} = (13, "", "", "Other");
- is_deeply( $mech->visible_form_values(), $test->{fields}, 'initial form values' );
-
- my $new_fields = {
- %{ $test->{fields} },
- %{ $test->{changes} },
- };
-
- if ( $test->{resend} ) {
- $mech->click_ok( 'resend' );
- } else {
- $mech->submit_form_ok( { with_fields => $new_fields }, 'form_submitted' );
- }
-
- is_deeply( $mech->visible_form_values(), $new_fields, 'changed form values' );
- is $log_entries->count, scalar @{$test->{log_entries}}, 'log entry count';
- is $log_entries->next->action, $_, 'log entry added' for @{ $test->{log_entries} };
-
- $report->discard_changes;
-
- if ($report->state eq 'confirmed' && $report->whensent) {
- $mech->content_contains( 'type="submit" name="resend"', 'resend button' );
- } else {
- $mech->content_lacks( 'type="submit" name="resend"', 'no resend button' );
- }
-
- $test->{changes}->{flagged} = 1 if $test->{changes}->{flagged};
- $test->{changes}->{non_public} = 1 if $test->{changes}->{non_public};
-
- is $report->$_, $test->{changes}->{$_}, "$_ updated" for grep { $_ ne 'username' } keys %{ $test->{changes} };
-
- if ( $test->{user} ) {
- is $report->user->id, $test->{user}->id, 'user changed';
- }
-
- if ( $test->{resend} ) {
- $mech->content_contains( 'That problem will now be resent' );
- is $report->whensent, undef, 'mark report to resend';
- }
-
- if ( $test->{expect_comment} ) {
- my $comment = $report->comments->first;
- ok $comment, 'report status change creates comment';
- is $report->comments->count, 1, 'report only has one comment';
- if ($test->{expected_text}) {
- is $comment->text, $test->{expected_text}, 'comment has expected text';
- } else {
- is $comment->text, '', 'comment has no text';
- }
- if ( $test->{user_body} ) {
- ok $comment->get_extra_metadata('is_body_user'), 'body user metadata set';
- ok !$comment->get_extra_metadata('is_superuser'), 'superuser metadata not set';
- is $comment->name, $test->{user_body}->name, 'comment name is body name';
- } else {
- ok !$comment->get_extra_metadata('is_body_user'), 'body user metadata not set';
- ok $comment->get_extra_metadata('is_superuser'), 'superuser metadata set';
- is $comment->name, _('an administrator'), 'comment name is admin';
- }
- } else {
- is $report->comments->count, 0, 'report has no comments';
- }
-
- $superuser->from_body(undef);
- $superuser->update;
- };
-}
-
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => 'fixmystreet',
-}, sub {
-
-subtest 'change report category' => sub {
- my ($ox_report) = $mech->create_problems_for_body(1, $oxfordshire->id, 'Unsure', {
- category => 'Potholes',
- areas => ',2237,2421,', # Cached used by categories_for_point...
- latitude => 51.7549262252,
- longitude => -1.25617899435,
- whensent => \'current_timestamp',
- });
- $mech->get_ok("/admin/report_edit/" . $ox_report->id);
-
- $mech->submit_form_ok( { with_fields => { category => 'Traffic lights' } }, 'form_submitted' );
- $ox_report->discard_changes;
- is $ox_report->category, 'Traffic lights';
- isnt $ox_report->whensent, undef;
- is $ox_report->comments->count, 1, "Comment created for update";
- is $ox_report->comments->first->text, '*Category changed from ‘Potholes’ to ‘Traffic lights’*', 'Comment text correct';
-
- $mech->submit_form_ok( { with_fields => { category => 'Graffiti' } }, 'form_submitted' );
- $ox_report->discard_changes;
- is $ox_report->category, 'Graffiti';
- is $ox_report->whensent, undef;
-};
-
-};
-
-subtest 'change email to new user' => sub {
- $log_entries->delete;
- $mech->get_ok("/admin/report_edit/$report_id");
- my $fields = {
- title => $report->title,
- detail => $report->detail,
- state => $report->state,
- name => $report->name,
- username => $report->user->email,
- category => 'Potholes',
- anonymous => 1,
- flagged => 'on',
- non_public => 'on',
- external_id => '13',
- external_body => '',
- external_team => '',
- };
-
- is_deeply( $mech->visible_form_values(), $fields, 'initial form values' );
-
- my $changes = {
- username => 'test3@example.com'
- };
-
- $user3 = FixMyStreet::App->model('DB::User')->find( { email => 'test3@example.com' } );
-
- ok !$user3, 'user not in database';
-
- my $new_fields = {
- %{ $fields },
- %{ $changes },
- };
-
- $mech->submit_form_ok(
- {
- with_fields => $new_fields,
- }
- );
-
- is $log_entries->count, 1, 'created admin log entries';
- 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' } );
-
- $report->discard_changes;
-
- ok $user3, 'new user created';
- is $report->user_id, $user3->id, 'user changed to new user';
-};
-
-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 } );
- $abuse->delete if $abuse;
-
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->content_contains('Ban user');
-
- $mech->click_ok('banuser');
-
- $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 } );
- ok $abuse, 'entry created in abuse table';
-
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->content_contains('<small>User in abuse table</small>');
-};
-
-subtest 'remove user from abuse list from edit user page' => sub {
- my $abuse = FixMyStreet::App->model('DB::Abuse')->find_or_create( { email => $user->email } );
- $mech->get_ok( '/admin/user_edit/' . $user->id );
- $mech->content_contains('User in abuse table');
-
- $mech->click_ok('unban');
-
- $abuse = FixMyStreet::App->model('DB::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 } );
- $mech->get_ok( '/admin/user_edit/' . $abuse_user->id );
- $mech->content_contains('User in abuse table');
- my $abuse_found = FixMyStreet::App->model('DB::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 } );
- 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 } );
- $abuse->delete if $abuse;
- $mech->get_ok( '/admin/user_edit/' . $user->id );
- $mech->content_lacks('User in abuse table');
-};
-
-subtest 'flagging user from report page' => sub {
- $report->user->flagged(0);
- $report->user->update;
-
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->content_contains('Flag user');
-
- $mech->click_ok('flaguser');
-
- $mech->content_contains('User flagged');
- $mech->content_contains('Remove flag');
-
- $report->discard_changes;
- ok $report->user->flagged, 'user flagged';
-
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->content_contains('Remove flag');
-};
-
-subtest 'unflagging user from report page' => sub {
- $report->user->flagged(1);
- $report->user->update;
-
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->content_contains('Remove flag');
-
- $mech->click_ok('removeuserflag');
-
- $mech->content_contains('User flag removed');
- $mech->content_contains('Flag user');
-
- $report->discard_changes;
- ok !$report->user->flagged, 'user not flagged';
-
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->content_contains('Flag user');
-};
-
-$log_entries->delete;
-
-my $update = FixMyStreet::App->model('DB::Comment')->create(
- {
- text => 'this is an update',
- user => $user,
- state => 'confirmed',
- problem => $report,
- mark_fixed => 0,
- anonymous => 1,
- }
-);
-
-$log_entries = FixMyStreet::App->model('DB::AdminLog')->search(
- {
- object_type => 'update',
- object_id => $update->id
- },
- {
- order_by => { -desc => 'id' },
- }
-);
-
-is $log_entries->count, 0, 'no admin log entries';
-
-for my $test (
- {
- desc => 'edit update text',
- fields => {
- text => 'this is an update',
- state => 'confirmed',
- name => '',
- anonymous => 1,
- username => 'test@example.com',
- },
- changes => {
- text => 'this is a changed update',
- },
- log_count => 1,
- log_entries => [qw/edit/],
- },
- {
- desc => 'edit update name',
- fields => {
- text => 'this is a changed update',
- state => 'confirmed',
- name => '',
- anonymous => 1,
- username => 'test@example.com',
- },
- changes => {
- name => 'A User',
- },
- log_count => 2,
- log_entries => [qw/edit edit/],
- },
- {
- desc => 'edit update anonymous',
- fields => {
- text => 'this is a changed update',
- state => 'confirmed',
- name => 'A User',
- anonymous => 1,
- username => 'test@example.com',
- },
- changes => {
- anonymous => 0,
- },
- log_count => 3,
- log_entries => [qw/edit edit edit/],
- },
- {
- desc => 'edit update user',
- fields => {
- text => 'this is a changed update',
- state => 'confirmed',
- name => 'A User',
- anonymous => 0,
- username => 'test@example.com',
- },
- changes => {
- username => 'test2@example.com',
- },
- log_count => 4,
- log_entries => [qw/edit edit edit edit/],
- user => $user2,
- },
- {
- desc => 'edit update state',
- fields => {
- text => 'this is a changed update',
- state => 'confirmed',
- name => 'A User',
- anonymous => 0,
- username => 'test2@example.com',
- },
- changes => {
- state => 'unconfirmed',
- },
- log_count => 5,
- log_entries => [qw/state_change edit edit edit edit/],
- },
- {
- desc => 'edit update state and text',
- fields => {
- text => 'this is a changed update',
- state => 'unconfirmed',
- name => 'A User',
- anonymous => 0,
- username => 'test2@example.com',
- },
- changes => {
- text => 'this is a twice changed update',
- state => 'confirmed',
- },
- log_count => 7,
- log_entries => [qw/edit state_change state_change edit edit edit edit/],
- },
-) {
- subtest $test->{desc} => sub {
- $log_entries->reset;
- $mech->get_ok('/admin/update_edit/' . $update->id );
-
- is_deeply $mech->visible_form_values, $test->{fields}, 'initial form values';
-
- my $to_submit = {
- %{ $test->{fields} },
- %{ $test->{changes} }
- };
-
- $mech->submit_form_ok( { with_fields => $to_submit } );
-
- is_deeply $mech->visible_form_values, $to_submit, 'submitted form values';
-
- is $log_entries->count, $test->{log_count}, 'number of log entries';
- is $log_entries->next->action, $_, 'log action' for @{ $test->{log_entries} };
-
- $update->discard_changes;
-
- is $update->$_, $test->{changes}->{$_} for grep { $_ ne 'username' } keys %{ $test->{changes} };
- if ( $test->{changes}{state} && $test->{changes}{state} eq 'confirmed' ) {
- isnt $update->confirmed, undef;
- }
-
- if ( $test->{user} ) {
- is $update->user->id, $test->{user}->id, 'update user';
- }
- };
-}
-
-my $westminster = $mech->create_body_ok(2504, 'Westminster City Council');
-$report->bodies_str($westminster->id);
-$report->update;
-
-for my $test (
- {
- desc => 'user is problem owner',
- problem_user => $user,
- update_user => $user,
- update_fixed => 0,
- update_reopen => 0,
- update_state => undef,
- user_body => undef,
- content => 'user is problem owner',
- },
- {
- desc => 'user is body user',
- problem_user => $user,
- update_user => $user2,
- update_fixed => 0,
- update_reopen => 0,
- update_state => undef,
- user_body => $westminster->id,
- content => 'user is from same council as problem - ' . $westminster->id,
- },
- {
- desc => 'update changed problem state',
- problem_user => $user,
- update_user => $user2,
- update_fixed => 0,
- update_reopen => 0,
- update_state => 'planned',
- user_body => $westminster->id,
- content => 'Update changed problem state to planned',
- },
- {
- desc => 'update marked problem as fixed',
- problem_user => $user,
- update_user => $user3,
- update_fixed => 1,
- update_reopen => 0,
- update_state => undef,
- user_body => undef,
- content => 'Update marked problem as fixed',
- },
- {
- desc => 'update reopened problem',
- problem_user => $user,
- update_user => $user,
- update_fixed => 0,
- update_reopen => 1,
- update_state => undef,
- user_body => undef,
- content => 'Update reopened problem',
- },
-) {
- subtest $test->{desc} => sub {
- $report->user( $test->{problem_user} );
- $report->update;
-
- $update->user( $test->{update_user} );
- $update->problem_state( $test->{update_state} );
- $update->mark_fixed( $test->{update_fixed} );
- $update->mark_open( $test->{update_reopen} );
- $update->update;
-
- $test->{update_user}->from_body( $test->{user_body} );
- $test->{update_user}->update;
-
- $mech->get_ok('/admin/update_edit/' . $update->id );
- $mech->content_contains( $test->{content} );
- };
-}
-
-subtest 'editing update email creates new user if required' => sub {
- my $user = FixMyStreet::App->model('DB::User')->find( { email => 'test4@example.com' } );
-
- $user->delete if $user;
-
- my $fields = {
- text => 'this is a changed update',
- state => 'hidden',
- name => 'A User',
- anonymous => 0,
- username => 'test4@example.com',
- };
-
- $mech->submit_form_ok( { with_fields => $fields } );
-
- $user = FixMyStreet::App->model('DB::User')->find( { email => 'test4@example.com' } );
-
- is_deeply $mech->visible_form_values, $fields, 'submitted form values';
-
- ok $user, 'new user created';
-
- $update->discard_changes;
- is $update->user->id, $user->id, 'update set to new user';
-};
-
-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 } );
- $abuse->delete if $abuse;
-
- $mech->get_ok( '/admin/update_edit/' . $update->id );
- $mech->content_contains('Ban user');
-
- $mech->click_ok('banuser');
-
- $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 } );
- ok $abuse, 'entry created in abuse table';
-
- $mech->get_ok( '/admin/update_edit/' . $update->id );
- $mech->content_contains('<small>User in abuse table</small>');
-};
-
-subtest 'flagging user from update page' => sub {
- $update->user->flagged(0);
- $update->user->update;
-
- $mech->get_ok( '/admin/update_edit/' . $update->id );
- $mech->content_contains('Flag user');
-
- $mech->click_ok('flaguser');
-
- $mech->content_contains('User flagged');
- $mech->content_contains('Remove flag');
-
- $update->discard_changes;
- ok $update->user->flagged, 'user flagged';
-
- $mech->get_ok( '/admin/update_edit/' . $update->id );
- $mech->content_contains('Remove flag');
-};
-
-subtest 'unflagging user from update page' => sub {
- $update->user->flagged(1);
- $update->user->update;
-
- $mech->get_ok( '/admin/update_edit/' . $update->id );
- $mech->content_contains('Remove flag');
-
- $mech->click_ok('removeuserflag');
-
- $mech->content_contains('User flag removed');
- $mech->content_contains('Flag user');
-
- $update->discard_changes;
- ok !$update->user->flagged, 'user not flagged';
-
- $mech->get_ok( '/admin/update_edit/' . $update->id );
- $mech->content_contains('Flag user');
-};
-
-subtest 'hiding comment marked as fixed reopens report' => sub {
- $update->mark_fixed( 1 );
- $update->update;
-
- $report->state('fixed - user');
- $report->update;
-
- my $fields = {
- text => 'this is a changed update',
- state => 'hidden',
- name => 'A User',
- anonymous => 0,
- username => 'test2@example.com',
- };
-
- $mech->submit_form_ok( { with_fields => $fields } );
-
- $report->discard_changes;
- is $report->state, 'confirmed', 'report reopened';
- $mech->content_contains('Problem marked as open');
-};
-
-$log_entries->delete;
-
-subtest 'report search' => sub {
- $update->state('confirmed');
- $update->user($report->user);
- $update->update;
-
- $mech->get_ok('/admin/reports');
- $mech->get_ok('/admin/reports?search=' . $report->id );
-
- $mech->content_contains( $report->title );
- my $r_id = $report->id;
- $mech->content_like( qr{href="http://[^/]*[^.]/report/$r_id"[^>]*>$r_id</a>} );
-
- $mech->get_ok('/admin/reports?search=' . $report->external_id);
- $mech->content_like( qr{href="http://[^/]*[^.]/report/$r_id"[^>]*>$r_id</a>} );
-
- $mech->get_ok('/admin/reports?search=ref:' . $report->external_id);
- $mech->content_like( qr{href="http://[^/]*[^.]/report/$r_id"[^>]*>$r_id</a>} );
-
- $mech->get_ok('/admin/reports?search=' . $report->user->email);
-
- my $u_id = $update->id;
- $mech->content_like( qr{href="http://[^/]*[^.]/report/$r_id"[^>]*>$r_id</a>} );
- $mech->content_like( qr{href="http://[^/]*[^.]/report/$r_id#update_$u_id"[^>]*>$u_id</a>} );
-
- $update->state('hidden');
- $update->update;
-
- $mech->get_ok('/admin/reports?search=' . $report->user->email);
- $mech->content_like( qr{<tr [^>]*hidden[^>]*> \s* <td> \s* $u_id \s* </td>}xs );
-
- $report->state('hidden');
- $report->update;
-
- $mech->get_ok('/admin/reports?search=' . $report->user->email);
- $mech->content_like( qr{<tr [^>]*hidden[^>]*> \s* <td[^>]*> \s* $r_id \s* </td>}xs );
-
- $report->state('fixed - user');
- $report->update;
-
- $mech->get_ok('/admin/reports?search=' . $report->user->email);
- $mech->content_like( qr{href="http://[^/]*[^.]/report/$r_id"[^>]*>$r_id</a>} );
-};
-
-subtest 'search abuse' => sub {
- $mech->get_ok( '/admin/users?search=example' );
- $mech->content_like(qr{test4\@example.com.*</td>\s*<td>.*?</td>\s*<td>User in abuse table}s);
-};
-
-subtest 'show flagged entries' => sub {
- $report->flagged( 1 );
- $report->update;
-
- $user->flagged( 1 );
- $user->update;
-
- $mech->get_ok('/admin/flagged');
- $mech->content_contains( $report->title );
- $mech->content_contains( $user->email );
-};
-
-my $haringey = $mech->create_body_ok(2509, 'Haringey Borough Council');
-
-subtest 'user search' => sub {
- $mech->get_ok('/admin/users');
- $mech->get_ok('/admin/users?search=' . $user->name);
-
- $mech->content_contains( $user->name);
- my $u_id = $user->id;
- $mech->content_like( qr{user_edit/$u_id">Edit</a>} );
-
- $mech->get_ok('/admin/users?search=' . $user->email);
-
- $mech->content_like( qr{user_edit/$u_id">Edit</a>} );
-
- $user->from_body($haringey->id);
- $user->update;
- $mech->get_ok('/admin/users?search=' . $haringey->id );
- $mech->content_contains('Haringey');
-};
-
-subtest 'search does not show user from another council' => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'oxfordshire' ],
- }, sub {
- $mech->get_ok('/admin/users');
- $mech->get_ok('/admin/users?search=' . $user->name);
-
- $mech->content_contains( "Searching found no users." );
-
- $mech->get_ok('/admin/users?search=' . $user->email);
- $mech->content_contains( "Searching found no users." );
- };
-};
-
-subtest 'user_edit does not show user from another council' => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'oxfordshire' ],
- }, sub {
- $mech->get('/admin/user_edit/' . $user->id);
- ok !$mech->res->is_success(), "want a bad response";
- is $mech->res->code, 404, "got 404";
- };
-};
-
-$log_entries = FixMyStreet::App->model('DB::AdminLog')->search(
- {
- object_type => 'user',
- object_id => $user->id
- },
- {
- order_by => { -desc => 'id' },
- }
-);
-
-is $log_entries->count, 0, 'no admin log entries';
-
-$user->flagged( 0 );
-$user->update;
-
-my $southend = $mech->create_body_ok(2607, 'Southend-on-Sea Borough Council');
-
-for my $test (
- {
- desc => 'add user - blank form',
- fields => {
- email => '', email_verified => 0,
- phone => '', phone_verified => 0,
- },
- error => ['Please verify at least one of email/phone', 'Please enter a name'],
- },
- {
- desc => 'add user - blank, verify phone',
- fields => {
- email => '', email_verified => 0,
- phone => '', phone_verified => 1,
- },
- error => ['Please enter a valid email or phone number', 'Please enter a name'],
- },
- {
- desc => 'add user - bad email',
- fields => {
- name => 'Norman',
- email => 'bademail', email_verified => 0,
- phone => '', phone_verified => 0,
- },
- error => ['Please enter a valid email'],
- },
- {
- desc => 'add user - bad phone',
- fields => {
- name => 'Norman',
- phone => '01214960000000', phone_verified => 1,
- },
- error => ['Please check your phone number is correct'],
- },
- {
- desc => 'add user - landline',
- fields => {
- name => 'Norman Name',
- phone => '+441214960000',
- phone_verified => 1,
- },
- error => ['Please enter a mobile number'],
- },
- {
- desc => 'add user - good details',
- fields => {
- name => 'Norman Name',
- phone => '+61491570156',
- phone_verified => 1,
- },
- },
-) {
- subtest $test->{desc} => sub {
- $mech->get_ok('/admin/users');
- $mech->submit_form_ok( { with_fields => $test->{fields} } );
- if ($test->{error}) {
- $mech->content_contains($_) for @{$test->{error}};
- } else {
- $mech->content_contains('Updated');
- }
- };
-}
-
-my %default_perms = (
- "permissions[moderate]" => undef,
- "permissions[planned_reports]" => undef,
- "permissions[report_edit]" => undef,
- "permissions[report_edit_category]" => undef,
- "permissions[report_edit_priority]" => undef,
- "permissions[report_inspect]" => undef,
- "permissions[report_instruct]" => undef,
- "permissions[contribute_as_another_user]" => undef,
- "permissions[contribute_as_anonymous_user]" => undef,
- "permissions[contribute_as_body]" => undef,
- "permissions[view_body_contribute_details]" => undef,
- "permissions[user_edit]" => undef,
- "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
-# Regression test for mysociety/fixmystreetforcouncils#250
-$user->update({ name => '' });
-
-FixMyStreet::override_config {
- MAPIT_URL => 'http://mapit.uk/',
-}, sub {
- for my $test (
- {
- desc => 'edit user name',
- fields => {
- name => '',
- email => 'test@example.com',
- body => $haringey->id,
- phone => '',
- flagged => undef,
- is_superuser => undef,
- area_id => '',
- %default_perms,
- },
- changes => {
- name => 'Changed User',
- },
- log_count => 1,
- log_entries => [qw/edit/],
- },
- {
- desc => 'edit user email',
- fields => {
- name => 'Changed User',
- email => 'test@example.com',
- body => $haringey->id,
- phone => '',
- flagged => undef,
- is_superuser => undef,
- area_id => '',
- %default_perms,
- },
- changes => {
- email => 'changed@example.com',
- },
- log_count => 2,
- log_entries => [qw/edit edit/],
- },
- {
- desc => 'edit user body',
- fields => {
- name => 'Changed User',
- email => 'changed@example.com',
- body => $haringey->id,
- phone => '',
- flagged => undef,
- is_superuser => undef,
- area_id => '',
- %default_perms,
- },
- changes => {
- body => $southend->id,
- },
- log_count => 3,
- log_entries => [qw/edit edit edit/],
- },
- {
- desc => 'edit user flagged',
- fields => {
- name => 'Changed User',
- email => 'changed@example.com',
- body => $southend->id,
- phone => '',
- flagged => undef,
- is_superuser => undef,
- area_id => '',
- %default_perms,
- },
- changes => {
- flagged => 'on',
- },
- log_count => 4,
- log_entries => [qw/edit edit edit edit/],
- },
- {
- desc => 'edit user remove flagged',
- fields => {
- name => 'Changed User',
- email => 'changed@example.com',
- body => $southend->id,
- phone => '',
- flagged => 'on',
- is_superuser => undef,
- area_id => '',
- %default_perms,
- },
- changes => {
- flagged => undef,
- },
- log_count => 4,
- log_entries => [qw/edit edit edit edit/],
- },
- {
- desc => 'edit user add is_superuser',
- fields => {
- name => 'Changed User',
- email => 'changed@example.com',
- body => $southend->id,
- phone => '',
- flagged => undef,
- is_superuser => undef,
- area_id => '',
- %default_perms,
- },
- changes => {
- is_superuser => 'on',
- },
- removed => [
- keys %default_perms,
- ],
- log_count => 5,
- log_entries => [qw/edit edit edit edit edit/],
- },
- {
- desc => 'edit user remove is_superuser',
- fields => {
- name => 'Changed User',
- email => 'changed@example.com',
- body => $southend->id,
- phone => '',
- flagged => undef,
- is_superuser => 'on',
- area_id => '',
- },
- changes => {
- is_superuser => undef,
- },
- added => {
- %default_perms,
- },
- log_count => 5,
- log_entries => [qw/edit edit edit edit edit/],
- },
- ) {
- subtest $test->{desc} => sub {
- $mech->get_ok( '/admin/user_edit/' . $user->id );
-
- my $visible = $mech->visible_form_values;
- is_deeply $visible, $test->{fields}, 'expected user';
-
- my $expected = {
- %{ $test->{fields} },
- %{ $test->{changes} }
- };
-
- $mech->submit_form_ok( { with_fields => $expected } );
-
- # Some actions cause visible fields to be added/removed
- foreach my $x (@{ $test->{removed} }) {
- delete $expected->{$x};
- }
- if ( $test->{added} ) {
- $expected = {
- %$expected,
- %{ $test->{added} }
- };
- }
-
- $visible = $mech->visible_form_values;
- is_deeply $visible, $expected, 'user updated';
-
- $mech->content_contains( 'Updated!' );
- };
- }
-};
-
-FixMyStreet::override_config {
- MAPIT_URL => 'http://mapit.uk/',
- SMS_AUTHENTICATION => 1,
-}, sub {
- subtest "Test edit user add verified phone" => sub {
- $mech->get_ok( '/admin/user_edit/' . $user->id );
- $mech->submit_form_ok( { with_fields => {
- phone => '+61491570157',
- phone_verified => 1,
- } } );
- $mech->content_contains( 'Updated!' );
- };
-
- subtest "Test changing user to an existing one" => sub {
- my $existing_user = $mech->create_user_ok('existing@example.com', name => 'Existing User');
- $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/user_edit/' . $user->id );
- $mech->submit_form_ok( { with_fields => { email => 'existing@example.com' } }, 'submit email change' );
- is $mech->uri->path, '/admin/user_edit/' . $existing_user->id, 'redirected';
- my $p = FixMyStreet::DB->resultset('Problem')->search({ user_id => $existing_user->id })->count;
- is $p, $count + 2, 'reports merged';
- };
-
-};
-
-subtest "Test setting a report from unconfirmed to something else doesn't cause a front end error" => sub {
- $report->update( { confirmed => undef, state => 'unconfirmed', non_public => 0 } );
- $mech->get_ok("/admin/report_edit/$report_id");
- $mech->submit_form_ok( { with_fields => { state => 'investigating' } } );
- $report->discard_changes;
- ok( $report->confirmed, 'report has a confirmed timestamp' );
- $mech->get_ok("/report/$report_id");
-};
-
subtest "Check admin_base_url" => sub {
my $rs = FixMyStreet::App->model('DB::Problem');
my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker($report->cobrand)->new();
@@ -1578,10 +140,6 @@ subtest "Check admin_base_url" => sub {
$mech->log_out_ok;
subtest "Users without from_body can't access admin" => sub {
- $user = FixMyStreet::App->model('DB::User')->find( { email => 'existing@example.com' } );
- $user->from_body( undef );
- $user->update;
-
$mech->log_in_ok( $user->email );
ok $mech->get('/admin');
@@ -1629,229 +187,4 @@ subtest "Users with from_body can't access fixmystreet.com admin" => sub {
};
};
-subtest "response templates can be added" => sub {
- is $oxfordshire->response_templates->count, 0, "No response templates yet";
- $mech->log_in_ok( $superuser->email );
- $mech->get_ok( "/admin/templates/" . $oxfordshire->id . "/new" );
-
- my $fields = {
- title => "Report acknowledgement",
- text => "Thank you for your report. We will respond shortly.",
- auto_response => undef,
- "contacts[".$oxfordshirecontact->id."]" => 1,
- };
- $mech->submit_form_ok( { with_fields => $fields } );
-
- is $oxfordshire->response_templates->count, 1, "Response template was added";
-};
-
-subtest "response templates are included on page" => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'oxfordshire' ],
- }, sub {
- $report->update({ category => $oxfordshirecontact->category, bodies_str => $oxfordshire->id });
- $mech->log_in_ok( $oxfordshireuser->email );
-
- $mech->get_ok("/report/" . $report->id);
- $mech->content_contains( $oxfordshire->response_templates->first->text );
-
- $mech->log_out_ok;
- };
-};
-
-subtest "auto-response templates that duplicate a single category can't be added" => sub {
- $mech->delete_response_template($_) for $oxfordshire->response_templates;
- my $template = $oxfordshire->response_templates->create({
- title => "Report fixed - potholes",
- text => "Thank you for your report. This problem has been fixed.",
- auto_response => 1,
- state => 'fixed - council',
- });
- $template->contact_response_templates->find_or_create({
- contact_id => $oxfordshirecontact->id,
- });
- is $oxfordshire->response_templates->count, 1, "Initial response template was created";
-
-
- $mech->log_in_ok( $superuser->email );
- $mech->get_ok( "/admin/templates/" . $oxfordshire->id . "/new" );
-
- # This response template has the same category & state as an existing one
- # so won't be allowed.
- my $fields = {
- title => "Report marked fixed - potholes",
- text => "Thank you for your report. This pothole has been fixed.",
- auto_response => 'on',
- state => 'fixed - council',
- "contacts[".$oxfordshirecontact->id."]" => 1,
- };
- $mech->submit_form_ok( { with_fields => $fields } );
- is $mech->uri->path, '/admin/templates/' . $oxfordshire->id . '/new', 'not redirected';
- $mech->content_contains( 'Please correct the errors below' );
- $mech->content_contains( 'There is already an auto-response template for this category/state.' );
-
- is $oxfordshire->response_templates->count, 1, "Duplicate response template wasn't added";
-};
-
-subtest "auto-response templates that duplicate all categories can't be added" => sub {
- $mech->delete_response_template($_) for $oxfordshire->response_templates;
- $oxfordshire->response_templates->create({
- title => "Report investigating - all cats",
- text => "Thank you for your report. This problem has been fixed.",
- auto_response => 1,
- state => 'fixed - council',
- });
- 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" );
-
- # There's already a response template for all categories and this state, so
- # this new template won't be allowed.
- my $fields = {
- title => "Report investigating - single cat",
- text => "Thank you for your report. This problem has been fixed.",
- auto_response => 'on',
- state => 'fixed - council',
- "contacts[".$oxfordshirecontact->id."]" => 1,
- };
- $mech->submit_form_ok( { with_fields => $fields } );
- is $mech->uri->path, '/admin/templates/' . $oxfordshire->id . '/new', 'not redirected';
- $mech->content_contains( 'Please correct the errors below' );
- $mech->content_contains( 'There is already an auto-response template for this category/state.' );
-
-
- is $oxfordshire->response_templates->count, 1, "Duplicate response template wasn't added";
-};
-
-subtest "all-category auto-response templates that duplicate a single category can't be added" => sub {
- $mech->delete_response_template($_) for $oxfordshire->response_templates;
- my $template = $oxfordshire->response_templates->create({
- title => "Report fixed - potholes",
- text => "Thank you for your report. This problem has been fixed.",
- auto_response => 1,
- state => 'fixed - council',
- });
- $template->contact_response_templates->find_or_create({
- contact_id => $oxfordshirecontact->id,
- });
- is $oxfordshire->response_templates->count, 1, "Initial response template was created";
-
-
- $mech->log_in_ok( $superuser->email );
- $mech->get_ok( "/admin/templates/" . $oxfordshire->id . "/new" );
-
- # This response template is implicitly for all categories, but there's
- # already a template for a specific category in this state, so it won't be
- # allowed.
- my $fields = {
- title => "Report marked fixed - all cats",
- text => "Thank you for your report. This problem has been fixed.",
- auto_response => 'on',
- state => 'fixed - council',
- };
- $mech->submit_form_ok( { with_fields => $fields } );
- is $mech->uri->path, '/admin/templates/' . $oxfordshire->id . '/new', 'not redirected';
- $mech->content_contains( 'Please correct the errors below' );
- $mech->content_contains( 'There is already an auto-response template for this category/state.' );
-
- is $oxfordshire->response_templates->count, 1, "Duplicate response template wasn't added";
-};
-
-
-
-$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" );
-
- my $fields = {
- name => "Cat 1A",
- description => "Fixed within 24 hours",
- deleted => undef,
- is_default => undef,
- "contacts[".$oxfordshirecontact->id."]" => 1,
- };
- $mech->submit_form_ok( { with_fields => $fields } );
-
- is $oxfordshire->response_priorities->count, 1, "Response priority was added to body";
- is $oxfordshirecontact->response_priorities->count, 1, "Response priority was added to contact";
-};
-
-subtest "response priorities can set to default" => sub {
- my $priority_id = $oxfordshire->response_priorities->first->id;
- is $oxfordshire->response_priorities->count, 1, "Response priority exists";
- $mech->get_ok( "/admin/responsepriorities/" . $oxfordshire->id . "/$priority_id" );
-
- my $fields = {
- name => "Cat 1A",
- description => "Fixed within 24 hours",
- deleted => undef,
- is_default => 1,
- "contacts[".$oxfordshirecontact->id."]" => 1,
- };
- $mech->submit_form_ok( { with_fields => $fields } );
-
- is $oxfordshire->response_priorities->count, 1, "Still one response priority";
- is $oxfordshirecontact->response_priorities->count, 1, "Still one response priority";
- ok $oxfordshire->response_priorities->first->is_default, "Response priority set to default";
-};
-
-subtest "response priorities can be listed" => sub {
- $mech->get_ok( "/admin/responsepriorities/" . $oxfordshire->id );
-
- $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 {
- $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->content_contains( $oxfordshire->response_priorities->first->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 );
- ok !$mech->res->is_success(), "want a bad response";
- is $mech->res->code, 404, "got 404";
- };
-};
-
-subtest "smoke view some stats pages" => sub {
- $mech->log_in_ok( $superuser->email );
- $mech->get_ok('/admin/stats/fix-rate');
- $mech->get_ok('/admin/stats/questionnaire');
-};
-
done_testing();
diff --git a/t/app/controller/admin/bodies.t b/t/app/controller/admin/bodies.t
new file mode 100644
index 000000000..9bdf8fb9a
--- /dev/null
+++ b/t/app/controller/admin/bodies.t
@@ -0,0 +1,165 @@
+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 );
+
+# This override is wrapped around ALL the /admin/body tests
+FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ MAPIT_TYPES => [ 'UTA' ],
+ BASE_URL => 'http://www.example.org',
+}, sub {
+
+my $body = $mech->create_body_ok(2650, 'Aberdeen City Council');
+$mech->get_ok('/admin/body/' . $body->id);
+$mech->content_contains('Aberdeen City Council');
+$mech->content_like(qr{AB\d\d});
+$mech->content_contains("http://www.example.org/around");
+
+subtest 'check contact creation' => sub {
+ $mech->get_ok('/admin/body/' . $body->id);
+
+ $mech->submit_form_ok( { with_fields => {
+ category => 'test category',
+ email => 'test@example.com',
+ note => 'test note',
+ non_public => undef,
+ state => 'unconfirmed',
+ } } );
+
+ $mech->content_contains( 'test category' );
+ $mech->content_contains( 'test@example.com' );
+ $mech->content_contains( '<td>test note' );
+ $mech->content_like( qr/<td>\s*unconfirmed\s*<\/td>/ ); # No private
+
+ $mech->submit_form_ok( { with_fields => {
+ category => 'private category',
+ email => 'test@example.com',
+ note => 'test note',
+ non_public => 'on',
+ } } );
+
+ $mech->content_contains( 'private category' );
+ $mech->content_like( qr{test\@example.com\s*</td>\s*<td>\s*confirmed\s*<br>\s*<small>\s*Private\s*</small>\s*</td>} );
+
+ $mech->submit_form_ok( { with_fields => {
+ category => 'test/category',
+ email => 'test@example.com',
+ note => 'test/note',
+ non_public => 'on',
+ } } );
+ $mech->get_ok('/admin/body/' . $body->id . '/test/category');
+ $mech->content_contains('<h1>test/category</h1>');
+};
+
+subtest 'check contact editing' => sub {
+ $mech->get_ok('/admin/body/' . $body->id .'/test%20category');
+
+ $mech->submit_form_ok( { with_fields => {
+ email => 'test2@example.com',
+ note => 'test2 note',
+ non_public => undef,
+ } } );
+
+ $mech->content_contains( 'test category' );
+ $mech->content_like( qr{test2\@example.com\s*</td>\s*<td>\s*unconfirmed\s*</td>} );
+ $mech->content_contains( '<td>test2 note' );
+
+ $mech->get_ok('/admin/body/' . $body->id . '/test%20category');
+ $mech->submit_form_ok( { with_fields => {
+ email => 'test2@example.com, test3@example.com',
+ note => 'test3 note',
+ } } );
+
+ $mech->content_contains( 'test2@example.com,test3@example.com' );
+
+ $mech->get_ok('/admin/body/' . $body->id . '/test%20category');
+ $mech->content_contains( '<td><strong>test2@example.com,test3@example.com' );
+
+ $mech->submit_form_ok( { with_fields => {
+ email => 'test2@example.com',
+ note => 'test2 note',
+ non_public => 'on',
+ } } );
+
+ $mech->content_like( qr{test2\@example.com\s*</td>\s*<td>\s*unconfirmed\s*<br>\s*<small>\s*Private\s*</small>\s*</td>} );
+
+ $mech->get_ok('/admin/body/' . $body->id . '/test%20category');
+ $mech->content_contains( '<td><strong>test2@example.com' );
+};
+
+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);
+
+ $mech->get_ok('/admin/body/' . $body->id);
+
+ $mech->form_number( 1 );
+ $mech->tick( 'confirmed', 'test category' );
+ $mech->submit_form_ok({form_number => 1});
+
+ $mech->content_like(qr'test2@example.com</td>[^<]*<td>\s*confirmed's);
+ $mech->get_ok('/admin/body/' . $body->id . '/test%20category');
+ $mech->content_like(qr{test2\@example.com[^<]*</td>[^<]*<td><strong>confirmed}s);
+};
+
+$body->update({ send_method => undef });
+
+subtest 'check open311 configuring' => sub {
+ $mech->get_ok('/admin/body/' . $body->id);
+ $mech->content_lacks('Council contacts configured via Open311');
+
+ $mech->form_number(3);
+ $mech->submit_form_ok(
+ {
+ with_fields => {
+ api_key => 'api key',
+ endpoint => 'http://example.com/open311',
+ jurisdiction => 'mySociety',
+ send_comments => 0,
+ send_method => 'Open311',
+ }
+ }
+ );
+ $mech->content_contains('Council contacts configured via Open311');
+ $mech->content_contains('Values updated');
+
+ my $conf = FixMyStreet::App->model('DB::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';
+
+ $mech->form_number(3);
+ $mech->submit_form_ok(
+ {
+ with_fields => {
+ api_key => 'new api key',
+ endpoint => 'http://example.org/open311',
+ jurisdiction => 'open311',
+ send_comments => 0,
+ send_method => 'Open311',
+ }
+ }
+ );
+
+ $mech->content_contains('Values updated');
+
+ $conf = FixMyStreet::App->model('DB::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';
+};
+
+subtest 'check text output' => sub {
+ $mech->get_ok('/admin/body/' . $body->id . '?text=1');
+ is $mech->content_type, 'text/plain';
+ $mech->content_contains('test category');
+ $mech->content_lacks('<body');
+};
+
+
+}; # END of override wrap
+
+done_testing();
diff --git a/t/app/controller/admin_defecttypes.t b/t/app/controller/admin/defecttypes.t
index e7d0e42af..e7d0e42af 100644
--- a/t/app/controller/admin_defecttypes.t
+++ b/t/app/controller/admin/defecttypes.t
diff --git a/t/app/controller/admin_permissions.t b/t/app/controller/admin/permissions.t
index 7944cc0b1..7944cc0b1 100644
--- a/t/app/controller/admin_permissions.t
+++ b/t/app/controller/admin/permissions.t
diff --git a/t/app/controller/admin/priorities.t b/t/app/controller/admin/priorities.t
new file mode 100644
index 000000000..4eff20be7
--- /dev/null
+++ b/t/app/controller/admin/priorities.t
@@ -0,0 +1,102 @@
+use FixMyStreet::TestMech;
+
+my $mech = FixMyStreet::TestMech->new;
+
+my $user = $mech->create_user_ok('test@example.com', name => 'Test User');
+
+my $superuser = $mech->create_user_ok('superuser@example.com', name => 'Super User', is_superuser => 1);
+
+my $oxfordshire = $mech->create_body_ok(2237, 'Oxfordshire County Council');
+my $oxfordshirecontact = $mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Potholes', email => 'potholes@example.com' );
+my $oxfordshireuser = $mech->create_user_ok('counciluser@example.com', name => 'Council User', from_body => $oxfordshire);
+
+my $bromley = $mech->create_body_ok(2482, 'Bromley Council');
+
+$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" );
+
+ my $fields = {
+ name => "Cat 1A",
+ description => "Fixed within 24 hours",
+ deleted => undef,
+ is_default => undef,
+ "contacts[".$oxfordshirecontact->id."]" => 1,
+ };
+ $mech->submit_form_ok( { with_fields => $fields } );
+
+ is $oxfordshire->response_priorities->count, 1, "Response priority was added to body";
+ is $oxfordshirecontact->response_priorities->count, 1, "Response priority was added to contact";
+};
+
+subtest "response priorities can set to default" => sub {
+ my $priority_id = $oxfordshire->response_priorities->first->id;
+ is $oxfordshire->response_priorities->count, 1, "Response priority exists";
+ $mech->get_ok( "/admin/responsepriorities/" . $oxfordshire->id . "/$priority_id" );
+
+ my $fields = {
+ name => "Cat 1A",
+ description => "Fixed within 24 hours",
+ deleted => undef,
+ is_default => 1,
+ "contacts[".$oxfordshirecontact->id."]" => 1,
+ };
+ $mech->submit_form_ok( { with_fields => $fields } );
+
+ is $oxfordshire->response_priorities->count, 1, "Still one response priority";
+ is $oxfordshirecontact->response_priorities->count, 1, "Still one response priority";
+ ok $oxfordshire->response_priorities->first->is_default, "Response priority set to default";
+};
+
+subtest "response priorities can be listed" => sub {
+ $mech->get_ok( "/admin/responsepriorities/" . $oxfordshire->id );
+
+ $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 {
+ $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->content_contains( $oxfordshire->response_priorities->first->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 );
+ ok !$mech->res->is_success(), "want a bad response";
+ is $mech->res->code, 404, "got 404";
+ };
+};
+
+done_testing();
diff --git a/t/app/controller/admin/report_edit.t b/t/app/controller/admin/report_edit.t
new file mode 100644
index 000000000..a8a0bd143
--- /dev/null
+++ b/t/app/controller/admin/report_edit.t
@@ -0,0 +1,556 @@
+use FixMyStreet::TestMech;
+# avoid wide character warnings from the category change message
+use open ':std', ':encoding(UTF-8)';
+
+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 $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' );
+$mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Traffic lights', email => 'lights@example.com' );
+
+my $oxford = $mech->create_body_ok(2421, 'Oxford City Council');
+$mech->create_contact_ok( body_id => $oxford->id, category => 'Graffiti', email => 'graffiti@example.net' );
+
+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(
+ {
+ postcode => 'SW1A 1AA',
+ bodies_str => '2504',
+ areas => ',105255,11806,11828,2247,2504,',
+ category => 'Other',
+ title => 'Report to Edit',
+ detail => 'Detail for Report to Edit',
+ used_map => 't',
+ name => 'Test User',
+ anonymous => 'f',
+ external_id => '13',
+ state => 'confirmed',
+ confirmed => $dt->ymd . ' ' . $dt->hms,
+ lang => 'en-gb',
+ service => '',
+ cobrand => '',
+ cobrand_data => '',
+ send_questionnaire => 't',
+ latitude => '51.5016605453401',
+ longitude => '-0.142497580865087',
+ user_id => $user->id,
+ whensent => $dt->ymd . ' ' . $dt->hms,
+ }
+);
+
+$mech->log_in_ok( $superuser->email );
+
+my $log_entries = FixMyStreet::App->model('DB::AdminLog')->search(
+ {
+ object_type => 'problem',
+ object_id => $report->id
+ },
+ {
+ order_by => { -desc => 'id' },
+ }
+);
+
+is $log_entries->count, 0, 'no admin log entries';
+
+my $report_id = $report->id;
+ok $report, "created test report - $report_id";
+
+foreach my $test (
+ {
+ description => 'edit report title',
+ fields => {
+ title => 'Report to Edit',
+ detail => 'Detail for Report to Edit',
+ state => 'confirmed',
+ name => 'Test User',
+ username => $user->email,
+ anonymous => 0,
+ flagged => undef,
+ non_public => undef,
+ },
+ changes => { title => 'Edited Report', },
+ log_entries => [qw/edit/],
+ resend => 0,
+ },
+ {
+ description => 'edit report description',
+ fields => {
+ title => 'Edited Report',
+ detail => 'Detail for Report to Edit',
+ state => 'confirmed',
+ name => 'Test User',
+ username => $user->email,
+ anonymous => 0,
+ flagged => undef,
+ non_public => undef,
+ },
+ changes => { detail => 'Edited Detail', },
+ log_entries => [qw/edit edit/],
+ resend => 0,
+ },
+ {
+ description => 'edit report user name',
+ fields => {
+ title => 'Edited Report',
+ detail => 'Edited Detail',
+ state => 'confirmed',
+ name => 'Test User',
+ username => $user->email,
+ anonymous => 0,
+ flagged => undef,
+ non_public => undef,
+ },
+ changes => { name => 'Edited User', },
+ log_entries => [qw/edit edit edit/],
+ resend => 0,
+ user => $user,
+ },
+ {
+ description => 'edit report set flagged true',
+ fields => {
+ title => 'Edited Report',
+ detail => 'Edited Detail',
+ state => 'confirmed',
+ name => 'Edited User',
+ username => $user->email,
+ anonymous => 0,
+ flagged => undef,
+ non_public => undef,
+ },
+ changes => {
+ flagged => 'on',
+ },
+ log_entries => [qw/edit edit edit edit/],
+ resend => 0,
+ user => $user,
+ },
+ {
+ description => 'edit report user email',
+ fields => {
+ title => 'Edited Report',
+ detail => 'Edited Detail',
+ state => 'confirmed',
+ name => 'Edited User',
+ username => $user->email,
+ anonymous => 0,
+ flagged => 'on',
+ non_public => undef,
+ },
+ changes => { username => $user2->email, },
+ log_entries => [qw/edit edit edit edit edit/],
+ resend => 0,
+ user => $user2,
+ },
+ {
+ description => 'change state to unconfirmed',
+ fields => {
+ title => 'Edited Report',
+ detail => 'Edited Detail',
+ state => 'confirmed',
+ name => 'Edited User',
+ username => $user2->email,
+ anonymous => 0,
+ flagged => 'on',
+ non_public => undef,
+ },
+ expect_comment => 1,
+ changes => { state => 'unconfirmed' },
+ log_entries => [qw/edit state_change edit edit edit edit edit/],
+ resend => 0,
+ },
+ {
+ description => 'change state to confirmed',
+ fields => {
+ title => 'Edited Report',
+ detail => 'Edited Detail',
+ state => 'unconfirmed',
+ name => 'Edited User',
+ username => $user2->email,
+ anonymous => 0,
+ flagged => 'on',
+ non_public => undef,
+ },
+ expect_comment => 1,
+ changes => { state => 'confirmed' },
+ log_entries => [qw/edit state_change edit state_change edit edit edit edit edit/],
+ resend => 0,
+ },
+ {
+ description => 'change state to fixed',
+ fields => {
+ title => 'Edited Report',
+ detail => 'Edited Detail',
+ state => 'confirmed',
+ name => 'Edited User',
+ username => $user2->email,
+ anonymous => 0,
+ flagged => 'on',
+ non_public => undef,
+ },
+ expect_comment => 1,
+ changes => { state => 'fixed' },
+ log_entries =>
+ [qw/edit state_change edit state_change edit state_change edit edit edit edit edit/],
+ resend => 0,
+ },
+ {
+ description => 'change state to hidden',
+ fields => {
+ title => 'Edited Report',
+ detail => 'Edited Detail',
+ state => 'fixed',
+ name => 'Edited User',
+ username => $user2->email,
+ anonymous => 0,
+ flagged => 'on',
+ non_public => undef,
+ },
+ expect_comment => 1,
+ changes => { state => 'hidden' },
+ log_entries => [
+ qw/edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/
+ ],
+ resend => 0,
+ },
+ {
+ description => 'edit and change state',
+ fields => {
+ title => 'Edited Report',
+ detail => 'Edited Detail',
+ state => 'hidden',
+ name => 'Edited User',
+ username => $user2->email,
+ anonymous => 0,
+ flagged => 'on',
+ non_public => undef,
+ },
+ expect_comment => 1,
+ changes => {
+ state => 'confirmed',
+ anonymous => 1,
+ },
+ log_entries => [
+ qw/edit state_change edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/
+ ],
+ resend => 0,
+ },
+ {
+ description => 'resend',
+ fields => {
+ title => 'Edited Report',
+ detail => 'Edited Detail',
+ state => 'confirmed',
+ name => 'Edited User',
+ username => $user2->email,
+ anonymous => 1,
+ flagged => 'on',
+ non_public => undef,
+ },
+ changes => {},
+ log_entries => [
+ qw/resend edit state_change edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/
+ ],
+ resend => 1,
+ },
+ {
+ description => 'non public',
+ fields => {
+ title => 'Edited Report',
+ detail => 'Edited Detail',
+ state => 'confirmed',
+ name => 'Edited User',
+ username => $user2->email,
+ anonymous => 1,
+ flagged => 'on',
+ non_public => undef,
+ },
+ changes => {
+ non_public => 'on',
+ },
+ log_entries => [
+ qw/edit resend edit state_change edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/
+ ],
+ resend => 0,
+ },
+ {
+ description => 'change state to investigating as body superuser',
+ fields => {
+ title => 'Edited Report',
+ detail => 'Edited Detail',
+ state => 'confirmed',
+ name => 'Edited User',
+ username => $user2->email,
+ anonymous => 1,
+ flagged => 'on',
+ non_public => 'on',
+ },
+ expect_comment => 1,
+ user_body => $oxfordshire,
+ changes => { state => 'investigating' },
+ log_entries => [
+ qw/edit state_change edit resend edit state_change edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/
+ ],
+ resend => 0,
+ },
+ {
+ description => 'change state to in progess and change category as body superuser',
+ fields => {
+ title => 'Edited Report',
+ detail => 'Edited Detail',
+ state => 'investigating',
+ name => 'Edited User',
+ username => $user2->email,
+ anonymous => 1,
+ flagged => 'on',
+ non_public => 'on',
+ },
+ expect_comment => 1,
+ expected_text => '*Category changed from ‘Other’ to ‘Potholes’*',
+ user_body => $oxfordshire,
+ changes => { state => 'in progress', category => 'Potholes' },
+ log_entries => [
+ qw/edit state_change edit state_change edit resend edit state_change edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/
+ ],
+ resend => 0,
+ },
+ )
+{
+ subtest $test->{description} => sub {
+ $report->comments->delete;
+ $log_entries->reset;
+
+ if ( $test->{user_body} ) {
+ $superuser->from_body( $test->{user_body}->id );
+ $superuser->update;
+ }
+
+ $mech->get_ok("/admin/report_edit/$report_id");
+
+ @{$test->{fields}}{'external_id', 'external_body', 'external_team', 'category'} = (13, "", "", "Other");
+ is_deeply( $mech->visible_form_values(), $test->{fields}, 'initial form values' );
+
+ my $new_fields = {
+ %{ $test->{fields} },
+ %{ $test->{changes} },
+ };
+
+ if ( $test->{resend} ) {
+ $mech->click_ok( 'resend' );
+ } else {
+ $mech->submit_form_ok( { with_fields => $new_fields }, 'form_submitted' );
+ }
+
+ is_deeply( $mech->visible_form_values(), $new_fields, 'changed form values' );
+ is $log_entries->count, scalar @{$test->{log_entries}}, 'log entry count';
+ is $log_entries->next->action, $_, 'log entry added' for @{ $test->{log_entries} };
+
+ $report->discard_changes;
+
+ if ($report->state eq 'confirmed' && $report->whensent) {
+ $mech->content_contains( 'type="submit" name="resend"', 'resend button' );
+ } else {
+ $mech->content_lacks( 'type="submit" name="resend"', 'no resend button' );
+ }
+
+ $test->{changes}->{flagged} = 1 if $test->{changes}->{flagged};
+ $test->{changes}->{non_public} = 1 if $test->{changes}->{non_public};
+
+ is $report->$_, $test->{changes}->{$_}, "$_ updated" for grep { $_ ne 'username' } keys %{ $test->{changes} };
+
+ if ( $test->{user} ) {
+ is $report->user->id, $test->{user}->id, 'user changed';
+ }
+
+ if ( $test->{resend} ) {
+ $mech->content_contains( 'That problem will now be resent' );
+ is $report->whensent, undef, 'mark report to resend';
+ }
+
+ if ( $test->{expect_comment} ) {
+ my $comment = $report->comments->first;
+ ok $comment, 'report status change creates comment';
+ is $report->comments->count, 1, 'report only has one comment';
+ if ($test->{expected_text}) {
+ is $comment->text, $test->{expected_text}, 'comment has expected text';
+ } else {
+ is $comment->text, '', 'comment has no text';
+ }
+ if ( $test->{user_body} ) {
+ ok $comment->get_extra_metadata('is_body_user'), 'body user metadata set';
+ ok !$comment->get_extra_metadata('is_superuser'), 'superuser metadata not set';
+ is $comment->name, $test->{user_body}->name, 'comment name is body name';
+ } else {
+ ok !$comment->get_extra_metadata('is_body_user'), 'body user metadata not set';
+ ok $comment->get_extra_metadata('is_superuser'), 'superuser metadata set';
+ is $comment->name, _('an administrator'), 'comment name is admin';
+ }
+ } else {
+ is $report->comments->count, 0, 'report has no comments';
+ }
+
+ $superuser->from_body(undef);
+ $superuser->update;
+ };
+}
+
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'fixmystreet',
+}, sub {
+
+subtest 'change report category' => sub {
+ my ($ox_report) = $mech->create_problems_for_body(1, $oxfordshire->id, 'Unsure', {
+ category => 'Potholes',
+ areas => ',2237,2421,', # Cached used by categories_for_point...
+ latitude => 51.7549262252,
+ longitude => -1.25617899435,
+ whensent => \'current_timestamp',
+ });
+ $mech->get_ok("/admin/report_edit/" . $ox_report->id);
+
+ $mech->submit_form_ok( { with_fields => { category => 'Traffic lights' } }, 'form_submitted' );
+ $ox_report->discard_changes;
+ is $ox_report->category, 'Traffic lights';
+ isnt $ox_report->whensent, undef;
+ is $ox_report->comments->count, 1, "Comment created for update";
+ is $ox_report->comments->first->text, '*Category changed from ‘Potholes’ to ‘Traffic lights’*', 'Comment text correct';
+
+ $mech->submit_form_ok( { with_fields => { category => 'Graffiti' } }, 'form_submitted' );
+ $ox_report->discard_changes;
+ is $ox_report->category, 'Graffiti';
+ is $ox_report->whensent, undef;
+};
+
+};
+
+subtest 'change email to new user' => sub {
+ $log_entries->delete;
+ $mech->get_ok("/admin/report_edit/$report_id");
+ my $fields = {
+ title => $report->title,
+ detail => $report->detail,
+ state => $report->state,
+ name => $report->name,
+ username => $report->user->email,
+ category => 'Potholes',
+ anonymous => 1,
+ flagged => 'on',
+ non_public => 'on',
+ external_id => '13',
+ external_body => '',
+ external_team => '',
+ };
+
+ is_deeply( $mech->visible_form_values(), $fields, 'initial form values' );
+
+ my $changes = {
+ username => 'test3@example.com'
+ };
+
+ my $user3 = FixMyStreet::App->model('DB::User')->find( { email => 'test3@example.com' } );
+
+ ok !$user3, 'user not in database';
+
+ my $new_fields = {
+ %{ $fields },
+ %{ $changes },
+ };
+
+ $mech->submit_form_ok(
+ {
+ with_fields => $new_fields,
+ }
+ );
+
+ is $log_entries->count, 1, 'created admin log entries';
+ 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' } );
+
+ $report->discard_changes;
+
+ ok $user3, 'new user created';
+ is $report->user_id, $user3->id, 'user changed to new user';
+};
+
+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 } );
+ $abuse->delete if $abuse;
+
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->content_contains('Ban user');
+
+ $mech->click_ok('banuser');
+
+ $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 } );
+ ok $abuse, 'entry created in abuse table';
+
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->content_contains('<small>User in abuse table</small>');
+};
+
+subtest 'flagging user from report page' => sub {
+ $report->user->flagged(0);
+ $report->user->update;
+
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->content_contains('Flag user');
+
+ $mech->click_ok('flaguser');
+
+ $mech->content_contains('User flagged');
+ $mech->content_contains('Remove flag');
+
+ $report->discard_changes;
+ ok $report->user->flagged, 'user flagged';
+
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->content_contains('Remove flag');
+};
+
+subtest 'unflagging user from report page' => sub {
+ $report->user->flagged(1);
+ $report->user->update;
+
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->content_contains('Remove flag');
+
+ $mech->click_ok('removeuserflag');
+
+ $mech->content_contains('User flag removed');
+ $mech->content_contains('Flag user');
+
+ $report->discard_changes;
+ ok !$report->user->flagged, 'user not flagged';
+
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->content_contains('Flag user');
+};
+
+subtest "Test setting a report from unconfirmed to something else doesn't cause a front end error" => sub {
+ $report->update( { confirmed => undef, state => 'unconfirmed', non_public => 0 } );
+ $mech->get_ok("/admin/report_edit/$report_id");
+ $mech->submit_form_ok( { with_fields => { state => 'investigating' } } );
+ $report->discard_changes;
+ ok( $report->confirmed, 'report has a confirmed timestamp' );
+ $mech->get_ok("/report/$report_id");
+};
+
+done_testing();
diff --git a/t/app/controller/admin_reportextrafields.t b/t/app/controller/admin/reportextrafields.t
index fb06665f4..fb06665f4 100644
--- a/t/app/controller/admin_reportextrafields.t
+++ b/t/app/controller/admin/reportextrafields.t
diff --git a/t/app/controller/admin/search.t b/t/app/controller/admin/search.t
new file mode 100644
index 000000000..497ac9fd6
--- /dev/null
+++ b/t/app/controller/admin/search.t
@@ -0,0 +1,121 @@
+use FixMyStreet::TestMech;
+# avoid wide character warnings from the category change message
+use open ':std', ':encoding(UTF-8)';
+
+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 $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' );
+$mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Traffic lights', email => 'lights@example.com' );
+my $oxfordshireuser = $mech->create_user_ok('counciluser@example.com', name => 'Council User', from_body => $oxfordshire);
+
+my $oxford = $mech->create_body_ok(2421, 'Oxford City Council');
+$mech->create_contact_ok( body_id => $oxford->id, category => 'Graffiti', email => 'graffiti@example.net' );
+
+my $bromley = $mech->create_body_ok(2482, 'Bromley Council');
+
+my $user3 = FixMyStreet::App->model('DB::User')->create( { email => 'test3@example.com' } );
+
+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(
+ {
+ postcode => 'SW1A 1AA',
+ bodies_str => '2504',
+ areas => ',105255,11806,11828,2247,2504,',
+ category => 'Other',
+ title => 'Report to Edit',
+ detail => 'Detail for Report to Edit',
+ used_map => 't',
+ name => 'Test User',
+ anonymous => 'f',
+ external_id => '13',
+ state => 'confirmed',
+ confirmed => $dt->ymd . ' ' . $dt->hms,
+ lang => 'en-gb',
+ service => '',
+ cobrand => '',
+ cobrand_data => '',
+ send_questionnaire => 't',
+ latitude => '51.5016605453401',
+ longitude => '-0.142497580865087',
+ user_id => $user->id,
+ whensent => $dt->ymd . ' ' . $dt->hms,
+ }
+);
+my $report_id = $report->id;
+ok $report, "created test report - $report_id";
+
+$mech->log_in_ok( $superuser->email );
+
+subtest 'show flagged entries' => sub {
+ $report->flagged( 1 );
+ $report->update;
+ $mech->get_ok('/admin/flagged');
+ $mech->content_contains( $report->title );
+};
+
+my $update = FixMyStreet::App->model('DB::Comment')->create(
+ {
+ text => 'this is an update',
+ user => $user,
+ state => 'confirmed',
+ problem => $report,
+ mark_fixed => 0,
+ anonymous => 1,
+ }
+);
+
+subtest 'report search' => sub {
+ $mech->get_ok('/admin/reports');
+ $mech->get_ok('/admin/reports?search=' . $report->id );
+
+ $mech->content_contains( $report->title );
+ my $r_id = $report->id;
+ $mech->content_like( qr{href="http://[^/]*[^.]/report/$r_id"[^>]*>$r_id</a>} );
+
+ $mech->get_ok('/admin/reports?search=' . $report->external_id);
+ $mech->content_like( qr{href="http://[^/]*[^.]/report/$r_id"[^>]*>$r_id</a>} );
+
+ $mech->get_ok('/admin/reports?search=ref:' . $report->external_id);
+ $mech->content_like( qr{href="http://[^/]*[^.]/report/$r_id"[^>]*>$r_id</a>} );
+
+ $mech->get_ok('/admin/reports?search=' . $report->user->email);
+
+ my $u_id = $update->id;
+ $mech->content_like( qr{href="http://[^/]*[^.]/report/$r_id"[^>]*>$r_id</a>} );
+ $mech->content_like( qr{href="http://[^/]*[^.]/report/$r_id#update_$u_id"[^>]*>$u_id</a>} );
+
+ $update->state('hidden');
+ $update->update;
+
+ $mech->get_ok('/admin/reports?search=' . $report->user->email);
+ $mech->content_like( qr{<tr [^>]*hidden[^>]*> \s* <td> \s* $u_id \s* </td>}xs );
+
+ $report->state('hidden');
+ $report->update;
+
+ $mech->get_ok('/admin/reports?search=' . $report->user->email);
+ $mech->content_like( qr{<tr [^>]*hidden[^>]*> \s* <td[^>]*> \s* $r_id \s* </td>}xs );
+
+ $report->state('fixed - user');
+ $report->update;
+
+ $mech->get_ok('/admin/reports?search=' . $report->user->email);
+ $mech->content_like( qr{href="http://[^/]*[^.]/report/$r_id"[^>]*>$r_id</a>} );
+};
+
+done_testing();
diff --git a/t/app/controller/admin_states.t b/t/app/controller/admin/states.t
index 60ffe5b88..60ffe5b88 100644
--- a/t/app/controller/admin_states.t
+++ b/t/app/controller/admin/states.t
diff --git a/t/app/controller/admin/stats.t b/t/app/controller/admin/stats.t
new file mode 100644
index 000000000..dae51d31f
--- /dev/null
+++ b/t/app/controller/admin/stats.t
@@ -0,0 +1,12 @@
+use FixMyStreet::TestMech;
+
+my $mech = FixMyStreet::TestMech->new;
+my $superuser = $mech->create_user_ok('superuser@example.com', name => 'Super User', is_superuser => 1);
+
+subtest "smoke view some stats pages" => sub {
+ $mech->log_in_ok( $superuser->email );
+ $mech->get_ok('/admin/stats/fix-rate');
+ $mech->get_ok('/admin/stats/questionnaire');
+};
+
+done_testing();
diff --git a/t/app/controller/admin/templates.t b/t/app/controller/admin/templates.t
new file mode 100644
index 000000000..179a1afcb
--- /dev/null
+++ b/t/app/controller/admin/templates.t
@@ -0,0 +1,183 @@
+use FixMyStreet::TestMech;
+
+my $mech = FixMyStreet::TestMech->new;
+
+my $user = $mech->create_user_ok('test@example.com', name => 'Test User');
+
+my $superuser = $mech->create_user_ok('superuser@example.com', name => 'Super User', is_superuser => 1);
+
+my $oxfordshire = $mech->create_body_ok(2237, 'Oxfordshire County Council');
+my $oxfordshirecontact = $mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Potholes', email => 'potholes@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(
+ {
+ postcode => 'SW1A 1AA',
+ bodies_str => '2504',
+ areas => ',105255,11806,11828,2247,2504,',
+ category => 'Other',
+ title => 'Report to Edit',
+ detail => 'Detail for Report to Edit',
+ used_map => 't',
+ name => 'Test User',
+ anonymous => 'f',
+ external_id => '13',
+ state => 'confirmed',
+ confirmed => $dt->ymd . ' ' . $dt->hms,
+ lang => 'en-gb',
+ service => '',
+ cobrand => '',
+ cobrand_data => '',
+ send_questionnaire => 't',
+ latitude => '51.5016605453401',
+ longitude => '-0.142497580865087',
+ user_id => $user->id,
+ whensent => $dt->ymd . ' ' . $dt->hms,
+ }
+);
+
+$mech->log_in_ok( $superuser->email );
+
+my $report_id = $report->id;
+ok $report, "created test report - $report_id";
+
+subtest "response templates can be added" => sub {
+ is $oxfordshire->response_templates->count, 0, "No response templates yet";
+ $mech->log_in_ok( $superuser->email );
+ $mech->get_ok( "/admin/templates/" . $oxfordshire->id . "/new" );
+
+ my $fields = {
+ title => "Report acknowledgement",
+ text => "Thank you for your report. We will respond shortly.",
+ auto_response => undef,
+ "contacts[".$oxfordshirecontact->id."]" => 1,
+ };
+ $mech->submit_form_ok( { with_fields => $fields } );
+
+ is $oxfordshire->response_templates->count, 1, "Response template was added";
+};
+
+subtest "response templates are included on page" => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'oxfordshire' ],
+ }, sub {
+ $report->update({ category => $oxfordshirecontact->category, bodies_str => $oxfordshire->id });
+ $mech->log_in_ok( $oxfordshireuser->email );
+
+ $mech->get_ok("/report/" . $report->id);
+ $mech->content_contains( $oxfordshire->response_templates->first->text );
+
+ $mech->log_out_ok;
+ };
+};
+
+subtest "auto-response templates that duplicate a single category can't be added" => sub {
+ $mech->delete_response_template($_) for $oxfordshire->response_templates;
+ my $template = $oxfordshire->response_templates->create({
+ title => "Report fixed - potholes",
+ text => "Thank you for your report. This problem has been fixed.",
+ auto_response => 1,
+ state => 'fixed - council',
+ });
+ $template->contact_response_templates->find_or_create({
+ contact_id => $oxfordshirecontact->id,
+ });
+ is $oxfordshire->response_templates->count, 1, "Initial response template was created";
+
+
+ $mech->log_in_ok( $superuser->email );
+ $mech->get_ok( "/admin/templates/" . $oxfordshire->id . "/new" );
+
+ # This response template has the same category & state as an existing one
+ # so won't be allowed.
+ my $fields = {
+ title => "Report marked fixed - potholes",
+ text => "Thank you for your report. This pothole has been fixed.",
+ auto_response => 'on',
+ state => 'fixed - council',
+ "contacts[".$oxfordshirecontact->id."]" => 1,
+ };
+ $mech->submit_form_ok( { with_fields => $fields } );
+ is $mech->uri->path, '/admin/templates/' . $oxfordshire->id . '/new', 'not redirected';
+ $mech->content_contains( 'Please correct the errors below' );
+ $mech->content_contains( 'There is already an auto-response template for this category/state.' );
+
+ is $oxfordshire->response_templates->count, 1, "Duplicate response template wasn't added";
+};
+
+subtest "auto-response templates that duplicate all categories can't be added" => sub {
+ $mech->delete_response_template($_) for $oxfordshire->response_templates;
+ $oxfordshire->response_templates->create({
+ title => "Report investigating - all cats",
+ text => "Thank you for your report. This problem has been fixed.",
+ auto_response => 1,
+ state => 'fixed - council',
+ });
+ 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" );
+
+ # There's already a response template for all categories and this state, so
+ # this new template won't be allowed.
+ my $fields = {
+ title => "Report investigating - single cat",
+ text => "Thank you for your report. This problem has been fixed.",
+ auto_response => 'on',
+ state => 'fixed - council',
+ "contacts[".$oxfordshirecontact->id."]" => 1,
+ };
+ $mech->submit_form_ok( { with_fields => $fields } );
+ is $mech->uri->path, '/admin/templates/' . $oxfordshire->id . '/new', 'not redirected';
+ $mech->content_contains( 'Please correct the errors below' );
+ $mech->content_contains( 'There is already an auto-response template for this category/state.' );
+
+
+ is $oxfordshire->response_templates->count, 1, "Duplicate response template wasn't added";
+};
+
+subtest "all-category auto-response templates that duplicate a single category can't be added" => sub {
+ $mech->delete_response_template($_) for $oxfordshire->response_templates;
+ my $template = $oxfordshire->response_templates->create({
+ title => "Report fixed - potholes",
+ text => "Thank you for your report. This problem has been fixed.",
+ auto_response => 1,
+ state => 'fixed - council',
+ });
+ $template->contact_response_templates->find_or_create({
+ contact_id => $oxfordshirecontact->id,
+ });
+ is $oxfordshire->response_templates->count, 1, "Initial response template was created";
+
+
+ $mech->log_in_ok( $superuser->email );
+ $mech->get_ok( "/admin/templates/" . $oxfordshire->id . "/new" );
+
+ # This response template is implicitly for all categories, but there's
+ # already a template for a specific category in this state, so it won't be
+ # allowed.
+ my $fields = {
+ title => "Report marked fixed - all cats",
+ text => "Thank you for your report. This problem has been fixed.",
+ auto_response => 'on',
+ state => 'fixed - council',
+ };
+ $mech->submit_form_ok( { with_fields => $fields } );
+ is $mech->uri->path, '/admin/templates/' . $oxfordshire->id . '/new', 'not redirected';
+ $mech->content_contains( 'Please correct the errors below' );
+ $mech->content_contains( 'There is already an auto-response template for this category/state.' );
+
+ is $oxfordshire->response_templates->count, 1, "Duplicate response template wasn't added";
+};
+
+done_testing();
diff --git a/t/app/controller/admin_translations.t b/t/app/controller/admin/translations.t
index f5c32baa6..f5c32baa6 100644
--- a/t/app/controller/admin_translations.t
+++ b/t/app/controller/admin/translations.t
diff --git a/t/app/controller/admin/update_edit.t b/t/app/controller/admin/update_edit.t
new file mode 100644
index 000000000..6ddbdbdfc
--- /dev/null
+++ b/t/app/controller/admin/update_edit.t
@@ -0,0 +1,383 @@
+use FixMyStreet::TestMech;
+# avoid wide character warnings from the category change message
+use open ':std', ':encoding(UTF-8)';
+
+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 $user3 = FixMyStreet::App->model('DB::User')->create( { email => 'test3@example.com' } );
+
+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(
+ {
+ postcode => 'SW1A 1AA',
+ bodies_str => '2504',
+ areas => ',105255,11806,11828,2247,2504,',
+ category => 'Other',
+ title => 'Report to Edit',
+ detail => 'Detail for Report to Edit',
+ used_map => 't',
+ name => 'Test User',
+ anonymous => 'f',
+ external_id => '13',
+ state => 'confirmed',
+ confirmed => $dt->ymd . ' ' . $dt->hms,
+ lang => 'en-gb',
+ service => '',
+ cobrand => '',
+ cobrand_data => '',
+ send_questionnaire => 't',
+ latitude => '51.5016605453401',
+ longitude => '-0.142497580865087',
+ user_id => $user->id,
+ whensent => $dt->ymd . ' ' . $dt->hms,
+ }
+);
+
+$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(
+ {
+ text => 'this is an update',
+ user => $user,
+ state => 'confirmed',
+ problem => $report,
+ mark_fixed => 0,
+ anonymous => 1,
+ }
+);
+
+my $log_entries = FixMyStreet::App->model('DB::AdminLog')->search(
+ {
+ object_type => 'update',
+ object_id => $update->id
+ },
+ {
+ order_by => { -desc => 'id' },
+ }
+);
+
+is $log_entries->count, 0, 'no admin log entries';
+
+for my $test (
+ {
+ desc => 'edit update text',
+ fields => {
+ text => 'this is an update',
+ state => 'confirmed',
+ name => '',
+ anonymous => 1,
+ username => 'test@example.com',
+ },
+ changes => {
+ text => 'this is a changed update',
+ },
+ log_count => 1,
+ log_entries => [qw/edit/],
+ },
+ {
+ desc => 'edit update name',
+ fields => {
+ text => 'this is a changed update',
+ state => 'confirmed',
+ name => '',
+ anonymous => 1,
+ username => 'test@example.com',
+ },
+ changes => {
+ name => 'A User',
+ },
+ log_count => 2,
+ log_entries => [qw/edit edit/],
+ },
+ {
+ desc => 'edit update anonymous',
+ fields => {
+ text => 'this is a changed update',
+ state => 'confirmed',
+ name => 'A User',
+ anonymous => 1,
+ username => 'test@example.com',
+ },
+ changes => {
+ anonymous => 0,
+ },
+ log_count => 3,
+ log_entries => [qw/edit edit edit/],
+ },
+ {
+ desc => 'edit update user',
+ fields => {
+ text => 'this is a changed update',
+ state => 'confirmed',
+ name => 'A User',
+ anonymous => 0,
+ username => 'test@example.com',
+ },
+ changes => {
+ username => 'test2@example.com',
+ },
+ log_count => 4,
+ log_entries => [qw/edit edit edit edit/],
+ user => $user2,
+ },
+ {
+ desc => 'edit update state',
+ fields => {
+ text => 'this is a changed update',
+ state => 'confirmed',
+ name => 'A User',
+ anonymous => 0,
+ username => 'test2@example.com',
+ },
+ changes => {
+ state => 'unconfirmed',
+ },
+ log_count => 5,
+ log_entries => [qw/state_change edit edit edit edit/],
+ },
+ {
+ desc => 'edit update state and text',
+ fields => {
+ text => 'this is a changed update',
+ state => 'unconfirmed',
+ name => 'A User',
+ anonymous => 0,
+ username => 'test2@example.com',
+ },
+ changes => {
+ text => 'this is a twice changed update',
+ state => 'confirmed',
+ },
+ log_count => 7,
+ log_entries => [qw/edit state_change state_change edit edit edit edit/],
+ },
+) {
+ subtest $test->{desc} => sub {
+ $log_entries->reset;
+ $mech->get_ok('/admin/update_edit/' . $update->id );
+
+ is_deeply $mech->visible_form_values, $test->{fields}, 'initial form values';
+
+ my $to_submit = {
+ %{ $test->{fields} },
+ %{ $test->{changes} }
+ };
+
+ $mech->submit_form_ok( { with_fields => $to_submit } );
+
+ is_deeply $mech->visible_form_values, $to_submit, 'submitted form values';
+
+ is $log_entries->count, $test->{log_count}, 'number of log entries';
+ is $log_entries->next->action, $_, 'log action' for @{ $test->{log_entries} };
+
+ $update->discard_changes;
+
+ is $update->$_, $test->{changes}->{$_} for grep { $_ ne 'username' } keys %{ $test->{changes} };
+ if ( $test->{changes}{state} && $test->{changes}{state} eq 'confirmed' ) {
+ isnt $update->confirmed, undef;
+ }
+
+ if ( $test->{user} ) {
+ is $update->user->id, $test->{user}->id, 'update user';
+ }
+ };
+}
+
+my $westminster = $mech->create_body_ok(2504, 'Westminster City Council');
+$report->bodies_str($westminster->id);
+$report->update;
+
+for my $test (
+ {
+ desc => 'user is problem owner',
+ problem_user => $user,
+ update_user => $user,
+ update_fixed => 0,
+ update_reopen => 0,
+ update_state => undef,
+ user_body => undef,
+ content => 'user is problem owner',
+ },
+ {
+ desc => 'user is body user',
+ problem_user => $user,
+ update_user => $user2,
+ update_fixed => 0,
+ update_reopen => 0,
+ update_state => undef,
+ user_body => $westminster->id,
+ content => 'user is from same council as problem - ' . $westminster->id,
+ },
+ {
+ desc => 'update changed problem state',
+ problem_user => $user,
+ update_user => $user2,
+ update_fixed => 0,
+ update_reopen => 0,
+ update_state => 'planned',
+ user_body => $westminster->id,
+ content => 'Update changed problem state to planned',
+ },
+ {
+ desc => 'update marked problem as fixed',
+ problem_user => $user,
+ update_user => $user3,
+ update_fixed => 1,
+ update_reopen => 0,
+ update_state => undef,
+ user_body => undef,
+ content => 'Update marked problem as fixed',
+ },
+ {
+ desc => 'update reopened problem',
+ problem_user => $user,
+ update_user => $user,
+ update_fixed => 0,
+ update_reopen => 1,
+ update_state => undef,
+ user_body => undef,
+ content => 'Update reopened problem',
+ },
+) {
+ subtest $test->{desc} => sub {
+ $report->user( $test->{problem_user} );
+ $report->update;
+
+ $update->user( $test->{update_user} );
+ $update->problem_state( $test->{update_state} );
+ $update->mark_fixed( $test->{update_fixed} );
+ $update->mark_open( $test->{update_reopen} );
+ $update->update;
+
+ $test->{update_user}->from_body( $test->{user_body} );
+ $test->{update_user}->update;
+
+ $mech->get_ok('/admin/update_edit/' . $update->id );
+ $mech->content_contains( $test->{content} );
+ };
+}
+
+subtest 'editing update email creates new user if required' => sub {
+ my $user = FixMyStreet::App->model('DB::User')->find( { email => 'test4@example.com' } );
+
+ $user->delete if $user;
+
+ my $fields = {
+ text => 'this is a changed update',
+ state => 'confirmed',
+ name => 'A User',
+ anonymous => 0,
+ username => 'test4@example.com',
+ };
+
+ $mech->submit_form_ok( { with_fields => $fields } );
+
+ $user = FixMyStreet::App->model('DB::User')->find( { email => 'test4@example.com' } );
+
+ is_deeply $mech->visible_form_values, $fields, 'submitted form values';
+
+ ok $user, 'new user created';
+
+ $update->discard_changes;
+ is $update->user->id, $user->id, 'update set to new user';
+};
+
+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 } );
+ $abuse->delete if $abuse;
+
+ $mech->get_ok( '/admin/update_edit/' . $update->id );
+ $mech->content_contains('Ban user');
+
+ $mech->click_ok('banuser');
+
+ $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 } );
+ ok $abuse, 'entry created in abuse table';
+
+ $mech->get_ok( '/admin/update_edit/' . $update->id );
+ $mech->content_contains('<small>User in abuse table</small>');
+};
+
+subtest 'flagging user from update page' => sub {
+ $update->user->flagged(0);
+ $update->user->update;
+
+ $mech->get_ok( '/admin/update_edit/' . $update->id );
+ $mech->content_contains('Flag user');
+
+ $mech->click_ok('flaguser');
+
+ $mech->content_contains('User flagged');
+ $mech->content_contains('Remove flag');
+
+ $update->discard_changes;
+ ok $update->user->flagged, 'user flagged';
+
+ $mech->get_ok( '/admin/update_edit/' . $update->id );
+ $mech->content_contains('Remove flag');
+};
+
+subtest 'unflagging user from update page' => sub {
+ $update->user->flagged(1);
+ $update->user->update;
+
+ $mech->get_ok( '/admin/update_edit/' . $update->id );
+ $mech->content_contains('Remove flag');
+
+ $mech->click_ok('removeuserflag');
+
+ $mech->content_contains('User flag removed');
+ $mech->content_contains('Flag user');
+
+ $update->discard_changes;
+ ok !$update->user->flagged, 'user not flagged';
+
+ $mech->get_ok( '/admin/update_edit/' . $update->id );
+ $mech->content_contains('Flag user');
+};
+
+subtest 'hiding comment marked as fixed reopens report' => sub {
+ $update->mark_fixed( 1 );
+ $update->update;
+
+ $report->state('fixed - user');
+ $report->update;
+
+ my $fields = {
+ text => 'this is a changed update',
+ state => 'hidden',
+ name => 'A User',
+ anonymous => 0,
+ username => 'test2@example.com',
+ };
+
+ $mech->submit_form_ok( { with_fields => $fields } );
+
+ $report->discard_changes;
+ is $report->state, 'confirmed', 'report reopened';
+ $mech->content_contains('Problem marked as open');
+};
+
+done_testing();
diff --git a/t/app/controller/admin/users.t b/t/app/controller/admin/users.t
new file mode 100644
index 000000000..8759e260d
--- /dev/null
+++ b/t/app/controller/admin/users.t
@@ -0,0 +1,453 @@
+use FixMyStreet::TestMech;
+
+my $mech = FixMyStreet::TestMech->new;
+
+my $user = $mech->create_user_ok('test@example.com', name => 'Test User');
+
+my $superuser = $mech->create_user_ok('superuser@example.com', name => 'Super User', is_superuser => 1);
+
+my $oxfordshire = $mech->create_body_ok(2237, 'Oxfordshire County Council');
+my $haringey = $mech->create_body_ok(2509, 'Haringey Borough Council');
+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 } );
+ $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);
+};
+
+subtest 'remove user from abuse list from edit user page' => sub {
+ $mech->get_ok( '/admin/user_edit/' . $user->id );
+ $mech->content_contains('User in abuse table');
+
+ $mech->click_ok('unban');
+
+ my $abuse = FixMyStreet::App->model('DB::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 } );
+ $mech->get_ok( '/admin/user_edit/' . $abuse_user->id );
+ $mech->content_contains('User in abuse table');
+ my $abuse_found = FixMyStreet::App->model('DB::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 } );
+ 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 } );
+ $abuse->delete if $abuse;
+ $mech->get_ok( '/admin/user_edit/' . $user->id );
+ $mech->content_lacks('User in abuse table');
+};
+
+subtest 'show flagged entries' => sub {
+ $user->flagged( 1 );
+ $user->update;
+
+ $mech->get_ok('/admin/flagged');
+ $mech->content_contains( $user->email );
+
+ $user->flagged( 0 );
+ $user->update;
+};
+
+subtest 'user search' => sub {
+ $mech->get_ok('/admin/users');
+ $mech->get_ok('/admin/users?search=' . $user->name);
+
+ $mech->content_contains( $user->name);
+ my $u_id = $user->id;
+ $mech->content_like( qr{user_edit/$u_id">Edit</a>} );
+
+ $mech->get_ok('/admin/users?search=' . $user->email);
+
+ $mech->content_like( qr{user_edit/$u_id">Edit</a>} );
+
+ $user->from_body($haringey->id);
+ $user->update;
+ $mech->get_ok('/admin/users?search=' . $haringey->id );
+ $mech->content_contains('Haringey');
+};
+
+subtest 'search does not show user from another council' => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'oxfordshire' ],
+ }, sub {
+ $mech->get_ok('/admin/users');
+ $mech->get_ok('/admin/users?search=' . $user->name);
+
+ $mech->content_contains( "Searching found no users." );
+
+ $mech->get_ok('/admin/users?search=' . $user->email);
+ $mech->content_contains( "Searching found no users." );
+ };
+};
+
+subtest 'user_edit does not show user from another council' => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'oxfordshire' ],
+ }, sub {
+ $mech->get('/admin/user_edit/' . $user->id);
+ ok !$mech->res->is_success(), "want a bad response";
+ is $mech->res->code, 404, "got 404";
+ };
+};
+
+for my $test (
+ {
+ desc => 'add user - blank form',
+ fields => {
+ email => '', email_verified => 0,
+ phone => '', phone_verified => 0,
+ },
+ error => ['Please verify at least one of email/phone', 'Please enter a name'],
+ },
+ {
+ desc => 'add user - blank, verify phone',
+ fields => {
+ email => '', email_verified => 0,
+ phone => '', phone_verified => 1,
+ },
+ error => ['Please enter a valid email or phone number', 'Please enter a name'],
+ },
+ {
+ desc => 'add user - bad email',
+ fields => {
+ name => 'Norman',
+ email => 'bademail', email_verified => 0,
+ phone => '', phone_verified => 0,
+ },
+ error => ['Please enter a valid email'],
+ },
+ {
+ desc => 'add user - bad phone',
+ fields => {
+ name => 'Norman',
+ phone => '01214960000000', phone_verified => 1,
+ },
+ error => ['Please check your phone number is correct'],
+ },
+ {
+ desc => 'add user - landline',
+ fields => {
+ name => 'Norman Name',
+ phone => '+441214960000',
+ phone_verified => 1,
+ },
+ error => ['Please enter a mobile number'],
+ },
+ {
+ desc => 'add user - good details',
+ fields => {
+ name => 'Norman Name',
+ phone => '+61491570156',
+ phone_verified => 1,
+ },
+ },
+) {
+ subtest $test->{desc} => sub {
+ $mech->get_ok('/admin/users');
+ $mech->submit_form_ok( { with_fields => $test->{fields} } );
+ if ($test->{error}) {
+ $mech->content_contains($_) for @{$test->{error}};
+ } else {
+ $mech->content_contains('Updated');
+ }
+ };
+}
+
+my %default_perms = (
+ "permissions[moderate]" => undef,
+ "permissions[planned_reports]" => undef,
+ "permissions[report_edit]" => undef,
+ "permissions[report_edit_category]" => undef,
+ "permissions[report_edit_priority]" => undef,
+ "permissions[report_inspect]" => undef,
+ "permissions[report_instruct]" => undef,
+ "permissions[contribute_as_another_user]" => undef,
+ "permissions[contribute_as_anonymous_user]" => undef,
+ "permissions[contribute_as_body]" => undef,
+ "permissions[view_body_contribute_details]" => undef,
+ "permissions[user_edit]" => undef,
+ "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
+# Regression test for mysociety/fixmystreetforcouncils#250
+$user->update({ name => '' });
+
+FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+}, sub {
+ for my $test (
+ {
+ desc => 'edit user name',
+ fields => {
+ name => '',
+ email => 'test@example.com',
+ email_verified => 1,
+ body => $haringey->id,
+ phone => '',
+ phone_verified => undef,
+ flagged => undef,
+ is_superuser => undef,
+ area_id => '',
+ %default_perms,
+ },
+ changes => {
+ name => 'Changed User',
+ },
+ log_count => 1,
+ log_entries => [qw/edit/],
+ },
+ {
+ desc => 'edit user email',
+ fields => {
+ name => 'Changed User',
+ email => 'test@example.com',
+ email_verified => 1,
+ body => $haringey->id,
+ phone => '',
+ phone_verified => undef,
+ flagged => undef,
+ is_superuser => undef,
+ area_id => '',
+ %default_perms,
+ },
+ changes => {
+ email => 'changed@example.com',
+ },
+ log_count => 2,
+ log_entries => [qw/edit edit/],
+ },
+ {
+ desc => 'edit user body',
+ fields => {
+ name => 'Changed User',
+ email => 'changed@example.com',
+ email_verified => 1,
+ body => $haringey->id,
+ phone => '',
+ phone_verified => undef,
+ flagged => undef,
+ is_superuser => undef,
+ area_id => '',
+ %default_perms,
+ },
+ changes => {
+ body => $southend->id,
+ },
+ log_count => 3,
+ log_entries => [qw/edit edit edit/],
+ },
+ {
+ desc => 'edit user flagged',
+ fields => {
+ name => 'Changed User',
+ email => 'changed@example.com',
+ email_verified => 1,
+ body => $southend->id,
+ phone => '',
+ phone_verified => undef,
+ flagged => undef,
+ is_superuser => undef,
+ area_id => '',
+ %default_perms,
+ },
+ changes => {
+ flagged => 'on',
+ },
+ log_count => 4,
+ log_entries => [qw/edit edit edit edit/],
+ },
+ {
+ desc => 'edit user remove flagged',
+ fields => {
+ name => 'Changed User',
+ email => 'changed@example.com',
+ email_verified => 1,
+ body => $southend->id,
+ phone => '',
+ phone_verified => undef,
+ flagged => 'on',
+ is_superuser => undef,
+ area_id => '',
+ %default_perms,
+ },
+ changes => {
+ flagged => undef,
+ },
+ log_count => 4,
+ log_entries => [qw/edit edit edit edit/],
+ },
+ {
+ desc => 'edit user add is_superuser',
+ fields => {
+ name => 'Changed User',
+ email => 'changed@example.com',
+ email_verified => 1,
+ body => $southend->id,
+ phone => '',
+ phone_verified => undef,
+ flagged => undef,
+ is_superuser => undef,
+ area_id => '',
+ %default_perms,
+ },
+ changes => {
+ is_superuser => 'on',
+ },
+ removed => [
+ keys %default_perms,
+ ],
+ log_count => 5,
+ log_entries => [qw/edit edit edit edit edit/],
+ },
+ {
+ desc => 'edit user remove is_superuser',
+ fields => {
+ name => 'Changed User',
+ email => 'changed@example.com',
+ email_verified => 1,
+ body => $southend->id,
+ phone => '',
+ phone_verified => undef,
+ flagged => undef,
+ is_superuser => 'on',
+ area_id => '',
+ },
+ changes => {
+ is_superuser => undef,
+ },
+ added => {
+ %default_perms,
+ },
+ log_count => 5,
+ log_entries => [qw/edit edit edit edit edit/],
+ },
+ ) {
+ subtest $test->{desc} => sub {
+ $mech->get_ok( '/admin/user_edit/' . $user->id );
+
+ my $visible = $mech->visible_form_values;
+ is_deeply $visible, $test->{fields}, 'expected user';
+
+ my $expected = {
+ %{ $test->{fields} },
+ %{ $test->{changes} }
+ };
+
+ $mech->submit_form_ok( { with_fields => $expected } );
+
+ # Some actions cause visible fields to be added/removed
+ foreach my $x (@{ $test->{removed} }) {
+ delete $expected->{$x};
+ }
+ if ( $test->{added} ) {
+ $expected = {
+ %$expected,
+ %{ $test->{added} }
+ };
+ }
+
+ $visible = $mech->visible_form_values;
+ is_deeply $visible, $expected, 'user updated';
+
+ $mech->content_contains( 'Updated!' );
+ };
+ }
+};
+
+FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ SMS_AUTHENTICATION => 1,
+}, sub {
+ subtest "Test edit user add verified phone" => sub {
+ $mech->get_ok( '/admin/user_edit/' . $user->id );
+ $mech->submit_form_ok( { with_fields => {
+ phone => '+61491570157',
+ phone_verified => 1,
+ } } );
+ $mech->content_contains( 'Updated!' );
+ };
+
+ subtest "Test changing user to an existing one" => sub {
+ my $existing_user = $mech->create_user_ok('existing@example.com', name => 'Existing User');
+ $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/user_edit/' . $user->id );
+ $mech->submit_form_ok( { with_fields => { email => 'existing@example.com' } }, 'submit email change' );
+ is $mech->uri->path, '/admin/user_edit/' . $existing_user->id, 'redirected';
+ my $p = FixMyStreet::DB->resultset('Problem')->search({ user_id => $existing_user->id })->count;
+ is $p, $count + 2, 'reports merged';
+ };
+
+};
+
+$user = $mech->create_user_ok('test@example.com', name => 'Test User');
+
+subtest "Anonymizing user from admin" => sub {
+ $mech->create_problems_for_body(4, 2237, 'Title');
+ 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/user_edit/' . $user->id );
+ $mech->submit_form_ok({ button => 'anon_everywhere' });
+ my $c = FixMyStreet::DB->resultset('Problem')->search({ user_id => $user->id, anonymous => 1 })->count;
+ is $c, $count_p;
+ $c = FixMyStreet::DB->resultset('Comment')->search({ user_id => $user->id, anonymous => 1 })->count;
+ is $c, $count_u;
+};
+
+subtest "Hiding user's reports from admin" => sub {
+ 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/user_edit/' . $user->id );
+ $mech->submit_form_ok({ button => 'hide_everywhere' });
+ my $c = FixMyStreet::DB->resultset('Problem')->search({ user_id => $user->id, state => 'hidden' })->count;
+ is $c, $count_p;
+ $c = FixMyStreet::DB->resultset('Comment')->search({ user_id => $user->id, state => 'hidden' })->count;
+ is $c, $count_u;
+};
+
+subtest "Logging user out" => sub {
+ my $mech2 = FixMyStreet::TestMech->new;
+ $mech2->log_in_ok($user->email);
+ $mech2->logged_in_ok;
+
+ $mech->get_ok( '/admin/user_edit/' . $user->id );
+ $mech->submit_form_ok({ button => 'logout_everywhere' }, 'Logging user out');
+ $mech2->not_logged_in_ok;
+};
+
+subtest "Removing account from admin" => sub {
+ $mech->create_problems_for_body(4, 2237, 'Title');
+ 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/user_edit/' . $user->id );
+ $mech->submit_form_ok({ button => 'remove_account' }, 'Removing account');
+ my $c = FixMyStreet::DB->resultset('Problem')->search({ user_id => $user->id, anonymous => 1, name => '' })->count;
+ is $c, $count_p, 'All reports anon/nameless';
+ $c = FixMyStreet::DB->resultset('Comment')->search({ user_id => $user->id, anonymous => 1, name => '' })->count;
+ is $c, $count_u, 'All updates anon/nameless';
+ $user->discard_changes;
+ is $user->name, '', 'Name gone';
+ is $user->password, '', 'Password gone';
+ is $user->email, 'removed-' . $user->id . '@example.org', 'Email gone'
+};
+
+done_testing();
diff --git a/t/app/controller/around.t b/t/app/controller/around.t
index d1254edb7..618998513 100644
--- a/t/app/controller/around.t
+++ b/t/app/controller/around.t
@@ -137,25 +137,28 @@ subtest 'check non public reports are not displayed on around page' => sub {
};
-subtest 'check category and status filtering works on /around?ajax' => sub {
+subtest 'check category and status filtering works on /around' => sub {
+ my $body = $mech->create_body_ok(2237, "Oxfordshire");
+
my $categories = [ 'Pothole', 'Vegetation', 'Flytipping' ];
my $params = {
- postcode => 'OX1 1ND',
- latitude => 51.7435918829363,
- longitude => -1.23201966270446,
+ postcode => 'OX20 1SZ',
+ latitude => 51.754926,
+ longitude => -1.256179,
};
my $bbox = ($params->{longitude} - 0.01) . ',' . ($params->{latitude} - 0.01)
. ',' . ($params->{longitude} + 0.01) . ',' . ($params->{latitude} + 0.01);
# 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" );
foreach my $state ( 'confirmed', 'fixed' ) {
my %report_params = (
%$params,
category => $category,
state => $state,
);
- $mech->create_problems_for_body( 1, 2237, 'Around page', \%report_params );
+ $mech->create_problems_for_body( 1, $body->id, 'Around page', \%report_params );
}
}
@@ -163,6 +166,14 @@ subtest 'check category and status filtering works on /around?ajax' => sub {
my $pins = $json->{pins};
is scalar @$pins, 6, 'correct number of reports when no filters';
+ # Regression test for filter_category in /around URL
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $mech->get_ok( '/around?filter_category=Pothole&bbox=' . $bbox );
+ $mech->content_contains('<option value="Pothole" selected>');
+ };
+
$json = $mech->get_ok_json( '/around?ajax=1&filter_category=Pothole&bbox=' . $bbox );
$pins = $json->{pins};
is scalar @$pins, 2, 'correct number of Pothole reports';
diff --git a/t/app/controller/auth.t b/t/app/controller/auth.t
index 8d60137a2..8cc7e4154 100644
--- a/t/app/controller/auth.t
+++ b/t/app/controller/auth.t
@@ -5,7 +5,7 @@ my $mech = FixMyStreet::TestMech->new;
my $test_email = 'test@example.com';
my $test_email3 = 'newuser@example.org';
-my $test_password = 'foobar';
+my $test_password = 'foobar123';
END {
done_testing();
@@ -276,3 +276,49 @@ subtest "check logging in with token" => sub {
$mech->delete_header('Authorization');
};
+
+subtest 'check password length/common' => sub {
+ $mech->get_ok('/auth');
+ $mech->submit_form_ok({
+ form_name => 'general_auth',
+ fields => { username => $test_email, password_register => 'short' },
+ button => 'sign_in_by_code',
+ });
+ $mech->content_contains("Please make sure your password is at least");
+ $mech->submit_form_ok({
+ form_name => 'general_auth',
+ fields => { username => $test_email, password_register => 'common' },
+ button => 'sign_in_by_code',
+ });
+ $mech->content_contains("Please choose a less commonly-used password");
+};
+
+subtest 'check common password AJAX call' => sub {
+ $mech->post_ok('/auth/common_password', { password_register => 'password' });
+ $mech->content_contains("Please choose a less commonly-used password");
+ $mech->post_ok('/auth/common_password', { password_register => 'squirblewirble' });
+ $mech->content_contains("true");
+};
+
+subtest "Test two-factor authentication login" => sub {
+ use Auth::GoogleAuth;
+ my $auth = Auth::GoogleAuth->new;
+ 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);
+ $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' => $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->logged_in_ok;
+};
diff --git a/t/app/controller/auth_profile.t b/t/app/controller/auth_profile.t
index 74edccfe6..4be1be12c 100644
--- a/t/app/controller/auth_profile.t
+++ b/t/app/controller/auth_profile.t
@@ -8,7 +8,7 @@ LWP::Protocol::PSGI->register($twilio->to_psgi_app, host => 'api.twilio.com');
my $test_email = 'test@example.com';
my $test_email2 = 'test@example.net';
-my $test_password = 'foobar';
+my $test_password = 'foobar123';
END {
done_testing();
@@ -75,12 +75,18 @@ subtest "Test change password page" => sub {
{
form_name => 'change_password',
fields =>
- { new_password => $test_password, confirm => $test_password, },
+ { new_password => 'new_password', confirm => 'new_password', },
},
- "change_password with '$test_password' and '$test_password'"
+ "change_password with 'new_password' and 'new_password'"
);
is $mech->uri->path, '/auth/change_password',
"still on change password page";
+ $mech->content_contains('check your email');
+
+ $link = $mech->get_link_from_email;
+ $mech->get_ok($link);
+ is $mech->uri->path, '/my', "redirected to /my";
+
$mech->content_contains( 'password has been changed',
"found password changed" );
@@ -88,6 +94,73 @@ subtest "Test change password page" => sub {
ok $user->password, "user now has a password";
};
+# Change password, when already got one
+subtest "Test change password page with current password" => sub {
+ $mech->get_ok('/auth/change_password');
+
+ ok my $form = $mech->form_name('change_password'),
+ "found change password form";
+ is_deeply [ sort grep { $_ } map { $_->name } $form->inputs ], #
+ [ 'confirm', 'current_password', 'new_password', 'token' ],
+ "check we got expected fields (ie not old_password)";
+
+ # check the various ways the form can be wrong
+ for my $test (
+ { current => '', new => '', conf => '', err => 'check the passwords', },
+ { current => 'new_password', new => '', conf => '', err => 'enter a password', },
+ { current => 'new_password', new => 'secret', conf => '', err => 'do not match', },
+ { current => 'new_password', new => '', conf => 'secret', err => 'do not match', },
+ { current => 'new_password', new => 'secret', conf => 'not_secret', err => 'do not match', },
+ )
+ {
+ $mech->get_ok('/auth/change_password');
+ $mech->content_lacks( $test->{err}, "did not find expected error" );
+ $mech->submit_form_ok(
+ {
+ form_name => 'change_password',
+ fields =>
+ { current_password => $test->{current}, new_password => $test->{new}, confirm => $test->{conf}, },
+ },
+ "change_password with '$test->{current}', '$test->{new}' and '$test->{conf}'"
+ );
+ $mech->content_contains( $test->{err}, "found expected error" );
+ }
+
+ my $user = FixMyStreet::App->model('DB::User')->find( { email => $test_email } );
+ ok $user, "got a user";
+
+ $mech->get_ok('/auth/change_password');
+ $mech->submit_form_ok(
+ {
+ form_name => 'change_password',
+ fields =>
+ { current_password => 'new_password', new_password => $test_password, confirm => $test_password },
+ },
+ "change_password with 'new_password' and '$test_password'"
+ );
+ is $mech->uri->path, '/auth/change_password',
+ "still on change password page";
+ $mech->content_contains( 'password has been changed',
+ "found password changed" );
+
+ $user->discard_changes();
+ ok $user->password, "user now has a password";
+};
+
+subtest 'check password length/common' => sub {
+ $mech->get_ok('/auth/change_password');
+ $mech->submit_form_ok({
+ form_name => 'change_password',
+ fields => { current_password => $test_password, new_password => 'short', confirm => 'short' },
+ });
+ $mech->content_contains("Please make sure your password is at least");
+ $mech->submit_form_ok({
+ form_name => 'change_password',
+ fields => { current_password => $test_password, new_password => 'common', confirm => 'common' },
+ });
+ $mech->content_contains("Please choose a less commonly-used password");
+};
+
subtest "Test change email page" => sub {
$mech->create_problems_for_body(1, 2514, 'Title1', { user => FixMyStreet::DB->resultset('User')->find( { email => $test_email } ) } );
@@ -274,7 +347,7 @@ subtest "Test superuser can access generate token page" => sub {
},
});
- $mech->content_lacks('Generate token');
+ $mech->content_lacks('Security');
$mech->get('/auth/generate_token');
is $mech->res->code, 403, "access denied";
@@ -282,7 +355,7 @@ subtest "Test superuser can access generate token page" => sub {
ok $user->update({ is_superuser => 1 }), 'user is superuser';
$mech->get_ok('/my');
- $mech->content_contains('Generate token');
+ $mech->content_contains('Security');
$mech->get_ok('/auth/generate_token');
};
@@ -299,7 +372,7 @@ subtest "Test staff user can access generate token page" => sub {
},
});
- $mech->content_lacks('Generate token');
+ $mech->content_lacks('Security');
my $body = $mech->create_body_ok(2237, 'Oxfordshire');
@@ -309,7 +382,7 @@ subtest "Test staff user can access generate token page" => sub {
ok $user->update({ from_body => $body }), 'user is staff user';
$mech->get_ok('/my');
- $mech->content_contains('Generate token');
+ $mech->content_contains('Security');
$mech->get_ok('/auth/generate_token');
};
@@ -333,7 +406,7 @@ subtest "Test generate token page" => sub {
$mech->follow_link_ok({url => '/auth/generate_token'});
$mech->content_lacks('Token:');
$mech->submit_form_ok(
- { with_fields => { generate_token => 'Generate token' } },
+ { button => 'generate_token' },
"submit generate token form"
);
$mech->content_contains( 'Your token has been generated', "token generated" );
@@ -352,4 +425,28 @@ subtest "Test generate token page" => sub {
$mech->log_out_ok;
$mech->add_header('Authorization', "Bearer $token");
$mech->logged_in_ok;
-}
+};
+
+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';
+
+ $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->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');
+
+ $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->content_contains('has been deactivated', "2FA deactivated");
+};
diff --git a/t/app/controller/report_as_other.t b/t/app/controller/report_as_other.t
index 91644e8ce..e8f65eb7b 100644
--- a/t/app/controller/report_as_other.t
+++ b/t/app/controller/report_as_other.t
@@ -39,7 +39,7 @@ subtest "Body user, has permission to add report as council" => sub {
};
my @users;
-subtest "Body user, has permission to add report as another user" => sub {
+subtest "Body user, has permission to add report as another user with email" => sub {
my $report = add_report(
'contribute_as_another_user',
form_as => 'another_user',
@@ -57,7 +57,49 @@ subtest "Body user, has permission to add report as another user" => sub {
push @users, $report->user;
};
-subtest "Body user, has permission to add report as another (existing) user" => sub {
+subtest "Body user, has permission to add report as another user with mobile phone number" => 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 => '07906 111111',
+ );
+ is $report->name, 'Another User', 'report name is given name';
+ is $report->user->name, 'Another User', 'user name matches';
+ is $report->user->phone, '+447906111111', 'user phone correct';
+ is $report->user->phone_verified, 1, 'user phone verified';
+ is $report->user->email, undef, 'user email correct';
+ 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 {
+ 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 => '01685 222222',
+ );
+ is $report->name, 'Another User', 'report name is given name';
+ is $report->user->name, 'Another User', 'user name matches';
+ is $report->user->phone, '+441685222222', 'user phone correct';
+ is $report->user->phone_verified, 1, 'user phone verified';
+ is $report->user->email, undef, 'user email correct';
+ 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 (existing) user with email" => sub {
$mech->create_user_ok('existing@example.net', name => 'Existing User');
my $report = add_report(
'contribute_as_another_user',
@@ -76,6 +118,25 @@ subtest "Body user, has permission to add report as another (existing) user" =>
push @users, $report->user;
};
+subtest "Body user, has permission to add report as another (existing) user with phone" => sub {
+ $mech->create_user_ok('+447906333333', name => 'Existing User');
+ my $report = add_report(
+ 'contribute_as_another_user',
+ form_as => 'another_user',
+ title => "Test Report",
+ detail => 'Test report details.',
+ category => 'Potholes',
+ name => 'Existing Yooser',
+ username => '07906 333333',
+ );
+ is $report->name, 'Existing Yooser', 'report name is given name';
+ is $report->user->name, 'Existing User', 'user name remains same';
+ 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 "Body user, has permission to add report as anonymous user" => sub {
my $report = add_report(
'contribute_as_anonymous_user',
@@ -102,7 +163,7 @@ subtest "Body user, has permission to add update as council" => sub {
is $update->anonymous, 0, 'update not anonymous';
};
-subtest "Body user, has permission to add update as another user" => sub {
+subtest "Body user, has permission to add update as another user with email" => sub {
my $update = add_update(
'contribute_as_another_user',
form_as => 'another_user',
@@ -118,7 +179,39 @@ subtest "Body user, has permission to add update as another user" => sub {
push @users, $update->user;
};
-subtest "Body user, has permission to add update as another (existing) user" => sub {
+subtest "Body user, has permission to add update as another user with mobile phone" => sub {
+ my $update = add_update(
+ 'contribute_as_another_user',
+ form_as => 'another_user',
+ update => 'Test Update',
+ name => 'Another User',
+ username => '07906 444444',
+ );
+ is $update->name, 'Another User', 'update name is given name';
+ is $update->user->name, 'Another User', 'user name matches';
+ 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 {
+ my $update = add_update(
+ 'contribute_as_another_user',
+ form_as => 'another_user',
+ update => 'Test Update',
+ name => 'Another User',
+ username => '01685 555555',
+ );
+ is $update->name, 'Another User', 'update name is given name';
+ is $update->user->name, 'Another User', 'user name matches';
+ 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 $update = add_update(
'contribute_as_another_user',
form_as => 'another_user',
@@ -133,6 +226,21 @@ subtest "Body user, has permission to add update as another (existing) user" =>
like $mech->get_text_body_from_email, qr/Your update has been logged/;
};
+subtest "Body user, has permission to add update as another (existing) user with phone" => sub {
+ my $update = add_update(
+ 'contribute_as_another_user',
+ form_as => 'another_user',
+ update => 'Test Update',
+ name => 'Existing Yooser',
+ username => '07906 333333',
+ );
+ is $update->name, 'Existing Yooser', 'update name is given name';
+ is $update->user->name, 'Existing User', 'user name remains same';
+ is $update->user->phone, '+447906333333', 'user phone correct';
+ isnt $update->user->id, $user->id, 'user does not match';
+ $mech->email_count_is(0);
+};
+
subtest "Body user, has permission to add update as anonymous user" => sub {
my $update = add_update(
'contribute_as_anonymous_user',
@@ -155,6 +263,7 @@ sub start_report {
FixMyStreet::override_config {
ALLOWED_COBRANDS => [ 'fixmystreet' ],
MAPIT_URL => 'http://mapit.uk/',
+ PHONE_COUNTRY => 'GB',
}, sub {
$mech->get_ok('/report/new?latitude=51.7549262252&longitude=-1.25617899435');
};
@@ -166,6 +275,7 @@ sub add_report {
FixMyStreet::override_config {
ALLOWED_COBRANDS => [ 'fixmystreet' ],
MAPIT_URL => 'http://mapit.uk/',
+ PHONE_COUNTRY => 'GB',
}, sub {
dropdown_shown(1);
$mech->submit_form_ok({
@@ -184,16 +294,28 @@ sub start_update {
$_->delete for $user->user_body_permissions;
$user->user_body_permissions->create({ body => $body, permission_type => $permission })
if $permission;
- $mech->get_ok('/report/' . $report_to_update->id);
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'fixmystreet' ],
+ MAPIT_URL => 'http://mapit.uk/',
+ PHONE_COUNTRY => 'GB',
+ }, sub {
+ $mech->get_ok('/report/' . $report_to_update->id);
+ };
}
sub add_update {
my ($permission, %fields) = @_;
start_update($permission);
- dropdown_shown(1, 'updateForm');
- $mech->submit_form_ok({
- with_fields => \%fields,
- }, "submit details");
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'fixmystreet' ],
+ MAPIT_URL => 'http://mapit.uk/',
+ PHONE_COUNTRY => 'GB',
+ }, sub {
+ dropdown_shown(1, 'updateForm');
+ $mech->submit_form_ok({
+ with_fields => \%fields,
+ }, "submit details");
+ };
$mech->content_contains('Thank you for updating this issue');
my $update = FixMyStreet::DB->resultset("Comment")->search(undef, { order_by => { -desc => 'id' } })->first;
ok $update, "Found the update";
diff --git a/t/app/controller/report_new.t b/t/app/controller/report_new.t
index e0fe205bd..3c120b0b0 100644
--- a/t/app/controller/report_new.t
+++ b/t/app/controller/report_new.t
@@ -705,7 +705,11 @@ subtest "test password errors for a user who is signing in as they report" => su
], "check there were errors";
};
-subtest "test report creation for a user who is signing in as they report" => sub {
+foreach my $test (
+ { two_factor => 0, desc => '', },
+ { two_factor => 1, desc => ' with two-factor', },
+) {
+ subtest "test report creation for a user who is signing in as they report$test->{desc}" => sub {
$mech->log_out_ok;
$mech->cookie_jar({});
$mech->clear_emails_ok;
@@ -722,6 +726,15 @@ subtest "test report creation for a user who is signing in as they report" => su
password => 'secret2',
} ), "set user details";
+ my $auth;
+ if ($test->{two_factor}) {
+ use Auth::GoogleAuth;
+ $auth = Auth::GoogleAuth->new;
+ $user->is_superuser(1);
+ $user->set_extra_metadata('2fa_secret', $auth->generate_secret32);
+ $user->update;
+ }
+
# submit initial pc form
$mech->get_ok('/around');
FixMyStreet::override_config {
@@ -742,7 +755,7 @@ subtest "test report creation for a user who is signing in as they report" => su
title => 'Test Report',
detail => 'Test report details.',
photo1 => '',
- username => 'test-2@example.com',
+ username => $test_email,
password_sign_in => 'secret2',
category => 'Street lighting',
}
@@ -750,6 +763,15 @@ subtest "test report creation for a user who is signing in as they report" => su
"submit good details"
);
+ if ($test->{two_factor}) {
+ 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" );
+ }
+
# check that we got the message expected
$mech->content_contains( 'You have successfully signed in; please check and confirm your details are accurate:' );
@@ -768,7 +790,10 @@ subtest "test report creation for a user who is signing in as they report" => su
my $report = $user->problems->first;
ok $report, "Found the report";
- $mech->content_contains('Thank you for reporting this issue');
+ if (!$test->{two_factor}) {
+ # The superuser account will be immediately redirected
+ $mech->content_contains('Thank you for reporting this issue');
+ }
# Check the report has been assigned appropriately
is $report->bodies_str, $body_ids{2651};
@@ -793,7 +818,8 @@ subtest "test report creation for a user who is signing in as they report" => su
# cleanup
$mech->delete_user($user)
-};
+ };
+}
#### test report creation for user with account and logged in
my ($saved_lat, $saved_lon);
@@ -1236,9 +1262,7 @@ for my $test (
is $user->title, $test->{'user_title'}, 'user title correct';
is_deeply $extras, $test->{extra}, 'extra contains correct values';
- $user->problems->delete;
- $user->alerts->delete;
- $user->delete;
+ $mech->delete_user($user);
};
}
@@ -1705,9 +1729,7 @@ subtest "extra google analytics code displayed on email confirmation problem cre
$mech->content_contains( "'id': 'report/" . $report->id . "'", 'extra google code present' );
- $user->problems->delete;
- $user->alerts->delete;
- $user->delete;
+ $mech->delete_user($user);
};
};
diff --git a/t/app/controller/report_new_text.t b/t/app/controller/report_new_text.t
index 734b9dbb4..cb07e57ee 100644
--- a/t/app/controller/report_new_text.t
+++ b/t/app/controller/report_new_text.t
@@ -45,8 +45,8 @@ foreach my $test (
password_register => '', password_sign_in => '',
},
changes => {
- username => '+44 121 496 0000',
- phone => '+44 121 496 0000',
+ username => '0121 496 0000',
+ phone => '0121 496 0000',
},
errors => [ 'Please enter a mobile number', ],
},
diff --git a/t/app/controller/report_update_text.t b/t/app/controller/report_update_text.t
index 45b4e78c2..a3b767221 100644
--- a/t/app/controller/report_update_text.t
+++ b/t/app/controller/report_update_text.t
@@ -95,7 +95,7 @@ for my $test (
password_sign_in => '',
},
changes => {
- username => '+44 121 496 0000',
+ username => '0121 496 0000',
},
field_errors => [ 'Please enter a mobile number' ]
},
diff --git a/t/app/controller/rss.t b/t/app/controller/rss.t
index 171121eaa..a8101b593 100644
--- a/t/app/controller/rss.t
+++ b/t/app/controller/rss.t
@@ -14,28 +14,19 @@ my $user1 = $mech->create_user_ok('reporter-rss@example.com', name => 'Reporter
my $dt_parser = FixMyStreet::App->model('DB')->schema->storage->datetime_parser;
-my $report = FixMyStreet::App->model('DB::Problem')->find_or_create( {
+my ($report) = $mech->create_problems_for_body(1, 2651, '', {
postcode => 'eh1 1BB',
- bodies_str => '2651',
areas => ',11808,135007,14419,134935,2651,20728,',
category => 'Street lighting',
title => '&Test’i<n>g \'☃"',
detail => 'Testing Detail',
- used_map => 1,
name => $user1->name,
- anonymous => 0,
- state => 'confirmed',
confirmed => $dt_parser->format_datetime($dt),
lastupdate => $dt_parser->format_datetime($dt),
whensent => $dt_parser->format_datetime($dt->clone->add( minutes => 5 )),
- lang => 'en-gb',
- service => '',
- cobrand => 'default',
- cobrand_data => '',
- send_questionnaire => 1,
latitude => '55.951963',
longitude => '-3.189944',
- user_id => $user1->id,
+ user => $user1,
} );
$mech->host('www.fixmystreet.com');
@@ -127,54 +118,19 @@ $report->delete();
my $council = $mech->create_body_ok(2333, 'Hart Council');
my $county = $mech->create_body_ok(2227, 'Hampshire Council');
-my $now = DateTime->now();
-my $report_to_council = FixMyStreet::App->model('DB::Problem')->find_or_create(
- {
- postcode => 'GU51 4AE',
- bodies_str => $council->id,
+my ($report_to_council) = $mech->create_problems_for_body(1, $council->id, '', {
+ user => $user1,
areas => ',2333,2227,',
- category => 'Other',
- title => 'council report',
- detail => 'Test 2 Detail',
- used_map => 't',
- name => 'Test User',
- anonymous => 'f',
- state => 'closed',
- confirmed => $now->ymd . ' ' . $now->hms,
- lang => 'en-gb',
- service => '',
- cobrand => 'default',
- cobrand_data => '',
- send_questionnaire => 't',
latitude => '51.279616',
longitude => '-0.846040',
- user_id => $user1->id,
- }
-);
+});
-my $report_to_county_council = FixMyStreet::App->model('DB::Problem')->find_or_create(
- {
- postcode => 'GU51 4AE',
- bodies_str => $county->id,
+my ($report_to_county_council) = $mech->create_problems_for_body(1, $county->id, '', {
+ user => $user1,
areas => ',2333,2227,',
- category => 'Other',
- title => 'county report',
- detail => 'Test 2 Detail',
- used_map => 't',
- name => 'Test User',
- anonymous => 'f',
- state => 'closed',
- confirmed => $now->ymd . ' ' . $now->hms,
- lang => 'en-gb',
- service => '',
- cobrand => 'default',
- cobrand_data => '',
- send_questionnaire => 't',
latitude => '51.279616',
longitude => '-0.846040',
- user_id => $user1->id,
- }
-);
+});
subtest "check RSS feeds on cobrand have correct URLs for non-cobrand reports" => sub {
$mech->host('hart.fixmystreet.com');
diff --git a/t/app/model/problem.t b/t/app/model/problem.t
index efc9057da..27f6aed66 100644
--- a/t/app/model/problem.t
+++ b/t/app/model/problem.t
@@ -2,6 +2,7 @@ use FixMyStreet::TestMech;
use FixMyStreet;
use FixMyStreet::App;
use FixMyStreet::DB;
+use FixMyStreet::Script::Reports;
use Sub::Override;
my $problem_rs = FixMyStreet::DB->resultset('Problem');
@@ -541,7 +542,7 @@ foreach my $test ( {
} );
FixMyStreet::override_config $override, sub {
- $problem_rs->send_reports();
+ FixMyStreet::Script::Reports::send();
};
$mech->email_count_is( $test->{ email_count } );
@@ -619,7 +620,7 @@ subtest 'check can set mutiple emails as a single contact' => sub {
} );
FixMyStreet::override_config $override, sub {
- $problem_rs->send_reports();
+ FixMyStreet::Script::Reports::send();
};
$mech->email_count_is(1);
@@ -652,7 +653,7 @@ subtest 'check can turn on report sent email alerts' => sub {
send_fail_count => 0,
} );
- $problem_rs->send_reports();
+ FixMyStreet::Script::Reports::send();
$mech->email_count_is( 2 );
my @emails = $mech->get_email;
@@ -698,7 +699,7 @@ subtest 'check iOS app store test reports not sent' => sub {
send_fail_count => 0,
} );
- $problem_rs->send_reports();
+ FixMyStreet::Script::Reports::send();
$mech->email_count_is( 0 );
@@ -727,7 +728,7 @@ subtest 'check reports from abuser not sent' => sub {
send_fail_count => 0,
} );
- $problem_rs->send_reports();
+ FixMyStreet::Script::Reports::send();
$mech->email_count_is( 1 );
@@ -743,7 +744,7 @@ subtest 'check reports from abuser not sent' => sub {
my $abuse = FixMyStreet::DB->resultset('Abuse')->create( { email => $problem->user->email } );
$mech->clear_emails_ok;
- $problem_rs->send_reports();
+ FixMyStreet::Script::Reports::send();
$mech->email_count_is( 0 );
diff --git a/t/app/sendreport/inspection_required.t b/t/app/sendreport/inspection_required.t
index c8cb30592..64d6f70ee 100644
--- a/t/app/sendreport/inspection_required.t
+++ b/t/app/sendreport/inspection_required.t
@@ -1,13 +1,10 @@
use FixMyStreet;
use FixMyStreet::DB;
use FixMyStreet::TestMech;
-use FixMyStreet::SendReport::Email;
+use FixMyStreet::Script::Reports;
ok( my $mech = FixMyStreet::TestMech->new, 'Created mech object' );
-use_ok 'FixMyStreet::Cobrand';
-FixMyStreet::DB->schema->cobrand(FixMyStreet::Cobrand::FixMyStreet->new());
-
my $user = $mech->create_user_ok( 'user@example.com' );
my $body = $mech->create_body_ok( 2237, 'Oxfordshire County Council');
@@ -31,7 +28,7 @@ my $report = $reports[0];
subtest "Report isn't sent if uninspected" => sub {
$mech->clear_emails_ok;
- FixMyStreet::DB->resultset('Problem')->send_reports();
+ FixMyStreet::Script::Reports::send();
$mech->email_count_is( 0 );
is $report->whensent, undef, "Report hasn't been sent";
@@ -42,7 +39,7 @@ subtest 'Report is sent when inspected' => sub {
$report->set_extra_metadata(inspected => 1);
$report->update;
- FixMyStreet::DB->resultset('Problem')->send_reports();
+ FixMyStreet::Script::Reports::send();
$report->discard_changes;
$mech->email_count_is( 1 );
@@ -61,7 +58,7 @@ subtest 'Uninspected report is sent when made by trusted user' => sub {
});
ok $user->has_permission_to('trusted', $report->bodies_str_ids), 'User can make trusted reports';
- FixMyStreet::DB->resultset('Problem')->send_reports();
+ FixMyStreet::Script::Reports::send();
$report->discard_changes;
$mech->email_count_is( 1 );
@@ -81,7 +78,7 @@ subtest "Uninspected report isn't sent when user rep is too low" => sub {
$contact->set_extra_metadata(reputation_threshold => 20);
$contact->update;
- FixMyStreet::DB->resultset('Problem')->send_reports();
+ FixMyStreet::Script::Reports::send();
$report->discard_changes;
$mech->email_count_is( 0 );
@@ -92,7 +89,7 @@ subtest 'Uninspected report is sent when user rep is high enough' => sub {
$user->set_extra_metadata(reputation => 21);
$user->update;
- FixMyStreet::DB->resultset('Problem')->send_reports();
+ FixMyStreet::Script::Reports::send();
$report->discard_changes;
$mech->email_count_is( 1 );
diff --git a/t/cobrand/bromley.t b/t/cobrand/bromley.t
index a64337085..41e351dea 100644
--- a/t/cobrand/bromley.t
+++ b/t/cobrand/bromley.t
@@ -1,5 +1,6 @@
use CGI::Simple;
use FixMyStreet::TestMech;
+use FixMyStreet::Script::Reports;
my $mech = FixMyStreet::TestMech->new;
# Create test data
@@ -48,13 +49,13 @@ $mech->content_contains( 'State changed to: No further action' );
subtest 'testing special Open311 behaviour', sub {
$report->set_extra_fields();
$report->update;
- $body->update( { send_method => 'Open311', endpoint => 'http://bromley.endpoint.example.com', jurisdiction => 'FMS', api_key => 'test' } );
+ $body->update( { send_method => 'Open311', endpoint => 'http://bromley.endpoint.example.com', jurisdiction => 'FMS', api_key => 'test', send_comments => 1 } );
my $test_data;
FixMyStreet::override_config {
STAGING_FLAGS => { send_reports => 1 },
ALLOWED_COBRANDS => [ 'fixmystreet', 'bromley' ],
}, sub {
- $test_data = FixMyStreet::DB->resultset('Problem')->send_reports();
+ $test_data = FixMyStreet::Script::Reports::send();
};
$report->discard_changes;
ok $report->whensent, 'Report marked as sent';
diff --git a/t/cobrand/fixamingata.t b/t/cobrand/fixamingata.t
index 133a8c950..0aa264660 100644
--- a/t/cobrand/fixamingata.t
+++ b/t/cobrand/fixamingata.t
@@ -1,5 +1,6 @@
use mySociety::Locale;
+use FixMyStreet::Script::Reports;
use FixMyStreet::TestMech;
my $mech = FixMyStreet::TestMech->new;
@@ -35,7 +36,7 @@ $mech->email_count_is(0);
FixMyStreet::override_config {
ALLOWED_COBRANDS => [ 'fixamingata' ],
}, sub {
- FixMyStreet::DB->resultset('Problem')->send_reports();
+ FixMyStreet::Script::Reports::send();
};
my $email = $mech->get_email;
my $plain = $mech->get_text_body_from_email($email, 1);
diff --git a/t/cobrand/zurich.t b/t/cobrand/zurich.t
index e0671db2a..385f7f077 100644
--- a/t/cobrand/zurich.t
+++ b/t/cobrand/zurich.t
@@ -3,10 +3,12 @@
use DateTime;
use Email::MIME;
+use File::Temp;
use LWP::Protocol::PSGI;
use Test::LongString;
use Path::Tiny;
use t::Mock::MapItZurich;
+use FixMyStreet::Script::Reports;
use FixMyStreet::TestMech;
my $mech = FixMyStreet::TestMech->new;
@@ -24,7 +26,6 @@ my $cobrand = FixMyStreet::Cobrand::Zurich->new();
my $sample_file = path(__FILE__)->parent->parent->child("app/controller/sample.jpg");
ok $sample_file->exists, "sample file $sample_file exists";
-my $sample_photo = $sample_file->slurp_raw;
# 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
@@ -36,7 +37,7 @@ sub send_reports_for_zurich {
ALLOWED_COBRANDS => ['zurich']
}, sub {
# Actually send the report
- FixMyStreet::DB->resultset('Problem')->send_reports('zurich');
+ FixMyStreet::Script::Reports::send('zurich');
};
}
sub reset_report_state {
@@ -102,7 +103,7 @@ my $superuser;
subtest "set up superuser" => sub {
$superuser = $mech->log_in_ok( 'super@example.org' );
# a user from body $zurich is a superuser, as $zurich has no parent id!
- $superuser->update({ from_body => $zurich->id });
+ $superuser->update({ from_body => $zurich->id });
$EXISTING_REPORT_COUNT = get_export_rows_count($mech);
$mech->log_out_ok;
};
@@ -111,7 +112,6 @@ my @reports = $mech->create_problems_for_body( 1, $division->id, 'Test', {
state => 'unconfirmed',
confirmed => undef,
cobrand => 'zurich',
- photo => $sample_photo,
areas => ',423017,',
});
my $report = $reports[0];
@@ -314,15 +314,30 @@ subtest "report_edit" => sub {
}
};
+# 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',
+ UPLOAD_DIR => $UPLOAD_DIR,
}, sub {
# Photo publishing
$mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->submit_form_ok( { with_fields => { state => 'confirmed', publish_photo => 1 } } );
+ $mech->submit_form_ok( { with_fields => { state => 'confirmed', publish_photo_1 => 1 } } );
+ $mech->get_ok( '/around?lat=' . $report->latitude . ';lon=' . $report->longitude);
+ $mech->content_lacks('photo/' . $report->id . '.0.fp.jpeg');
+ $mech->content_contains('photo/' . $report->id . '.1.fp.jpeg');
+ $mech->content_lacks('photo/' . $report->id . '.2.fp.jpeg');
$mech->get_ok( '/report/' . $report->id );
- $mech->content_contains('photo/' . $report->id . '.0.jpeg');
+ $mech->content_lacks('photo/' . $report->id . '.0.jpeg');
+ $mech->content_contains('photo/' . $report->id . '.1.jpeg');
+ $mech->content_lacks('photo/' . $report->id . '.2.jpeg');
# Internal notes
$mech->get_ok( '/admin/report_edit/' . $report->id );
@@ -450,12 +465,16 @@ $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;
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');
+
$mech->get_ok( '/admin/report_edit/' . $report->id );
$mech->content_lacks( 'Unbest&auml;tigt' ); # Confirmed email
$mech->submit_form_ok( { with_fields => { status_update => 'FINAL UPDATE' } } );
@@ -479,7 +498,6 @@ $mech->clear_emails_ok;
state => 'unconfirmed',
confirmed => undef,
cobrand => 'zurich',
- photo => $sample_photo,
areas => ',423017,',
});
$report = $reports[0];
@@ -521,7 +539,6 @@ $mech->email_count_is(0);
state => 'unconfirmed',
confirmed => undef,
cobrand => 'zurich',
- photo => $sample_photo,
areas => ',423017,',
});
$report = $reports[0];
@@ -829,7 +846,7 @@ subtest "test stats" => sub {
$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';
@@ -864,7 +881,7 @@ subtest 'email images to external partners' => sub {
});
my $fileid = $photoset->data;
- $report->set_extra_metadata('publish_photo' => 1);
+ $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({
diff --git a/t/geocode/google.t b/t/geocode/google.t
new file mode 100644
index 000000000..ee3c15ea8
--- /dev/null
+++ b/t/geocode/google.t
@@ -0,0 +1,22 @@
+package FixMyStreet::Cobrand::Tester;
+use parent 'FixMyStreet::Cobrand::Default';
+sub country { 'GB' }
+sub disambiguate_location { { components => 'country:IE' } }
+
+package main;
+
+use FixMyStreet::Test;
+use FixMyStreet::Geocode::Google;
+use Catalyst::Test 'FixMyStreet::App';
+use t::Mock::GoogleGeocoder;
+
+my $c = ctx_request('/');
+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);
+is scalar @{$r->{error}}, 2;
+
+done_testing;
diff --git a/t/images/12049724866_404b066875_z.jpg b/t/images/12049724866_404b066875_z.jpg
new file mode 100644
index 000000000..42de32674
--- /dev/null
+++ b/t/images/12049724866_404b066875_z.jpg
Binary files differ
diff --git a/t/images/12205918375_f37f0b27a9_z.jpg b/t/images/12205918375_f37f0b27a9_z.jpg
new file mode 100644
index 000000000..6b0c8637d
--- /dev/null
+++ b/t/images/12205918375_f37f0b27a9_z.jpg
Binary files differ
diff --git a/t/images/14347396807_20737504f7_z.jpg b/t/images/14347396807_20737504f7_z.jpg
new file mode 100644
index 000000000..820382985
--- /dev/null
+++ b/t/images/14347396807_20737504f7_z.jpg
Binary files differ
diff --git a/t/images/14792525771_167bc20e3d_z.jpg b/t/images/14792525771_167bc20e3d_z.jpg
new file mode 100644
index 000000000..a52d134a0
--- /dev/null
+++ b/t/images/14792525771_167bc20e3d_z.jpg
Binary files differ
diff --git a/t/images/19119222668_a3c866d7c8_z.jpg b/t/images/19119222668_a3c866d7c8_z.jpg
new file mode 100644
index 000000000..48ec0102b
--- /dev/null
+++ b/t/images/19119222668_a3c866d7c8_z.jpg
Binary files differ
diff --git a/t/images/20515339175_f4ed9fc1d9_z.jpg b/t/images/20515339175_f4ed9fc1d9_z.jpg
new file mode 100644
index 000000000..9b70bb6fc
--- /dev/null
+++ b/t/images/20515339175_f4ed9fc1d9_z.jpg
Binary files differ
diff --git a/t/images/22593395257_3d48f23bfa_z.jpg b/t/images/22593395257_3d48f23bfa_z.jpg
new file mode 100644
index 000000000..e297e460c
--- /dev/null
+++ b/t/images/22593395257_3d48f23bfa_z.jpg
Binary files differ
diff --git a/t/images/22998854352_17555b7536_z.jpg b/t/images/22998854352_17555b7536_z.jpg
new file mode 100644
index 000000000..f754806d2
--- /dev/null
+++ b/t/images/22998854352_17555b7536_z.jpg
Binary files differ
diff --git a/t/images/23222004240_273977b2b2_z.jpg b/t/images/23222004240_273977b2b2_z.jpg
new file mode 100644
index 000000000..952cea966
--- /dev/null
+++ b/t/images/23222004240_273977b2b2_z.jpg
Binary files differ
diff --git a/t/images/27050321819_ac123400eb_z.jpg b/t/images/27050321819_ac123400eb_z.jpg
new file mode 100644
index 000000000..3b16ac4c2
--- /dev/null
+++ b/t/images/27050321819_ac123400eb_z.jpg
Binary files differ
diff --git a/t/images/31889115854_01cdf38b0d_z.jpg b/t/images/31889115854_01cdf38b0d_z.jpg
new file mode 100644
index 000000000..8a20014db
--- /dev/null
+++ b/t/images/31889115854_01cdf38b0d_z.jpg
Binary files differ
diff --git a/t/images/33717571655_46dfc6f65f_z.jpg b/t/images/33717571655_46dfc6f65f_z.jpg
new file mode 100644
index 000000000..839206b95
--- /dev/null
+++ b/t/images/33717571655_46dfc6f65f_z.jpg
Binary files differ
diff --git a/t/images/35732107202_b790c61f63_z.jpg b/t/images/35732107202_b790c61f63_z.jpg
new file mode 100644
index 000000000..ae514d465
--- /dev/null
+++ b/t/images/35732107202_b790c61f63_z.jpg
Binary files differ
diff --git a/t/images/36296226976_a83a118ff8_z.jpg b/t/images/36296226976_a83a118ff8_z.jpg
new file mode 100644
index 000000000..63285ea62
--- /dev/null
+++ b/t/images/36296226976_a83a118ff8_z.jpg
Binary files differ
diff --git a/t/images/3705226606_eac71cf195_z.jpg b/t/images/3705226606_eac71cf195_z.jpg
new file mode 100644
index 000000000..3c07dceb4
--- /dev/null
+++ b/t/images/3705226606_eac71cf195_z.jpg
Binary files differ
diff --git a/t/images/37855543925_9dbbbecf41_z.jpg b/t/images/37855543925_9dbbbecf41_z.jpg
new file mode 100644
index 000000000..510586516
--- /dev/null
+++ b/t/images/37855543925_9dbbbecf41_z.jpg
Binary files differ
diff --git a/t/images/38110448864_fd71227247_z.jpg b/t/images/38110448864_fd71227247_z.jpg
new file mode 100644
index 000000000..832b2c6f8
--- /dev/null
+++ b/t/images/38110448864_fd71227247_z.jpg
Binary files differ
diff --git a/t/images/6304445383_bd216ca892_z.jpg b/t/images/6304445383_bd216ca892_z.jpg
new file mode 100644
index 000000000..dccfe13da
--- /dev/null
+++ b/t/images/6304445383_bd216ca892_z.jpg
Binary files differ
diff --git a/t/images/8895442578_376a9b0be0_z.jpg b/t/images/8895442578_376a9b0be0_z.jpg
new file mode 100644
index 000000000..b27437bac
--- /dev/null
+++ b/t/images/8895442578_376a9b0be0_z.jpg
Binary files differ
diff --git a/t/sendreport/open311.t b/t/sendreport/open311.t
index 52b1952f4..1eb5535aa 100644
--- a/t/sendreport/open311.t
+++ b/t/sendreport/open311.t
@@ -1,4 +1,5 @@
use CGI::Simple;
+use FixMyStreet::Script::Reports;
use FixMyStreet::TestMech;
my $mech = FixMyStreet::TestMech->new;
@@ -25,7 +26,7 @@ subtest 'testing Open311 behaviour', sub {
STAGING_FLAGS => { send_reports => 1 },
ALLOWED_COBRANDS => [ 'fixmystreet' ],
}, sub {
- $test_data = FixMyStreet::DB->resultset('Problem')->send_reports();
+ $test_data = FixMyStreet::Script::Reports::send();
};
$report->discard_changes;
ok $report->whensent, 'Report marked as sent';
diff --git a/t/utils.t b/t/utils.t
index f989580c8..aeaf225c7 100644
--- a/t/utils.t
+++ b/t/utils.t
@@ -67,7 +67,9 @@ is Utils::cleanup_text( "This has new\n\n\nlines in it", { allow_multiline => 1
is Utils::prettify_dt(), "[unknown time]";
-my $dt = DateTime->now;
+# Make sure we create the date using the FMS timezone that prettify_dt uses
+# otherwise this can fail if the local timezone is not the same as the FMS one
+my $dt = DateTime->now( time_zone => FixMyStreet->time_zone || FixMyStreet->local_time_zone );
is Utils::prettify_dt($dt), $dt->strftime("%H:%M today");
# Same week test