diff options
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Moderate.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/DB/Result/Comment.pm | 4 | ||||
-rw-r--r-- | t/app/controller/moderate.t | 325 | ||||
-rw-r--r-- | t/app/model/moderation.t | 66 |
4 files changed, 395 insertions, 2 deletions
diff --git a/perllib/FixMyStreet/App/Controller/Moderate.pm b/perllib/FixMyStreet/App/Controller/Moderate.pm index bf70d52c5..b2bd3db3d 100644 --- a/perllib/FixMyStreet/App/Controller/Moderate.pm +++ b/perllib/FixMyStreet/App/Controller/Moderate.pm @@ -124,9 +124,9 @@ sub report_moderate_hide : Private { if ($c->req->param('problem_hide')) { - $problem->update({ state => 'hidden' }); + $c->res->redirect( '/' ); # Go directly to front-page $c->detach( 'report_moderate_audit', ['hide'] ); # break chain here. } } diff --git a/perllib/FixMyStreet/DB/Result/Comment.pm b/perllib/FixMyStreet/DB/Result/Comment.pm index 526fbff90..3fae6860a 100644 --- a/perllib/FixMyStreet/DB/Result/Comment.pm +++ b/perllib/FixMyStreet/DB/Result/Comment.pm @@ -207,6 +207,8 @@ __PACKAGE__->has_many( # Schema::Loader, but that doesn't know about the problem_id mapping, so we now # (slightly hackishly) redefine here: # +# we also add cascade_delete, though this seems to be insufficient. +# # TODO: should add FK on moderation_original_data field for this, to get S::L to # pick up without hacks. @@ -216,7 +218,7 @@ __PACKAGE__->might_have( { "foreign.comment_id" => "self.id", "foreign.problem_id" => "self.problem_id", }, - { cascade_copy => 0, cascade_delete => 0 }, + { cascade_copy => 0, cascade_delete => 1 }, ); # we need the inline_constructor bit as we don't inherit from Moose diff --git a/t/app/controller/moderate.t b/t/app/controller/moderate.t new file mode 100644 index 000000000..82e178f9b --- /dev/null +++ b/t/app/controller/moderate.t @@ -0,0 +1,325 @@ +use strict; +use warnings; +use Test::More; +use utf8; + +use FixMyStreet::TestMech; +use FixMyStreet::App; +use Data::Dumper; + +my $mech = FixMyStreet::TestMech->new; + +my $BROMLEY_ID = 2482; +my $body = $mech->create_body_ok( $BROMLEY_ID, 'Bromley Council' ); + +my $dt = DateTime->now; + +my $user = + FixMyStreet::App->model('DB::User') + ->find_or_create( { email => 'test-moderation@example.com', name => 'Test User' } ); +$user->user_body_permissions->delete_all; +$user->discard_changes; + +sub create_report { + FixMyStreet::App->model('DB::Problem')->create( + { + postcode => 'BR1 3SB', + bodies_str => $BROMLEY_ID, + areas => ",$BROMLEY_ID,", + category => 'Other', + title => 'Good bad good', + detail => 'Good bad bad bad good bad', + used_map => 't', + name => 'Test User', + anonymous => 'f', + state => 'confirmed', + confirmed => $dt->ymd . ' ' . $dt->hms, + lang => 'en-gb', + service => '', + cobrand => 'default', + cobrand_data => '', + send_questionnaire => 't', + latitude => '51.4129', + longitude => '0.007831', + user_id => $user->id, + photo => 'DUMMY DATA', # this obv fake data would not be + # accepted by front-end but is + # enough to trigger "I have a + # photo" behaviour + }); +} +my $report = create_report(); +my $report2 = create_report(); + +my $REPORT_URL = '/report/' . $report->id ; + +subtest 'Auth' => sub { + + subtest 'Unaffiliated user cannot see moderation' => sub { + $mech->get_ok($REPORT_URL); + $mech->content_lacks('Moderat'); + + $mech->log_in_ok( $user->email ); + + $mech->get_ok($REPORT_URL); + $mech->content_lacks('Moderat'); + + $user->update({ from_body => $BROMLEY_ID }); + + $mech->get_ok($REPORT_URL); + $mech->content_lacks('Moderat'); + }; + + subtest 'Affiliated and permissioned user can see moderation' => sub { + # login and from_body are done in previous test. + $user->user_body_permissions->create({ + body => $body, + permission_type => 'moderate', + }); + + $mech->get_ok($REPORT_URL); + $mech->content_contains('Moderat'); + }; +}; + +my %problem_prepopulated = ( + problem_show_name => 1, + problem_show_photo => 1, + problem_title => 'Good bad good', + problem_detail => 'Good bad bad bad good bad', +); + +subtest 'Problem moderation' => sub { + + subtest 'Post modify title and text' => sub { + $mech->post_ok('/moderate/report/' . $report->id, { + %problem_prepopulated, + problem_title => 'Good good', + problem_detail => 'Good good improved', + }); + $mech->base_like( qr{\Q$REPORT_URL\E} ); + + $report->discard_changes; + is $report->title, 'Good [...] good'; + is $report->detail, 'Good [...] good [...]improved'; + }; + + subtest 'Revert title and text' => sub { + $mech->post_ok('/moderate/report/' . $report->id, { + %problem_prepopulated, + problem_revert_title => 1, + problem_revert_detail => 1, + }); + $mech->base_like( qr{\Q$REPORT_URL\E} ); + + $report->discard_changes; + is $report->title, 'Good bad good'; + is $report->detail, 'Good bad bad bad good bad'; + }; + + subtest 'Make anonymous' => sub { + $mech->content_lacks('Reported anonymously'); + + $mech->post_ok('/moderate/report/' . $report->id, { + %problem_prepopulated, + problem_show_name => 0, + }); + $mech->base_like( qr{\Q$REPORT_URL\E} ); + + $mech->content_contains('Reported anonymously'); + + $mech->post_ok('/moderate/report/' . $report->id, { + %problem_prepopulated, + problem_show_name => 1, + }); + $mech->base_like( qr{\Q$REPORT_URL\E} ); + + $mech->content_lacks('Reported anonymously'); + }; + + subtest 'Hide photo' => sub { + $mech->content_contains('Photo of this report'); + + $mech->post_ok('/moderate/report/' . $report->id, { + %problem_prepopulated, + problem_show_photo => 0, + }); + $mech->base_like( qr{\Q$REPORT_URL\E} ); + + $mech->content_lacks('Photo of this report'); + + $mech->post_ok('/moderate/report/' . $report->id, { + %problem_prepopulated, + problem_show_photo => 1, + }); + $mech->base_like( qr{\Q$REPORT_URL\E} ); + + $mech->content_contains('Photo of this report'); + }; + + subtest 'Hide report' => sub { + my $resp = $mech->post('/moderate/report/' . $report->id, { + %problem_prepopulated, + problem_hide => 1, + }); + $mech->base_unlike( qr{/report/}, 'redirected to front page' ); + + $report->discard_changes; + is $report->state, 'hidden', 'Is hidden'; + + # reset + $report->update({ state => 'confirmed' }); + }; +}; + +$mech->content_lacks('Posted anonymously', 'sanity check'); + +subtest 'Problem 2' => sub { + my $REPORT2_URL = '/report/' . $report2->id ; + $mech->post_ok('/moderate/report/' . $report2->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->post_ok('/moderate/report/' . $report2->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'; +}; + +sub create_update { + $report->comments->create({ + user => $user, + name => 'Test User', + anonymous => 'f', + photo => 'DUMMY DATA', # as above + text => 'update good good bad good', + state => 'confirmed', + mark_fixed => 0, + }); +} +my %update_prepopulated = ( + update_show_name => 1, + update_show_photo => 1, + update_detail => 'update good good bad good', +); + +my $update = create_update(); + +subtest 'updates' => sub { + + my $MODERATE_UPDATE_URL = sprintf '/moderate/report/%d/update/%d', $report->id, $update->id; + + subtest 'Update modify text' => sub { + $mech->post_ok( $MODERATE_UPDATE_URL, { + %update_prepopulated, + update_detail => 'update good good good', + }) or die $mech->content; + $mech->base_like( qr{\Q$REPORT_URL\E} ); + + $update->discard_changes; + is $update->text, 'update good good [...] good', + }; + + subtest 'Revert text' => sub { + $mech->post_ok( $MODERATE_UPDATE_URL, { + %update_prepopulated, + update_revert_detail => 1, + }); + $mech->base_like( qr{\Q$REPORT_URL\E} ); + + $update->discard_changes; + $update->discard_changes; + is $update->text, 'update good good bad good', + }; + + subtest 'Make anonymous' => sub { + $mech->content_lacks('Posted anonymously') + or die sprintf '%d (%d)', $update->id, $report->comments->count; + + $mech->post_ok( $MODERATE_UPDATE_URL, { + %update_prepopulated, + update_show_name => 0, + }); + $mech->base_like( qr{\Q$REPORT_URL\E} ); + + $mech->content_contains('Posted anonymously'); + + $mech->post_ok( $MODERATE_UPDATE_URL, { + %update_prepopulated, + update_show_name => 1, + }); + $mech->base_like( qr{\Q$REPORT_URL\E} ); + + $mech->content_lacks('Posted anonymously'); + }; + + subtest 'Hide photo' => sub { + $report->update({ photo => undef }); # hide the main photo so we can just look for text in comment + + $mech->get_ok($REPORT_URL); + + $mech->content_contains('Photo of this report'); + + $mech->post_ok( $MODERATE_UPDATE_URL, { + %update_prepopulated, + update_show_photo => 0, + }); + $mech->base_like( qr{\Q$REPORT_URL\E} ); + + $mech->content_lacks('Photo of this report'); + + $mech->post_ok( $MODERATE_UPDATE_URL, { + %update_prepopulated, + update_show_photo => 1, + }); + $mech->base_like( qr{\Q$REPORT_URL\E} ); + + $mech->content_contains('Photo of this report'); + }; + + subtest 'Hide comment' => sub { + $mech->content_contains('update good good bad good'); + + $mech->post_ok( $MODERATE_UPDATE_URL, { + %update_prepopulated, + update_hide => 1, + }); + $mech->content_lacks('update good good bad good'); + }; + + $update->moderation_original_data->delete; +}; + +my $update2 = create_update(); + +subtest 'Update 2' => sub { + my $MODERATE_UPDATE2_URL = sprintf '/moderate/report/%d/update/%d', $report->id, $update2->id; + $mech->post_ok( $MODERATE_UPDATE2_URL, { + %update_prepopulated, + update_detail => 'update good good good', + }) or die $mech->content; + + $update2->discard_changes; + is $update2->text, 'update good good [...] good', +}; + +$update->delete; +$update2->delete; +$report->moderation_original_data->delete; +$report->delete; +$report2->delete; + +done_testing(); diff --git a/t/app/model/moderation.t b/t/app/model/moderation.t new file mode 100644 index 000000000..cdc9a91b0 --- /dev/null +++ b/t/app/model/moderation.t @@ -0,0 +1,66 @@ +use strict; +use warnings; +use Test::More; +use Test::Exception; +use utf8; + +use FixMyStreet::App; +use Data::Dumper; +use DateTime; + +my $dt = DateTime->now; +my $user = FixMyStreet::App->model('DB::User')->find_or_create({ + name => 'Bob', email => 'bob@example.com', +}); + +sub get_report_and_original_data { + my $report = FixMyStreet::App->model('DB::Problem')->create( + { + postcode => 'BR1 3SB', + bodies_str => '', + areas => ",,", + category => 'Other', + title => 'test', + detail => 'test', + used_map => 't', + name => 'Anon', + anonymous => 't', + state => 'confirmed', + confirmed => $dt->ymd . ' ' . $dt->hms, + lang => 'en-gb', + service => '', + cobrand => 'default', + cobrand_data => '', + send_questionnaire => 't', + latitude => '51.4129', + longitude => '0.007831', + user => $user, + }); + my $original = $report->create_related( moderation_original_data => { + anonymous => 't', + title => 'test', + detail => 'test', + photo => 'f', + } ); + + return ($report, $original); +} + +subtest 'Explicit Deletion (sanity test)' => sub { + my ($report, $orig) = get_report_and_original_data; + + lives_ok { + $orig->delete; + $report->delete; + }; +}; + +subtest 'Implicit Chained Deletion' => sub { + my ($report, $orig) = get_report_and_original_data; + + lives_ok { + $report->delete; + }; +}; + +done_testing(); |