diff options
Diffstat (limited to 't/app/controller/admin')
-rw-r--r-- | t/app/controller/admin/bodies.t | 129 | ||||
-rw-r--r-- | t/app/controller/admin/defecttypes.t | 21 | ||||
-rw-r--r-- | t/app/controller/admin/manifesttheme.t | 340 | ||||
-rw-r--r-- | t/app/controller/admin/permissions.t | 8 | ||||
-rw-r--r-- | t/app/controller/admin/priorities.t | 43 | ||||
-rw-r--r-- | t/app/controller/admin/report_edit.t | 25 | ||||
-rw-r--r-- | t/app/controller/admin/reportextrafields.t | 131 | ||||
-rw-r--r-- | t/app/controller/admin/roles.t | 139 | ||||
-rw-r--r-- | t/app/controller/admin/search.t | 6 | ||||
-rw-r--r-- | t/app/controller/admin/templates.t | 159 | ||||
-rw-r--r-- | t/app/controller/admin/translations.t | 2 | ||||
-rw-r--r-- | t/app/controller/admin/triage.t | 126 | ||||
-rw-r--r-- | t/app/controller/admin/update_edit.t | 30 | ||||
-rw-r--r-- | t/app/controller/admin/users.t | 159 | ||||
-rw-r--r-- | t/app/controller/admin/users_import.t | 34 |
15 files changed, 1161 insertions, 191 deletions
diff --git a/t/app/controller/admin/bodies.t b/t/app/controller/admin/bodies.t index f67e45bf6..c73a90da1 100644 --- a/t/app/controller/admin/bodies.t +++ b/t/app/controller/admin/bodies.t @@ -1,10 +1,3 @@ -package FixMyStreet::Cobrand::Tester; - -use parent 'FixMyStreet::Cobrand::Default'; - -sub enable_category_groups { 1 } - -package main; use FixMyStreet::TestMech; my $mech = FixMyStreet::TestMech->new; @@ -58,7 +51,7 @@ subtest 'check contact creation' => sub { non_public => 'on', } } ); $mech->get_ok('/admin/body/' . $body->id . '/test/category'); - $mech->content_contains('<h1>test/category</h1>'); + $mech->content_contains('test/category'); }; subtest 'check contact editing' => sub { @@ -98,6 +91,21 @@ subtest 'check contact editing' => sub { $mech->content_contains( '<td><strong>test2@example.com' ); }; +subtest 'check contact renaming' => sub { + my ($report) = $mech->create_problems_for_body(1, $body->id, 'Title', { category => 'test category' }); + $mech->get_ok('/admin/body/' . $body->id .'/test%20category'); + $mech->submit_form_ok( { with_fields => { category => 'private category' } } ); + $mech->content_contains('You cannot rename'); + $mech->submit_form_ok( { with_fields => { category => 'testing category' } } ); + $mech->content_contains( 'testing category' ); + $mech->get('/admin/body/' . $body->id . '/test%20category'); + is $mech->res->code, 404; + $mech->get_ok('/admin/body/' . $body->id . '/testing%20category'); + $report->discard_changes; + is $report->category, 'testing category'; + $mech->submit_form_ok( { with_fields => { category => 'test category' } } ); +}; + subtest 'check contact updating' => sub { $mech->get_ok('/admin/body/' . $body->id . '/test%20category'); $mech->content_like(qr{test2\@example.com</strong>[^<]*</td>[^<]*<td>unconfirmed}s); @@ -134,7 +142,7 @@ subtest 'check open311 configuring' => sub { $mech->content_contains('Council contacts configured via Open311'); $mech->content_contains('Values updated'); - my $conf = FixMyStreet::App->model('DB::Body')->find( $body->id ); + my $conf = FixMyStreet::DB->resultset('Body')->find( $body->id ); is $conf->endpoint, 'http://example.com/open311', 'endpoint configured'; is $conf->api_key, 'api key', 'api key configured'; is $conf->jurisdiction, 'mySociety', 'jurisdiction configures'; @@ -154,7 +162,7 @@ subtest 'check open311 configuring' => sub { $mech->content_contains('Values updated'); - $conf = FixMyStreet::App->model('DB::Body')->find( $body->id ); + $conf = FixMyStreet::DB->resultset('Body')->find( $body->id ); is $conf->endpoint, 'http://example.org/open311', 'endpoint updated'; is $conf->api_key, 'new api key', 'api key updated'; is $conf->jurisdiction, 'open311', 'jurisdiction configures'; @@ -169,14 +177,14 @@ subtest 'check open311 configuring' => sub { jurisdiction => 'open311', send_comments => 0, send_method => 'Open311', - fetch_all_problems => 1, + 'extra[fetch_all_problems]' => 1, } } ); $mech->content_contains('Values updated'); - $conf = FixMyStreet::App->model('DB::Body')->find( $body->id ); + $conf = FixMyStreet::DB->resultset('Body')->find( $body->id ); ok $conf->get_extra_metadata('fetch_all_problems'), 'fetch all problems set'; $mech->form_number(3); @@ -188,17 +196,35 @@ subtest 'check open311 configuring' => sub { jurisdiction => 'open311', send_comments => 0, send_method => 'Open311', - fetch_all_problems => 0, + 'extra[fetch_all_problems]' => 0, + can_be_devolved => 1, # for next test } } ); $mech->content_contains('Values updated'); - $conf = FixMyStreet::App->model('DB::Body')->find( $body->id ); + $conf = FixMyStreet::DB->resultset('Body')->find( $body->id ); ok !$conf->get_extra_metadata('fetch_all_problems'), 'fetch all problems unset'; }; +subtest 'check open311 devolved editing' => sub { + $mech->get_ok('/admin/body/' . $body->id . '/test%20category'); + $mech->submit_form_ok( { with_fields => { + send_method => 'Email', + email => 'testing@example.org', + note => 'Updating contact to email', + } } ); + $mech->content_contains('Values updated'); + $mech->get_ok('/admin/body/' . $body->id . '/test%20category'); + $mech->submit_form_ok( { with_fields => { + send_method => '', + email => 'open311-code', + note => 'Removing email send method', + } } ); + $mech->content_contains('Values updated'); +}; + subtest 'check text output' => sub { $mech->get_ok('/admin/body/' . $body->id . '?text=1'); is $mech->content_type, 'text/plain'; @@ -206,18 +232,49 @@ subtest 'check text output' => sub { $mech->content_lacks('<body'); }; +subtest 'disable form message editing' => sub { + $mech->get_ok('/admin/body/' . $body->id . '/test%20category'); + $mech->submit_form_ok( { with_fields => { + disable => 1, + disable_message => '<em>Please</em> <u>ring</u> us on <a href="tel:01234">01234</a>, click <a href="javascript:bad">bad</a>', + note => 'Adding emergency message', + } } ); + $mech->content_contains('Values updated'); + my $contact = $body->contacts->find({ category => 'test category' }); + is_deeply $contact->get_extra_fields, [{ + description => '<em>Please</em> ring us on <a href="tel:01234">01234</a>, click <a>bad</a>', + code => '_fms_disable_', + protected => 'true', + variable => 'false', + disable_form => 'true', + }], 'right message added'; +}; + +subtest 'open311 protection editing' => sub { + $mech->get_ok('/admin/body/' . $body->id . '/test%20category'); + $mech->submit_form_ok( { with_fields => { + open311_protect => 1, + note => 'Protected from Open311 changes', + } } ); + $mech->content_contains('Values updated'); + my $contact = $body->contacts->find({ category => 'test category' }); + is $contact->get_extra_metadata('open311_protect'), 1, 'Open311 protect flag set'; +}; + }; # END of override wrap FixMyStreet::override_config { - ALLOWED_COBRANDS => ['tester'], MAPIT_URL => 'http://mapit.uk/', MAPIT_TYPES => [ 'UTA' ], BASE_URL => 'http://www.example.org', + COBRAND_FEATURES => { + category_groups => { default => 1 }, + } }, sub { subtest 'group editing works' => sub { $mech->get_ok('/admin/body/' . $body->id); - $mech->content_contains( 'group</strong> is used for the top-level category' ); + $mech->content_contains('Parent categories'); $mech->submit_form_ok( { with_fields => { category => 'grouped category', @@ -229,12 +286,12 @@ FixMyStreet::override_config { } } ); my $contact = $body->contacts->find({ category => 'grouped category' }); - is $contact->get_extra_metadata('group'), 'group a', "group stored correctly"; + is_deeply $contact->get_extra_metadata('group'), ['group a'], "group stored correctly"; }; subtest 'group can be unset' => sub { $mech->get_ok('/admin/body/' . $body->id); - $mech->content_contains( 'group</strong> is used for the top-level category' ); + $mech->content_contains('Parent categories'); $mech->submit_form_ok( { with_fields => { category => 'grouped category', @@ -251,5 +308,41 @@ FixMyStreet::override_config { }; +FixMyStreet::override_config { + MAPIT_URL => 'http://mapit.uk/', + MAPIT_TYPES => [ 'UTA' ], + BASE_URL => 'http://www.example.org', + COBRAND_FEATURES => { + category_groups => { default => 1 }, + } +}, sub { + subtest 'multi group editing works' => sub { + $mech->get_ok('/admin/body/' . $body->id); + $mech->content_contains('Parent categories'); + + # have to do this as a post as adding a second group requires + # javascript + $mech->post_ok( '/admin/body/' . $body->id, { + posted => 'new', + token => $mech->form_id('category_edit')->value('token'), + category => 'grouped category', + email => 'test@example.com', + note => 'test note', + 'group' => [ 'group a', 'group b'], + non_public => undef, + state => 'unconfirmed', + } ); + + my $contact = $body->contacts->find({ category => 'grouped category' }); + is_deeply $contact->get_extra_metadata('group'), ['group a', 'group b'], "group stored correctly"; + }; +}; + +subtest 'check log of the above' => sub { + $mech->get_ok('/admin/users/' . $superuser->id . '/log'); + $mech->content_contains('Added category <a href="/admin/body/' . $body->id . '/test/category">test/category</a>'); + $mech->content_contains('Edited category <a href="/admin/body/' . $body->id . '/test category">test category</a>'); + $mech->content_contains('Edited body <a href="/admin/body/' . $body->id . '">Aberdeen City Council</a>'); +}; done_testing(); diff --git a/t/app/controller/admin/defecttypes.t b/t/app/controller/admin/defecttypes.t index 12ae8948c..15fdac2f8 100644 --- a/t/app/controller/admin/defecttypes.t +++ b/t/app/controller/admin/defecttypes.t @@ -1,5 +1,4 @@ use FixMyStreet::TestMech; -use Test::MockModule; my $mech = FixMyStreet::TestMech->new; @@ -27,16 +26,6 @@ FixMyStreet::override_config { ALLOWED_COBRANDS => ['bromley'], }, sub { FixMyStreet::override_config { ALLOWED_COBRANDS => ['oxfordshire'], }, sub { - my $cobrand = Test::MockModule->new('FixMyStreet::Cobrand::Oxfordshire'); - $cobrand->mock('available_permissions', sub { - my $self = shift; - - my $perms = FixMyStreet::Cobrand::Default->available_permissions; - $perms->{Bodies}->{defect_type_edit} = "Add/edit defect types"; - - return $perms; - }); - my $body = $mech->create_body_ok( 2237, 'Oxfordshire County Council' ); subtest 'check defect types menu available to superusers' => sub { @@ -107,7 +96,7 @@ FixMyStreet::override_config { ALLOWED_COBRANDS => ['oxfordshire'], }, sub { }; subtest 'check editing a defect type' => sub { - my $defect = FixMyStreet::App->model('DB::DefectType')->search( { + my $defect = FixMyStreet::DB->resultset('DefectType')->search( { name => 'A defect', body_id => $body->id } )->first; @@ -126,7 +115,7 @@ FixMyStreet::override_config { ALLOWED_COBRANDS => ['oxfordshire'], }, sub { $mech->content_lacks('A defect'); $mech->content_contains('Updated defect'); - my $defects = FixMyStreet::App->model('DB::DefectType')->search( { + my $defects = FixMyStreet::DB->resultset('DefectType')->search( { body_id => $body->id } ); @@ -134,7 +123,7 @@ FixMyStreet::override_config { ALLOWED_COBRANDS => ['oxfordshire'], }, sub { }; subtest 'check adding a category to a defect' => sub { - my $defect = FixMyStreet::App->model('DB::DefectType')->search( { + my $defect = FixMyStreet::DB->resultset('DefectType')->search( { name => 'Updated defect', body_id => $body->id } )->first; @@ -163,7 +152,7 @@ FixMyStreet::override_config { ALLOWED_COBRANDS => ['oxfordshire'], }, sub { }; subtest 'check removing category from a defect' => sub { - my $defect = FixMyStreet::App->model('DB::DefectType')->search( { + my $defect = FixMyStreet::DB->resultset('DefectType')->search( { name => 'Updated defect', body_id => $body->id } )->first; @@ -191,7 +180,7 @@ FixMyStreet::override_config { ALLOWED_COBRANDS => ['oxfordshire'], }, sub { }; subtest 'check adding codes to a defect' => sub { - my $defect = FixMyStreet::App->model('DB::DefectType')->search( { + my $defect = FixMyStreet::DB->resultset('DefectType')->search( { name => 'Updated defect', body_id => $body->id } )->first; diff --git a/t/app/controller/admin/manifesttheme.t b/t/app/controller/admin/manifesttheme.t new file mode 100644 index 000000000..c1b2d4542 --- /dev/null +++ b/t/app/controller/admin/manifesttheme.t @@ -0,0 +1,340 @@ +use Path::Tiny; +use FixMyStreet::DB; +use FixMyStreet::TestMech; + +my $mech = FixMyStreet::TestMech->new; + +my $superuser = $mech->create_user_ok('superuser@example.com', name => 'Super User', is_superuser => 1); + +$mech->log_in_ok( $superuser->email ); + +FixMyStreet::override_config { + ALLOWED_COBRANDS => [ 'lincolnshire', 'tfl', 'fixmystreet' ], +}, sub { + +ok $mech->host('lincolnshire.fixmystreet.com'); + +subtest "theme link on cobrand admin goes to create form if no theme exists" => sub { + is( FixMyStreet::DB->resultset('ManifestTheme')->count, 0, "no themes yet" ); + + $mech->get_ok("/admin"); + $mech->follow_link_ok({ text => "Manifest Theme" }); + + is $mech->res->previous->code, 302, "got 302 for redirect"; + is $mech->res->previous->base->path, "/admin/manifesttheme", "redirected from index"; + is $mech->uri->path, '/admin/manifesttheme/create', "redirected to create page"; +}; + +subtest "name and short_name are required fields" => sub { + is( FixMyStreet::DB->resultset('ManifestTheme')->count, 0, "no themes yet" ); + + $mech->get_ok("/admin/manifesttheme/create"); + $mech->content_lacks("Delete theme"); + + $mech->submit_form_ok({}); + is $mech->uri->path, '/admin/manifesttheme/create', "stayed on create page"; + $mech->content_contains("field is required"); + is( FixMyStreet::DB->resultset('ManifestTheme')->count, 0, "theme not created" ); + + $mech->get_ok("/admin/manifesttheme/create"); + $mech->submit_form_ok({ with_fields => { short_name => "Lincs FMS" } }); + is $mech->uri->path, '/admin/manifesttheme/create', "stayed on create page"; + $mech->content_contains("field is required", "name is required"); + is( FixMyStreet::DB->resultset('ManifestTheme')->count, 0, "theme not created" ); + + $mech->get_ok("/admin/manifesttheme/create"); + $mech->submit_form_ok({ with_fields => { name => "Lincolnshire FixMyStreet" } }); + is $mech->uri->path, '/admin/manifesttheme/create', "stayed on create page"; + $mech->content_contains("field is required", "short_name is required"); + is( FixMyStreet::DB->resultset('ManifestTheme')->count, 0, "theme not created" ); +}; + +subtest "cobrand admin lets you create a new theme" => sub { + is( FixMyStreet::DB->resultset('ManifestTheme')->count, 0, "no themes yet" ); + + $mech->get_ok("/admin/manifesttheme/create"); + $mech->content_lacks("Delete theme"); + + my $fields = { + name => "Lincolnshire FixMyStreet", + short_name => "Lincs FMS", + }; + $mech->submit_form_ok( { with_fields => $fields } ); + is $mech->uri->path, '/admin/manifesttheme/lincolnshire', "redirected to edit page"; + is( FixMyStreet::DB->resultset('ManifestTheme')->count, 1, "theme was created" ); + + my $theme = FixMyStreet::DB->resultset('ManifestTheme')->find({ cobrand => 'lincolnshire' }); + is $theme->name, "Lincolnshire FixMyStreet"; + is $theme->short_name, "Lincs FMS"; + is $theme->background_colour, undef; + + my $log = $superuser->admin_logs->search({}, { order_by => { -desc => 'id' } })->first; + is $log->object_id, $theme->id; + is $log->action, "add"; + is $log->object_summary, "lincolnshire"; + is $log->link, "/admin/manifesttheme/lincolnshire"; +}; + +subtest "cobrand admin lets you update an existing theme" => sub { + $mech->get_ok("/admin/manifesttheme/lincolnshire"); + + my $fields = { + background_colour => "#663399", + theme_colour => "rgb(102, 51, 153)", + }; + $mech->submit_form_ok( { with_fields => $fields } ); + + my $theme = FixMyStreet::DB->resultset('ManifestTheme')->find({ cobrand => 'lincolnshire' }); + is $theme->background_colour, "#663399"; + is $theme->theme_colour, "rgb(102, 51, 153)"; + + my $log = $superuser->admin_logs->search({}, { order_by => { -desc => 'id' } })->first; + is $log->object_id, $theme->id; + is $log->action, "edit"; +}; + +subtest "cobrand admin lets you add an icon to an existing theme" => sub { + $mech->get_ok("/admin/manifesttheme/lincolnshire"); + + my $sample_jpeg = path(__FILE__)->parent->parent->child("sample.jpg"); + ok $sample_jpeg->exists, "sample image $sample_jpeg exists"; + my $icon_filename = '74e3362283b6ef0c48686fb0e161da4043bbcc97.jpg'; + + $mech->post( '/admin/manifesttheme/lincolnshire', + Content_Type => 'form-data', + Content => { + name => "Lincolnshire FixMyStreet", + short_name => "Lincs FMS", + background_colour => "#663399", + theme_colour => "rgb(102, 51, 153)", + cobrand => 'lincolnshire', + icon => [ $sample_jpeg, undef, Content_Type => 'image/jpeg' ], + }, + ); + ok $mech->success, 'Posted request successfully'; + + is $mech->uri->path, '/admin/manifesttheme/lincolnshire', "redirected back to edit page"; + $mech->content_contains("<img src=\"/theme/lincolnshire/" . $icon_filename); + $mech->content_contains("<td class=\"icon-size\">133x100</td>"); + my $icon_dest = path(FixMyStreet->path_to('web/theme/lincolnshire/', $icon_filename)); + ok $icon_dest->exists, "Icon stored on disk"; +}; + +subtest "cobrand admin lets you delete an icon from an existing theme" => sub { + my $icon_filename = '74e3362283b6ef0c48686fb0e161da4043bbcc97.jpg'; + my $icon_dest = path(FixMyStreet->path_to('web/theme/lincolnshire/', $icon_filename)); + ok $icon_dest->exists, "Icon exists on disk"; + + $mech->get_ok("/admin/manifesttheme/lincolnshire"); + my $fields = { + delete_icon => "/theme/lincolnshire/$icon_filename", + }; + $mech->submit_form_ok( { with_fields => $fields } ); + + is $mech->uri->path, '/admin/manifesttheme/lincolnshire', "redirected back to edit page"; + $mech->content_lacks("<img src=\"/theme/lincolnshire/" . $icon_filename); + $mech->content_lacks("<td class=\"icon-size\">133x100</td>"); + ok !$icon_dest->exists, "Icon removed from disk"; +}; + +subtest "cobrand admin rejects non-images" => sub { + $mech->get_ok("/admin/manifesttheme/lincolnshire"); + + my $sample_pdf = path(__FILE__)->parent->parent->child("sample.pdf"); + ok $sample_pdf->exists, "sample image $sample_pdf exists"; + + $mech->post( '/admin/manifesttheme/lincolnshire', + Content_Type => 'form-data', + Content => { + name => "Lincolnshire FixMyStreet", + short_name => "Lincs FMS", + background_colour => "#663399", + theme_colour => "rgb(102, 51, 153)", + cobrand => 'lincolnshire', + icon => [ $sample_pdf, undef, Content_Type => 'application/pdf' ], + }, + ); + ok $mech->success, 'Posted request successfully'; + + is $mech->uri->path, '/admin/manifesttheme/lincolnshire', "redirected back to edit page"; + $mech->content_lacks("90f7a64043fb458d58de1a0703a6355e2856b15e.pdf"); + $mech->content_contains("File type not recognised. Please upload an image."); +}; + +subtest "theme link on cobrand admin goes to edit form when theme exists" => sub { + is( FixMyStreet::DB->resultset('ManifestTheme')->count, 1, "theme exists" ); + + $mech->get_ok("/admin"); + $mech->follow_link_ok({ text => "Manifest Theme" }); + + is $mech->res->previous->code, 302, "got 302 for redirect"; + is $mech->res->previous->base->path, "/admin/manifesttheme", "redirected from index"; + is $mech->uri->path, '/admin/manifesttheme/lincolnshire', "redirected to edit page"; +}; + +subtest "create page on cobrand admin redirects to edit form when theme exists" => sub { + is( FixMyStreet::DB->resultset('ManifestTheme')->count, 1, "theme exists" ); + + $mech->get_ok("/admin/manifesttheme/create"); + + is $mech->res->previous->code, 302, "got 302 for redirect"; + is $mech->uri->path, '/admin/manifesttheme/lincolnshire', "redirected to edit page"; +}; + +subtest "can delete theme" => sub { + is( FixMyStreet::DB->resultset('ManifestTheme')->count, 1, "theme exists" ); + + my $theme_id = FixMyStreet::DB->resultset('ManifestTheme')->find({ cobrand => 'lincolnshire' })->id; + + # Add an icon so we can test it gets deleted when the theme is deleted + my $sample_jpeg = path(__FILE__)->parent->parent->child("sample.jpg"); + ok $sample_jpeg->exists, "sample image $sample_jpeg exists"; + my $icon_filename = '74e3362283b6ef0c48686fb0e161da4043bbcc97.jpg'; + + $mech->post( '/admin/manifesttheme/lincolnshire', + Content_Type => 'form-data', + Content => { + name => "Lincolnshire FixMyStreet", + short_name => "Lincs FMS", + background_colour => "#663399", + theme_colour => "rgb(102, 51, 153)", + cobrand => "lincolnshire", + icon => [ $sample_jpeg, undef, Content_Type => 'image/jpeg' ], + }, + ); + ok $mech->success, 'Posted request successfully'; + + is $mech->uri->path, '/admin/manifesttheme/lincolnshire', "redirected back to edit page"; + my $icon_dest = path(FixMyStreet->path_to('web/theme/lincolnshire/', $icon_filename)); + ok $icon_dest->exists, "Icon stored on disk"; + + $mech->submit_form_ok({ button => 'delete_theme' }); + is $mech->uri->path, '/admin/manifesttheme/create', "redirected to create page"; + + is( FixMyStreet::DB->resultset('ManifestTheme')->count, 0, "theme deleted" ); + ok !$icon_dest->exists, "Icon removed from disk"; + + my $log = $superuser->admin_logs->search({}, { order_by => { -desc => 'id' } })->first; + is $log->object_id, $theme_id; + is $log->action, "delete"; +}; + +subtest "can't edit another cobrand's theme" => sub { + FixMyStreet::DB->resultset('ManifestTheme')->create({ + cobrand => "tfl", + name => "Transport for London Street Care", + short_name => "TfL Street Care", + }); + + $mech->get("/admin/manifesttheme/tfl"); + ok !$mech->res->is_success(), "want a bad response"; + is $mech->res->code, 404, "got 404"; +}; + +ok $mech->host('www.fixmystreet.com'); + +subtest "fms cobrand lets you view all manifest themes" => sub { + is( FixMyStreet::DB->resultset('ManifestTheme')->count, 1, "theme already exists" ); + + $mech->get_ok("/admin"); + $mech->follow_link_ok({ text => "Manifest Theme" }); + + is $mech->uri->path, '/admin/manifesttheme', "taken to list page"; + + $mech->content_contains("Transport for London Street Care"); + $mech->content_contains("TfL Street Care"); + +}; + +subtest "fms cobrand lets you edit a cobrand's manifest theme" => sub { + $mech->get_ok("/admin/manifesttheme"); + $mech->follow_link_ok({ url => "manifesttheme/tfl" }) or diag $mech->content; + + my $fields = { + name => "Transport for London Report It", + }; + $mech->submit_form_ok( { with_fields => $fields } ); + is $mech->uri->path, '/admin/manifesttheme', "redirected back to list page"; + + my $theme = FixMyStreet::DB->resultset('ManifestTheme')->find({ cobrand => 'tfl' }); + is $theme->name, "Transport for London Report It"; + +}; + +subtest "fms cobrand lets you create a new manifest theme" => sub { + $mech->get_ok("/admin/manifesttheme"); + $mech->follow_link_ok({ text => "Create" }); + + my $fields = { + name => "FixMyStreet Pro", + short_name => "FMS Pro", + cobrand => "fixmystreet", + }; + $mech->submit_form_ok( { with_fields => $fields } ); + is $mech->uri->path, '/admin/manifesttheme', "redirected to list page"; + + is( FixMyStreet::DB->resultset('ManifestTheme')->count, 2, "theme added" ); + my $theme = FixMyStreet::DB->resultset('ManifestTheme')->find({ cobrand => 'fixmystreet' }); + is $theme->name, "FixMyStreet Pro"; +}; + +subtest "fms cobrand prevents you creating a duplicate theme" => sub { + $mech->get_ok("/admin/manifesttheme"); + $mech->follow_link_ok({ text => "Create" }); + + my $fields = { + name => "FixMyStreet Pro", + short_name => "FMS Pro", + cobrand => "fixmystreet", + }; + $mech->submit_form_ok( { with_fields => $fields } ); + is $mech->uri->path, '/admin/manifesttheme/create', "stayed on create form"; + + is( FixMyStreet::DB->resultset('ManifestTheme')->count, 2, "theme not added" ); +}; + +subtest "fms cobrand prevents creating a duplicate by editing" => sub { + $mech->get_ok("/admin/manifesttheme"); + $mech->follow_link_ok({ url => "manifesttheme/tfl" }); + + my $fields = { + cobrand => "fixmystreet", + }; + $mech->submit_form_ok( { with_fields => $fields } ); + is $mech->uri->path, '/admin/manifesttheme/tfl', "stayed on edit page"; +}; + +}; + +FixMyStreet::override_config { + ALLOWED_COBRANDS => [ 'fixamingata' ], +}, sub { + +ok $mech->host("www.fixamingata.se"), "change host to FixaMinGata"; + +subtest "single cobrand behaves correctly" => sub { + FixMyStreet::DB->resultset('ManifestTheme')->delete_all; + is( FixMyStreet::DB->resultset('ManifestTheme')->count, 0, "themes all deleted" ); + + $mech->get_ok("/admin/manifesttheme"); + is $mech->uri->path, '/admin/manifesttheme/create', "redirected to create page"; + + my $fields = { + name => "FixaMinGata Theme Test", + short_name => "FixaMinGata Short Name", + cobrand => "fixamingata", + }; + $mech->submit_form_ok( { with_fields => $fields } ); + is $mech->uri->path, '/admin/manifesttheme/fixamingata', "redirected to edit form page"; + $mech->content_contains("FixaMinGata Theme Test"); + $mech->content_contains("FixaMinGata Short Name"); + + is( FixMyStreet::DB->resultset('ManifestTheme')->count, 1, "theme added" ); + my $theme = FixMyStreet::DB->resultset('ManifestTheme')->find({ cobrand => 'fixamingata' }); + is $theme->name, "FixaMinGata Theme Test"; +}; + + +}; + +done_testing(); diff --git a/t/app/controller/admin/permissions.t b/t/app/controller/admin/permissions.t index ff5a8ec4f..b7bffaaa5 100644 --- a/t/app/controller/admin/permissions.t +++ b/t/app/controller/admin/permissions.t @@ -1,5 +1,4 @@ use FixMyStreet::TestMech; -use Test::MockModule; my $mech = FixMyStreet::TestMech->new; @@ -29,13 +28,6 @@ ok $report, "created test report - $report_id"; $mech->log_in_ok( $oxfordshireuser->email ); -my $cobrand = Test::MockModule->new('FixMyStreet::Cobrand::Oxfordshire'); -$cobrand->mock('available_permissions', sub { - my $self = shift; - - return FixMyStreet::Cobrand::Default->available_permissions; -}); - subtest "Users can't edit report without report_edit permission" => sub { FixMyStreet::override_config { ALLOWED_COBRANDS => [ 'oxfordshire' ], diff --git a/t/app/controller/admin/priorities.t b/t/app/controller/admin/priorities.t index 4eff20be7..8341e212d 100644 --- a/t/app/controller/admin/priorities.t +++ b/t/app/controller/admin/priorities.t @@ -16,14 +16,14 @@ $mech->log_in_ok( $superuser->email ); subtest "response priorities can be added" => sub { is $oxfordshire->response_priorities->count, 0, "No response priorities yet"; - $mech->get_ok( "/admin/responsepriorities/" . $oxfordshire->id . "/new" ); + $mech->get_ok( "/admin/responsepriorities/" . $oxfordshire->id . "/create" ); my $fields = { name => "Cat 1A", description => "Fixed within 24 hours", deleted => undef, is_default => undef, - "contacts[".$oxfordshirecontact->id."]" => 1, + contacts => $oxfordshirecontact->id, }; $mech->submit_form_ok( { with_fields => $fields } ); @@ -41,7 +41,7 @@ subtest "response priorities can set to default" => sub { description => "Fixed within 24 hours", deleted => undef, is_default => 1, - "contacts[".$oxfordshirecontact->id."]" => 1, + contacts => $oxfordshirecontact->id, }; $mech->submit_form_ok( { with_fields => $fields } ); @@ -51,49 +51,36 @@ subtest "response priorities can set to default" => sub { }; subtest "response priorities can be listed" => sub { - $mech->get_ok( "/admin/responsepriorities/" . $oxfordshire->id ); + $mech->get_ok( "/admin/responsepriorities" ); $mech->content_contains( $oxfordshire->response_priorities->first->name ); $mech->content_contains( $oxfordshire->response_priorities->first->description ); }; -subtest "response priorities are limited by body" => sub { - my $bromleypriority = $bromley->response_priorities->create( { - deleted => 0, - name => "Bromley Cat 0", - } ); - - is $bromley->response_priorities->count, 1, "Response priority was added to Bromley"; - is $oxfordshire->response_priorities->count, 1, "Response priority wasn't added to Oxfordshire"; - - $mech->get_ok( "/admin/responsepriorities/" . $oxfordshire->id ); - $mech->content_lacks( $bromleypriority->name ); - - $mech->get_ok( "/admin/responsepriorities/" . $bromley->id ); - $mech->content_contains( $bromleypriority->name ); -}; - $mech->log_out_ok; subtest "response priorities can't be viewed across councils" => sub { FixMyStreet::override_config { ALLOWED_COBRANDS => [ 'oxfordshire' ], }, sub { + my $bromley_priority = $bromley->response_priorities->create( { + deleted => 0, + name => "Bromley Cat 0", + } ); + + is $bromley->response_priorities->count, 1, "Response priority was added to Bromley"; + is $oxfordshire->response_priorities->count, 1, "Response priority wasn't added to Oxfordshire"; + $oxfordshireuser->user_body_permissions->create({ body => $oxfordshire, permission_type => 'responsepriority_edit', }); $mech->log_in_ok( $oxfordshireuser->email ); - $mech->get_ok( "/admin/responsepriorities/" . $oxfordshire->id ); + $mech->get_ok( "/admin/responsepriorities" ); $mech->content_contains( $oxfordshire->response_priorities->first->name ); + $mech->content_lacks( $bromley_priority->name ); - - $mech->get( "/admin/responsepriorities/" . $bromley->id ); - ok !$mech->res->is_success(), "want a bad response"; - is $mech->res->code, 404, "got 404"; - - my $bromley_priority_id = $bromley->response_priorities->first->id; - $mech->get( "/admin/responsepriorities/" . $bromley->id . "/" . $bromley_priority_id ); + $mech->get( "/admin/responsepriorities/" . $bromley->id . "/" . $bromley_priority->id ); ok !$mech->res->is_success(), "want a bad response"; is $mech->res->code, 404, "got 404"; }; diff --git a/t/app/controller/admin/report_edit.t b/t/app/controller/admin/report_edit.t index c6e03ff7e..438bcc241 100644 --- a/t/app/controller/admin/report_edit.t +++ b/t/app/controller/admin/report_edit.t @@ -24,7 +24,7 @@ my $dt = DateTime->new( second => 23 ); -my $report = FixMyStreet::App->model('DB::Problem')->find_or_create( +my $report = FixMyStreet::DB->resultset('Problem')->find_or_create( { postcode => 'SW1A 1AA', bodies_str => '2504', @@ -52,7 +52,7 @@ my $report = FixMyStreet::App->model('DB::Problem')->find_or_create( $mech->log_in_ok( $superuser->email ); -my $log_entries = FixMyStreet::App->model('DB::AdminLog')->search( +my $log_entries = FixMyStreet::DB->resultset('AdminLog')->search( { object_type => 'problem', object_id => $report->id @@ -353,7 +353,7 @@ foreach my $test ( user_body => $oxfordshire, changes => { state => 'in progress', category => 'Potholes' }, log_entries => [ - qw/edit state_change edit state_change edit edit resend edit state_change edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/ + qw/edit state_change category_change edit state_change edit edit resend edit state_change edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/ ], resend => 0, }, @@ -412,6 +412,13 @@ foreach my $test ( delete $test->{changes}->{closed_updates}; } + if ($test->{changes}{title} || $test->{changes}{detail} || $test->{changes}{anonymous}) { + $mech->get_ok("/report/$report_id"); + $mech->content_contains("Anonymous: <del style='background-color:#fcc'>No</del><ins style='background-color:#cfc'>Yes</ins>") if $test->{changes}{anonymous}; + $mech->content_contains("Details: <ins style='background-color:#cfc'>Edited </ins>Detail<del style='background-color:#fcc'> for Report to Edit</del>") if $test->{changes}{detail}; + $mech->content_contains("Subject: <ins style='background-color:#cfc'>Edited </ins>Repor<del style='background-color:#fcc'>t to Edi</del>") if $test->{changes}{title}; + } + is $report->$_, $test->{changes}->{$_}, "$_ updated" for grep { $_ ne 'username' } keys %{ $test->{changes} }; if ( $test->{user} ) { @@ -504,7 +511,7 @@ subtest 'change email to new user' => sub { username => 'test3@example.com' }; - my $user3 = FixMyStreet::App->model('DB::User')->find( { email => 'test3@example.com' } ); + my $user3 = FixMyStreet::DB->resultset('User')->find( { email => 'test3@example.com' } ); ok !$user3, 'user not in database'; @@ -523,7 +530,7 @@ subtest 'change email to new user' => sub { is $log_entries->first->action, 'edit', 'log action'; is_deeply( $mech->visible_form_values(), $new_fields, 'changed form values' ); - $user3 = FixMyStreet::App->model('DB::User')->find( { email => 'test3@example.com' } ); + $user3 = FixMyStreet::DB->resultset('User')->find( { email => 'test3@example.com' } ); $report->discard_changes; @@ -534,7 +541,7 @@ subtest 'change email to new user' => sub { subtest 'adding email to abuse list from report page' => sub { my $email = $report->user->email; - my $abuse = FixMyStreet::App->model('DB::Abuse')->find( { email => $email } ); + my $abuse = FixMyStreet::DB->resultset('Abuse')->find( { email => $email } ); $abuse->delete if $abuse; $mech->get_ok( '/admin/report_edit/' . $report->id ); @@ -545,7 +552,7 @@ subtest 'adding email to abuse list from report page' => sub { $mech->content_contains('User added to abuse list'); $mech->content_contains('<small>User in abuse table</small>'); - $abuse = FixMyStreet::App->model('DB::Abuse')->find( { email => $email } ); + $abuse = FixMyStreet::DB->resultset('Abuse')->find( { email => $email } ); ok $abuse, 'entry created in abuse table'; $mech->get_ok( '/admin/report_edit/' . $report->id ); @@ -612,7 +619,7 @@ subtest "Test alert count display" => sub { $mech->get_ok("/admin/report_edit/$report_id"); $mech->content_contains('Alerts: 0'); - my $alert = FixMyStreet::App->model('DB::Alert')->find_or_create( + my $alert = FixMyStreet::DB->resultset('Alert')->find_or_create( { alert_type => 'new_updates', parameter => $report_id, @@ -634,7 +641,7 @@ subtest "Test alert count display" => sub { $alert->delete; }; -my $report2 = FixMyStreet::App->model('DB::Problem')->find_or_create( +my $report2 = FixMyStreet::DB->resultset('Problem')->find_or_create( { postcode => 'SW1A 1AA', bodies_str => '2504', diff --git a/t/app/controller/admin/reportextrafields.t b/t/app/controller/admin/reportextrafields.t index e02df864f..dede25207 100644 --- a/t/app/controller/admin/reportextrafields.t +++ b/t/app/controller/admin/reportextrafields.t @@ -9,6 +9,8 @@ sub allow_report_extra_fields { 1 } sub area_types { [ 'UTA' ] } +sub must_have_2fa { 0 } + package FixMyStreet::Cobrand::SecondTester; @@ -62,13 +64,12 @@ FixMyStreet::override_config { $mech->get_ok("/admin/body/" . $body->id . "/" . $contact->category); $mech->submit_form_ok( { with_fields => { - "metadata[0].order" => "1", - "metadata[0].code" => "string_test", - "metadata[0].required" => "on", - "metadata[0].notice" => "", - "metadata[0].description" => "this is a test description", - "metadata[0].datatype_description" => "hint here", - "metadata[0].datatype" => "string", + "metadata[9999].order" => "1", + "metadata[9999].code" => "string_test", + "metadata[9999].required" => 1, + "metadata[9999].behaviour" => "question", + "metadata[9999].description" => "<div style='foo'>this is a test description</div>", + "metadata[9999].datatype" => "string", "note" => "Added extra field", }}); $mech->content_contains('Values updated'); @@ -78,25 +79,23 @@ FixMyStreet::override_config { code => "string_test", required => "true", variable => "true", + protected => "false", description => "this is a test description", - datatype_description => "hint here", datatype => "string", }; $contact->discard_changes; is_deeply $contact->get_extra_fields, $contact_extra_fields, 'new string field was added'; - $mech->get_ok("/admin/body/" . $body->id . "/" . $contact->category); $mech->submit_form_ok( { with_fields => { - "metadata[1].order" => "2", - "metadata[1].code" => "list_test", - "metadata[1].required" => undef, - "metadata[1].notice" => "", - "metadata[1].description" => "this field is a list", - "metadata[1].datatype_description" => "", - "metadata[1].datatype" => "list", - "metadata[1].values[0].key" => "key1", - "metadata[1].values[0].name" => "name1", + "metadata[9999].order" => "2", + "metadata[9999].code" => "list_test", + "metadata[9999].required" => undef, + "metadata[9999].behaviour" => "question", + "metadata[9999].description" => "this field is a list", + "metadata[9999].datatype" => "singlevaluelist", + "metadata[9999].values[8888].key" => "key1", + "metadata[9999].values[8888].name" => "name1", "note" => "Added extra list field", }}); $mech->content_contains('Values updated'); @@ -106,8 +105,8 @@ FixMyStreet::override_config { code => "list_test", required => "false", variable => "true", + protected => "false", description => "this field is a list", - datatype_description => "", datatype => "singlevaluelist", values => [ { name => "name1", key => "key1" }, @@ -116,6 +115,28 @@ FixMyStreet::override_config { $contact->discard_changes; is_deeply $contact->get_extra_fields, $contact_extra_fields, 'new list field was added'; + $mech->get_ok("/admin/body/" . $body->id . "/" . $contact->category); + $mech->submit_form_ok( { with_fields => { + "metadata[9999].order" => "3", + "metadata[9999].code" => "emergency", + "metadata[9999].behaviour" => "notice", + "metadata[9999].disable_form" => "1", + "metadata[9999].description" => "please ring", + "note" => "Added notice field", + }}); + $mech->content_contains('Values updated'); + + push @$contact_extra_fields, { + order => "3", + code => "emergency", + protected => "false", + description => "please ring", + disable_form => 'true', + variable => 'false', + }; + $contact->discard_changes; + is_deeply $contact->get_extra_fields, $contact_extra_fields, 'new field was added'; + $contact->set_extra_fields(); $contact->update; }; @@ -137,11 +158,7 @@ FixMyStreet::override_config { is $contact->email, 'test4@example.com', 'contact updated'; is_deeply $meta_data, [ { order => 0, - datatype => 'string', - datatype_description => '', - description => '', - required => 'false', - variable => 'true', + protected => 'false', code => 'POT', automated => 'server_set' } ], "automated fields not unset"; @@ -151,7 +168,7 @@ FixMyStreet::override_config { subtest 'Create and update new ReportExtraFields' => sub { my $extra_fields = []; - my $model = FixMyStreet::App->model('DB::ReportExtraField'); + my $model = FixMyStreet::DB->resultset('ReportExtraField'); is $model->count, 0, 'no ReportExtraFields yet'; $mech->get_ok("/admin/reportextrafields"); @@ -161,13 +178,12 @@ FixMyStreet::override_config { name => "Test extra fields", cobrand => "tester", language => undef, - "metadata[0].order" => "1", - "metadata[0].code" => "string_test", - "metadata[0].required" => "on", - "metadata[0].notice" => "", - "metadata[0].description" => "this is a test description", - "metadata[0].datatype_description" => "hint here", - "metadata[0].datatype" => "string", + "metadata[9999].order" => "1", + "metadata[9999].code" => "string_test", + "metadata[9999].required" => 1, + "metadata[9999].behaviour" => "question", + "metadata[9999].description" => "this is a test description", + "metadata[9999].datatype" => "string", }}); is $model->count, 1, 'new ReportExtraFields created'; @@ -177,8 +193,8 @@ FixMyStreet::override_config { code => "string_test", required => "true", variable => "true", + protected => "false", description => "this is a test description", - datatype_description => "hint here", datatype => "string", }; is_deeply $object->get_extra_fields, $extra_fields, 'new string field was added'; @@ -188,15 +204,14 @@ FixMyStreet::override_config { $mech->get_ok("/admin/reportextrafields/" . $object->id); $mech->submit_form_ok( { with_fields => { "language" => "en-gb", - "metadata[1].order" => "2", - "metadata[1].code" => "list_test", - "metadata[1].required" => undef, - "metadata[1].notice" => "", - "metadata[1].description" => "this field is a list", - "metadata[1].datatype_description" => "", - "metadata[1].datatype" => "list", - "metadata[1].values[0].key" => "key1", - "metadata[1].values[0].name" => "name1", + "metadata[9999].order" => "2", + "metadata[9999].code" => "list_test", + "metadata[9999].required" => undef, + "metadata[9999].behaviour" => "question", + "metadata[9999].description" => "this field is a list", + "metadata[9999].datatype" => "singlevaluelist", + "metadata[9999].values[8888].key" => "key1", + "metadata[9999].values[8888].name" => "name1", }}); push @$extra_fields, { @@ -204,8 +219,8 @@ FixMyStreet::override_config { code => "list_test", required => "false", variable => "true", + protected => "false", description => "this field is a list", - datatype_description => "", datatype => "singlevaluelist", values => [ { name => "name1", key => "key1" }, @@ -218,24 +233,16 @@ FixMyStreet::override_config { $mech->get_ok("/admin/reportextrafields/" . $object->id); $mech->submit_form_ok({ with_fields => { - "metadata[2].order" => "3", - "metadata[2].code" => "automated_test", - "metadata[2].required" => undef, - "metadata[2].notice" => "", - "metadata[2].description" => "", - "metadata[2].datatype_description" => "", - "metadata[2].datatype" => "string", - "metadata[2].automated" => "server_set", + "metadata[9999].order" => "3", + "metadata[9999].code" => "automated_test", + "metadata[9999].required" => undef, + "metadata[9999].behaviour" => "server", }}); push @$extra_fields, { order => "3", code => "automated_test", - required => "false", - variable => "true", - description => "", - datatype_description => "", - datatype => "string", + protected => "false", automated => "server_set", }; @@ -245,8 +252,8 @@ FixMyStreet::override_config { $mech->get_ok("/admin/reportextrafields/" . $object->id); $mech->submit_form_ok( { with_fields => { - "metadata[1].values[1].key" => "key2", - "metadata[1].values[1].name" => "name2", + "metadata[1].values[8888].key" => "key2", + "metadata[1].values[8888].name" => "name2", }}); push @{$extra_fields->[1]->{values}}, { name => "name2", key => "key2" }; @@ -291,7 +298,7 @@ FixMyStreet::override_config { LANGUAGES => [ 'en-gb,English,en_GB' ] }, sub { subtest "Extra fields are missing from cobrand that doesn't allow them" => sub { - my $object = FixMyStreet::App->model('DB::ReportExtraField')->first; + my $object = FixMyStreet::DB->resultset('ReportExtraField')->first; $object->update({ language => "", cobrand => ""}); $mech->get_ok("/report/new?longitude=-1.351488&latitude=51.847235&category=" . $contact->category); @@ -300,7 +307,7 @@ FixMyStreet::override_config { }; }; -FixMyStreet::App->model('DB::ReportExtraField')->delete_all; +FixMyStreet::DB->resultset('ReportExtraField')->delete_all; $mech->log_out_ok; subtest 'Reports are created with correct extra metadata' => sub { @@ -308,7 +315,7 @@ subtest 'Reports are created with correct extra metadata' => sub { ALLOWED_COBRANDS => [ 'tester' ], MAPIT_URL => 'http://mapit.uk/', }, sub { - my $model = FixMyStreet::App->model('DB::ReportExtraField'); + my $model = FixMyStreet::DB->resultset('ReportExtraField'); my $extra_fields = $model->find_or_create({ name => "Test extra fields", language => "", @@ -320,7 +327,6 @@ subtest 'Reports are created with correct extra metadata' => sub { required => "true", variable => "true", description => "this is a test description", - datatype_description => "hint here", datatype => "string", }); $extra_fields->push_extra_fields({ @@ -329,7 +335,6 @@ subtest 'Reports are created with correct extra metadata' => sub { required => "false", variable => "true", description => "this field is a list", - datatype_description => "", datatype => "singlevaluelist", values => [ { name => "name1", key => "key1" }, diff --git a/t/app/controller/admin/roles.t b/t/app/controller/admin/roles.t new file mode 100644 index 000000000..bc8371404 --- /dev/null +++ b/t/app/controller/admin/roles.t @@ -0,0 +1,139 @@ +use FixMyStreet::TestMech; + +my $mech = FixMyStreet::TestMech->new; + +my $superuser = $mech->create_user_ok('superuser@example.com', name => 'Super User', is_superuser => 1); + +my $body = $mech->create_body_ok(2237, 'Oxfordshire County Council'); +my $body2 = $mech->create_body_ok(2482, 'Bromley Council'); +my $editor = $mech->create_user_ok('counciluser@example.com', name => 'Council User', from_body => $body); +my $user = $mech->create_user_ok('staffuser@example.com', name => 'Other Council User', from_body => $body); + +$editor->user_body_permissions->create({ + body => $body, + permission_type => 'user_edit', +}); +$editor->user_body_permissions->create({ + body => $body, + permission_type => 'user_manage_permissions', +}); +$user->user_body_permissions->create({ + body => $body, + permission_type => 'report_edit_priority', +}); + +my $role_a = FixMyStreet::DB->resultset("Role")->create({ + body => $body, + name => 'Role A', + permissions => ['moderate', 'user_edit'], +}); +FixMyStreet::DB->resultset("Role")->create({ + body => $body2, + name => 'Role Z', + permissions => ['report_inspect', 'planned_reports'], +}); + +FixMyStreet::override_config { + ALLOWED_COBRANDS => 'oxfordshire', + MAPIT_URL => 'http://mapit.uk', +}, sub { + + $mech->log_in_ok( $editor->email ); + + subtest 'role index page' => sub { + $mech->get_ok("/admin/roles"); + $mech->content_contains('Role A'); + $mech->content_contains('Moderate report details'); + $mech->content_lacks('Role Z'); + $mech->content_lacks('Manage shortlist'); + $mech->content_lacks('Add/edit response templates'); # About to be added + }; + + subtest 'create a role' => sub { + $mech->follow_link_ok({ text => 'Create' }); + $mech->content_lacks('Body'); + $mech->submit_form_ok({ with_fields => { name => 'Role A' }}); + $mech->content_contains('Role names must be unique'); + $mech->submit_form_ok({ with_fields => { + name => 'Role B', + permissions => [ ['template_edit', 'user_manage_permissions'] ], + }}); + + $mech->content_contains('Role B'); + $mech->content_contains('Add/edit response templates'); + }; + + subtest 'editing a role preselects correct options' => sub { + $mech->follow_link_ok({ text => 'Edit' }); + $mech->content_like(qr/value="moderate"[^>]*checked/); + $mech->content_like(qr/value="user_edit"[^>]*checked/); + }; + + subtest 'editing a role to same name as another fails' => sub { + $mech->submit_form_ok({ with_fields => { name => 'Role B' }}); + $mech->content_contains('Role names must be unique'); + }; + + subtest 'delete a role' => sub { + $mech->submit_form_ok({ button => 'delete_role' }); + $mech->content_lacks('Role A'); + }; + + subtest 'assign a user to a role' => sub { + $mech->get_ok('/admin/users/' . $user->id); + $mech->content_contains('Role B'); + $mech->content_lacks('Role Z'); + $mech->submit_form_ok({ with_fields => { + roles => 'Role B', + }}); + $mech->content_like(qr/<option[^>]*selected>Role B/); + $mech->content_like(qr/<input[^>]*checkbox[^>]*template_edit[^>]*checked/); + is $user->roles->count, 1, 'in one role'; + is $user->user_body_permissions->count, 0, 'permissions removed'; + }; + + subtest 'check user has the permissions of the role' => sub { + $mech->log_in_ok($user->email); + $mech->get_ok('/admin/templates'); + }; + + subtest 'remove user from role' => sub { + $mech->log_in_ok( $editor->email ); + $mech->get_ok('/admin/users/' . $user->id); + $mech->submit_form_ok({ with_fields => { + roles => undef, + }}, 'remove role'); + }; +}; + +subtest 'superuser can see all bodies' => sub { + $mech->log_in_ok( $superuser->email ); + + $mech->get_ok("/admin/roles"); + $mech->content_contains('Oxfordshire'); + $mech->content_contains('Bromley'); + $mech->content_contains('Role B'); + $mech->content_contains('Role Z'); + $mech->follow_link_ok({ text => 'Create' }); + $mech->content_contains('Body'); + $mech->content_contains('Bromley'); + + $mech->submit_form_ok({ with_fields => { body => $body->id, name => 'Role B' }}); + $mech->content_contains('Role names must be unique'); + + $mech->submit_form_ok({ with_fields => { + name => 'Role C', + body => $body2->id, + permissions => 'contribute_as_body', + }}); + $mech->content_contains('Role C'); +}; + +subtest 'check log of the above' => sub { + my $id = FixMyStreet::DB->resultset("Role")->find({ name => "Role B" })->id; + $mech->get_ok('/admin/users/' . $editor->id . '/log'); + $mech->content_contains('Added role <a href="/admin/roles/' . $id . '">Role B</a>'); + $mech->content_contains('Deleted role ' . $role_a->id); +}; + +done_testing(); diff --git a/t/app/controller/admin/search.t b/t/app/controller/admin/search.t index f8e70cb7a..d46843799 100644 --- a/t/app/controller/admin/search.t +++ b/t/app/controller/admin/search.t @@ -20,7 +20,7 @@ $mech->create_contact_ok( body_id => $oxford->id, category => 'Graffiti', email my $bromley = $mech->create_body_ok(2482, 'Bromley Council'); -my $user3 = FixMyStreet::App->model('DB::User')->create( { email => 'test3@example.com' } ); +my $user3 = FixMyStreet::DB->resultset('User')->create( { email => 'test3@example.com' } ); my $dt = DateTime->new( year => 2011, @@ -31,7 +31,7 @@ my $dt = DateTime->new( second => 23 ); -my $report = FixMyStreet::App->model('DB::Problem')->find_or_create( +my $report = FixMyStreet::DB->resultset('Problem')->find_or_create( { postcode => 'SW1A 1AA', bodies_str => '2504', @@ -68,7 +68,7 @@ subtest 'show flagged entries' => sub { $mech->content_contains( $report->title ); }; -my $update = FixMyStreet::App->model('DB::Comment')->create( +my $update = FixMyStreet::DB->resultset('Comment')->create( { text => 'this is an update', user => $user, diff --git a/t/app/controller/admin/templates.t b/t/app/controller/admin/templates.t index 0d4430cad..ad5b3e77b 100644 --- a/t/app/controller/admin/templates.t +++ b/t/app/controller/admin/templates.t @@ -8,18 +8,36 @@ my $superuser = $mech->create_user_ok('superuser@example.com', name => 'Super Us my $oxfordshire = $mech->create_body_ok(2237, 'Oxfordshire County Council'); my $oxfordshirecontact = $mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Potholes', email => 'potholes@example.com' ); +my $oxfordshirecontact2 = $mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Flytipping', email => 'flytipping@example.com' ); my $oxfordshireuser = $mech->create_user_ok('counciluser@example.com', name => 'Council User', from_body => $oxfordshire); -my $dt = DateTime->new( - year => 2011, - month => 04, - day => 16, - hour => 15, - minute => 47, - second => 23 -); - -my $report = FixMyStreet::App->model('DB::Problem')->find_or_create( +my $bromley = $mech->create_body_ok(2482, 'Bromley Borough Council'); +my $bromleycontact = $mech->create_contact_ok( body_id => $bromley->id, category => 'Potholes', email => 'potholes@example.com' ); +my $bromleyuser = $mech->create_user_ok('bromleyuser@example.com', name => 'Council User', from_body => $bromley); +$bromleyuser->user_body_permissions->find_or_create({ + body => $bromley, + permission_type => 'report_inspect', +}); +my $bromleytemplate = $bromley->response_templates->create({ + title => "Bromley-specific response template.", + text => "This template will only appear on the Bromley cobrand.", +}); + +my $tfl = $mech->create_body_ok(2482, 'TfL'); +my $tflcontact = $mech->create_contact_ok( body_id => $tfl->id, category => 'Potholes', email => 'potholes@example.com' ); +my $tfluser = $mech->create_user_ok('tfluser@example.com', name => 'Council User', from_body => $tfl); +$tfluser->user_body_permissions->find_or_create({ + body => $tfl, + permission_type => 'report_inspect', +}); +my $tfltemplate = $tfl->response_templates->create({ + title => "TfL-specific response template.", + text => "This template will only appear on the TfL cobrand.", +}); + +my $dt = DateTime->now(); + +my $report = FixMyStreet::DB->resultset('Problem')->find_or_create( { postcode => 'SW1A 1AA', bodies_str => '2504', @@ -45,8 +63,6 @@ my $report = FixMyStreet::App->model('DB::Problem')->find_or_create( } ); -$mech->log_in_ok( $superuser->email ); - my $report_id = $report->id; ok $report, "created test report - $report_id"; @@ -63,7 +79,37 @@ subtest "response templates can be added" => sub { }; $mech->submit_form_ok( { with_fields => $fields } ); - is $oxfordshire->response_templates->count, 1, "Response template was added"; + is $oxfordshire->response_templates->count, 1, "Response template was added"; +}; + +subtest 'check log of the above' => sub { + my $template_id = $oxfordshire->response_templates->first->id; + $mech->get_ok('/admin/users/' . $superuser->id . '/log'); + $mech->content_contains('Added template <a href="/admin/templates/' . $oxfordshire->id . '/' . $template_id . '">Report acknowledgement</a>'); +}; + +subtest "but not another with the same title" => sub { + my $fields = { + title => "Report acknowledgement", + text => "Another report acknowledgement.", + auto_response => undef, + "contacts[".$oxfordshirecontact->id."]" => 1, + }; + my $list_url = "/admin/templates/" . $oxfordshire->id; + $mech->get_ok( "$list_url/new" ); + $mech->submit_form_ok( { with_fields => $fields } ); + is $mech->uri->path, "$list_url/new", 'not redirected'; + $mech->content_contains( 'Please correct the errors below' ); + $mech->content_contains( 'There is already a template with that title.' ); + + my @ts = $oxfordshire->response_templates->all; + is @ts, 1, "No new response template was added"; + + my $url = "$list_url/" . $ts[0]->id; + $mech->get_ok($url); + $mech->submit_form_ok( { with_fields => $fields } ); + is $mech->uri->path, $list_url, 'redirected'; + is $oxfordshire->response_templates->count, 1, "No new response template was added"; }; subtest "response templates are included on page" => sub { @@ -193,7 +239,6 @@ subtest "auto-response templates that duplicate external_status_code can't be ad }); is $oxfordshire->response_templates->count, 1, "Initial response template was created"; - $mech->log_in_ok( $superuser->email ); $mech->get_ok( "/admin/templates/" . $oxfordshire->id . "/new" ); @@ -231,4 +276,90 @@ subtest "templates that set state and external_status_code can't be added" => su is $oxfordshire->response_templates->count, 0, "Invalid response template wasn't added"; }; +subtest "category groups are shown" => sub { + FixMyStreet::override_config { + ALLOWED_COBRANDS => [ 'oxfordshire' ], + COBRAND_FEATURES => { + category_groups => { + oxfordshire => 1, + }, + multiple_category_groups => { + oxfordshire => 1, + }, + }, + }, sub { + + $mech->log_in_ok( $superuser->email ); + + $mech->get_ok( "/admin/templates/" . $oxfordshire->id . "/new" ); + $mech->content_contains("No Group") or diag $mech->content; + $mech->content_lacks("Multiple Groups"); + $mech->content_lacks("These categories appear in more than one group:"); + + $oxfordshirecontact->set_extra_metadata( group => [ 'Highways' ] ); + $oxfordshirecontact->update; + $oxfordshirecontact2->set_extra_metadata( group => [ 'Street Cleaning' ] ); + $oxfordshirecontact2->update; + $mech->get_ok( "/admin/templates/" . $oxfordshire->id . "/new" ); + $mech->content_lacks("No Group"); + $mech->content_lacks("Multiple Groups"); + $mech->content_lacks("These categories appear in more than one group:"); + $mech->content_contains("Highways"); + $mech->content_contains("Street Cleaning"); + + $oxfordshirecontact->set_extra_metadata( group => [ 'Highways', 'Roads & Pavements' ] ); + $oxfordshirecontact->update; + $oxfordshirecontact2->set_extra_metadata( group => [ 'Street Cleaning' ] ); + $oxfordshirecontact2->update; + $mech->get_ok( "/admin/templates/" . $oxfordshire->id . "/new" ); + $mech->content_lacks("No Group"); + $mech->content_contains("Multiple Groups"); + $mech->content_contains("These categories appear in more than one group:"); + $mech->content_contains("Highways; Roads & Pavements"); + $mech->content_contains("Street Cleaning"); + }; +}; + +subtest "TfL cobrand only shows TfL templates" => sub { + FixMyStreet::override_config { + ALLOWED_COBRANDS => [ 'tfl' ], + COBRAND_FEATURES => { internal_ips => { tfl => [ '127.0.0.1' ] } }, + }, sub { + $report->update({ + category => $tflcontact->category, + bodies_str => $tfl->id, + latitude => 51.402096, + longitude => 0.015784, + state => 'confirmed', + areas => ',2482,', + }); + $mech->log_in_ok( $tfluser->email ); + + $mech->get_ok("/report/" . $report->id); + $mech->content_contains( $tfltemplate->text ); + $mech->content_contains( $tfltemplate->title ); + $mech->content_lacks( $bromleytemplate->text ); + $mech->content_lacks( $bromleytemplate->title ); + + $mech->log_out_ok; + }; +}; + +subtest "Bromley cobrand only shows Bromley templates" => sub { + FixMyStreet::override_config { + ALLOWED_COBRANDS => [ 'bromley', 'tfl' ], + }, sub { + $report->update({ category => $bromleycontact->category, bodies_str => $bromley->id }); + $mech->log_in_ok( $bromleyuser->email ); + + $mech->get_ok("/report/" . $report->id); + $mech->content_contains( $bromleytemplate->text ); + $mech->content_contains( $bromleytemplate->title ); + $mech->content_lacks( $tfltemplate->text ); + $mech->content_lacks( $tfltemplate->title ); + + $mech->log_out_ok; + }; +}; + done_testing(); diff --git a/t/app/controller/admin/translations.t b/t/app/controller/admin/translations.t index f5c32baa6..442be68d5 100644 --- a/t/app/controller/admin/translations.t +++ b/t/app/controller/admin/translations.t @@ -59,7 +59,7 @@ subtest 'check add category with translation' => sub { $mech->submit_form_ok( { with_fields => { category => 'Potholes', translation_de => 'DE potholes', - email => 'potholes@example.org', + email => 'potholes', } } ); # check that error page includes translations diff --git a/t/app/controller/admin/triage.t b/t/app/controller/admin/triage.t new file mode 100644 index 000000000..6e134ff67 --- /dev/null +++ b/t/app/controller/admin/triage.t @@ -0,0 +1,126 @@ +use FixMyStreet::TestMech; +use FixMyStreet::Script::Alerts; + +my $mech = FixMyStreet::TestMech->new; + +my $user = $mech->create_user_ok('test@example.com', name => 'Test User'); +my $user2 = $mech->create_user_ok('test2@example.com', name => 'Test User 2'); +my $superuser = $mech->create_user_ok( + 'superuser@example.com', + name => 'Super User', + is_superuser => 1 +); + +my $iow = $mech->create_body_ok(2636, 'Isle of Wight Council', { can_be_devolved => 1 } ); +my $iow_contact = $mech->create_contact_ok( + body_id => $iow->id, + category => 'Potholes', + email => 'potholes@example.com', + send_method => 'Triage' +); +$mech->create_contact_ok( + body_id => $iow->id, + category => 'Traffic lights', + email => 'lights@example.com' +); + +my $dt = DateTime->now(); + +my ($report) = $mech->create_problems_for_body( + 1, + $iow->id, + 'TITLE', + { + areas => 2636, + category => 'Potholes', + whensent => $dt, + latitude => 50.71086, + longitude => -1.29573, + send_method_used => 'Triage', + } +); + +FixMyStreet::override_config { + STAGING_FLAGS => { send_reports => 1, skip_checks => 0 }, + ALLOWED_COBRANDS => [ 'isleofwight' ], + MAPIT_URL => 'http://mapit.uk/', +}, sub { + subtest "user can access triage page with triage permission" => sub { + $user->update({ from_body => $iow }); + $mech->log_out_ok; + $mech->get_ok('/admin/triage'); + + $mech->log_in_ok($user->email); + $mech->get('/admin/triage'); + is $mech->res->code, 403, 'permission denied'; + + $user->user_body_permissions->create( { body => $iow, permission_type => 'triage' } ); + $mech->get_ok('/admin/triage'); + }; + + subtest "reports marked for triage show triage interface" => sub { + $mech->log_out_ok; + $mech->log_in_ok( $user->email ); + + $mech->get_ok('/report/' . $report->id); + $mech->content_lacks('CONFIRM Subject'); + + $report->update( { state => 'for triage' } ); + + $mech->get_ok('/report/' . $report->id); + $mech->content_contains('CONFIRM Subject'); + }; + + subtest "changing report category marks report as confirmed" => sub { + my $report_url = '/report/' . $report->id; + $mech->get_ok($report_url); + + my $alert = FixMyStreet::DB->resultset('Alert')->create( + { + user => $user2, + alert_type => 'new_updates', + parameter => $report->id, + parameter2 => '', + confirmed => 1, + } + ); + + $mech->content_contains('Traffic lights'); + + $mech->submit_form_ok( { + with_fields => { + category => 'Traffic lights', + include_update => 0, + } + }, + 'triage form submitted' + ); + + $mech->content_contains('Potholes'); + + $report->discard_changes; + is $report->state, 'confirmed', 'report marked as confirmed'; + ok !$report->whensent, 'report marked to resend'; + + my @comments = $report->comments; + my $comment = $comments[0]; + my $extra = $comment->get_extra_metadata(); + is $extra->{triage_report}, 1, 'comment indicates it is for triage in extra'; + is $extra->{holding_category}, 'Potholes', 'comment extra has previous category'; + is $extra->{new_category}, 'Traffic lights', 'comment extra has new category'; + ok $comment->whensent, 'comment is marked as sent'; + + $mech->get_ok($report_url); + $mech->content_contains('Report triaged from Potholes to Traffic lights'); + + $mech->log_out_ok; + $mech->get_ok($report_url); + $mech->content_lacks('Report triaged from Potholes to Traffic lights'); + + $mech->clear_emails_ok; + FixMyStreet::Script::Alerts::send(); + $mech->email_count_is(0); + }; +}; + +done_testing(); diff --git a/t/app/controller/admin/update_edit.t b/t/app/controller/admin/update_edit.t index 6ddbdbdfc..57c8973d4 100644 --- a/t/app/controller/admin/update_edit.t +++ b/t/app/controller/admin/update_edit.t @@ -10,7 +10,7 @@ my $user2 = $mech->create_user_ok('test2@example.com', name => 'Test User 2'); my $superuser = $mech->create_user_ok('superuser@example.com', name => 'Super User', is_superuser => 1); -my $user3 = FixMyStreet::App->model('DB::User')->create( { email => 'test3@example.com' } ); +my $user3 = FixMyStreet::DB->resultset('User')->create( { email => 'test3@example.com' } ); my $dt = DateTime->new( year => 2011, @@ -21,7 +21,7 @@ my $dt = DateTime->new( second => 23 ); -my $report = FixMyStreet::App->model('DB::Problem')->find_or_create( +my $report = FixMyStreet::DB->resultset('Problem')->find_or_create( { postcode => 'SW1A 1AA', bodies_str => '2504', @@ -52,7 +52,7 @@ $mech->log_in_ok( $superuser->email ); my $report_id = $report->id; ok $report, "created test report - $report_id"; -my $update = FixMyStreet::App->model('DB::Comment')->create( +my $update = FixMyStreet::DB->resultset('Comment')->create( { text => 'this is an update', user => $user, @@ -63,7 +63,7 @@ my $update = FixMyStreet::App->model('DB::Comment')->create( } ); -my $log_entries = FixMyStreet::App->model('DB::AdminLog')->search( +my $log_entries = FixMyStreet::DB->resultset('AdminLog')->search( { object_type => 'update', object_id => $update->id @@ -83,7 +83,7 @@ for my $test ( state => 'confirmed', name => '', anonymous => 1, - username => 'test@example.com', + username => $update->user->email, }, changes => { text => 'this is a changed update', @@ -98,7 +98,7 @@ for my $test ( state => 'confirmed', name => '', anonymous => 1, - username => 'test@example.com', + username => $update->user->email, }, changes => { name => 'A User', @@ -113,7 +113,7 @@ for my $test ( state => 'confirmed', name => 'A User', anonymous => 1, - username => 'test@example.com', + username => $update->user->email, }, changes => { anonymous => 0, @@ -128,10 +128,10 @@ for my $test ( state => 'confirmed', name => 'A User', anonymous => 0, - username => 'test@example.com', + username => $update->user->email, }, changes => { - username => 'test2@example.com', + username => $user2->email, }, log_count => 4, log_entries => [qw/edit edit edit edit/], @@ -144,7 +144,7 @@ for my $test ( state => 'confirmed', name => 'A User', anonymous => 0, - username => 'test2@example.com', + username => $user2->email, }, changes => { state => 'unconfirmed', @@ -159,7 +159,7 @@ for my $test ( state => 'unconfirmed', name => 'A User', anonymous => 0, - username => 'test2@example.com', + username => $user2->email, }, changes => { text => 'this is a twice changed update', @@ -275,7 +275,7 @@ for my $test ( } subtest 'editing update email creates new user if required' => sub { - my $user = FixMyStreet::App->model('DB::User')->find( { email => 'test4@example.com' } ); + my $user = FixMyStreet::DB->resultset('User')->find( { email => 'test4@example.com' } ); $user->delete if $user; @@ -289,7 +289,7 @@ subtest 'editing update email creates new user if required' => sub { $mech->submit_form_ok( { with_fields => $fields } ); - $user = FixMyStreet::App->model('DB::User')->find( { email => 'test4@example.com' } ); + $user = FixMyStreet::DB->resultset('User')->find( { email => 'test4@example.com' } ); is_deeply $mech->visible_form_values, $fields, 'submitted form values'; @@ -302,7 +302,7 @@ subtest 'editing update email creates new user if required' => sub { subtest 'adding email to abuse list from update page' => sub { my $email = $update->user->email; - my $abuse = FixMyStreet::App->model('DB::Abuse')->find( { email => $email } ); + my $abuse = FixMyStreet::DB->resultset('Abuse')->find( { email => $email } ); $abuse->delete if $abuse; $mech->get_ok( '/admin/update_edit/' . $update->id ); @@ -313,7 +313,7 @@ subtest 'adding email to abuse list from update page' => sub { $mech->content_contains('User added to abuse list'); $mech->content_contains('<small>User in abuse table</small>'); - $abuse = FixMyStreet::App->model('DB::Abuse')->find( { email => $email } ); + $abuse = FixMyStreet::DB->resultset('Abuse')->find( { email => $email } ); ok $abuse, 'entry created in abuse table'; $mech->get_ok( '/admin/update_edit/' . $update->id ); diff --git a/t/app/controller/admin/users.t b/t/app/controller/admin/users.t index e2c922a23..4f0298103 100644 --- a/t/app/controller/admin/users.t +++ b/t/app/controller/admin/users.t @@ -3,6 +3,9 @@ use FixMyStreet::TestMech; my $mech = FixMyStreet::TestMech->new; my $user = $mech->create_user_ok('test@example.com', name => 'Test User'); +my $original_user_id = $user->id; # For log later +my $user2 = $mech->create_user_ok('test2@example.com', name => 'Test User 2'); +my $user3 = $mech->create_user_ok('test3@example.com', name => 'Test User 3'); my $superuser = $mech->create_user_ok('superuser@example.com', name => 'Super User', is_superuser => 1); @@ -13,7 +16,7 @@ my $southend = $mech->create_body_ok(2607, 'Southend-on-Sea Borough Council'); $mech->log_in_ok( $superuser->email ); subtest 'search abuse' => sub { - my $abuse = FixMyStreet::App->model('DB::Abuse')->find_or_create( { email => $user->email } ); + my $abuse = FixMyStreet::DB->resultset('Abuse')->find_or_create( { email => $user->email } ); $mech->get_ok( '/admin/users?search=example' ); $mech->content_like(qr{test\@example.com.*</td>\s*<td>.*?</td>\s*<td>User in abuse table}s); }; @@ -24,26 +27,26 @@ subtest 'remove user from abuse list from edit user page' => sub { $mech->click_ok('unban'); - my $abuse = FixMyStreet::App->model('DB::Abuse')->find( { email => $user->email } ); + my $abuse = FixMyStreet::DB->resultset('Abuse')->find( { email => $user->email } ); ok !$abuse, 'record removed from abuse table'; }; subtest 'remove user with phone account from abuse list from edit user page' => sub { my $abuse_user = $mech->create_user_ok('01234 456789'); - my $abuse = FixMyStreet::App->model('DB::Abuse')->find_or_create( { email => $abuse_user->phone } ); + my $abuse = FixMyStreet::DB->resultset('Abuse')->find_or_create( { email => $abuse_user->phone } ); $mech->get_ok( '/admin/users/' . $abuse_user->id ); $mech->content_contains('User in abuse table'); - my $abuse_found = FixMyStreet::App->model('DB::Abuse')->find( { email => $abuse_user->phone } ); + my $abuse_found = FixMyStreet::DB->resultset('Abuse')->find( { email => $abuse_user->phone } ); ok $abuse_found, 'user in abuse table'; $mech->click_ok('unban'); - $abuse = FixMyStreet::App->model('DB::Abuse')->find( { email => $user->phone } ); + $abuse = FixMyStreet::DB->resultset('Abuse')->find( { email => $user->phone } ); ok !$abuse, 'record removed from abuse table'; }; subtest 'no option to remove user already in abuse list' => sub { - my $abuse = FixMyStreet::App->model('DB::Abuse')->find( { email => $user->email } ); + my $abuse = FixMyStreet::DB->resultset('Abuse')->find( { email => $user->email } ); $abuse->delete if $abuse; $mech->get_ok( '/admin/users/' . $user->id ); $mech->content_lacks('User in abuse table'); @@ -60,6 +63,7 @@ subtest 'show flagged entries' => sub { $user->update; }; +my $role; subtest 'user search' => sub { $mech->get_ok('/admin/users'); $mech->get_ok('/admin/users?search=' . $user->name); @@ -74,17 +78,37 @@ subtest 'user search' => sub { $user->from_body($haringey->id); $user->update; + $role = $user->roles->create({ + body => $haringey, + name => 'Role A', + permissions => ['moderate', 'user_edit'], + }); + $user->add_to_roles($role); $mech->get_ok('/admin/users?search=' . $haringey->id ); - $mech->content_contains('Haringey'); + $mech->content_contains('test@example.com'); + $mech->get_ok('/admin/users?role=' . $role->id); + $mech->content_contains('selected>Role A'); + $mech->content_contains('test@example.com'); +}; + +subtest 'user assign role' => sub { + $user->remove_from_roles($role); + is $user->roles->count, 0; + $mech->get_ok('/admin/users'); + $mech->submit_form_ok({ with_fields => { uid => $user->id, roles => $role->id } }); + is $user->roles->count, 1; }; subtest 'search does not show user from another council' => sub { FixMyStreet::override_config { ALLOWED_COBRANDS => [ 'oxfordshire' ], }, sub { + $superuser->update({ from_body => $oxfordshire->id }); $mech->get_ok('/admin/users'); - $mech->get_ok('/admin/users?search=' . $user->name); + $mech->content_lacks('Super User'); + $superuser->update({ from_body => undef }); + $mech->get_ok('/admin/users?search=' . $user->name); $mech->content_contains( "Searching found no users." ); $mech->get_ok('/admin/users?search=' . $user->email); @@ -102,6 +126,71 @@ subtest 'user_edit does not show user from another council' => sub { }; }; +$mech->log_out_ok; + +subtest 'user_edit redirects appropriately' => sub { + FixMyStreet::override_config { + ALLOWED_COBRANDS => [ 'oxfordshire' ], + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $user2->update({ from_body => $oxfordshire->id }); + $user3->update({ from_body => $oxfordshire->id }); + $user3->user_body_permissions->create( { + body => $oxfordshire, + permission_type => 'user_edit', + } ); + $user3->user_body_permissions->create( { + body => $oxfordshire, + permission_type => 'user_assign_body', + } ); + $mech->log_in_ok( $user3->email ); + + $mech->get_ok('/admin/users/' . $user2->id); + $mech->submit_form_ok( { with_fields => { + name => "Updated Name" + } } ); + $user2->discard_changes; + is $user2->name, "Updated Name", "Name set correctly"; + is $mech->uri->path, '/admin/users/' . $user2->id, 'redirected back to user form'; + + $mech->get_ok('/admin/users/' . $user2->id); + $mech->submit_form_ok( { with_fields => { + body => undef + } } ); + $user2->discard_changes; + is $user2->from_body, undef, "from_body unset"; + is $mech->uri->path, '/admin/users', 'redirected back to users list'; + + $mech->log_out_ok; + }; +}; + +subtest 'user categories are cleared when from_body is unset' => sub { + FixMyStreet::override_config { + ALLOWED_COBRANDS => [ 'oxfordshire' ], + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $mech->log_in_ok( $user3->email ); + + my $cat1 = $mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Traffic lights', email => 'lights@example.com' ); + my $cat2 = $mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Potholes', email => 'potholes@example.com' ); + $user2->set_extra_metadata('categories', [ $cat1->id, $cat2->id ]); + $user2->from_body($oxfordshire->id); + $user2->update; + + $mech->get_ok('/admin/users/' . $user2->id); + $mech->submit_form_ok( { with_fields => { + body => undef + } } ); + + $user2->discard_changes; + is $user2->from_body, undef, "from_body unset"; + is $user2->get_extra_metadata('categories'), undef, "categories unset"; + }; +}; + +$mech->log_in_ok( $superuser->email ); + for my $test ( { desc => 'add user - blank form', @@ -157,6 +246,7 @@ for my $test ( subtest $test->{desc} => sub { $mech->get_ok('/admin/users'); $mech->submit_form_ok( { with_fields => $test->{fields} } ); + $mech->content_contains('Norman') if $test->{fields}{name}; if ($test->{error}) { $mech->content_contains($_) for @{$test->{error}}; } else { @@ -166,7 +256,7 @@ for my $test ( } my %default_perms = ( - "permissions[moderate]" => undef, + "permissions[moderate]" => 'on', "permissions[planned_reports]" => undef, "permissions[report_mark_private]" => undef, "permissions[report_edit]" => undef, @@ -180,14 +270,13 @@ my %default_perms = ( "permissions[contribute_as_body]" => undef, "permissions[default_to_body]" => undef, "permissions[view_body_contribute_details]" => undef, - "permissions[user_edit]" => undef, + "permissions[user_edit]" => 'on', "permissions[user_manage_permissions]" => undef, "permissions[user_assign_body]" => undef, "permissions[user_assign_areas]" => undef, "permissions[template_edit]" => undef, "permissions[responsepriority_edit]" => undef, "permissions[category_edit]" => undef, - trusted_bodies => undef, ); # Start this section with user having no name @@ -202,7 +291,7 @@ FixMyStreet::override_config { desc => 'edit user name', fields => { name => '', - email => 'test@example.com', + email => $user->email, email_verified => 1, body => $haringey->id, phone => '', @@ -211,6 +300,7 @@ FixMyStreet::override_config { is_superuser => undef, area_ids => undef, %default_perms, + roles => $role->id, }, changes => { name => 'Changed User', @@ -222,7 +312,7 @@ FixMyStreet::override_config { desc => 'edit user email', fields => { name => 'Changed User', - email => 'test@example.com', + email => $user->email, email_verified => 1, body => $haringey->id, phone => '', @@ -231,6 +321,7 @@ FixMyStreet::override_config { is_superuser => undef, area_ids => undef, %default_perms, + roles => $role->id, }, changes => { email => 'changed@example.com', @@ -251,10 +342,14 @@ FixMyStreet::override_config { is_superuser => undef, area_ids => undef, %default_perms, + roles => $role->id, }, changes => { body => $southend->id, }, + removed => [ + 'roles', + ], log_count => 3, log_entries => [qw/edit edit edit/], }, @@ -339,6 +434,8 @@ FixMyStreet::override_config { }, added => { %default_perms, + 'permissions[moderate]' => undef, + 'permissions[user_edit]' => undef, }, log_count => 5, log_entries => [qw/edit edit edit edit edit/], @@ -394,7 +491,7 @@ FixMyStreet::override_config { $mech->create_problems_for_body(2, 2514, 'Title', { user => $existing_user }); my $count = FixMyStreet::DB->resultset('Problem')->search({ user_id => $user->id })->count; $mech->get_ok( '/admin/users/' . $user->id ); - $mech->submit_form_ok( { with_fields => { email => 'existing@example.com' } }, 'submit email change' ); + $mech->submit_form_ok( { with_fields => { email => $existing_user->email } }, 'submit email change' ); is $mech->uri->path, '/admin/users/' . $existing_user->id, 'redirected'; my $p = FixMyStreet::DB->resultset('Problem')->search({ user_id => $existing_user->id })->count; is $p, $count + 2, 'reports merged'; @@ -448,7 +545,7 @@ subtest "Send login email from admin for unverified email" => sub { is $email->header('Subject'), "Your FixMyStreet account details", "subject is correct"; - is $email->header('To'), 'test@example.com', "to is correct"; + is $email->header('To'), $user->email, "to is correct"; my $link = $mech->get_link_from_email($email); @@ -470,7 +567,10 @@ subtest "Send login email from admin for unverified email" => sub { }; subtest "Anonymizing user from admin" => sub { - $mech->create_problems_for_body(4, 2237, 'Title'); + my ($problem) = $mech->create_problems_for_body(4, 2237, 'Title'); + $mech->create_comment_for_problem($problem, $user, $user->name, 'An update', 'f', 'confirmed', 'confirmed'); + $mech->create_comment_for_problem($problem, $user, $user->name, '2nd update', 't', 'confirmed', 'fixed - user'); + $mech->create_comment_for_problem($problem, $user, $user->name, '3rd update', 'f', 'unconfirmed', 'confirmed'); my $count_p = FixMyStreet::DB->resultset('Problem')->search({ user_id => $user->id })->count; my $count_u = FixMyStreet::DB->resultset('Comment')->search({ user_id => $user->id })->count; $mech->get_ok( '/admin/users/' . $user->id ); @@ -492,6 +592,12 @@ subtest "Hiding user's reports from admin" => sub { is $c, $count_u; }; +subtest "Hiding user with only unconfirmed updates does not error" => sub { + FixMyStreet::DB->resultset('Comment')->search({ user_id => $user->id, state => 'hidden' })->update({ state => 'unconfirmed' }); + $mech->get_ok( '/admin/users/' . $user->id ); + $mech->submit_form_ok({ button => 'hide_everywhere' }); +}; + subtest "Logging user out" => sub { my $mech2 = FixMyStreet::TestMech->new; $mech2->log_in_ok($user->email); @@ -580,4 +686,25 @@ subtest "View timeline" => sub { $mech->get_ok('/admin/timeline'); }; +subtest 'View user log' => sub { + my $p = FixMyStreet::DB->resultset('Problem')->search({ user_id => $user->id })->first; + $user->add_to_planned_reports($p); + + # User 1 created all the reports + my $id = $p->id; + $mech->get_ok('/admin/users?search=' . $user->email); + $mech->follow_link_ok({ text => 'Timeline', n => 2 }); + $mech->content_like(qr/Problem.*?>$id<\/a> created/); + $mech->content_like(qr/Problem.*?>$id<\/a> added to shortlist/); + + # User 3 edited user 2 above + $mech->get_ok('/admin/users/' . $user3->id . '/log'); + $mech->content_like(qr/Edited user.*?test2\@example/); + + # Superuser added a user, and merged one + $mech->get_ok('/admin/users/' . $superuser->id . '/log'); + $mech->content_like(qr/Added user.*?0156/); + $mech->content_like(qr/Merged user $original_user_id/); +}; + done_testing(); diff --git a/t/app/controller/admin/users_import.t b/t/app/controller/admin/users_import.t new file mode 100644 index 000000000..df8884797 --- /dev/null +++ b/t/app/controller/admin/users_import.t @@ -0,0 +1,34 @@ +use FixMyStreet::TestMech; + +my $mech = FixMyStreet::TestMech->new; + +my $superuser = $mech->create_user_ok('superuser@example.com', name => 'Super User', is_superuser => 1); +my $body = $mech->create_body_ok(2509, 'Haringey Borough Council'); + +$mech->log_in_ok( $superuser->email ); + +my $body_id = $body->id; +my $csv = <<EOF; +name,email,from_body,permissions,roles +Adrian,adrian\@example.org,$body_id,moderate:user_edit, +Belinda,belinda\@example.org,$body_id,,Customer Service +EOF + +FixMyStreet::DB->resultset("Role")->create({ + body => $body, + name => 'Customer Service', +}); + +subtest 'import CSV file' => sub { + $mech->get_ok('/admin/users/import'); + $mech->submit_form_ok({ with_fields => { + csvfile => [ [ undef, 'foo.csv', Content => $csv ], 1], + }}); + $mech->content_contains('Created 2 new users'); + my $a = FixMyStreet::DB->resultset("User")->find({ email => 'adrian@example.org' }); + is $a->user_body_permissions->count, 2; + my $b = FixMyStreet::DB->resultset("User")->find({ email => 'belinda@example.org' }); + is $b->roles->count, 1; +}; + +done_testing(); |