use FixMyStreet::TestMech;
# avoid wide character warnings from the category change message
use open ':std', ':encoding(UTF-8)';
my $mech = FixMyStreet::TestMech->new;
my $user = $mech->create_user_ok('test@example.com', name => 'Test User');
my $user2 = $mech->create_user_ok('test2@example.com', name => 'Test User 2');
my $superuser = $mech->create_user_ok('superuser@example.com', name => 'Super User', is_superuser => 1);
my $oxfordshire = $mech->create_body_ok(2237, 'Oxfordshire County Council');
my $oxfordshirecontact = $mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Potholes', email => 'potholes@example.com' );
$mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Traffic lights', email => 'lights@example.com' );
my $oxford = $mech->create_body_ok(2421, 'Oxford City Council');
$mech->create_contact_ok( body_id => $oxford->id, category => 'Graffiti', email => 'graffiti@example.net' );
my $dt = DateTime->new(
year => 2011,
month => 04,
day => 16,
hour => 15,
minute => 47,
second => 23
);
my $report = FixMyStreet::App->model('DB::Problem')->find_or_create(
{
postcode => 'SW1A 1AA',
bodies_str => '2504',
areas => ',105255,11806,11828,2247,2504,',
category => 'Other',
title => 'Report to Edit',
detail => 'Detail for Report to Edit',
used_map => 't',
name => 'Test User',
anonymous => 'f',
external_id => '13',
state => 'confirmed',
confirmed => $dt->ymd . ' ' . $dt->hms,
lang => 'en-gb',
service => '',
cobrand => '',
cobrand_data => '',
send_questionnaire => 't',
latitude => '51.5016605453401',
longitude => '-0.142497580865087',
user_id => $user->id,
whensent => $dt->ymd . ' ' . $dt->hms,
}
);
$mech->log_in_ok( $superuser->email );
my $log_entries = FixMyStreet::App->model('DB::AdminLog')->search(
{
object_type => 'problem',
object_id => $report->id
},
{
order_by => { -desc => 'id' },
}
);
is $log_entries->count, 0, 'no admin log entries';
my $report_id = $report->id;
ok $report, "created test report - $report_id";
foreach my $test (
{
description => 'edit report title',
fields => {
title => 'Report to Edit',
detail => 'Detail for Report to Edit',
state => 'confirmed',
name => 'Test User',
username => $user->email,
anonymous => 0,
flagged => undef,
non_public => undef,
closed_updates => undef,
},
changes => { title => 'Edited Report', },
log_entries => [qw/edit/],
resend => 0,
},
{
description => 'edit report description',
fields => {
title => 'Edited Report',
detail => 'Detail for Report to Edit',
state => 'confirmed',
name => 'Test User',
username => $user->email,
anonymous => 0,
flagged => undef,
non_public => undef,
closed_updates => undef,
},
changes => { detail => 'Edited Detail', },
log_entries => [qw/edit edit/],
resend => 0,
},
{
description => 'edit report user name',
fields => {
title => 'Edited Report',
detail => 'Edited Detail',
state => 'confirmed',
name => 'Test User',
username => $user->email,
anonymous => 0,
flagged => undef,
non_public => undef,
closed_updates => undef,
},
changes => { name => 'Edited User', },
log_entries => [qw/edit edit edit/],
resend => 0,
user => $user,
},
{
description => 'edit report set flagged true',
fields => {
title => 'Edited Report',
detail => 'Edited Detail',
state => 'confirmed',
name => 'Edited User',
username => $user->email,
anonymous => 0,
flagged => undef,
non_public => undef,
closed_updates => undef,
},
changes => {
flagged => 'on',
},
log_entries => [qw/edit edit edit edit/],
resend => 0,
user => $user,
},
{
description => 'edit report user email',
fields => {
title => 'Edited Report',
detail => 'Edited Detail',
state => 'confirmed',
name => 'Edited User',
username => $user->email,
anonymous => 0,
flagged => 'on',
non_public => undef,
closed_updates => undef,
},
changes => { username => $user2->email, },
log_entries => [qw/edit edit edit edit edit/],
resend => 0,
user => $user2,
},
{
description => 'change state to unconfirmed',
fields => {
title => 'Edited Report',
detail => 'Edited Detail',
state => 'confirmed',
name => 'Edited User',
username => $user2->email,
anonymous => 0,
flagged => 'on',
non_public => undef,
closed_updates => undef,
},
expect_comment => 1,
changes => { state => 'unconfirmed' },
log_entries => [qw/edit state_change edit edit edit edit edit/],
resend => 0,
},
{
description => 'change state to confirmed',
fields => {
title => 'Edited Report',
detail => 'Edited Detail',
state => 'unconfirmed',
name => 'Edited User',
username => $user2->email,
anonymous => 0,
flagged => 'on',
non_public => undef,
closed_updates => undef,
},
expect_comment => 1,
changes => { state => 'confirmed' },
log_entries => [qw/edit state_change edit state_change edit edit edit edit edit/],
resend => 0,
},
{
description => 'change state to fixed',
fields => {
title => 'Edited Report',
detail => 'Edited Detail',
state => 'confirmed',
name => 'Edited User',
username => $user2->email,
anonymous => 0,
flagged => 'on',
non_public => undef,
closed_updates => undef,
},
expect_comment => 1,
changes => { state => 'fixed' },
log_entries =>
[qw/edit state_change edit state_change edit state_change edit edit edit edit edit/],
resend => 0,
},
{
description => 'change state to hidden',
fields => {
title => 'Edited Report',
detail => 'Edited Detail',
state => 'fixed',
name => 'Edited User',
username => $user2->email,
anonymous => 0,
flagged => 'on',
non_public => undef,
closed_updates => undef,
},
expect_comment => 1,
changes => { state => 'hidden' },
log_entries => [
qw/edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/
],
resend => 0,
},
{
description => 'edit and change state',
fields => {
title => 'Edited Report',
detail => 'Edited Detail',
state => 'hidden',
name => 'Edited User',
username => $user2->email,
anonymous => 0,
flagged => 'on',
non_public => undef,
closed_updates => undef,
},
expect_comment => 1,
changes => {
state => 'confirmed',
anonymous => 1,
},
log_entries => [
qw/edit state_change edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/
],
resend => 0,
},
{
description => 'resend',
fields => {
title => 'Edited Report',
detail => 'Edited Detail',
state => 'confirmed',
name => 'Edited User',
username => $user2->email,
anonymous => 1,
flagged => 'on',
non_public => undef,
closed_updates => undef,
},
changes => {},
log_entries => [
qw/resend edit state_change edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/
],
resend => 1,
},
{
description => 'non public',
fields => {
title => 'Edited Report',
detail => 'Edited Detail',
state => 'confirmed',
name => 'Edited User',
username => $user2->email,
anonymous => 1,
flagged => 'on',
non_public => undef,
closed_updates => undef,
},
changes => {
non_public => 'on',
},
log_entries => [
qw/edit resend edit state_change edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/
],
resend => 0,
},
{
description => 'close to updates',
fields => {
title => 'Edited Report',
detail => 'Edited Detail',
state => 'confirmed',
name => 'Edited User',
username => $user2->email,
anonymous => 1,
flagged => 'on',
non_public => 'on',
closed_updates => undef,
},
changes => { closed_updates => 'on' },
log_entries => [
qw/edit edit resend edit state_change edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/
],
},
{
description => 'change state to investigating as body superuser',
fields => {
title => 'Edited Report',
detail => 'Edited Detail',
state => 'confirmed',
name => 'Edited User',
username => $user2->email,
anonymous => 1,
flagged => 'on',
non_public => 'on',
closed_updates => undef,
},
expect_comment => 1,
user_body => $oxfordshire,
changes => { state => 'investigating' },
log_entries => [
qw/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,
},
{
description => 'change state to in progess and change category as body superuser',
fields => {
title => 'Edited Report',
detail => 'Edited Detail',
state => 'investigating',
name => 'Edited User',
username => $user2->email,
anonymous => 1,
flagged => 'on',
non_public => 'on',
closed_updates => undef,
},
expect_comment => 1,
expected_text => '*Category changed from ‘Other’ to ‘Potholes’*',
user_body => $oxfordshire,
changes => { state => 'in progress', category => 'Potholes' },
log_entries => [
qw/edit state_change edit state_change edit edit resend edit state_change edit state_change edit state_change edit state_change edit state_change edit edit edit edit edit/
],
resend => 0,
},
)
{
subtest $test->{description} => sub {
$report->comments->delete;
$log_entries->reset;
if ( $test->{user_body} ) {
$superuser->from_body( $test->{user_body}->id );
$superuser->update;
}
$mech->get_ok("/admin/report_edit/$report_id");
@{$test->{fields}}{'external_id', 'external_body', 'external_team', 'category'} = (13, "", "", "Other");
is_deeply( $mech->visible_form_values(), $test->{fields}, 'initial form values' );
my $new_fields = {
%{ $test->{fields} },
%{ $test->{changes} },
};
if ( $test->{resend} ) {
$mech->click_ok( 'resend' );
} else {
$mech->submit_form_ok( { with_fields => $new_fields }, 'form_submitted' );
}
is_deeply( $mech->visible_form_values(), $new_fields, 'changed form values' );
is $log_entries->count, scalar @{$test->{log_entries}}, 'log entry count';
is $log_entries->next->action, $_, 'log entry added' for @{ $test->{log_entries} };
$report->discard_changes;
if ($report->state eq 'confirmed' && $report->whensent) {
$mech->content_contains( 'type="submit" name="resend"', 'resend button' );
} else {
$mech->content_lacks( 'type="submit" name="resend"', 'no resend button' );
}
if ($report->state eq 'fixed') {
$mech->content_contains('pin-green');
}
$test->{changes}->{flagged} = 1 if $test->{changes}->{flagged};
$test->{changes}->{non_public} = 1 if $test->{changes}->{non_public};
if ($test->{changes}->{closed_updates}) {
is $report->get_extra_metadata('closed_updates'), 1, "closed_updates updated";
$mech->get_ok("/report/$report_id");
$mech->content_lacks('Provide an update');
$report->unset_extra_metadata('closed_updates');
$report->update;
delete $test->{changes}->{closed_updates};
}
is $report->$_, $test->{changes}->{$_}, "$_ updated" for grep { $_ ne 'username' } keys %{ $test->{changes} };
if ( $test->{user} ) {
is $report->user->id, $test->{user}->id, 'user changed';
}
if ( $test->{resend} ) {
$mech->content_contains( 'That problem will now be resent' );
is $report->whensent, undef, 'mark report to resend';
}
if ( $test->{expect_comment} ) {
my $comment = $report->comments->first;
ok $comment, 'report status change creates comment';
is $report->comments->count, 1, 'report only has one comment';
if ($test->{expected_text}) {
is $comment->text, $test->{expected_text}, 'comment has expected text';
} else {
is $comment->text, '', 'comment has no text';
}
if ( $test->{user_body} ) {
ok $comment->get_extra_metadata('is_body_user'), 'body user metadata set';
ok !$comment->get_extra_metadata('is_superuser'), 'superuser metadata not set';
is $comment->name, $test->{user_body}->name, 'comment name is body name';
} else {
ok !$comment->get_extra_metadata('is_body_user'), 'body user metadata not set';
ok $comment->get_extra_metadata('is_superuser'), 'superuser metadata set';
is $comment->name, _('an administrator'), 'comment name is admin';
}
} else {
is $report->comments->count, 0, 'report has no comments';
}
$superuser->from_body(undef);
$superuser->update;
};
}
FixMyStreet::override_config {
ALLOWED_COBRANDS => 'fixmystreet',
}, sub {
subtest 'change report category' => sub {
my ($ox_report) = $mech->create_problems_for_body(1, $oxfordshire->id, 'Unsure', {
category => 'Potholes',
areas => ',2237,2421,', # Cached used by categories_for_point...
latitude => 51.7549262252,
longitude => -1.25617899435,
whensent => \'current_timestamp',
});
$mech->get_ok("/admin/report_edit/" . $ox_report->id);
$mech->submit_form_ok( { with_fields => { category => 'Traffic lights' } }, 'form_submitted' );
$ox_report->discard_changes;
is $ox_report->category, 'Traffic lights';
isnt $ox_report->whensent, undef;
is $ox_report->comments->count, 1, "Comment created for update";
is $ox_report->comments->first->text, '*Category changed from ‘Potholes’ to ‘Traffic lights’*', 'Comment text correct';
$mech->submit_form_ok( { with_fields => { category => 'Graffiti' } }, 'form_submitted' );
$ox_report->discard_changes;
is $ox_report->category, 'Graffiti';
is $ox_report->whensent, undef;
};
};
subtest 'change email to new user' => sub {
$log_entries->delete;
$mech->get_ok("/admin/report_edit/$report_id");
my $fields = {
title => $report->title,
detail => $report->detail,
state => $report->state,
name => $report->name,
username => $report->user->email,
category => 'Potholes',
anonymous => 1,
flagged => 'on',
non_public => 'on',
closed_updates => undef,
external_id => '13',
external_body => '',
external_team => '',
};
is_deeply( $mech->visible_form_values(), $fields, 'initial form values' );
my $changes = {
username => 'test3@example.com'
};
my $user3 = FixMyStreet::App->model('DB::User')->find( { email => 'test3@example.com' } );
ok !$user3, 'user not in database';
my $new_fields = {
%{ $fields },
%{ $changes },
};
$mech->submit_form_ok(
{
with_fields => $new_fields,
}
);
is $log_entries->count, 1, 'created admin log entries';
is $log_entries->first->action, 'edit', 'log action';
is_deeply( $mech->visible_form_values(), $new_fields, 'changed form values' );
$user3 = FixMyStreet::App->model('DB::User')->find( { email => 'test3@example.com' } );
$report->discard_changes;
ok $user3, 'new user created';
is $report->user_id, $user3->id, 'user changed to new user';
};
subtest 'adding email to abuse list from report page' => sub {
my $email = $report->user->email;
my $abuse = FixMyStreet::App->model('DB::Abuse')->find( { email => $email } );
$abuse->delete if $abuse;
$mech->get_ok( '/admin/report_edit/' . $report->id );
$mech->content_contains('Ban user');
$mech->click_ok('banuser');
$mech->content_contains('User added to abuse list');
$mech->content_contains('User in abuse table');
$abuse = FixMyStreet::App->model('DB::Abuse')->find( { email => $email } );
ok $abuse, 'entry created in abuse table';
$mech->get_ok( '/admin/report_edit/' . $report->id );
$mech->content_contains('User in abuse table');
};
subtest 'flagging user from report page' => sub {
$report->user->flagged(0);
$report->user->update;
$mech->get_ok( '/admin/report_edit/' . $report->id );
$mech->content_contains('Flag user');
$mech->click_ok('flaguser');
$mech->content_contains('User flagged');
$mech->content_contains('Remove flag');
$report->discard_changes;
ok $report->user->flagged, 'user flagged';
$mech->get_ok( '/admin/report_edit/' . $report->id );
$mech->content_contains('Remove flag');
};
subtest 'unflagging user from report page' => sub {
$report->user->flagged(1);
$report->user->update;
$mech->get_ok( '/admin/report_edit/' . $report->id );
$mech->content_contains('Remove flag');
$mech->click_ok('removeuserflag');
$mech->content_contains('User flag removed');
$mech->content_contains('Flag user');
$report->discard_changes;
ok !$report->user->flagged, 'user not flagged';
$mech->get_ok( '/admin/report_edit/' . $report->id );
$mech->content_contains('Flag user');
};
subtest "Test setting a report from unconfirmed to something else doesn't cause a front end error" => sub {
$report->update( { confirmed => undef, state => 'unconfirmed', non_public => 0 } );
$mech->get_ok("/admin/report_edit/$report_id");
$mech->submit_form_ok( { with_fields => { state => 'investigating' } } );
$report->discard_changes;
ok( $report->confirmed, 'report has a confirmed timestamp' );
$mech->get_ok("/report/$report_id");
};
subtest "Test display of report extra data" => sub {
$mech->get_ok("/admin/report_edit/$report_id");
$mech->content_contains('Extra data: No');
$report->set_extra_metadata('extra_field', 'this is extra data');
$report->update;
$mech->get_ok("/admin/report_edit/$report_id");
$mech->content_contains('extra_field: 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',
bodies_str => '2504',
areas => ',105255,11806,11828,2247,2504,',
category => 'Other',
title => 'Report to Duplicate Edit',
detail => 'Detail for Duplicate Report to Edit',
used_map => 't',
name => 'Test User',
anonymous => 'f',
external_id => '13',
state => 'confirmed',
confirmed => $dt->ymd . ' ' . $dt->hms,
lang => 'en-gb',
service => '',
cobrand => '',
cobrand_data => '',
send_questionnaire => 't',
latitude => '51.5016605453401',
longitude => '-0.142497580865087',
user_id => $user->id,
whensent => $dt->ymd . ' ' . $dt->hms,
}
);
subtest "Test display of report duplicates extra data" => sub {
$report->update( { extra => undef } );
$mech->get_ok("/admin/report_edit/$report_id");
$mech->content_contains('Extra data: No');
$report2->set_duplicate_of($report_id);
$report2->update;
$mech->get_ok("/admin/report_edit/$report_id");
$mech->content_contains('Duplicates: ' . $report2->id);
};
subtest "Test display of fields extra data" => sub {
$report->unset_extra_metadata( 'duplicates' );
$report->update;
$mech->get_ok("/admin/report_edit/$report_id");
$mech->content_contains('Extra data: No');
$report->push_extra_fields( {
name => 'report_url',
value => 'http://example.com',
});
$report->update;
$report->discard_changes;
$mech->get_ok("/admin/report_edit/$report_id");
$mech->content_contains('report_url: http://example.com');
$report->set_extra_fields( {
description => 'Report URL',
name => 'report_url',
value => 'http://example.com',
});
$report->update;
$mech->get_ok("/admin/report_edit/$report_id");
$mech->content_contains('Report URL (report_url): http://example.com');
};
done_testing();