diff options
Diffstat (limited to 't/app/controller')
34 files changed, 1959 insertions, 825 deletions
diff --git a/t/app/controller/admin.t b/t/app/controller/admin.t index b69a711c8..d50702086 100644 --- a/t/app/controller/admin.t +++ b/t/app/controller/admin.t @@ -1,3 +1,9 @@ +package FixMyStreet::Cobrand::OxfordshireUTA; +use parent 'FixMyStreet::Cobrand::Oxfordshire'; +sub area_types { [ 'UTA' ] } + +package main; + use FixMyStreet::TestMech; my $mech = FixMyStreet::TestMech->new; @@ -8,6 +14,7 @@ my $superuser = $mech->create_user_ok('superuser@example.com', name => 'Super Us my $oxfordshire = $mech->create_body_ok(2237, 'Oxfordshire County Council'); my $oxfordshireuser = $mech->create_user_ok('counciluser@example.com', name => 'Council User', from_body => $oxfordshire); +$oxfordshireuser->user_body_permissions->create({ body => $oxfordshire, permission_type => 'category_edit' }); my $dt = DateTime->new( year => 2011, @@ -129,35 +136,51 @@ subtest 'check summary counts' => sub { subtest "Check admin_base_url" => sub { my $rs = FixMyStreet::App->model('DB::Problem'); - my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker($report->cobrand)->new(); + my $cobrand = $report->get_cobrand_logged; is ($report->admin_url($cobrand), (sprintf 'http://www.example.org/admin/report_edit/%d', $report_id), 'get_admin_url OK'); }; +subtest "Check body dropdown on admin index page" => sub { + FixMyStreet::override_config { + MAPIT_TYPES => [ 'UTA' ], + MAPIT_URL => 'http://mapit.uk/', + }, sub { + ok $mech->get('/admin'); + $mech->submit_form_ok({ with_fields => { body => $oxfordshire->id } }); + }; +}; + # Finished with the superuser tests $mech->log_out_ok; subtest "Users without from_body can't access admin" => sub { $mech->log_in_ok( $user->email ); - ok $mech->get('/admin'); is $mech->res->code, 403, "got 403"; - - $mech->log_out_ok; }; +$mech->log_in_ok( $oxfordshireuser->email ); + subtest "Users with from_body can access their own council's admin" => sub { FixMyStreet::override_config { ALLOWED_COBRANDS => [ 'oxfordshire' ], }, sub { - $mech->log_in_ok( $oxfordshireuser->email ); - $mech->get_ok('/admin'); $mech->content_contains( 'FixMyStreet admin:' ); + }; +}; - $mech->log_out_ok; + +subtest "Check admin index page redirects" => sub { + FixMyStreet::override_config { + ALLOWED_COBRANDS => [ 'oxfordshireuta' ], + MAPIT_URL => 'http://mapit.uk/', + }, sub { + ok $mech->get('/admin/bodies'); + is $mech->uri->path, '/admin/body/' . $oxfordshire->id, 'body redirects okay'; }; }; @@ -165,12 +188,8 @@ subtest "Users with from_body can't access another council's admin" => sub { FixMyStreet::override_config { ALLOWED_COBRANDS => [ 'bristol' ], }, sub { - $mech->log_in_ok( $oxfordshireuser->email ); - ok $mech->get('/admin'); is $mech->res->code, 403, "got 403"; - - $mech->log_out_ok; }; }; @@ -178,12 +197,8 @@ subtest "Users with from_body can't access fixmystreet.com admin" => sub { FixMyStreet::override_config { ALLOWED_COBRANDS => [ 'fixmystreet' ], }, sub { - $mech->log_in_ok( $oxfordshireuser->email ); - ok $mech->get('/admin'); is $mech->res->code, 403, "got 403"; - - $mech->log_out_ok; }; }; diff --git a/t/app/controller/admin/bodies.t b/t/app/controller/admin/bodies.t index a485d286d..f67e45bf6 100644 --- a/t/app/controller/admin/bodies.t +++ b/t/app/controller/admin/bodies.t @@ -1,9 +1,17 @@ +package FixMyStreet::Cobrand::Tester; + +use parent 'FixMyStreet::Cobrand::Default'; + +sub enable_category_groups { 1 } + +package main; 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 ); +my $body = $mech->create_body_ok(2650, 'Aberdeen City Council'); # This override is wrapped around ALL the /admin/body tests FixMyStreet::override_config { @@ -12,7 +20,6 @@ FixMyStreet::override_config { 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}); @@ -56,6 +63,7 @@ subtest 'check contact creation' => sub { subtest 'check contact editing' => sub { $mech->get_ok('/admin/body/' . $body->id .'/test%20category'); + $mech->content_lacks( 'group</strong> is used for the top-level category' ); $mech->submit_form_ok( { with_fields => { email => 'test2@example.com', @@ -201,4 +209,47 @@ subtest 'check text output' => sub { }; # END of override wrap +FixMyStreet::override_config { + ALLOWED_COBRANDS => ['tester'], + MAPIT_URL => 'http://mapit.uk/', + MAPIT_TYPES => [ 'UTA' ], + BASE_URL => 'http://www.example.org', +}, sub { + subtest 'group editing works' => sub { + $mech->get_ok('/admin/body/' . $body->id); + $mech->content_contains( 'group</strong> is used for the top-level category' ); + + $mech->submit_form_ok( { with_fields => { + category => 'grouped category', + email => 'test@example.com', + note => 'test note', + group => 'group a', + non_public => undef, + state => 'unconfirmed', + } } ); + + my $contact = $body->contacts->find({ category => 'grouped category' }); + is $contact->get_extra_metadata('group'), 'group a', "group stored correctly"; + }; + + subtest 'group can be unset' => sub { + $mech->get_ok('/admin/body/' . $body->id); + $mech->content_contains( 'group</strong> is used for the top-level category' ); + + $mech->submit_form_ok( { with_fields => { + category => 'grouped category', + email => 'test@example.com', + note => 'test note', + group => undef, + non_public => undef, + state => 'unconfirmed', + } } ); + + my $contact = $body->contacts->find({ category => 'grouped category' }); + is $contact->get_extra_metadata('group'), undef, "group unset correctly"; + }; + +}; + + done_testing(); diff --git a/t/app/controller/admin/defecttypes.t b/t/app/controller/admin/defecttypes.t index e7d0e42af..12ae8948c 100644 --- a/t/app/controller/admin/defecttypes.t +++ b/t/app/controller/admin/defecttypes.t @@ -1,4 +1,5 @@ use FixMyStreet::TestMech; +use Test::MockModule; my $mech = FixMyStreet::TestMech->new; @@ -26,8 +27,32 @@ FixMyStreet::override_config { ALLOWED_COBRANDS => ['bromley'], }, sub { FixMyStreet::override_config { ALLOWED_COBRANDS => ['oxfordshire'], }, sub { + my $cobrand = Test::MockModule->new('FixMyStreet::Cobrand::Oxfordshire'); + $cobrand->mock('available_permissions', sub { + my $self = shift; + + my $perms = FixMyStreet::Cobrand::Default->available_permissions; + $perms->{Bodies}->{defect_type_edit} = "Add/edit defect types"; + + return $perms; + }); + my $body = $mech->create_body_ok( 2237, 'Oxfordshire County Council' ); + subtest 'check defect types menu available to superusers' => sub { + my $user = $mech->create_user_ok( + 'superuser@example.com', + name => 'Test Superuser', + is_superuser => 1 + ); + + $mech->log_in_ok( $user->email ); + $mech->get_ok('/admin'); + $mech->content_contains('Defect Types'); + $mech->get_ok('/admin/defecttypes'); + $mech->log_out_ok(); + }; + my $user = $mech->create_user_ok( 'oxford@example.com', name => 'Test User', diff --git a/t/app/controller/admin/permissions.t b/t/app/controller/admin/permissions.t index 7944cc0b1..ff5a8ec4f 100644 --- a/t/app/controller/admin/permissions.t +++ b/t/app/controller/admin/permissions.t @@ -1,4 +1,5 @@ use FixMyStreet::TestMech; +use Test::MockModule; my $mech = FixMyStreet::TestMech->new; @@ -28,6 +29,13 @@ ok $report, "created test report - $report_id"; $mech->log_in_ok( $oxfordshireuser->email ); +my $cobrand = Test::MockModule->new('FixMyStreet::Cobrand::Oxfordshire'); +$cobrand->mock('available_permissions', sub { + my $self = shift; + + return FixMyStreet::Cobrand::Default->available_permissions; +}); + subtest "Users can't edit report without report_edit permission" => sub { FixMyStreet::override_config { ALLOWED_COBRANDS => [ 'oxfordshire' ], @@ -91,7 +99,7 @@ FixMyStreet::override_config { my $p = $perm ? 'with' : 'without'; my $r = $report->user eq $user2 ? 'with' : 'without'; subtest "User $u edit user for $b $p permission, $r cobrand relation" => sub { - $mech->get("/admin/user_edit/$user2_id"); + $mech->get("/admin/users/$user2_id"); my $success = $mech->res->is_success(); ok $result == 200 ? $success : !$success, "got correct response"; is $mech->res->code, $result, "got $result"; @@ -100,13 +108,23 @@ FixMyStreet::override_config { } } + subtest "Users can't edit users of their own council without permission" => sub { + $mech->get_ok("/admin/users/$user2_id"); + $mech->submit_form_ok( { with_fields => { + email => $user2->email, + } } ); + $user2->discard_changes; + # Make sure we haven't lost the from_body info + is $user2->from_body->id, $oxfordshire->id; + }; + $oxfordshireuser->user_body_permissions->create({ body => $oxfordshire, permission_type => 'user_assign_body', }); subtest "Users can edit users of their own council" => sub { - $mech->get_ok("/admin/user_edit/$user2_id"); + $mech->get_ok("/admin/users/$user2_id"); $mech->content_contains( $user2->name ); # We shouldn't be able to see the permissions tick boxes @@ -131,7 +149,7 @@ FixMyStreet::override_config { subtest "Users can edit permissions" => sub { is $user2->user_body_permissions->count, 0, 'user2 has no permissions'; - $mech->get_ok("/admin/user_edit/$user2_id"); + $mech->get_ok("/admin/users/$user2_id"); $mech->content_contains('Moderate report details'); $mech->submit_form_ok( { with_fields => { @@ -163,8 +181,9 @@ FixMyStreet::override_config { subtest "Unsetting user from_body removes all permissions and area " => sub { is $user2->user_body_permissions->count, 1, 'user2 has 1 permission'; + $user2->update({ area_ids => [123] }); # Set to check cleared - $mech->get_ok("/admin/user_edit/$user2_id"); + $mech->get_ok("/admin/users/$user2_id"); $mech->content_contains('Moderate report details'); $mech->submit_form_ok( { with_fields => { @@ -186,8 +205,9 @@ FixMyStreet::override_config { "permissions[user_assign_areas]" => undef, } } ); + $user2->discard_changes; is $user2->user_body_permissions->count, 0, 'user2 has had permissions removed'; - is $user2->area_id, undef, 'user2 has had area removed'; + is $user2->area_ids, undef, 'user2 has had area removed'; }; }; diff --git a/t/app/controller/admin/report_edit.t b/t/app/controller/admin/report_edit.t index 5e3e6c315..c6e03ff7e 100644 --- a/t/app/controller/admin/report_edit.t +++ b/t/app/controller/admin/report_edit.t @@ -608,6 +608,32 @@ subtest "Test display of report extra data" => sub { $mech->content_contains('extra_field</strong>: this is extra data'); }; +subtest "Test alert count display" => sub { + $mech->get_ok("/admin/report_edit/$report_id"); + $mech->content_contains('Alerts: 0'); + + my $alert = FixMyStreet::App->model('DB::Alert')->find_or_create( + { + alert_type => 'new_updates', + parameter => $report_id, + user => $user, + } + ); + + $mech->get_ok("/admin/report_edit/$report_id"); + $mech->content_contains('Alerts: 0', 'does not include unconfirmed reports'); + + $alert->update( { confirmed => 1 } ); + $mech->get_ok("/admin/report_edit/$report_id"); + $mech->content_contains('Alerts: 1'); + + $alert->update( { whendisabled => \"now()" } ); + $mech->get_ok("/admin/report_edit/$report_id"); + $mech->content_contains('Alerts: 0'); + + $alert->delete; +}; + my $report2 = FixMyStreet::App->model('DB::Problem')->find_or_create( { postcode => 'SW1A 1AA', diff --git a/t/app/controller/admin/reportextrafields.t b/t/app/controller/admin/reportextrafields.t index fb06665f4..e02df864f 100644 --- a/t/app/controller/admin/reportextrafields.t +++ b/t/app/controller/admin/reportextrafields.t @@ -120,12 +120,42 @@ FixMyStreet::override_config { $contact->update; }; + subtest 'check contact updating does not remove server_set' => sub { + $contact->set_extra_fields(({ code => 'POT', automated => 'server_set' })); + $contact->update; + + $mech->get_ok("/admin/body/" . $body->id . "/" . $contact->category); + $mech->submit_form_ok( { with_fields => { + email => 'test4@example.com', + note => 'test4 note', + } } ); + + $mech->content_like(qr'test4@example.com's); + + $contact->discard_changes; + my $meta_data = $contact->get_extra_fields; + is $contact->email, 'test4@example.com', 'contact updated'; + is_deeply $meta_data, [ { + order => 0, + datatype => 'string', + datatype_description => '', + description => '', + required => 'false', + variable => 'true', + code => 'POT', + automated => 'server_set' + } ], "automated fields not unset"; + }; + + subtest 'Create and update new ReportExtraFields' => sub { my $extra_fields = []; - my $model = FixMyStreet::App->model('DB::ReportExtraFields'); + my $model = FixMyStreet::App->model('DB::ReportExtraField'); is $model->count, 0, 'no ReportExtraFields yet'; + $mech->get_ok("/admin/reportextrafields"); + $mech->get_ok("/admin/reportextrafields/new"); $mech->submit_form_ok({ with_fields => { name => "Test extra fields", @@ -181,11 +211,39 @@ FixMyStreet::override_config { { name => "name1", key => "key1" }, ] }; + $object->discard_changes; is_deeply $object->get_extra_fields, $extra_fields, 'new list field was added'; is $object->language, "en-gb", "Correct language was set"; $mech->get_ok("/admin/reportextrafields/" . $object->id); + $mech->submit_form_ok({ with_fields => { + "metadata[2].order" => "3", + "metadata[2].code" => "automated_test", + "metadata[2].required" => undef, + "metadata[2].notice" => "", + "metadata[2].description" => "", + "metadata[2].datatype_description" => "", + "metadata[2].datatype" => "string", + "metadata[2].automated" => "server_set", + }}); + + push @$extra_fields, { + order => "3", + code => "automated_test", + required => "false", + variable => "true", + description => "", + datatype_description => "", + datatype => "string", + automated => "server_set", + }; + + $object->discard_changes; + is_deeply $object->get_extra_fields, $extra_fields, 'new automated field was added'; + is $object->language, "en-gb", "Correct language was set"; + + $mech->get_ok("/admin/reportextrafields/" . $object->id); $mech->submit_form_ok( { with_fields => { "metadata[1].values[1].key" => "key2", "metadata[1].values[1].name" => "name2", @@ -233,7 +291,7 @@ FixMyStreet::override_config { LANGUAGES => [ 'en-gb,English,en_GB' ] }, sub { subtest "Extra fields are missing from cobrand that doesn't allow them" => sub { - my $object = FixMyStreet::App->model('DB::ReportExtraFields')->first; + my $object = FixMyStreet::App->model('DB::ReportExtraField')->first; $object->update({ language => "", cobrand => ""}); $mech->get_ok("/report/new?longitude=-1.351488&latitude=51.847235&category=" . $contact->category); @@ -242,7 +300,7 @@ FixMyStreet::override_config { }; }; -FixMyStreet::App->model('DB::ReportExtraFields')->delete_all; +FixMyStreet::App->model('DB::ReportExtraField')->delete_all; $mech->log_out_ok; subtest 'Reports are created with correct extra metadata' => sub { @@ -250,7 +308,7 @@ subtest 'Reports are created with correct extra metadata' => sub { ALLOWED_COBRANDS => [ 'tester' ], MAPIT_URL => 'http://mapit.uk/', }, sub { - my $model = FixMyStreet::App->model('DB::ReportExtraFields'); + my $model = FixMyStreet::App->model('DB::ReportExtraField'); my $extra_fields = $model->find_or_create({ name => "Test extra fields", language => "", diff --git a/t/app/controller/admin/search.t b/t/app/controller/admin/search.t index 497ac9fd6..f8e70cb7a 100644 --- a/t/app/controller/admin/search.t +++ b/t/app/controller/admin/search.t @@ -103,7 +103,7 @@ subtest 'report search' => sub { $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 ); + $mech->content_like( qr{<tr [^>]*hidden[^>]*> \s* <td[^>]*> \s* $u_id \s* </td>}xs ); $report->state('hidden'); $report->update; diff --git a/t/app/controller/admin/users.t b/t/app/controller/admin/users.t index 8759e260d..e2c922a23 100644 --- a/t/app/controller/admin/users.t +++ b/t/app/controller/admin/users.t @@ -19,7 +19,7 @@ subtest 'search abuse' => sub { }; subtest 'remove user from abuse list from edit user page' => sub { - $mech->get_ok( '/admin/user_edit/' . $user->id ); + $mech->get_ok( '/admin/users/' . $user->id ); $mech->content_contains('User in abuse table'); $mech->click_ok('unban'); @@ -31,7 +31,7 @@ subtest 'remove user from abuse list from edit user page' => sub { 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->get_ok( '/admin/users/' . $abuse_user->id ); $mech->content_contains('User in abuse table'); my $abuse_found = FixMyStreet::App->model('DB::Abuse')->find( { email => $abuse_user->phone } ); ok $abuse_found, 'user in abuse table'; @@ -45,7 +45,7 @@ subtest 'remove user with phone account from abuse list from edit user page' => 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->get_ok( '/admin/users/' . $user->id ); $mech->content_lacks('User in abuse table'); }; @@ -66,11 +66,11 @@ subtest 'user search' => sub { $mech->content_contains( $user->name); my $u_id = $user->id; - $mech->content_like( qr{user_edit/$u_id">Edit</a>} ); + $mech->content_like( qr{users/$u_id">Edit</a>} ); $mech->get_ok('/admin/users?search=' . $user->email); - $mech->content_like( qr{user_edit/$u_id">Edit</a>} ); + $mech->content_like( qr{users/$u_id">Edit</a>} ); $user->from_body($haringey->id); $user->update; @@ -96,7 +96,7 @@ 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); + $mech->get('/admin/users/' . $user->id); ok !$mech->res->is_success(), "want a bad response"; is $mech->res->code, 404, "got 404"; }; @@ -168,14 +168,17 @@ for my $test ( my %default_perms = ( "permissions[moderate]" => undef, "permissions[planned_reports]" => undef, + "permissions[report_mark_private]" => undef, "permissions[report_edit]" => undef, "permissions[report_edit_category]" => undef, "permissions[report_edit_priority]" => undef, "permissions[report_inspect]" => undef, "permissions[report_instruct]" => undef, + "permissions[report_prefill]" => undef, "permissions[contribute_as_another_user]" => undef, "permissions[contribute_as_anonymous_user]" => undef, "permissions[contribute_as_body]" => undef, + "permissions[default_to_body]" => undef, "permissions[view_body_contribute_details]" => undef, "permissions[user_edit]" => undef, "permissions[user_manage_permissions]" => undef, @@ -206,7 +209,7 @@ FixMyStreet::override_config { phone_verified => undef, flagged => undef, is_superuser => undef, - area_id => '', + area_ids => undef, %default_perms, }, changes => { @@ -226,7 +229,7 @@ FixMyStreet::override_config { phone_verified => undef, flagged => undef, is_superuser => undef, - area_id => '', + area_ids => undef, %default_perms, }, changes => { @@ -246,7 +249,7 @@ FixMyStreet::override_config { phone_verified => undef, flagged => undef, is_superuser => undef, - area_id => '', + area_ids => undef, %default_perms, }, changes => { @@ -266,7 +269,7 @@ FixMyStreet::override_config { phone_verified => undef, flagged => undef, is_superuser => undef, - area_id => '', + area_ids => undef, %default_perms, }, changes => { @@ -286,7 +289,7 @@ FixMyStreet::override_config { phone_verified => undef, flagged => 'on', is_superuser => undef, - area_id => '', + area_ids => undef, %default_perms, }, changes => { @@ -306,7 +309,7 @@ FixMyStreet::override_config { phone_verified => undef, flagged => undef, is_superuser => undef, - area_id => '', + area_ids => undef, %default_perms, }, changes => { @@ -329,7 +332,7 @@ FixMyStreet::override_config { phone_verified => undef, flagged => undef, is_superuser => 'on', - area_id => '', + area_ids => undef, }, changes => { is_superuser => undef, @@ -342,7 +345,7 @@ FixMyStreet::override_config { }, ) { subtest $test->{desc} => sub { - $mech->get_ok( '/admin/user_edit/' . $user->id ); + $mech->get_ok( '/admin/users/' . $user->id ); my $visible = $mech->visible_form_values; is_deeply $visible, $test->{fields}, 'expected user'; @@ -378,7 +381,7 @@ FixMyStreet::override_config { SMS_AUTHENTICATION => 1, }, sub { subtest "Test edit user add verified phone" => sub { - $mech->get_ok( '/admin/user_edit/' . $user->id ); + $mech->get_ok( '/admin/users/' . $user->id ); $mech->submit_form_ok( { with_fields => { phone => '+61491570157', phone_verified => 1, @@ -390,9 +393,9 @@ FixMyStreet::override_config { 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->get_ok( '/admin/users/' . $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'; + is $mech->uri->path, '/admin/users/' . $existing_user->id, 'redirected'; my $p = FixMyStreet::DB->resultset('Problem')->search({ user_id => $existing_user->id })->count; is $p, $count + 2, 'reports merged'; }; @@ -401,11 +404,76 @@ FixMyStreet::override_config { $user = $mech->create_user_ok('test@example.com', name => 'Test User'); +subtest "Send login email from admin" => sub { + $mech->email_count_is(0); + $mech->get_ok( '/admin/users/' . $user->id ); + $mech->submit_form_ok( + { + button => 'send_login_email' + }, + "send login email form submitted" + ); + + my $email = $mech->get_email; + ok $email, "got an email"; + + is $email->header('Subject'), "Your FixMyStreet account details", + "subject is correct"; + is $email->header('To'), $user->email, "to is correct"; + + my $link = $mech->get_link_from_email($email); + + my $mech2 = FixMyStreet::TestMech->new; + $mech2->not_logged_in_ok; + $mech2->get_ok($link); + $mech2->logged_in_ok; + $mech2->log_out_ok; + + $mech->clear_emails_ok; +}; + +subtest "Send login email from admin for unverified email" => sub { + $user->update( { email_verified => 0 } ); + $mech->email_count_is(0); + $mech->get_ok( '/admin/users/' . $user->id ); + $mech->submit_form_ok( + { + button => 'send_login_email' + }, + "send login email form submitted" + ); + + my $email = $mech->get_email; + ok $email, "got an email"; + + is $email->header('Subject'), "Your FixMyStreet account details", + "subject is correct"; + is $email->header('To'), 'test@example.com', "to is correct"; + + my $link = $mech->get_link_from_email($email); + + my $mech2 = FixMyStreet::TestMech->new; + $mech2->not_logged_in_ok; + $mech2->get_ok($link); + $mech2->logged_in_ok; + + my $test_user = FixMyStreet::DB->resultset('User')->search({ + email => $user->email + }, { order_by => [ { -desc => 'id' } ] } ); + $user->discard_changes; + + is $test_user->count, 1, "only one user"; + is $test_user->first->id, $user->id, "User is same"; + ok $user->email_verified, 'email is verified now'; + $mech2->log_out_ok; + $user->update( { email_verified => 1 } ); +}; + 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->get_ok( '/admin/users/' . $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; @@ -416,7 +484,7 @@ subtest "Anonymizing user from admin" => sub { 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->get_ok( '/admin/users/' . $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; @@ -429,7 +497,7 @@ subtest "Logging user out" => sub { $mech2->log_in_ok($user->email); $mech2->logged_in_ok; - $mech->get_ok( '/admin/user_edit/' . $user->id ); + $mech->get_ok( '/admin/users/' . $user->id ); $mech->submit_form_ok({ button => 'logout_everywhere' }, 'Logging user out'); $mech2->not_logged_in_ok; }; @@ -438,7 +506,7 @@ 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->get_ok( '/admin/users/' . $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'; @@ -450,4 +518,66 @@ subtest "Removing account from admin" => sub { is $user->email, 'removed-' . $user->id . '@example.org', 'Email gone' }; +subtest "can view list of user's alerts" => sub { + $mech->get_ok( '/admin/users/' . $user->id ); + $mech->content_lacks("User's alerts", 'no list of alerts'); + + $mech->create_problems_for_body(1, 2514, 'Title', { user => $user }); + my $p = FixMyStreet::DB->resultset('Problem')->search({ user_id => $user->id })->first; + + my $alert = FixMyStreet::DB->resultset('Alert')->find_or_create({ + user_id => $user->id, + alert_type => 'new_updates', + parameter => $p->id + }); + + + $mech->get_ok( '/admin/users/' . $user->id ); + $mech->content_contains("User's alerts", 'has list of alerts'); + $mech->content_contains($alert->id, 'lists alert'); +}; + +subtest "can edit list of user's alerts" => sub { + $mech->get_ok( '/admin/users/' . $user->id ); + + my $alert = FixMyStreet::DB->resultset('Alert')->search({ + user_id => $user->id, + alert_type => 'new_updates', + })->first; + + $mech->content_like(qr[<td>${\$alert->id}</td>\s*<td>new_updates</td>]m, 'alert on page'); + + $mech->submit_form_ok( { + with_fields => { + 'edit_alert[' . $alert->id . ']' => 'disable' + } + }, 'disabling alert'); + + $alert->discard_changes; + ok $alert->whendisabled, 'alert disabled'; + + $mech->submit_form_ok( { + with_fields => { + 'edit_alert[' . $alert->id . ']' => 'enable' + } + }, 'enabling alert'); + + $alert->discard_changes; + is $alert->whendisabled, undef, 'alert enabled'; + + $mech->submit_form_ok( { + with_fields => { + 'edit_alert[' . $alert->id . ']' => 'delete', + } + }, 'deleting alert'); + + $mech->content_unlike(qr[<td>${\$alert->id}</td>\s*<td>new_updates</td>]m, 'alert not on page'); + + is $user->alerts->count, 0, 'alert deleted'; +}; + +subtest "View timeline" => sub { + $mech->get_ok('/admin/timeline'); +}; + done_testing(); diff --git a/t/app/controller/alert.t b/t/app/controller/alert.t index ce3c2ef9b..41aee5bbc 100644 --- a/t/app/controller/alert.t +++ b/t/app/controller/alert.t @@ -1,5 +1,3 @@ -use LWP::Protocol::PSGI; - use FixMyStreet::TestMech; my $mech = FixMyStreet::TestMech->new; @@ -11,6 +9,11 @@ $mech->title_like(qr/^Local RSS feeds and email alerts/); $mech->content_contains('Local RSS feeds and email alerts'); $mech->content_contains('html class="no-js" lang="en-gb"'); +my $body = $mech->create_body_ok(2651, 'Edinburgh'); +$mech->create_body_ok(2504, 'Birmingham City Council'); +$mech->create_body_ok(2226, 'Gloucestershire County Council'); +$mech->create_body_ok(2326, 'Cheltenham Borough Council'); + # check that we can get list page FixMyStreet::override_config { ALLOWED_COBRANDS => [ { 'fixmystreet' => '.' } ], @@ -35,11 +38,10 @@ FixMyStreet::override_config { $mech->content_contains('Problems within City Centre ward'); $mech->content_contains('/rss/reports/Edinburgh'); $mech->content_contains('/rss/reports/Edinburgh/City+Centre'); - $mech->content_contains('council:2651:Edinburgh'); - $mech->content_contains('ward:2651:20728:Edinburgh:City_Centre'); + $mech->content_contains('council:' . $body->id . ':Edinburgh'); + $mech->content_contains('ward:' . $body->id . ':20728:Edinburgh:City_Centre'); subtest "Test Nominatim lookup" => sub { - LWP::Protocol::PSGI->register(t::Mock::Nominatim->run_if_script, host => 'nominatim.openstreetmap.org'); $mech->get_ok('/alert/list?pc=High Street'); $mech->content_contains('We found more than one match for that location'); }; @@ -52,16 +54,12 @@ FixMyStreet::override_config { $mech->content_contains('Problems in an area'); $mech->content_contains('Reports by destination'); - $mech->get_ok('/alert/subscribe?rss=1&type=local&pc=ky16+8yg&rss=Give+me+an+RSS+feed&rznvy=' ); + $mech->get_ok('/alert/subscribe?rss=1&type=local&pc=EH1+1BB&rss=Give+me+an+RSS+feed&rznvy=' ); $mech->content_contains('Please select the feed you want'); - $mech->get_ok('/alert/subscribe?rss=1&feed=invalid:1000:A_Locationtype=local&pc=ky16+8yg&rss=Give+me+an+RSS+feed&rznvy='); + $mech->get_ok('/alert/subscribe?rss=1&feed=invalid:1000:A_Locationtype=local&pc=EH1+1BB&rss=Give+me+an+RSS+feed&rznvy='); $mech->content_contains('Illegal feed selection'); - $mech->create_body_ok(2504, 'Birmingham City Council'); - $mech->create_body_ok(2226, 'Gloucestershire County Council'); - $mech->create_body_ok(2326, 'Cheltenham Borough Council'); - $mech->get_ok('/alert/subscribe?rss=1&feed=area:1000:Birmingham'); is $mech->uri->path, '/rss/reports/Birmingham'; diff --git a/t/app/controller/alert_new.t b/t/app/controller/alert_new.t index 27371e4a9..f77114d86 100644 --- a/t/app/controller/alert_new.t +++ b/t/app/controller/alert_new.t @@ -184,13 +184,15 @@ foreach my $test ( }; } +my $body = $mech->create_body_ok(2651, 'Edinburgh Council'); + foreach my $test ( { desc => 'logged in user signing up', email => 'test-sign-in@example.com', type => 'council', - param1 => 2651, - param2 => 2651, + param1 => $body->id, + param2 => $body->id, confirmed => 1, } ) @@ -207,9 +209,9 @@ foreach my $test ( ALLOWED_COBRANDS => [ { 'fixmystreet' => '.' } ], MAPIT_URL => 'http://mapit.uk/', }, sub { - $mech->get_ok('/alert/list?pc=EH991SP'); + $mech->get_ok('/alert/list?pc=EH11BB'); }; - $mech->set_visible( [ radio => 'council:2651:City_of_Edinburgh' ] ); + $mech->set_visible( [ radio => 'council:' . $body->id . ':City_of_Edinburgh' ] ); $mech->click('alert'); my $alert = FixMyStreet::App->model('DB::Alert')->find( @@ -324,11 +326,7 @@ subtest "Test two-tier council alerts" => sub { }; subtest "Test normal alert signups and that alerts are sent" => sub { - $mech->delete_user( 'reporter@example.com' ); - $mech->delete_user( 'alerts@example.com' ); - my $user1 = $mech->create_user_ok('reporter@example.com', name => 'Reporter User' ); - my $user2 = $mech->create_user_ok('alerts@example.com', name => 'Alert User' ); for my $alert ( @@ -368,69 +366,31 @@ subtest "Test normal alert signups and that alerts are sent" => sub { } } - my $dt = DateTime->now(time_zone => 'Europe/London')->add(days => 2); + my $dt = DateTime->now()->add(days => 2); - my $dt_parser = FixMyStreet::App->model('DB')->schema->storage->datetime_parser; - - my $report_time = '2011-03-01 12:00:00'; - my $report = FixMyStreet::App->model('DB::Problem')->find_or_create( { + my ($report) = $mech->create_problems_for_body(1, 1, 'Testing', { + dt => $dt, + user => $user1, postcode => 'EH1 1BB', - bodies_str => '1', areas => ',11808,135007,14419,134935,2651,20728,', category => 'Street lighting', - title => 'Testing', - detail => 'Testing Detail', - used_map => 1, - name => $user1->name, - anonymous => 0, state => 'fixed - user', - 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, + lastupdate => $dt, + whensent => $dt->clone->add( minutes => 5 ), latitude => '55.951963', longitude => '-3.189944', - user_id => $user1->id, - } ); + }); my $report_id = $report->id; ok $report, "created test report - $report_id"; - my $alert = FixMyStreet::App->model('DB::Alert')->create( { - parameter => $report_id, - alert_type => 'new_updates', - user => $user1, - } )->confirm; - ok $alert, 'created alert for reporter'; - - my $update = FixMyStreet::App->model('DB::Comment')->create( { - problem_id => $report_id, - user_id => $user2->id, - name => 'Other User', - mark_fixed => 'false', - text => 'This is some update text', - state => 'confirmed', - confirmed => $dt->clone->add( hours => 7 ), - anonymous => 'f', - } ); - my $update_id = $update->id; - ok $update, "created test update - $update_id"; - - $update = FixMyStreet::App->model('DB::Comment')->create( { - problem_id => $report_id, - user_id => $user2->id, - name => 'Anonymous User', - mark_fixed => 'true', - text => 'This is some more update text', - state => 'confirmed', - confirmed => $dt->clone->add( hours => 8 ), - anonymous => 't', - } ); - $update_id = $update->id; - ok $update, "created test update - $update_id"; + subtest 'check signing up for alerts via report page' => sub { + $mech->log_in_ok($user1->email); + $mech->get_ok("/report/$report_id"); + $mech->submit_form_ok({ button => 'alert', with_fields => { type => 'updates' } }); + }; + + $mech->create_comment_for_problem($report, $user2, 'Other User', 'This is some update text', 'f', 'confirmed', undef, { confirmed => $dt->clone->add( hours => 7 ) }); + $mech->create_comment_for_problem($report, $user2, 'Anonymous User', 'This is some more update text', 't', 'confirmed', 'fixed - user', { confirmed => $dt->clone->add( hours => 8 ) }); FixMyStreet::override_config { MAPIT_URL => 'http://mapit.uk/', @@ -475,66 +435,16 @@ subtest "Test normal alert signups and that alerts are sent" => sub { }; subtest "Test alerts are not sent for no-text updates" => sub { - $mech->delete_user( 'reporter@example.com' ); - $mech->delete_user( 'alerts@example.com' ); - my $user1 = $mech->create_user_ok('reporter@example.com', name => 'Reporter User' ); my $user2 = $mech->create_user_ok('alerts@example.com', name => 'Alert User' ); my $user3 = $mech->create_user_ok('staff@example.com', name => 'Staff User', from_body => $gloucester ); - my $dt = DateTime->now(time_zone => 'Europe/London')->add(days => 2); - - my $dt_parser = FixMyStreet::App->model('DB')->schema->storage->datetime_parser; + my $dt = DateTime->now()->add(days => 2); - my $report_time = '2011-03-01 12:00:00'; - my $report = FixMyStreet::App->model('DB::Problem')->find_or_create( { - postcode => 'EH1 1BB', - bodies_str => '1', - areas => ',11808,135007,14419,134935,2651,20728,', - category => 'Street lighting', - title => 'Testing', - detail => 'Testing Detail', - used_map => 1, - name => $user1->name, - anonymous => 0, - state => 'fixed - user', - 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, - } ); + my ($report, $report2) = $mech->create_problems_for_body(2, 1, 'Testing', { + user => $user1, + }); my $report_id = $report->id; ok $report, "created test report - $report_id"; - - my $report2 = FixMyStreet::App->model('DB::Problem')->create( { - postcode => 'EH1 1BB', - bodies_str => '1', - areas => ',11808,135007,14419,134935,2651,20728,', - category => 'Street lighting', - title => 'Testing', - detail => 'Testing Detail', - used_map => 1, - name => $user1->name, - anonymous => 0, - state => 'fixed - user', - 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, - } ); my $report2_id = $report2->id; ok $report2, "created test report - $report2_id"; @@ -553,31 +463,8 @@ subtest "Test alerts are not sent for no-text updates" => sub { } )->confirm; ok $alert, 'created alert for other user'; - my $update = FixMyStreet::App->model('DB::Comment')->create( { - problem_id => $report_id, - user_id => $user3->id, - name => 'Staff User', - mark_fixed => 'false', - text => '', - state => 'confirmed', - confirmed => $dt->clone->add( hours => 9 ), - anonymous => 'f', - } ); - my $update_id = $update->id; - ok $update, "created test update from staff user - $update_id"; - - my $update2 = FixMyStreet::App->model('DB::Comment')->create( { - problem_id => $report2_id, - user_id => $user3->id, - name => 'Staff User', - mark_fixed => 'false', - text => 'This is a normal update', - state => 'confirmed', - confirmed => $dt->clone->add( hours => 9 ), - anonymous => 'f', - } ); - my $update2_id = $update2->id; - ok $update2, "created test update from staff user - $update2_id"; + $mech->create_comment_for_problem($report, $user3, 'Staff User', '', 'f', 'confirmed', undef, { confirmed => $dt->clone->add( hours => 9 ) }); + $mech->create_comment_for_problem($report2, $user3, 'Staff User', 'This is a normal update', 'f', 'confirmed', undef, { confirmed => $dt->clone->add( hours => 9 ) }); $mech->clear_emails_ok; FixMyStreet::override_config { @@ -594,40 +481,14 @@ subtest "Test alerts are not sent for no-text updates" => sub { }; subtest "Test no marked as confirmed added to alerts" => sub { - $mech->delete_user( 'reporter@example.com' ); - $mech->delete_user( 'alerts@example.com' ); - my $user1 = $mech->create_user_ok('reporter@example.com', name => 'Reporter User' ); my $user2 = $mech->create_user_ok('alerts@example.com', name => 'Alert User' ); my $user3 = $mech->create_user_ok('staff@example.com', name => 'Staff User', from_body => $gloucester ); - my $dt = DateTime->now(time_zone => 'Europe/London')->add(days => 2); - - my $dt_parser = FixMyStreet::App->model('DB')->schema->storage->datetime_parser; + my $dt = DateTime->now()->add(days => 2); - my $report_time = '2011-03-01 12:00:00'; - my $report = FixMyStreet::App->model('DB::Problem')->find_or_create( { - postcode => 'EH1 1BB', - bodies_str => '1', - areas => ',11808,135007,14419,134935,2651,20728,', - category => 'Street lighting', - title => 'Testing', - 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, - } ); + my ($report) = $mech->create_problems_for_body(1, 1, 'Testing', { + user => $user1, + }); my $report_id = $report->id; ok $report, "created test report - $report_id"; @@ -638,19 +499,7 @@ subtest "Test no marked as confirmed added to alerts" => sub { } )->confirm; ok $alert, 'created alert for other user'; - my $update = FixMyStreet::App->model('DB::Comment')->create( { - problem_id => $report_id, - user_id => $user3->id, - name => 'Staff User', - mark_fixed => 'false', - text => 'this is update', - state => 'confirmed', - problem_state => 'confirmed', - confirmed => $dt->clone->add( hours => 9 ), - anonymous => 'f', - } ); - my $update_id = $update->id; - ok $update, "created test update from staff user - $update_id"; + $mech->create_comment_for_problem($report, $user3, 'Staff User', 'this is update', 'f', 'confirmed', 'confirmed', { confirmed => $dt->clone->add( hours => 9 ) }); $mech->clear_emails_ok; FixMyStreet::override_config { @@ -692,40 +541,14 @@ for my $test ( }, ) { subtest $test->{desc} => sub { - $mech->delete_user( 'reporter@example.com' ); - $mech->delete_user( 'alerts@example.com' ); - my $user1 = $mech->create_user_ok('reporter@example.com', name => 'Reporter User' ); my $user2 = $mech->create_user_ok('alerts@example.com', name => 'Alert User' ); my $user3 = $mech->create_user_ok('staff@example.com', name => 'Staff User', from_body => $gloucester ); - my $dt = DateTime->now(time_zone => 'Europe/London')->add(days => 2); + my $dt = DateTime->now()->add(days => 2); - my $dt_parser = FixMyStreet::App->model('DB')->schema->storage->datetime_parser; - - my $report_time = '2011-03-01 12:00:00'; - my $report = FixMyStreet::App->model('DB::Problem')->find_or_create( { - postcode => 'EH1 1BB', - bodies_str => '1', - areas => ',11808,135007,14419,134935,2651,20728,', - category => 'Street lighting', - title => 'Testing', - 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, - } ); + my ($report) = $mech->create_problems_for_body(1, 1, 'Testing', { + user => $user1, + }); my $report_id = $report->id; ok $report, "created test report - $report_id"; @@ -736,19 +559,7 @@ for my $test ( } )->confirm; ok $alert, 'created alert for other user'; - my $update = FixMyStreet::App->model('DB::Comment')->create( { - problem_id => $report_id, - user_id => $user3->id, - name => 'Staff User', - mark_fixed => 'false', - text => $test->{update_text}, - problem_state => $test->{problem_state}, - state => 'confirmed', - confirmed => $dt->clone->add( hours => 9 ), - anonymous => 'f', - } ); - my $update_id = $update->id; - ok $update, "created test update from staff user - $update_id"; + $mech->create_comment_for_problem($report, $user3, 'Staff User', $test->{update_text}, 'f', 'confirmed', $test->{problem_state}, { confirmed => $dt->clone->add( hours => 9 ) }); $mech->clear_emails_ok; FixMyStreet::override_config { @@ -775,41 +586,14 @@ for my $test ( } subtest "Test signature template is used from cobrand" => sub { - $mech->delete_user( 'reporter@example.com' ); - $mech->delete_user( 'alerts@example.com' ); - my $user1 = $mech->create_user_ok('reporter@example.com', name => 'Reporter User' ); - my $user2 = $mech->create_user_ok('alerts@example.com', name => 'Alert User' ); - my $dt = DateTime->now(time_zone => 'Europe/London')->add(days => 2); + my $dt = DateTime->now()->add(days => 2); - my $dt_parser = FixMyStreet::App->model('DB')->schema->storage->datetime_parser; - - my $report_time = '2011-03-01 12:00:00'; - my $report = FixMyStreet::App->model('DB::Problem')->find_or_create( { - postcode => 'EH1 1BB', - bodies_str => '2651', - areas => ',11808,135007,14419,134935,2651,20728,', - category => 'Street lighting', - title => 'Testing', - detail => 'Testing Detail', - used_map => 1, - name => $user1->name, - anonymous => 0, - state => 'fixed - user', - 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, - } ); + my ($report) = $mech->create_problems_for_body(1, $body->id, 'Testing', { + user => $user1, + }); my $report_id = $report->id; ok $report, "created test report - $report_id"; @@ -822,19 +606,7 @@ subtest "Test signature template is used from cobrand" => sub { my $ret = $alert->confirm; ok $ret, 'created alert for reporter'; - my $update = FixMyStreet::App->model('DB::Comment')->create( { - problem_id => $report_id, - user_id => $user2->id, - name => 'Other User', - mark_fixed => 'false', - text => 'This is some update text', - state => 'confirmed', - confirmed => $dt->clone->add( hours => 7 ), - anonymous => 'f', - } ); - my $update_id = $update->id; - ok $update, "created test update - $update_id"; - + $mech->create_comment_for_problem($report, $user2, 'Other User', 'This is some update text', 'f', 'confirmed', undef, { confirmed => $dt->clone->add( hours => 7 ) }); $mech->clear_emails_ok; FixMyStreet::override_config { @@ -848,18 +620,7 @@ subtest "Test signature template is used from cobrand" => sub { like $email, qr/All the best/, 'default signature used'; unlike $email, qr/twitter.com/, 'nothing from fixmystreet signature'; - $update = FixMyStreet::App->model('DB::Comment')->create( { - problem_id => $report_id, - user_id => $user2->id, - name => 'Anonymous User', - mark_fixed => 'true', - text => 'This is some more update text', - state => 'confirmed', - confirmed => $dt->clone->add( hours => 8 ), - anonymous => 't', - } ); - $update_id = $update->id; - ok $update, "created test update - $update_id"; + $mech->create_comment_for_problem($report, $user2, 'Anonymous User', 'This is some more update text', 't', 'confirmed', 'fixed - user', { confirmed => $dt->clone->add( hours => 8 ) }); $alert->cobrand('fixmystreet'); $alert->update; @@ -884,15 +645,15 @@ for my $test ( desc => 'check non public reports are not included in council problems alerts', alert_params => { alert_type => 'council_problems', - parameter => '2651', - parameter2 => '2651', + parameter => $body->id, + parameter2 => $body->id, } }, { desc => 'check non public reports are not included in ward problems alerts', alert_params => { alert_type => 'ward_problems', - parameter => '2651', + parameter => $body->id, parameter2 => '20728', } }, @@ -914,14 +675,10 @@ for my $test ( }, ) { subtest $test->{desc} => sub { - $mech->delete_user( 'reporter@example.com' ); - $mech->delete_user( 'alerts@example.com' ); - my $user1 = $mech->create_user_ok('reporter@example.com', name => 'Reporter User'); - my $user2 = $mech->create_user_ok('alerts@example.com', name => 'Alert User'); - my $dt = DateTime->now->add( minutes => -30 ); + my $dt = DateTime->now()->add( minutes => -30 ); my $r_dt = $dt->clone->add( minutes => 20 ); my $alert_params = $test->{alert_params}; @@ -932,32 +689,15 @@ for my $test ( my $alert_user1 = FixMyStreet::App->model('DB::Alert')->create( $alert_params ); ok $alert_user1, "alert created"; - my $dt_parser = FixMyStreet::App->model('DB')->schema->storage->datetime_parser; - - my $report = FixMyStreet::App->model('DB::Problem')->find_or_create( { - postcode => 'EH1 1BB', - bodies_str => '2651', + my ($report) = $mech->create_problems_for_body(1, $body->id, 'Testing', { areas => ',11808,135007,14419,134935,2651,20728,', - category => 'Street lighting', title => 'Alert test for non public reports', - detail => 'Testing Detail', - used_map => 1, - name => $user2->name, - anonymous => 0, - state => 'confirmed', - confirmed => $dt_parser->format_datetime($r_dt), - lastupdate => $dt_parser->format_datetime($r_dt), - whensent => $dt_parser->format_datetime($r_dt->clone->add( minutes => 5 )), - lang => 'en-gb', - service => '', - cobrand => 'default', - cobrand_data => '', - send_questionnaire => 1, + confirmed => $r_dt, # Needed so timezone set right latitude => '55.951963', longitude => '-3.189944', - user_id => $user2->id, + user => $user2, non_public => 1, - } ); + }); $mech->clear_emails_ok; FixMyStreet::override_config { @@ -982,55 +722,19 @@ for my $test ( } subtest 'check new updates alerts for non public reports only go to report owner' => sub { - $mech->delete_user( 'reporter@example.com' ); - $mech->delete_user( 'alerts@example.com' ); - my $user1 = $mech->create_user_ok('reporter@example.com', name => 'Reporter User'); - my $user2 = $mech->create_user_ok('alerts@example.com', name => 'Alert User'); - my $user3 = $mech->create_user_ok('updates@example.com', name => 'Update User'); my $dt = DateTime->now->add( minutes => -30 ); my $r_dt = $dt->clone->add( minutes => 20 ); - my $dt_parser = FixMyStreet::App->model('DB')->schema->storage->datetime_parser; + my ($report) = $mech->create_problems_for_body(1, $body->id, 'Testing', { + user => $user2, + non_public => 1, + }); - my $report = FixMyStreet::App->model('DB::Problem')->find_or_create( { - postcode => 'EH1 1BB', - bodies_str => '2651', - areas => ',11808,135007,14419,134935,2651,20728,', - category => 'Street lighting', - title => 'Alert test for non public reports', - detail => 'Testing Detail', - used_map => 1, - name => $user2->name, - anonymous => 0, - state => 'confirmed', - confirmed => $dt_parser->format_datetime($r_dt), - lastupdate => $dt_parser->format_datetime($r_dt), - whensent => $dt_parser->format_datetime($r_dt->clone->add( minutes => 5 )), - lang => 'en-gb', - service => '', - cobrand => 'default', - cobrand_data => '', - send_questionnaire => 1, - latitude => '55.951963', - longitude => '-3.189944', - user_id => $user2->id, - non_public => 1, - } ); - - my $update = FixMyStreet::App->model('DB::Comment')->create( { - problem_id => $report->id, - user_id => $user3->id, - name => 'Anonymous User', - mark_fixed => 'false', - text => 'This is some more update text', - state => 'confirmed', - confirmed => $r_dt->clone->add( minutes => 8 ), - anonymous => 't', - } ); + $mech->create_comment_for_problem($report, $user3, 'Anonymous User', 'This is some more update text', 't', 'confirmed', undef, { confirmed => $r_dt->clone->add( minutes => 8 ) }); my $alert_user1 = FixMyStreet::App->model('DB::Alert')->create( { user => $user1, @@ -1041,7 +745,6 @@ subtest 'check new updates alerts for non public reports only go to report owner } ); ok $alert_user1, "alert created"; - $mech->clear_emails_ok; FixMyStreet::App->model('DB::AlertType')->email_alerts(); $mech->email_count_is(0); @@ -1070,59 +773,24 @@ subtest 'check new updates alerts for non public reports only go to report owner $mech->delete_user( $user3 ); }; -subtest 'check setting inlude dates in new updates cobrand option' => sub { +subtest 'check setting include dates in new updates cobrand option' => sub { my $include_date_in_alert_override= Sub::Override->new( "FixMyStreet::Cobrand::Default::include_time_in_update_alerts", sub { return 1; } ); - $mech->delete_user( 'reporter@example.com' ); - $mech->delete_user( 'alerts@example.com' ); my $user1 = $mech->create_user_ok('reporter@example.com', name => 'Reporter User'); - my $user2 = $mech->create_user_ok('alerts@example.com', name => 'Alert User'); - my $user3 = $mech->create_user_ok('updates@example.com', name => 'Update User'); my $dt = DateTime->now->add( minutes => -30 ); my $r_dt = $dt->clone->add( minutes => 20 ); - my $dt_parser = FixMyStreet::App->model('DB')->schema->storage->datetime_parser; - - my $report = FixMyStreet::App->model('DB::Problem')->find_or_create( { - postcode => 'EH1 1BB', - bodies_str => '2651', - areas => ',11808,135007,14419,134935,2651,20728,', - category => 'Street lighting', - title => 'Alert test for non public reports', - detail => 'Testing Detail', - used_map => 1, - name => $user2->name, - anonymous => 0, - state => 'confirmed', - confirmed => $dt_parser->format_datetime($r_dt), - lastupdate => $dt_parser->format_datetime($r_dt), - whensent => $dt_parser->format_datetime($r_dt->clone->add( minutes => 5 )), - lang => 'en-gb', - service => '', - cobrand => 'default', - cobrand_data => '', - send_questionnaire => 1, - latitude => '55.951963', - longitude => '-3.189944', - user_id => $user2->id, - } ); + my ($report) = $mech->create_problems_for_body(1, $body->id, 'Testing', { + user => $user2, + }); - my $update = FixMyStreet::App->model('DB::Comment')->create( { - problem_id => $report->id, - user_id => $user3->id, - name => 'Anonymous User', - mark_fixed => 'false', - text => 'This is some more update text', - state => 'confirmed', - confirmed => $r_dt->clone->add( minutes => 8 ), - anonymous => 't', - } ); + my $update = $mech->create_comment_for_problem($report, $user3, 'Anonymous User', 'This is some more update text', 't', 'confirmed', undef, { confirmed => $r_dt }); my $alert_user1 = FixMyStreet::App->model('DB::Alert')->create( { user => $user1, @@ -1137,13 +805,6 @@ subtest 'check setting inlude dates in new updates cobrand option' => sub { $mech->clear_emails_ok; FixMyStreet::App->model('DB::AlertType')->email_alerts(); - # if we don't do this then we're applying the date inflation code and - # it's timezone munging to the DateTime object above and not the DateTime - # object that's inflated from the database value and these turn out to be - # different as the one above has a UTC timezone and not the floating one - # that those from the DB do. - $update->discard_changes(); - my $date_in_alert = Utils::prettify_dt( $update->confirmed ); my $email = $mech->get_text_body_from_email; like $email, qr/$date_in_alert/, 'alert contains date'; diff --git a/t/app/controller/around.t b/t/app/controller/around.t index 8eaba6450..b123692fa 100644 --- a/t/app/controller/around.t +++ b/t/app/controller/around.t @@ -1,3 +1,13 @@ +package FixMyStreet::Map::Tester; +use base 'FixMyStreet::Map::FMS'; + +use constant ZOOM_LEVELS => 99; +use constant MIN_ZOOM_LEVEL => 88; + +1; + +package main; + use Test::MockModule; use FixMyStreet::TestMech; @@ -8,28 +18,6 @@ subtest "check that if no query we get sent back to the homepage" => sub { is $mech->uri->path, '/', "redirected to '/'"; }; -# x,y requests were generated by the old map code. We keep the behavior for -# historic links -subtest "redirect x,y requests to lat/lon (301 - permanent)" => sub { - - FixMyStreet::override_config { - MAPIT_URL => 'http://mapit.uk/', - }, sub { - $mech->get_ok('/around?x=3281&y=1113'); - }; - - # did we redirect to lat,lon? - is $mech->uri->path, '/around', "still on /around"; - is_deeply { $mech->uri->query_form }, - { lat => 51.499825, lon => -0.140137, zoom => 3 }, - "lat,lon correctly set"; - - # was it a 301? - is $mech->res->code, 200, "got 200 for final destination"; - is $mech->res->previous->code, 301, "got 301 for redirect"; - -}; - # test various locations on inital search box foreach my $test ( { @@ -94,7 +82,10 @@ foreach my $test ( }; } -my @edinburgh_problems = $mech->create_problems_for_body( 5, 2651, 'Around page', { +my $body_edin_id = $mech->create_body_ok(2651, 'City of Edinburgh Council')->id; +my $body_west_id = $mech->create_body_ok(2504, 'Westminster City Council')->id; + +my @edinburgh_problems = $mech->create_problems_for_body( 5, $body_edin_id, 'Around page', { postcode => 'EH1 1BB', latitude => 55.9519637512, longitude => -3.17492254484, @@ -118,7 +109,7 @@ subtest 'check non public reports are not displayed on around page' => sub { $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB' } }, "good location" ); }; - $mech->content_contains( 'Around page Test 3 for 2651', + $mech->content_contains( "Around page Test 3 for $body_edin_id", 'problem to be marked non public visible' ); my $private = $edinburgh_problems[2]; @@ -132,14 +123,82 @@ subtest 'check non public reports are not displayed on around page' => sub { $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB' } }, "good location" ); }; - $mech->content_lacks( 'Around page Test 3 for 2651', + $mech->content_lacks( "Around page Test 3 for $body_edin_id", 'problem marked non public is not visible' ); }; +for my $permission ( qw/ report_inspect report_mark_private/ ) { + subtest 'check non public reports are displayed on around page with $permission permission' => sub { + my $body = FixMyStreet::DB->resultset('Body')->find( $body_edin_id ); + my $body2 = FixMyStreet::DB->resultset('Body')->find( $body_west_id ); + my $user = $mech->log_in_ok( 'test@example.com' ); + $user->user_body_permissions->delete(); + $user->update({ from_body => $body }); + $user->user_body_permissions->find_or_create({ + body => $body, + permission_type => $permission, + }); -subtest 'check category, status and extra filtering works on /around' => sub { - my $body = $mech->create_body_ok(2237, "Oxfordshire"); + $mech->get_ok('/'); + FixMyStreet::override_config { + ALLOWED_COBRANDS => [ { 'fixmystreet' => '.' } ], + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB' } }, + "good location" ); + }; + $mech->content_contains( "Around page Test 3 for $body_edin_id", + 'problem marked non public is visible' ); + $mech->content_contains( "Around page Test 2 for $body_edin_id", + 'problem marked public is visible' ); + FixMyStreet::override_config { + ALLOWED_COBRANDS => [ { 'fixmystreet' => '.' } ], + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $mech->get_ok('/around?pc=EH1+1BB&status=non_public'); + }; + $mech->content_contains( "Around page Test 3 for $body_edin_id", + 'problem marked non public is visible' ); + $mech->content_lacks( "Around page Test 2 for $body_edin_id", + 'problem marked public is not visible' ); + + $user->user_body_permissions->delete(); + $user->update({ from_body => $body2 }); + $user->user_body_permissions->find_or_create({ + body => $body2, + permission_type => $permission, + }); + + $mech->get_ok('/'); + FixMyStreet::override_config { + ALLOWED_COBRANDS => [ { 'fixmystreet' => '.' } ], + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB' } }, + "good location" ); + }; + $mech->content_lacks( "Around page Test 3 for $body_edin_id", + 'problem marked non public is not visible' ); + $mech->content_contains( "Around page Test 2 for $body_edin_id", + 'problem marked public is visible' ); + + FixMyStreet::override_config { + ALLOWED_COBRANDS => [ { 'fixmystreet' => '.' } ], + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $mech->get_ok('/around?pc=EH1+1BB&status=non_public'); + }; + $mech->content_lacks( "Around page Test 3 for $body_edin_id", + 'problem marked non public is not visible' ); + $mech->content_lacks( "Around page Test 2 for $body_edin_id", + 'problem marked public is visible' ); + }; +} + +my $body = $mech->create_body_ok(2237, "Oxfordshire"); + +subtest 'check category, status and extra filtering works on /around' => sub { my $categories = [ 'Pothole', 'Vegetation', 'Flytipping' ]; my $params = { postcode => 'OX20 1SZ', @@ -152,7 +211,7 @@ subtest 'check category, status and extra filtering works on /around' => sub { # Create one open and one fixed report in each category foreach my $category ( @$categories ) { $mech->create_contact_ok( category => $category, body_id => $body->id, email => "$category\@example.org" ); - foreach my $state ( 'confirmed', 'fixed' ) { + foreach my $state ( 'confirmed', 'fixed - user', 'fixed - council' ) { my %report_params = ( %$params, category => $category, @@ -165,10 +224,11 @@ subtest 'check category, status and extra filtering works on /around' => sub { my $json = $mech->get_ok_json( '/around?ajax=1&bbox=' . $bbox ); my $pins = $json->{pins}; - is scalar @$pins, 6, 'correct number of reports when no filters'; + is scalar @$pins, 9, 'correct number of reports when no filters'; # Regression test for filter_category in /around URL FixMyStreet::override_config { + ALLOWED_COBRANDS => 'fixmystreet', MAPIT_URL => 'http://mapit.uk/', }, sub { $mech->get_ok( '/around?filter_category=Pothole&bbox=' . $bbox ); @@ -177,7 +237,7 @@ subtest 'check category, status and extra filtering works on /around' => sub { $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'; + is scalar @$pins, 3, 'correct number of Pothole reports'; $json = $mech->get_ok_json( '/around?ajax=1&status=open&bbox=' . $bbox ); $pins = $json->{pins}; @@ -185,16 +245,86 @@ subtest 'check category, status and extra filtering works on /around' => sub { $json = $mech->get_ok_json( '/around?ajax=1&status=fixed&filter_category=Vegetation&bbox=' . $bbox ); $pins = $json->{pins}; - is scalar @$pins, 1, 'correct number of fixed Vegetation reports'; + is scalar @$pins, 2, 'correct number of fixed Vegetation reports'; my $cobrand = Test::MockModule->new('FixMyStreet::Cobrand::Default'); - $cobrand->mock('display_location_extra_params', sub { { external_body => "Pothole-fixed" } }); + $cobrand->mock('display_location_extra_params', sub { { external_body => "Pothole-confirmed" } }); $json = $mech->get_ok_json( '/around?ajax=1&bbox=' . $bbox ); $pins = $json->{pins}; is scalar @$pins, 1, 'correct number of external_body reports'; }; +subtest 'check old problems not shown by default on around page' => sub { + my $params = { + postcode => 'OX20 1SZ', + latitude => 51.754926, + longitude => -1.256179, + }; + my $bbox = ($params->{longitude} - 0.01) . ',' . ($params->{latitude} - 0.01) + . ',' . ($params->{longitude} + 0.01) . ',' . ($params->{latitude} + 0.01); + + my $json = $mech->get_ok_json( '/around?ajax=1&bbox=' . $bbox ); + my $pins = $json->{pins}; + is scalar @$pins, 9, 'correct number of reports when no age'; + + my $problems = FixMyStreet::App->model('DB::Problem')->to_body( $body->id ); + $problems->first->update( { confirmed => \"current_timestamp-'7 months'::interval" } ); + + $json = $mech->get_ok_json( '/around?ajax=1&bbox=' . $bbox ); + $pins = $json->{pins}; + is scalar @$pins, 8, 'correct number of reports with old report'; + + $json = $mech->get_ok_json( '/around?show_old_reports=1&ajax=1&bbox=' . $bbox ); + $pins = $json->{pins}; + is scalar @$pins, 9, 'correct number of reports with show_old_reports'; + + $problems->update( { confirmed => \"current_timestamp" } ); +}; + +subtest 'check sorting by update uses lastupdate to determine age' => sub { + my $params = { + postcode => 'OX20 1SZ', + latitude => 51.754926, + longitude => -1.256179, + }; + my $bbox = ($params->{longitude} - 0.01) . ',' . ($params->{latitude} - 0.01) + . ',' . ($params->{longitude} + 0.01) . ',' . ($params->{latitude} + 0.01); + + my $problems = FixMyStreet::App->model('DB::Problem')->to_body( $body->id ); + $problems->first->update( { confirmed => \"current_timestamp-'7 months'::interval" } ); + + my $json = $mech->get_ok_json( '/around?ajax=1&bbox=' . $bbox ); + my $pins = $json->{pins}; + is scalar @$pins, 8, 'correct number of reports with default sorting'; + + + $json = $mech->get_ok_json( '/around?ajax=1&sort=updated-desc&bbox=' . $bbox ); + $pins = $json->{pins}; + is scalar @$pins, 9, 'correct number of reports with updated sort'; + + $problems->update( { confirmed => \"current_timestamp" } ); +}; + +subtest 'check show old reports checkbox shown on around page' => sub { + FixMyStreet::override_config { + ALLOWED_COBRANDS => [ { fixmystreet => '.' } ], + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $mech->get_ok( '/around?pc=OX20+1SZ' ); + $mech->content_contains('id="show_old_reports_wrapper" class="report-list-filters hidden"'); + + my $problems = FixMyStreet::App->model('DB::Problem')->to_body( $body->id ); + $problems->first->update( { confirmed => \"current_timestamp-'7 months'::interval" } ); + + $mech->get_ok( '/around?pc=OX20+1SZ&status=all' ); + $mech->content_lacks('id="show_old_reports_wrapper" class="report-list-filters hidden"'); + $mech->content_contains('id="show_old_reports_wrapper" class="report-list-filters"'); + + $problems->update( { confirmed => \"current_timestamp" } ); + }; +}; + subtest 'check skip_around skips around page' => sub { my $cobrand = Test::MockModule->new('FixMyStreet::Cobrand::Default'); $cobrand->mock('skip_around_page', sub { 1 }); @@ -202,11 +332,41 @@ subtest 'check skip_around skips around page' => sub { FixMyStreet::override_config { MAPIT_URL => 'http://mapit.uk/', + MAPIT_TYPES => ['CTY', 'DIS'], }, sub { $mech->get('/around?latitude=51.754926&longitude=-1.256179'); - is $mech->res->code, 302, "around page is a redirect"; + is $mech->res->previous->code, 302, "around page is a redirect"; is $mech->uri->path, '/report/new', "and redirects to /report/new"; }; }; +subtest 'check map zoom level customisation' => sub { + FixMyStreet::override_config { + ALLOWED_COBRANDS => 'fixmystreet', + MAPIT_URL => 'http://mapit.uk/', + MAP_TYPE => 'OSM', + }, sub { + $mech->get('/around?latitude=51.754926&longitude=-1.256179'); + $mech->content_contains('data-numZoomLevels=6'); + $mech->content_contains('data-zoomOffset=13'); + }; + + + FixMyStreet::override_config { + ALLOWED_COBRANDS => 'fixmystreet', + MAPIT_URL => 'http://mapit.uk/', + MAP_TYPE => 'Tester', + }, sub { + $mech->get('/around?latitude=51.754926&longitude=-1.256179'); + $mech->content_contains('data-numZoomLevels=99'); + $mech->content_contains('data-zoomOffset=88'); + }; +}; + +subtest 'check nearby lookup' => sub { + my $p = FixMyStreet::DB->resultset("Problem")->search({ external_body => "Pothole-confirmed" })->first; + $mech->get_ok('/around/nearby?latitude=51.754926&longitude=-1.256179&filter_category=Pothole'); + $mech->content_contains('["51.754926","-1.256179","yellow",' . $p->id . ',"Around page Test 1 for ' . $body->id . '","small",false]'); +}; + done_testing(); diff --git a/t/app/controller/auth.t b/t/app/controller/auth.t index 8cc7e4154..ffabc75f3 100644 --- a/t/app/controller/auth.t +++ b/t/app/controller/auth.t @@ -100,33 +100,6 @@ $mech->not_logged_in_ok; $mech->log_out_ok; } -foreach my $remember_me ( '1', '0' ) { - subtest "sign in using valid details (remember_me => '$remember_me')" => sub { - $mech->get_ok('/auth'); - $mech->submit_form_ok( - { - form_name => 'general_auth', - fields => { - username => $test_email, - password_sign_in => $test_password, - remember_me => ( $remember_me ? 1 : undef ), - }, - button => 'sign_in_by_password', - }, - "sign in with '$test_email' & '$test_password'" - ); - is $mech->uri->path, '/my', "redirected to correct page"; - - my $expiry = $mech->session_cookie_expiry; - $remember_me - ? cmp_ok( $expiry, '>', 86400, "long expiry time" ) - : is( $expiry, 0, "no expiry time" ); - - # logout - $mech->log_out_ok; - }; -} - # try to sign in with bad details $mech->get_ok('/auth'); $mech->submit_form_ok( @@ -278,7 +251,7 @@ subtest "check logging in with token" => sub { }; subtest 'check password length/common' => sub { - $mech->get_ok('/auth'); + $mech->get_ok('/auth/create'); $mech->submit_form_ok({ form_name => 'general_auth', fields => { username => $test_email, password_register => 'short' }, @@ -300,6 +273,16 @@ subtest 'check common password AJAX call' => sub { $mech->content_contains("true"); }; +subtest 'test forgotten password page' => sub { + $mech->get_ok('/auth/forgot'); + $mech->content_contains('Forgot password'); + $mech->submit_form_ok({ + form_name => 'general_auth', + fields => { username => $test_email, password_register => 'squirblewirble' }, + button => 'sign_in_by_code', + }); +}; + subtest "Test two-factor authentication login" => sub { use Auth::GoogleAuth; my $auth = Auth::GoogleAuth->new; diff --git a/t/app/controller/auth_social.t b/t/app/controller/auth_social.t index 031fb8d9e..ac3d98b15 100644 --- a/t/app/controller/auth_social.t +++ b/t/app/controller/auth_social.t @@ -103,8 +103,8 @@ for my $fb_state ( 'refused', 'no email', 'existing UID', 'okay' ) { # We don't have an email, so check that we can still submit it, # and the ID carries through the confirmation $fields->{username} = $fb_email; - $fields->{name} = 'Ffion Tester'; - $mech->submit_form(with_fields => $fields); + $fields->{name} = 'Ffion Tester' unless $page eq 'my'; + $mech->submit_form(with_fields => $fields, $page eq 'my' ? (button => 'sign_in_by_code') : ()); $mech->content_contains('Nearly done! Now check your email'); my $url = $mech->get_link_from_email; @@ -211,8 +211,8 @@ for my $tw_state ( 'refused', 'existing UID', 'no email' ) { # We don't have an email, so check that we can still submit it, # and the ID carries through the confirmation $fields->{username} = $tw_email; - $fields->{name} = 'Ffion Tester'; - $mech->submit_form(with_fields => $fields); + $fields->{name} = 'Ffion Tester' unless $page eq 'my'; + $mech->submit_form(with_fields => $fields, $page eq 'my' ? (button => 'sign_in_by_code') : ()); $mech->content_contains('Nearly done! Now check your email'); my $url = $mech->get_link_from_email; diff --git a/t/app/controller/contact.t b/t/app/controller/contact.t index 4f255f058..842f27dd5 100644 --- a/t/app/controller/contact.t +++ b/t/app/controller/contact.t @@ -1,8 +1,19 @@ +package FixMyStreet::Cobrand::AbuseOnly; + +use base 'FixMyStreet::Cobrand::Default'; + +sub abuse_reports_only { 1; } + +1; + +package main; + use FixMyStreet::TestMech; my $mech = FixMyStreet::TestMech->new; $mech->get_ok('/contact'); +my ($csrf) = $mech->content =~ /meta content="([^"]*)" name="csrf-token"/; $mech->title_like(qr/Contact Us/); $mech->content_contains("It's often quickest to "); @@ -269,25 +280,16 @@ for my $test ( }; } -for my $test ( - { - fields => { - em => 'test@example.com', - name => 'A name', - subject => 'A subject', - message => 'A message', - }, - }, - { - fields => { - em => 'test@example.com', - name => 'A name', - subject => 'A subject', - message => 'A message', - id => $problem_main->id, - }, - }, +my %common = ( + em => 'test@example.com', + name => 'A name', + subject => 'A subject', + message => 'A message', +); +for my $test ( + { fields => \%common }, + { fields => { %common, id => $problem_main->id } }, ) { subtest 'check email sent correctly' => sub { @@ -305,11 +307,11 @@ for my $test ( my $email = $mech->get_email; - is $email->header('Subject'), 'FMS message: ' . $test->{fields}->{subject}, 'subject'; + is $email->header('Subject'), 'FixMyStreet message: ' . $test->{fields}->{subject}, 'subject'; is $email->header('From'), "\"$test->{fields}->{name}\" <$test->{fields}->{em}>", 'from'; my $body = $mech->get_text_body_from_email($email); like $body, qr/$test->{fields}->{message}/, 'body'; - like $body, qr/Sent by contact.cgi on \S+. IP address (?:\d{1,3}\.){3,}\d{1,3}/, 'body footer'; + like $body, qr/Sent by contact form on \S+.\s+IP address (?:\d{1,3}\.){3,}\d{1,3}, user agent ./, 'body footer'; my $problem_id = $test->{fields}{id}; like $body, qr/Complaint about report $problem_id/, 'reporting a report' if $test->{fields}{id}; @@ -326,39 +328,22 @@ for my $test ( for my $test ( { - fields => { - em => 'test@example.com', - name => 'A name', - subject => 'A subject', - message => 'A message', - dest => undef, - }, + fields => { %common, dest => undef }, page_errors => [ 'There were problems with your report. Please see below.', 'Please enter who your message is for', + 'You can only contact the team behind FixMyStreet using our contact form', # The JS-hidden one ] }, { - fields => { - em => 'test@example.com', - name => 'A name', - subject => 'A subject', - message => 'A message', - dest => 'council', - }, + fields => { %common, dest => 'council' }, page_errors => [ 'There were problems with your report. Please see below.', 'You can only contact the team behind FixMyStreet using our contact form', ] }, { - fields => { - em => 'test@example.com', - name => 'A name', - subject => 'A subject', - message => 'A message', - dest => 'update', - }, + fields => { %common, dest => 'update' }, page_errors => [ 'There were problems with your report. Please see below.', 'You can only contact the team behind FixMyStreet using our contact form', @@ -381,44 +366,21 @@ for my $test ( $test->{fields}->{'extra.phone'} = ''; is_deeply $mech->visible_form_values, $test->{fields}, 'form values'; + # Ugh, but checking div not hidden; text always shown and hidden with CSS if ( $test->{fields}->{dest} and $test->{fields}->{dest} eq 'update' ) { - $mech->content_contains( 'www.writetothem.com', 'includes link to WTT if trying to update report' ); + $mech->content_contains('<div class="form-error__box form-error--update">'); } elsif ( $test->{fields}->{dest} and $test->{fields}->{dest} eq 'council' ) { - $mech->content_lacks( 'www.writetothem.com', 'does not include link to WTT if trying to contact council' ); - $mech->content_contains( 'should find contact details', 'mentions checking council website for contact details' ); + # Ugh, but checking div not hidden + $mech->content_contains('<div class="form-error__box form-error--council">'); } } }; } for my $test ( - { - fields => { - em => 'test@example.com', - name => 'A name', - subject => 'A subject', - message => 'A message', - dest => 'help', - }, - }, - { - fields => { - em => 'test@example.com', - name => 'A name', - subject => 'A subject', - message => 'A message', - dest => 'feedback', - }, - }, - { - fields => { - em => 'test@example.com', - name => 'A name', - subject => 'A subject', - message => 'A message', - dest => 'from_council', - }, - }, + { fields => { %common, dest => 'help' } }, + { fields => { %common, dest => 'feedback' } }, + { fields => { %common, dest => 'from_council' } }, ) { subtest 'check email sent correctly with dest field set to us' => sub { @@ -436,24 +398,67 @@ for my $test ( for my $test ( { + fields => { %common, dest => undef }, + page_errors => + [ 'There were problems with your report. Please see below.', + 'Please enter a topic of your message', + 'You can only use this form to report inappropriate content', # The JS-hidden one + ] + }, + { + fields => { %common, dest => 'council' }, + page_errors => + [ 'There were problems with your report. Please see below.', + 'You can only use this form to report inappropriate content', + ] + }, + { + fields => { %common, dest => 'update' }, + page_errors => + [ 'There were problems with your report. Please see below.', + 'You can only use this form to report inappropriate content', + ] + }, + ) +{ + subtest 'check Bucks submit page incorrect destination handling' => sub { + FixMyStreet::override_config { + ALLOWED_COBRANDS => [ 'buckinghamshire' ], + }, sub { + $mech->get_ok( '/contact?id=' . $problem_main->id, 'can visit for abuse report' ); + $mech->submit_form_ok( { with_fields => $test->{fields} } ); + is_deeply $mech->page_errors, $test->{page_errors}, 'page errors'; + + $test->{fields}->{'extra.phone'} = ''; + is_deeply $mech->visible_form_values, $test->{fields}, 'form values'; + + if ( $test->{fields}->{dest} and $test->{fields}->{dest} eq 'update' ) { + $mech->content_contains('please leave an update'); + } elsif ( $test->{fields}->{dest} and $test->{fields}->{dest} eq 'council' ) { + $mech->content_contains('should find other contact details'); + } + } + }; +} + +for my $test ( + { fields => { - em => 'test@example.com', - name => 'A name', - subject => 'A subject', - message => 'A message', + %common, + token => $csrf, dest => 'from_council', success_url => '/faq', + s => "", }, url_should_be => 'http://localhost/faq', }, { fields => { - em => 'test@example.com', - name => 'A name', - subject => 'A subject', - message => 'A message', + %common, + token => $csrf, dest => 'from_council', success_url => 'http://www.example.com', + s => "", }, url_should_be => 'http://www.example.com', }, @@ -469,6 +474,24 @@ for my $test ( }; } +subtest 'check can limit contact to abuse reports' => sub { + FixMyStreet::override_config { + 'ALLOWED_COBRANDS' => [ 'abuseonly' ], + }, sub { + $mech->get( '/contact' ); + is $mech->res->code, 404, 'cannot visit contact page'; + $mech->get_ok( '/contact?id=' . $problem_main->id, 'can visit for abuse report' ); + + my $token = FixMyStreet::App->model("DB::Token")->create({ + scope => 'moderation', + data => { id => $problem_main->id } + }); + + $mech->get_ok( '/contact?m=' . $token->token, 'can visit for moderation complaint' ); + + } +}; + $problem_main->delete; done_testing(); diff --git a/t/app/controller/dashboard.t b/t/app/controller/dashboard.t index b53056968..ff8d1a9d5 100644 --- a/t/app/controller/dashboard.t +++ b/t/app/controller/dashboard.t @@ -1,4 +1,17 @@ use Test::MockTime ':all'; + +package FixMyStreet::Cobrand::Tester; +use parent 'FixMyStreet::Cobrand::Default'; +# Allow access if CSV export for a body, otherwise deny +sub dashboard_permission { + my $self = shift; + my $c = $self->{c}; + return 0 unless $c->get_param('export'); + return $c->get_param('body') || 0; +} + +package main; + use strict; use warnings; @@ -43,9 +56,13 @@ foreach my $problem (@fixed_problems) { $mech->create_comment_for_problem($problem, $counciluser, 'Title', 'text', 0, 'confirmed', 'fixed'); } +my $first_problem_id; +my $first_update_id; foreach my $problem (@closed_problems) { $problem->update({ state => 'closed' }); - $mech->create_comment_for_problem($problem, $counciluser, 'Title', 'text', 0, 'confirmed', 'closed', { confirmed => \'current_timestamp' }); + my ($update) = $mech->create_comment_for_problem($problem, $counciluser, 'Title', 'text', 0, 'confirmed', 'closed', { confirmed => \'current_timestamp' }); + $first_problem_id = $problem->id unless $first_problem_id; + $first_update_id = $update->id unless $first_update_id; } my $categories = scraper { @@ -96,7 +113,7 @@ FixMyStreet::override_config { }; subtest 'area user can only see their area' => sub { - $counciluser->update({area_id => $area_id}); + $counciluser->update({area_ids => [ $area_id ]}); $mech->get_ok("/dashboard"); $mech->content_contains('<h1>Trowbridge</h1>'); @@ -105,7 +122,11 @@ FixMyStreet::override_config { $mech->get_ok("/dashboard?ward=$alt_area_id"); $mech->content_contains('<h1>Trowbridge</h1>'); - $counciluser->update({area_id => undef}); + $counciluser->update({area_ids => [ $area_id, $alt_area_id ]}); + $mech->get_ok("/dashboard"); + $mech->content_contains('<h1>Bradford-on-Avon / Trowbridge</h1>'); + + $counciluser->update({area_ids => undef}); }; subtest 'The correct categories and totals shown by default' => sub { @@ -146,15 +167,10 @@ FixMyStreet::override_config { areas => ",$alt_area_id,2651,", }); $mech->get_ok('/dashboard?export=1'); - open my $data_handle, '<', \$mech->content; - my $csv = Text::CSV->new( { binary => 1 } ); - my @rows; - while ( my $row = $csv->getline( $data_handle ) ) { - push @rows, $row; - } + my @rows = $mech->content_as_csv; is scalar @rows, 19, '1 (header) + 18 (reports) = 19 lines'; - is scalar @{$rows[0]}, 18, '18 columns present'; + is scalar @{$rows[0]}, 20, '20 columns present'; is_deeply $rows[0], [ @@ -176,6 +192,8 @@ FixMyStreet::override_config { 'Easting', 'Northing', 'Report URL', + 'Site Used', + 'Reported As', ], 'Column headers look correct'; @@ -184,6 +202,27 @@ FixMyStreet::override_config { is $rows[5]->[16], '179716', 'Correct Northing conversion'; }; + subtest 'export updates as csv' => sub { + $mech->get_ok('/dashboard?updates=1&export=1'); + my @rows = $mech->content_as_csv; + is scalar @rows, 15, '1 (header) + 14 (updates) = 15 lines'; + is scalar @{$rows[0]}, 8, '8 columns present'; + + is_deeply $rows[0], + [ + 'Report ID', 'Update ID', 'Date', 'Status', 'Problem state', + 'Text', 'User Name', 'Reported As', + ], + 'Column headers look correct'; + + is $rows[1]->[0], $first_problem_id, 'Correct report ID'; + is $rows[1]->[1], $first_update_id, 'Correct update ID'; + is $rows[1]->[3], 'confirmed', 'Correct state'; + is $rows[1]->[4], 'closed', 'Correct problem state'; + is $rows[1]->[5], 'text', 'Correct text'; + is $rows[1]->[6], 'Title', 'Correct name'; + }; + subtest 'export as csv using token' => sub { $mech->log_out_ok; @@ -198,21 +237,37 @@ FixMyStreet::override_config { $mech->get_ok('/dashboard?export=1'); like $mech->res->header('Content-type'), qr'text/csv'; $mech->content_contains('Report ID'); + $mech->delete_header('Authorization'); + }; +}; + +FixMyStreet::override_config { + ALLOWED_COBRANDS => 'tester', + MAPIT_URL => 'http://mapit.uk/', +}, sub { + subtest 'no body or export, 404' => sub { + $mech->get('/dashboard'); + is $mech->status, '404', 'No parameters, 404'; + $mech->get('/dashboard?export=1'); + is $mech->status, '404', 'If no body, 404'; + $mech->get("/dashboard?body=$body_id"); + is $mech->status, '404', 'If no export, 404'; + }; + + subtest 'body and export, okay' => sub { + $mech->get_ok("/dashboard?body=$body_id&export=1"); }; }; sub test_table { my ($content, @expected) = @_; my $res = $categories->scrape( $mech->content ); - my $i = 0; + my @actual; foreach my $row ( @{ $res->{rows} }[1 .. 11] ) { - foreach my $col ( @{ $row->{cols} } ) { - is $col, $expected[$i++]; - } + push @actual, @{$row->{cols}} if $row->{cols}; } + is_deeply \@actual, \@expected; } -END { - restore_time; - done_testing(); -} +restore_time; +done_testing(); diff --git a/t/app/controller/develop.t b/t/app/controller/develop.t index 92aa86721..7fde5ef83 100644 --- a/t/app/controller/develop.t +++ b/t/app/controller/develop.t @@ -1,19 +1,28 @@ use FixMyStreet::TestMech; +FixMyStreet::App->log->disable('info'); +END { FixMyStreet::App->log->enable('info'); } + ok( my $mech = FixMyStreet::TestMech->new, 'Created mech object' ); my ($problem) = $mech->create_problems_for_body(1, 2504, 'title'); my $update = $mech->create_comment_for_problem($problem, $problem->user, 'Name', 'Text', 'f', 'confirmed', 'confirmed'); subtest 'not visible on live site' => sub { - FixMyStreet::override_config { - STAGING_SITE => 0 - }, sub { - $mech->get('/_dev/email/'); - is $mech->res->code, 404; - $mech->get('/_dev/email/login'); - is $mech->res->code, 404; - }; + $mech->get('/_dev/'); + is $mech->res->code, 404; + $mech->get('/_dev/email'); + is $mech->res->code, 404; + $mech->get('/_dev/email/login'); + is $mech->res->code, 404; +}; + +$problem->user->update({ is_superuser => 1 }); +$mech->log_in_ok($problem->user->email); + +subtest 'dev index' => sub { + $mech->get_ok('/_dev/'); + $mech->content_contains('<h1>/_dev</h1>'); }; subtest 'dev email index page' => sub { @@ -30,4 +39,27 @@ subtest 'individual email previews' => sub { $mech->get_ok('/_dev/email/update-confirm?update=' . $update->id); }; +subtest 'problem confirmation page preview' => sub { + $mech->get_ok('/_dev/confirm_problem/' . $problem->id ); +}; + +subtest 'update confirmation page preview' => sub { + $mech->get_ok('/_dev/confirm_update/' . $problem->id); +}; + +subtest 'alert confirmation page preview' => sub { + $mech->get_ok('/_dev/confirm_alert/subscribe'); +}; + +subtest 'contact form submission page preview' => sub { + $mech->get_ok('/_dev/contact_submit/1'); +}; + +subtest 'questionnaire completion page previews' => sub { + $mech->get_ok('/_dev/questionnaire_completed?been_fixed=Yes'); + $mech->get_ok('/_dev/questionnaire_completed?been_fixed=Unknown'); + $mech->get_ok('/_dev/questionnaire_completed?new_state=confirmed'); + $mech->get_ok('/_dev/questionnaire_creator_fixed'); +}; + done_testing(); diff --git a/t/app/controller/index.t b/t/app/controller/index.t index 9be6dfa1e..bd268b3d7 100644 --- a/t/app/controller/index.t +++ b/t/app/controller/index.t @@ -29,15 +29,15 @@ subtest "does pc, (x,y), (e,n) or (lat,lon) go to /around" => sub { }, { in => { lat => 51.50100, lon => -0.14158 }, - out => { lat => 51.50100, lon => -0.14158, zoom => 3 }, + out => { lat => 51.50100, lon => -0.14158 }, }, { in => { x => 3281, y => 1113, }, - out => { lat => 51.499825, lon => -0.140137, zoom => 3 }, + out => { lat => 51.499825, lon => -0.140137 }, }, { in => { e => 1234, n => 4567 }, - out => { lat => 49.808509, lon => -7.544784, zoom => 3 }, + out => { lat => 49.808509, lon => -7.544784 }, }, ) { diff --git a/t/app/controller/moderate.t b/t/app/controller/moderate.t index 4b2f0cfe3..7ef24bbe8 100644 --- a/t/app/controller/moderate.t +++ b/t/app/controller/moderate.t @@ -4,6 +4,12 @@ use parent 'FixMyStreet::Cobrand::Default'; sub send_moderation_notifications { 0 } +package FixMyStreet::Cobrand::TestTitle; + +use parent 'FixMyStreet::Cobrand::Default'; + +sub moderate_permission_title { 0 } + package main; use FixMyStreet::TestMech; @@ -15,6 +21,7 @@ $mech->host('www.example.org'); my $BROMLEY_ID = 2482; my $body = $mech->create_body_ok( $BROMLEY_ID, 'Bromley Council' ); +$mech->create_contact_ok( body => $body, category => 'Lost toys', email => 'losttoys@example.net' ); my $dt = DateTime->now; @@ -43,11 +50,11 @@ sub create_report { latitude => '51.4129', longitude => '0.007831', user_id => $user2->id, - photo => $mech->get_photo_data, + photo => '74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg', + extra => { moon => 'waxing full' }, }); } my $report = create_report(); -my $report2 = create_report(); my $REPORT_URL = '/report/' . $report->id ; @@ -57,6 +64,9 @@ subtest 'Auth' => sub { $mech->get_ok($REPORT_URL); $mech->content_lacks('Moderat'); + $mech->get_ok("$REPORT_URL/moderate"); + $mech->content_lacks('Moderat'); + $mech->log_in_ok( $user->email ); $mech->get_ok($REPORT_URL); @@ -86,7 +96,7 @@ subtest 'Auth' => sub { my %problem_prepopulated = ( problem_show_name => 1, - problem_show_photo => 1, + problem_photo => 1, problem_title => 'Good bad good', problem_detail => 'Good bad bad bad good bad', ); @@ -95,6 +105,9 @@ subtest 'Problem moderation' => sub { subtest 'Post modify title and text' => sub { $mech->get_ok($REPORT_URL); + $mech->content_lacks('show-moderation'); + $mech->follow_link_ok({ text_regex => qr/^Moderate$/ }); + $mech->content_contains('show-moderation'); $mech->submit_form_ok({ with_fields => { %problem_prepopulated, problem_title => 'Good good', @@ -119,6 +132,25 @@ subtest 'Problem moderation' => sub { $report->discard_changes; is $report->title, 'Good bad good'; is $report->detail, 'Good bad bad bad good bad'; + + my @history = $report->moderation_original_datas->search(undef, { order_by => 'id' })->all; + is @history, 2, 'Right number of entries'; + is $history[0]->title, 'Good bad good', 'Correct original title'; + is $history[1]->title, 'Good good', 'Correct second title'; + }; + + subtest 'Post modified title after edited elsewhere' => sub { + $mech->submit_form_ok({ with_fields => { + %problem_prepopulated, + problem_title => 'Good good', + form_started => 1, # January 1970! + }}); + $mech->base_like( qr{\Q/moderate$REPORT_URL\E} ); + $mech->content_contains('Good bad good'); # Displayed title + $mech->content_contains('Good good'); # Form edit + + $report->discard_changes; + is $report->title, 'Good bad good', 'title unchanged'; }; subtest 'Make anonymous' => sub { @@ -146,7 +178,7 @@ subtest 'Problem moderation' => sub { $mech->submit_form_ok({ with_fields => { %problem_prepopulated, - problem_show_photo => 0, + problem_photo => 0, }}); $mech->base_like( qr{\Q$REPORT_URL\E} ); @@ -154,7 +186,7 @@ subtest 'Problem moderation' => sub { $mech->submit_form_ok({ with_fields => { %problem_prepopulated, - problem_show_photo => 1, + problem_photo => 1, }}); $mech->base_like( qr{\Q$REPORT_URL\E} ); @@ -208,34 +240,124 @@ subtest 'Problem moderation' => sub { $report->update({ state => 'confirmed' }); } }; + + subtest 'Try and moderate title when not allowed' => sub { + FixMyStreet::override_config { + ALLOWED_COBRANDS => 'testtitle' + }, sub { + $mech->get_ok($REPORT_URL); + $mech->submit_form_ok({ with_fields => { + problem_show_name => 1, + problem_photo => 1, + problem_detail => 'Changed detail', + }}); + $mech->base_like( qr{\Q$REPORT_URL\E} ); + $mech->content_like(qr/Moderated by Bromley Council/); + + $report->discard_changes; + is $report->title, 'Good bad good'; + is $report->detail, 'Changed detail'; + } + }; + + subtest 'Moderate extra data' => sub { + my ($csrf) = $mech->content =~ /meta content="([^"]*)" name="csrf-token"/; + $mech->post_ok('http://www.example.org/moderate/report/' . $report->id, { + %problem_prepopulated, + 'extra.weather' => 'snow', + 'extra.moon' => 'waning full', + token => $csrf, + }); + $report->discard_changes; + is $report->get_extra_metadata('weather'), 'snow'; + is $report->get_extra_metadata('moon'), 'waning full'; + my $mod = $report->moderation_original_data; + is $mod->get_extra_metadata('moon'), 'waxing full'; + is $mod->get_extra_metadata('weather'), undef; + + my $diff = $mod->extra_diff($report, 'moon'); + is $diff, "wa<del style='background-color:#fcc'>x</del><ins style='background-color:#cfc'>n</ins>ing full", 'Correct diff'; + }; + + subtest 'Moderate category' => sub { + $report->update; + my ($csrf) = $mech->content =~ /meta content="([^"]*)" name="csrf-token"/; + $mech->post_ok('http://www.example.org/moderate/report/' . $report->id, { + %problem_prepopulated, + 'category' => 'Lost toys', + token => $csrf, + }); + $report->discard_changes; + is $report->category, 'Lost toys'; + }; + + subtest 'Moderate state' => sub { + my $mods_count = $report->moderation_original_datas->count; + my ($csrf) = $mech->content =~ /meta content="([^"]*)" name="csrf-token"/; + $mech->post_ok('http://www.example.org/moderate/report/' . $report->id, { + %problem_prepopulated, + state => 'confirmed', + token => $csrf, + }); + $report->discard_changes; + is $report->state, 'confirmed', 'state has not changed'; + is $report->comments->count, 0, 'same state, no update'; + is $report->moderation_original_datas->count, $mods_count, 'No moderation entry either'; + $mech->post_ok('http://www.example.org/moderate/report/' . $report->id, { + %problem_prepopulated, + state => 'in progress', + token => $csrf, + }); + $report->discard_changes; + is $report->state, 'in progress', 'state has changed'; + is $report->comments->count, 1, 'a new update added'; + $report->update({ state => 'confirmed' }); + is $report->moderation_original_datas->count, $mods_count, 'No moderation entry, only state changed'; + }; + + subtest 'Moderate location' => sub { + FixMyStreet::override_config { + MAPIT_URL => 'http://mapit.uk/', + ALLOWED_COBRANDS => 'fixmystreet', + }, sub { + my ($csrf) = $mech->content =~ /meta content="([^"]*)" name="csrf-token"/; + $mech->post_ok('http://www.example.org/moderate/report/' . $report->id, { + %problem_prepopulated, + latitude => '53', + longitude => '0.01578', + token => $csrf, + }); + $report->discard_changes; + is $report->latitude, 51.4129, 'No change when moved out of area'; + $mech->post_ok('http://www.example.org/moderate/report/' . $report->id, { + %problem_prepopulated, + latitude => '51.4021', + longitude => '0.01578', + token => $csrf, + }); + $report->discard_changes; + is $report->latitude, 51.4021, 'Updated when same body'; + }; + }; }; $mech->content_lacks('Posted anonymously', 'sanity check'); +my ($csrf) = $mech->content =~ /meta content="([^"]*)" name="csrf-token"/; -subtest 'Problem 2' => sub { - my $REPORT2_URL = '/report/' . $report2->id ; - $mech->get_ok($REPORT2_URL); - $mech->submit_form_ok({ with_fields => { +subtest 'Edit photos' => sub { + $mech->post_ok('http://www.example.org/moderate/report/' . $report->id, { %problem_prepopulated, - problem_title => 'Good good', - problem_detail => 'Good good improved', - }}); - $mech->base_like( qr{\Q$REPORT2_URL\E} ); - - $report2->discard_changes; - is $report2->title, 'Good good'; - is $report2->detail, 'Good good improved'; - - $mech->submit_form_ok({ with_fields => { + photo1 => 'something-wrong', + token => $csrf, + }); + $mech->post_ok('http://www.example.org/moderate/report/' . $report->id, { %problem_prepopulated, - problem_revert_title => 1, - problem_revert_detail => 1, - }}); - $mech->base_like( qr{\Q$REPORT2_URL\E} ); - - $report2->discard_changes; - is $report2->title, 'Good bad good'; - is $report2->detail, 'Good bad bad bad good bad'; + photo1 => '', + upload_fileid => '', + token => $csrf, + }); + $report->discard_changes; + is $report->photo, undef; }; sub create_update { @@ -243,16 +365,17 @@ sub create_update { user => $user2, name => 'Test User 2', anonymous => 'f', - photo => $mech->get_photo_data, + photo => '74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg', text => 'update good good bad good', state => 'confirmed', mark_fixed => 0, + confirmed => $dt, }); } my %update_prepopulated = ( update_show_name => 1, - update_show_photo => 1, - update_detail => 'update good good bad good', + update_photo => 1, + update_text => 'update good good bad good', ); my $update = create_update(); @@ -261,9 +384,12 @@ subtest 'updates' => sub { subtest 'Update modify text' => sub { $mech->get_ok($REPORT_URL); + $mech->content_lacks('show-moderation'); + $mech->follow_link_ok({ text_regex => qr/^Moderate this update$/ }); + $mech->content_contains('show-moderation'); $mech->submit_form_ok({ with_fields => { %update_prepopulated, - update_detail => 'update good good good', + update_text => 'update good good good', }}) or die $mech->content; $mech->base_like( qr{\Q$REPORT_URL\E} ); @@ -274,12 +400,11 @@ subtest 'updates' => sub { subtest 'Revert text' => sub { $mech->submit_form_ok({ with_fields => { %update_prepopulated, - update_revert_detail => 1, + update_revert_text => 1, }}); $mech->base_like( qr{\Q$REPORT_URL\E} ); $update->discard_changes; - $update->discard_changes; is $update->text, 'update good good bad good', }; @@ -304,6 +429,20 @@ subtest 'updates' => sub { $mech->content_lacks('Posted anonymously'); }; + subtest 'Moderate extra data' => sub { + $update->set_extra_metadata('moon', 'waxing full'); + $update->update; + my ($csrf) = $mech->content =~ /meta content="([^"]*)" name="csrf-token"/; + $mech->post_ok('http://www.example.org/moderate/report/' . $report->id . '/update/' . $update->id, { + %update_prepopulated, + 'extra.weather' => 'snow', + 'extra.moon' => 'waxing full', + token => $csrf, + }); + $update->discard_changes; + is $update->get_extra_metadata('weather'), 'snow'; + }; + subtest 'Hide photo' => sub { $report->update({ photo => undef }); # hide the main photo so we can just look for text in comment @@ -314,7 +453,7 @@ subtest 'updates' => sub { $mech->submit_form_ok({ with_fields => { %update_prepopulated, - update_show_photo => 0, + update_photo => 0, }}); $mech->base_like( qr{\Q$REPORT_URL\E} ); @@ -322,7 +461,7 @@ subtest 'updates' => sub { $mech->submit_form_ok({ with_fields => { %update_prepopulated, - update_show_photo => 1, + update_photo => 1, }}); $mech->base_like( qr{\Q$REPORT_URL\E} ); @@ -348,7 +487,7 @@ subtest 'Update 2' => sub { $mech->get_ok($REPORT_URL); $mech->submit_form_ok({ with_fields => { %update_prepopulated, - update_detail => 'update good good good', + update_text => 'update good good good', }}) or die $mech->content; $update2->discard_changes; @@ -359,6 +498,9 @@ subtest 'Now stop being a staff user' => sub { $user->update({ from_body => undef }); $mech->get_ok($REPORT_URL); $mech->content_contains('Moderated by Bromley Council'); + + $mech->get_ok("$REPORT_URL/moderate/" . $update->id); + $mech->content_lacks('Moderate this update'); }; subtest 'And do it as a superuser' => sub { @@ -372,4 +514,7 @@ subtest 'And do it as a superuser' => sub { $mech->content_contains('Moderated by an administrator'); }; +subtest 'Check moderation history in admin' => sub { + $mech->get_ok('/admin/report_edit/' . $report->id); +}; done_testing(); diff --git a/t/app/controller/my_planned.t b/t/app/controller/my_planned.t index 67d59e148..a6a47a798 100644 --- a/t/app/controller/my_planned.t +++ b/t/app/controller/my_planned.t @@ -1,4 +1,5 @@ use FixMyStreet::TestMech; +use Test::MockModule; my $mech = FixMyStreet::TestMech->new; $mech->get_ok('/my/planned'); @@ -187,6 +188,13 @@ FixMyStreet::override_config { ALLOWED_COBRANDS => [ 'oxfordshire' ], BASE_URL => 'http://oxfordshire.fixmystreet.site', }, sub { + my $cobrand = Test::MockModule->new('FixMyStreet::Cobrand::Oxfordshire'); + $cobrand->mock('available_permissions', sub { + my $self = shift; + + return FixMyStreet::Cobrand::Default->available_permissions; + }); + subtest "can remove problems not displayed in cobrand from shortlist" => sub { $user->user_planned_reports->remove(); my ($problem1) = $mech->create_problems_for_body(2, $body->id, 'New Problem'); diff --git a/t/app/controller/open311.t b/t/app/controller/open311.t index 9f4f594fe..79fe159a3 100644 --- a/t/app/controller/open311.t +++ b/t/app/controller/open311.t @@ -6,7 +6,7 @@ my $mech = FixMyStreet::TestMech->new; $mech->get_ok('/open311.cgi/v2/requests.rss?jurisdiction_id=fiksgatami.no&status=open&agency_responsible=1854'); like $mech->uri, qr[/open311/v2/requests\.rss\?.{65}]; # Don't know order parameters will be in now -$mech->create_problems_for_body(2, 2237, 'Around page'); +my ($problem1, $problem2) = $mech->create_problems_for_body(2, 2237, 'Around page'); $mech->get_ok('/open311/v2/requests.xml?jurisdiction_id=foo&status=open&agency_responsible=2237'); $mech->content_contains('<description>Around page Test 2 for 2237: Around page Test 2 for 2237 Detail</description>'); $mech->content_contains('<interface_used>Web interface</interface_used>'); @@ -18,4 +18,43 @@ my $problems = $json->{requests}[0]{request}; is @$problems, 2; like $problems->[0]{description}, qr/Around page Test/; +subtest "non_public reports aren't available" => sub { + $problem1->update({ + non_public => 1, + detail => 'This report is now private', + }); + $mech->get_ok('/open311/v2/requests.json?jurisdiction_id=foo'); + $json = decode_json($mech->content); + $problems = $json->{requests}[0]{request}; + is @$problems, 1; + like $problems->[0]{description}, qr/Around page Test/; + $mech->content_lacks('This report is now private'); + + my $problem_id = $problem1->id; + $mech->get_ok("/open311/v2/requests/$problem_id.json?jurisdiction_id=foo"); + $json = decode_json($mech->content); + $problems = $json->{requests}[0]{request}; + is @$problems, 0; +}; + +subtest "hidden reports aren't available" => sub { + $problem1->update({ + non_public => 0, + detail => 'This report is now hidden', + state => "hidden", + }); + $mech->get_ok('/open311/v2/requests.json?jurisdiction_id=foo'); + $json = decode_json($mech->content); + $problems = $json->{requests}[0]{request}; + is @$problems, 1; + like $problems->[0]{description}, qr/Around page Test/; + $mech->content_lacks('This report is now hidden'); + + my $problem_id = $problem1->id; + $mech->get_ok("/open311/v2/requests/$problem_id.json?jurisdiction_id=foo"); + $json = decode_json($mech->content); + $problems = $json->{requests}[0]{request}; + is @$problems, 0; +}; + done_testing(); diff --git a/t/app/controller/photo.t b/t/app/controller/photo.t index e9183836b..842daa0dc 100644 --- a/t/app/controller/photo.t +++ b/t/app/controller/photo.t @@ -24,7 +24,10 @@ subtest "Check multiple upload worked" => sub { FixMyStreet::override_config { ALLOWED_COBRANDS => [ { fixmystreet => '.' } ], MAPIT_URL => 'http://mapit.uk/', - UPLOAD_DIR => $UPLOAD_DIR, + PHOTO_STORAGE_BACKEND => 'FileSystem', + PHOTO_STORAGE_OPTIONS => { + UPLOAD_DIR => $UPLOAD_DIR, + }, }, sub { $mech->log_in_ok('test@example.com'); @@ -72,12 +75,15 @@ subtest "Check multiple upload worked" => sub { }; }; -subtest "Check photo uploading URL works" => sub { +subtest "Check photo uploading URL and endpoints work" => sub { my $UPLOAD_DIR = tempdir( CLEANUP => 1 ); # submit initial pc form FixMyStreet::override_config { - UPLOAD_DIR => $UPLOAD_DIR, + PHOTO_STORAGE_BACKEND => 'FileSystem', + PHOTO_STORAGE_OPTIONS => { + UPLOAD_DIR => $UPLOAD_DIR, + }, }, sub { $mech->post( '/photo/upload', Content_Type => 'form-data', @@ -89,20 +95,21 @@ subtest "Check photo uploading URL works" => sub { is $mech->content, '{"id":"74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg"}'; my $image_file = path($UPLOAD_DIR, '74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg'); ok $image_file->exists, 'File uploaded to temp'; - }; -}; -subtest "Check photo URL endpoints work" => sub { - my $p = FixMyStreet::DB->resultset("Problem")->first; - - $mech->get_ok('/photo/temp.74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg'); - my $image_file = FixMyStreet->path_to('web/photo/temp.74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg'); - ok -e $image_file, 'File uploaded to temp'; - $mech->get_ok('/photo/' . $p->id . '.jpeg'); - $image_file = FixMyStreet->path_to('web/photo/' . $p->id . '.jpeg'); - ok -e $image_file, 'File uploaded to temp'; - my $res = $mech->get('/photo/0.jpeg'); - is $res->code, 404, "got 404"; + my $p = FixMyStreet::DB->resultset("Problem")->first; + + foreach my $i ( + '/photo/temp.74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg', + '/photo/fulltemp.74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg', + '/photo/' . $p->id . '.jpeg', + '/photo/' . $p->id . '.full.jpeg') { + $mech->get_ok($i); + $image_file = FixMyStreet->path_to("web$i"); + ok -e $image_file, 'File uploaded to temp'; + } + my $res = $mech->get('/photo/0.jpeg'); + is $res->code, 404, "got 404"; + }; }; done_testing(); diff --git a/t/app/controller/questionnaire.t b/t/app/controller/questionnaire.t index 75542d759..05aed7262 100644 --- a/t/app/controller/questionnaire.t +++ b/t/app/controller/questionnaire.t @@ -40,6 +40,26 @@ my $report = FixMyStreet::App->model('DB::Problem')->find_or_create( my $report_id = $report->id; ok $report, "created test report - $report_id"; +# Make sure questionnaires aren't sent if the report is closed. +foreach my $state ( + 'closed', 'duplicate', 'not responsible', 'unable to fix', 'internal referral' +) { + subtest "questionnaire not sent for $state state" => sub { + $report->update( { send_questionnaire => 1, state => $state } ); + $report->questionnaires->delete; + FixMyStreet::App->model('DB::Questionnaire')->send_questionnaires( { + site => 'fixmystreet' + } ); + + $mech->email_count_is(0); + + $report->discard_changes; + is $report->send_questionnaire, 0; + } +} +$report->update( { send_questionnaire => 1, state => 'confirmed' } ); +$report->questionnaires->delete; + # Call the questionaire sending function... FixMyStreet::App->model('DB::Questionnaire')->send_questionnaires( { site => 'fixmystreet' @@ -85,10 +105,16 @@ foreach my $test ( }, { desc => 'User goes to questionnaire URL for an already answered questionnaire', - answered => \'current_timestamp', + answered => \"current_timestamp - '10 minutes'::interval", content => 'already answered this questionnaire', code => 400, }, + { + desc => 'User goes to questionnaire URL for a very recently answered questionnaire', + answered => \"current_timestamp - '10 seconds'::interval", + content_lacks => 'already answered this questionnaire', + code => 200, + }, ) { subtest $test->{desc} => sub { $report->state( $test->{state} || 'confirmed' ); @@ -99,7 +125,8 @@ foreach my $test ( $token .= $test->{token_extra} if $test->{token_extra}; $mech->get("/Q/$token"); is $mech->res->code, $test->{code}, "Right status received"; - $mech->content_contains( $test->{content} ); + $mech->content_contains( $test->{content} ) if $test->{content}; + $mech->content_lacks( $test->{content_lacks} ) if $test->{content_lacks}; # Reset, no matter what test did $report->state( 'confirmed' ); $report->update; diff --git a/t/app/controller/report_as_other.t b/t/app/controller/report_as_other.t index 367d9a1d4..0c8b7d995 100644 --- a/t/app/controller/report_as_other.t +++ b/t/app/controller/report_as_other.t @@ -16,6 +16,8 @@ my $test_email = 'body-user@example.net'; my $user = $mech->log_in_ok($test_email); $user->update({ from_body => $body->id, name => 'Body User' }); +my $superuser = $mech->create_user_ok('superuser@example.net', name => "Super", is_superuser => 1); + my ($report_to_update) = $mech->create_problems_for_body(1, $body->id, 'Title', { category => 'Potholes' }); subtest "Body user, no permissions, no special reporting tools shown" => sub { @@ -123,7 +125,7 @@ subtest "Body user, has permission to add report as another (existing) user with my $send_confirmation_mail_override = Sub::Override->new( "FixMyStreet::Cobrand::Default::report_sent_confirmation_email", - sub { return 1; } + sub { return 'external_id'; } ); FixMyStreet::Script::Reports::send(); $mech->email_count_is(2); @@ -150,10 +152,11 @@ subtest "Body user, has permission to add report as another (existing) user with push @users, $report->user; }; -subtest "Body user, has permission to add report as anonymous user" => sub { +subtest "Superuser, can add report as anonymous user" => sub { FixMyStreet::Script::Reports::send(); $mech->clear_emails_ok; + my $user = $mech->log_in_ok($superuser->email); my $report = add_report( 'contribute_as_anonymous_user', form_as => 'anonymous_user', @@ -161,23 +164,23 @@ subtest "Body user, has permission to add report as anonymous user" => sub { detail => 'Test report details.', category => 'Street lighting', ); - is $report->name, 'Oxfordshire County Council', 'report name is body'; - is $report->user->name, 'Body User', 'user name unchanged'; + is $report->name, 'an administrator', 'report name is admin'; + is $report->user->name, 'Super', 'user name unchanged'; is $report->user->id, $user->id, 'user matches'; is $report->anonymous, 1, 'report anonymous'; my $send_confirmation_mail_override = Sub::Override->new( "FixMyStreet::Cobrand::Default::report_sent_confirmation_email", - sub { return 1; } + sub { return 'external_id'; } ); FixMyStreet::Script::Reports::send(); - # No report sent email is sent - $mech->email_count_is(1); my $email = $mech->get_email; like $email->header('Subject'), qr/Problem Report: Test Report/, 'report email title correct'; $mech->clear_emails_ok; $send_confirmation_mail_override->restore(); + + $mech->log_in_ok($test_email); }; subtest "Body user, has permission to add update as council" => sub { @@ -282,6 +285,24 @@ subtest "Body user, has permission to add update as anonymous user" => sub { is $update->anonymous, 1, 'update anonymous'; }; +for my $test_permission ( qw/planned_reports default_to_body/ ) { + subtest "$test_permission user defaults to reporting as body" => sub { + $_->delete for $user->user_body_permissions; + for my $permission ( 'contribute_as_another_user', 'contribute_as_anonymous_user', 'contribute_as_body', $test_permission ) { + $user->user_body_permissions->create({ body => $body, permission_type => $permission }) + } + 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'); + }; + + is $mech->visible_form_values()->{form_as}, 'body', 'report as body is default'; + }; +} + done_testing(); sub start_report { @@ -311,7 +332,9 @@ sub add_report { with_fields => \%fields, }, "submit details"); }; - $mech->content_contains('Thank you for reporting this issue'); + # Anonymous test done as superuser, which redirects + $mech->content_contains('Thank you for reporting this issue') + unless $permission eq 'contribute_as_anonymous_user'; my $report = FixMyStreet::DB->resultset("Problem")->search(undef, { order_by => { -desc => 'id' } })->first; ok $report, "Found the report"; is $report->state, 'confirmed', "report is now confirmed"; diff --git a/t/app/controller/report_display.t b/t/app/controller/report_display.t index 17b9180c1..bde090dd1 100644 --- a/t/app/controller/report_display.t +++ b/t/app/controller/report_display.t @@ -129,6 +129,7 @@ subtest "test a good report" => sub { 'Reported by Test User at 15:47, Sat 16 April 2011', 'correct problem meta information'; $mech->content_contains('Test 2 Detail'); + $mech->content_lacks('Sent to'); my $update_form = $mech->form_name('updateForm'); @@ -142,6 +143,18 @@ subtest "test a good report" => sub { is $update_form->value($_), $fields{$_}, "$_ value" for keys %fields; }; +subtest "test duration string" => sub { + $report->update({ whensent => \'current_timestamp' }); + $mech->get_ok("/report/$report_id"); + $mech->content_contains('Sent to Westminster'); + FixMyStreet::override_config { + AREA_LINKS_FROM_PROBLEMS => 1, + }, sub { + $mech->get_ok("/report/$report_id"); + $mech->content_contains('Sent to <a href="/reports/Westminster+City+Council">Westminster'); + }; +}; + foreach my $meta ( { anonymous => 'f', @@ -361,7 +374,12 @@ for my $test ( $banner->{text} =~ s/ $//g; } - is $banner->{id}, $test->{banner_id}, 'banner id'; + if ( $test->{banner_id} ) { + ok $banner->{class} =~ /banner--$test->{banner_id}/i, 'banner class'; + } else { + is $banner->{class}, $test->{banner_id}, 'banner class'; + } + if ($test->{banner_text}) { ok $banner->{text} =~ /$test->{banner_text}/i, 'banner text'; } else { diff --git a/t/app/controller/report_import.t b/t/app/controller/report_import.t index e4a202db7..223979d1b 100644 --- a/t/app/controller/report_import.t +++ b/t/app/controller/report_import.t @@ -89,6 +89,15 @@ subtest "Test creating bad partial entries" => sub { }; +for my $test ( + { + desc => 'Submit a correct entry', + }, + { + desc => 'Submit a correct web entry', + web => 1, + } +) { subtest "Submit a correct entry" => sub { $mech->get_ok('/import'); @@ -101,13 +110,18 @@ subtest "Submit a correct entry" => sub { subject => 'Test report', detail => 'This is a test report', photo => $sample_file, + web => $test->{web}, } }, "fill in form" ); is_deeply( $mech->import_errors, [], "got no errors" ); - is $mech->content, 'SUCCESS', "Got success response"; + if ( $test->{web} ) { + $mech->content_contains('Nearly done! Now check', "Got email confirmation page"); + } else { + is $mech->content, 'SUCCESS', "Got success response"; + } # check that we have received the email my $token_url = $mech->get_link_from_email; @@ -223,6 +237,7 @@ subtest "Submit a correct entry" => sub { $mech->delete_user($user); }; +} subtest "Submit a correct entry (with location)" => sub { diff --git a/t/app/controller/report_inspect.t b/t/app/controller/report_inspect.t index 6a001225d..ef05288c7 100644 --- a/t/app/controller/report_inspect.t +++ b/t/app/controller/report_inspect.t @@ -1,4 +1,5 @@ use FixMyStreet::TestMech; +use Test::MockModule; my $mech = FixMyStreet::TestMech->new; @@ -7,6 +8,14 @@ my $oxon = $mech->create_body_ok(2237, 'Oxfordshire County Council', { can_be_de my $contact = $mech->create_contact_ok( body_id => $oxon->id, category => 'Cows', email => 'cows@example.net' ); my $contact2 = $mech->create_contact_ok( body_id => $oxon->id, category => 'Sheep', email => 'SHEEP', send_method => 'Open311' ); my $contact3 = $mech->create_contact_ok( body_id => $oxon->id, category => 'Badgers', email => 'badgers@example.net' ); +my $dt = FixMyStreet::DB->resultset("DefectType")->create({ + body => $oxon, + name => 'Small Defect', description => "Teeny", +}); +FixMyStreet::DB->resultset("ContactDefectType")->create({ + contact => $contact, + defect_type => $dt, +}); my $rp = FixMyStreet::DB->resultset("ResponsePriority")->create({ body => $oxon, name => 'High Priority', @@ -23,14 +32,14 @@ FixMyStreet::DB->resultset("ContactResponsePriority")->create({ contact => $contact3, response_priority => $rp2, }); -my $wodc = $mech->create_body_ok(2420, 'West Oxfordshire District Council'); -$mech->create_contact_ok( body_id => $wodc->id, category => 'Horses', email => 'horses@example.net' ); +my $oxfordcity = $mech->create_body_ok(2421, 'Oxford City Council'); +$mech->create_contact_ok( body_id => $oxfordcity->id, category => 'Horses', email => 'horses@example.net' ); my ($report, $report2, $report3) = $mech->create_problems_for_body(3, $oxon->id, 'Test', { - category => 'Cows', cobrand => 'fixmystreet', areas => ',2237,2420', + category => 'Cows', cobrand => 'fixmystreet', areas => ',2237,2421,', whensent => \'current_timestamp', - latitude => 51.847693, longitude => -1.355908, + latitude => 51.754926, longitude => -1.256179, }); my $report_id = $report->id; my $report2_id = $report2->id; @@ -48,12 +57,22 @@ FixMyStreet::override_config { subtest "test inspect page" => sub { $mech->get_ok("/report/$report_id"); $mech->content_lacks('Save changes'); + $mech->content_lacks('Private'); + $mech->content_lacks('Priority'); + $mech->content_lacks('Traffic management'); + $mech->content_lacks('/admin/report_edit/'.$report_id.'">admin</a>)'); + + $user->user_body_permissions->create({ body => $oxon, permission_type => 'report_mark_private' }); + $mech->get_ok("/report/$report_id"); + $mech->content_contains('Private'); + $mech->content_contains('Save changes'); $mech->content_lacks('Priority'); $mech->content_lacks('Traffic management'); $mech->content_lacks('/admin/report_edit/'.$report_id.'">admin</a>)'); $user->user_body_permissions->create({ body => $oxon, permission_type => 'report_edit_priority' }); $mech->get_ok("/report/$report_id"); + $mech->content_contains('Private'); $mech->content_contains('Save changes'); $mech->content_contains('Priority'); $mech->content_lacks('Traffic management'); @@ -62,6 +81,7 @@ FixMyStreet::override_config { $user->user_body_permissions->create({ body => $oxon, permission_type => 'report_inspect' }); $mech->get_ok("/report/$report_id"); $mech->content_contains('Save changes'); + $mech->content_contains('Private'); $mech->content_contains('Priority'); $mech->content_contains('Traffic management'); $mech->content_lacks('/admin/report_edit/'.$report_id.'">admin</a>)'); @@ -82,7 +102,28 @@ FixMyStreet::override_config { $user->update({is_superuser => 0}); }; + subtest "test mark private submission" => sub { + $user->user_body_permissions->delete; + $user->user_body_permissions->create({ body => $oxon, permission_type => 'report_mark_private' }); + + $mech->get_ok("/report/$report_id"); + $mech->submit_form_ok({ button => 'save', with_fields => { non_public => 1 } }); + $report->discard_changes; + my $alert = FixMyStreet::App->model('DB::Alert')->find( + { user => $user, alert_type => 'new_updates', confirmed => 1, } + ); + + is $report->state, 'confirmed', 'report state not changed'; + ok $report->non_public, 'report not public'; + ok !defined( $alert ) , 'not signed up for alerts'; + + $report->update( { non_public => 0 } ); + }; subtest "test basic inspect submission" => sub { + $user->user_body_permissions->create({ body => $oxon, permission_type => 'report_edit_priority' }); + $user->user_body_permissions->create({ body => $oxon, permission_type => 'report_inspect' }); + + $mech->get_ok("/report/$report_id"); $mech->submit_form_ok({ button => 'save', with_fields => { traffic_information => 'Yes', state => 'Action scheduled', include_update => undef } }); $report->discard_changes; my $alert = FixMyStreet::App->model('DB::Alert')->find( @@ -144,6 +185,19 @@ FixMyStreet::override_config { $mech->content_lacks('Invalid location'); }; + subtest "test areas update when location changes" => sub { + $report->discard_changes; + my ($lat, $lon, $areas) = ($report->latitude, $report->longitude, $report->areas); + $mech->get_ok("/report/$report_id"); + $mech->submit_form_ok({ button => 'save', with_fields => { latitude => 52.038712, longitude => -1.346397, include_update => undef } }); + $mech->content_lacks('Invalid location'); + $report->discard_changes; + is $report->areas, ",151767,2237,2419,", 'Areas set correctly'; + $mech->submit_form_ok({ button => 'save', with_fields => { latitude => $lat, longitude => $lon, include_update => undef } }); + $report->discard_changes; + is $report->areas, $areas, 'Areas reset correctly'; + }; + subtest "test duplicate reports are shown" => sub { my $old_state = $report->state; $report->set_extra_metadata('duplicate_of' => $report2->id); @@ -394,6 +448,24 @@ FixMyStreet::override_config { is $report->response_priority->id, $rp->id, 'response priority set'; }; + subtest "check can set defect type for category when changing from category with no defect types" => sub { + $report->update({ category => 'Sheep', defect_type_id => undef }); + $user->user_body_permissions->delete; + $user->user_body_permissions->create({ body => $oxon, permission_type => 'report_inspect' }); + $mech->get_ok("/report/$report_id"); + $mech->submit_form_ok({ + button => 'save', + with_fields => { + include_update => 0, + defect_type => $dt->id, + category => 'Cows', + } + }); + $report->discard_changes; + is $report->defect_type->id, $dt->id, 'defect type set'; + $report->update({ defect_type_id => undef }); + }; + subtest "check can't set priority that isn't for a category" => sub { $report->discard_changes; $report->update({ category => 'Cows', response_priority_id => $rp->id }); @@ -414,6 +486,26 @@ FixMyStreet::override_config { is $report->response_priority, undef, 'response priority set'; }; + subtest "check can unset priority" => sub { + $report->discard_changes; + $report->update({ category => 'Cows', response_priority_id => $rp->id }); + $report->discard_changes; + is $report->response_priority->id, $rp->id, 'response priority set'; + $user->user_body_permissions->delete; + $user->user_body_permissions->create({ body => $oxon, permission_type => 'report_edit_category' }); + $user->user_body_permissions->create({ body => $oxon, permission_type => 'report_edit_priority' }); + $mech->get_ok("/report/$report_id"); + $mech->submit_form_ok({ + button => 'save', + with_fields => { + priority => "", + } + }); + + $report->discard_changes; + is $report->response_priority, undef, 'response priority unset'; + }; + subtest "check nearest address display" => sub { $mech->get_ok("/report/$report_id"); $mech->content_lacks('Nearest calculated address', 'No address displayed'); @@ -460,6 +552,14 @@ foreach my $test ( FixMyStreet::override_config { ALLOWED_COBRANDS => $test->{cobrand}, }, sub { + my $cobrand = Test::MockModule->new('FixMyStreet::Cobrand::Oxfordshire'); + $cobrand->mock('available_permissions', sub { + my $self = shift; + + my $perms = FixMyStreet::Cobrand::Default->available_permissions; + + return $perms; + }); subtest $test->{desc} => sub { $user->user_body_permissions->delete; $user->user_body_permissions->create({ body => $oxon, permission_type => 'report_inspect' }); @@ -506,6 +606,14 @@ foreach my $test ( FixMyStreet::override_config { ALLOWED_COBRANDS => 'oxfordshire', }, sub { + my $cobrand = Test::MockModule->new('FixMyStreet::Cobrand::Oxfordshire'); + $cobrand->mock('available_permissions', sub { + my $self = shift; + + my $perms = FixMyStreet::Cobrand::Default->available_permissions; + + return $perms; + }); subtest "test negative reputation" => sub { my $reputation = $report->user->get_extra_metadata("reputation") || 0; @@ -641,7 +749,7 @@ FixMyStreet::override_config { # set the timezone on this so the date comparison below doesn't fail due to mismatched # timezones my $now = DateTime->now( - time_zone => FixMyStreet->time_zone || FixMyStreet->local_time_zone + time_zone => FixMyStreet->local_time_zone )->subtract(days => 1); $mech->submit_form(button => 'save', form_id => 'report_inspect_form', fields => { include_update => 1, public_update => 'An update', saved_at => $now->epoch }); @@ -655,6 +763,14 @@ FixMyStreet::override_config { ALLOWED_COBRANDS => [ 'oxfordshire', 'fixmystreet' ], BASE_URL => 'http://fixmystreet.site', }, sub { + my $cobrand = Test::MockModule->new('FixMyStreet::Cobrand::Oxfordshire'); + $cobrand->mock('available_permissions', sub { + my $self = shift; + + my $perms = FixMyStreet::Cobrand::Default->available_permissions; + + return $perms; + }); subtest "test report not resent when category changes if send_method doesn't change" => sub { $mech->get_ok("/report/$report3_id"); $mech->submit_form(button => 'save', with_fields => { category => 'Badgers', include_update => undef, }); @@ -690,7 +806,7 @@ FixMyStreet::override_config { $report->discard_changes; is $report->category, "Horses", "Report in correct category"; is $report->whensent, undef, "Report marked as unsent"; - is $report->bodies_str, $wodc->id, "Reported to WODC"; + is $report->bodies_str, $oxfordcity->id, "Reported to Oxford City"; is $mech->uri->path, "/report/$report_id", "redirected to correct page"; is $mech->res->code, 200, "got 200 for final destination"; diff --git a/t/app/controller/report_interest_count.t b/t/app/controller/report_interest_count.t index 04f567615..330d844d0 100644 --- a/t/app/controller/report_interest_count.t +++ b/t/app/controller/report_interest_count.t @@ -109,7 +109,7 @@ FixMyStreet::override_config { $mech->content_contains( '1 supporter' ); $mech->log_out_ok( $user->email ); - $mech->post_ok("/report/support", { id => $report_id } ); + $mech->post_ok("/report/$report_id/support"); is $mech->uri->path, "/report/$report_id", 'add support redirects to report page'; diff --git a/t/app/controller/report_new.t b/t/app/controller/report_new.t index dff04176b..af18c39b9 100644 --- a/t/app/controller/report_new.t +++ b/t/app/controller/report_new.t @@ -24,10 +24,15 @@ subtest "test that bare requests to /report/new get redirected" => sub { MAPIT_URL => 'http://mapit.uk/', }, sub { $mech->get_ok('/report/new?pc=SW1A%201AA'); + is $mech->uri->path, '/around', "went to /around"; + is_deeply { $mech->uri->query_form }, { pc => 'SW1A 1AA' }, + "pc correctly transferred"; + + $mech->get_ok('/report/new?pc_override=SW1A%201AA&latitude=51&longitude=-2'); + is $mech->uri->path, '/around', "went to /around"; + is_deeply { $mech->uri->query_form }, { pc => 'SW1A 1AA' }, + "pc correctly transferred, lat/lon gone"; }; - is $mech->uri->path, '/around', "went to /around"; - is_deeply { $mech->uri->query_form }, { pc => 'SW1A 1AA' }, - "pc correctly transferred"; }; my %body_ids; @@ -40,6 +45,13 @@ for my $body ( { area_id => 2482, name => 'Bromley Council' }, { area_id => 2227, name => 'Hampshire County Council' }, { area_id => 2333, name => 'Hart Council' }, + { area_id => 2535, name => 'Sandwell Borough Council' }, + { area_id => 1000, name => 'Highways England' }, + { area_id => 2217, name => 'Buckinghamshire County Council' }, + { area_id => 2232, name => 'Lincolnshire County Council' }, + { area_id => 2237, name => 'Oxfordshire County Council' }, + { area_id => 2600, name => 'Rutland County Council' }, + { area_id => 2234, name => 'Northamptonshire County Council' }, ) { my $body_obj = $mech->create_body_ok($body->{area_id}, $body->{name}); push @bodies, $body_obj; @@ -97,6 +109,36 @@ my $contact10 = $mech->create_contact_ok( category => 'Street lighting', email => 'streetlights-2326@example.com', ); +my $contact11 = $mech->create_contact_ok( + body_id => $body_ids{1000}, # Highways + category => 'Pothole', + email => 'pothole-1000@example.com', +); +my $contact12 = $mech->create_contact_ok( + body_id => $body_ids{2217}, # Buckinghamshire + category => 'Street lighting', + email => 'streetlights-2217@example.com', +); +my $contact13 = $mech->create_contact_ok( + body_id => $body_ids{2232}, # Lincolnshire + category => 'Trees', + email => 'trees-2232@example.com', +); +my $contact14 = $mech->create_contact_ok( + body_id => $body_ids{2237}, # Oxfordshire + category => 'Trees', + email => 'trees-2247@example.com', +); +my $contact15 = $mech->create_contact_ok( + body_id => $body_ids{2600}, # Rutland + category => 'Trees', + email => 'trees-2600@example.com', +); +my $contact16 = $mech->create_contact_ok( + body_id => $body_ids{2234}, # Northamptonshire + category => 'Trees', + email => 'trees-2234@example.com', +); # test that the various bit of form get filled in and errors correctly # generated. @@ -113,11 +155,9 @@ foreach my $test ( name => '', may_show_name => '1', username => '', - email => '', phone => '', password_sign_in => '', password_register => '', - remember_me => undef, }, changes => {}, errors => [ @@ -140,12 +180,10 @@ foreach my $test ( name => '', may_show_name => '1', username => '', - email => '', phone => '', category => 'Something bad', password_sign_in => '', password_register => '', - remember_me => undef, }, changes => { category => '-- Pick a category --', @@ -170,12 +208,10 @@ foreach my $test ( name => '', may_show_name => '1', username => '', - email => '', phone => '', category => 'Street lighting', password_sign_in => '', password_register => '', - remember_me => undef, }, changes => {}, errors => [ @@ -197,12 +233,10 @@ foreach my $test ( name => '', may_show_name => undef, username => '', - email => '', phone => '', category => 'Street lighting', password_sign_in => '', password_register => '', - remember_me => undef, }, changes => {}, errors => [ @@ -224,12 +258,10 @@ foreach my $test ( name => 'Bob Jones', may_show_name => undef, username => '', - email => '', phone => '', category => 'Street lighting', password_sign_in => '', password_register => '', - remember_me => undef, }, changes => {}, errors => [ @@ -250,12 +282,10 @@ foreach my $test ( name => 'Bob Jones', may_show_name => '1', username => '', - email => '', phone => '', category => 'Street lighting', password_sign_in => '', password_register => '', - remember_me => undef, }, changes => {}, errors => [ @@ -276,12 +306,10 @@ foreach my $test ( name => 'Bob Jones', may_show_name => '1', username => '', - email => '', phone => '', category => 'Street lighting', password_sign_in => '', password_register => '', - remember_me => undef, }, changes => { title => 'Dog poo on walls', @@ -302,12 +330,10 @@ foreach my $test ( name => 'DUDE', may_show_name => '1', username => '', - email => '', phone => '', category => 'Street lighting', password_sign_in => '', password_register => '', - remember_me => undef, }, changes => {}, errors => [ @@ -327,12 +353,10 @@ foreach my $test ( name => 'anonymous', may_show_name => '1', username => '', - email => '', phone => '', category => 'Street lighting', password_sign_in => '', password_register => '', - remember_me => undef, }, changes => {}, errors => [ @@ -352,14 +376,12 @@ foreach my $test ( name => 'Joe Smith', may_show_name => '1', username => 'not an email', - email => '', phone => '', category => 'Street lighting', password_sign_in => '', password_register => '', - remember_me => undef, }, - changes => { username => 'notanemail', email => 'notanemail' }, + changes => { username => 'notanemail' }, errors => [ 'Please enter a valid email', ], }, { @@ -374,12 +396,10 @@ foreach my $test ( name => '', may_show_name => '1', username => '', - email => '', phone => '', category => 'Street lighting', password_sign_in => '', password_register => '', - remember_me => undef, }, changes => { title => 'Test title', @@ -402,17 +422,14 @@ foreach my $test ( name => ' Bob Jones ', may_show_name => '1', username => ' BOB @ExAmplE.COM ', - email => '', phone => '', category => 'Street lighting', password_sign_in => '', password_register => '', - remember_me => undef, }, changes => { name => 'Bob Jones', username => 'bob@example.com', - email => 'bob@example.com', }, errors => [ 'Please enter a subject', 'Please enter some details', ], }, @@ -428,12 +445,10 @@ foreach my $test ( name => 'Bob Jones', may_show_name => '1', username => 'bob@example.com', - email => 'bob@example.com', phone => '', category => 'Street lighting', password_sign_in => '', password_register => '', - remember_me => undef, }, changes => { photo1 => '', @@ -452,12 +467,10 @@ foreach my $test ( name => 'Bob Jones', may_show_name => '1', username => 'bob@example.com', - email => 'bob@example.com', phone => '', category => 'Street lighting', password_sign_in => '', password_register => '', - remember_me => undef, }, changes => { photo1 => '', @@ -476,18 +489,157 @@ foreach my $test ( name => 'Bob Jones', may_show_name => '1', username => 'bob@example.com', - email => 'bob@example.com', phone => '', category => 'Street lighting', password_sign_in => '', password_register => '', - remember_me => undef, }, changes => { photo1 => '', }, errors => [ "Please enter a subject" ], }, + { + msg => 'Bromley long detail', + pc => 'BR1 3UH', + fields => { + fms_extra_title => 'MR', + title => '', + detail => 'X' . 'x' x 1751, + photo1 => '', + photo2 => '', + photo3 => '', + name => 'Bob Example', + may_show_name => '1', + username => 'bob@example.com', + phone => '', + category => 'Trees', + password_sign_in => '', + password_register => '', + }, + changes => { }, + errors => [ 'Please enter a subject', 'Reports are limited to 1750 characters in length. Please shorten your report' ], + }, + { + msg => 'Oxfordshire long detail', + pc => 'OX20 1SZ', + fields => { + title => '', + detail => 'X' . 'x' x 1701, + photo1 => '', + photo2 => '', + photo3 => '', + name => 'Bob Example', + may_show_name => '1', + username => 'bob@example.com', + phone => '', + category => 'Trees', + password_sign_in => '', + password_register => '', + }, + changes => { }, + errors => [ 'Please enter a subject', 'Reports are limited to 1700 characters in length. Please shorten your report' ], + }, + { + msg => 'Lincolnshire long phone', + pc => 'PE9 2GX', + fields => { + title => '', + detail => 'Detail', + photo1 => '', + photo2 => '', + photo3 => '', + name => 'Bob Example', + may_show_name => '1', + username => 'bob@example.com', + phone => '123456789 12345678910', + category => 'Trees', + password_sign_in => '', + password_register => '', + }, + changes => { }, + errors => [ 'Please enter a subject', 'Phone numbers are limited to 20 characters in length.' ], + }, + { + msg => 'Buckinghamshire long name', + pc => 'RG9 6TL', + fields => { + title => '', + detail => '', + photo1 => '', + photo2 => '', + photo3 => '', + name => 'This is a very long name that should fail validation', + may_show_name => '1', + username => 'bob@example.com', + phone => '', + category => 'Street lighting', + password_sign_in => '', + password_register => '', + }, + changes => { }, + errors => [ 'Please enter a subject', 'Please enter some details', 'Names are limited to 50 characters in length.' ], + }, + { + msg => 'Rutland long name', + pc => 'LE15 0GJ', + fields => { + title => '', + detail => '', + photo1 => '', + photo2 => '', + photo3 => '', + name => 'This is a very long name that should fail validation', + may_show_name => '1', + username => 'bob@example.com', + phone => '', + category => 'Trees', + password_sign_in => '', + password_register => '', + }, + changes => { }, + errors => [ 'Please enter a subject', 'Please enter some details', 'Names are limited to 40 characters in length.' ], + }, + { + msg => 'Oxfordshire validation', + pc => 'OX20 1SZ', + fields => { + title => '', + detail => '', + photo1 => '', + photo2 => '', + photo3 => '', + name => 'This is a really extraordinarily long name that definitely should fail validation', + may_show_name => '1', + username => 'bob.has.a.very.long.email@thisisalonghostname.example.com', + phone => '01234 5678910 09876 54321 ext 203', + category => 'Trees', + password_sign_in => '', + password_register => '', + }, + changes => { }, + errors => [ 'Please enter a subject', 'Please enter some details', 'Emails are limited to 50 characters in length.', 'Phone numbers are limited to 20 characters in length.', 'Names are limited to 50 characters in length.'], + }, + { + msg => 'Northamptonshire validation', + pc => 'NN1 1NS', + fields => { + title => 'This is a very long title that should fail the validation as it is really much too long to pass the validation of 120 characters', + detail => '', + photo1 => '', + photo2 => '', + photo3 => '', + name => 'A User', + may_show_name => '1', + username => 'user@example.org', + phone => '', + category => 'Trees', + password_sign_in => '', + password_register => '', + }, + changes => { }, + errors => [ 'Summaries are limited to 120 characters in length. Please shorten your summary', 'Please enter some details'], + }, ) { subtest "check form errors where $test->{msg}" => sub { @@ -495,7 +647,7 @@ foreach my $test ( # submit initial pc form FixMyStreet::override_config { - ALLOWED_COBRANDS => [ { fixmystreet => '.' } ], + ALLOWED_COBRANDS => [ { fixmystreet => '.' }, 'bromley', 'oxfordshire', 'rutland', 'lincolnshire', 'buckinghamshire', 'northamptonshire' ], MAPIT_URL => 'http://mapit.uk/', }, sub { $mech->submit_form_ok( { with_fields => { pc => $test->{pc} } }, @@ -679,6 +831,7 @@ subtest "test password errors for a user who is signing in as they report" => su name => 'Joe Bloggs', phone => '01234 567 890', password => 'secret2', + phone_verified => 1, } ), "set user details"; # submit initial pc form @@ -714,6 +867,8 @@ subtest "test password errors for a user who is signing in as they report" => su is_deeply $mech->page_errors, [ "There was a problem with your login information. If you cannot remember your password, or do not have one, please fill in the \x{2018}No\x{2019} section of the form.", ], "check there were errors"; + + $mech->content_lacks('1234', 'phone number not shown'); }; foreach my $test ( @@ -960,12 +1115,26 @@ foreach my $test ( email_count => 1, }, { - desc => "test invalid single_body_only means multiple report bodies", + desc => "test invalid single_body_only means no report bodies", category => 'Street lighting', - councils => [ 2226, 2326 ], + councils => [], extra_fields => { single_body_only => 'Invalid council' }, email_count => 1, }, + { + desc => "test do_not_send means body is ignored", + category => 'Street lighting', + councils => [ 2326 ], + extra_fields => { do_not_send => 'Gloucestershire County Council' }, + email_count => 1, + }, + { + desc => "test single_body_only with Highways England", + category => 'Street lighting', + councils => [ 1000 ], + extra_fields => { single_body_only => 'Highways England' }, + email_count => 1, + }, ) { subtest $test->{desc} => sub { @@ -1036,7 +1205,7 @@ foreach my $test ( ok $report, "Found the report"; # Check the report has been assigned appropriately - is $report->bodies_str, join(',', @body_ids{@{$test->{councils}}}); + is $report->bodies_str, join(',', @body_ids{@{$test->{councils}}}) || undef; $mech->content_contains('Thank you for reporting this issue'); @@ -1177,24 +1346,48 @@ subtest "test report creation for a category that is non public" => sub { $contact2->category( "Pothol\xc3\xa9s" ); $contact2->update; -my $extra_details; -FixMyStreet::override_config { - ALLOWED_COBRANDS => [ { fixmystreet => '.' } ], - MAPIT_URL => 'http://mapit.uk/', -}, sub { - $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=' . $saved_lat . '&longitude=' . $saved_lon ); -}; -$mech->content_contains( "Pothol\xc3\xa9s" ); -like $extra_details->{councils_text}, qr/<strong>Cheltenham/; -ok !$extra_details->{titles_list}, 'Non Bromley does not send back list of titles'; - -FixMyStreet::override_config { - ALLOWED_COBRANDS => [ { fixmystreet => '.' } ], - MAPIT_URL => 'http://mapit.uk/', -}, sub { - $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=51.4021&longitude=0.01578'); +subtest "check map click ajax response" => sub { + my $extra_details; + FixMyStreet::override_config { + ALLOWED_COBRANDS => 'fixmystreet', + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=' . $saved_lat . '&longitude=' . $saved_lon ); + }; + # this order seems to be random so check individually/sort + like $extra_details->{councils_text}, qr/Cheltenham Borough Council/, 'correct council text for two tier'; + like $extra_details->{councils_text}, qr/Gloucestershire County Council/, 'correct council text for two tier'; + like $extra_details->{category}, qr/Pothol\x{00E9}s.*Street lighting/, 'category looks correct for two tier council'; + my @sorted_bodies = sort @{ $extra_details->{bodies} }; + is_deeply \@sorted_bodies, [ "Cheltenham Borough Council", "Gloucestershire County Council" ], 'correct bodies for two tier'; + ok !$extra_details->{titles_list}, 'Non Bromley does not send back list of titles'; + + FixMyStreet::override_config { + ALLOWED_COBRANDS => 'fixmystreet', + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=51.4021&longitude=0.01578'); + }; + ok $extra_details->{titles_list}, 'Bromley sends back list of titles'; + like $extra_details->{councils_text}, qr/Bromley Council/, 'correct council text'; + like $extra_details->{councils_text_private}, qr/^These details will be sent to the council, but will never be shown online/, 'correct private council text'; + like $extra_details->{category}, qr/Trees/, 'category looks correct'; + is_deeply $extra_details->{bodies}, [ "Bromley Council" ], 'correct bodies'; + ok !$extra_details->{contribute_as}, 'no contribute as section'; + ok !$extra_details->{top_message}, 'no top message'; + ok $extra_details->{extra_name_info}, 'extra name info'; + + FixMyStreet::override_config { + ALLOWED_COBRANDS => 'fixmystreet', + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=52.563074&longitude=-1.991032' ); + }; + like $extra_details->{councils_text}, qr/^These will be published online for others to see/, 'correct council text for council with no contacts'; + is $extra_details->{category}, '', 'category is empty for council with no contacts'; + is_deeply $extra_details->{bodies}, [ "Sandwell Borough Council" ], 'correct bodies for council with no contacts'; + ok !$extra_details->{extra_name_info}, 'no extra name info'; }; -ok $extra_details->{titles_list}, 'Bromley sends back list of titles'; #### test uploading an image @@ -1552,7 +1745,7 @@ subtest "test Hart" => sub { if ( $test->{confirm} ) { is $mech->uri->path, "/report/new"; my $base = 'www.fixmystreet.com'; - $base = "hart.fixmystreet.com" unless $test->{national}; + $base = '"' unless $test->{national}; $mech->content_contains("$base/report/" . $report->id, "links to correct site"); } else { # receive token @@ -1579,7 +1772,7 @@ subtest "test Hart" => sub { }; my $base = 'www.fixmystreet.com'; - $base = 'hart.fixmystreet.com' unless $test->{national}; + $base = '"' unless $test->{national}; $mech->content_contains( $base . '/report/' . $report->id, 'confirm page links to correct site' ); @@ -1637,9 +1830,12 @@ subtest "unresponsive body handling works" => sub { # Test body-level send method my $old_send = $contact1->body->send_method; $contact1->body->update( { send_method => 'Refused' } ); - $mech->get_ok('/report/new/ajax?latitude=55.952055&longitude=-3.189579'); # Edinburgh my $body_id = $contact1->body->id; - ok $mech->content_like( qr{Edinburgh.*accept reports.*/unresponsive\?body=$body_id} ); + my $extra_details = $mech->get_ok_json('/report/new/ajax?latitude=55.952055&longitude=-3.189579'); + like $extra_details->{top_message}, qr{Edinburgh.*accept reports.*/unresponsive\?body=$body_id}; + is_deeply $extra_details->{unresponsive}, { $body_id => 1 }, "unresponsive json set"; + $extra_details = $mech->get_ok_json('/report/new/category_extras?category=Street%20lighting&latitude=55.952055&longitude=-3.189579'); + is_deeply $extra_details->{unresponsive}, { $body_id => 1 }, "unresponsive json set"; my $test_email = 'test-2@example.com'; $mech->log_out_ok; @@ -1713,8 +1909,10 @@ subtest "unresponsive body handling works" => sub { # And test per-category refusing my $old_email = $contact3->email; $contact3->update( { email => 'REFUSED' } ); - $mech->get_ok('/report/new/category_extras?category=Trees&latitude=51.896268&longitude=-2.093063'); - ok $mech->content_like( qr/Cheltenham.*Trees.*unresponsive.*category=Trees/ ); + $extra_details = $mech->get_ok_json('/report/new/ajax?latitude=51.896268&longitude=-2.093063'); + like $extra_details->{by_category}{$contact3->category}{category_extra}, qr/Cheltenham.*Trees.*unresponsive.*category=Trees/s; + $extra_details = $mech->get_ok_json('/report/new/category_extras?category=Trees&latitude=51.896268&longitude=-2.093063'); + is_deeply $extra_details->{unresponsive}, { $contact3->body->id => 1 }, "unresponsive json set"; $mech->get_ok('/around'); $mech->submit_form_ok( { with_fields => { pc => 'GL50 2PR', } }, "submit location" ); @@ -1879,6 +2077,51 @@ subtest "extra google analytics code displayed on email confirmation problem cre }; }; + +my $private_perms = $mech->create_user_ok('private_perms@example.org', name => 'private', from_body => $bodies[0]); +subtest "report_mark_private allows users to mark reports as private" => sub { + FixMyStreet::override_config { + ALLOWED_COBRANDS => [ { fixmystreet => '.' } ], + BASE_URL => 'https://www.fixmystreet.com', + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $mech->log_out_ok; + + $private_perms->user_body_permissions->find_or_create({ + body => $bodies[0], + permission_type => 'report_mark_private', + }); + + $mech->log_in_ok('private_perms@example.org'); + $mech->get_ok('/'); + $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB' } }, + "submit location" ); + $mech->follow_link_ok( + { text_regex => qr/skip this step/i, }, + "follow 'skip this step' link" + ); + + $mech->submit_form_ok( + { + with_fields => { + title => "Private report", + detail => 'Private report details.', + photo1 => '', + name => 'Joe Bloggs', + may_show_name => '1', + phone => '07903 123 456', + category => 'Trees', + non_public => 1, + } + }, + "submit good details" + ); + + $mech->content_contains('Great work. Now spread the word', 'shown confirmation page'); + } +}; + +my $inspector = $mech->create_user_ok('inspector@example.org', name => 'inspector', from_body => $bodies[0]); foreach my $test ( { non_public => 0 }, { non_public => 1 }, @@ -1891,12 +2134,11 @@ foreach my $test ( }, sub { $mech->log_out_ok; - my $user = $mech->create_user_ok('inspector@example.org', name => 'inspector', from_body => $bodies[0]); - $user->user_body_permissions->find_or_create({ + $inspector->user_body_permissions->find_or_create({ body => $bodies[0], permission_type => 'planned_reports', }); - $user->user_body_permissions->find_or_create({ + $inspector->user_body_permissions->find_or_create({ body => $bodies[0], permission_type => 'report_inspect', }); @@ -1931,4 +2173,111 @@ foreach my $test ( }; } +subtest "check map click ajax response for inspector" => sub { + $mech->log_out_ok; + + my $extra_details; + $inspector->user_body_permissions->find_or_create({ + body => $bodies[0], + permission_type => 'planned_reports', + }); + $inspector->user_body_permissions->find_or_create({ + body => $bodies[0], + permission_type => 'report_inspect', + }); + + $mech->log_in_ok('inspector@example.org'); + FixMyStreet::override_config { + ALLOWED_COBRANDS => [ { fixmystreet => '.' } ], + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=55.952055&longitude=-3.189579' ); + }; + like $extra_details->{category}, qr/data-prefill="0/, 'inspector prefill not set'; + ok !$extra_details->{contribute_as}, 'no contribute as section'; +}; + +subtest "check map click ajax response for inspector and uk cobrand" => sub { + $mech->log_out_ok; + + my $extra_details; + $inspector->user_body_permissions->find_or_create({ + body => $bodies[4], + permission_type => 'planned_reports', + }); + $inspector->user_body_permissions->find_or_create({ + body => $bodies[4], + permission_type => 'report_inspect', + }); + + $mech->log_in_ok('inspector@example.org'); + FixMyStreet::override_config { + ALLOWED_COBRANDS => [ { bromley => '.' } ], + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=51.402096&longitude=0.015784' ); + }; + like $extra_details->{category}, qr/data-prefill="0/, 'inspector prefill not set'; +}; + +for my $test ( + { + desc => 'map click ajax for contribute_as_another_user', + permissions => { + contribute_as_another_user => 1, + contribute_as_anonymous_user => undef, + contribute_as_body => undef, + } + }, + { + desc => 'map click ajax for contribute_as_anonymous_user', + permissions => { + contribute_as_another_user => undef, + contribute_as_anonymous_user => 1, + contribute_as_body => undef, + } + }, + { + desc => 'map click ajax for contribute_as_body', + permissions => { + contribute_as_another_user => undef, + contribute_as_anonymous_user => undef, + contribute_as_body => 1, + } + }, +) { + subtest $test->{desc} => sub { + $mech->log_out_ok; + my $extra_details; + (my $name = $test->{desc}) =~ s/.*(contri.*)/$1/; + my $user = $mech->create_user_ok("$name\@example.org", name => 'test user', from_body => $bodies[0]); + for my $p ( keys %{$test->{permissions}} ) { + next unless $test->{permissions}->{$p}; + $user->user_body_permissions->find_or_create({ + body => $bodies[0], + permission_type => $p, + }); + } + $mech->log_in_ok("$name\@example.org"); + FixMyStreet::override_config { + ALLOWED_COBRANDS => [ { fixmystreet => '.' } ], + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=55.952055&longitude=-3.189579' ); + }; + for my $p ( keys %{$test->{permissions}} ) { + (my $key = $p) =~ s/contribute_as_//; + is $extra_details->{contribute_as}->{$key}, $test->{permissions}->{$p}, "$key correctly set"; + } + + FixMyStreet::override_config { + ALLOWED_COBRANDS => [ { fixmystreet => '.' } ], + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=51.754926&longitude=-1.256179' ); + }; + ok !$extra_details->{contribute_as}, 'no contribute as section for other council'; + }; +} + done_testing(); diff --git a/t/app/controller/report_new_open311.t b/t/app/controller/report_new_open311.t index 17b489447..dc9a26791 100644 --- a/t/app/controller/report_new_open311.t +++ b/t/app/controller/report_new_open311.t @@ -73,12 +73,10 @@ my $empty_form = { name => '', may_show_name => '1', username => '', - email => '', phone => '', category => '', password_sign_in => '', password_register => '', - remember_me => undef, }; foreach my $test ( { @@ -249,13 +247,18 @@ subtest "Category extras omits description label when all fields are hidden" => ALLOWED_COBRANDS => [ { fixmystreet => '.' } ], MAPIT_URL => 'http://mapit.uk/', }, sub { - my $json = $mech->get_ok_json('/report/new/category_extras?category=Pothole&latitude=55.952055&longitude=-3.189579'); - my $category_extra = $json->{category_extra}; - contains_string($category_extra, "usrn"); - contains_string($category_extra, "central_asset_id"); - lacks_string($category_extra, "USRN", "Lacks 'USRN' label"); - lacks_string($category_extra, "Asset ID", "Lacks 'Asset ID' label"); - lacks_string($category_extra, "resolve your problem quicker, by providing some extra detail", "Lacks description text"); + for ( + { url => '/report/new/ajax?' }, + { url => '/report/new/category_extras?category=Pothole' }, + ) { + my $json = $mech->get_ok_json($_->{url} . '&latitude=55.952055&longitude=-3.189579'); + my $category_extra = $json->{by_category} ? $json->{by_category}{Pothole}{category_extra} : $json->{category_extra}; + contains_string($category_extra, "usrn"); + contains_string($category_extra, "central_asset_id"); + lacks_string($category_extra, "USRN", "Lacks 'USRN' label"); + lacks_string($category_extra, "Asset ID", "Lacks 'Asset ID' label"); + lacks_string($category_extra, "resolve your problem quicker, by providing some extra detail", "Lacks description text"); + } }; }; @@ -264,17 +267,22 @@ subtest "Category extras includes description label for user" => sub { ALLOWED_COBRANDS => [ { fixmystreet => '.' } ], MAPIT_URL => 'http://mapit.uk/', }, sub { - $contact4->push_extra_fields({ description => 'Size?', code => 'size', required => 'true', automated => '', variable => 'true', order => '3' }); + $contact4->push_extra_fields({ description => 'Size?', code => 'size', required => 'true', automated => '', variable => 'true', order => '3', values => undef }); $contact4->update; - - my $json = $mech->get_ok_json('/report/new/category_extras?category=Pothole&latitude=55.952055&longitude=-3.189579'); - my $category_extra = $json->{category_extra}; - contains_string($category_extra, "usrn"); - contains_string($category_extra, "central_asset_id"); - lacks_string($category_extra, "USRN", "Lacks 'USRN' label"); - lacks_string($category_extra, "Asset ID", "Lacks 'Asset ID' label"); - contains_string($category_extra, "Size?"); - contains_string($category_extra, "resolve your problem quicker, by providing some extra detail", "Contains description text"); + for ( + { url => '/report/new/ajax?' }, + { url => '/report/new/category_extras?category=Pothole' }, + ) { + my $json = $mech->get_ok_json($_->{url} . '&latitude=55.952055&longitude=-3.189579'); + my $category_extra = $json->{by_category} ? $json->{by_category}{Pothole}{category_extra} : $json->{category_extra}; + contains_string($category_extra, "usrn"); + contains_string($category_extra, "central_asset_id"); + lacks_string($category_extra, "USRN", "Lacks 'USRN' label"); + lacks_string($category_extra, "Asset ID", "Lacks 'Asset ID' label"); + contains_string($category_extra, "Size?"); + lacks_string($category_extra, '<option value=""'); + contains_string($category_extra, "resolve your problem quicker, by providing some extra detail", "Contains description text"); + } }; }; diff --git a/t/app/controller/report_new_text.t b/t/app/controller/report_new_text.t index cb07e57ee..fad7fb6ab 100644 --- a/t/app/controller/report_new_text.t +++ b/t/app/controller/report_new_text.t @@ -23,7 +23,7 @@ foreach my $test ( username => '0121 4960000000', email => '', phone => '', title => 'Title', detail => 'Detail', name => 'Bob Jones', category => 'Street lighting', - may_show_name => '1', remember_me => undef, + may_show_name => '1', photo1 => '', photo2 => '', photo3 => '', password_register => '', password_sign_in => '', }, @@ -40,7 +40,7 @@ foreach my $test ( username => '0121 4960000', email => '', phone => '', title => 'Title', detail => 'Detail', name => 'Bob Jones', category => 'Street lighting', - may_show_name => '1', remember_me => undef, + may_show_name => '1', photo1 => '', photo2 => '', photo3 => '', password_register => '', password_sign_in => '', }, @@ -222,6 +222,8 @@ subtest "test password errors for a user who is signing in as they report" => su ALLOWED_COBRANDS => [ { fixmystreet => '.' } ], MAPIT_URL => 'http://mapit.uk/', SMS_AUTHENTICATION => 1, + phone_verified => 1, + email_verified => 1, }, sub { $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB', } }, "submit location" ); $mech->follow_link_ok( { text_regex => qr/skip this step/i, }, "follow 'skip this step' link" ); @@ -245,6 +247,8 @@ subtest "test password errors for a user who is signing in as they report" => su is_deeply $mech->page_errors, [ "There was a problem with your login information. If you cannot remember your password, or do not have one, please fill in the \x{2018}No\x{2019} section of the form.", ], "check there were errors"; + + $mech->content_lacks($user->email, 'email not displayed'); }; subtest "test report creation for a user who is signing in as they report" => sub { @@ -320,7 +324,7 @@ subtest "test report creation for a user who is logged in" => sub { { title => '', detail => '', - may_show_name => '1', + may_show_name => undef, name => 'Joe Bloggs', email => 'joe@example.net', photo1 => '', diff --git a/t/app/controller/report_update_text.t b/t/app/controller/report_update_text.t index a3b767221..4ab8e4bae 100644 --- a/t/app/controller/report_update_text.t +++ b/t/app/controller/report_update_text.t @@ -71,7 +71,6 @@ for my $test ( fixed => undef, add_alert => 1, may_show_name => undef, - remember_me => undef, password_sign_in => '', password_register => '', }, @@ -90,7 +89,6 @@ for my $test ( fixed => undef, add_alert => 1, may_show_name => undef, - remember_me => undef, password_register => '', password_sign_in => '', }, diff --git a/t/app/controller/report_updates.t b/t/app/controller/report_updates.t index aba7340b0..8ff5b4d24 100644 --- a/t/app/controller/report_updates.t +++ b/t/app/controller/report_updates.t @@ -1,3 +1,14 @@ +use strict; +use warnings; + +package FixMyStreet::Cobrand::NoUpdates; + +use parent 'FixMyStreet::Cobrand::FixMyStreet'; + +sub updates_disallowed { 1 } + +package main; + use FixMyStreet::TestMech; use Web::Scraper; use Path::Class; @@ -175,6 +186,20 @@ subtest "several updates shown in correct order" => sub { old_state => 'confirmed', new_state => 'fixed - user', }, + { # One reopening, no associated update + problem_id => $report_id, + whensent => '2011-03-16 08:12:36', + whenanswered => '2011-03-16 08:12:36', + old_state => 'fixed - user', + new_state => 'confirmed', + }, + { # One marking fixed, no associated update + problem_id => $report_id, + whensent => '2011-03-17 08:12:36', + whenanswered => '2011-03-17 08:12:36', + old_state => 'confirmed', + new_state => 'fixed - user', + }, ) { my $q = FixMyStreet::App->model('DB::Questionnaire')->find_or_create( $fields @@ -229,13 +254,15 @@ subtest "several updates shown in correct order" => sub { $mech->get_ok("/report/$report_id"); my $meta = $mech->extract_update_metas; - is scalar @$meta, 6, 'number of updates'; + is scalar @$meta, 8, 'number of updates'; is $meta->[0], 'Posted by Other User at 12:23, Thu 10 March 2011', 'first update'; is $meta->[1], 'Posted by Main User at 12:23, Thu 10 March 2011 Still open, via questionnaire', 'second update'; is $meta->[2], 'Still open, via questionnaire, 12:23, Fri 11 March 2011', 'questionnaire'; is $meta->[3], 'Still open, via questionnaire, 12:23, Sat 12 March 2011', 'questionnaire'; is $meta->[4], 'State changed to: Fixed', 'third update, part 1'; is $meta->[5], 'Posted anonymously at 08:12, Tue 15 March 2011', 'third update, part 2'; + is $meta->[6], 'Still open, via questionnaire, 08:12, Wed 16 March 2011', 'reopen questionnaire'; + is $meta->[7], 'Questionnaire filled in by problem reporter; State changed to: Fixed, 08:12, Thu 17 March 2011', 'fix questionnaire'; $report->questionnaires->delete; }; @@ -252,7 +279,6 @@ for my $test ( fixed => undef, add_alert => 1, may_show_name => undef, - remember_me => undef, password_register => '', password_sign_in => '', }, @@ -271,7 +297,6 @@ for my $test ( fixed => undef, add_alert => 1, may_show_name => undef, - remember_me => undef, password_sign_in => '', password_register => '', }, @@ -290,7 +315,6 @@ for my $test ( fixed => undef, add_alert => 1, may_show_name => undef, - remember_me => undef, password_register => '', password_sign_in => '', }, @@ -311,7 +335,6 @@ for my $test ( fixed => undef, add_alert => 1, may_show_name => undef, - remember_me => undef, password_register => '', password_sign_in => '', }, @@ -345,14 +368,13 @@ for my $test ( initial_values => { name => '', username => '', - may_show_name => 1, + may_show_name => undef, add_alert => 1, photo1 => '', photo2 => '', photo3 => '', update => '', fixed => undef, - remember_me => undef, password_register => '', password_sign_in => '', }, @@ -371,14 +393,13 @@ for my $test ( initial_values => { name => '', username => '', - may_show_name => 1, + may_show_name => undef, add_alert => 1, photo1 => '', photo2 => '', photo3 => '', update => '', fixed => undef, - remember_me => undef, password_register => '', password_sign_in => '', }, @@ -475,14 +496,13 @@ for my $test ( initial_values => { name => '', username => '', - may_show_name => 1, + may_show_name => undef, add_alert => 1, photo1 => '', photo2 => '', photo3 => '', update => '', fixed => undef, - remember_me => undef, password_register => '', password_sign_in => '', }, @@ -577,7 +597,6 @@ subtest 'check non authority user cannot change set state' => sub { for my $state ( qw/unconfirmed hidden partial/ ) { subtest "check that update cannot set state to $state" => sub { - $mech->log_in_ok( $user->email ); $user->from_body( $body->id ); $user->update; @@ -726,8 +745,6 @@ for my $test ( $report->update; } - $mech->log_in_ok( $user->email ); - if ($test->{view_username}) { ok $user->user_body_permissions->create({ body => $body, @@ -809,7 +826,6 @@ subtest 'check meta correct for comments marked confirmed but not marked open' = }; subtest "check first comment with no status change has no status in meta" => sub { - $mech->log_in_ok( $user->email ); $user->from_body( undef ); $user->update; @@ -823,7 +839,6 @@ subtest "check first comment with no status change has no status in meta" => sub }; subtest "check comment with no status change has not status in meta" => sub { - $mech->log_in_ok( $user->email ); $user->from_body( undef ); $user->update; @@ -1066,8 +1081,6 @@ subtest $test->{desc} => sub { extra => $extra, } ); - $mech->log_in_ok( $user->email ); - ok $user->user_body_permissions->search({ body_id => $body->id, @@ -1132,7 +1145,6 @@ subtest $test->{desc} => sub { extra => $extra, } ); - $mech->log_in_ok( $user->email ); $mech->get_ok("/report/$report_id"); my $update_meta = $mech->extract_update_metas; @@ -1186,7 +1198,6 @@ subtest $test->{desc} => sub { } ); } - $mech->log_in_ok( $user->email ); $mech->get_ok("/report/$report_id"); my $update_meta = $mech->extract_update_metas; @@ -2150,4 +2161,20 @@ subtest 'check cannot answer other user\'s creator fixed questionnaire' => sub { $mech->content_contains( "I'm afraid we couldn't locate your problem in the database." ) }; +subtest 'updates can be provided' => sub { + $mech->log_out_ok(); + $mech->get( "/report/$report_id" ); + $mech->content_contains("Provide an update"); +}; + +FixMyStreet::override_config { + ALLOWED_COBRANDS => [ { 'noupdates' => '.' } ], +}, sub { + subtest 'test cobrand updates_disallowed' => sub { + $mech->log_out_ok(); + $mech->get( "/report/$report_id" ); + $mech->content_lacks("Provide an update"); + }; +}; + done_testing(); diff --git a/t/app/controller/reports.t b/t/app/controller/reports.t index 8cdfddd1b..ac230ef95 100644 --- a/t/app/controller/reports.t +++ b/t/app/controller/reports.t @@ -1,7 +1,7 @@ use Test::MockTime qw(:all); use FixMyStreet::TestMech; use mySociety::MaPit; -use FixMyStreet::App; +use FixMyStreet::DB; use FixMyStreet::Script::UpdateAllReports; use DateTime; @@ -95,8 +95,19 @@ $fife_problems[10]->update( { state => 'hidden', }); -# Run the cron script old-data (for the table no longer used by default) -FixMyStreet::Script::UpdateAllReports::generate(1); +FixMyStreet::override_config { + ALLOWED_COBRANDS => 'fixmystreet', +}, sub { + subtest 'Test the cron script old-data (for the table no longer used by default)' => sub { + FixMyStreet::Script::UpdateAllReports::generate(1); + + # Old style page no longer exists in core, but let's just check the code works okay + my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker('fixmystreet')->new(); + FixMyStreet::DB->schema->cobrand($cobrand); + my @bodies = FixMyStreet::DB->resultset('Body')->active->translated->all_sorted; + is $bodies[0]->{url}->(), '/reports/Birmingham'; + }; +}; # Run the cron script that makes the data for /reports so we don't get an error. my $data = FixMyStreet::Script::UpdateAllReports::generate_dashboard(); @@ -115,19 +126,20 @@ $mech->content_contains('5,9,10,22'); $mech->content_contains('2,3,4,4'); FixMyStreet::override_config { + ALLOWED_COBRANDS => 'fixmystreet', MAPIT_URL => 'http://mapit.uk/', }, sub { $mech->submit_form_ok( { with_fields => { body => $body_edin_id } }, 'Submitted dropdown okay' ); - is $mech->uri->path, '/reports/City+of+Edinburgh+Council'; + is $mech->uri->path, '/reports/City+of+Edinburgh'; subtest "test ward pages" => sub { $mech->get_ok('/reports/Birmingham/Bad-Ward'); - is $mech->uri->path, '/reports/Birmingham+City+Council'; - $mech->get_ok('/reports/Birmingham/Aston'); - is $mech->uri->path, '/reports/Birmingham+City+Council/Aston'; - $mech->get_ok('/reports/Birmingham/Aston|Bournville'); - is $mech->uri->path, '/reports/Birmingham+City+Council/Aston%7CBournville'; - $mech->content_contains('Aston, Bournville'); + is $mech->uri->path, '/reports/Birmingham'; + $mech->get_ok('/reports/Birmingham/Bordesley+and+Highgate'); + is $mech->uri->path, '/reports/Birmingham/Bordesley+and+Highgate'; + $mech->get_ok('/reports/Birmingham/Bordesley+and+Highgate|Birchfield'); + is $mech->uri->path, '/reports/Birmingham/Bordesley+and+Highgate%7CBirchfield'; + $mech->content_contains('Birchfield, Bordesley & Highgate'); }; $mech->get_ok('/reports/Westminster'); @@ -203,6 +215,93 @@ is scalar @$problems, 4, 'only public problems are displayed'; $mech->content_lacks('All reports Test 3 for ' . $body_west_id, 'non public problem is not visible'); +for my $permission( qw/ report_inspect report_mark_private / ) { + subtest "user with $permission permission can see non public reports" => sub { + my $body = FixMyStreet::DB->resultset('Body')->find( $body_west_id ); + my $body2 = FixMyStreet::DB->resultset('Body')->find( $body_edin_id ); + my $user = $mech->log_in_ok( 'test@example.com' ); + + # from body, no permission + $user->user_body_permissions->delete(); + $user->update({ from_body => $body }); + + FixMyStreet::override_config { + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $mech->get_ok('/reports/Westminster'); + }; + $problems = $mech->extract_problem_list; + is scalar @$problems, 4, 'only public problems are displayed if no permission'; + $mech->content_lacks('All reports Test 3 for ' . $body_west_id, 'non public problem is not visible if no permission'); + $mech->content_lacks('<option value="non_public">Private only</option>'); + + # from body, no permission, limited to private in url + FixMyStreet::override_config { + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $mech->get_ok('/reports/Westminster?status=non_public'); + }; + $problems = $mech->extract_problem_list; + is scalar @$problems, 4, 'only public problems are displayed if no permission, despite override'; + $mech->content_lacks('All reports Test 3 for ' . $body_west_id, 'non public problem is not visible despite override'); + + # from body, has permission + $user->user_body_permissions->find_or_create({ + body => $body, + permission_type => $permission, + }); + + FixMyStreet::override_config { + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $mech->get_ok('/reports/Westminster'); + }; + $problems = $mech->extract_problem_list; + is scalar @$problems, 5, 'public and non-public problems are displayed if permission'; + $mech->content_contains('All reports Test 3 for ' . $body_west_id, 'non public problem is visible if permission'); + $mech->content_contains('<option value="non_public">Private only</option>'); + + # From body, limited to private only + FixMyStreet::override_config { + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $mech->get_ok('/reports/Westminster?status=non_public'); + }; + $problems = $mech->extract_problem_list; + is scalar @$problems, 1, 'only non-public problems are displayed with non_public filter'; + $mech->content_contains('All reports Test 3 for ' . $body_west_id, 'non public problem is visible with non_public filter'); + $mech->content_lacks('All reports Test 4 for ' . $body_west_id, 'public problem is not visible with non_public filter'); + + # from other body, has permission + $user->user_body_permissions->delete(); + $user->update({ from_body => $body2 }); + $user->user_body_permissions->find_or_create({ + body => $body2, + permission_type => $permission, + }); + + FixMyStreet::override_config { + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $mech->get_ok('/reports/Westminster'); + }; + $problems = $mech->extract_problem_list; + is scalar @$problems, 4, 'only public problems are displayed for other body user'; + $mech->content_contains('<option value="non_public">Private only</option>'); + $mech->content_lacks('All reports Test 3 for ' . $body_west_id, 'non public problem is not visible for other body user'); + + # From other body, limited to private only + FixMyStreet::override_config { + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $mech->get_ok('/reports/Westminster?status=non_public'); + }; + $problems = $mech->extract_problem_list; + is scalar @$problems, 4, 'non-public problems are not displayed for other body with override'; + $mech->content_lacks('All reports Test 3 for ' . $body_west_id, 'non public problem is not visible for other body with override'); + }; +} + # No change to numbers if report is non-public FixMyStreet::override_config { TEST_DASHBOARD_DATA => $data, @@ -253,7 +352,7 @@ subtest "it lists shortlisted reports" => sub { FixMyStreet::override_config { MAPIT_URL => 'http://mapit.uk/' }, sub { - my $body = FixMyStreet::App->model('DB::Body')->find( $body_edin_id ); + my $body = FixMyStreet::DB->resultset('Body')->find( $body_edin_id ); my $user = $mech->log_in_ok( 'test@example.com' ); $user->update({ from_body => $body }); $user->user_body_permissions->find_or_create({ @@ -303,7 +402,7 @@ subtest "it allows body users to filter by subtypes" => sub { FixMyStreet::override_config { MAPIT_URL => 'http://mapit.uk/' }, sub { - my $body = FixMyStreet::App->model('DB::Body')->find( $body_edin_id ); + my $body = FixMyStreet::DB->resultset('Body')->find( $body_edin_id ); my $user = $mech->log_in_ok( 'test@example.com' ); $user->update({ from_body => $body }); @@ -362,7 +461,7 @@ subtest "it does not allow body users to filter subcategories for other bodies" FixMyStreet::override_config { MAPIT_URL => 'http://mapit.uk/' }, sub { - my $body = FixMyStreet::App->model('DB::Body')->find( $body_west_id ); + my $body = FixMyStreet::DB->resultset('Body')->find( $body_west_id ); my $user = $mech->log_in_ok( 'test@example.com' ); $user->update({ from_body => $body }); diff --git a/t/app/controller/root.t b/t/app/controller/root.t index ddf659b77..85119da24 100644 --- a/t/app/controller/root.t +++ b/t/app/controller/root.t @@ -1,4 +1,5 @@ use FixMyStreet::TestMech; +use Test::MockModule; ok( my $mech = FixMyStreet::TestMech->new, 'Created mech object' ); @@ -73,4 +74,17 @@ FixMyStreet::override_config { }; }; +subtest "check_login_disallowed cobrand hook" => sub { + my $cobrand = Test::MockModule->new('FixMyStreet::Cobrand::Default'); + $cobrand->mock('check_login_disallowed', sub { + my $self = shift; + return 0 if $self->{c}->req->path eq 'auth'; + return 1; + } + ); + + $mech->get_ok('/'); + is $mech->uri->path_query, '/auth?r=', 'redirects to auth page'; +}; + done_testing(); |