diff options
author | Ivan Kohler <ivan@freeside.biz> | 2012-04-24 11:35:56 -0700 |
---|---|---|
committer | Ivan Kohler <ivan@freeside.biz> | 2012-04-24 11:35:56 -0700 |
commit | 6587f6ba7d047ddc1686c080090afe7d53365bd4 (patch) | |
tree | ec77342668e8865aca669c9b4736e84e3077b523 /rt/t/web | |
parent | 47153aae5c2fc00316654e7277fccd45f72ff611 (diff) |
first pass RT4 merge, RT#13852
Diffstat (limited to 'rt/t/web')
94 files changed, 4977 insertions, 777 deletions
diff --git a/rt/t/web/admin_groups.t b/rt/t/web/admin_groups.t new file mode 100644 index 000000000..783b5ad44 --- /dev/null +++ b/rt/t/web/admin_groups.t @@ -0,0 +1,59 @@ +#!/usr/bin/perl +use strict; +use warnings; + +use RT::Test tests => 26; + +my ( $url, $m ) = RT::Test->started_ok; +ok( $m->login(), 'logged in' ); + +{ + diag "test creating a group" if $ENV{TEST_VERBOSE}; + $m->get_ok( $url . '/Admin/Groups/Modify.html?Create=1' ); + $m->content_contains('Create a new group', 'found title'); + $m->submit_form_ok({ + form_number => 3, + fields => { Name => 'test group' }, + }); + $m->content_contains('Group created', 'found results'); + $m->content_contains('Modify the group test group', 'found title'); +} + +{ + diag "test creating another group" if $ENV{TEST_VERBOSE}; + $m->get_ok( $url . '/Admin/Groups/Modify.html?Create=1' ); + $m->content_contains('Create a new group', 'found title'); + $m->submit_form_ok({ + form_number => 3, + fields => { Name => 'test group2' }, + }); + $m->content_contains('Group created', 'found results'); + $m->content_contains('Modify the group test group2', 'found title'); +} + +{ + diag "test creating an overlapping group" if $ENV{TEST_VERBOSE}; + $m->get_ok( $url . '/Admin/Groups/Modify.html?Create=1' ); + $m->content_contains('Create a new group', 'found title'); + $m->submit_form_ok({ + form_number => 3, + fields => { Name => 'test group' }, + }); + $m->content_contains('Group could not be created', 'found results'); + $m->content_like(qr/Group name .+? is already in use/, 'found message'); +} + +{ + diag "test updating a group name to overlap" if $ENV{TEST_VERBOSE}; + $m->get_ok( $url . '/Admin/Groups/' ); + $m->follow_link_ok({text => 'test group2'}, 'found title'); + $m->content_contains('Modify the group test group2'); + $m->submit_form_ok({ + form_number => 3, + fields => { Name => 'test group' }, + }); + $m->content_lacks('Name changed', "name not changed"); + $m->content_contains('Illegal value for Name', 'found error message'); + $m->content_contains('test group', 'did not find new name'); +} + diff --git a/rt/t/web/admin_user.t b/rt/t/web/admin_user.t new file mode 100644 index 000000000..fde075f4d --- /dev/null +++ b/rt/t/web/admin_user.t @@ -0,0 +1,21 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use RT::Test tests => 7; + +my ( $url, $m ) = RT::Test->started_ok; +ok( $m->login(), 'logged in' ); + +my $root = RT::User->new( $RT::SystemUser ); +$root->Load('root'); +ok( $root->id, 'loaded root' ); + + +diag "test the history page" if $ENV{TEST_VERBOSE}; +$m->get_ok( $url . '/Admin/Users/History.html?id=' . $root->id ); +$m->content_contains('User created', 'has User created entry'); + +# TODO more /Admin/Users tests + diff --git a/rt/t/web/articles-links.t b/rt/t/web/articles-links.t new file mode 100644 index 000000000..713dc05e4 --- /dev/null +++ b/rt/t/web/articles-links.t @@ -0,0 +1,52 @@ +use strict; +use warnings; + +use RT::Test tests => 18; + +RT->Config->Set( MasonLocalComponentRoot => RT::Test::get_abs_relocatable_dir('html') ); + +my ($baseurl, $m) = RT::Test->started_ok; + +my $queue = RT::Queue->new(RT->SystemUser); +$queue->Load('General'); + +my $class = RT::Class->new(RT->SystemUser); +my ($ok, $msg) = $class->Create(Name => "issues"); +ok($ok, "created class: $msg"); + +($ok, $msg) = $class->AddToObject($queue); +ok($ok, "applied class to General: $msg"); + +my $article = RT::Article->new(RT->SystemUser); +($ok, $msg) = $article->Create(Name => "instance of ticket #17421", Class => $class->id); +ok($ok, "created article: $msg"); + +ok($m->login, "logged in"); + +my $ticket = RT::Test->create_ticket(Queue => $queue->Id, Subject => 'oh wow! an AUTOLOAD bug'); + +$m->goto_ticket($ticket->id); +$m->follow_link_ok({text => 'Reply'}); + +$m->form_name('TicketUpdate'); +$m->field('Articles-Include-Article-Named' => $article->Name); +$m->submit; + +$m->content_contains('instance of ticket #17421', 'got the name of the article in the ticket'); + +# delete RT::Article's Name method on the server so we'll need to AUTOLOAD it +my $clone = $m->clone; +$clone->get_ok('/delete-article-name-method.html'); +like($clone->content, qr/{deleted}/); + +$m->form_name('TicketUpdate'); +$m->click('SubmitTicket'); + +$m->follow_link_ok({text => 'Links'}); + +$m->text_contains('Article ' . $article->id . ': instance of ticket #17421', 'Article appears with its name in the links table'); + +my $refers_to = $ticket->RefersTo; +is($refers_to->Count, 1, 'the ticket has a refers-to link'); +is($refers_to->First->TargetURI->URI, 'fsck.com-article://example.com/article/' . $article->Id, 'when we included the article it created a refers-to'); + diff --git a/rt/t/web/attachment-with-name-0.t b/rt/t/web/attachment-with-name-0.t new file mode 100644 index 000000000..12a8dd548 --- /dev/null +++ b/rt/t/web/attachment-with-name-0.t @@ -0,0 +1,23 @@ +use strict; +use warnings; + +use RT::Test tests => 8; +my ( $baseurl, $m ) = RT::Test->started_ok; +ok $m->login, 'logged in as root'; + +use File::Spec; + +my $file = File::Spec->catfile( RT::Test->temp_directory, 0 ); +open my $fh, '>', $file or die $!; +print $fh 'foobar'; +close $fh; + +$m->get_ok( '/Ticket/Create.html?Queue=1' ); + +$m->submit_form( + form_number => 3, + fields => { Subject => 'test att 0', Content => 'test', Attach => $file }, +); +$m->content_like( qr/Ticket \d+ created/i, 'created the ticket' ); +$m->follow_link_ok( { text => 'Download 0' } ); +$m->content_contains( 'foobar', 'file content' ); diff --git a/rt/t/web/attachment_encoding.t b/rt/t/web/attachment_encoding.t index 9ba567746..bfbf24590 100644 --- a/rt/t/web/attachment_encoding.t +++ b/rt/t/web/attachment_encoding.t @@ -3,13 +3,11 @@ use strict; use warnings; -use RT::Test tests => 28; +use RT::Test tests => 32; use Encode; my ( $baseurl, $m ) = RT::Test->started_ok; ok $m->login, 'logged in as root'; -$RT::Test::SKIP_REQUEST_WORK_AROUND = 1; - use utf8; use File::Spec; @@ -19,7 +17,7 @@ diag 'test without attachments' if $ENV{TEST_VERBOSE}; { $m->get_ok( $baseurl . '/Ticket/Create.html?Queue=1' ); - $m->form_number(3); + $m->form_name('TicketModify'); $m->submit_form( form_number => 3, fields => { Subject => '标题', Content => '测试' }, @@ -47,7 +45,7 @@ diag 'test with attachemnts' if $ENV{TEST_VERBOSE}; { my $file = - File::Spec->catfile( File::Spec->tmpdir, 'rt_attachemnt_abcde.txt' ); + File::Spec->catfile( RT::Test->temp_directory, encode_utf8 '附件.txt' ); open( my $fh, '>', $file ) or die $!; binmode $fh, ':utf8'; print $fh '附件'; @@ -55,12 +53,14 @@ diag 'test with attachemnts' if $ENV{TEST_VERBOSE}; $m->get_ok( $baseurl . '/Ticket/Create.html?Queue=1' ); - $m->form_number(3); + $m->form_name('TicketModify'); $m->submit_form( form_number => 3, fields => { Subject => '标题', Content => '测试', Attach => $file }, ); $m->content_like( qr/Ticket \d+ created/i, 'created the ticket' ); + $m->content_contains( '附件.txt', 'attached filename' ); + $m->content_lacks( encode_utf8 '附件.txt', 'no double encoded attached filename' ); $m->follow_link_ok( { text => 'with headers' }, '-> /Ticket/Attachment/WithHeaders/...' ); @@ -82,7 +82,7 @@ diag 'test with attachemnts' if $ENV{TEST_VERBOSE}; $m->back; $m->back; - $m->follow_link_ok( { text_regex => qr/by Enoch Root/ }, + $m->follow_link_ok( { text => 'Download 附件.txt' }, '-> /Ticket/Attachment/...' ); $m->content_contains( '附件', 'has content 附件' ); @@ -100,4 +100,3 @@ diag 'test with attachemnts' if $ENV{TEST_VERBOSE}; unlink $file; } - diff --git a/rt/t/web/attachments.t b/rt/t/web/attachments.t index e827b2f02..8c75f6caf 100644 --- a/rt/t/web/attachments.t +++ b/rt/t/web/attachments.t @@ -1,15 +1,15 @@ #!/usr/bin/perl -w use strict; -use RT::Test tests => 14; +use RT::Test tests => 25; -use constant LogoFile => $RT::MasonComponentRoot .'/NoAuth/images/bplogo.gif'; +use constant LogoFile => $RT::MasonComponentRoot .'/NoAuth/images/bpslogo.png'; use constant FaviconFile => $RT::MasonComponentRoot .'/NoAuth/images/favicon.png'; my ($baseurl, $m) = RT::Test->started_ok; ok $m->login, 'logged in'; -my $queue = RT::Queue->new($RT::Nobody); +my $queue = RT::Queue->new(RT->Nobody); my $qid = $queue->Load('General'); ok( $qid, "Loaded General queue" ); @@ -17,7 +17,7 @@ $m->form_name('CreateTicketInQueue'); $m->field('Queue', $qid); $m->submit; is($m->status, 200, "request successful"); -$m->content_like(qr/Create a new ticket/, 'ticket create page'); +$m->content_contains("Create a new ticket", 'ticket create page'); $m->form_name('TicketCreate'); $m->field('Subject', 'Attachments test'); @@ -26,9 +26,9 @@ $m->field('Content', 'Some content'); $m->submit; is($m->status, 200, "request successful"); -$m->content_like(qr/Attachments test/, 'we have subject on the page'); -$m->content_like(qr/Some content/, 'and content'); -$m->content_like(qr/Download bplogo\.gif/, 'page has file name'); +$m->content_contains('Attachments test', 'we have subject on the page'); +$m->content_contains('Some content', 'and content'); +$m->content_contains('Download bpslogo.png', 'page has file name'); $m->follow_link_ok({text => 'Reply'}, "reply to the ticket"); $m->form_name('TicketUpdate'); @@ -42,6 +42,34 @@ $m->field('UpdateContent', 'Message'); $m->click('SubmitTicket'); is($m->status, 200, "request successful"); -$m->content_like(qr/Download bplogo\.gif/, 'page has file name'); -$m->content_like(qr/Download favicon\.png/, 'page has file name'); +$m->content_contains('Download bpslogo.png', 'page has file name'); +$m->content_contains('Download favicon.png', 'page has file name'); + +diag "test mobile ui"; +$m->get_ok( $baseurl . '/m/ticket/create?Queue=' . $qid ); + +$m->form_name('TicketCreate'); +$m->field('Subject', 'Attachments test'); +$m->field('Attach', LogoFile); +$m->field('Content', 'Some content'); +$m->submit; +is($m->status, 200, "request successful"); + +$m->content_contains('Attachments test', 'we have subject on the page'); +$m->content_contains('bpslogo.png', 'page has file name'); + +$m->follow_link_ok({text => 'Reply'}, "reply to the ticket"); +$m->form_name('TicketUpdate'); +$m->field('Attach', LogoFile); +$m->click('AddMoreAttach'); +is($m->status, 200, "request successful"); + +$m->form_name('TicketUpdate'); +$m->field('Attach', FaviconFile); +$m->field('UpdateContent', 'Message'); +$m->click('SubmitTicket'); +is($m->status, 200, "request successful"); + +$m->content_contains('bpslogo.png', 'page has file name'); +$m->content_contains('favicon.png', 'page has file name'); diff --git a/rt/t/web/basic.t b/rt/t/web/basic.t index 3f94e732f..31e28c406 100644 --- a/rt/t/web/basic.t +++ b/rt/t/web/basic.t @@ -4,37 +4,35 @@ use strict; use warnings; use Encode; -use RT::Test tests => 21; -$RT::Test::SKIP_REQUEST_WORK_AROUND = 1; +use RT::Test tests => 23; my ($baseurl, $agent) = RT::Test->started_ok; my $url = $agent->rt_base_url; -diag $url if $ENV{TEST_VERBOSE}; # get the top page { $agent->get($url); - is ($agent->{'status'}, 200, "Loaded a page"); + is ($agent->status, 200, "Loaded a page"); } # test a login { $agent->login('root' => 'password'); # the field isn't named, so we have to click link 0 - is( $agent->{'status'}, 200, "Fetched the page ok"); - ok( $agent->{'content'} =~ /Logout/i, "Found a logout link"); + is( $agent->status, 200, "Fetched the page ok"); + $agent->content_contains("Logout", "Found a logout link"); } { - $agent->get($url."Ticket/Create.html?Queue=1"); - is ($agent->{'status'}, 200, "Loaded Create.html"); - $agent->form_number(3); + $agent->goto_create_ticket(1); + is ($agent->status, 200, "Loaded Create.html"); + $agent->form_name('TicketCreate'); my $string = Encode::decode_utf8("I18N Web Testing æøå"); $agent->field('Subject' => "Ticket with utf8 body"); $agent->field('Content' => $string); ok($agent->submit, "Created new ticket with $string as Content"); - $agent->content_like( qr{$string} , "Found the content"); + $agent->content_contains($string, "Found the content"); ok($agent->{redirected_uri}, "Did redirection"); { @@ -48,15 +46,15 @@ diag $url if $ENV{TEST_VERBOSE}; } { - $agent->get($url."Ticket/Create.html?Queue=1"); - is ($agent->{'status'}, 200, "Loaded Create.html"); - $agent->form_number(3); + $agent->goto_create_ticket(1); + is ($agent->status, 200, "Loaded Create.html"); + $agent->form_name('TicketCreate'); my $string = Encode::decode_utf8("I18N Web Testing æøå"); $agent->field('Subject' => $string); $agent->field('Content' => "Ticket with utf8 subject"); ok($agent->submit, "Created new ticket with $string as Content"); - $agent->content_like( qr{$string} , "Found the content"); + $agent->content_contains($string, "Found the content"); ok($agent->{redirected_uri}, "Did redirection"); { @@ -71,14 +69,13 @@ diag $url if $ENV{TEST_VERBOSE}; # Update time worked in hours { $agent->follow_link( text_regex => qr/Basics/ ); - $agent->submit_form( form_number => 3, + $agent->submit_form( form_name => 'TicketModify', fields => { TimeWorked => 5, 'TimeWorked-TimeUnits' => "hours" } ); - like ($agent->{'content'}, qr/to '300'/, "5 hours is 300 minutes"); + $agent->content_contains("to '300'", "5 hours is 300 minutes"); } -# {{{ test an image TODO: { todo_skip("Need to handle mason trying to compile images",1); @@ -94,9 +91,7 @@ is( "got a file of the correct size ($file)", ); } -# }}} -# {{{ Query Builder tests # # XXX: hey-ho, we have these tests in t/web/query-builder # TODO: move everything about QB there @@ -135,5 +130,3 @@ $query =~ s/\s+/ /g; is ($query, "Subject LIKE 'aaa' AND Subject LIKE 'bbb'"); - -1; diff --git a/rt/t/web/case-sensitivity.t b/rt/t/web/case-sensitivity.t new file mode 100644 index 000000000..276b7615a --- /dev/null +++ b/rt/t/web/case-sensitivity.t @@ -0,0 +1,85 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use RT::Test tests => 18; + +my $q = RT::Test->load_or_create_queue( Name => 'General' ); +ok $q && $q->id, 'loaded or created queue'; + +my ($root, $root_id); +{ + $root = RT::User->new( RT->SystemUser ); + $root->Load('root'); + ok $root_id = $root->id, 'found root'; +} + +my ($baseurl, $m) = RT::Test->started_ok; +$m->login; + +# test users auto completer +{ + $m->get_ok('/Helpers/Autocomplete/Users?term=eNo'); + require JSON; + is_deeply( + JSON::from_json( $m->content ), + [{"value" => "root\@localhost","label" => "Enoch Root"}] + ); +} + +# test ticket's People page +{ + my $ticket = RT::Test->create_ticket( Queue => $q->id ); + ok $ticket && $ticket->id, "created ticket"; + + $m->goto_ticket( $ticket->id ); + $m->follow_link_ok( {text => 'People'} ); + $m->form_number(3); + $m->select( UserField => 'RealName' ); + $m->field( UserString => 'eNo' ); + $m->click('OnlySearchForPeople'); + + my $form = $m->form_number(3); + my $input = $form->find_input('Ticket-AddWatcher-Principal-'. $root->id ); + ok $input, 'input is there'; +} + +# test users' admin UI +{ + $m->get_ok('/Admin/Users/'); + + $m->form_number(4); + $m->select( UserField => 'RealName' ); + $m->field( UserString => 'eNo' ); + $m->submit; + + like $m->uri, qr{\QAdmin/Users/Modify.html?id=$root_id\E}; +} + +# create a cf for testing +my $cf; +{ + $cf = RT::CustomField->new(RT->SystemUser); + my ($id,$msg) = $cf->Create( + Name => 'Test', + Type => 'Select', + MaxValues => '1', + Queue => $q->id, + ); + ok($id,$msg); + + ($id,$msg) = $cf->AddValue(Name => 'Enoch', Description => 'Root'); + ok($id,$msg); +} + +# test custom field values auto completer +{ + $m->get_ok('/Helpers/Autocomplete/CustomFieldValues?term=eNo&Object---CustomField-'. $cf->id .'-Value'); + require JSON; + is_deeply( + JSON::from_json( $m->content ), + [{"value" => "Enoch","label" => "Enoch (Root)"}] + ); +} + diff --git a/rt/t/web/cf_access.t b/rt/t/web/cf_access.t index 183597b4a..73b7765c1 100644 --- a/rt/t/web/cf_access.t +++ b/rt/t/web/cf_access.t @@ -1,23 +1,54 @@ #!/usr/bin/perl -w use strict; -use RT::Test tests => 26; -$RT::Test::SKIP_REQUEST_WORK_AROUND = 1; +use RT::Test tests => 32; my ($baseurl, $m) = RT::Test->started_ok; -use constant ImageFile => $RT::MasonComponentRoot .'/NoAuth/images/bplogo.gif'; +use constant ImageFile => $RT::MasonComponentRoot .'/NoAuth/images/bpslogo.png'; use constant ImageFileContent => RT::Test->file_content(ImageFile); ok $m->login, 'logged in'; -diag "Create a CF" if $ENV{'TEST_VERBOSE'}; +diag "Create a CF"; { - $m->follow_link( text => 'Configuration' ); - $m->title_is(q/RT Administration/, 'admin screen'); - $m->follow_link( text => 'Custom Fields' ); - $m->title_is(q/Select a Custom Field/, 'admin-cf screen'); - $m->follow_link( text => 'Create' ); + $m->follow_link( id => 'tools-config-custom-fields-create'); + + # Test form validation + $m->submit_form( + form_name => "ModifyCustomField", + fields => { + TypeComposite => 'Image-0', + LookupType => 'RT::Queue-RT::Ticket', + Name => '', + Description => 'img', + }, + ); + $m->text_contains('Invalid value for Name'); + + $m->submit_form( + form_name => "ModifyCustomField", + fields => { + TypeComposite => 'Image-0', + LookupType => 'RT::Queue-RT::Ticket', + Name => '0', + Description => 'img', + }, + ); + $m->text_contains('Invalid value for Name'); + + $m->submit_form( + form_name => "ModifyCustomField", + fields => { + TypeComposite => 'Image-0', + LookupType => 'RT::Queue-RT::Ticket', + Name => '1', + Description => 'img', + }, + ); + $m->text_contains('Invalid value for Name'); + + # The real submission $m->submit_form( form_name => "ModifyCustomField", fields => { @@ -27,19 +58,47 @@ diag "Create a CF" if $ENV{'TEST_VERBOSE'}; Description => 'img', }, ); + $m->text_contains('Object created'); + + # Validation on update + $m->form_name("ModifyCustomField"); + $m->set_fields( + TypeComposite => 'Image-0', + LookupType => 'RT::Queue-RT::Ticket', + Name => '', + Description => 'img', + ); + $m->click('Update'); + $m->text_contains('Illegal value for Name'); + $m->form_name("ModifyCustomField"); + $m->set_fields( + TypeComposite => 'Image-0', + LookupType => 'RT::Queue-RT::Ticket', + Name => '0', + Description => 'img', + ); + $m->click('Update'); + $m->text_contains('Illegal value for Name'); + $m->form_name("ModifyCustomField"); + $m->set_fields( + TypeComposite => 'Image-0', + LookupType => 'RT::Queue-RT::Ticket', + Name => '1', + Description => 'img', + ); + $m->click('Update'); + $m->text_contains('Illegal value for Name'); } -diag "apply the CF to General queue" if $ENV{'TEST_VERBOSE'}; +diag "apply the CF to General queue"; my ( $cf, $cfid, $tid ); { - $m->title_is(q/Created CustomField img/, 'admin-cf created'); - $m->follow_link( text => 'Queues' ); - $m->title_is(q/Admin queues/, 'admin-queues screen'); + $m->title_is(q/Editing CustomField img/, 'admin-cf created'); + $m->follow_link( id => 'tools-config-queues'); $m->follow_link( text => 'General' ); - $m->title_is(q/Editing Configuration for queue General/, 'admin-queue: general'); - $m->follow_link( text => 'Ticket Custom Fields' ); - - $m->title_is(q/Edit Custom Fields for General/, 'admin-queue: general cfid'); + $m->title_is(q/Configuration for queue General/, 'admin-queue: general'); + $m->follow_link( id => 'page-ticket-custom-fields'); + $m->title_is(q/Custom Fields for queue General/, 'admin-queue: general cfid'); $m->form_name('EditCustomFields'); # Sort by numeric IDs in names @@ -52,7 +111,7 @@ my ( $cf, $cfid, $tid ); $m->tick( AddCustomField => $_ => 0 ) for @names; # ...and not any other. ;-) $m->click('UpdateCFs'); - $m->content_like( qr/Object created/, 'TCF added to the queue' ); + $m->content_contains('Object created', 'TCF added to the queue' ); } my $tester = RT::Test->load_or_create_user( Name => 'tester', Password => '123456' ); @@ -61,17 +120,16 @@ RT::Test->set_rights( Right => [qw(SeeQueue ShowTicket CreateTicket)], }, ); -ok $m->login( $tester->Name, 123456), 'logged in'; +ok $m->login( $tester->Name, 123456, logout => 1), 'logged in'; diag "check that we have no the CF on the create" - ." ticket page when user has no SeeCustomField right" - if $ENV{'TEST_VERBOSE'}; + ." ticket page when user has no SeeCustomField right"; { $m->submit_form( form_name => "CreateTicketInQueue", fields => { Queue => 'General' }, ); - $m->content_unlike(qr/Upload multiple images/, 'has no upload image field'); + $m->content_lacks('Upload multiple images', 'has no upload image field'); my $form = $m->form_name("TicketCreate"); my $upload_field = "Object-RT::Ticket--CustomField-$cfid-Upload"; @@ -83,9 +141,9 @@ diag "check that we have no the CF on the create" ); $m->content_like(qr/Ticket \d+ created/, "a ticket is created succesfully"); - $m->content_unlike(qr/img:/, 'has no img field on the page'); + $m->content_lacks('img:', 'has no img field on the page'); $m->follow_link( text => 'Custom Fields'); - $m->content_unlike(qr/Upload multiple images/, 'has no upload image field'); + $m->content_lacks('Upload multiple images', 'has no upload image field'); } RT::Test->set_rights( @@ -95,14 +153,13 @@ RT::Test->set_rights( ); diag "check that we have no the CF on the create" - ." ticket page when user has no ModifyCustomField right" - if $ENV{'TEST_VERBOSE'}; + ." ticket page when user has no ModifyCustomField right"; { $m->submit_form( form_name => "CreateTicketInQueue", fields => { Queue => 'General' }, ); - $m->content_unlike(qr/Upload multiple images/, 'has no upload image field'); + $m->content_lacks('Upload multiple images', 'has no upload image field'); my $form = $m->form_name("TicketCreate"); my $upload_field = "Object-RT::Ticket--CustomField-$cfid-Upload"; @@ -115,9 +172,9 @@ diag "check that we have no the CF on the create" $tid = $1 if $m->content =~ /Ticket (\d+) created/i; ok $tid, "a ticket is created succesfully"; - $m->follow_link( text => 'Custom Fields' ); - $m->content_unlike(qr/Upload multiple images/, 'has no upload image field'); - $form = $m->form_number(3); + $m->follow_link( id => 'page-basics'); + $m->content_lacks('Upload multiple images', 'has no upload image field'); + $form = $m->form_name('TicketModify'); $upload_field = "Object-RT::Ticket-$tid-CustomField-$cfid-Upload"; ok !$form->find_input( $upload_field ), 'no form field on the page'; } @@ -128,13 +185,13 @@ RT::Test->set_rights( }, ); -diag "create a ticket with an image" if $ENV{'TEST_VERBOSE'}; +diag "create a ticket with an image"; { $m->submit_form( form_name => "CreateTicketInQueue", fields => { Queue => 'General' }, ); - $m->content_like(qr/Upload multiple images/, 'has a upload image field'); + $m->content_contains('Upload multiple images', 'has a upload image field'); $cf =~ /(\d+)$/ or die "Hey this is impossible dude"; my $upload_field = "Object-RT::Ticket--CustomField-$1-Upload"; @@ -153,14 +210,12 @@ diag "create a ticket with an image" if $ENV{'TEST_VERBOSE'}; $m->title_like(qr/testing img cf creation/, "its title is the Subject"); - $m->follow_link( text => 'bplogo.gif' ); + $m->follow_link( text => 'bpslogo.png' ); $m->content_is(ImageFileContent, "it links to the uploaded image"); } $m->get( $m->rt_base_url ); -$m->follow_link( text => 'Tickets' ); -$m->follow_link( text => 'New Query' ); - +$m->follow_link( id => 'search-new'); $m->title_is(q/Query Builder/, 'Query building'); $m->submit_form( form_name => "BuildQuery", @@ -182,7 +237,7 @@ $m->click('AddCol'); $m->form_name('BuildQuery'); $m->click('DoSearch'); -$m->follow_link( text_regex => qr/bplogo\.gif/ ); +$m->follow_link( text_regex => qr/bpslogo\.png/ ); $m->content_is(ImageFileContent, "it links to the uploaded image"); __END__ diff --git a/rt/t/web/cf_date.t b/rt/t/web/cf_date.t new file mode 100644 index 000000000..887aa4220 --- /dev/null +++ b/rt/t/web/cf_date.t @@ -0,0 +1,187 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use RT::Test tests => 35; + +my ( $baseurl, $m ) = RT::Test->started_ok; +ok $m->login, 'logged in as root'; +my $root = RT::User->new(RT->SystemUser); +ok( $root->Load('root'), 'load root user' ); + +my $cf_name = 'test cf date'; + +my $cfid; +diag "Create a CF"; +{ + $m->follow_link( id => 'tools-config-custom-fields-create'); + $m->submit_form( + form_name => "ModifyCustomField", + fields => { + Name => $cf_name, + TypeComposite => 'Date-1', + LookupType => 'RT::Queue-RT::Ticket', + }, + ); + $m->content_contains('Object created', 'created CF sucessfully' ); + $cfid = $m->form_name('ModifyCustomField')->value('id'); + ok $cfid, "found id of the CF in the form, it's #$cfid"; +} + +diag "apply the CF to General queue"; +my $queue = RT::Test->load_or_create_queue( Name => 'General' ); +ok $queue && $queue->id, 'loaded or created queue'; + +{ + $m->follow_link( id => 'tools-config-queues-select'); + $m->title_is( q/Admin queues/, 'admin-queues screen' ); + $m->follow_link( text => 'General' ); + $m->title_is( q/Configuration for queue General/, + 'admin-queue: general' ); + $m->follow_link( text => 'Ticket Custom Fields' ); + $m->title_is( q/Custom Fields for queue General/, + 'admin-queue: general cfid' ); + + $m->form_name('EditCustomFields'); + $m->tick( "AddCustomField" => $cfid ); + $m->click('UpdateCFs'); + + $m->content_contains('Object created', 'TCF added to the queue' ); +} + +diag 'check valid inputs with various timezones in ticket create page'; +{ + my ( $ticket, $id ); + + $m->submit_form( + form_name => "CreateTicketInQueue", + fields => { Queue => 'General' }, + ); + $m->content_contains('Select date', 'has cf field' ); + + $m->submit_form( + form_name => "TicketCreate", + fields => { + Subject => 'test 2010-05-04', + Content => 'test', + "Object-RT::Ticket--CustomField-$cfid-Values" => '2010-05-04', + }, + ); + ok( ($id) = $m->content =~ /Ticket (\d+) created/, "created ticket $id" ); + + $ticket = RT::Ticket->new(RT->SystemUser); + $ticket->Load($id); + is( $ticket->CustomFieldValues($cfid)->First->Content, + '2010-05-04', 'date in db' ); + + $m->content_contains('test cf date:', 'has no cf date field on the page' ); + $m->content_contains('Tue May 04 2010', + 'has cf date value on the page' ); +} + +diag 'check search build page'; +{ + $m->get_ok( $baseurl . '/Search/Build.html?Query=Queue=1' ); + + $m->form_name('BuildQuery'); + my ($cf_op) = + $m->find_all_inputs( type => 'option', name_regex => qr/test cf date/ ); + is_deeply( + [ $cf_op->possible_values ], + [ '<', '=', '>' ], + 'right oprators' + ); + + my ($cf_field) = + $m->find_all_inputs( type => 'text', name_regex => qr/test cf date/ ); + $m->submit_form( + fields => { + $cf_op->name => '=', + $cf_field->name => '2010-05-04' + }, + button => 'DoSearch', + ); + + $m->content_contains( 'Found 1 ticket', 'Found 1 ticket' ); + $m->content_contains( '2010-05-04', 'got the right ticket' ); + $m->content_lacks( '2010-05-06', 'did not get the wrong ticket' ); + + $m->get_ok( $baseurl . '/Search/Build.html?Query=Queue=1' ); + $m->form_name('BuildQuery'); + $m->submit_form( + fields => { + $cf_op->name => '<', + $cf_field->name => '2010-05-05' + }, + button => 'DoSearch', + ); + $m->content_contains( 'Found 1 ticket', 'Found 1 ticket' ); + + $m->get_ok( $baseurl . '/Search/Build.html?Query=Queue=1' ); + $m->form_name('BuildQuery'); + $m->submit_form( + fields => { + $cf_op->name => '>', + $cf_field->name => '2010-05-03', + }, + button => 'DoSearch', + ); + $m->content_contains( 'Found 1 ticket', 'Found 1 ticket' ); + + $m->get_ok( $baseurl . '/Search/Build.html?Query=Queue=1' ); + $m->form_name('BuildQuery'); + $m->submit_form( + fields => { + $cf_op->name => '=', + $cf_field->name => '2010-05-05', + }, + button => 'DoSearch', + ); + $m->content_contains( 'Found 0 tickets', 'Found 0 tickets' ); + + $m->get_ok( $baseurl . '/Search/Build.html?Query=Queue=1' ); + $m->form_name('BuildQuery'); + $m->submit_form( + fields => { + $cf_op->name => '<', + $cf_field->name => '2010-05-03', + }, + button => 'DoSearch', + ); + $m->content_contains( 'Found 0 tickets', 'Found 0 tickets' ); + + $m->get_ok( $baseurl . '/Search/Build.html?Query=Queue=1' ); + $m->form_name('BuildQuery'); + $m->submit_form( + fields => { + $cf_op->name => '>', + $cf_field->name => '2010-05-05', + }, + button => 'DoSearch', + ); + $m->content_contains( 'Found 0 tickets', 'Found 0 tickets' ); +} + +diag 'check invalid inputs'; +{ + $m->submit_form( + form_name => "CreateTicketInQueue", + fields => { Queue => 'General' }, + ); + my $form = $m->form_name("TicketCreate"); + + $m->submit_form( + form_name => "TicketCreate", + fields => { + Subject => 'test', + Content => 'test', + "Object-RT::Ticket--CustomField-$cfid-Values" => 'foodate', + }, + ); + $m->content_like( qr/Ticket \d+ created/, + "a ticket is created succesfully" ); + + $m->content_contains('test cf date:', 'has no cf date field on the page' ); + $m->content_lacks('foodate', 'invalid dates not set' ); +} diff --git a/rt/t/web/cf_datetime.t b/rt/t/web/cf_datetime.t new file mode 100644 index 000000000..9781c5e2e --- /dev/null +++ b/rt/t/web/cf_datetime.t @@ -0,0 +1,235 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use RT::Test tests => 51; + +RT->Config->Set( 'Timezone' => 'EST5EDT' ); # -04:00 +my ($baseurl, $m) = RT::Test->started_ok; +ok $m->login, 'logged in as root'; +my $root = RT::User->new( RT->SystemUser ); +ok( $root->Load('root'), 'load root user' ); + +my $cf_name = 'test cf datetime'; + +my $why; + +if ( ( $ENV{RT_TEST_WEB_HANDLER} || '' ) =~ /^apache(\+mod_perl)?$/ + && RT::Test::Apache->apache_mpm_type =~ /^(?:worker|event)$/ ) +{ + $why = +'localizing $ENV{TZ} does *not* work with mod_perl+mpm_event or mod_perl+mpm_worker'; +} + +my $cfid; +diag "Create a CF"; +{ + $m->follow_link( id => 'tools-config-custom-fields-create'); + $m->submit_form( + form_name => "ModifyCustomField", + fields => { + Name => $cf_name, + TypeComposite => 'DateTime-1', + LookupType => 'RT::Queue-RT::Ticket', + }, + ); + $m->content_contains('Object created', 'created CF sucessfully' ); + $cfid = $m->form_name('ModifyCustomField')->value('id'); + ok $cfid, "found id of the CF in the form, it's #$cfid"; +} + +diag "apply the CF to General queue"; +my $queue = RT::Test->load_or_create_queue( Name => 'General' ); +ok $queue && $queue->id, 'loaded or created queue'; + +{ + $m->follow_link( text => 'Queues' ); + $m->title_is(q/Admin queues/, 'admin-queues screen'); + $m->follow_link( text => 'General' ); + $m->title_is(q/Configuration for queue General/, 'admin-queue: general'); + $m->follow_link( text => 'Ticket Custom Fields' ); + $m->title_is(q/Custom Fields for queue General/, 'admin-queue: general cfid'); + + $m->form_name('EditCustomFields'); + $m->tick( "AddCustomField" => $cfid ); + $m->click('UpdateCFs'); + + $m->content_contains('Object created', 'TCF added to the queue' ); +} + +diag 'check valid inputs with various timezones in ticket create page'; +{ + my ( $ticket, $id ); + + $m->submit_form( + form_name => "CreateTicketInQueue", + fields => { Queue => 'General' }, + ); + $m->content_contains('Select datetime', 'has cf field'); + + $m->submit_form( + form_name => "TicketCreate", + fields => { + Subject => 'test 2010-05-04 13:00:01', + Content => 'test', + "Object-RT::Ticket--CustomField-$cfid-Values" => '2010-05-04 13:00:01', + }, + ); + ok( ($id) = $m->content =~ /Ticket (\d+) created/, + "created ticket $id" ); + + $ticket = RT::Ticket->new( RT->SystemUser ); + $ticket->Load($id); + TODO: { + local $TODO = $why; + is( + $ticket->CustomFieldValues($cfid)->First->Content, + '2010-05-04 17:00:01', + 'date in db is in UTC' + ); + } + + $m->content_contains('test cf datetime:', 'has cf datetime field on the page'); + $m->content_contains('Tue May 04 13:00:01 2010', 'has cf datetime value on the page'); + + $root->SetTimezone( 'Asia/Shanghai' ); + # interesting that $m->reload doesn't work + $m->get_ok( $m->uri ); + + TODO: { + local $TODO = $why; + $m->content_contains( 'Wed May 05 01:00:01 2010', + 'cf datetime value respects user timezone' ); + } + + $m->submit_form( + form_name => "CreateTicketInQueue", + fields => { Queue => 'General' }, + ); + $m->submit_form( + form_name => "TicketCreate", + fields => { + Subject => 'test 2010-05-06 07:00:01', + Content => 'test', + "Object-RT::Ticket--CustomField-$cfid-Values" => '2010-05-06 07:00:01', + }, + ); + ok( ($id) = $m->content =~ /Ticket (\d+) created/, + "created ticket $id" ); + $ticket = RT::Ticket->new( RT->SystemUser ); + $ticket->Load($id); + TODO: { + local $TODO = $why; + is( + $ticket->CustomFieldValues($cfid)->First->Content, + '2010-05-05 23:00:01', + 'date in db is in UTC' + ); + } + + $m->content_contains('test cf datetime:', 'has cf datetime field on the page'); + $m->content_contains( 'Thu May 06 07:00:01 2010', + 'cf datetime input respects user timezone' ); + $root->SetTimezone( 'EST5EDT' ); # back to -04:00 + $m->get_ok( $m->uri ); + + TODO: { + local $TODO = $why; + $m->content_contains( 'Wed May 05 19:00:01 2010', + 'cf datetime value respects user timezone' ); + } +} + + +diag 'check search build page'; +{ + $m->get_ok( $baseurl . '/Search/Build.html?Query=Queue=1' ); + + $m->form_name('BuildQuery'); + my ($cf_op) = + $m->find_all_inputs( type => 'option', name_regex => qr/test cf datetime/ ); + is_deeply( + [ $cf_op->possible_values ], + [ '<', '=', '>' ], + 'right oprators' + ); + + my ($cf_field) = + $m->find_all_inputs( type => 'text', name_regex => qr/test cf datetime/ ); + + is_results_number( { $cf_op->name => '=', $cf_field->name => '2010-05-04', }, 1 ); + $m->content_contains( '2010-05-04', 'got the right ticket' ); + $m->content_lacks( '2010-05-06', 'did not get the wrong ticket' ); + + my $shanghai = RT::Test->load_or_create_user( + Name => 'shanghai', + Password => 'password', + Timezone => 'Asia/Shanghai', + ); + ok( $shanghai->PrincipalObj->GrantRight( + Right => 'SuperUser', + Object => $RT::System, + )); + $m->login( 'shanghai', 'password', logout => 1 ); + + is_results_number( { $cf_op->name => '<', $cf_field->name => '2010-05-07', }, 2 ); + is_results_number( { $cf_op->name => '>', $cf_field->name => '2010-05-04', }, 2 ); + + TODO: { + local $TODO = $why; + is_results_number( { $cf_op->name => '=', $cf_field->name => '2010-05-05', }, 1 ); + is_results_number( { $cf_op->name => '=', $cf_field->name => '2010-05-05 01:00:01', }, 1 ); + } + + is_results_number( + { $cf_op->name => '=', $cf_field->name => '2010-05-05 02:00:01', }, 0 ); + + is_results_number( { $cf_op->name => '=', $cf_field->name => '2010-05-06', }, 1 ); + is_results_number( { $cf_op->name => '=', $cf_field->name => '2010-05-06 07:00:01', }, 1 ); + is_results_number( { $cf_op->name => '=', $cf_field->name => '2010-05-06 08:00:01', }, 0 ); +} + +diag 'check invalid inputs'; +{ + $m->submit_form( + form_name => "CreateTicketInQueue", + fields => { Queue => 'General' }, + ); + my $form = $m->form_name("TicketCreate"); + + $m->submit_form( + form_name => "TicketCreate", + fields => { + Subject => 'test', + Content => 'test', + "Object-RT::Ticket--CustomField-$cfid-Values" => 'foodate', + }, + ); + $m->content_like(qr/Ticket \d+ created/, "a ticket is created succesfully"); + + $m->content_contains('test cf datetime:', 'has cf datetime field on the page'); + $m->content_lacks('foodate', 'invalid dates not set'); +} + +sub is_results_number { + local $Test::Builder::Level = $Test::Builder::Level + 1; + my $fields = shift; + my $number = shift; + my $operator = shift; + my $value = shift; + { + local $TODO; + $m->get_ok( $baseurl . '/Search/Build.html?Query=Queue=1' ); + } + $m->form_name('BuildQuery'); + $m->submit_form( + fields => $fields, + button => 'DoSearch', + ); + $m->content_contains( "Found $number ticket", "Found $number ticket" ); +} + +# to make $m->DESTROY happy +undef $m; + diff --git a/rt/t/web/cf_onqueue.t b/rt/t/web/cf_onqueue.t index bed4dd188..422eeff60 100644 --- a/rt/t/web/cf_onqueue.t +++ b/rt/t/web/cf_onqueue.t @@ -6,13 +6,9 @@ my ($baseurl, $m) = RT::Test->started_ok; ok $m->login, 'logged in'; -diag "Create a queue CF" if $ENV{'TEST_VERBOSE'}; +diag "Create a queue CF"; { - $m->follow_link( text => 'Configuration' ); - $m->title_is(q/RT Administration/, 'admin screen'); - $m->follow_link( text => 'Custom Fields' ); - $m->title_is(q/Select a Custom Field/, 'admin-cf screen'); - $m->follow_link( text => 'Create' ); + $m->follow_link( id => 'tools-config-custom-fields-create'); $m->submit_form( form_name => "ModifyCustomField", fields => { @@ -22,10 +18,10 @@ diag "Create a queue CF" if $ENV{'TEST_VERBOSE'}; Description => 'QueueCFTest', }, ); - $m->content_like( qr/Object created/, 'CF QueueCFTest created' ); + $m->content_contains('Object created', 'CF QueueCFTest created' ); } -diag "Apply the new CF globally" if $ENV{'TEST_VERBOSE'}; +diag "Apply the new CF globally"; { $m->follow_link( text => 'Global' ); $m->title_is(q!Admin/Global configuration!, 'global configuration screen'); @@ -33,22 +29,22 @@ diag "Apply the new CF globally" if $ENV{'TEST_VERBOSE'}; $m->title_is(q/Global custom field configuration/, 'global custom field configuration screen'); $m->follow_link( url => 'Queues.html' ); $m->title_is(q/Edit Custom Fields for all queues/, 'global custom field for all queues configuration screen'); - $m->content_like( qr/QueueCFTest/, 'CF QueueCFTest displayed on page' ); + $m->content_contains('QueueCFTest', 'CF QueueCFTest displayed on page' ); $m->form_name('EditCustomFields'); $m->tick( AddCustomField => 1 ); $m->click('UpdateCFs'); - $m->content_like( qr/Object created/, 'CF QueueCFTest enabled globally' ); + $m->content_contains('Object created', 'CF QueueCFTest enabled globally' ); } -diag "Edit the CF value for default queue" if $ENV{'TEST_VERBOSE'}; +diag "Edit the CF value for default queue"; { $m->follow_link( url => '/Admin/Queues/' ); $m->title_is(q/Admin queues/, 'queues configuration screen'); $m->follow_link( text => "1" ); - $m->title_is(q/Editing Configuration for queue General/, 'default queue configuration screen'); - $m->content_like( qr/QueueCFTest/, 'CF QueueCFTest displayed on default queue' ); + $m->title_is(q/Configuration for queue General/, 'default queue configuration screen'); + $m->content_contains('QueueCFTest', 'CF QueueCFTest displayed on default queue' ); $m->submit_form( form_number => 3, # The following doesn't want to works :( @@ -57,7 +53,7 @@ diag "Edit the CF value for default queue" if $ENV{'TEST_VERBOSE'}; 'Object-RT::Queue-1-CustomField-1-Value' => 'QueueCFTest content', }, ); - $m->content_like( qr/QueueCFTest QueueCFTest content added/, 'Content filed in CF QueueCFTest for default queue' ); + $m->content_contains('QueueCFTest QueueCFTest content added', 'Content filed in CF QueueCFTest for default queue' ); } diff --git a/rt/t/web/cf_render_type.t b/rt/t/web/cf_render_type.t new file mode 100644 index 000000000..8d8efa897 --- /dev/null +++ b/rt/t/web/cf_render_type.t @@ -0,0 +1,50 @@ +use strict; +use warnings; + +use RT::Test tests => 8; + +my ($baseurl, $m) = RT::Test->started_ok; +ok $m->login, 'logged in as root'; + +my $cf_name = 'test render type'; + +my $cfid; +diag "Create a CF"; +{ + $m->follow_link( id => 'tools-config-custom-fields-create'); + $m->submit_form( + form_name => "ModifyCustomField", + fields => { + Name => $cf_name, + TypeComposite => 'Freeform-1', + LookupType => 'RT::Queue-RT::Ticket', + }, + ); + $m->content_contains('Object created', 'created Freeform-1' ); + $cfid = $m->form_name('ModifyCustomField')->value('id'); + ok $cfid, "found id of the CF in the form, it's #$cfid"; +} + +diag "change to Select type"; +{ + $m->submit_form( + form_name => "ModifyCustomField", + fields => { TypeComposite => 'Select-1', }, + button => 'Update', + ); + $m->content_contains( + "Type changed from 'Enter one value' to 'Select one value'", + 'changed to Select-1' ); +} + +diag "let's save it again"; +{ + $m->submit_form( + form_name => "ModifyCustomField", + button => 'Update', + ); + $m->content_lacks( "Render Type changed from '1' to 'Select box'", + 'no buggy RenderType change msg' ); +} + + diff --git a/rt/t/web/cf_select_one.t b/rt/t/web/cf_select_one.t index 26c1fcf65..15fe416b4 100644 --- a/rt/t/web/cf_select_one.t +++ b/rt/t/web/cf_select_one.t @@ -3,7 +3,7 @@ use strict; use warnings; -use RT::Test tests => 46; +use RT::Test tests => 45; my ($baseurl, $m) = RT::Test->started_ok; ok $m->login, 'logged in as root'; @@ -11,13 +11,9 @@ ok $m->login, 'logged in as root'; my $cf_name = 'test select one value'; my $cfid; -diag "Create a CF" if $ENV{'TEST_VERBOSE'}; +diag "Create a CF"; { - $m->follow_link( text => 'Configuration' ); - $m->title_is(q/RT Administration/, 'admin screen'); - $m->follow_link( text => 'Custom Fields' ); - $m->title_is(q/Select a Custom Field/, 'admin-cf screen'); - $m->follow_link( text => 'Create' ); + $m->follow_link( id => 'tools-config-custom-fields-create'); $m->submit_form( form_name => "ModifyCustomField", fields => { @@ -26,12 +22,12 @@ diag "Create a CF" if $ENV{'TEST_VERBOSE'}; LookupType => 'RT::Queue-RT::Ticket', }, ); - $m->content_like( qr/Object created/, 'created CF sucessfully' ); + $m->content_contains('Object created', 'created CF sucessfully' ); $cfid = $m->form_name('ModifyCustomField')->value('id'); ok $cfid, "found id of the CF in the form, it's #$cfid"; } -diag "add 'qwe', 'ASD', '0' and ' foo ' as values to the CF" if $ENV{'TEST_VERBOSE'}; +diag "add 'qwe', 'ASD', '0' and ' foo ' as values to the CF"; { foreach my $value(qw(qwe ASD 0), 'foo ') { $m->submit_form( @@ -41,38 +37,36 @@ diag "add 'qwe', 'ASD', '0' and ' foo ' as values to the CF" if $ENV{'TEST_VERBO }, button => 'Update', ); - $m->content_like( qr/Object created/, 'added a value to the CF' ); # or diag $m->content; + $m->content_contains('Object created', 'added a value to the CF' ); # or diag $m->content; my $v = $value; $v =~ s/^\s+$//; $v =~ s/\s+$//; - $m->content_like( qr/value="$v"/, 'the added value is right' ); + $m->content_contains("value=\"$v\"", 'the added value is right' ); } } my $queue = RT::Test->load_or_create_queue( Name => 'General' ); ok $queue && $queue->id, 'loaded or created queue'; -diag "apply the CF to General queue" if $ENV{'TEST_VERBOSE'}; +diag "apply the CF to General queue"; { - $m->follow_link( text => 'Queues' ); - $m->title_is(q/Admin queues/, 'admin-queues screen'); + $m->follow_link( id => 'tools-config-queues'); $m->follow_link( text => 'General' ); - $m->title_is(q/Editing Configuration for queue General/, 'admin-queue: general'); - $m->follow_link( text => 'Ticket Custom Fields' ); - $m->title_is(q/Edit Custom Fields for General/, 'admin-queue: general cfid'); + $m->title_is(q/Configuration for queue General/, 'admin-queue: general'); + $m->follow_link( id => 'page-ticket-custom-fields'); + $m->title_is(q/Custom Fields for queue General/, 'admin-queue: general cfid'); $m->form_name('EditCustomFields'); $m->tick( "AddCustomField" => $cfid ); $m->click('UpdateCFs'); - $m->content_like( qr/Object created/, 'TCF added to the queue' ); + $m->content_contains('Object created', 'TCF added to the queue' ); } my $tid; -diag "create a ticket using API with 'asd'(not 'ASD') as value of the CF" - if $ENV{'TEST_VERBOSE'}; +diag "create a ticket using API with 'asd'(not 'ASD') as value of the CF"; { - my $ticket = RT::Ticket->new( $RT::SystemUser ); + my $ticket = RT::Ticket->new( RT->SystemUser ); my ($txnid, $msg); ($tid, $txnid, $msg) = $ticket->Create( Subject => 'test', @@ -80,7 +74,7 @@ diag "create a ticket using API with 'asd'(not 'ASD') as value of the CF" "CustomField-$cfid" => 'asd', ); ok $tid, "created ticket"; - diag $msg if $msg && $ENV{'TEST_VERBOSE'}; + diag $msg if $msg; # we use lc as we really don't care about case # so if later we'll add canonicalization of value @@ -89,72 +83,69 @@ diag "create a ticket using API with 'asd'(not 'ASD') as value of the CF" 'asd', 'assigned value of the CF'; } -diag "check that values of the CF are case insensetive(asd vs. ASD)" - if $ENV{'TEST_VERBOSE'}; +diag "check that values of the CF are case insensetive(asd vs. ASD)"; { ok $m->goto_ticket( $tid ), "opened ticket's page"; - $m->follow_link( text => 'Custom Fields' ); + $m->follow_link( id => 'page-basics'); $m->title_like(qr/Modify ticket/i, 'modify ticket'); - $m->content_like(qr/\Q$cf_name/, 'CF on the page'); + $m->content_contains($cf_name, 'CF on the page'); - my $value = $m->form_number(3)->value("Object-RT::Ticket-$tid-CustomField-$cfid-Values"); + my $value = $m->form_name('TicketModify')->value("Object-RT::Ticket-$tid-CustomField-$cfid-Values"); is lc $value, 'asd', 'correct value is selected'; $m->submit; $m->content_unlike(qr/\Q$cf_name\E.*?changed/mi, 'field is not changed'); - $value = $m->form_number(3)->value("Object-RT::Ticket-$tid-CustomField-$cfid-Values"); + $value = $m->form_name('TicketModify')->value("Object-RT::Ticket-$tid-CustomField-$cfid-Values"); is lc $value, 'asd', 'the same value is still selected'; - my $ticket = RT::Ticket->new( $RT::SystemUser ); + my $ticket = RT::Ticket->new( RT->SystemUser ); $ticket->Load( $tid ); ok $ticket->id, 'loaded the ticket'; is lc $ticket->FirstCustomFieldValue( $cf_name ), 'asd', 'value is still the same'; } -diag "check that 0 is ok value of the CF" - if $ENV{'TEST_VERBOSE'}; +diag "check that 0 is ok value of the CF"; { ok $m->goto_ticket( $tid ), "opened ticket's page"; - $m->follow_link( text => 'Custom Fields' ); + $m->follow_link( id => 'page-basics'); $m->title_like(qr/Modify ticket/i, 'modify ticket'); - $m->content_like(qr/\Q$cf_name/, 'CF on the page'); + $m->content_contains($cf_name, 'CF on the page'); - my $value = $m->form_number(3)->value("Object-RT::Ticket-$tid-CustomField-$cfid-Values"); + my $value = $m->form_name('TicketModify')->value("Object-RT::Ticket-$tid-CustomField-$cfid-Values"); is lc $value, 'asd', 'correct value is selected'; $m->select("Object-RT::Ticket-$tid-CustomField-$cfid-Values" => 0 ); $m->submit; $m->content_like(qr/\Q$cf_name\E.*?changed/mi, 'field is changed'); - $m->content_unlike(qr/0 is no longer a value for custom field/mi, 'no bad message in results'); + $m->content_lacks('0 is no longer a value for custom field', 'no bad message in results'); - $value = $m->form_number(3)->value("Object-RT::Ticket-$tid-CustomField-$cfid-Values"); + $value = $m->form_name('TicketModify')->value("Object-RT::Ticket-$tid-CustomField-$cfid-Values"); is lc $value, '0', 'new value is selected'; - my $ticket = RT::Ticket->new( $RT::SystemUser ); + my $ticket = RT::Ticket->new( RT->SystemUser ); $ticket->Load( $tid ); ok $ticket->id, 'loaded the ticket'; is lc $ticket->FirstCustomFieldValue( $cf_name ), '0', 'API returns correct value'; } -diag "check that we can set empty value when the current is 0" - if $ENV{'TEST_VERBOSE'}; +diag "check that we can set empty value when the current is 0"; { ok $m->goto_ticket( $tid ), "opened ticket's page"; - $m->follow_link( text => 'Custom Fields' ); + $m->follow_link( id => 'page-basics'); $m->title_like(qr/Modify ticket/i, 'modify ticket'); - $m->content_like(qr/\Q$cf_name/, 'CF on the page'); + $m->content_contains($cf_name, 'CF on the page'); - my $value = $m->form_number(3)->value("Object-RT::Ticket-$tid-CustomField-$cfid-Values"); + my $value = $m->form_name('TicketModify')->value("Object-RT::Ticket-$tid-CustomField-$cfid-Values"); is lc $value, '0', 'correct value is selected'; $m->select("Object-RT::Ticket-$tid-CustomField-$cfid-Values" => '' ); $m->submit; - $m->content_like(qr/0 is no longer a value for custom field/mi, '0 is no longer a value'); + $m->content_contains('0 is no longer a value for custom field', '0 is no longer a value'); - $value = $m->form_number(3)->value("Object-RT::Ticket-$tid-CustomField-$cfid-Values"); + $value = $m->form_name('TicketModify')->value("Object-RT::Ticket-$tid-CustomField-$cfid-Values"); is $value, '', '(no value) is selected'; - my $ticket = RT::Ticket->new( $RT::SystemUser ); + my $ticket = RT::Ticket->new( RT->SystemUser ); $ticket->Load( $tid ); ok $ticket->id, 'loaded the ticket'; is $ticket->FirstCustomFieldValue( $cf_name ), diff --git a/rt/t/web/charting.t b/rt/t/web/charting.t index 7c11f9c92..32d95d99b 100644 --- a/rt/t/web/charting.t +++ b/rt/t/web/charting.t @@ -1,7 +1,16 @@ use strict; use warnings; -use RT::Test no_plan => 1; +BEGIN { + require RT::Test; + + if (eval { require GD; 1 }) { + RT::Test->import(plan => 'no_plan'); + } + else { + RT::Test->import(skip_all => 'GD required.'); + } +} for my $n (1..7) { my $ticket = RT::Ticket->new( RT->SystemUser ); @@ -26,8 +35,8 @@ ok( $m->login, "Logged in" ); # Test that defaults work $m->get_ok( "/Search/Chart.html?Query=id>0" ); -$m->content_like(qr{<th[^>]*>\s*Queue\s*</th>\s*<th[^>]*>\s*Tickets\s*</th>}, "Grouped by queue"); -$m->content_like(qr{General</a>\s*</td>\s*<td[^>]*>\s*7}, "Found results in table"); +$m->content_like(qr{<th[^>]*>Queue\s*</th>\s*<th[^>]*>Tickets\s*</th>}, "Grouped by queue"); +$m->content_like(qr{General</a>\s*</td>\s*<td[^>]*>\s*<a[^>]*>7</a>}, "Found results in table"); $m->content_like(qr{<img src="/Search/Chart\?}, "Found image"); $m->get_ok( "/Search/Chart?Query=id>0" ); @@ -37,8 +46,8 @@ ok( length($m->content), "Has content" ); # Group by Queue $m->get_ok( "/Search/Chart.html?Query=id>0&PrimaryGroupBy=Queue" ); -$m->content_like(qr{<th[^>]*>\s*Queue\s*</th>\s*<th[^>]*>\s*Tickets\s*</th>}, "Grouped by queue"); -$m->content_like(qr{General</a>\s*</td>\s*<td[^>]*>\s*7}, "Found results in table"); +$m->content_like(qr{<th[^>]*>Queue\s*</th>\s*<th[^>]*>Tickets\s*</th>}, "Grouped by queue"); +$m->content_like(qr{General</a>\s*</td>\s*<td[^>]*>\s*<a[^>]*>7</a>}, "Found results in table"); $m->content_like(qr{<img src="/Search/Chart\?}, "Found image"); $m->get_ok( "/Search/Chart?Query=id>0&PrimaryGroupBy=Queue" ); @@ -48,9 +57,9 @@ ok( length($m->content), "Has content" ); # Group by Requestor email $m->get_ok( "/Search/Chart.html?Query=id>0&PrimaryGroupBy=Requestor.EmailAddress" ); -$m->content_like(qr{<th[^>]*>\s*Requestor\.EmailAddress\s*</th>\s*<th[^>]*>\s*Tickets\s*</th>}, +$m->content_like(qr{<th[^>]*>Requestor\.EmailAddress\s*</th>\s*<th[^>]*>Tickets\s*</th>}, "Grouped by requestor"); -$m->content_like(qr{root0\@localhost</a>\s*</td>\s*<td[^>]*>\s*3}, "Found results in table"); +$m->content_like(qr{root0\@localhost</a>\s*</td>\s*<td[^>]*>\s*<a[^>]*>3</a>}, "Found results in table"); $m->content_like(qr{<img src="/Search/Chart\?}, "Found image"); $m->get_ok( "/Search/Chart?Query=id>0&PrimaryGroupBy=Requestor.Email" ); @@ -60,7 +69,7 @@ ok( length($m->content), "Has content" ); # Group by Requestor phone -- which is bogus, and falls back to queue $m->get_ok( "/Search/Chart.html?Query=id>0&PrimaryGroupBy=Requestor.Phone" ); -$m->content_like(qr{General</a>\s*</td>\s*<td[^>]*>\s*7}, +$m->content_like(qr{General</a>\s*</td>\s*<td[^>]*>\s*<a[^>]*>7</a>}, "Found queue results in table, as a default"); $m->content_like(qr{<img src="/Search/Chart\?}, "Found image"); diff --git a/rt/t/web/class_create.t b/rt/t/web/class_create.t new file mode 100644 index 000000000..cec41a8aa --- /dev/null +++ b/rt/t/web/class_create.t @@ -0,0 +1,75 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use RT::Test tests => 13; + +my ( $baseurl, $m ) = RT::Test->started_ok; +ok $m->login, 'logged in as root'; +my $root = RT::User->new(RT->SystemUser); +ok( $root->Load('root'), 'load root user' ); + +my $class_name = 'test class'; + +my $class_id; +diag "Create a class"; +{ + $m->follow_link( id => 'tools-config-articles-classes-create'); + + # Test class form validation + $m->submit_form( + form_name => 'ModifyClass', + fields => { + Name => '', + }, + ); + $m->text_contains('Invalid value for Name'); + $m->submit_form( + form_name => 'ModifyClass', + fields => { + Name => '0', + }, + ); + $m->text_contains('Invalid value for Name'); + $m->submit_form( + form_name => 'ModifyClass', + fields => { + Name => '1', + }, + ); + $m->text_contains('Invalid value for Name'); + $m->submit_form( + form_name => 'ModifyClass', + fields => { + Name => $class_name, + }, + ); + $m->content_contains('Object created', 'created class sucessfully' ); + + # Test validation on updae + $m->form_name('ModifyClass'); + $m->set_fields( + Name => '', + ); + $m->click_button(value => 'Save Changes'); + $m->text_contains('Illegal value for Name'); + + $m->form_name('ModifyClass'); + $m->set_fields( + Name => '0', + ); + $m->click_button(value => 'Save Changes'); + $m->text_contains('Illegal value for Name'); + + $m->form_name('ModifyClass'); + $m->set_fields( + Name => '1', + ); + $m->click_button(value => 'Save Changes'); + $m->text_contains('Illegal value for Name'); + + $class_id = $m->form_name('ModifyClass')->value('id'); + ok $class_id, "found id of the class in the form, it's #$class_id"; +} + diff --git a/rt/t/web/clickjacking-preventions.t b/rt/t/web/clickjacking-preventions.t new file mode 100644 index 000000000..dde82952b --- /dev/null +++ b/rt/t/web/clickjacking-preventions.t @@ -0,0 +1,30 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +use RT::Test tests => 11; + +my ($url, $m); + +# Enabled by default +{ + ok(RT->Config->Get('Framebusting'), "Framebusting enabled by default"); + + ($url, $m) = RT::Test->started_ok; + $m->get_ok($url); + $m->content_contains('if (window.top !== window.self) {', "Found the framekiller javascript"); + is $m->response->header('X-Frame-Options'), 'DENY', "X-Frame-Options is set to DENY"; + + RT::Test->stop_server; +} + +# Disabled +{ + RT->Config->Set('Framebusting', 0); + + ($url, $m) = RT::Test->started_ok; + $m->get_ok($url); + $m->content_lacks('if (window.top !== window.self) {', "Didn't find the framekiller javascript"); + is $m->response->header('X-Frame-Options'), undef, "X-Frame-Options is not present"; +} + diff --git a/rt/t/web/command_line.t b/rt/t/web/command_line.t index 884b064e6..1fed8e69e 100644 --- a/rt/t/web/command_line.t +++ b/rt/t/web/command_line.t @@ -3,7 +3,7 @@ use strict; use File::Spec (); use Test::Expect; -use RT::Test tests => 295; +use RT::Test tests => 303, actual_server => 1; my ($baseurl, $m) = RT::Test->started_ok; use RT::User; @@ -11,7 +11,6 @@ use RT::Queue; my $rt_tool_path = "$RT::BinPath/rt"; -# {{{ test configuration options # config directives: # (in $CWD/.rtrc) @@ -38,14 +37,13 @@ $ENV{'RTSERVER'} =RT->Config->Get('WebBaseURL') ; $ENV{'RTDEBUG'} = '1'; # - RTCONFIG Specifies a name other than ".rtrc" for the # configuration file. +$ENV{'RTCONFIG'} = '/dev/null'; # # - RTQUERY Default RT Query for rt list # - RTORDERBY Default order for rt list -# }}} -# {{{ test ticket manipulation # create a ticket expect_run( @@ -54,6 +52,7 @@ expect_run( quit => 'quit', ); expect_send(q{create -t ticket set subject='new ticket' add cc=foo@example.com}, "Creating a ticket..."); + expect_like(qr/Ticket \d+ created/, "Created the ticket"); expect_handle->before() =~ /Ticket (\d+) created/; my $ticket_id = $1; @@ -65,7 +64,6 @@ expect_like(qr/Ticket \d+ created/, "Created the ticket"); expect_send(q{rt create -t ticket set subject='rt ticket'}, "Creating a ticket with 'rt create'..."); expect_like(qr/Ticket \d+ created/, "Created the ticket"); -# {{{ test queue manipulation # creating queues expect_send("create -t queue set Name='NewQueue$$'", 'Creating a queue...'); @@ -85,19 +83,18 @@ TODO: { expect_like(qr/$queue_id: EditedQueue$$/, 'Found the queue'); } -# }}} # Set up a custom field for editing tests -my $cf = RT::CustomField->new($RT::SystemUser); +my $cf = RT::CustomField->new(RT->SystemUser); my ($val,$msg) = $cf->Create(Name => 'MyCF'.$$, Type => 'FreeformSingle', Queue => $queue_id); ok($val,$msg); -my $othercf = RT::CustomField->new($RT::SystemUser); +my $othercf = RT::CustomField->new(RT->SystemUser); ($val,$msg) = $othercf->Create(Name => 'My CF'.$$, Type => 'FreeformSingle', Queue => $queue_id); ok($val,$msg); -my $multiple_cf = RT::CustomField->new($RT::SystemUser); +my $multiple_cf = RT::CustomField->new(RT->SystemUser); ($val,$msg) = $multiple_cf->Create(Name => 'MultipleCF'.$$, Type => 'FreeformMultiple', Queue => $queue_id); ok($val,$msg); @@ -118,7 +115,7 @@ ok($val,$msg); # text attachment check_attachment($test_email); # binary attachment - check_attachment($RT::MasonComponentRoot.'/NoAuth/images/bplogo.gif'); + check_attachment($RT::MasonComponentRoot.'/NoAuth/images/bpslogo.png'); # change a ticket's Owner expect_send("edit ticket/$ticket_id set owner=root", 'Changing owner...'); @@ -130,6 +127,11 @@ expect_send("edit ticket/$ticket_id set requestors=foo\@example.com", 'Changing expect_like(qr/Ticket $ticket_id updated/, 'Changed Requestor'); expect_send("show ticket/$ticket_id -f requestors", 'Verifying change...'); expect_like(qr/Requestors: foo\@example.com/, 'Verified change'); +# set multiple Requestors +expect_send("edit ticket/$ticket_id set requestors=foo\@example.com,bar\@example.com", 'Changing Requestor...'); +expect_like(qr/Ticket $ticket_id updated/, 'Changed Requestor'); +expect_send("show ticket/$ticket_id -f requestors", 'Verifying change...'); +expect_like(qr/Requestors: bar\@example.com, foo\@example.com/, 'Verified change'); # change a ticket's Cc expect_send("edit ticket/$ticket_id set cc=bar\@example.com", 'Changing Cc...'); expect_like(qr/Ticket $ticket_id updated/, 'Changed Cc'); @@ -269,17 +271,19 @@ expect_send("show ticket/$ticket_id -f status", 'Verifying change...'); expect_like(qr/Status: resolved/, 'Verified change'); # try to set status to an illegal value expect_send("edit ticket/$ticket_id set status=quux", 'Changing status to an illegal value...'); -expect_like(qr/illegal value/i, 'Errored out'); +expect_like(qr/isn't a valid status/i, 'Errored out'); expect_send("show ticket/$ticket_id -f status", 'Verifying lack of change...'); expect_like(qr/Status: resolved/, 'Verified change'); -# }}} -# {{{ display # show ticket list expect_send("ls -s -t ticket -o +id \"Status='resolved'\"", 'Listing resolved tickets...'); expect_like(qr/$ticket_id: new ticket/, 'Found our ticket'); + +expect_send("ls -s -t ticket -f Requestors $ticket_id", 'getting Requestors'); +expect_like(qr/$ticket_id\s+bar\@example.com,\s+foo\@example.com/, 'got Requestors'); + # show ticket list verbosely expect_send("ls -l -t ticket -o +id \"Status='resolved'\"", 'Listing resolved tickets verbosely...'); expect_like(qr/id: ticket\/$ticket_id/, 'Found our ticket'); @@ -307,9 +311,7 @@ ok($attachment_id, "Got attachment id=$attachment_id $attachment_type"); expect_send("show -s ticket/$ticket_id/attachments/$attachment_id", "Showing attachment $attachment_id..."); expect_like(qr/ContentType: $attachment_type/, 'Got the attachment'); -# }}} -# {{{ test user manipulation # creating users expect_send("create -t user set Name='NewUser$$' EmailAddress='fbar$$\@example.com'", 'Creating a user...'); @@ -329,9 +331,7 @@ TODO: { expect_like(qr/$user_id: EditedUser$$/, 'Found the user'); } -# }}} -# {{{ test group manipulation TODO: { todo_skip "Group manipulation doesn't work right now", 8; @@ -354,11 +354,9 @@ TODO: { } } -# }}} TODO: { todo_skip "Custom field manipulation not yet implemented", 8; -# {{{ test custom field manipulation # creating custom fields expect_send("create -t custom_field set Name='NewCF$$'", 'Creating a custom field...'); @@ -379,9 +377,7 @@ TODO: { } } -# }}} -# {{{ test merging tickets expect_send("create -t ticket set subject='CLIMergeTest1-$$'", 'Creating first ticket to merge...'); expect_like(qr/Ticket \d+ created/, 'Created first ticket'); expect_handle->before() =~ /Ticket (\d+) created/; @@ -395,30 +391,23 @@ ok($merge_ticket_B, "Got second ticket to merge id=$merge_ticket_B"); expect_send("merge $merge_ticket_B $merge_ticket_A", 'Merging the tickets...'); expect_like(qr/Merge completed/, 'Merged the tickets'); -TODO: { - local $TODO = "we generate a spurious warning here"; - $m->no_warnings_ok; -} - expect_send("show ticket/$merge_ticket_A/history", 'Checking merge on first ticket'); expect_like(qr/Merged into ticket #$merge_ticket_A by root/, 'Merge recorded in first ticket'); expect_send("show ticket/$merge_ticket_B/history", 'Checking merge on second ticket'); expect_like(qr/Merged into ticket #$merge_ticket_A by root/, 'Merge recorded in second ticket'); -# }}} -# {{{ test taking/stealing tickets { # create a user; give them privileges to take and steal ### TODO: implement 'grant' in the CLI tool; use that here instead. ### this breaks the abstraction barrier, like, a lot. - my $steal_user = RT::User->new($RT::SystemUser); + my $steal_user = RT::User->new(RT->SystemUser); my ($steal_user_id, $msg) = $steal_user->Create( Name => "fooser$$", EmailAddress => "fooser$$\@localhost", Privileged => 1, Password => 'foobar', ); ok($steal_user_id, "Created the user? $msg"); - my $steal_queue = RT::Queue->new($RT::SystemUser); + my $steal_queue = RT::Queue->new(RT->SystemUser); my $steal_queue_id; ($steal_queue_id, $msg) = $steal_queue->Create( Name => "Steal$$" ); ok($steal_queue_id, "Got the queue? $msg"); @@ -476,9 +465,7 @@ expect_like(qr/Merged into ticket #$merge_ticket_A by root/, 'Merge recorded in expect_send("steal $steal_ticket_id", 'root steals the ticket back...'); expect_like(qr/Owner changed from fooser$$ to root/, '...and succeeds.'); } -# }}} -# {{{ test ticket linking my @link_relns = ( 'DependsOn', 'DependedOnBy', 'RefersTo', 'ReferredToBy', 'MemberOf', 'HasMember', ); my %display_relns = map { $_ => $_ } @link_relns; @@ -502,7 +489,6 @@ expect_like(qr/Merged into ticket #$merge_ticket_A by root/, 'Merge recorded in #expect_unlike(qr/\Q$reln: \E[\w\d\.]+\Q://\E[w\d\.]+\/ticket\/$link2_id/, "Removed link $reln"); } -# }}} expect_quit(); # We need to do this ourselves, so that we quit # *before* we tear down the webserver. @@ -536,9 +522,16 @@ sub check_attachment { my $attachment_content = do { local($/); <$fh> }; close $fh; chomp $attachment_content; - expect_is($attachment_content,"Attachment contains original text"); + TODO: { + local $TODO = "Binary PNG content is getting mangled somewhere along the way" + if $attachment_path =~ /\.png$/; + expect_is($attachment_content,"Attachment contains original text"); + } } +# you may encounter warning like Use of uninitialized value $ampm +# ... in Time::ParseDate +my @warnings = grep { $_ !~ /\$ampm/ } $m->get_warnings; +is( scalar @warnings, 0, 'no extra warnings' ); - -1; +1; # needed to avoid a weird exit value from expect_quit diff --git a/rt/t/web/command_line_with_unknown_field.t b/rt/t/web/command_line_with_unknown_field.t index 9a7ec7acd..736be4d1c 100644 --- a/rt/t/web/command_line_with_unknown_field.t +++ b/rt/t/web/command_line_with_unknown_field.t @@ -3,7 +3,7 @@ use strict; use File::Spec (); use Test::Expect; -use RT::Test tests => 10; +use RT::Test tests => 14, actual_server => 1; my ($baseurl, $m) = RT::Test->started_ok; my $rt_tool_path = "$RT::BinPath/rt"; @@ -12,6 +12,7 @@ $ENV{'RTPASSWD'} = 'password'; $RT::Logger->debug("Connecting to server at ".RT->Config->Get('WebBaseURL')); $ENV{'RTSERVER'} =RT->Config->Get('WebBaseURL') ; $ENV{'RTDEBUG'} = '1'; +$ENV{'RTCONFIG'} = '/dev/null'; expect_run( command => "$rt_tool_path shell", @@ -19,6 +20,7 @@ expect_run( quit => 'quit', ); expect_send(q{create -t ticket set subject='new ticket' add cc=foo@example.com}, "Creating a ticket..."); + expect_like(qr/Ticket \d+ created/, "Created the ticket"); expect_handle->before() =~ /Ticket (\d+) created/; my $ticket_id = $1; @@ -32,3 +34,10 @@ expect_like(qr/homer: Unknown field/, 'homer is unknown field'); expect_like(qr/homer: simpson/, 'the value we set for homer is shown too'); expect_quit(); + +# you may encounter warning like Use of uninitialized value $ampm +# ... in Time::ParseDate +my @warnings = grep { $_ !~ /\$ampm/ } $m->get_warnings; +is( scalar @warnings, 0, 'no extra warnings' ); + +1; # needed to avoid a weird exit value from expect_quit diff --git a/rt/t/web/compilation_errors.t b/rt/t/web/compilation_errors.t index 36a006890..1f82ab91f 100644 --- a/rt/t/web/compilation_errors.t +++ b/rt/t/web/compilation_errors.t @@ -7,7 +7,7 @@ BEGIN { sub wanted { -f && /\.html$/ && $_ !~ /Logout.html$/ && $File::Find::dir !~ /RichText/; } - my $tests = 4; + my $tests = 8; find( sub { wanted() and $tests += 4 }, 'share/html/' ); plan tests => $tests; } @@ -28,33 +28,37 @@ $agent->cookie_jar($cookie_jar); # get the top page my $url = $agent->rt_base_url; -diag "Base URL is '$url'" if $ENV{TEST_VERBOSE}; $agent->get($url); -is ($agent->{'status'}, 200, "Loaded a page"); - -# {{{ test a login +is($agent->status, 200, "Loaded a page"); # follow the link marked "Login" $agent->login(root => 'password'); -is($agent->{'status'}, 200, "Fetched the page ok"); -like( $agent->{'content'} , qr/Logout/i, "Found a logout link"); +is($agent->status, 200, "Fetched the page ok"); +$agent->content_contains('Logout', "Found a logout link"); + +find ( sub { wanted() and test_get($agent, $File::Find::name) } , 'share/html/'); -find ( sub { wanted() and test_get($File::Find::name) } , 'share/html/'); +TODO: { + local $TODO = "we spew *lots* of undef warnings"; + $agent->no_warnings_ok; +}; sub test_get { + my $agent = shift; my $file = shift; $file =~ s#^share/html/##; - diag( "testing $url/$file" ) if $ENV{TEST_VERBOSE}; - ok ($agent->get("$url/$file", "GET $url/$file"), "Can Get $url/$file"); - is ($agent->{'status'}, 200, "Loaded $file"); -# ok( $agent->{'content'} =~ /Logout/i, "Found a logout link on $file "); - ok( $agent->{'content'} !~ /Not logged in/i, "Still logged in for $file"); - ok( $agent->{'content'} !~ /raw error/i, "Didn't get a Mason compilation error on $file"); + diag( "testing $url/$file" ); + + $agent->get_ok("$url/$file"); + is($agent->status, 200, "Loaded $file"); + $agent->content_lacks('Not logged in', "Still logged in for $file"); + $agent->content_lacks('raw error', "Didn't get a Mason compilation error on $file") or do { + if (my ($error) = $agent->content =~ /<pre>(.*?line.*?)$/s) { + diag "$file: $error"; + } + }; } -# }}} - -1; diff --git a/rt/t/web/config_tab_right.t b/rt/t/web/config_tab_right.t index 4dc9ec082..361506c10 100644 --- a/rt/t/web/config_tab_right.t +++ b/rt/t/web/config_tab_right.t @@ -2,11 +2,11 @@ use strict; use warnings; -use RT::Test tests => 8; +use RT::Test nodata => 1, tests => 10; my ($uname, $upass, $user) = ('tester', 'tester'); { - $user = RT::User->new($RT::SystemUser); + $user = RT::User->new(RT->SystemUser); my ($status, $msg) = $user->Create( Name => $uname, Password => $upass, @@ -20,7 +20,7 @@ my ($baseurl, $m) = RT::Test->started_ok; ok $m->login($uname, $upass), "logged in"; { - $m->content_unlike(qr/Configuration/, 'no configuration'); + $m->content_lacks('Configuration', 'no configuration tab'); $m->get('/Admin/'); is $m->status, 403, 'no access to /Admin/'; } @@ -33,7 +33,7 @@ RT::Test->set_rights( { $m->get('/'); - $m->content_like(qr/Configuration/, 'configuration is there'); + $m->content_contains('Configuration', 'configuration tab is there'); $m->follow_link_ok({text => 'Configuration'}); is $m->status, 200, 'user has access to /Admin/'; diff --git a/rt/t/web/crypt-gnupg.t b/rt/t/web/crypt-gnupg.t index fb28c887c..6bdefdac7 100644 --- a/rt/t/web/crypt-gnupg.t +++ b/rt/t/web/crypt-gnupg.t @@ -1,20 +1,16 @@ #!/usr/bin/perl -w use strict; -use RT::Test tests => 94; - -plan skip_all => 'GnuPG required.' - unless eval 'use GnuPG::Interface; 1'; -plan skip_all => 'gpg executable is required.' - unless RT::Test->find_executable('gpg'); - +use RT::Test::GnuPG + tests => 102, + gnupg_options => { + passphrase => 'recipient', + 'trust-model' => 'always', +}; +use Test::Warn; use RT::Action::SendEmail; -eval 'use GnuPG::Interface; 1' or plan skip_all => 'GnuPG required.'; - -RT::Test->set_mail_catcher; - RT->Config->Set( CommentAddress => 'general@example.com'); RT->Config->Set( CorrespondAddress => 'general@example.com'); RT->Config->Set( DefaultSearchResultFormat => qq{ @@ -26,23 +22,6 @@ RT->Config->Set( DefaultSearchResultFormat => qq{ 'KR-__KeyRequestors__-K', Status}); -use File::Spec (); -use Cwd; -use File::Temp qw(tempdir); -my $homedir = tempdir( CLEANUP => 1 ); - -use_ok('RT::Crypt::GnuPG'); - -RT->Config->Set( 'GnuPG', - Enable => 1, - OutgoingMessagesFormat => 'RFC' ); - -RT->Config->Set( 'GnuPGOptions', - homedir => $homedir, - passphrase => 'recipient', - 'no-permission-warning' => undef, - 'trust-model' => 'always'); -RT->Config->Set( 'MailPlugins' => 'Auth::MailFrom', 'Auth::GnuPG' ); RT::Test->import_gnupg_key('recipient@example.com', 'public'); RT::Test->import_gnupg_key('recipient@example.com', 'secret'); @@ -51,7 +30,7 @@ RT::Test->import_gnupg_key('general@example.com', 'secret'); RT::Test->import_gnupg_key('general@example.com.2', 'public'); RT::Test->import_gnupg_key('general@example.com.2', 'secret'); -ok(my $user = RT::User->new($RT::SystemUser)); +ok(my $user = RT::User->new(RT->SystemUser)); ok($user->Load('root'), "Loaded user 'root'"); $user->SetEmailAddress('recipient@example.com'); @@ -62,11 +41,6 @@ my $queue = RT::Test->load_or_create_queue( ok $queue && $queue->id, 'loaded or created queue'; my $qid = $queue->id; -RT::Test->set_rights( - Principal => 'Everyone', - Right => ['CreateTicket', 'ShowTicket', 'SeeQueue', 'ModifyTicket'], -); - my ($baseurl, $m) = RT::Test->started_ok; ok $m->login, 'logged in'; @@ -113,7 +87,7 @@ MAIL is ($status >> 8, 0, "The mail gateway exited normally"); ok ($id, "got id of a newly created ticket - $id"); - my $tick = RT::Ticket->new( $RT::SystemUser ); + my $tick = RT::Ticket->new( RT->SystemUser ); $tick->Load( $id ); ok ($tick->id, "loaded ticket #$id"); @@ -181,7 +155,7 @@ MAIL is ($status >> 8, 0, "The mail gateway exited normally"); ok ($id, "got id of a newly created ticket - $id"); - my $tick = RT::Ticket->new( $RT::SystemUser ); + my $tick = RT::Ticket->new( RT->SystemUser ); $tick->Load( $id ); ok ($tick->id, "loaded ticket #$id"); @@ -253,7 +227,7 @@ MAIL is ($status >> 8, 0, "The mail gateway exited normally"); ok ($id, "got id of a newly created ticket - $id"); - my $tick = RT::Ticket->new( $RT::SystemUser ); + my $tick = RT::Ticket->new( RT->SystemUser ); $tick->Load( $id ); ok ($tick->id, "loaded ticket #$id"); @@ -319,7 +293,7 @@ MAIL is ($status >> 8, 0, "The mail gateway exited normally"); ok ($id, "got id of a newly created ticket - $id"); - my $tick = RT::Ticket->new( $RT::SystemUser ); + my $tick = RT::Ticket->new( RT->SystemUser ); $tick->Load( $id ); ok ($tick->id, "loaded ticket #$id"); @@ -361,12 +335,12 @@ my $nokey = RT::Test->load_or_create_user(Name => 'nokey', EmailAddress => 'noke $nokey->PrincipalObj->GrantRight(Right => 'CreateTicket'); $nokey->PrincipalObj->GrantRight(Right => 'OwnTicket'); -my $tick = RT::Ticket->new( $RT::SystemUser ); +my $tick = RT::Ticket->new( RT->SystemUser ); $tick->Create(Subject => 'owner lacks pubkey', Queue => 'general', Owner => $nokey); ok(my $id = $tick->id, 'created ticket for owner-without-pubkey'); -$tick = RT::Ticket->new( $RT::SystemUser ); +$tick = RT::Ticket->new( RT->SystemUser ); $tick->Create(Subject => 'owner has pubkey', Queue => 'general', Owner => 'root'); ok($id = $tick->id, 'created ticket for owner-with-pubkey'); @@ -379,11 +353,18 @@ To: general\@example.com hello MAIL -((my $status), $id) = RT::Test->send_via_mailgate($mail); +my $status; +warning_like { + ($status, $id) = RT::Test->send_via_mailgate($mail); +} [ + qr/nokey\@example.com: skipped: public key not found/, + qr/Recipient 'nokey\@example.com' is unusable/, +]; + is ($status >> 8, 0, "The mail gateway exited normally"); ok ($id, "got id of a newly created ticket - $id"); -$tick = RT::Ticket->new( $RT::SystemUser ); +$tick = RT::Ticket->new( RT->SystemUser ); $tick->Load( $id ); ok ($tick->id, "loaded ticket #$id"); @@ -396,7 +377,7 @@ is ($tick->Subject, my $key1 = "EC1E81E7DC3DB42788FB0E4E9FA662C06DE22FC2"; my $key2 = "75E156271DCCF02DDD4A7A8CDF651FA0632C4F50"; -ok($user = RT::User->new($RT::SystemUser)); +ok($user = RT::User->new(RT->SystemUser)); ok($user->Load('root'), "Loaded user 'root'"); is($user->PreferredKey, $key1, "preferred key is set correctly"); $m->get("$baseurl/Prefs/Other.html"); @@ -407,11 +388,11 @@ like($m->content, qr/$key1/, "first key shows up in preferences"); like($m->content, qr/$key2/, "second key shows up in preferences"); like($m->content, qr/$key1.*?$key2/s, "first key shows up before the second"); -$m->form_number(3); +$m->form_name('ModifyPreferences'); $m->select("PreferredKey" => $key2); $m->submit; -ok($user = RT::User->new($RT::SystemUser)); +ok($user = RT::User->new(RT->SystemUser)); ok($user->Load('root'), "Loaded user 'root'"); is($user->PreferredKey, $key2, "preferred key is set correctly to the new value"); @@ -423,6 +404,8 @@ like($m->content, qr/$key2/, "second key shows up in preferences"); like($m->content, qr/$key1/, "first key shows up in preferences"); like($m->content, qr/$key2.*?$key1/s, "second key (now preferred) shows up before the first"); +$m->no_warnings_ok; + # test that the new fields work $m->get("$baseurl/Search/Simple.html?q=General"); my $content = $m->content; @@ -441,6 +424,10 @@ like($content, qr/KO-nokey \(no pubkey!\)-K/, "KeyOwnerName issues no-pubkey war like($content, qr/KO-Nobody \(no pubkey!\)-K/, "KeyOwnerName issues no-pubkey warning for nobody"); like($content, qr/KR-recipient\@example.com-K/, "KeyRequestors does not issue no-pubkey warning for recipient\@example.com"); + like($content, qr/KR-general\@example.com-K/, "KeyRequestors does not issue no-pubkey warning for general\@example.com"); like($content, qr/KR-nokey\@example.com \(no pubkey!\)-K/, "KeyRequestors DOES issue no-pubkey warning for nokey\@example.com"); +$m->next_warning_like(qr/public key not found/); +$m->next_warning_like(qr/public key not found/); +$m->no_leftover_warnings_ok; diff --git a/rt/t/web/custom_frontpage.t b/rt/t/web/custom_frontpage.t index 79ea56629..43c5f6e33 100644 --- a/rt/t/web/custom_frontpage.t +++ b/rt/t/web/custom_frontpage.t @@ -1,12 +1,12 @@ #!/usr/bin/perl -w use strict; -use RT::Test tests => 7; +use RT::Test tests => 12; my ($baseurl, $m) = RT::Test->started_ok; my $url = $m->rt_base_url; -my $user_obj = RT::User->new($RT::SystemUser); +my $user_obj = RT::User->new(RT->SystemUser); my ($ret, $msg) = $user_obj->LoadOrCreateByEmail('customer@example.com'); ok($ret, 'ACL test user creation'); $user_obj->SetName('customer'); @@ -29,9 +29,9 @@ $m->field ( "SavedSearchDescription" => 'stupid tickets'); $m->click_button (name => 'SavedSearchSave'); $m->get ( $url.'Prefs/MyRT.html' ); -$m->content_like (qr/stupid tickets/, 'saved search listed in rt at a glance items'); +$m->content_contains('stupid tickets', 'saved search listed in rt at a glance items'); -ok $m->login, 'we did log in as root'; +ok $m->login('root', 'password', logout => 1), 'we did log in as root'; $m->get ( $url.'Prefs/MyRT.html' ); $m->form_name ('SelectionBox-body'); @@ -58,4 +58,33 @@ $m->click_button (name => 'movedown'); $m->form_name ('SelectionBox-body'); #$m->click_button (name => 'body-Save'); $m->get ( $url ); -$m->content_like (qr'highest priority tickets', 'adds them back'); +$m->content_contains('highest priority tickets', 'adds them back'); + + +#create a saved search with special chars +$m->get( $url . "Search/Build.html" ); +$m->form_name('BuildQuery'); +$m->field( "ValueOfAttachment" => 'stupid' ); +$m->field( "SavedSearchDescription" => 'special chars [test] [_1] ~[_1~]' ); +$m->click_button( name => 'SavedSearchSave' ); +my ($name) = $m->content =~ /value="(RT::User-\d+-SavedSearch-\d+)"/; +ok( $name, 'saved search name' ); +$m->get( $url . 'Prefs/MyRT.html' ); +$m->content_contains( 'special chars [test] [_1] ~[_1~]', + 'saved search listed in rt at a glance items' ); + +$m->get( $url . 'Prefs/MyRT.html' ); +$m->form_name('SelectionBox-body'); +$m->field( + 'body-Available' => [ + 'component-QuickCreate', + 'system-Unowned Tickets', + 'system-My Tickets', + 'saved-' . $name, + ] +); +$m->click_button( name => 'add' ); + +$m->get($url); +$m->content_like( qr/special chars \[test\] \d+ \[_1\]/, + 'special chars in titlebox' ); diff --git a/rt/t/web/custom_search.t b/rt/t/web/custom_search.t index 05cfdab60..f8fde2500 100644 --- a/rt/t/web/custom_search.t +++ b/rt/t/web/custom_search.t @@ -1,7 +1,7 @@ #!/usr/bin/perl -w use strict; -use RT::Test tests => 11; +use RT::Test tests => 13; my ($baseurl, $m) = RT::Test->started_ok; my $url = $m->rt_base_url; @@ -9,7 +9,7 @@ my $url = $m->rt_base_url; -my $t = RT::Ticket->new($RT::SystemUser); +my $t = RT::Ticket->new(RT->SystemUser); $t->Create(Subject => 'for custom search'.$$, Queue => 'general', Owner => 'root', Requestor => 'customsearch@localhost'); ok(my $id = $t->id, 'created ticket for custom search'); @@ -24,7 +24,7 @@ $m->get ( $url.'Prefs/MyRT.html' ); my $cus_hp = $m->find_link( text => "My Tickets" ); my $cus_qs = $m->find_link( text => "Quick search" ); $m->get ($cus_hp); -$m->content_like (qr'highest priority tickets'); +$m->content_contains('highest priority tickets'); # add Requestor to the fields $m->form_name ('BuildQuery'); diff --git a/rt/t/web/dashboards-basics.t b/rt/t/web/dashboards-basics.t new file mode 100644 index 000000000..1d56da5be --- /dev/null +++ b/rt/t/web/dashboards-basics.t @@ -0,0 +1,268 @@ +#!/usr/bin/perl -w +use strict; + +use RT::Test tests => 122; +my ($baseurl, $m) = RT::Test->started_ok; + +my $url = $m->rt_base_url; + +my $user_obj = RT::User->new(RT->SystemUser); +my ($ret, $msg) = $user_obj->LoadOrCreateByEmail('customer@example.com'); +ok($ret, 'ACL test user creation'); +$user_obj->SetName('customer'); +$user_obj->SetPrivileged(1); +($ret, $msg) = $user_obj->SetPassword('customer'); +$user_obj->PrincipalObj->GrantRight(Right => 'ModifySelf'); +my $currentuser = RT::CurrentUser->new($user_obj); + +my $onlooker = RT::User->new(RT->SystemUser); +($ret, $msg) = $onlooker->LoadOrCreateByEmail('onlooker@example.com'); +ok($ret, 'ACL test user creation'); +$onlooker->SetName('onlooker'); +$onlooker->SetPrivileged(1); +($ret, $msg) = $onlooker->SetPassword('onlooker'); + +my $queue = RT::Queue->new(RT->SystemUser); +$queue->Create(Name => 'SearchQueue'.$$); + +for my $user ($user_obj, $onlooker) { + $user->PrincipalObj->GrantRight(Right => 'ModifySelf'); + for my $right (qw/SeeQueue ShowTicket OwnTicket/) { + $user->PrincipalObj->GrantRight(Right => $right, Object => $queue); + } +} + +ok $m->login(customer => 'customer'), "logged in"; + +$m->get_ok($url."Dashboards/index.html"); +$m->content_lacks('<a href="/Dashboards/Modify.html?Create=1">New</a>', + "No 'new dashboard' link because we have no CreateOwnDashboard"); + +$m->no_warnings_ok; + +$m->get_ok($url."Dashboards/Modify.html?Create=1"); +$m->content_contains("Permission denied"); +$m->content_lacks("Save Changes"); + +$m->warning_like(qr/Permission denied/, "got a permission denied warning"); + +$user_obj->PrincipalObj->GrantRight(Right => 'ModifyOwnDashboard', Object => $RT::System); + +# Modify itself is no longer good enough, you need Create +$m->get_ok($url."Dashboards/Modify.html?Create=1"); +$m->content_contains("Permission denied"); +$m->content_lacks("Save Changes"); + +$m->warning_like(qr/Permission denied/, "got a permission denied warning"); + +$user_obj->PrincipalObj->GrantRight(Right => 'CreateOwnDashboard', Object => $RT::System); + +$m->get_ok($url."Dashboards/Modify.html?Create=1"); +$m->content_lacks("Permission denied"); +$m->content_contains("Create"); + +$m->get_ok($url."Dashboards/index.html"); +$m->content_contains("New", "'New' link because we now have ModifyOwnDashboard"); +$m->follow_link_ok({ id => 'home-dashboard_create'}); +$m->form_name('ModifyDashboard'); +$m->field("Name" => 'different dashboard'); +$m->content_lacks('Delete', "Delete button hidden because we are creating"); +$m->click_button(value => 'Create'); +$m->content_contains("Saved dashboard different dashboard"); +$user_obj->PrincipalObj->GrantRight(Right => 'SeeOwnDashboard', Object => $RT::System); +$m->get($url."Dashboards/index.html"); +$m->follow_link_ok({ text => 'different dashboard'}); +$m->content_lacks("Permission denied", "we now have SeeOwnDashboard"); +$m->content_lacks('Delete', "Delete button hidden because we lack DeleteOwnDashboard"); + +$m->get_ok($url."Dashboards/index.html"); +$m->content_contains("different dashboard", "we now have SeeOwnDashboard"); +$m->content_lacks("Permission denied"); + +$m->follow_link_ok({text => "different dashboard"}); +$m->content_contains("Basics"); +$m->content_contains("Content"); +$m->content_lacks("Subscription", "we don't have the SubscribeDashboard right"); + +$m->follow_link_ok({text => "Basics"}); +$m->content_contains("Modify the dashboard different dashboard"); + +$m->follow_link_ok({text => "Content"}); +$m->content_contains("Modify the content of dashboard different dashboard"); +my $form = $m->form_name('Dashboard-Searches-body'); +my @input = $form->find_input('Searches-body-Available'); +my ($unowned) = + map { ( $_->possible_values )[1] } + grep { ( $_->value_names )[1] =~ /Saved Search: Unowned Tickets/ } @input; +$form->value('Searches-body-Available' => $unowned ); +$m->click_button(name => 'add'); +$m->content_contains("Dashboard updated"); + +my $dashboard = RT::Dashboard->new($currentuser); +my ($id) = $m->content =~ /name="id" value="(\d+)"/; +ok($id, "got an ID, $id"); +$dashboard->LoadById($id); +is($dashboard->Name, "different dashboard"); + +is($dashboard->Privacy, 'RT::User-' . $user_obj->Id, "correct privacy"); +is($dashboard->PossibleHiddenSearches, 0, "all searches are visible"); + +my @searches = $dashboard->Searches; +is(@searches, 1, "one saved search in the dashboard"); +like($searches[0]->Name, qr/newest unowned tickets/, "correct search name"); + +$form = $m->form_name('Dashboard-Searches-body'); +@input = $form->find_input('Searches-body-Available'); +my ($my_tickets) = + map { ( $_->possible_values )[1] } + grep { ( $_->value_names )[1] =~ /Saved Search: My Tickets/ } @input; +$form->value('Searches-body-Available' => $my_tickets ); +$m->click_button(name => 'add'); +$m->content_contains("Dashboard updated"); + +RT::Record->FlushCache if RT::Record->can('FlushCache'); +$dashboard = RT::Dashboard->new($currentuser); +$dashboard->LoadById($id); + +@searches = $dashboard->Searches; +is(@searches, 2, "two saved searches in the dashboard"); +like($searches[0]->Name, qr/newest unowned tickets/, "correct existing search name"); +like($searches[1]->Name, qr/highest priority tickets I own/, "correct new search name"); + +my $ticket = RT::Ticket->new(RT->SystemUser); +$ticket->Create( + Queue => $queue->Id, + Requestor => [ $user_obj->Name ], + Owner => $user_obj, + Subject => 'dashboard test', +); + +$m->follow_link_ok({id => 'page-show'}); +$m->content_contains("50 highest priority tickets I own"); +$m->content_contains("50 newest unowned tickets"); +$m->content_unlike( qr/Bookmarked Tickets.*Bookmarked Tickets/s, + 'only dashboard queries show up' ); +$m->content_contains("dashboard test", "ticket subject"); + +$m->get_ok("/Dashboards/$id/This fragment left intentionally blank"); +$m->content_contains("50 highest priority tickets I own"); +$m->content_contains("50 newest unowned tickets"); +$m->content_unlike( qr/Bookmarked Tickets.*Bookmarked Tickets/s, + 'only dashboard queries show up' ); +$m->content_contains("dashboard test", "ticket subject"); + +$m->get_ok("/Dashboards/Subscription.html?id=$id"); +$m->form_name('SubscribeDashboard'); +$m->click_button(name => 'Save'); +$m->content_contains("Permission denied"); +$m->warning_like(qr/Unable to subscribe to dashboard.*Permission denied/, "got a permission denied warning when trying to subscribe to a dashboard"); + +$user_obj->Attributes->RedoSearch; +is($user_obj->Attributes->Named('Subscription'), 0, "no subscriptions"); + +$user_obj->PrincipalObj->GrantRight(Right => 'SubscribeDashboard', Object => $RT::System); + +$m->get_ok("/Dashboards/Modify.html?id=$id"); +$m->follow_link_ok({text => "Subscription"}); +$m->content_contains("Subscribe to dashboard different dashboard"); +$m->content_contains("Unowned Tickets"); +$m->content_contains("My Tickets"); +$m->content_unlike( qr/Bookmarked Tickets.*Bookmarked Tickets/s, + 'only dashboard queries show up' ); + +$m->form_name('SubscribeDashboard'); +$m->click_button(name => 'Save'); +$m->content_lacks("Permission denied"); +$m->content_contains("Subscribed to dashboard different dashboard"); + +$user_obj->Attributes->RedoSearch; +is($user_obj->Attributes->Named('Subscription'), 1, "we have a subscription"); + +$m->get_ok("/Dashboards/Modify.html?id=$id"); +$m->follow_link_ok({text => "Subscription"}); +$m->content_contains("Modify the subscription to dashboard different dashboard"); + +$m->get_ok("/Dashboards/Modify.html?id=$id&Delete=1"); +$m->content_contains("Permission denied", "unable to delete dashboard because we lack DeleteOwnDashboard"); + +$m->warning_like(qr/Couldn't delete dashboard.*Permission denied/, "got a permission denied warning when trying to delete the dashboard"); + +$user_obj->PrincipalObj->GrantRight(Right => 'DeleteOwnDashboard', Object => $RT::System); + +$m->get_ok("/Dashboards/Modify.html?id=$id"); +$m->content_contains('Delete', "Delete button shows because we have DeleteOwnDashboard"); + +$m->form_name('ModifyDashboard'); +$m->click_button(name => 'Delete'); +$m->content_contains("Deleted dashboard"); + +$m->get("/Dashboards/Modify.html?id=$id"); +$m->content_lacks("different dashboard", "dashboard was deleted"); +$m->content_contains("Failed to load dashboard $id"); + +$m->warning_like(qr/Failed to load dashboard.*Couldn't find row/, "the dashboard was deleted"); + +$user_obj->PrincipalObj->GrantRight(Right => "SuperUser", Object => $RT::System); + +# now test that we warn about searches others can't see +# first create a personal saved search... +$m->get_ok($url."Search/Build.html"); +$m->follow_link_ok({text => 'Advanced'}); +$m->form_with_fields('Query'); +$m->field(Query => "id > 0"); +$m->submit; + +$m->form_with_fields('SavedSearchDescription'); +$m->field(SavedSearchDescription => "personal search"); +$m->click_button(name => "SavedSearchSave"); + +# then the system-wide dashboard +$m->get_ok($url."Dashboards/Modify.html?Create=1"); + +$m->form_name('ModifyDashboard'); +$m->field("Name" => 'system dashboard'); +$m->field("Privacy" => 'RT::System-1'); +$m->content_lacks('Delete', "Delete button hidden because we are creating"); +$m->click_button(value => 'Create'); +$m->content_lacks("No permission to create dashboards"); +$m->content_contains("Saved dashboard system dashboard"); + +$m->follow_link_ok({id => 'page-content'}); + +$form = $m->form_name('Dashboard-Searches-body'); +@input = $form->find_input('Searches-body-Available'); +my ($personal) = + map { ( $_->possible_values )[1] } + grep { ( $_->value_names )[1] =~ /Saved Search: personal search/ } @input; +$form->value('Searches-body-Available' => $personal ); +$m->click_button(name => 'add'); +$m->content_contains("Dashboard updated"); + +$m->content_contains("The following queries may not be visible to all users who can see this dashboard."); + +$m->follow_link_ok({id => 'page-show'}); +$m->content_contains("personal search", "saved search shows up"); +$m->content_contains("dashboard test", "matched ticket shows up"); + +# make sure the onlooker can't see the search... +$onlooker->PrincipalObj->GrantRight(Right => 'SeeDashboard', Object => $RT::System); + +my $omech = RT::Test::Web->new; +ok $omech->login(onlooker => 'onlooker'), "logged in"; +$omech->get_ok("/Dashboards"); + +$omech->follow_link_ok({text => 'system dashboard'}); +$omech->content_lacks("personal search", "saved search doesn't show up"); +$omech->content_lacks("dashboard test", "matched ticket doesn't show up"); + +$omech->warning_like(qr/User .* tried to load container user /, "can't see other users' personal searches"); + +# make sure that navigating to dashboard pages with bad IDs throws an error +my ($bad_id) = $personal =~ /^search-(\d+)/; + +for my $page (qw/Modify Queries Render Subscription/) { + $m->get("/Dashboards/$page.html?id=$bad_id"); + $m->content_like(qr/Couldn.+t load dashboard $bad_id: Invalid object type/); + $m->warning_like(qr/Couldn't load dashboard $bad_id: Invalid object type/); +} + diff --git a/rt/t/web/dashboards-deleted-saved-search.t b/rt/t/web/dashboards-deleted-saved-search.t new file mode 100644 index 000000000..4cd7fea1f --- /dev/null +++ b/rt/t/web/dashboards-deleted-saved-search.t @@ -0,0 +1,89 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +use RT::Test tests => 20; +my ( $url, $m ) = RT::Test->started_ok; +ok( $m->login, 'logged in' ); + +# create a saved search +$m->get_ok( $url . "/Search/Build.html?Query=" . 'id=1' ); + +$m->submit_form( + form_name => 'BuildQuery', + fields => { SavedSearchDescription => 'foo', }, + button => 'SavedSearchSave', +); + +my ( $search_uri, $user_id, $search_id ) = + $m->content =~ /value="(RT::User-(\d+)-SavedSearch-(\d+))"/; +$m->submit_form( + form_name => 'BuildQuery', + fields => { SavedSearchLoad => $search_uri }, + button => 'SavedSearchSave', +); + +$m->content_like( qr/name="SavedSearchDelete"\s+value="Delete"/, + 'found Delete button' ); +$m->content_like( + qr/name="SavedSearchDescription"\s+value="foo"/, + 'found Description input with the value filled' +); + +# create a dashboard with the created search + +$m->get_ok( $url . "/Dashboards/Modify.html?Create=1" ); +$m->submit_form( + form_name => 'ModifyDashboard', + fields => { Name => 'bar' }, +); + +$m->content_contains('Saved dashboard bar', 'dashboard saved' ); +my $dashboard_queries_link = $m->find_link( text_regex => qr/Content/ ); +my ( $dashboard_id ) = $dashboard_queries_link->url =~ /id=(\d+)/; + +$m->get_ok( $url . "/Dashboards/Queries.html?id=$dashboard_id" ); + +$m->content_lacks( 'value="Update"', 'no update button' ); + +$m->submit_form( + form_name => 'Dashboard-Searches-body', + fields => + { 'Searches-body-Available' => "search-$search_id-RT::User-$user_id" }, + button => 'add', +); + +$m->content_contains('Dashboard updated', 'added search foo to dashboard bar' ); + +# delete the created search + +$m->get_ok( $url . "/Search/Build.html?Query=" . 'id=1' ); +$m->submit_form( + form_name => 'BuildQuery', + fields => { SavedSearchLoad => $search_uri }, +); +$m->submit_form( + form_name => 'BuildQuery', + button => 'SavedSearchDelete', +); + +$m->content_lacks( $search_uri, 'deleted search foo' ); + +# here is what we really want to test + +$m->get_ok( $url . "/Dashboards/Queries.html?id=$dashboard_id" ); +$m->content_contains('Deleted queries', 'found deleted message' ); + +# Update button shows so we can update the deleted search easily +$m->content_contains( 'value="Update"', 'found update button' ); + +$m->submit_form( + form_name => 'Dashboard-Searches-body', + button => 'update', +); + +$m->content_lacks('Deleted queries', 'deleted message is gone' ); +$m->content_lacks( 'value="Update"', 'update button is gone too' ); + +$m->get_warnings; # we'll get a lot of warnings because the deleted search + diff --git a/rt/t/web/dashboards-groups.t b/rt/t/web/dashboards-groups.t index cbf1d6a9f..ac2a5aca0 100644 --- a/rt/t/web/dashboards-groups.t +++ b/rt/t/web/dashboards-groups.t @@ -1,13 +1,13 @@ #!/usr/bin/perl -w use strict; -use RT::Test tests => 40; +use RT::Test nodata => 1, tests => 64; my ($baseurl, $m) = RT::Test->started_ok; my $url = $m->rt_base_url; -# create user and queue {{{ -my $user_obj = RT::User->new($RT::SystemUser); +# create user and queue +my $user_obj = RT::User->new(RT->SystemUser); my ($ok, $msg) = $user_obj->LoadOrCreateByEmail('customer@example.com'); ok($ok, 'ACL test user creation'); $user_obj->SetName('customer'); @@ -16,7 +16,7 @@ $user_obj->SetPrivileged(1); $user_obj->PrincipalObj->GrantRight(Right => 'ModifySelf'); my $currentuser = RT::CurrentUser->new($user_obj); -my $queue = RT::Queue->new($RT::SystemUser); +my $queue = RT::Queue->new(RT->SystemUser); $queue->Create(Name => 'SearchQueue'.$$); $user_obj->PrincipalObj->GrantRight(Right => $_, Object => $queue) @@ -26,13 +26,12 @@ $user_obj->PrincipalObj->GrantRight(Right => $_, Object => $queue) # are checked and not these as well $user_obj->PrincipalObj->GrantRight(Right => $_, Object => $RT::System) for qw/SubscribeDashboard CreateOwnDashboard SeeOwnDashboard ModifyOwnDashboard DeleteOwnDashboard/; -# }}} -# create and test groups (outer < inner < user) {{{ -my $inner_group = RT::Group->new($RT::SystemUser); +# create and test groups (outer < inner < user) +my $inner_group = RT::Group->new(RT->SystemUser); ($ok, $msg) = $inner_group->CreateUserDefinedGroup(Name => "inner", Description => "inner group"); ok($ok, "created inner group: $msg"); -my $outer_group = RT::Group->new($RT::SystemUser); +my $outer_group = RT::Group->new(RT->SystemUser); ($ok, $msg) = $outer_group->CreateUserDefinedGroup(Name => "outer", Description => "outer group"); ok($ok, "created outer group: $msg"); @@ -51,28 +50,36 @@ ok(!$inner_group->HasMember($outer_group->PrincipalId), "inner doesn't have oute ok($inner_group->HasMember($user_obj->PrincipalId), "inner has user"); ok(!$inner_group->HasMemberRecursively($outer_group->PrincipalId), "inner doesn't have outer, even recursively"); ok($inner_group->HasMemberRecursively($user_obj->PrincipalId), "inner has user recursively"); -# }}} ok $m->login(customer => 'customer'), "logged in"; -$m->get_ok("$url/Dashboards"); -$m->follow_link_ok({text => "New"}); +$m->follow_link_ok({ id => 'home-dashboard_create'}); $m->form_name('ModifyDashboard'); is_deeply([$m->current_form->find_input('Privacy')->possible_values], ["RT::User-" . $user_obj->Id], "the only selectable privacy is user"); $m->content_lacks('Delete', "Delete button hidden because we are creating"); $user_obj->PrincipalObj->GrantRight(Right => 'CreateGroupDashboard', Object => $inner_group); -$m->follow_link_ok({text => "New"}); +$m->follow_link_ok({ id => 'home-dashboard_create'}); $m->form_name('ModifyDashboard'); is_deeply([$m->current_form->find_input('Privacy')->possible_values], ["RT::User-" . $user_obj->Id, "RT::Group-" . $inner_group->Id], "the only selectable privacies are user and inner group (not outer group)"); -$m->field("Name" => 'inner dashboard'); +$m->field("Name" => 'broken dashboard'); $m->field("Privacy" => "RT::Group-" . $inner_group->Id); $m->content_lacks('Delete', "Delete button hidden because we are creating"); +$m->click_button(value => 'Create'); +$m->content_contains("saved", "we lack SeeGroupDashboard, so we end up back at the index."); +$user_obj->PrincipalObj->GrantRight( + Right => 'SeeGroupDashboard', + Object => $inner_group, +); +$m->follow_link_ok({ id => 'home-dashboard_create'}); +$m->form_name('ModifyDashboard'); +$m->field("Name" => 'inner dashboard'); +$m->field("Privacy" => "RT::Group-" . $inner_group->Id); $m->click_button(value => 'Create'); -$m->content_lacks("No permission to create dashboards"); +$m->content_lacks("Permission denied", "we now have SeeGroupDashboard"); $m->content_contains("Saved dashboard inner dashboard"); $m->content_lacks('Delete', "Delete button hidden because we lack DeleteDashboard"); @@ -85,18 +92,104 @@ is($dashboard->Name, "inner dashboard"); is($dashboard->Privacy, 'RT::Group-' . $inner_group->Id, "correct privacy"); is($dashboard->PossibleHiddenSearches, 0, "all searches are visible"); -$m->no_warnings_ok; - -$m->get_ok("/Dashboards/Modify.html?id=$id"); -$m->content_lacks("inner dashboard", "no SeeGroupDashboard right"); -$m->content_contains("Permission denied"); - -$m->warning_like(qr/Permission denied/, "got a permission denied warning"); -$user_obj->PrincipalObj->GrantRight(Right => 'SeeGroupDashboard', Object => $inner_group); $m->get_ok("/Dashboards/Modify.html?id=$id"); $m->content_contains("inner dashboard", "we now have SeeGroupDashboard right"); $m->content_lacks("Permission denied"); - $m->content_contains('Subscription', "Subscription link not hidden because we have SubscribeDashboard"); + +$m->get_ok("/Dashboards/index.html"); +$m->content_contains("inner dashboard", "We can see the inner dashboard from the UI"); + +$m->get_ok("/index.html"); +$m->content_contains("inner dashboard", "We can see the inner dashboard from the menu drop-down"); + +my ($group) = grep {$_->isa("RT::Group") and $_->Id == $inner_group->Id} + RT::Dashboard->new($currentuser)->_PrivacyObjects; +ok($group, "Found the group in the privacy objects list"); + +my @loading = map {ref($_)."-".$_->Id} RT::Dashboard->new($currentuser)->ObjectsForLoading; +is_deeply( + \@loading, + ["RT::User-".$user_obj->Id, "RT::Group-".$inner_group->Id], + "We can load from ourselves (SeeOwnDashboard) and a group we are with SeeGroupDashboard" +); + +# If you are granted SeeGroupDashboard globally, you can only see +# dashboards in groups you are in. +$user_obj->PrincipalObj->RevokeRight( + Right => 'SeeGroupDashboard', + Object => $inner_group, +); +$user_obj->PrincipalObj->GrantRight( + Right => 'SeeGroupDashboard', + Object => RT->System, +); +$m->get_ok("/Dashboards/index.html"); +$m->content_contains("inner dashboard", "Having SeeGroupDashboard gobally is fine for groups you are in"); +@loading = map {ref($_)."-".$_->Id} RT::Dashboard->new($currentuser)->ObjectsForLoading; +is_deeply( + \@loading, + ["RT::User-".$user_obj->Id, "RT::Group-".$inner_group->Id], + "SeeGroupDashboard globally still works for groups you are in" +); + +$inner_group->DeleteMember($user_obj->PrincipalObj->Id); +ok(!$outer_group->HasMemberRecursively($user_obj->PrincipalId), "outer no longer has user recursively"); +ok(!$inner_group->HasMemberRecursively($user_obj->PrincipalId), "inner no longer has user recursively"); +$m->get_ok("/Dashboards/index.html"); +$m->content_lacks("inner dashboard", "But global SeeGroupDashboard isn't enough for other groups"); +$m->no_warnings_ok; +@loading = map {ref($_)."-".$_->Id} RT::Dashboard->new($currentuser)->ObjectsForLoading; +is_deeply( + \@loading, + ["RT::User-".$user_obj->Id], + "We only have our SeeOwnDashboard right, as we are no longer in inner" +); + +# Similarly, if you're a SuperUser, you still only see dashboards for +# groups you belong to +$user_obj->PrincipalObj->RevokeRight( + Right => 'SeeGroupDashboard', + Object => RT->System, +); +$user_obj->PrincipalObj->GrantRight( + Right => 'SuperUser', + Object => RT->System, +); +$m->get_ok("/Dashboards/index.html"); +$m->content_lacks("inner dashboard", "Superuser can't see dashboards in groups they're not in"); +@loading = map {ref($_)."-".$_->Id} RT::Dashboard->new($currentuser)->ObjectsForLoading; +is_deeply( + \@loading, + ["RT::User-".$user_obj->Id, "RT::System-1"], + "We pick up the system-level SeeDashboard right from superuser" +); +@loading = map {ref($_)."-".$_->Id} RT::Dashboard->new($currentuser)->ObjectsForLoading(IncludeSuperuserGroups => 0); +is_deeply( + \@loading, + ["RT::User-".$user_obj->Id, "RT::System-1"], + "IncludeSuperusers only cuts out _group_ dashboard objects for loading, not user and system ones" +); + +$inner_group->AddMember($user_obj->PrincipalId); +$m->get_ok("/Dashboards/index.html"); +$m->content_contains("inner dashboard", "Superuser can see dashboards in groups they are in"); +@loading = map {ref($_)."-".$_->Id} RT::Dashboard->new($currentuser)->ObjectsForLoading; +is_deeply( + \@loading, + ["RT::User-".$user_obj->Id, "RT::Group-".$inner_group->Id, "RT::System-1"], + "Becoming a member of the group makes it a possibility" +); +@loading = map {ref($_)."-".$_->Id} RT::Dashboard->new($currentuser)->ObjectsForLoading(IncludeSuperuserGroups => 0); +is_deeply( + \@loading, + ["RT::User-".$user_obj->Id, "RT::System-1"], + "But only via superuser" +); + +$m->get_ok("/Dashboards/index.html"); +$m->content_contains("inner dashboard", "The dashboards list includes superuser rights"); +$m->get_ok("/index.html"); +$m->content_lacks("inner dashboard", "But the menu skips them"); diff --git a/rt/t/web/dashboards-permissions.t b/rt/t/web/dashboards-permissions.t index 172404289..f2e59e5cc 100644 --- a/rt/t/web/dashboards-permissions.t +++ b/rt/t/web/dashboards-permissions.t @@ -2,13 +2,13 @@ use strict; use warnings; -use RT::Test tests => 7; +use RT::Test nodata => 1, tests => 8; my ($baseurl, $m) = RT::Test->started_ok; my $url = $m->rt_base_url; # create user and queue {{{ -my $user_obj = RT::User->new($RT::SystemUser); +my $user_obj = RT::User->new(RT->SystemUser); my ($ok, $msg) = $user_obj->LoadOrCreateByEmail('customer@example.com'); ok($ok, 'ACL test user creation'); $user_obj->SetName('customer'); @@ -17,7 +17,7 @@ $user_obj->SetPrivileged(1); $user_obj->PrincipalObj->GrantRight(Right => 'ModifySelf'); my $currentuser = RT::CurrentUser->new($user_obj); -my $queue = RT::Queue->new($RT::SystemUser); +my $queue = RT::Queue->new(RT->SystemUser); $queue->Create(Name => 'SearchQueue'.$$); $user_obj->PrincipalObj->GrantRight(Right => $_, Object => $queue) @@ -25,13 +25,11 @@ $user_obj->PrincipalObj->GrantRight(Right => $_, Object => $queue) $user_obj->PrincipalObj->GrantRight(Right => $_, Object => $RT::System) for qw/SubscribeDashboard CreateOwnDashboard SeeOwnDashboard ModifyOwnDashboard DeleteOwnDashboard/; -# }}} ok $m->login(customer => 'customer'), "logged in"; -$m->get_ok("$url/Dashboards"); -$m->follow_link_ok({text => "New"}); +$m->follow_link_ok( {id => 'home-dashboard_create'}); $m->form_name('ModifyDashboard'); is_deeply([$m->current_form->find_input('Privacy')->possible_values], ["RT::User-" . $user_obj->Id], "the only selectable privacy is user"); $m->content_lacks('Delete', "Delete button hidden because we are creating"); diff --git a/rt/t/web/dashboards-search-cache.t b/rt/t/web/dashboards-search-cache.t new file mode 100644 index 000000000..ad2a96969 --- /dev/null +++ b/rt/t/web/dashboards-search-cache.t @@ -0,0 +1,73 @@ +#!/usr/bin/perl -w +use strict; + +use RT::Test tests => 20; +my ($baseurl, $m) = RT::Test->started_ok; + +my $url = $m->rt_base_url; + +ok($m->login, 'logged in'); + +# create a search +$m->follow_link_ok({text => 'Tickets'}, 'to query builder'); +$m->form_name('BuildQuery'); + +$m->field(ValueOfid => 10 ); +$m->click('AddClause'); +$m->text_contains( 'id < 10', 'added new clause'); + +$m->form_name('BuildQuery'); +$m->field(SavedSearchDescription => 'Original Name'); +$m->click('SavedSearchSave'); + +# create a dashboard +$m->get_ok("$url/Dashboards/Modify.html?Create=1"); +$m->form_name('ModifyDashboard'); +$m->field('Name' => 'cachey dashboard'); +$m->click_button(value => 'Create'); +$m->text_contains('Saved dashboard cachey dashboard'); + +my ($dashboard_id) = $m->content =~ /name="id" value="(\d+)"/; +ok($dashboard_id, "got an ID, $dashboard_id"); + +# add the search to the dashboard +$m->follow_link_ok({text => 'Content'}); +my $form = $m->form_name('Dashboard-Searches-body'); +my @input = $form->find_input('Searches-body-Available'); +my ($search) = + map { ( $_->possible_values )[1] } + grep { ( $_->value_names )[1] =~ /Saved Search: Original Name/ } @input; +$form->value('Searches-body-Available' => $search ); +$m->click_button(name => 'add'); +$m->text_contains('Dashboard updated'); + +# subscribe to the dashboard +$m->follow_link_ok({text => 'Subscription'}); +$m->text_contains('Saved Search: Original Name'); +$m->form_name('SubscribeDashboard'); +$m->click_button(name => 'Save'); +$m->text_contains('Subscribed to dashboard cachey dashboard'); + +# rename the search +$m->follow_link_ok({text => 'Tickets'}, 'to query builder'); +$form = $m->form_name('BuildQuery'); +@input = $form->find_input('SavedSearchLoad'); +($search) = + map { ( $_->possible_values )[1] } + grep { ( $_->value_names )[1] =~ /Original Name/ } @input; +$form->value('SavedSearchLoad' => $search ); +$m->click_button(value => 'Load'); +$m->text_contains('Loaded saved search "Original Name"'); + +$m->form_name('BuildQuery'); +$m->field('SavedSearchDescription' => 'New Name'); +$m->click_button(value => 'Update'); +$m->text_contains('Updated saved search "New Name"'); + +# check subscription page again +$m->get_ok("/Dashboards/Subscription.html?id=$dashboard_id"); +TODO: { + local $TODO = 'we cache search names too aggressively'; + $m->text_contains('Saved Search: New Name'); + $m->text_unlike(qr/Saved Search: Original Name/); # t-w-m lacks text_lacks +} diff --git a/rt/t/web/gnupg-headers.t b/rt/t/web/gnupg-headers.t new file mode 100644 index 000000000..88b3ab9c2 --- /dev/null +++ b/rt/t/web/gnupg-headers.t @@ -0,0 +1,53 @@ +#!/usr/bin/perl -w +use strict; + +use RT::Test::GnuPG + tests => 15, + gnupg_options => { + passphrase => 'recipient', + 'trust-model' => 'always', + }; + +RT::Test->import_gnupg_key( 'recipient@example.com', 'public' ); +RT::Test->import_gnupg_key( 'general@example.com', 'secret' ); + +ok( my $user = RT::User->new( RT->SystemUser ) ); +ok( $user->Load('root'), "Loaded user 'root'" ); +$user->SetEmailAddress('recipient@example.com'); + +my $queue = RT::Test->load_or_create_queue( + Name => 'General', + CorrespondAddress => 'general@example.com', +); +ok $queue && $queue->id, 'loaded or created queue'; +my $qid = $queue->id; + +my ( $baseurl, $m ) = RT::Test->started_ok; +ok $m->login, 'logged in'; + +diag "test with Encrypt and Sign disabled"; + +$m->goto_create_ticket($queue); +$m->form_name('TicketCreate'); +$m->field( 'Subject', 'Signing test' ); +$m->field( 'Content', 'Some other content' ); +$m->submit; +$m->content_like( qr/Ticket \d+ created/i, 'created the ticket' ); +$m->follow_link_ok( { text => 'with headers' } ); +$m->content_contains('X-RT-Encrypt: 0'); +$m->content_contains('X-RT-Sign: 0'); + +diag "test with Encrypt and Sign enabled"; + +$m->goto_create_ticket($queue); +$m->form_name('TicketCreate'); +$m->field( 'Subject', 'Signing test' ); +$m->field( 'Content', 'Some other content' ); +$m->tick( 'Encrypt', 1 ); +$m->tick( 'Sign', 1 ); +$m->submit; +$m->content_like( qr/Ticket \d+ created/i, 'created the ticket' ); +$m->follow_link_ok( { text => 'with headers' } ); +$m->content_contains('X-RT-Encrypt: 1'); +$m->content_contains('X-RT-Sign: 1'); + diff --git a/rt/t/web/gnupg-select-keys-on-create.t b/rt/t/web/gnupg-select-keys-on-create.t index deee6b291..cf27e48a7 100644 --- a/rt/t/web/gnupg-select-keys-on-create.t +++ b/rt/t/web/gnupg-select-keys-on-create.t @@ -2,34 +2,8 @@ use strict; use warnings; -use RT::Test tests => 60; - -plan skip_all => 'GnuPG required.' - unless eval 'use GnuPG::Interface; 1'; -plan skip_all => 'gpg executable is required.' - unless RT::Test->find_executable('gpg'); - - +use RT::Test::GnuPG tests => 79, gnupg_options => { passphrase => 'rt-test' }; use RT::Action::SendEmail; -use File::Temp qw(tempdir); - -RT::Test->set_mail_catcher; - -use_ok('RT::Crypt::GnuPG'); - -RT->Config->Set( GnuPG => - Enable => 1, - OutgoingMessagesFormat => 'RFC', -); - -RT->Config->Set( GnuPGOptions => - homedir => scalar tempdir( CLEANUP => 0 ), - passphrase => 'rt-test', - 'no-permission-warning' => undef, -); -diag "GnuPG --homedir ". RT->Config->Get('GnuPGOptions')->{'homedir'} if $ENV{TEST_VERBOSE}; - -RT->Config->Set( 'MailPlugins' => 'Auth::MailFrom', 'Auth::GnuPG' ); my $queue = RT::Test->load_or_create_queue( Name => 'Regression', @@ -38,28 +12,24 @@ my $queue = RT::Test->load_or_create_queue( ); ok $queue && $queue->id, 'loaded or created queue'; -RT::Test->set_rights( - Principal => 'Everyone', - Right => ['CreateTicket', 'ShowTicket', 'SeeQueue', 'ReplyToTicket', 'ModifyTicket'], -); - my ($baseurl, $m) = RT::Test->started_ok; ok $m->login, 'logged in'; -diag "check that signing doesn't work if there is no key" if $ENV{TEST_VERBOSE}; +diag "check that signing doesn't work if there is no key"; { RT::Test->clean_caught_mails; ok $m->goto_create_ticket( $queue ), "UI -> create ticket"; - $m->form_number(3); + $m->form_name('TicketCreate'); $m->tick( Sign => 1 ); $m->field( Requestors => 'rt-test@example.com' ); $m->field( Content => 'Some content' ); $m->submit; - $m->content_like( - qr/unable to sign outgoing email messages/i, + $m->content_contains( + 'unable to sign outgoing email messages', 'problems with passphrase' ); + $m->warning_like(qr/signing failed: secret key not available/); my @mail = RT::Test->fetch_caught_mails; ok !@mail, 'there are no outgoing emails'; @@ -72,33 +42,36 @@ diag "check that signing doesn't work if there is no key" if $ENV{TEST_VERBOSE}; is $res{'info'}[0]{'TrustTerse'}, 'ultimate', 'ultimately trusted key'; } -diag "check that things don't work if there is no key" if $ENV{TEST_VERBOSE}; +diag "check that things don't work if there is no key"; { RT::Test->clean_caught_mails; ok $m->goto_create_ticket( $queue ), "UI -> create ticket"; - $m->form_number(3); + $m->form_name('TicketCreate'); $m->tick( Encrypt => 1 ); $m->field( Requestors => 'rt-test@example.com' ); $m->field( Content => 'Some content' ); $m->submit; - $m->content_like( - qr/You are going to encrypt outgoing email messages/i, + $m->content_contains( + 'You are going to encrypt outgoing email messages', 'problems with keys' ); - $m->content_like( - qr/There is no key suitable for encryption/i, + $m->content_contains( + 'There is no key suitable for encryption', 'problems with keys' ); - my $form = $m->form_number(3); + my $form = $m->form_name('TicketCreate'); ok !$form->find_input( 'UseKey-rt-test@example.com' ), 'no key selector'; my @mail = RT::Test->fetch_caught_mails; ok !@mail, 'there are no outgoing emails'; + + $m->next_warning_like(qr/public key not found/) for 1 .. 4; + $m->no_leftover_warnings_ok; } -diag "import first key of rt-test\@example.com" if $ENV{TEST_VERBOSE}; +diag "import first key of rt-test\@example.com"; my $fpr1 = ''; { RT::Test->import_gnupg_key('rt-test@example.com', 'public'); @@ -107,45 +80,47 @@ my $fpr1 = ''; $fpr1 = $res{'info'}[0]{'Fingerprint'}; } -diag "check that things still doesn't work if key is not trusted" if $ENV{TEST_VERBOSE}; +diag "check that things still doesn't work if key is not trusted"; { RT::Test->clean_caught_mails; ok $m->goto_create_ticket( $queue ), "UI -> create ticket"; - $m->form_number(3); + $m->form_name('TicketCreate'); $m->tick( Encrypt => 1 ); $m->field( Requestors => 'rt-test@example.com' ); $m->field( Content => 'Some content' ); $m->submit; - $m->content_like( - qr/You are going to encrypt outgoing email messages/i, + $m->content_contains( + 'You are going to encrypt outgoing email messages', 'problems with keys' ); - $m->content_like( - qr/There is one suitable key, but trust level is not set/i, + $m->content_contains( + 'There is one suitable key, but trust level is not set', 'problems with keys' ); - my $form = $m->form_number(3); + my $form = $m->form_name('TicketCreate'); ok my $input = $form->find_input( 'UseKey-rt-test@example.com' ), 'found key selector'; is scalar $input->possible_values, 1, 'one option'; $m->select( 'UseKey-rt-test@example.com' => $fpr1 ); $m->submit; - $m->content_like( - qr/You are going to encrypt outgoing email messages/i, + $m->content_contains( + 'You are going to encrypt outgoing email messages', 'problems with keys' ); - $m->content_like( - qr/Selected key either is not trusted/i, + $m->content_contains( + 'Selected key either is not trusted', 'problems with keys' ); my @mail = RT::Test->fetch_caught_mails; ok !@mail, 'there are no outgoing emails'; + + $m->no_warnings_ok; } -diag "import a second key of rt-test\@example.com" if $ENV{TEST_VERBOSE}; +diag "import a second key of rt-test\@example.com"; my $fpr2 = ''; { RT::Test->import_gnupg_key('rt-test@example.com.2', 'public'); @@ -154,42 +129,44 @@ my $fpr2 = ''; $fpr2 = $res{'info'}[2]{'Fingerprint'}; } -diag "check that things still doesn't work if two keys are not trusted" if $ENV{TEST_VERBOSE}; +diag "check that things still doesn't work if two keys are not trusted"; { RT::Test->clean_caught_mails; ok $m->goto_create_ticket( $queue ), "UI -> create ticket"; - $m->form_number(3); + $m->form_name('TicketCreate'); $m->tick( Encrypt => 1 ); $m->field( Requestors => 'rt-test@example.com' ); $m->field( Content => 'Some content' ); $m->submit; - $m->content_like( - qr/You are going to encrypt outgoing email messages/i, + $m->content_contains( + 'You are going to encrypt outgoing email messages', 'problems with keys' ); - $m->content_like( - qr/There are several keys suitable for encryption/i, + $m->content_contains( + 'There are several keys suitable for encryption', 'problems with keys' ); - my $form = $m->form_number(3); + my $form = $m->form_name('TicketCreate'); ok my $input = $form->find_input( 'UseKey-rt-test@example.com' ), 'found key selector'; is scalar $input->possible_values, 2, 'two options'; $m->select( 'UseKey-rt-test@example.com' => $fpr1 ); $m->submit; - $m->content_like( - qr/You are going to encrypt outgoing email messages/i, + $m->content_contains( + 'You are going to encrypt outgoing email messages', 'problems with keys' ); - $m->content_like( - qr/Selected key either is not trusted/i, + $m->content_contains( + 'Selected key either is not trusted', 'problems with keys' ); my @mail = RT::Test->fetch_caught_mails; ok !@mail, 'there are no outgoing emails'; + + $m->no_warnings_ok; } { @@ -204,26 +181,28 @@ diag "check that we see key selector even if only one key is trusted but there a RT::Test->clean_caught_mails; ok $m->goto_create_ticket( $queue ), "UI -> create ticket"; - $m->form_number(3); + $m->form_name('TicketCreate'); $m->tick( Encrypt => 1 ); $m->field( Requestors => 'rt-test@example.com' ); $m->field( Content => 'Some content' ); $m->submit; - $m->content_like( - qr/You are going to encrypt outgoing email messages/i, + $m->content_contains( + 'You are going to encrypt outgoing email messages', 'problems with keys' ); - $m->content_like( - qr/There are several keys suitable for encryption/i, + $m->content_contains( + 'There are several keys suitable for encryption', 'problems with keys' ); - my $form = $m->form_number(3); + my $form = $m->form_name('TicketCreate'); ok my $input = $form->find_input( 'UseKey-rt-test@example.com' ), 'found key selector'; is scalar $input->possible_values, 2, 'two options'; my @mail = RT::Test->fetch_caught_mails; ok !@mail, 'there are no outgoing emails'; + + $m->no_warnings_ok; } diag "check that key selector works and we can select trusted key"; @@ -231,21 +210,21 @@ diag "check that key selector works and we can select trusted key"; RT::Test->clean_caught_mails; ok $m->goto_create_ticket( $queue ), "UI -> create ticket"; - $m->form_number(3); + $m->form_name('TicketCreate'); $m->tick( Encrypt => 1 ); $m->field( Requestors => 'rt-test@example.com' ); $m->field( Content => 'Some content' ); $m->submit; - $m->content_like( - qr/You are going to encrypt outgoing email messages/i, + $m->content_contains( + 'You are going to encrypt outgoing email messages', 'problems with keys' ); - $m->content_like( - qr/There are several keys suitable for encryption/i, + $m->content_contains( + 'There are several keys suitable for encryption', 'problems with keys' ); - my $form = $m->form_number(3); + my $form = $m->form_name('TicketCreate'); ok my $input = $form->find_input( 'UseKey-rt-test@example.com' ), 'found key selector'; is scalar $input->possible_values, 2, 'two options'; @@ -256,6 +235,8 @@ diag "check that key selector works and we can select trusted key"; my @mail = RT::Test->fetch_caught_mails; ok @mail, 'there are some emails'; check_text_emails( { Encrypt => 1 }, @mail ); + + $m->no_warnings_ok; } diag "check encrypting of attachments"; @@ -263,22 +244,22 @@ diag "check encrypting of attachments"; RT::Test->clean_caught_mails; ok $m->goto_create_ticket( $queue ), "UI -> create ticket"; - $m->form_number(3); + $m->form_name('TicketCreate'); $m->tick( Encrypt => 1 ); $m->field( Requestors => 'rt-test@example.com' ); $m->field( Content => 'Some content' ); $m->field( Attach => $0 ); $m->submit; - $m->content_like( - qr/You are going to encrypt outgoing email messages/i, + $m->content_contains( + 'You are going to encrypt outgoing email messages', 'problems with keys' ); - $m->content_like( - qr/There are several keys suitable for encryption/i, + $m->content_contains( + 'There are several keys suitable for encryption', 'problems with keys' ); - my $form = $m->form_number(3); + my $form = $m->form_name('TicketCreate'); ok my $input = $form->find_input( 'UseKey-rt-test@example.com' ), 'found key selector'; is scalar $input->possible_values, 2, 'two options'; @@ -289,37 +270,7 @@ diag "check encrypting of attachments"; my @mail = RT::Test->fetch_caught_mails; ok @mail, 'there are some emails'; check_text_emails( { Encrypt => 1, Attachment => 1 }, @mail ); -} -sub check_text_emails { - my %args = %{ shift @_ }; - my @mail = @_; - - ok scalar @mail, "got some mail"; - for my $mail (@mail) { - for my $type ('email', 'attachment') { - next if $type eq 'attachment' && !$args{'Attachment'}; - - my $content = $type eq 'email' - ? "Some content" - : "Attachment content"; - - if ( $args{'Encrypt'} ) { - unlike $mail, qr/$content/, "outgoing $type was encrypted"; - } else { - like $mail, qr/$content/, "outgoing $type was not encrypted"; - } - - next unless $type eq 'email'; - - if ( $args{'Sign'} && $args{'Encrypt'} ) { - like $mail, qr/BEGIN PGP MESSAGE/, 'outgoing email was signed'; - } elsif ( $args{'Sign'} ) { - like $mail, qr/SIGNATURE/, 'outgoing email was signed'; - } else { - unlike $mail, qr/SIGNATURE/, 'outgoing email was not signed'; - } - } - } + $m->no_warnings_ok; } diff --git a/rt/t/web/gnupg-select-keys-on-update.t b/rt/t/web/gnupg-select-keys-on-update.t index 76817ddf2..4842dcd54 100644 --- a/rt/t/web/gnupg-select-keys-on-update.t +++ b/rt/t/web/gnupg-select-keys-on-update.t @@ -2,34 +2,9 @@ use strict; use warnings; -use RT::Test tests => 68; - -plan skip_all => 'GnuPG required.' - unless eval 'use GnuPG::Interface; 1'; -plan skip_all => 'gpg executable is required.' - unless RT::Test->find_executable('gpg'); - +use RT::Test::GnuPG tests => 86, gnupg_options => { passphrase => 'rt-test' }; use RT::Action::SendEmail; -use File::Temp qw(tempdir); - -RT::Test->set_mail_catcher; - -use_ok('RT::Crypt::GnuPG'); - -RT->Config->Set( GnuPG => - Enable => 1, - OutgoingMessagesFormat => 'RFC', -); - -RT->Config->Set( GnuPGOptions => - homedir => scalar tempdir( CLEANUP => 0 ), - passphrase => 'rt-test', - 'no-permission-warning' => undef, -); -diag "GnuPG --homedir ". RT->Config->Get('GnuPGOptions')->{'homedir'} if $ENV{TEST_VERBOSE}; - -RT->Config->Set( 'MailPlugins' => 'Auth::MailFrom', 'Auth::GnuPG' ); my $queue = RT::Test->load_or_create_queue( Name => 'Regression', @@ -38,18 +13,13 @@ my $queue = RT::Test->load_or_create_queue( ); ok $queue && $queue->id, 'loaded or created queue'; -RT::Test->set_rights( - Principal => 'Everyone', - Right => ['CreateTicket', 'ShowTicket', 'SeeQueue', 'ReplyToTicket', 'ModifyTicket'], -); - my ($baseurl, $m) = RT::Test->started_ok; ok $m->login, 'logged in'; my $tid; { - my $ticket = RT::Ticket->new( $RT::SystemUser ); + my $ticket = RT::Ticket->new( RT->SystemUser ); ($tid) = $ticket->Create( Subject => 'test', Queue => $queue->id, @@ -57,24 +27,27 @@ my $tid; ok $tid, 'ticket created'; } -diag "check that signing doesn't work if there is no key" if $ENV{TEST_VERBOSE}; +diag "check that signing doesn't work if there is no key"; { RT::Test->clean_caught_mails; ok $m->goto_ticket( $tid ), "UI -> ticket #$tid"; $m->follow_link_ok( { text => 'Reply' }, 'ticket -> reply' ); - $m->form_number(3); + $m->form_name('TicketUpdate'); $m->tick( Sign => 1 ); $m->field( UpdateCc => 'rt-test@example.com' ); $m->field( UpdateContent => 'Some content' ); $m->click('SubmitTicket'); - $m->content_like( - qr/unable to sign outgoing email messages/i, + $m->content_contains( + 'unable to sign outgoing email messages', 'problems with passphrase' ); my @mail = RT::Test->fetch_caught_mails; ok !@mail, 'there are no outgoing emails'; + + $m->next_warning_like(qr/secret key not available/); + $m->no_leftover_warnings_ok; } { @@ -84,35 +57,38 @@ diag "check that signing doesn't work if there is no key" if $ENV{TEST_VERBOSE}; is $res{'info'}[0]{'TrustTerse'}, 'ultimate', 'ultimately trusted key'; } -diag "check that things don't work if there is no key" if $ENV{TEST_VERBOSE}; +diag "check that things don't work if there is no key"; { RT::Test->clean_caught_mails; ok $m->goto_ticket( $tid ), "UI -> ticket #$tid"; $m->follow_link_ok( { text => 'Reply' }, 'ticket -> reply' ); - $m->form_number(3); + $m->form_name('TicketUpdate'); $m->tick( Encrypt => 1 ); $m->field( UpdateCc => 'rt-test@example.com' ); $m->field( UpdateContent => 'Some content' ); $m->click('SubmitTicket'); - $m->content_like( - qr/You are going to encrypt outgoing email messages/i, + $m->content_contains( + 'You are going to encrypt outgoing email messages', 'problems with keys' ); - $m->content_like( - qr/There is no key suitable for encryption/i, + $m->content_contains( + 'There is no key suitable for encryption', 'problems with keys' ); - my $form = $m->form_number(3); + my $form = $m->form_name('TicketUpdate'); ok !$form->find_input( 'UseKey-rt-test@example.com' ), 'no key selector'; my @mail = RT::Test->fetch_caught_mails; ok !@mail, 'there are no outgoing emails'; + + $m->next_warning_like(qr/public key not found/) for 1 .. 2; + $m->no_leftover_warnings_ok; } -diag "import first key of rt-test\@example.com" if $ENV{TEST_VERBOSE}; +diag "import first key of rt-test\@example.com"; my $fpr1 = ''; { RT::Test->import_gnupg_key('rt-test@example.com', 'public'); @@ -121,46 +97,48 @@ my $fpr1 = ''; $fpr1 = $res{'info'}[0]{'Fingerprint'}; } -diag "check that things still doesn't work if key is not trusted" if $ENV{TEST_VERBOSE}; +diag "check that things still doesn't work if key is not trusted"; { RT::Test->clean_caught_mails; ok $m->goto_ticket( $tid ), "UI -> ticket #$tid"; $m->follow_link_ok( { text => 'Reply' }, 'ticket -> reply' ); - $m->form_number(3); + $m->form_name('TicketUpdate'); $m->tick( Encrypt => 1 ); $m->field( UpdateCc => 'rt-test@example.com' ); $m->field( UpdateContent => 'Some content' ); $m->click('SubmitTicket'); - $m->content_like( - qr/You are going to encrypt outgoing email messages/i, + $m->content_contains( + 'You are going to encrypt outgoing email messages', 'problems with keys' ); - $m->content_like( - qr/There is one suitable key, but trust level is not set/i, + $m->content_contains( + 'There is one suitable key, but trust level is not set', 'problems with keys' ); - my $form = $m->form_number(3); + my $form = $m->form_name('TicketUpdate'); ok my $input = $form->find_input( 'UseKey-rt-test@example.com' ), 'found key selector'; is scalar $input->possible_values, 1, 'one option'; $m->select( 'UseKey-rt-test@example.com' => $fpr1 ); $m->click('SubmitTicket'); - $m->content_like( - qr/You are going to encrypt outgoing email messages/i, + $m->content_contains( + 'You are going to encrypt outgoing email messages', 'problems with keys' ); - $m->content_like( - qr/Selected key either is not trusted/i, + $m->content_contains( + 'Selected key either is not trusted', 'problems with keys' ); my @mail = RT::Test->fetch_caught_mails; ok !@mail, 'there are no outgoing emails'; + + $m->no_warnings_ok; } -diag "import a second key of rt-test\@example.com" if $ENV{TEST_VERBOSE}; +diag "import a second key of rt-test\@example.com"; my $fpr2 = ''; { RT::Test->import_gnupg_key('rt-test@example.com.2', 'public'); @@ -169,43 +147,45 @@ my $fpr2 = ''; $fpr2 = $res{'info'}[2]{'Fingerprint'}; } -diag "check that things still doesn't work if two keys are not trusted" if $ENV{TEST_VERBOSE}; +diag "check that things still doesn't work if two keys are not trusted"; { RT::Test->clean_caught_mails; ok $m->goto_ticket( $tid ), "UI -> ticket #$tid"; $m->follow_link_ok( { text => 'Reply' }, 'ticket -> reply' ); - $m->form_number(3); + $m->form_name('TicketUpdate'); $m->tick( Encrypt => 1 ); $m->field( UpdateCc => 'rt-test@example.com' ); $m->field( UpdateContent => 'Some content' ); $m->click('SubmitTicket'); - $m->content_like( - qr/You are going to encrypt outgoing email messages/i, + $m->content_contains( + 'You are going to encrypt outgoing email messages', 'problems with keys' ); - $m->content_like( - qr/There are several keys suitable for encryption/i, + $m->content_contains( + 'There are several keys suitable for encryption', 'problems with keys' ); - my $form = $m->form_number(3); + my $form = $m->form_name('TicketUpdate'); ok my $input = $form->find_input( 'UseKey-rt-test@example.com' ), 'found key selector'; is scalar $input->possible_values, 2, 'two options'; $m->select( 'UseKey-rt-test@example.com' => $fpr1 ); $m->click('SubmitTicket'); - $m->content_like( - qr/You are going to encrypt outgoing email messages/i, + $m->content_contains( + 'You are going to encrypt outgoing email messages', 'problems with keys' ); - $m->content_like( - qr/Selected key either is not trusted/i, + $m->content_contains( + 'Selected key either is not trusted', 'problems with keys' ); my @mail = RT::Test->fetch_caught_mails; ok !@mail, 'there are no outgoing emails'; + + $m->no_warnings_ok; } { @@ -215,130 +195,103 @@ diag "check that things still doesn't work if two keys are not trusted" if $ENV{ is $res{'info'}[1]{'TrustLevel'}, 0, 'is not trusted key'; } -diag "check that we see key selector even if only one key is trusted but there are more keys" if $ENV{TEST_VERBOSE}; +diag "check that we see key selector even if only one key is trusted but there are more keys"; { RT::Test->clean_caught_mails; ok $m->goto_ticket( $tid ), "UI -> ticket #$tid"; $m->follow_link_ok( { text => 'Reply' }, 'ticket -> reply' ); - $m->form_number(3); + $m->form_name('TicketUpdate'); $m->tick( Encrypt => 1 ); $m->field( UpdateCc => 'rt-test@example.com' ); $m->field( UpdateContent => 'Some content' ); $m->click('SubmitTicket'); - $m->content_like( - qr/You are going to encrypt outgoing email messages/i, + $m->content_contains( + 'You are going to encrypt outgoing email messages', 'problems with keys' ); - $m->content_like( - qr/There are several keys suitable for encryption/i, + $m->content_contains( + 'There are several keys suitable for encryption', 'problems with keys' ); - my $form = $m->form_number(3); + my $form = $m->form_name('TicketUpdate'); ok my $input = $form->find_input( 'UseKey-rt-test@example.com' ), 'found key selector'; is scalar $input->possible_values, 2, 'two options'; my @mail = RT::Test->fetch_caught_mails; ok !@mail, 'there are no outgoing emails'; + + $m->no_warnings_ok; } -diag "check that key selector works and we can select trusted key" if $ENV{TEST_VERBOSE}; +diag "check that key selector works and we can select trusted key"; { RT::Test->clean_caught_mails; ok $m->goto_ticket( $tid ), "UI -> ticket #$tid"; $m->follow_link_ok( { text => 'Reply' }, 'ticket -> reply' ); - $m->form_number(3); + $m->form_name('TicketUpdate'); $m->tick( Encrypt => 1 ); $m->field( UpdateCc => 'rt-test@example.com' ); $m->field( UpdateContent => 'Some content' ); $m->click('SubmitTicket'); - $m->content_like( - qr/You are going to encrypt outgoing email messages/i, + $m->content_contains( + 'You are going to encrypt outgoing email messages', 'problems with keys' ); - $m->content_like( - qr/There are several keys suitable for encryption/i, + $m->content_contains( + 'There are several keys suitable for encryption', 'problems with keys' ); - my $form = $m->form_number(3); + my $form = $m->form_name('TicketUpdate'); ok my $input = $form->find_input( 'UseKey-rt-test@example.com' ), 'found key selector'; is scalar $input->possible_values, 2, 'two options'; $m->select( 'UseKey-rt-test@example.com' => $fpr1 ); $m->click('SubmitTicket'); - $m->content_like( qr/Message recorded/i, 'Message recorded' ); + $m->content_contains('Message recorded', 'Message recorded' ); my @mail = RT::Test->fetch_caught_mails; ok @mail, 'there are some emails'; check_text_emails( { Encrypt => 1 }, @mail ); + + $m->no_warnings_ok; } -diag "check encrypting of attachments" if $ENV{TEST_VERBOSE}; +diag "check encrypting of attachments"; { RT::Test->clean_caught_mails; ok $m->goto_ticket( $tid ), "UI -> ticket #$tid"; $m->follow_link_ok( { text => 'Reply' }, 'ticket -> reply' ); - $m->form_number(3); + $m->form_name('TicketUpdate'); $m->tick( Encrypt => 1 ); $m->field( UpdateCc => 'rt-test@example.com' ); $m->field( UpdateContent => 'Some content' ); $m->field( Attach => $0 ); $m->click('SubmitTicket'); - $m->content_like( - qr/You are going to encrypt outgoing email messages/i, + $m->content_contains( + 'You are going to encrypt outgoing email messages', 'problems with keys' ); - $m->content_like( - qr/There are several keys suitable for encryption/i, + $m->content_contains( + 'There are several keys suitable for encryption', 'problems with keys' ); - my $form = $m->form_number(3); + my $form = $m->form_name('TicketUpdate'); ok my $input = $form->find_input( 'UseKey-rt-test@example.com' ), 'found key selector'; is scalar $input->possible_values, 2, 'two options'; $m->select( 'UseKey-rt-test@example.com' => $fpr1 ); $m->click('SubmitTicket'); - $m->content_like( qr/Message recorded/i, 'Message recorded' ); + $m->content_contains('Message recorded', 'Message recorded' ); my @mail = RT::Test->fetch_caught_mails; ok @mail, 'there are some emails'; check_text_emails( { Encrypt => 1, Attachment => 1 }, @mail ); -} -sub check_text_emails { - my %args = %{ shift @_ }; - my @mail = @_; - - ok scalar @mail, "got some mail"; - for my $mail (@mail) { - for my $type ('email', 'attachment') { - next if $type eq 'attachment' && !$args{'Attachment'}; - - my $content = $type eq 'email' - ? "Some content" - : "Attachment content"; - - if ( $args{'Encrypt'} ) { - unlike $mail, qr/$content/, "outgoing $type was encrypted"; - } else { - like $mail, qr/$content/, "outgoing $type was not encrypted"; - } - - next unless $type eq 'email'; - - if ( $args{'Sign'} && $args{'Encrypt'} ) { - like $mail, qr/BEGIN PGP MESSAGE/, 'outgoing email was signed'; - } elsif ( $args{'Sign'} ) { - like $mail, qr/SIGNATURE/, 'outgoing email was signed'; - } else { - unlike $mail, qr/SIGNATURE/, 'outgoing email was not signed'; - } - } - } + $m->no_warnings_ok; } - diff --git a/rt/t/web/gnupg-tickyboxes.t b/rt/t/web/gnupg-tickyboxes.t new file mode 100644 index 000000000..944539758 --- /dev/null +++ b/rt/t/web/gnupg-tickyboxes.t @@ -0,0 +1,84 @@ +#!/usr/bin/perl -w +use strict; +use warnings; + +use RT::Test::GnuPG tests => 22, gnupg_options => { passphrase => 'rt-test' }; + +use RT::Action::SendEmail; + +RT::Test->import_gnupg_key('rt-recipient@example.com'); +RT::Test->import_gnupg_key('rt-test@example.com', 'public'); + +my $queue = RT::Test->load_or_create_queue( + Name => 'Regression', + CorrespondAddress => 'rt-recipient@example.com', + CommentAddress => 'rt-recipient@example.com', +); +ok $queue && $queue->id, 'loaded or created queue'; + +my ($baseurl, $m) = RT::Test->started_ok; +ok $m->login, 'logged in'; + +my @variants = ( + {}, + { Sign => 1 }, + { Encrypt => 1 }, + { Sign => 1, Encrypt => 1 }, +); + +# collect emails +my %mail = ( + plain => [], + signed => [], + encrypted => [], + signed_encrypted => [], +); + +diag "check in read-only mode that queue's props influence create/update ticket pages"; +{ + foreach my $variant ( @variants ) { + set_queue_crypt_options( $queue => %$variant ); + $m->goto_create_ticket( $queue ); + $m->form_name('TicketCreate'); + if ( $variant->{'Encrypt'} ) { + ok $m->value('Encrypt', 2), "encrypt tick box is checked"; + } else { + ok !$m->value('Encrypt', 2), "encrypt tick box is unchecked"; + } + if ( $variant->{'Sign'} ) { + ok $m->value('Sign', 2), "sign tick box is checked"; + } else { + ok !$m->value('Sign', 2), "sign tick box is unchecked"; + } + } + + # to avoid encryption/signing during create + set_queue_crypt_options($queue); + + my $ticket = RT::Ticket->new( RT->SystemUser ); + my ($id) = $ticket->Create( + Subject => 'test', + Queue => $queue->id, + Requestor => 'rt-test@example.com', + ); + ok $id, 'ticket created'; + + foreach my $variant ( @variants ) { + set_queue_crypt_options( $queue => %$variant ); + $m->get( $m->rt_base_url . "/Ticket/Update.html?Action=Respond&id=$id" ); + $m->form_name('TicketUpdate'); + if ( $variant->{'Encrypt'} ) { + ok $m->value('Encrypt', 2), "encrypt tick box is checked"; + } else { + ok !$m->value('Encrypt', 2), "encrypt tick box is unchecked"; + } + if ( $variant->{'Sign'} ) { + ok $m->value('Sign', 2), "sign tick box is checked"; + } else { + ok !$m->value('Sign', 2), "sign tick box is unchecked"; + } + } +} + + + diff --git a/rt/t/web/googleish_search.t b/rt/t/web/googleish_search.t new file mode 100644 index 000000000..e2a4e9116 --- /dev/null +++ b/rt/t/web/googleish_search.t @@ -0,0 +1,219 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +use RT::Test tests => 96, config => 'Set( %FullTextSearch, Enable => 1, Indexed => 0 );'; +my ($baseurl, $m) = RT::Test->started_ok; +my $url = $m->rt_base_url; + +my $queue = RT::Queue->new($RT::SystemUser); +$queue->Create( Name => 'other' ); +ok( $queue->id, 'created queue other'); + +my $two_words_queue = RT::Test->load_or_create_queue( + Name => 'Two Words', +); +ok $two_words_queue && $two_words_queue->id, 'loaded or created a queue'; + + +{ + my $tickets = RT::Tickets->new( RT->SystemUser ); + my $active = "( ".join( " OR ", map "Status = '$_'", RT::Queue->ActiveStatusArray())." )"; + my $inactive = "( ".join( " OR ", map "Status = '$_'", RT::Queue->InactiveStatusArray())." )"; + + require RT::Search::Googleish; + my $parser = RT::Search::Googleish->new( + TicketsObj => $tickets, + Argument => '', + ); + is $parser->QueryToSQL("foo"), "$active AND ( Subject LIKE 'foo' )", "correct parsing"; + is $parser->QueryToSQL("1"), "( Id = 1 )", "correct parsing"; + is $parser->QueryToSQL("#1"), "( Id = 1 )", "correct parsing"; + is $parser->QueryToSQL("'1'"), "$active AND ( Subject LIKE '1' )", "correct parsing"; + + is $parser->QueryToSQL("foo bar"), + "$active AND ( Subject LIKE 'foo' AND Subject LIKE 'bar' )", + "correct parsing"; + is $parser->QueryToSQL("'foo bar'"), + "$active AND ( Subject LIKE 'foo bar' )", + "correct parsing"; + + is $parser->QueryToSQL("'foo \\' bar'"), + "$active AND ( Subject LIKE 'foo \\' bar' )", + "correct parsing"; + is $parser->QueryToSQL('"foo \' bar"'), + "$active AND ( Subject LIKE 'foo \\' bar' )", + "correct parsing"; + is $parser->QueryToSQL('"\f\o\o"'), + "$active AND ( Subject LIKE '\\\\f\\\\o\\\\o' )", + "correct parsing"; + + is $parser->QueryToSQL("General"), "( Queue = 'General' ) AND $active", "correct parsing"; + is $parser->QueryToSQL("'Two Words'"), "$active AND ( Subject LIKE 'Two Words' )", "correct parsing"; + is $parser->QueryToSQL("queue:'Two Words'"), "( Queue = 'Two Words' ) AND $active", "correct parsing"; + is $parser->QueryToSQL("subject:'Two Words'"), "$active AND ( Subject LIKE 'Two Words' )", "correct parsing"; + + is $parser->QueryToSQL("me"), "( Owner.id = '__CurrentUser__' ) AND $active", "correct parsing"; + is $parser->QueryToSQL("'me'"), "$active AND ( Subject LIKE 'me' )", "correct parsing"; + is $parser->QueryToSQL("owner:me"), "( Owner.id = '__CurrentUser__' ) AND $active", "correct parsing"; + is $parser->QueryToSQL("owner:'me'"), "( Owner = 'me' ) AND $active", "correct parsing"; + + is $parser->QueryToSQL("resolved me"), "( Owner.id = '__CurrentUser__' ) AND ( Status = 'resolved' )", "correct parsing"; + is $parser->QueryToSQL("resolved active me"), "( Owner.id = '__CurrentUser__' ) AND ( Status = 'resolved' OR Status = 'new' OR Status = 'open' OR Status = 'stalled' )", "correct parsing"; + is $parser->QueryToSQL("status:active"), $active, "Explicit active search"; + is $parser->QueryToSQL("status:'active'"), "( Status = 'active' )", "Quoting active makes it the actual word"; + is $parser->QueryToSQL("inactive me"), "( Owner.id = '__CurrentUser__' ) AND $inactive", "correct parsing"; + + is $parser->QueryToSQL("cf.Foo:bar"), "( 'CF.{Foo}' LIKE 'bar' ) AND $active", "correct parsing of CFs"; + is $parser->QueryToSQL(q{cf."don't foo?":'bar n\\' baz'}), qq/( 'CF.{don\\'t foo?}' LIKE 'bar n\\' baz' ) AND $active/, "correct parsing of CFs with quotes"; +} + +my $ticket_found_1 = RT::Ticket->new($RT::SystemUser); +my $ticket_found_2 = RT::Ticket->new($RT::SystemUser); +my $ticket_not_found = RT::Ticket->new($RT::SystemUser); + +$ticket_found_1->Create( + Subject => 'base ticket 1'.$$, + Queue => 'general', + Owner => 'root', + Requestor => 'customsearch@localhost', + Content => 'this is base ticket 1', +); +ok( $ticket_found_1->id, 'created ticket for custom search'); + + +$ticket_found_2->Create( + Subject => 'base ticket 2'.$$, + Queue => 'general', + Owner => 'root', + Requestor => 'customsearch@localhost', + Content => 'this is base ticket 2', +); +ok( $ticket_found_2->id, 'created ticket for custom search'); + +$ticket_not_found = RT::Ticket->new($RT::SystemUser); +$ticket_not_found->Create( + Subject => 'not found subject' . $$, + Queue => 'other', + Owner => 'nobody', + Requestor => 'notfound@localhost', + Content => 'this is not found content', +); +ok( $ticket_not_found->id, 'created ticket for custom search'); + +ok($m->login, 'logged in'); + +my @queries = ( + 'base ticket', 'root', + 'customsearch@localhost', 'requestor:customsearch', + 'subject:base', 'subject:"base ticket"', + 'queue:general', 'owner:root', +); + +for my $q (@queries) { + $m->form_with_fields('q'); + $m->field( q => $q ); + $m->submit; + $m->content_contains( 'base ticket 1', 'base ticket 1 is found' ); + $m->content_contains( 'base ticket 2', 'base ticket 2 is found' ); + $m->content_lacks( 'not found subject', 'not found ticket is not found' ); +} + +$ticket_not_found->SetStatus('open'); +is( $ticket_not_found->Status, 'open', 'status of not found ticket is open' ); +@queries = qw/new status:new/; +for my $q (@queries) { + $m->form_with_fields('q'); + $m->field( q => $q ); + $m->submit; + $m->content_contains( 'base ticket 1', 'base ticket 1 is found' ); + $m->content_contains( 'base ticket 2', 'base ticket 2 is found' ); + $m->content_lacks( 'not found subject', 'not found ticket is not found' ); +} + +@queries = ( 'fulltext:"base ticket 1"', "'base ticket 1'" ); +for my $q (@queries) { + $m->form_with_fields('q'); + $m->field( q => $q ); + $m->submit; + $m->content_contains( 'base ticket 1', 'base ticket 1 is found' ); + $m->content_lacks( 'base ticket 2', 'base ticket 2 is not found' ); + $m->content_lacks( 'not found subject', 'not found ticket is not found' ); +} + +# now let's test with ' or " +for my $quote ( q{'}, q{"} ) { + my $user = RT::User->new($RT::SystemUser); + is( ref($user), 'RT::User' ); + my ( $id, $msg ) = $user->Create( + Name => qq!foo${quote}bar!, + EmailAddress => qq!foo${quote}bar$$\@example.com !, + Privileged => 1, + ); + ok ($id, "Creating user - " . $msg ); + + my ( $grantid, $grantmsg ) = + $user->PrincipalObj->GrantRight( Right => 'OwnTicket' ); + ok( $grantid, $grantmsg ); + + + + my $ticket_quote = RT::Ticket->new($RT::SystemUser); + $ticket_quote->Create( + Subject => qq!base${quote}ticket $$!, + Queue => 'general', + Owner => $user->Name, + Requestor => qq!custom${quote}search\@localhost!, + Content => qq!this is base${quote}ticket with quote inside!, + ); + ok( $ticket_quote->id, 'created ticket with quote for custom search' ); + + @queries = ( + qq!fulltext:base${quote}ticket!, + "base${quote}ticket", + "owner:foo${quote}bar", + "foo${quote}bar", + + # email doesn't allow " character + $quote eq q{'} + ? ( + "requestor:custom${quote}search\@localhost", + "custom${quote}search\@localhost", + ) + : (), + ); + for my $q (@queries) { + $m->form_with_fields('q'); + $m->field( q => $q ); + $m->submit; + my $escape_quote = $quote; + RT::Interface::Web::EscapeUTF8(\$escape_quote); + $m->content_contains( "base${escape_quote}ticket", + "base${quote}ticket is found" ); + } +} + +# Create a CF +{ + my $cf = RT::CustomField->new(RT->SystemUser); + ok( $cf->Create(Name => 'Foo', Type => 'Freeform', MaxValues => '1', Queue => 0) ); + ok $cf->Id; + + $ticket_found_1->AddCustomFieldValue( Field => 'Foo', Value => 'bar' ); + $ticket_found_2->AddCustomFieldValue( Field => 'Foo', Value => 'bar' ); + $ticket_not_found->AddCustomFieldValue( Field => 'Foo', Value => 'baz' ); + is( $ticket_found_1->FirstCustomFieldValue('Foo'), 'bar', 'cf value is ok' ); + is( $ticket_found_2->FirstCustomFieldValue('Foo'), 'bar', 'cf value is ok' ); + is( $ticket_not_found->FirstCustomFieldValue('Foo'), 'baz', 'cf value is ok' ); + + @queries = qw/cf.Foo:bar/; + for my $q (@queries) { + $m->form_with_fields('q'); + $m->field( q => $q ); + $m->submit; + $m->content_contains( 'base ticket 1', 'base ticket 1 is found' ); + $m->content_contains( 'base ticket 2', 'base ticket 2 is found' ); + $m->content_lacks( 'not found subject', 'not found ticket is not found' ); + } +} + diff --git a/rt/t/web/group_create.t b/rt/t/web/group_create.t new file mode 100644 index 000000000..26da59268 --- /dev/null +++ b/rt/t/web/group_create.t @@ -0,0 +1,75 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use RT::Test tests => 13; + +my ( $baseurl, $m ) = RT::Test->started_ok; +ok $m->login, 'logged in as root'; +my $root = RT::User->new(RT->SystemUser); +ok( $root->Load('root'), 'load root user' ); + +my $group_name = 'test group'; + +my $group_id; +diag "Create a group"; +{ + $m->follow_link( id => 'tools-config-groups-create'); + + # Test group form validation + $m->submit_form( + form_name => 'ModifyGroup', + fields => { + Name => '', + }, + ); + $m->text_contains('Name is required'); + $m->submit_form( + form_name => 'ModifyGroup', + fields => { + Name => '0', + }, + ); + $m->text_contains('Could not create group'); + $m->submit_form( + form_name => 'ModifyGroup', + fields => { + Name => '1', + }, + ); + $m->text_contains('Could not create group'); + $m->submit_form( + form_name => 'ModifyGroup', + fields => { + Name => $group_name, + }, + ); + $m->content_contains('Group created', 'created group sucessfully' ); + + # Test validation on updae + $m->form_name('ModifyGroup'); + $m->set_fields( + Name => '', + ); + $m->click_button(value => 'Save Changes'); + $m->text_contains('Illegal value for Name'); + + $m->form_name('ModifyGroup'); + $m->set_fields( + Name => '0', + ); + $m->click_button(value => 'Save Changes'); + $m->text_contains('Illegal value for Name'); + + $m->form_name('ModifyGroup'); + $m->set_fields( + Name => '1', + ); + $m->click_button(value => 'Save Changes'); + $m->text_contains('Illegal value for Name'); + + $group_id = $m->form_name('ModifyGroup')->value('id'); + ok $group_id, "found id of the group in the form, it's #$group_id"; +} + diff --git a/rt/t/web/html/Callbacks/logout.t/NoAuth/Logout.html/Default b/rt/t/web/html/Callbacks/logout.t/NoAuth/Logout.html/Default new file mode 100644 index 000000000..90278ae49 --- /dev/null +++ b/rt/t/web/html/Callbacks/logout.t/NoAuth/Logout.html/Default @@ -0,0 +1,6 @@ +<%args> +$URL +</%args> +<%init> +$$URL = 'http://bestpractical.com/rt'; +</%init> diff --git a/rt/t/web/html/NoAuth/js/not-by-default.js b/rt/t/web/html/NoAuth/js/not-by-default.js new file mode 100644 index 000000000..568f670ee --- /dev/null +++ b/rt/t/web/html/NoAuth/js/not-by-default.js @@ -0,0 +1,3 @@ +function just_testing() { + alert("hi"); +} diff --git a/rt/t/web/html/delete-article-name-method.html b/rt/t/web/html/delete-article-name-method.html new file mode 100644 index 000000000..27592c1d0 --- /dev/null +++ b/rt/t/web/html/delete-article-name-method.html @@ -0,0 +1,15 @@ +<%INIT> +# This is used by t/web/articles-links.t. Since we fork off a server +# under most test configurations, and we need a way to run code in the +# middle of the test script, we have to play at shenanigans to delete +# RT::Article's Name method. Other options were a Plack::Middleware that +# eval'd code given by paths like /__perl/(.+) (is scary), a signal +# handler (fails under apache), and only running articles-links.t for +# inline tests (fails under apache and standalone) + +delete $RT::Article::{Name}; + +</%INIT> + +<% RT::Article->can('Name') ? '{exists}' : '{deleted}' %> + diff --git a/rt/t/web/html_template.t b/rt/t/web/html_template.t index a2461dc97..662a26bbd 100644 --- a/rt/t/web/html_template.t +++ b/rt/t/web/html_template.t @@ -8,22 +8,17 @@ use Encode; my ( $baseurl, $m ) = RT::Test->started_ok; ok $m->login, 'logged in as root'; -$RT::Test::SKIP_REQUEST_WORK_AROUND = 1; -RT::Test->set_mail_catcher; - use utf8; diag('make Autoreply template a html one and add utf8 chars') if $ENV{TEST_VERBOSE}; { - $m->follow_link_ok( { text => 'Configuration' }, '-> Configuration' ); - $m->follow_link_ok( { text => 'Global' }, '-> Global' ); - $m->follow_link_ok( { text => 'Templates' }, '-> Templates' ); + $m->follow_link_ok( { id => 'tools-config-global-templates' }, '-> Templates' ); $m->follow_link_ok( { text => 'Autoreply' }, '-> Autoreply' ); - $m->form_number(3); $m->submit_form( + form_name => 'ModifyTemplate', fields => { Content => <<'EOF', Subject: AutoReply: {$Ticket->Subject} @@ -46,9 +41,8 @@ diag('create a ticket to see the autoreply mail') if $ENV{TEST_VERBOSE}; { $m->get_ok( $baseurl . '/Ticket/Create.html?Queue=1' ); - $m->form_number(3); $m->submit_form( - form_number => 3, + form_name => 'TicketCreate', fields => { Subject => '标题', Content => '<h1>测试</h1>', ContentType => 'text/html' }, ); diff --git a/rt/t/web/logout.t b/rt/t/web/logout.t new file mode 100644 index 000000000..889e5fc18 --- /dev/null +++ b/rt/t/web/logout.t @@ -0,0 +1,39 @@ +#!/usr/bin/perl +use strict; +use warnings; + +use RT::Test tests => 12; + +my ($baseurl, $agent) = RT::Test->started_ok; + +my $url = $agent->rt_base_url; +diag $url if $ENV{TEST_VERBOSE}; + +# test that logout would actually redirects to the correct URL +{ + ok $agent->login, "logged in"; + $agent->follow_link_ok({ text => 'Logout' }); + like $agent->uri, qr'/Logout\.html$', "right url"; + $agent->content_contains('<meta http-equiv="refresh" content="1;URL=/"', "found the expected meta-refresh"); +} + +# Stop server and set MasonLocalComponentRoot +RT::Test->stop_server; + +RT->Config->Set(MasonLocalComponentRoot => RT::Test::get_abs_relocatable_dir('html')); + +($baseurl, $agent) = RT::Test->started_ok; + +$url = $agent->rt_base_url; +diag $url if $ENV{TEST_VERBOSE}; + +# test that logout would actually redirects to URL from the callback +{ + ok $agent->login, "logged in"; + $agent->follow_link_ok({ text => 'Logout' }); + like $agent->uri, qr'/Logout\.html$', "right url"; + $agent->content_contains('<meta http-equiv="refresh" content="1;URL=http://bestpractical.com/rt"', "found the expected meta-refresh"); +} + + +1; diff --git a/rt/t/web/offline.t b/rt/t/web/offline.t new file mode 100644 index 000000000..b3762fc20 --- /dev/null +++ b/rt/t/web/offline.t @@ -0,0 +1,78 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +use RT::Test tests => 20; + +my ( $url, $m ) = RT::Test->started_ok; +ok( $m->login, 'logged in' ); + +{ + my $template = <<EOF; +===Create-Ticket: ticket1 +Queue: General +Subject: test +Status: new +EOF + my $ticket = create_ticket_offline( $m, $template ); + ok $ticket->id, 'created a ticket with offline tool'; + is $ticket->QueueObj->Name, 'General', 'correct value'; + is $ticket->Subject, 'test', 'correct value'; + is $ticket->Status, 'new', 'correct value'; +} + +{ + my $template = <<'EOF'; +===Create-Ticket: ticket1 +Queue: General +Subject: test +Status: new +Requestor: test@example.com +EOF + my $ticket = create_ticket_offline( $m, $template ); + ok $ticket->id, 'created a ticket with offline tool'; + is $ticket->RequestorAddresses, 'test@example.com', 'correct value'; +} + +{ + my $group = RT::Group->new(RT->SystemUser); + my ($id, $msg) = $group->CreateUserDefinedGroup( Name => 'test' ); + ok $id, "created a user defined group"; + + my $template = <<'EOF'; +===Create-Ticket: ticket1 +Queue: General +Subject: test +Status: new +Requestor: test@example.com +RequestorGroup: test +EOF + my $ticket = create_ticket_offline( $m, $template ); + ok $ticket->id, 'created a ticket with offline tool'; + ok grep( + { $_->MemberId eq $group->id } + @{ $ticket->Requestors->MembersObj->ItemsArrayRef } + ), 'correct value' ; + is $ticket->RequestorAddresses, 'test@example.com', 'correct value'; +} + +sub create_ticket_offline { + my ($m, $template) = @_; + + $m->get_ok( $url . '/Tools/Offline.html' ); + + $m->submit_form( + form_name => 'TicketUpdate', + fields => { string => $template }, + button => 'UpdateTickets', + ); + + my $ticket = RT::Ticket->new( RT->SystemUser ); + $m->content_like( qr/Ticket \d+ created/, 'found ticket created message' ) + or return $ticket; + + $ticket->Load( $m->content =~ /Ticket (\d+) created/ ); + return $ticket; +} + + diff --git a/rt/t/web/offline_messages_utf8.t b/rt/t/web/offline_messages_utf8.t index 9901b4555..bf9cf39fa 100644 --- a/rt/t/web/offline_messages_utf8.t +++ b/rt/t/web/offline_messages_utf8.t @@ -2,8 +2,7 @@ use strict; use warnings; -use RT::Test tests => 6; -use File::Temp qw/tempfile/; +use RT::Test tests => 8; use Encode; use RT::Ticket; diff --git a/rt/t/web/offline_utf8.t b/rt/t/web/offline_utf8.t index 2a3e64d3c..24795c0d3 100644 --- a/rt/t/web/offline_utf8.t +++ b/rt/t/web/offline_utf8.t @@ -2,11 +2,14 @@ use strict; use warnings; -use RT::Test tests => 8; -use File::Temp qw/tempfile/; +use RT::Test tests => 9; +use utf8; + use Encode; + use RT::Ticket; -my ( $fh, $file ) = tempfile; +my $file = File::Spec->catfile( RT::Test->temp_directory, 'template' ); +open my $fh, '>', $file or die $!; my $template = <<EOF; ===Create-Ticket: ticket1 Queue: General @@ -38,17 +41,17 @@ $m->submit_form( button => 'UpdateTickets', # mimic what browsers do: they seems decoded $template - fields => { string => decode( 'utf8', $template ), }, + fields => { string => $template }, ); $m->content_like( qr/Ticket \d+ created/, 'found ticket created message' ); my ( $ticket_id ) = $m->content =~ /Ticket (\d+) created/; -my $ticket = RT::Ticket->new( $RT::SystemUser ); +my $ticket = RT::Ticket->new( RT->SystemUser ); $ticket->Load( $ticket_id ); is( $ticket->Subject, '标题', 'subject in $ticket is right' ); -$m->get_ok( $url . "/Ticket/Display.html?id=$ticket_id" ); +$m->goto_ticket($ticket_id); $m->content_contains( '这是正文', 'content is right in ticket display page' ); diff --git a/rt/t/web/passthrough-jsmin b/rt/t/web/passthrough-jsmin new file mode 100644 index 000000000..3d9bf0129 --- /dev/null +++ b/rt/t/web/passthrough-jsmin @@ -0,0 +1,5 @@ +#!/bin/sh + +echo "// passthrough-jsmin added this"; + +exec cat; diff --git a/rt/t/web/path-traversal.t b/rt/t/web/path-traversal.t index 8d2f5cc88..5d5c954a1 100644 --- a/rt/t/web/path-traversal.t +++ b/rt/t/web/path-traversal.t @@ -1,7 +1,7 @@ use strict; use warnings; -use RT::Test tests => 20; +use RT::Test tests => 22; my ($baseurl, $agent) = RT::Test->started_ok; @@ -19,11 +19,17 @@ $agent->warning_like(qr/Invalid request.*aborting/,); $agent->get("$baseurl/NoAuth/../../../etc/RT_Config.pm"); is($agent->status, 400); -$agent->warning_like(qr/Invalid request.*aborting/,); +SKIP: { + skip "Apache rejects busting up above / for us", 2 if $ENV{RT_TEST_WEB_HANDLER} =~ /^apache/; + $agent->warning_like(qr/Invalid request.*aborting/,); +}; $agent->get("$baseurl/NoAuth/css/web2/images/../../../../../../etc/RT_Config.pm"); is($agent->status, 400); -$agent->warning_like(qr/Invalid request.*aborting/,); +SKIP: { + skip "Apache rejects busting up above / for us", 2 if $ENV{RT_TEST_WEB_HANDLER} =~ /^apache/; + $agent->warning_like(qr/Invalid request.*aborting/,); +}; # do not reject these URLs, even though they contain /. outside the path $agent->get("$baseurl/index.html?ignored=%2F%2E"); diff --git a/rt/t/web/private-components.t b/rt/t/web/private-components.t index 30e145f34..ceb2b34af 100644 --- a/rt/t/web/private-components.t +++ b/rt/t/web/private-components.t @@ -1,6 +1,6 @@ use strict; -use RT::Test tests => 20; +use RT::Test tests => 24; my ($baseurl, $agent) = RT::Test->started_ok; ok $agent->login, 'logged in'; @@ -18,6 +18,10 @@ $agent->get("/Widgets/TitleBox?title=private"); is($agent->status, 403); $agent->content_lacks("private"); +$agent->get("/m/_elements/header?title=private"); +is($agent->status, 403); +$agent->content_lacks("private"); + $agent->get("/autohandler"); is($agent->status, 403); $agent->content_lacks("comp called without component"); diff --git a/rt/t/web/query_builder.t b/rt/t/web/query_builder.t index 25d6ec5a3..0abbfaca8 100644 --- a/rt/t/web/query_builder.t +++ b/rt/t/web/query_builder.t @@ -5,7 +5,7 @@ use HTTP::Request::Common; use HTTP::Cookies; use LWP; use Encode; -use RT::Test tests => 50; +use RT::Test tests => 56; my $cookie_jar = HTTP::Cookies->new; my ($baseurl, $agent) = RT::Test->started_ok; @@ -22,12 +22,12 @@ ok $queue && $queue->id, 'loaded or created queue'; my $url = $agent->rt_base_url; ok $agent->login, "logged in"; -# {{{ Query Builder tests my $response = $agent->get($url."Search/Build.html"); ok $response->is_success, "Fetched ". $url ."Search/Build.html"; sub getQueryFromForm { + my $agent = shift; $agent->form_name('BuildQuery'); # This pulls out the "hidden input" query from the page my $q = $agent->current_form->find_input("Query")->value; @@ -38,117 +38,117 @@ sub getQueryFromForm { } sub selectedClauses { + my $agent = shift; my @clauses = grep { defined } map { $_->value } $agent->current_form->find_input("clauses"); return [ @clauses ]; } -diag "add the first condition" if $ENV{'TEST_VERBOSE'}; +diag "add the first condition"; { ok $agent->form_name('BuildQuery'), "found the form once"; $agent->field("ActorField", "Owner"); $agent->field("ActorOp", "="); $agent->field("ValueOfActor", "Nobody"); $agent->submit; - is getQueryFromForm, "Owner = 'Nobody'", 'correct query'; + is getQueryFromForm($agent), "Owner = 'Nobody'", 'correct query'; } -diag "set the next condition" if $ENV{'TEST_VERBOSE'}; +diag "set the next condition"; { ok($agent->form_name('BuildQuery'), "found the form again"); $agent->field("QueueOp", "!="); $agent->field("ValueOfQueue", "Regression"); $agent->submit; - is getQueryFromForm, "Owner = 'Nobody' AND Queue != 'Regression'", + is getQueryFromForm($agent), "Owner = 'Nobody' AND Queue != 'Regression'", 'correct query'; } -diag "We're going to delete the owner" if $ENV{'TEST_VERBOSE'}; +diag "We're going to delete the owner"; { $agent->select("clauses", ["0"] ); $agent->click("DeleteClause"); ok $agent->form_name('BuildQuery'), "found the form"; - is getQueryFromForm, "Queue != 'Regression'", 'correct query'; + is getQueryFromForm($agent), "Queue != 'Regression'", 'correct query'; } -diag "add a cond with OR and se number by the way" if $ENV{'TEST_VERBOSE'}; +diag "add a cond with OR and se number by the way"; { $agent->field("AndOr", "OR"); $agent->select("idOp", ">"); $agent->field("ValueOfid" => "1234"); $agent->click("AddClause"); ok $agent->form_name('BuildQuery'), "found the form again"; - is getQueryFromForm, "Queue != 'Regression' OR id > 1234", + is getQueryFromForm($agent), "Queue != 'Regression' OR id > 1234", "added something as OR, and number not quoted"; - is_deeply selectedClauses, ["1"], 'the id that we just entered is still selected'; + is_deeply selectedClauses($agent), ["1"], 'the id that we just entered is still selected'; } -diag "Move the second one up a level" if $ENV{'TEST_VERBOSE'}; +diag "Move the second one up a level"; { $agent->click("Up"); ok $agent->form_name('BuildQuery'), "found the form again"; - is getQueryFromForm, "id > 1234 OR Queue != 'Regression'", "moved up one"; - is_deeply selectedClauses, ["0"], 'the one we moved up is selected'; + is getQueryFromForm($agent), "id > 1234 OR Queue != 'Regression'", "moved up one"; + is_deeply selectedClauses($agent), ["0"], 'the one we moved up is selected'; } -diag "Move the second one right" if $ENV{'TEST_VERBOSE'}; +diag "Move the second one right"; { $agent->click("Right"); ok $agent->form_name('BuildQuery'), "found the form again"; - is getQueryFromForm, "Queue != 'Regression' OR ( id > 1234 )", + is getQueryFromForm($agent), "Queue != 'Regression' OR ( id > 1234 )", "moved over to the right (and down)"; - is_deeply selectedClauses, ["2"], 'the one we moved right is selected'; + is_deeply selectedClauses($agent), ["2"], 'the one we moved right is selected'; } -diag "Move the block up" if $ENV{'TEST_VERBOSE'}; +diag "Move the block up"; { $agent->select("clauses", ["1"]); $agent->click("Up"); ok $agent->form_name('BuildQuery'), "found the form again"; - is getQueryFromForm, "( id > 1234 ) OR Queue != 'Regression'", "moved up"; - is_deeply selectedClauses, ["0"], 'the one we moved up is selected'; + is getQueryFromForm($agent), "( id > 1234 ) OR Queue != 'Regression'", "moved up"; + is_deeply selectedClauses($agent), ["0"], 'the one we moved up is selected'; } -diag "Can not move up the top most clause" if $ENV{'TEST_VERBOSE'}; +diag "Can not move up the top most clause"; { $agent->select("clauses", ["0"]); $agent->click("Up"); ok $agent->form_name('BuildQuery'), "found the form again"; - $agent->content_like(qr/error: can\S+t move up/, "i shouldn't have been able to hit up"); - is_deeply selectedClauses, ["0"], 'the one we tried to move is selected'; + $agent->content_contains("error: can't move up", "i shouldn't have been able to hit up"); + is_deeply selectedClauses($agent), ["0"], 'the one we tried to move is selected'; } -diag "Can not move left the left most clause" if $ENV{'TEST_VERBOSE'}; +diag "Can not move left the left most clause"; { $agent->click("Left"); ok($agent->form_name('BuildQuery'), "found the form again"); - $agent->content_like(qr/error: can\S+t move left/, "i shouldn't have been able to hit left"); - is_deeply selectedClauses, ["0"], 'the one we tried to move is selected'; + $agent->content_contains("error: can't move left", "i shouldn't have been able to hit left"); + is_deeply selectedClauses($agent), ["0"], 'the one we tried to move is selected'; } -diag "Add a condition into a nested block" if $ENV{'TEST_VERBOSE'}; +diag "Add a condition into a nested block"; { $agent->select("clauses", ["1"]); $agent->select("ValueOfStatus" => "stalled"); $agent->submit; ok $agent->form_name('BuildQuery'), "found the form again"; - is_deeply selectedClauses, ["2"], 'the one we added is only selected'; - is getQueryFromForm, + is_deeply selectedClauses($agent), ["2"], 'the one we added is only selected'; + is getQueryFromForm($agent), "( id > 1234 AND Status = 'stalled' ) OR Queue != 'Regression'", "added new one"; } -diag "click advanced, enter 'C1 OR ( C2 AND C3 )', apply, aggregators should stay the same." - if $ENV{'TEST_VERBOSE'}; +diag "click advanced, enter 'C1 OR ( C2 AND C3 )', apply, aggregators should stay the same."; { my $response = $agent->get($url."Search/Edit.html"); ok( $response->is_success, "Fetched /Search/Edit.html" ); - ok($agent->form_number(3), "found the form"); + ok($agent->form_name('BuildQueryAdvanced'), "found the form"); $agent->field("Query", "Status = 'new' OR ( Status = 'open' AND Subject LIKE 'office' )"); $agent->submit; - is( getQueryFromForm, + is( getQueryFromForm($agent), "Status = 'new' OR ( Status = 'open' AND Subject LIKE 'office' )", "no aggregators change" ); @@ -194,11 +194,10 @@ diag "click advanced, enter 'C1 OR ( C2 AND C3 )', apply, aggregators should sta # - clears entire query # - clears it from the session, too -# }}} # create a custom field with nonascii name and try to add a condition { - my $cf = RT::CustomField->new( $RT::SystemUser ); + my $cf = RT::CustomField->new( RT->SystemUser ); $cf->LoadByName( Name => "\x{442}", Queue => 0 ); if ( $cf->id ) { is($cf->Type, 'Freeform', 'loaded and type is correct'); @@ -217,22 +216,21 @@ diag "click advanced, enter 'C1 OR ( C2 AND C3 )', apply, aggregators should sta ok($agent->form_name('BuildQuery'), "found the form once"); $agent->field("ValueOf'CF.{\x{442}}'", "\x{441}"); $agent->submit(); - is( getQueryFromForm, + is( getQueryFromForm($agent), "'CF.{\x{442}}' LIKE '\x{441}'", "no changes, no duplicate condition with badly encoded text" ); } -diag "input a condition, select (several conditions), click delete" - if $ENV{'TEST_VERBOSE'}; +diag "input a condition, select (several conditions), click delete"; { my $response = $agent->get( $url."Search/Edit.html" ); ok $response->is_success, "Fetched /Search/Edit.html"; - ok $agent->form_number(3), "found the form"; + ok $agent->form_name('BuildQueryAdvanced'), "found the form"; $agent->field("Query", "( Status = 'new' OR Status = 'open' )"); $agent->submit; - is( getQueryFromForm, + is( getQueryFromForm($agent), "( Status = 'new' OR Status = 'open' )", "query is the same" ); @@ -240,7 +238,7 @@ diag "input a condition, select (several conditions), click delete" $agent->field( ValueOfid => 10 ); $agent->click("DeleteClause"); - is( getQueryFromForm, + is( getQueryFromForm($agent), "id < 10", "replaced query successfuly" ); @@ -251,7 +249,7 @@ diag "send query with not quoted negative number"; my $response = $agent->get($url."Search/Build.html?Query=Priority%20>%20-2"); ok( $response->is_success, "Fetched " . $url."Search/Build.html" ); - is( getQueryFromForm, + is( getQueryFromForm($agent), "Priority > -2", "query is the same" ); @@ -261,7 +259,7 @@ diag "click advanced, enter an invalid SQL IS restriction, apply and check that { my $response = $agent->get($url."Search/Edit.html"); ok( $response->is_success, "Fetched /Search/Edit.html" ); - ok($agent->form_number(3), "found the form"); + ok($agent->form_name('BuildQueryAdvanced'), "found the form"); $agent->field("Query", "Requestor.EmailAddress IS 'FOOBAR'"); $agent->submit; is( getQueryFromForm($agent), @@ -274,7 +272,7 @@ diag "click advanced, enter an invalid SQL IS NOT restriction, apply and check t { my $response = $agent->get($url."Search/Edit.html"); ok( $response->is_success, "Fetched /Search/Edit.html" ); - ok($agent->form_number(3), "found the form"); + ok($agent->form_name('BuildQueryAdvanced'), "found the form"); $agent->field("Query", "Requestor.EmailAddress IS NOT 'FOOBAR'"); $agent->submit; is( getQueryFromForm($agent), @@ -283,3 +281,17 @@ diag "click advanced, enter an invalid SQL IS NOT restriction, apply and check t ); } +diag "click advanced, enter a valid SQL, but the field is lower cased"; +{ + my $response = $agent->get($url."Search/Edit.html"); + ok( $response->is_success, "Fetched /Search/Edit.html" ); + ok($agent->form_name('BuildQueryAdvanced'), "found the form"); + $agent->field("Query", "status = 'new'"); + $agent->submit; + $agent->content_lacks( 'Unknown field:', 'no "unknown field" warning' ); + is( getQueryFromForm($agent), + "Status = 'new'", + "field's case is corrected" + ); +} + diff --git a/rt/t/web/query_log.t b/rt/t/web/query_log.t new file mode 100644 index 000000000..e19f44dc6 --- /dev/null +++ b/rt/t/web/query_log.t @@ -0,0 +1,20 @@ +#!/usr/bin/perl +use strict; +use warnings; + +use RT::Test tests => 9; + +RT->Config->Set(StatementLog => 1); + +my ($baseurl, $m) = RT::Test->started_ok; +ok $m->login, 'logged in'; + +my $root = RT::User->new($RT::SystemUser); +$root->LoadByEmail('root@localhost'); + +$m->get_ok("/Admin/Tools/Queries.html"); +$m->text_contains("/index.html", "we include info about a page we hit while logging in"); +$m->text_contains("Stack:", "stack traces"); +$m->text_like(qr{share/html/autohandler:\d+}, "stack trace includes mason components"); +$m->text_contains("SELECT * FROM Principals WHERE id = '".$root->id."'", "we interpolate bind params"); + diff --git a/rt/t/web/queue_caching.t b/rt/t/web/queue_caching.t new file mode 100644 index 000000000..d90aacbdf --- /dev/null +++ b/rt/t/web/queue_caching.t @@ -0,0 +1,90 @@ +use strict; +use warnings; +use RT::Test tests => 36; + +# make an initial queue, so we have more than 1 +my $original_test_queue = new_queue("Test$$"); + +my ($baseurl, $m) = RT::Test->started_ok; +ok $m->login, 'logged in'; + +diag("Check for 2 existing queues being visible"); +{ + check_queues($m); +} + +diag("Add a new queue, which won't show up until we fix the cache"); +{ + new_queue("New Test $$"); + check_queues($m); +} + +diag("Disable an existing queue, it should stop appearing in the list"); +{ + ok($original_test_queue->SetDisabled(1)); + check_queues($m); +} + +diag("Bring back a disabled queue"); +{ + ok($original_test_queue->SetDisabled(0)); + check_queues($m); +} + +diag("Test a user who has more limited rights Queues"); +{ + +my $user_a = RT::Test->load_or_create_user( + Name => 'user_a', Password => 'password', +); +ok $user_a && $user_a->id, 'loaded or created user'; + +ok( RT::Test->set_rights( + { Principal => $user_a, Right => [qw(SeeQueue CreateTicket)], Object => $original_test_queue }, +), 'Allow user a to see the testing queue'); + +my $a_m = RT::Test::Web->new; +ok $a_m->login('user_a', 'password'), 'logged in as user A'; + +# check that they see a single queue +check_queues($a_m,[$original_test_queue->Id]); + +ok( RT::Test->add_rights( + { Principal => $user_a, Right => [qw(SeeQueue CreateTicket)] }, +), 'add global queue viewing rights'); + +check_queues($a_m); + +} + +sub new_queue { + my $name = shift; + my $new_queue = RT::Queue->new(RT->SystemUser); + ok($new_queue->Create( Name => $name, Description => "Testing for $name queue" ), "Created queue ".$new_queue->Name); + return $new_queue; +} + +sub internal_queues { + my $internal_queues = RT::Queues->new(RT->SystemUser); + $internal_queues->Limit(FIELD => 'Disabled', VALUE => 0); + my $queuelist; + while ( my $q = $internal_queues->Next ) { + $queuelist->{$q->Id} = $q->Name; + } + return $queuelist; +} + + +# takes a WWW::Mech object and an optional arrayref of queue ids +# compares the list of ids to the dropdown of Queues for the New Ticket In form +sub check_queues { + my $browser = shift; + my $queue_list = shift; + $browser->get_ok($baseurl,"Navigated to homepage"); + ok(my $form = $browser->form_name('CreateTicketInQueue'), "Found New Ticket In form"); + ok(my $queuelist = $form->find_input('Queue','option'), "Found queue select"); + my @queues = $queuelist->possible_values; + + $queue_list = [keys %{internal_queues()}] unless $queue_list; + is_deeply([sort @queues],[sort @$queue_list], "Queue list contains the expected queues"); +} diff --git a/rt/t/web/queue_create.t b/rt/t/web/queue_create.t new file mode 100644 index 000000000..3d2cd04d0 --- /dev/null +++ b/rt/t/web/queue_create.t @@ -0,0 +1,75 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use RT::Test tests => 13; + +my ( $baseurl, $m ) = RT::Test->started_ok; +ok $m->login, 'logged in as root'; +my $root = RT::User->new(RT->SystemUser); +ok( $root->Load('root'), 'load root user' ); + +my $queue_name = 'test queue'; + +my $queue_id; +diag "Create a queue"; +{ + $m->follow_link( id => 'tools-config-queues-create'); + + # Test queue form validation + $m->submit_form( + form_name => 'ModifyQueue', + fields => { + Name => '', + }, + ); + $m->text_contains('Queue name is required'); + $m->submit_form( + form_name => 'ModifyQueue', + fields => { + Name => '0', + }, + ); + $m->text_contains("'0' is not a valid name"); + $m->submit_form( + form_name => 'ModifyQueue', + fields => { + Name => '1', + }, + ); + $m->text_contains("'1' is not a valid name"); + $m->submit_form( + form_name => 'ModifyQueue', + fields => { + Name => $queue_name, + }, + ); + $m->content_contains('Queue created', 'created queue sucessfully' ); + + # Test validation on update + $m->form_name('ModifyQueue'); + $m->set_fields( + Name => '', + ); + $m->click_button(value => 'Save Changes'); + $m->content_contains('Illegal value for Name'); + + $m->form_name('ModifyQueue'); + $m->set_fields( + Name => '0', + ); + $m->click_button(value => 'Save Changes'); + $m->content_contains('Illegal value for Name'); + + $m->form_name('ModifyQueue'); + $m->set_fields( + Name => '1', + ); + $m->click_button(value => 'Save Changes'); + $m->content_contains('Illegal value for Name'); + + $queue_id = $m->form_name('ModifyQueue')->value('id'); + ok $queue_id, "found id of the queue in the form, it's #$queue_id"; +} + diff --git a/rt/t/web/quickcreate.t b/rt/t/web/quickcreate.t new file mode 100644 index 000000000..b257f9ddd --- /dev/null +++ b/rt/t/web/quickcreate.t @@ -0,0 +1,37 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +use RT::Test tests => 11; + +RT->Config->Set('DisplayTicketAfterQuickCreate' => 0); + +my ($baseurl, $m) = RT::Test->started_ok; + +ok($m->login, 'logged in'); + +$m->form_with_fields('Subject', 'Content'); +$m->field(Subject => 'from quick create'); +$m->submit; + +$m->content_like(qr/Ticket \d+ created in queue/, 'created ticket'); +like( $m->uri, qr{^\Q$baseurl\E/(?:index\.html)?\?results=}, 'still in homepage' ); +unlike( $m->uri, qr{Ticket/Display.html}, 'not on ticket display page' ); + +$m->get_ok($baseurl . '/Prefs/Other.html'); +$m->submit_form( + form_name => 'ModifyPreferences', + fields => { 'DisplayTicketAfterQuickCreate' => 1, }, + button => 'Update', +); + +$m->content_contains( 'Preferences saved', + 'enabled DisplayTicketAfterQuickCreate' ); +$m->get($baseurl); + +$m->form_with_fields('Subject', 'Content'); +$m->field(Subject => 'from quick create'); +$m->submit; + +$m->content_like(qr/Ticket \d+ created in queue/, 'created ticket'); +like( $m->uri, qr!/Ticket/Display.html!, 'still in homepage' ); diff --git a/rt/t/web/quicksearch.t b/rt/t/web/quicksearch.t index cd9a8e76c..8cc084ce5 100644 --- a/rt/t/web/quicksearch.t +++ b/rt/t/web/quicksearch.t @@ -2,12 +2,12 @@ use strict; use warnings; -use RT::Test tests => 7; +use RT::Test tests => 9; my ($baseurl, $m) = RT::Test->started_ok; my $url = $m->rt_base_url; # merged tickets still show up in search -my $t1 = RT::Ticket->new($RT::SystemUser); +my $t1 = RT::Ticket->new(RT->SystemUser); $t1->Create( Subject => 'base ticket'.$$, Queue => 'general', @@ -22,7 +22,7 @@ $t1->Create( ); ok(my $id1 = $t1->id, 'created ticket for custom search'); -my $t2 = RT::Ticket->new($RT::SystemUser); +my $t2 = RT::Ticket->new(RT->SystemUser); $t2->Create( Subject => 'merged away'.$$, Queue => 'general', diff --git a/rt/t/web/redirect-after-login.t b/rt/t/web/redirect-after-login.t index d39bb58c8..d429d30d1 100644 --- a/rt/t/web/redirect-after-login.t +++ b/rt/t/web/redirect-after-login.t @@ -3,7 +3,9 @@ use strict; use warnings; -use RT::Test tests => 120; +use RT::Test tests => 122; + +RT->Config->Set( GnuPG => Enable => 0 ); my ($baseurl, $agent) = RT::Test->started_ok; @@ -51,11 +53,9 @@ diag $url if $ENV{TEST_VERBOSE}; ok( $agent->content =~ /Your username or password is incorrect/i, "Found the error message"); like( $agent->uri, qr{/NoAuth/Login\.html$}, "now on /NoAuth/Login.html" ); - $agent->logout(); - - # Handle the warning after we're done with the page, since this leaves us - # with a completely different $mech $agent->warning_like(qr/FAILED LOGIN for root/, "got failed login warning"); + + $agent->logout(); } # test a login from a non-front page, both with a double leading slash and without @@ -116,6 +116,7 @@ for my $path (qw(Prefs/Other.html /Prefs/Other.html)) { ok( $agent->content =~ /Your username or password is incorrect/i, "Found the error message"); like( $agent->uri, qr{/NoAuth/Login\.html$}, "still on /NoAuth/Login.html" ); + $agent->warning_like(qr/FAILED LOGIN for root/, "got failed login warning"); # try to login again ok($agent->current_form->find_input('user')); @@ -136,10 +137,6 @@ for my $path (qw(Prefs/Other.html /Prefs/Other.html)) { is( $agent->uri, $requested, "right URL" ); like( $agent->{redirected_uri}, qr{/NoAuth/Login\.html}, "We redirected from login"); $agent->logout(); - - # Handle the warning after we're done with the page, since this leaves us - # with a completely different $mech - $agent->warning_like(qr/FAILED LOGIN for root/, "got failed login warning"); } # test a login from the main page with query params @@ -163,9 +160,6 @@ for my $path (qw(Prefs/Other.html /Prefs/Other.html)) { ok($agent->current_form->find_input('user')); ok($agent->current_form->find_input('pass')); like($agent->current_form->action, qr{/NoAuth/Login\.html$}, "login form action is correct"); - - # Handle the warning after we're done with the page, since this leaves us - # with a completely different $mech $agent->warning_like(qr/FAILED LOGIN for root/, "got failed login warning"); } @@ -183,6 +177,7 @@ for my $path (qw(Prefs/Other.html /Prefs/Other.html)) { ok($agent->current_form->find_input('next')); like($agent->value('next'), qr/^[a-z0-9]{32}$/i, "next page argument is a hash"); like($agent->current_form->action, qr{/NoAuth/Login\.html$}, "login form action is correct"); + $agent->warning_like(qr/FAILED LOGIN for root/, "got failed login warning"); # Try to login again ok($agent->content =~ /username:/i); @@ -197,10 +192,6 @@ for my $path (qw(Prefs/Other.html /Prefs/Other.html)) { is( $agent->uri, $requested, "right URL" ); like( $agent->{redirected_uri}, qr{/NoAuth/Login\.html}, "We redirected from login"); $agent->logout(); - - # Handle the warning after we're done with the page, since this leaves us - # with a completely different $mech - $agent->warning_like(qr/FAILED LOGIN for root/, "got failed login warning"); } # test REST login response @@ -221,9 +212,6 @@ for my $path (qw(Prefs/Other.html /Prefs/Other.html)) { is($agent->uri, $requested, "didn't redirect to /NoAuth/Login.html for REST"); like($agent->content, qr/401 Credentials required/i, "got error status"); like($agent->content, qr/Your username or password is incorrect/, "got error message"); - - # Handle the warning after we're done with the page, since this leaves us - # with a completely different $mech $agent->warning_like(qr/FAILED LOGIN for root/, "got failed login warning"); } diff --git a/rt/t/web/redirect.t b/rt/t/web/redirect.t new file mode 100644 index 000000000..d92386bb8 --- /dev/null +++ b/rt/t/web/redirect.t @@ -0,0 +1,106 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use RT::Test tests => 13; + +my $r = $HTML::Mason::Commands::r = bless {}, 'R'; +my $m = $HTML::Mason::Commands::m = bless {}, 'M'; + +set_config( + CanonicalizeRedirectURLs => 0, + WebDomain => 'localhost', + WebPort => 80, + WebPath => '', +); +is( RT->Config->Get('WebBaseURL'), 'http://localhost' ); +is( RT->Config->Get('WebURL'), 'http://localhost/' ); + +redirect_ok( + 'http://localhost/Ticket/', 'http://localhost/Ticket/', + { SERVER_NAME => 'localhost', SERVER_PORT => 80 }, +); +redirect_ok( + '/Ticket/', 'http://localhost/Ticket/', + { SERVER_NAME => 'localhost', SERVER_PORT => 80 }, +); +redirect_ok( + 'http://localhost/Ticket/', 'http://example.com/Ticket/', + { SERVER_NAME => 'example.com', SERVER_PORT => 80 }, +); + +set_config( + CanonicalizeRedirectURLs => 0, + WebDomain => 'localhost', + WebPort => 443, + WebPath => '', +); +is( RT->Config->Get('WebBaseURL'), 'https://localhost' ); +is( RT->Config->Get('WebURL'), 'https://localhost/' ); + +redirect_ok( + 'https://localhost/Ticket/', 'https://localhost/Ticket/', + { SERVER_NAME => 'localhost', SERVER_PORT => 443, HTTPS => 'on' }, +); +redirect_ok( + '/Ticket/', 'https://localhost/Ticket/', + { SERVER_NAME => 'localhost', SERVER_PORT => 443, HTTPS => 'on' }, +); +redirect_ok( + 'https://localhost/Ticket/', 'http://localhost/Ticket/', + { SERVER_NAME => 'localhost', SERVER_PORT => 80 }, +); +redirect_ok( + '/Ticket/', 'http://localhost/Ticket/', + { SERVER_NAME => 'localhost', SERVER_PORT => 80 }, +); +redirect_ok( + 'https://localhost/Ticket/', 'http://example.com/Ticket/', + { SERVER_NAME => 'example.com', SERVER_PORT => 80 }, +); +redirect_ok( + 'https://localhost/Ticket/', 'https://example.com/Ticket/', + { SERVER_NAME => 'example.com', SERVER_PORT => 443, HTTPS => 'on' }, +); + +sub set_config { + my %values = @_; + while ( my ($k, $v) = each %values ) { + RT->Config->Set( $k => $v ); + } + + unless ( $values{'WebBaseURL'} ) { + my $port = RT->Config->Get('WebPort'); + RT->Config->Set( + WebBaseURL => + ($port == 443? 'https': 'http') .'://' + . RT->Config->Get('WebDomain') + . ($port != 80 && $port != 443? ":$port" : '') + ); + } + unless ( $values{'WebURL'} ) { + RT->Config->Set( + WebURL => RT->Config->Get('WebBaseURL') . RT->Config->Get('WebPath') . "/" + ); + } +} + +sub redirect_ok { + my ($to, $expected, $env, $details) = @_; + + local %ENV = %ENV; + while ( my ($k, $v) = each %{ $env || {} } ) { + $ENV{ $k } = $v; + } + RT::Interface::Web::Redirect( $to ); + is($m->redirect, $expected, $details || "correct for '$to'"); +} + +package R; +sub status {}; + +package M; +sub redirect { $_[0]{'last'} = $_[1] if @_ > 1; return $_[0]{'last'} } +sub abort {} + diff --git a/rt/t/web/reminders.t b/rt/t/web/reminders.t new file mode 100644 index 000000000..32e130c47 --- /dev/null +++ b/rt/t/web/reminders.t @@ -0,0 +1,88 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use RT::Test tests => 35; + +my ($baseurl, $m) = RT::Test->started_ok; + +ok($m->login, 'logged in'); +my $user = RT::CurrentUser->new('root'); + +my $ticket = RT::Ticket->new($user); +$ticket->Create(Subject => 'testing reminders!', Queue => 'General'); +ok($ticket->id, 'created a ticket'); + +$m->goto_ticket($ticket->id); +$m->text_contains('New reminder:', 'can create a new reminder'); +$m->content_unlike(qr{Check box to complete}, "we don't display this text when there are no reminders"); +$m->content_unlike(qr{<th[^>]*>Reminders?</th>}, "no reminder titlebar"); + +$m->follow_link_ok({id => 'page-reminders'}); +$m->title_is("Reminders for ticket #" . $ticket->id); +$m->text_contains('New reminder:', 'can create a new reminder'); +$m->content_unlike(qr{Check box to complete}, "we don't display this text when there are no reminders"); +$m->content_unlike(qr{<th[^>]*>Reminders?</th>}, "no reminder titlebar"); + +$m->goto_ticket($ticket->id); +$m->form_name('UpdateReminders'); +$m->field( 'NewReminder-Subject' => "baby's first reminder" ); +$m->submit; + +my $reminders = RT::Reminders->new($user); +$reminders->Ticket($ticket->id); +my $col = $reminders->Collection; +is($col->Count, 1, 'got a reminder'); +my $reminder = $col->First; +is($reminder->Subject, "baby's first reminder"); +my $reminder_id = $reminder->id; +is($reminder->Status, 'new'); + +$m->text_contains('New reminder:', 'can create a new reminder'); +$m->text_contains('Check box to complete', "we DO display this text when there are reminders"); +$m->content_like(qr{<th[^>]*>Reminders?</th>}, "now we have a reminder titlebar"); +$m->text_contains("baby's first reminder", "display the reminder's subject"); + +$m->follow_link_ok({id => 'page-reminders'}); +$m->title_is("Reminders for ticket #" . $ticket->id); +$m->form_name('UpdateReminders'); +$m->field("Reminder-Subject-$reminder_id" => "changed the subject"); +$m->submit; + +DBIx::SearchBuilder::Record::Cachable->FlushCache; +$reminder = RT::Ticket->new($user); +$reminder->Load($reminder_id); +is($reminder->Subject, 'changed the subject'); +is($reminder->Status, 'new'); + +$m->goto_ticket($ticket->id); +$m->form_name('UpdateReminders'); +$m->tick("Complete-Reminder-$reminder_id" => 1); +$m->submit; + +DBIx::SearchBuilder::Record::Cachable->FlushCache; +$reminder = RT::Ticket->new($user); +$reminder->Load($reminder_id); +is($reminder->Status, 'resolved'); + +$m->text_contains('New reminder:', 'can create a new reminder'); +$m->content_unlike(qr{Check box to complete}, "we don't display this text when there are open reminders"); +$m->content_unlike(qr{<th[^>]*>Reminders?</th>}, "no reminder titlebar"); +$m->content_unlike(qr{baby's first reminder}, "we don't display resolved reminders"); + +$m->follow_link_ok({id => 'page-reminders'}); +$m->title_is("Reminders for ticket #" . $ticket->id); +$m->text_contains('New reminder:', 'can create a new reminder'); +$m->text_contains('Check box to complete', "we DO display this text when there are reminders"); +$m->content_contains("changed the subject", "display the resolved reminder's subject"); + +# make sure that when we submit the form, it doesn't accidentally reopen +# resolved reminders +$m->goto_ticket($ticket->id); +$m->form_name('UpdateReminders'); +$m->submit; + +DBIx::SearchBuilder::Record::Cachable->FlushCache; +$reminder = RT::Ticket->new($user); +$reminder->Load($reminder_id); +is($reminder->Status, 'resolved'); + diff --git a/rt/t/web/remote_user.t b/rt/t/web/remote_user.t new file mode 100644 index 000000000..edad6ef95 --- /dev/null +++ b/rt/t/web/remote_user.t @@ -0,0 +1,36 @@ +use strict; +use warnings; +use RT; +use RT::Test tests => 9; +use MIME::Base64 qw//; + +RT->Config->Set( DevelMode => 0 ); +RT->Config->Set( WebExternalAuth => 1 ); + +sub auth { + return Authorization => "Basic " . + MIME::Base64::encode( join(":", @_) ); +} + +my ( $url, $m ) = RT::Test->started_ok( basic_auth => 1 ); +$m->get($url); +is($m->status, 401, "Initial request with no creds gets 401"); + +$m->get($url, auth( root => "wrong" )); +is($m->status, 401, "Request with wrong creds gets 401"); + +$m->get($url, auth( root => "password" )); +is($m->status, 200, "Request with right creds gets 200"); + +$m->content_like( + qr{<span class="current-user">\Qroot\E</span>}i, + "Has user on the page" +); +$m->content_unlike(qr/Logout/i, "Has no logout button, no WebFallbackToInternalAuth"); + +$m->get($url); +is($m->status, 401, "Subsequent requests without credentials aren't still logged in"); + + +# Put the credentials back for the warnings check at the end +$m->default_header( auth( root => "password" )); diff --git a/rt/t/web/requestor_groups_edit_link.t b/rt/t/web/requestor_groups_edit_link.t new file mode 100644 index 000000000..9d1fefd5c --- /dev/null +++ b/rt/t/web/requestor_groups_edit_link.t @@ -0,0 +1,56 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use RT::Test tests => 11; + +RT->Config->Set( ShowMoreAboutPrivilegedUsers => 1 ); + +my ( $url, $m ) = RT::Test->started_ok; +my $user_a = RT::Test->load_or_create_user( + Name => 'user_a', + Password => 'password', +); +ok( $user_a, 'created user user_a' ); +ok( + RT::Test->set_rights( + { + Principal => $user_a, + Right => [ qw/SeeQueue ShowTicket CreateTicket/ ] + }, + ), + 'set rights for user_a' +); + +my $ticket = RT::Ticket->new(RT->SystemUser); +my ($id) = $ticket->Create( + Subject => 'groups limit', + Queue => 'General', + Requestor => $user_a->id, +); +ok( $id, 'created ticket' ); + + +ok( $m->login( user_a => 'password' ), 'logged in as user_a' ); + +$m->goto_ticket($id); + +ok( + !$m->find_link( text => 'Edit' ), 'no Edit link without AdminUsers permission' +); + +ok( + RT::Test->add_rights( + { + Principal => $user_a, + Right => [ qw/AdminUsers ShowConfigTab/ ] + }, + ), + 'add AdminUsers and ShowConfigTab rights for user_a' +); + +$m->goto_ticket($id); +$m->follow_link_ok( { text => 'Edit' }, 'follow the Edit link' ); +is( $m->uri, $url . "/Admin/Users/Memberships.html?id=" . $user_a->id, 'url is right' ); + diff --git a/rt/t/web/requestor_groups_limit.t b/rt/t/web/requestor_groups_limit.t new file mode 100644 index 000000000..7987a136c --- /dev/null +++ b/rt/t/web/requestor_groups_limit.t @@ -0,0 +1,36 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use RT::Test tests => 11; + +diag "set groups limit to 1"; +RT->Config->Set( ShowMoreAboutPrivilegedUsers => 1 ); +RT->Config->Set( MoreAboutRequestorGroupsLimit => 1 ); + +my $ticket = RT::Ticket->new(RT->SystemUser); +my ($id) = $ticket->Create( + Subject => 'groups limit', + Queue => 'General', + Requestor => 'root@localhost', +); +ok( $id, 'created ticket' ); + +my ( $url, $m ) = RT::Test->started_ok; +ok( $m->login(), 'logged in as root' ); +$m->goto_ticket($id); +$m->content_like( qr/Everyone|Privileged/, 'got one group' ); +$m->content_unlike( qr/Everyone.*?Privileged/, 'not 2 groups' ); + +RT::Test->stop_server; + +diag "set groups limit to 2"; + +RT->Config->Set( MoreAboutRequestorGroupsLimit => 2 ); +( $url, $m ) = RT::Test->started_ok; +ok( $m->login(), 'logged in as root' ); +$m->goto_ticket($id); +$m->content_contains( 'Everyone', 'got the first group' ); +$m->content_contains( 'Privileged', 'got the second group' ); + diff --git a/rt/t/web/rest-non-ascii-subject.t b/rt/t/web/rest-non-ascii-subject.t index 371b2ffc0..d7a89af5e 100644 --- a/rt/t/web/rest-non-ascii-subject.t +++ b/rt/t/web/rest-non-ascii-subject.t @@ -2,9 +2,7 @@ # Test ticket creation with REST using non ascii subject use strict; use warnings; -use RT::Test tests => 7; - -local $RT::Test::SKIP_REQUEST_WORK_AROUND = 1; +use RT::Test tests => 9; use Encode; # \x{XX} where XX is less than 255 is not treated as unicode code point @@ -42,7 +40,7 @@ $m->post("$baseurl/REST/1.0/ticket/new", [ my ($id) = $m->content =~ /Ticket (\d+) created/; ok($id, "got ticket #$id"); -my $ticket = RT::Ticket->new($RT::SystemUser); +my $ticket = RT::Ticket->new(RT->SystemUser); $ticket->Load($id); is($ticket->Id, $id, "loaded the REST-created ticket"); is($ticket->Subject, $subject, "ticket subject successfully set"); diff --git a/rt/t/web/rest-sort.t b/rt/t/web/rest-sort.t new file mode 100644 index 000000000..6b4d35169 --- /dev/null +++ b/rt/t/web/rest-sort.t @@ -0,0 +1,46 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use RT::Test tests => 25; + +my ($baseurl, $m) = RT::Test->started_ok; + +RT::Test->create_tickets( + { }, + { Subject => 'uno' }, + { Subject => 'dos' }, + { Subject => 'tres' }, +); + +ok($m->login, 'logged in'); + +sorted_tickets_ok('Subject', ['2: dos', '3: tres', '1: uno']); +sorted_tickets_ok('+Subject', ['2: dos', '3: tres', '1: uno']); +sorted_tickets_ok('-Subject', ['1: uno', '3: tres', '2: dos']); + +sorted_tickets_ok('id', ['1: uno', '2: dos', '3: tres']); +sorted_tickets_ok('+id', ['1: uno', '2: dos', '3: tres']); +sorted_tickets_ok('-id', ['3: tres', '2: dos', '1: uno']); + +undef $m; + +sub sorted_tickets_ok { + local $Test::Builder::Level = $Test::Builder::Level + 1; + my $order = shift; + my $expected = shift; + + my $query = 'id > 0'; + + my $uri = URI->new("$baseurl/REST/1.0/search/ticket"); + $uri->query_form( + query => $query, + orderby => $order, + ); + $m->get_ok($uri); + + my @lines = split /\n/, $m->content; + shift @lines; # header + shift @lines; # empty line + + is_deeply(\@lines, $expected, "sorted results by '$order'"); +} diff --git a/rt/t/web/rest.t b/rt/t/web/rest.t index b3a7c558b..5e7194c95 100644 --- a/rt/t/web/rest.t +++ b/rt/t/web/rest.t @@ -1,7 +1,7 @@ #!/usr/bin/env perl use strict; use warnings; -use RT::Test tests => 16; +use RT::Test tests => 18; my ($baseurl, $m) = RT::Test->started_ok; @@ -46,7 +46,7 @@ $m->post("$baseurl/REST/1.0/ticket/edit", [ my ($id) = $m->content =~ /Ticket (\d+) created/; ok($id, "got ticket #$id"); -my $ticket = RT::Ticket->new($RT::SystemUser); +my $ticket = RT::Ticket->new(RT->SystemUser); $ticket->Load($id); is($ticket->Id, $id, "loaded the REST-created ticket"); is($ticket->Subject, "REST interface", "subject successfully set"); diff --git a/rt/t/web/richtext-autohandler.t b/rt/t/web/richtext-autohandler.t index 56617b2fb..734426fc3 100644 --- a/rt/t/web/richtext-autohandler.t +++ b/rt/t/web/richtext-autohandler.t @@ -1,13 +1,13 @@ use strict; -use RT::Test tests => 7; +use RT::Test tests => 9; my ($baseurl, $agent) = RT::Test->started_ok; -$agent->get("$baseurl/NoAuth/RichText/FCKeditor/license.txt"); +$agent->get("$baseurl/NoAuth/RichText/ckeditor/config.js"); is($agent->status, 403); -$agent->content_lacks("It is not the purpose of this section to induce"); +$agent->content_lacks("config.disableNativeSpellChecker"); -$agent->get_ok("/NoAuth/RichText/license.txt"); -$agent->content_contains("It is not the purpose of this section to induce"); +$agent->get_ok("/NoAuth/RichText/config.js"); +$agent->content_contains("config.disableNativeSpellChecker"); $agent->warning_like(qr/Invalid request directly to the rich text editor/,); diff --git a/rt/t/web/rights.t b/rt/t/web/rights.t index b47ba99af..9a5f358e2 100644 --- a/rt/t/web/rights.t +++ b/rt/t/web/rights.t @@ -7,34 +7,32 @@ use RT::Test tests => 14; my ($baseurl, $m) = RT::Test->started_ok; ok $m->login, "logged in"; -$m->follow_link_ok({ text => 'Configuration' }); -$m->follow_link_ok({ text => 'Global' }); -$m->follow_link_ok({ text => 'Group Rights' }); +$m->follow_link_ok({ id => 'tools-config-global-group-rights'}); sub get_rights { my $agent = shift; my $principal_id = shift; my $object = shift; - $agent->form_number(3); - my @inputs = $agent->current_form->find_input("RevokeRight-$principal_id-$object"); - my @rights = sort grep $_, map $_->possible_values, grep $_, @inputs; + $agent->form_name('ModifyGroupRights'); + my @inputs = $agent->current_form->find_input("SetRights-$principal_id-$object"); + my @rights = sort grep $_, map $_->possible_values, grep $_ && $_->value, @inputs; return @rights; }; -diag "load Everyone group" if $ENV{'TEST_VERBOSE'}; +diag "load Everyone group"; my ($everyone, $everyone_gid); { - $everyone = RT::Group->new( $RT::SystemUser ); + $everyone = RT::Group->new( RT->SystemUser ); $everyone->LoadSystemInternalGroup('Everyone'); ok($everyone_gid = $everyone->id, "loaded 'everyone' group"); } -diag "revoke all global rights from Everyone group" if $ENV{'TEST_VERBOSE'}; +diag "revoke all global rights from Everyone group"; my @has = get_rights( $m, $everyone_gid, 'RT::System-1' ); if ( @has ) { - $m->form_number(3); - $m->tick("RevokeRight-$everyone_gid-RT::System-1", $_) foreach @has; + $m->form_name('ModifyGroupRights'); + $m->untick("SetRights-$everyone_gid-RT::System-1", $_) foreach @has; $m->submit; is_deeply([get_rights( $m, $everyone_gid, 'RT::System-1' )], [], 'deleted all rights' ); @@ -42,10 +40,10 @@ if ( @has ) { ok(1, 'the group has no global rights'); } -diag "grant SuperUser right to everyone" if $ENV{'TEST_VERBOSE'}; +diag "grant SuperUser right to everyone"; { - $m->form_number(3); - $m->select("GrantRight-$everyone_gid-RT::System-1", ['SuperUser']); + $m->form_name('ModifyGroupRights'); + $m->tick("SetRights-$everyone_gid-RT::System-1", 'SuperUser'); $m->submit; $m->content_contains('Right Granted', 'got message'); @@ -54,10 +52,10 @@ diag "grant SuperUser right to everyone" if $ENV{'TEST_VERBOSE'}; is_deeply( [get_rights( $m, $everyone_gid, 'RT::System-1' )], ['SuperUser'], 'granted SuperUser right' ); } -diag "revoke the right" if $ENV{'TEST_VERBOSE'}; +diag "revoke the right"; { - $m->form_number(3); - $m->tick("RevokeRight-$everyone_gid-RT::System-1", 'SuperUser'); + $m->form_name('ModifyGroupRights'); + $m->untick("SetRights-$everyone_gid-RT::System-1", 'SuperUser'); $m->submit; $m->content_contains('Right revoked', 'got message'); @@ -67,10 +65,10 @@ diag "revoke the right" if $ENV{'TEST_VERBOSE'}; } -diag "return rights the group had in the beginning" if $ENV{'TEST_VERBOSE'}; +diag "return rights the group had in the beginning"; if ( @has ) { - $m->form_number(3); - $m->select("GrantRight-$everyone_gid-RT::System-1", \@has); + $m->form_name('ModifyGroupRights'); + $m->tick("SetRights-$everyone_gid-RT::System-1", $_) for @has; $m->submit; $m->content_contains('Right Granted', 'got message'); diff --git a/rt/t/web/rights1.t b/rt/t/web/rights1.t index c8892f2fe..24e5c3448 100644 --- a/rt/t/web/rights1.t +++ b/rt/t/web/rights1.t @@ -2,11 +2,11 @@ use strict; use HTTP::Cookies; -use RT::Test tests => 29; +use RT::Test nodata => 1, tests => 31; my ($baseurl, $agent) = RT::Test->started_ok; # Create a user with basically no rights, to start. -my $user_obj = RT::User->new($RT::SystemUser); +my $user_obj = RT::User->new(RT->SystemUser); my ($ret, $msg) = $user_obj->LoadOrCreateByEmail('customer-'.$$.'@example.com'); ok($ret, 'ACL test user creation'); $user_obj->SetName('customer-'.$$); @@ -24,7 +24,6 @@ my $cookie_jar = HTTP::Cookies->new; $agent->cookie_jar($cookie_jar); -no warnings 'once'; # get the top page $agent->login( $user_obj->Name, 'customer'); @@ -36,13 +35,13 @@ ok(!$agent->find_link( url => "$RT::WebPath/User/Prefs.html", # Now test for their presence, one at a time. Sleep for a bit after # ACL changes, thanks to the 10s ACL cache. -my ($grantid,$grantmsg) =$user_obj->PrincipalObj->GrantRight(Right => 'ShowConfigTab', Object => $RT::System); +my ($grantid,$grantmsg) =$user_obj->PrincipalObj->GrantRight(Right => 'ShowConfigTab', Object => RT->System); ok($grantid,$grantmsg); $agent->reload; -like($agent->{'content'} , qr/Logout/i, "Reloaded page successfully"); +$agent->content_contains('Logout', "Reloaded page successfully"); ok($agent->find_link( url => "$RT::WebPath/Admin/", text => 'Configuration'), "Found config tab" ); my ($revokeid,$revokemsg) =$user_obj->PrincipalObj->RevokeRight(Right => 'ShowConfigTab'); @@ -50,41 +49,40 @@ ok ($revokeid,$revokemsg); ($grantid,$grantmsg) =$user_obj->PrincipalObj->GrantRight(Right => 'ModifySelf'); ok ($grantid,$grantmsg); $agent->reload(); -like($agent->{'content'} , qr/Logout/i, "Reloaded page successfully"); +$agent->content_contains('Logout', "Reloaded page successfully"); ok($agent->find_link( - text => 'Preferences'), "Found prefs pane" ); + id => 'preferences-settings' ), "Found prefs pane" ); ($revokeid,$revokemsg) = $user_obj->PrincipalObj->RevokeRight(Right => 'ModifySelf'); ok ($revokeid,$revokemsg); # Good. Now load the search page and test Load/Save Search. $agent->follow_link( url => "$RT::WebPath/Search/Build.html", text => 'Tickets'); -is($agent->{'status'}, 200, "Fetched search builder page"); -ok($agent->{'content'} !~ /Load saved search/i, "No search loading box"); -ok($agent->{'content'} !~ /Saved searches/i, "No saved searches box"); +is($agent->status, 200, "Fetched search builder page"); +$agent->content_lacks("Load saved search", "No search loading box"); +$agent->content_lacks("Saved searches", "No saved searches box"); ($grantid,$grantmsg) = $user_obj->PrincipalObj->GrantRight(Right => 'LoadSavedSearch'); ok($grantid,$grantmsg); $agent->reload(); -like($agent->{'content'} , qr/Load saved search/i, "Search loading box exists"); -ok($agent->{'content'} !~ /input\s+type=['"]submit['"][^>]+name=['"]SavedSearchSave['"]/i, +$agent->content_contains("Load saved search", "Search loading box exists"); +$agent->content_unlike(qr/input\s+type=['"]submit['"][^>]+name=['"]SavedSearchSave['"]/i, "Still no saved searches box"); ($grantid,$grantmsg) =$user_obj->PrincipalObj->GrantRight(Right => 'CreateSavedSearch'); ok ($grantid,$grantmsg); $agent->reload(); -like($agent->{'content'} , qr/Load saved search/i, - "Search loading box still exists"); -like($agent->{'content'} , qr/input\s+type=['"]submit['"][^>]+name=['"]SavedSearchSave['"]/i, +$agent->content_contains("Load saved search", "Search loading box still exists"); +$agent->content_like(qr/input\s+type=['"]submit['"][^>]+name=['"]SavedSearchSave['"]/i, "Saved searches box exists"); # Create a group, and a queue, so we can test limited user visibility # via SelectOwner. -my $queue_obj = RT::Queue->new($RT::SystemUser); +my $queue_obj = RT::Queue->new(RT->SystemUser); ($ret, $msg) = $queue_obj->Create(Name => 'CustomerQueue-'.$$, Description => 'queue for SelectOwner testing'); ok($ret, "SelectOwner test queue creation. $msg"); -my $group_obj = RT::Group->new($RT::SystemUser); +my $group_obj = RT::Group->new(RT->SystemUser); ($ret, $msg) = $group_obj->CreateUserDefinedGroup(Name => 'CustomerGroup-'.$$, Description => 'group for SelectOwner testing'); ok($ret, "SelectOwner test group creation. $msg"); @@ -107,4 +105,3 @@ ok($agent->form_name('BuildQuery'), "Yep, form is still there"); my $input = $agent->current_form->find_input('ValueOfActor'); ok(grep(/customer-$$/, $input->value_names()), "Found self in the actor listing"); -1; diff --git a/rt/t/web/saved_search_chart.t b/rt/t/web/saved_search_chart.t index 105166233..f84307162 100644 --- a/rt/t/web/saved_search_chart.t +++ b/rt/t/web/saved_search_chart.t @@ -2,11 +2,12 @@ use strict; use warnings; -use RT::Test tests => 19; +use RT::Test no_plan => 1; my ( $url, $m ) = RT::Test->started_ok; use RT::Attribute; -my $search = RT::Attribute->new($RT::SystemUser); -my $ticket = RT::Ticket->new($RT::SystemUser); + +my $search = RT::Attribute->new(RT->SystemUser); +my $ticket = RT::Ticket->new(RT->SystemUser); my ( $ret, $msg ) = $ticket->Create( Subject => 'base ticket' . $$, Queue => 'general', @@ -35,7 +36,7 @@ $m->submit_form( button => 'SavedSearchSave', ); -$m->content_like( qr/Chart first chart saved/, 'saved first chart' ); +$m->content_contains("Chart first chart saved", 'saved first chart' ); my ( $search_uri, $id ) = $m->content =~ /value="(RT::User-\d+-SavedSearch-(\d+))"/; $m->submit_form( @@ -64,8 +65,8 @@ $m->submit_form( button => 'SavedSearchSave', ); -$m->content_like( qr/Chart first chart updated/, 'found updated message' ); -$m->content_like( qr/id=2/, 'Query is updated' ); +$m->content_contains("Chart first chart updated", 'found updated message' ); +$m->content_contains("id=2", 'Query is updated' ); $m->content_like( qr/value="Status"\s+selected="selected"/, 'PrimaryGroupBy is updated' ); $m->content_like( qr/value="pie"\s+selected="selected"/, @@ -81,6 +82,73 @@ $m->submit_form( form_name => 'SaveSearch', button => 'SavedSearchDelete', ); -$m->content_like( qr/Chart first chart deleted/, 'found deleted message' ); +$m->content_contains("Chart first chart deleted", 'found deleted message' ); $m->content_unlike( qr/value="RT::User-\d+-SavedSearch-\d+"/, 'no saved search' ); + +for ('A' .. 'F') { + $ticket->Create( + Subject => $$ . $_, + ); +} + +for ([A => 'subject="'.$$.'A"'], [BorC => 'subject="'.$$.'B" OR subject="'.$$.'C"']) { + $m->get_ok('/Search/Edit.html'); + $m->form_name('BuildQueryAdvanced'); + $m->field('Query', $_->[1]); + $m->submit; + + # Save the search + $m->follow_link_ok({id => 'page-chart'}); + $m->form_name('SaveSearch'); + $m->field(SavedSearchDescription => $_->[0]); + $m->click_ok('SavedSearchSave'); + $m->text_contains('Chart ' . $_->[0] . ' saved.'); + +} + +$m->form_name('SaveSearch'); +my @saved_search_ids = + $m->current_form->find_input('SavedSearchLoad')->possible_values; +shift @saved_search_ids; # first value is blank + +cmp_ok(@saved_search_ids, '==', 2, 'Two saved charts were made'); + +# TODO get find_link('page-chart')->URI->params to work... +sub page_chart_link_has { + my ($m, $id, $msg) = @_; + + $Test::Builder::Level = $Test::Builder::Level + 1; + + (my $dec_id = $id) =~ s/:/%3A/g; + + my $chart_url = $m->find_link(id => 'page-chart')->url; + like( + $chart_url, qr{SavedChartSearchId=\Q$dec_id\E}, + $msg || 'Page chart link matches the pattern we expected' + ); +} + +# load the first chart +$m->field('SavedSearchLoad' => $saved_search_ids[0]); +$m->click('SavedSearchLoadSubmit'); + +page_chart_link_has($m, $saved_search_ids[0]); + +$m->form_name('SaveSearch'); +is($m->form_number(3)->value('SavedChartSearchId'), $saved_search_ids[0]); + +$m->form_name('SaveSearch'); + +# now load the second chart +$m->field('SavedSearchLoad' => $saved_search_ids[1]); +$m->click('SavedSearchLoadSubmit'); + +page_chart_link_has($m, $saved_search_ids[1]); + +is( + $m->form_number(3)->value('SavedChartSearchId'), $saved_search_ids[1], + 'Second form is seen as a hidden field' +); + +page_chart_link_has($m, $saved_search_ids[1]); diff --git a/rt/t/web/saved_search_context.t b/rt/t/web/saved_search_context.t new file mode 100644 index 000000000..fe9c51ead --- /dev/null +++ b/rt/t/web/saved_search_context.t @@ -0,0 +1,69 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +use RT::Test no_plan => 1; +my ( $url, $m ) = RT::Test->started_ok; + +my $ticket = RT::Ticket->new(RT->SystemUser); +for (['x', 50], ['y', 40], ['z', 30]) { + $ticket->Create( + Subject => $_->[0], + Queue => 'general', + Owner => 'root', + Priority => $_->[1], + Requestor => 'root@localhost', + ); +} + +ok( $m->login, 'logged in' ); + +$m->get($url . '/Search/Build.html?NewQuery=1'); +$m->form_name('BuildQuery'); +$m->field(ValueOfPriority => 45); +$m->click('DoSearch'); +#RT->Logger->error($m->uri); sleep 100; +#{ open my $fh, '>', 'm.html'; print $fh $m->content; close $fh; }; die; +$m->text_contains('Found 2 tickets'); + +$m->follow_link(id => 'page-edit_search'); +$m->form_name('BuildQuery'); +$m->field(ValueOfAttachment => 'z'); +$m->click('DoSearch'); + +$m->text_contains('Found 1 ticket'); + +$m->follow_link(id => 'page-bulk'); + +$m->form_name('BulkUpdate'); +ok(!$m->value('UpdateTicket2'), "There is no Ticket #2 in the search's bulk update"); + +sub edit_search_link_has { + my ($m, $id, $msg) = @_; + + local $Test::Builder::Level = $Test::Builder::Level + 1; + + (my $dec_id = $id) =~ s/:/%3A/g; + + my $chart_url = $m->find_link(id => 'page-edit_search')->url; + like( + $chart_url, qr{SavedSearchId=\Q$dec_id\E}, + $msg || 'Search link matches the pattern we expected' + ); +} + +diag("Test search context"); +{ + $m->get_ok($url . '/Search/Build.html'); + $m->form_name('BuildQuery'); + $m->field(ValueOfPriority => 45); + $m->click('AddClause'); + $m->form_name('BuildQuery'); + $m->set_fields( + SavedSearchDescription => 'my saved search', + ); + $m->click('SavedSearchSave'); + + my $saved_search_id = $m->form_name('BuildQuery')->value('SavedSearchId'); + edit_search_link_has($m, $saved_search_id); +} diff --git a/rt/t/web/saved_search_permissions.t b/rt/t/web/saved_search_permissions.t index f91ca13c6..5cae30b28 100644 --- a/rt/t/web/saved_search_permissions.t +++ b/rt/t/web/saved_search_permissions.t @@ -2,8 +2,8 @@ use strict; use warnings; -use RT::Test tests => 10; -my $user = RT::User->new($RT::SystemUser); +use RT::Test tests => 12; +my $user = RT::User->new(RT->SystemUser); ok( $user->Create( Name => 'foo', @@ -23,7 +23,7 @@ $m->submit_form( $m->content_contains( q{name="SavedSearchDescription" value="test"}, 'saved test search' ); my ($id) = $m->content =~ /value="(RT::User-\d+-SavedSearch-\d+)"/; -ok( $m->login( 'foo', 'foobar' ), 'logged in' ); +ok( $m->login( 'foo', 'foobar', logout => 1 ), 'logged in' ); $m->get_ok( $url . "/Search/Build.html?SavedSearchLoad=$id" ); my $message = qq{Can not load saved search "$id"}; diff --git a/rt/t/web/saved_search_update.t b/rt/t/web/saved_search_update.t index 9b2724e82..dfb18d49c 100644 --- a/rt/t/web/saved_search_update.t +++ b/rt/t/web/saved_search_update.t @@ -3,7 +3,7 @@ use strict; use warnings; -use RT::Test tests => 16; +use RT::Test tests => 18; my $root = RT::User->new( $RT::SystemUser ); $root->Load('root'); diff --git a/rt/t/web/scrips.t b/rt/t/web/scrips.t new file mode 100644 index 000000000..def20eca7 --- /dev/null +++ b/rt/t/web/scrips.t @@ -0,0 +1,105 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use RT::Test tests => 14; + +# TODO: +# Test the rest of the conditions. +# Test actions. +# Test templates? +# Test cleanup scripts. + +my ($baseurl, $m) = RT::Test->started_ok; +ok $m->login, "logged in"; + +$m->follow_link_ok({id => 'tools-config-global-scrips-create'}); + +sub prepare_code_with_value { + my $value = shift; + + # changing the ticket is an easy scrip check for a test + return + '$self->TicketObj->SetSubject(' . + '$self->TicketObj->Subject . ' . + '"|" . ' . $value . + ')'; +} + +{ + # preserve order for checking the subject string later + my @values_for_actions; + + my $conds = RT::ScripConditions->new(RT->SystemUser); + foreach my $cond_value ('On Forward', 'On Forward Ticket', 'On Forward Transaction') { + $conds->Limit( + FIELD => 'name', + VALUE => $cond_value, + ENTRYAGGREGATOR => 'OR', + ); + } + + while (my $rec = $conds->Next) { + push @values_for_actions, [$rec->Id, '"' . $rec->Name . '"']; + } + + @values_for_actions = sort { $a->[0] cmp $b->[0] } @values_for_actions; + + foreach my $data (@values_for_actions) { + my ($condition, $prepare_code_value) = @$data; + diag "Create Scrip (Cond #$condition)" if $ENV{TEST_VERBOSE}; + $m->follow_link_ok({id => 'tools-config-global-scrips-create'}); + my $prepare_code = prepare_code_with_value($prepare_code_value); + $m->form_name('ModifyScrip'); + $m->set_fields( + 'Scrip-new-ScripCondition' => $condition, + 'Scrip-new-ScripAction' => 15, # User Defined + 'Scrip-new-Template' => 1, # Blank + 'Scrip-new-CustomPrepareCode' => $prepare_code, + ); + $m->submit; + } + + my $ticket_obj = RT::Test->create_ticket( + Subject => 'subject', + Content => 'stuff', + Queue => 1, + ); + my $ticket = $ticket_obj->id; + $m->goto_ticket($ticket); + + $m->follow_link_ok( + { id => 'page-actions-forward' }, + 'follow 1st Forward to forward ticket' + ); + + diag "Forward Ticket" if $ENV{TEST_VERBOSE}; + $m->submit_form( + form_name => 'ForwardMessage', + fields => { + To => 'rt-test, rt-to@example.com', + }, + button => 'ForwardAndReturn' + ); + + $m->text_contains("#${ticket}: subject|On Forward|On Forward Ticket"); + + diag "Forward Transaction" if $ENV{TEST_VERBOSE}; + # get the first transaction on the ticket + my ($transaction) = $ticket_obj->Transactions->First->id; + $m->get( + "$baseurl/Ticket/Forward.html?id=1&QuoteTransaction=$transaction" + ); + $m->submit_form( + form_name => 'ForwardMessage', + fields => { + To => 'rt-test, rt-to@example.com', + }, + button => 'ForwardAndReturn' + ); + + $m->text_contains("#${ticket}: subject|On Forward|On Forward Ticket|On Forward|On Forward Transaction"); + + RT::Test->clean_caught_mails; +} diff --git a/rt/t/web/scrub.t b/rt/t/web/scrub.t new file mode 100644 index 000000000..6483a7500 --- /dev/null +++ b/rt/t/web/scrub.t @@ -0,0 +1,46 @@ +#!/usr/bin/perl +use strict; +use warnings; + +use RT::Test nodb => 1, tests => 6; +use RT::Interface::Web; # This gets us HTML::Mason::Commands +use Test::LongString; + +{ + my $html = 'This is a test of <span style="color: rgb(255, 0, 0); ">color</span> and <span style="font-size: 18px; "><span style="font-family: Georgia, serif; ">font</span></span> and <em><u><strike><strong>boldness</strong></strike></u></em>.'; + is_string(scrub_html($html), $html, "CKEditor produced HTML sails through"); +} + +{ + my $html = '<p style="text-align: right; "> + And <span style="color: rgb(255, 0, 0); "><span style="font-size: 16px; "><span style="font-family: Georgia, serif; ">alignment with color</span></span></span>?</p>'; + is_string(scrub_html($html), $html, "CKEditor produced HTML sails through"); +} + +{ + my $html = 'This is a test of <span style="color: rgb(255, 0, 0); content: url(/Nasty/URL);">color</span> and <span style="font-size: 18px; "><span style="font-family: Georgia, serif; ">font</span></span> and <em><u><strike><strong>boldness</strong></strike></u></em>.'; + my $expected = 'This is a test of <span>color</span> and <span style="font-size: 18px; "><span style="font-family: Georgia, serif; ">font</span></span> and <em><u><strike><strong>boldness</strong></strike></u></em>.'; + is_string(scrub_html($html), $expected, "nasty CSS not allowed through"); +} + +{ + my $html = 'Let\'s add some <span style="color: blue; font-family: Georgia">color</span> up in <span style="color: #DEADBE">here</span>.'; + is_string(scrub_html($html), $html, "multiple props and color specs allowed"); +} + +{ + my $html = q[<span lang=EN-US style='font-family:"Century Gothic","sans-serif";'>oh hai I'm some text</span>]; + my $expected = q[<span style="font-family:"Century Gothic","sans-serif";">oh hai I'm some text</span>]; + is_string(scrub_html($html), $expected, "font lists"); +} + +{ + my $html = q[<span lang=EN-US style='font-size:7.5pt;font-family:"Century Gothic","sans-serif";color:#666666;mso-fareast-language:IT'>oh hai I'm some text</span>]; + my $expected = q[<span style="font-size:7.5pt;font-family:"Century Gothic","sans-serif";color:#666666;mso-fareast-language:IT">oh hai I'm some text</span>]; + is_string(scrub_html($html), $expected, "outlook html"); +} + +sub scrub_html { + return HTML::Mason::Commands::ScrubHTML(shift); +} + diff --git a/rt/t/web/search_bulk_update_links.t b/rt/t/web/search_bulk_update_links.t index d6bfdfd3c..7d150a699 100644 --- a/rt/t/web/search_bulk_update_links.t +++ b/rt/t/web/search_bulk_update_links.t @@ -2,7 +2,7 @@ use strict; use warnings; -use RT::Test tests => 28; +use RT::Test tests => 47; my ( $url, $m ) = RT::Test->started_ok; ok( $m->login, 'logged in' ); @@ -13,7 +13,7 @@ use RT::Ticket; my ( @link_tickets, @search_tickets ); for ( 1 .. 3 ) { - my $link_ticket = RT::Ticket->new($RT::SystemUser); + my $link_ticket = RT::Ticket->new(RT->SystemUser); my ( $ret, $msg ) = $link_ticket->Create( Subject => "link ticket $_", Queue => 'general', @@ -25,7 +25,7 @@ for ( 1 .. 3 ) { } for ( 1 .. 3 ) { - my $ticket = RT::Ticket->new($RT::SystemUser); + my $ticket = RT::Ticket->new(RT->SystemUser); my ( $ret, $msg ) = $ticket->Create( Subject => "search ticket $_", Queue => 'general', @@ -41,7 +41,7 @@ $m->get_ok( $url . "/Search/Bulk.html?Query=id=$search_tickets[0]&Rows=10" ); $m->content_contains( 'Current Links', 'has current links part' ); $m->content_lacks( 'DeleteLink--', 'no delete link stuff' ); $m->submit_form( - form_number => 3, + form_name => 'BulkUpdate', fields => { 'Ticket-DependsOn' => $link_tickets[0], 'Ticket-MemberOf' => $link_tickets[1], @@ -77,9 +77,17 @@ $m->get_ok( $url . "/Search/Bulk.html?Query=$query&Rows=10" ); $m->content_contains( 'Current Links', 'has current links part' ); $m->content_lacks( 'DeleteLink--', 'no delete link stuff' ); +$m->form_name('BulkUpdate'); +my @fields = qw/Owner AddRequestor DeleteRequestor AddCc DeleteCc AddAdminCc +DeleteAdminCc Subject Priority Queue Status Starts_Date Told_Date Due_Date +Resolved_Date UpdateSubject UpdateContent/; +for my $field ( @fields ) { + is( $m->value($field), '', "default $field is empty" ); +} + # test DependsOn, MemberOf and RefersTo $m->submit_form( - form_number => 3, + form_name => 'BulkUpdate', fields => { 'Ticket-DependsOn' => $link_tickets[0], 'Ticket-MemberOf' => $link_tickets[1], @@ -98,7 +106,7 @@ $m->content_contains( 'found refers to link' ); $m->submit_form( - form_number => 3, + form_name => 'BulkUpdate', fields => { "DeleteLink--DependsOn-fsck.com-rt://$rtname/ticket/$link_tickets[0]" => 1, @@ -114,7 +122,7 @@ $m->content_lacks( 'DeleteLink--', 'links are all deleted' ); # test DependedOnBy, Members and ReferredToBy $m->submit_form( - form_number => 3, + form_name => 'BulkUpdate', fields => { 'DependsOn-Ticket' => $link_tickets[0], 'MemberOf-Ticket' => $link_tickets[1], @@ -133,7 +141,7 @@ $m->content_contains( 'found referrd to link' ); $m->submit_form( - form_number => 3, + form_name => 'BulkUpdate', fields => { "DeleteLink-fsck.com-rt://$rtname/ticket/$link_tickets[0]-DependsOn-" => 1, diff --git a/rt/t/web/search_cf_quotes.t b/rt/t/web/search_cf_quotes.t new file mode 100644 index 000000000..360fe0dc9 --- /dev/null +++ b/rt/t/web/search_cf_quotes.t @@ -0,0 +1,53 @@ +use strict; +use warnings; + +use RT::Test tests => 24; +my ( $baseurl, $m ) = RT::Test->started_ok; + +my $cf = RT::CustomField->new($RT::SystemUser); +ok( + $cf->Create( + Name => "I'm a cf", + Type => 'Date', + LookupType => 'RT::Queue-RT::Ticket', + ) +); +ok( $cf->AddToObject( RT::Queue->new($RT::SystemUser) ) ); + +RT::Test->create_tickets( + { Queue => 'General' }, + { Subject => 'ticket foo', 'CustomField-' . $cf->id => '2011-09-15' }, + { Subject => 'ticket bar', 'CustomField-' . $cf->id => '2011-10-15' }, + { Subject => 'ticket baz' }, +); + +ok( $m->login, 'logged in' ); + +$m->get_ok('/Search/Build.html'); +$m->form_name( 'BuildQuery' ); + +my ($cf_op) = + $m->find_all_inputs( type => 'option', name_regex => qr/I'm a cf/ ); +my ($cf_field) = + $m->find_all_inputs( type => 'text', name_regex => qr/I'm a cf/ ); + +diag "search directly"; +$m->submit_form( + fields => { $cf_op->name => '<', $cf_field->name => '2011-09-30', }, + button => 'DoSearch', +); + +$m->title_is( 'Found 1 ticket', 'found only 1 ticket' ); +$m->content_contains( 'ticket foo', 'has ticket foo' ); + +diag "first add clause, then search"; +$m->get_ok('/Search/Build.html?NewQuery=1'); +$m->form_name( 'BuildQuery' ); +$m->submit_form( + fields => { $cf_op->name => '<', $cf_field->name => '2011-09-30', }, + button => 'AddClause', +); +$m->follow_link_ok( { text => 'Show Results' } ); +$m->title_is( 'Found 1 ticket', 'found only 1 ticket' ); +$m->content_contains( 'ticket foo', 'has ticket foo' ); + diff --git a/rt/t/web/search_rss.t b/rt/t/web/search_rss.t index 454dc0369..95de931c3 100644 --- a/rt/t/web/search_rss.t +++ b/rt/t/web/search_rss.t @@ -2,10 +2,10 @@ use strict; -use RT::Test tests => 36; -RT::Test->started_ok; +use RT::Test tests => 38; +my ($baseurl, $agent) = RT::Test->started_ok; -my $ticket = RT::Ticket->new($RT::SystemUser); +my $ticket = RT::Ticket->new(RT->SystemUser); for ( 1 .. 5 ) { $ticket->Create( Subject => 'Ticket ' . $_, @@ -15,7 +15,6 @@ for ( 1 .. 5 ) { ); } -my $agent = RT::Test::Web->new; ok $agent->login('root', 'password'), 'logged in as root'; $agent->get_ok('/Search/Build.html'); @@ -23,7 +22,7 @@ $agent->form_name('BuildQuery'); $agent->field('idOp', '>'); $agent->field('ValueOfid', '0'); $agent->submit('DoSearch'); -$agent->follow_link_ok({text=>'Show Results'}); +$agent->follow_link_ok({id => 'page-results'}); for ( 1 .. 5 ) { $agent->content_contains('Ticket ' . $_); @@ -64,7 +63,7 @@ my $user_b = RT::Test->load_or_create_user( Name => 'user_b', Password => 'password', ); ok $user_b && $user_b->id, 'loaded or created user'; -$agent_b->login('user_b', 'password'), 'logged in as user B'; +$agent_b->login('user_b', 'password'); $agent_b->get_ok($noauth_uri); is( $agent_b->content_type, 'application/rss+xml', 'content type' ); is( $agent_b->content, $rss_content, 'content' ); diff --git a/rt/t/web/search_simple.t b/rt/t/web/search_simple.t new file mode 100644 index 000000000..1efc9a566 --- /dev/null +++ b/rt/t/web/search_simple.t @@ -0,0 +1,22 @@ +use strict; +use warnings; + +use RT::Test tests => 16; +my ( $baseurl, $m ) = RT::Test->started_ok; + +RT::Test->create_tickets( + { Queue => 'General' }, + { Subject => 'ticket foo' }, + { Subject => 'ticket bar' }, +); + +ok( $m->login, 'logged in' ); + +$m->get_ok('/Search/Simple.html'); +$m->content_lacks( 'Show Results', 'no page menu' ); +$m->get_ok('/Search/Simple.html?q=ticket foo'); +$m->content_contains( 'Show Results', "has page menu" ); +$m->title_is( 'Found 1 ticket', 'title' ); +$m->content_contains( 'ticket foo', 'has ticket foo' ); + +# TODO more simple search tests diff --git a/rt/t/web/search_tabs.t b/rt/t/web/search_tabs.t new file mode 100644 index 000000000..b3ed2cbdf --- /dev/null +++ b/rt/t/web/search_tabs.t @@ -0,0 +1,86 @@ +#!/usr/bin/perl +use warnings; +use strict; + +use RT::Test tests => 21; +my ($baseurl, $agent) = RT::Test->started_ok; + +my $ticket = RT::Ticket->new(RT->SystemUser); +for ( 1 .. 3 ) { + $ticket->Create( + Subject => 'Ticket ' . $_, + Queue => 'General', + Owner => 'root', + Requestor => 'clownman@localhost', + ); +} + +ok $agent->login('root', 'password'), 'logged in as root'; + +# [issues.bestpractical.com #16841] { +$agent->get_ok('/Search/Build.html'); + +$agent->form_name('BuildQuery'); +$agent->field('idOp', '='); +$agent->field('ValueOfid', '1'); +$agent->submit('AddClause'); + +$agent->form_name('BuildQuery'); +$agent->field('idOp', '='); +$agent->field('ValueOfid', '2'); +$agent->field('AndOr', 'OR'); +$agent->submit('AddClause'); + +$agent->follow_link_ok({id => 'page-results'}); +$agent->title_is('Found 2 tickets'); +# } + +# [issues.bestpractical.com #17237] { +$agent->follow_link_ok({text => 'New Search'}); +$agent->title_is('Query Builder'); + +$agent->form_name('BuildQuery'); +$agent->field('idOp', '='); +$agent->field('ValueOfid', '1'); +$agent->submit('AddClause'); + +$agent->form_name('BuildQuery'); +$agent->field('idOp', '='); +$agent->field('ValueOfid', '2'); +$agent->field('AndOr', 'OR'); +$agent->click_button(name => 'DoSearch'); + +$agent->title_is('Found 2 tickets'); + +$agent->follow_link_ok({id => 'page-results'}); +$agent->title_is('Found 2 tickets'); +# } + +$agent->follow_link_ok({text => 'Chart'}); +$agent->text_contains('id = 1 OR id = 2'); +$agent->form_name('SaveSearch'); +$agent->field('SavedSearchDescription' => 'this is my saved chart'); +$agent->click_button(name => 'SavedSearchSave'); + +# Confirm that we saved the chart and that it's the "current chart" +$agent->text_contains('Chart this is my saved chart saved.'); +$agent->form_name('SaveSearch'); +is($agent->value('SavedSearchDescription'), 'this is my saved chart'); + +$agent->follow_link_ok({text => 'Edit Search'}); +$agent->form_name('BuildQuery'); +$agent->field('idOp', '='); +$agent->field('ValueOfid', '3'); +$agent->field('AndOr', 'OR'); +$agent->click_button(name => 'DoSearch'); + +$agent->title_is('Found 3 tickets'); + +$agent->follow_link_ok({text => 'Chart'}); +$agent->text_contains('id = 1 OR id = 2 OR id = 3'); + +# The interesting bit: confirm that the chart we saved is still the +# "current chart" after roundtripping through search builder +$agent->form_name('SaveSearch'); +is($agent->value('SavedSearchDescription'), 'this is my saved chart'); + diff --git a/rt/t/web/self_service.t b/rt/t/web/self_service.t new file mode 100644 index 000000000..49d9e37ee --- /dev/null +++ b/rt/t/web/self_service.t @@ -0,0 +1,19 @@ +use strict; +use warnings; +use RT::Test tests => 9; + +my ($url, $m) = RT::Test->started_ok; + +my ($ticket) = + RT::Test->create_ticket( Queue => 'General', Subject => 'test subject' ); + +$m->login(); + +$m->get_ok( '/SelfService/Display.html?id=' . $ticket->id, + 'got selfservice display page' ); + +my $title = '#' . $ticket->id . ': test subject'; +$m->title_is( $title ); +$m->content_contains( "<h1>$title</h1>", "contains <h1>$title</h1>" ); + +# TODO need more SelfService tests diff --git a/rt/t/web/squish.t b/rt/t/web/squish.t new file mode 100644 index 000000000..ff43e74fb --- /dev/null +++ b/rt/t/web/squish.t @@ -0,0 +1,78 @@ +use strict; +use warnings; +use RT; +use RT::Test tests => 26; + +RT->Config->Set( DevelMode => 0 ); +RT->Config->Set( WebDefaultStylesheet => 'aileron' ); +RT->Config->Set( MasonLocalComponentRoot => RT::Test::get_abs_relocatable_dir('html') ); + +my ( $url, $m ) = RT::Test->started_ok; +$m->login; + +diag "test squished files with devel mode disabled"; + +$m->follow_link_ok( { url_regex => qr!aileron-squished-([a-f0-9]{32})\.css! }, + 'follow squished css' ); +$m->content_like( qr!/\*\* End of .*?.css \*/!, 'squished css' ); +$m->content_lacks( 'text-decoration: underline !important;', + 'no print.css by default' ); + +$m->back; +my ($js_link) = + $m->content =~ m!src="([^"]+?squished-([a-f0-9]{32})\.js)"!; +$m->get_ok( $url . $js_link, 'follow squished js' ); +$m->content_lacks('function just_testing', "no not-by-default.js"); +$m->content_contains('jQuery.noConflict', "found default js content"); + +RT::Test->stop_server; + +diag "test squished files with customized files and devel mode disabled"; +RT->AddJavaScript( 'not-by-default.js' ); +RT->AddStyleSheets( 'print.css' ); + +( $url, $m ) = RT::Test->started_ok; + +$m->login; +$m->follow_link_ok( { url_regex => qr!aileron-squished-([a-f0-9]{32})\.css! }, + 'follow squished css' ); +$m->content_like( qr!/\*\* End of .*?.css \*/!, 'squished css' ); +$m->content_contains( 'text-decoration: underline !important;', + 'has print.css' ); + +$m->back; +($js_link) = + $m->content =~ m!src="([^"]+?squished-([a-f0-9]{32})\.js)"!; +$m->get_ok( $url . $js_link, 'follow squished js' ); +$m->content_contains( 'function just_testing', "has not-by-default.js" ); +$m->content_contains('jQuery.noConflict', "found default js content"); +RT::Test->stop_server; + + +diag "Test with a trivial jsmin which is a pass-through"; +RT->Config->Set( 'JSMinPath' => RT::Test::get_abs_relocatable_dir("passthrough-jsmin")); +( $url, $m ) = RT::Test->started_ok; +$m->login; +($js_link) = + $m->content =~ m!src="([^"]+?squished-([a-f0-9]{32})\.js)"!; +$m->get_ok( $url . $js_link, 'follow squished js' ); +$m->content_contains( 'passthrough-jsmin added this', "has passthrough-added content" ); +$m->content_contains( 'function just_testing', "has not-by-default.js" ); +$m->content_contains('jQuery.noConflict', "found default js content"); +RT::Test->stop_server; + + +diag "test squished files with devel mode enabled"; +RT->Config->Set( 'DevelMode' => 1 ); +RT->AddJavaScript( 'not-by-default.js' ); +RT->AddStyleSheets( 'nottherebutwedontcare.css' ); + +( $url, $m ) = RT::Test->started_ok; +$m->login; +$m->content_unlike( qr!squished-.*?\.(js|css)!, + 'no squished link with develmode' ); + +$m->content_contains('not-by-default.js', "found extra javascript resource"); +$m->content_contains('nottherebutwedontcare.css', "found extra css resource"); +$m->content_contains('jquery_noconflict.js', "found a default js resource"); + diff --git a/rt/t/web/template.t b/rt/t/web/template.t new file mode 100644 index 000000000..40a5366dc --- /dev/null +++ b/rt/t/web/template.t @@ -0,0 +1,62 @@ +#!/usr/bin/perl +use strict; +use warnings; + +use RT::Test tests => 19; + +my $user_a = RT::Test->load_or_create_user( + Name => 'user_a', Password => 'password', +); +ok $user_a && $user_a->id, 'loaded or created user'; + +my ($baseurl, $m) = RT::Test->started_ok; + +ok( RT::Test->set_rights( + { Principal => $user_a, Right => [qw(ShowConfigTab ShowTemplate ModifyTemplate)] }, +), 'set rights'); + +ok $m->login('user_a', 'password'), 'logged in as user A'; + +# get to the templates screen +$m->follow_link( text => 'Configuration' ); +$m->title_is(q{RT Administration}, 'admin screen'); + +$m->follow_link( text => 'Global' ); +$m->title_is(q{Admin/Global configuration}, 'global admin'); + +$m->follow_link( text => 'Templates' ); +$m->title_is(q{Modify templates which apply to all queues}, 'global templates'); + +$m->follow_link( text => 'Resolved' ); # template name +$m->title_is(q{Modify template Resolved}, 'modifying the Resolved template'); + +# now try changing Type back and forth +$m->form_name('ModifyTemplate'); +is($m->value('Type'), 'Perl'); + +$m->field(Type => 'Simple'); +$m->submit; + +$m->title_is(q{Modify template Resolved}, 'modifying the Resolved template'); +$m->form_name('ModifyTemplate'); +is($m->value('Type'), 'Simple', 'updated type to simple'); + +$m->field(Type => 'Perl'); +$m->submit; + +$m->title_is(q{Modify template Resolved}, 'modifying the Resolved template'); +$m->form_name('ModifyTemplate'); +is($m->value('Type'), 'Simple', 'need the ExecuteCode right to update Type to Perl'); +$m->content_contains('Permission Denied'); + +ok( RT::Test->add_rights( + { Principal => $user_a, Right => [qw(ExecuteCode)] }, +), 'add ExecuteCode rights'); + +$m->field(Type => 'Perl'); +$m->submit; + +$m->title_is(q{Modify template Resolved}, 'modifying the Resolved template'); +$m->form_name('ModifyTemplate'); +is($m->value('Type'), 'Perl', 'now that we have ExecuteCode we can update Type to Perl'); + diff --git a/rt/t/web/ticket-create-utf8.t b/rt/t/web/ticket-create-utf8.t index f37eeec06..8d36bd19e 100644 --- a/rt/t/web/ticket-create-utf8.t +++ b/rt/t/web/ticket-create-utf8.t @@ -3,9 +3,7 @@ use strict; use warnings; -use RT::Test tests => 41; - -$RT::Test::SKIP_REQUEST_WORK_AROUND = 1; +use RT::Test tests => 43; use Encode; @@ -32,7 +30,7 @@ ok $m->login, 'logged in'; # create a ticket with a subject only foreach my $test_str ( $ru_test, $l1_test ) { ok $m->goto_create_ticket( $q ), "go to create ticket"; - $m->form_number(3); + $m->form_name('TicketCreate'); $m->field( Subject => $test_str ); $m->submit; @@ -49,7 +47,7 @@ foreach my $test_str ( $ru_test, $l1_test ) { foreach my $test_str ( $ru_test, $l1_test ) { foreach my $support_str ( $ru_support, $l1_support ) { ok $m->goto_create_ticket( $q ), "go to create ticket"; - $m->form_number(3); + $m->form_name('TicketCreate'); $m->field( Subject => $test_str ); $m->field( Content => $support_str ); $m->submit; @@ -58,8 +56,8 @@ foreach my $test_str ( $ru_test, $l1_test ) { qr{<td\s+class="message-header-value"[^>]*>\s*\Q$test_str\E\s*</td>}i, 'header on the page' ); - $m->content_like( - qr{\Q$support_str\E}i, + $m->content_contains( + $support_str, 'content on the page' ); @@ -72,7 +70,7 @@ foreach my $test_str ( $ru_test, $l1_test ) { foreach my $test_str ( $ru_test, $l1_test ) { foreach my $support_str ( $ru_support, $l1_support ) { ok $m->goto_create_ticket( $q ), "go to create ticket"; - $m->form_number(3); + $m->form_name('TicketCreate'); $m->field( Subject => $test_str ); $m->field( Content => $support_str ); $m->submit; @@ -81,8 +79,8 @@ foreach my $test_str ( $ru_test, $l1_test ) { qr{<td\s+class="message-header-value"[^>]*>\s*\Q$test_str\E\s*</td>}i, 'header on the page' ); - $m->content_like( - qr{\Q$support_str\E}i, + $m->content_contains( + $support_str, 'content on the page' ); diff --git a/rt/t/web/ticket_display.t b/rt/t/web/ticket_display.t new file mode 100644 index 000000000..a9cab0cbf --- /dev/null +++ b/rt/t/web/ticket_display.t @@ -0,0 +1,63 @@ +use strict; +use warnings; + +use RT::Test tests => 18; + +my $queue = RT::Test->load_or_create_queue( Name => 'General' ); + +my $user = RT::Test->load_or_create_user( + Name => 'user', + Password => 'password', +); + +my ( $baseurl, $m ) = RT::Test->started_ok; +ok( + RT::Test->set_rights( + { Principal => $user, Right => [qw(SeeQueue CreateTicket)] }, + ), + 'set rights' +); + +ok $m->login( 'user', 'password' ), 'logged in as user'; + +diag "test ShowTicket right"; +{ + + $m->get_ok( '/Ticket/Create.html?Queue=' . $queue->id, + 'go to ticket create page' ); + my $form = $m->form_name('TicketCreate'); + $m->submit_form( fields => { Subject => 'ticket foo' } ); + + my $ticket = RT::Test->last_ticket; + ok( $ticket->id, 'ticket is created' ); + my $id = $ticket->id; + + $m->content_lacks( "Ticket $id created", 'created ticket' ); + $m->content_contains( "No permission to view newly created ticket #$id", + 'got no permission msg' ); + $m->warning_like( qr/No permission to view newly created ticket #$id/, + 'got no permission warning' ); + + + $m->goto_ticket($id); + $m->content_contains( "No permission to view ticket", + 'got no permission msg' ); + $m->warning_like( qr/No permission to view ticket/, 'got warning' ); + $m->title_is('RT Error'); + + ok( + RT::Test->add_rights( + { Principal => $user, Right => [qw(ShowTicket)] }, + ), + 'add ShowTicket right' + ); + + $m->reload; + + $m->content_lacks( "No permission to view ticket", 'no error msg' ); + $m->title_is( "#$id: ticket foo", 'we can it' ); +} + + +# TODO more /Ticket/Display.html tests here + diff --git a/rt/t/web/ticket_forward.t b/rt/t/web/ticket_forward.t new file mode 100644 index 000000000..be06ad976 --- /dev/null +++ b/rt/t/web/ticket_forward.t @@ -0,0 +1,232 @@ +#!/usr/bin/perl +use strict; +use warnings; + +use RT::Test tests => undef; +use File::Spec; +my $att_file = File::Spec->catfile( RT::Test->temp_directory, 'attachment' ); +open my $att_fh, '>', $att_file or die $!; +print $att_fh "this is an attachment"; +close $att_fh; +my $att_name = ( File::Spec->splitpath($att_file) )[-1]; + +my ( $baseurl, $m ) = RT::Test->started_ok; +ok $m->login, 'logged in as root'; + +# Create a ticket with content and an attachment +$m->get_ok( $baseurl . '/Ticket/Create.html?Queue=1' ); + +$m->submit_form( + form_name => 'TicketCreate', + fields => { + Subject => 'test forward', + Content => 'this is content', + Attach => $att_file, + }, +); +$m->content_like( qr/Ticket \d+ created/i, 'created the ticket' ); +RT::Test->clean_caught_mails; + +diag "Forward Ticket" if $ENV{TEST_VERBOSE}; +{ + $m->follow_link_ok( + { id => 'page-actions-forward' }, + 'follow 1st Forward to forward ticket' + ); + + $m->submit_form( + form_name => 'ForwardMessage', + fields => { + To => 'rt-test, rt-to@example.com', + Cc => 'rt-cc@example.com', + }, + button => 'ForwardAndReturn' + ); + $m->content_contains( 'Sent email successfully', 'sent mail msg' ); + $m->content_contains( + 'Forwarded Ticket to rt-test, rt-to@example.com, rt-cc@example.com', + 'txn msg' ); + my ($mail) = RT::Test->fetch_caught_mails; + like( $mail, qr!Subject: test forward!, 'Subject field' ); + like( $mail, qr!To: rt-test, rt-to\@example.com!, 'To field' ); + like( $mail, qr!Cc: rt-cc\@example.com!, 'Cc field' ); + like( $mail, qr!This is a forward of ticket!, 'content' ); + like( $mail, qr!this is an attachment!, 'att content' ); + like( $mail, qr!$att_name!, 'att file name' ); +} + +diag "Forward Transaction" if $ENV{TEST_VERBOSE}; +{ + $m->follow_link_ok( { text => 'Forward', n => 2 }, 'follow 2nd Forward' ); + $m->submit_form( + form_name => 'ForwardMessage', + fields => { + To => 'rt-test, rt-to@example.com', + Cc => 'rt-cc@example.com', + Bcc => 'rt-bcc@example.com' + }, + button => 'ForwardAndReturn' + ); + $m->content_contains( 'Sent email successfully', 'sent mail msg' ); + $m->content_like( +qr/Forwarded Transaction #\d+ to rt-test, rt-to\@example.com, rt-cc\@example.com, rt-bcc\@example.com/, + 'txn msg' + ); + my ($mail) = RT::Test->fetch_caught_mails; + like( $mail, qr!Subject: test forward!, 'Subject field' ); + like( $mail, qr!To: rt-test, rt-to\@example.com!, 'To field' ); + like( $mail, qr!Cc: rt-cc\@example.com!, 'Cc field' ); + like( $mail, qr!Bcc: rt-bcc\@example.com!, 'Bcc field' ); + like( $mail, qr!This is a forward of transaction!, 'content' ); + like( $mail, qr!$att_name!, 'att file name' ); + like( $mail, qr!this is an attachment!, 'att content' ); +} + +diag "Forward Ticket without content" if $ENV{TEST_VERBOSE}; +{ + my $ticket = RT::Test->create_ticket( + Subject => 'test forward without content', + Queue => 1, + ); + $m->get_ok( $baseurl . '/Ticket/Forward.html?id=' . $ticket->id ); + $m->submit_form( + form_name => 'ForwardMessage', + fields => { To => 'rt-test@example.com', }, + button => 'ForwardAndReturn' + ); + $m->content_contains( 'Sent email successfully', 'sent mail msg' ); + my ($mail) = RT::Test->fetch_caught_mails; + like( $mail, qr/Subject: Fwd: \[example\.com #\d\] test forward without content/, 'Subject field' ); + like( $mail, qr/To: rt-test\@example\.com/, 'To field' ); + like( $mail, qr/This is a forward of ticket #\d/, 'content' ); +} + +diag "Forward Transaction with attachments but empty content" if $ENV{TEST_VERBOSE}; +{ + # Create a ticket without content but with a non-text/plain attachment + $m->get_ok( $baseurl . '/Ticket/Create.html?Queue=1' ); + + $m->form_name('TicketCreate'); + my $attach = $m->current_form->find_input('Attach'); + $attach->filename("awesome.patch"); + $attach->headers('Content-Type' => 'text/x-diff'); + $m->set_fields( + Subject => 'test forward, empty content but attachments', + Attach => $att_file, # from up top + ); + $m->click('AddMoreAttach'); + $m->form_name('TicketCreate'); + $attach = $m->current_form->find_input('Attach'); + $attach->filename("bpslogo.png"); + $attach->headers('Content-Type' => 'image/png'); + $m->set_fields( + Attach => RT::Test::get_relocatable_file('bpslogo.png', '..', 'data'), # an image! + ); + $m->submit; + $m->content_like( qr/Ticket \d+ created/i, 'created the ticket' ); + $m->content_like( qr/awesome\.patch/, 'uploaded patch file' ); + $m->content_like( qr/text\/x-diff/, 'uploaded patch file content type' ); + $m->content_like( qr/bpslogo\.png/, 'uploaded image file' ); + $m->content_like( qr/image\/png/, 'uploaded image file content type' ); + RT::Test->clean_caught_mails; + + $m->follow_link_ok( { text => 'Forward', n => 2 }, 'follow 2nd Forward' ); + $m->submit_form( + form_name => 'ForwardMessage', + fields => { + To => 'rt-test@example.com', + }, + button => 'ForwardAndReturn' + ); + $m->content_contains( 'Sent email successfully', 'sent mail msg' ); + $m->content_like( qr/Forwarded Transaction #\d+ to rt-test\@example\.com/, 'txn msg' ); + my ($mail) = RT::Test->fetch_caught_mails; + like( $mail, qr/Subject: test forward, empty content but attachments/, 'Subject field' ); + like( $mail, qr/To: rt-test\@example.com/, 'To field' ); + like( $mail, qr/This is a forward of transaction/, 'content' ); + like( $mail, qr/awesome\.patch/, 'att file name' ); + like( $mail, qr/this is an attachment/, 'att content' ); + like( $mail, qr/text\/x-diff/, 'att content type' ); + like( $mail, qr/bpslogo\.png/, 'att image file name' ); + like( $mail, qr/image\/png/, 'att image content type' ); +} + +diag "Forward Transaction with attachments but no 'content' part" if $ENV{TEST_VERBOSE}; +{ + my $mime = MIME::Entity->build( + From => 'test@example.com', + Subject => 'attachments for everyone', + Type => 'multipart/mixed', + ); + + $mime->attach( + Path => $att_file, + Type => 'text/x-diff', + Filename => 'awesome.patch', + Disposition => 'attachment', + ); + + $mime->attach( + Path => RT::Test::get_relocatable_file('bpslogo.png', '..', 'data'), + Type => 'image/png', + Filename => 'bpslogo.png', + Encoding => 'base64', + Disposition => 'attachment', + ); + + my $ticket = RT::Test->create_ticket( + Queue => 1, + Subject => 'test forward, attachments but no "content"', + MIMEObj => $mime, + ); + + $m->get_ok( $baseurl . '/Ticket/Display.html?id=' . $ticket->Id ); + $m->content_like( qr/awesome\.patch/, 'uploaded patch file' ); + $m->content_like( qr/text\/x-diff/, 'uploaded patch file content type' ); + $m->content_like( qr/bpslogo\.png/, 'uploaded image file' ); + $m->content_like( qr/image\/png/, 'uploaded image file content type' ); + RT::Test->clean_caught_mails; + + # Forward txn + $m->follow_link_ok( { text => 'Forward', n => 2 }, 'follow 2nd Forward' ); + $m->submit_form( + form_name => 'ForwardMessage', + fields => { + To => 'rt-test@example.com', + }, + button => 'ForwardAndReturn' + ); + $m->content_contains( 'Sent email successfully', 'sent mail msg' ); + $m->content_like( qr/Forwarded Transaction #\d+ to rt-test\@example\.com/, 'txn msg' ); + + # Forward ticket + $m->follow_link_ok( { text => 'Forward', n => 1 }, 'follow 1st Forward' ); + $m->submit_form( + form_name => 'ForwardMessage', + fields => { + To => 'rt-test@example.com', + }, + button => 'ForwardAndReturn' + ); + $m->content_contains( 'Sent email successfully', 'sent mail msg' ); + $m->content_like( qr/Forwarded Ticket to rt-test\@example\.com/, 'txn msg' ); + + my ($forward_txn, $forward_ticket) = RT::Test->fetch_caught_mails; + my $tag = qr/Fwd: \[example\.com #\d+\]/; + like( $forward_txn, qr/Subject: $tag attachments for everyone/, 'Subject field is from txn' ); + like( $forward_txn, qr/This is a forward of transaction/, 'forward description' ); + like( $forward_ticket, qr/Subject: $tag test forward, attachments but no "content"/, 'Subject field is from ticket' ); + like( $forward_ticket, qr/This is a forward of ticket/, 'forward description' ); + + for my $mail ($forward_txn, $forward_ticket) { + like( $mail, qr/To: rt-test\@example.com/, 'To field' ); + like( $mail, qr/awesome\.patch/, 'att file name' ); + like( $mail, qr/this is an attachment/, 'att content' ); + like( $mail, qr/text\/x-diff/, 'att content type' ); + like( $mail, qr/bpslogo\.png/, 'att image file name' ); + like( $mail, qr/image\/png/, 'att image content type' ); + } +} + +undef $m; +done_testing; diff --git a/rt/t/web/ticket_links.t b/rt/t/web/ticket_links.t new file mode 100644 index 000000000..cb30e92f9 --- /dev/null +++ b/rt/t/web/ticket_links.t @@ -0,0 +1,110 @@ +use strict; +use warnings; +use RT::Test tests => 106; + +my ( $baseurl, $m ) = RT::Test->started_ok; +ok( $m->login, "Logged in" ); + +my $queue = RT::Test->load_or_create_queue( Name => 'General' ); +ok( $queue->id, "loaded the General queue" ); + +my ( $deleted, $active, $inactive ) = RT::Test->create_tickets( + { Queue => 'General' }, + { Subject => 'deleted ticket', }, + { Subject => 'active ticket', }, + { Subject => 'inactive ticket', } +); + +my ( $deleted_id, $active_id, $inactive_id ) = + ( $deleted->id, $active->id, $inactive->id ); + +$deleted->SetStatus('deleted'); +is( $deleted->Status, 'deleted', "deleted $deleted_id" ); + +$inactive->SetStatus('resolved'); +is( $inactive->Status, 'resolved', 'resolved $inactive_id' ); + +for my $type ( "DependsOn", "MemberOf", "RefersTo" ) { + for my $c (qw/base target/) { + my $id; + + diag "create ticket with links of type $type $c"; + { + ok( $m->goto_create_ticket($queue), "go to create ticket" ); + $m->form_name('TicketCreate'); + $m->field( Subject => "test ticket creation with $type $c" ); + if ( $c eq 'base' ) { + $m->field( "new-$type", "$deleted_id $active_id $inactive_id" ); + } + else { + $m->field( "$type-new", "$deleted_id $active_id $inactive_id" ); + } + + $m->submit; + $m->content_like(qr/Ticket \d+ created/, 'created ticket'); + $m->content_contains("Can't link to a deleted ticket"); + $id = RT::Test->last_ticket->id; + } + + diag "add ticket links of type $type $c"; + { + my $ticket = RT::Test->create_ticket( + Queue => 'General', + Subject => "test $type $c", + ); + $id = $ticket->id; + + $m->goto_ticket($id); + $m->follow_link_ok( { text => 'Links' }, "Followed link to Links" ); + + ok( $m->form_with_fields("$id-DependsOn"), "found the form" ); + if ( $c eq 'base' ) { + $m->field( "$id-$type", "$deleted_id $active_id $inactive_id" ); + } + else { + $m->field( "$type-$id", "$deleted_id $active_id $inactive_id" ); + } + $m->submit; + $m->content_contains("Can't link to a deleted ticket"); + + if ( $c eq 'base' ) { + $m->content_like( + qr{"DeleteLink--$type-.*?ticket/$active_id"}, + "$c for $type: has active ticket", + ); + $m->content_like( + qr{"DeleteLink--$type-.*?ticket/$inactive_id"}, + "base for $type: has inactive ticket", + ); + $m->content_unlike( + qr{"DeleteLink--$type-.*?ticket/$deleted_id"}, + "base for $type: no deleted ticket", + ); + } + else { + $m->content_like( + qr{"DeleteLink-.*?ticket/$active_id-$type-"}, + "$c for $type: has active ticket", + ); + $m->content_like( + qr{"DeleteLink-.*?ticket/$inactive_id-$type-"}, + "base for $type: has inactive ticket", + ); + $m->content_unlike( + qr{"DeleteLink-.*?ticket/$deleted_id-$type-"}, + "base for $type: no deleted ticket", + ); + } + } + + $m->goto_ticket($id); + $m->content_like( qr{$active_id:.*?\[new\]}, "has active ticket", ); + $m->content_like( + qr{$inactive_id:.*?\[resolved\]}, + "has inactive ticket", + ); + $m->content_unlike( qr{$deleted_id.*?\[deleted\]}, "no deleted ticket", + ); + } +} + diff --git a/rt/t/web/ticket_modify_all.t b/rt/t/web/ticket_modify_all.t new file mode 100644 index 000000000..c9dd7e7cd --- /dev/null +++ b/rt/t/web/ticket_modify_all.t @@ -0,0 +1,44 @@ +use strict; +use warnings; + +use RT::Test tests => 15; + +my $ticket = RT::Test->create_ticket( + Subject => 'test bulk update', + Queue => 1, +); + +my ( $url, $m ) = RT::Test->started_ok; +ok( $m->login, 'logged in' ); + +$m->get_ok( $url . "/Ticket/ModifyAll.html?id=" . $ticket->id ); + +$m->submit_form( + form_number => 3, + fields => { 'UpdateContent' => 'this is update content' }, + button => 'SubmitTicket', +); + +$m->content_contains("Message recorded", 'updated ticket'); +$m->content_lacks("this is update content", 'textarea is clear'); + +$m->get_ok($url . '/Ticket/Display.html?id=' . $ticket->id ); +$m->content_contains("this is update content", 'updated content in display page'); + +# NOTE http://issues.bestpractical.com/Ticket/Display.html?id=18284 +RT::Test->stop_server; +RT->Config->Set(AutocompleteOwners => 1); +($url, $m) = RT::Test->started_ok; +$m->login; + +$m->get_ok($url . '/Ticket/ModifyAll.html?id=' . $ticket->id); + +$m->form_name('TicketModifyAll'); +$m->field(Owner => 'root'); +$m->click('SubmitTicket'); + +$m->form_name('TicketModifyAll'); +is($m->value('Owner'), 'root', 'owner was successfully changed to root'); + +# XXX TODO test other parts, i.e. basic, dates, people and links + diff --git a/rt/t/web/ticket_modify_people.t b/rt/t/web/ticket_modify_people.t new file mode 100644 index 000000000..750be3f2c --- /dev/null +++ b/rt/t/web/ticket_modify_people.t @@ -0,0 +1,113 @@ +use strict; +use warnings; + +use RT::Test tests => 23; + +my $root = RT::Test->load_or_create_user( Name => 'root' ); +my $group_foo = RT::Group->new($RT::SystemUser); +my ( $ret, $msg ) = $group_foo->CreateUserDefinedGroup( + Name => 'group_foo', + Description => 'group_foo', +); +ok( $ret, 'created group_foo' ); + +my $ticket = RT::Test->create_ticket( + Subject => 'test modify people', + Queue => 'General', + Requestor => $root->id, + Cc => $group_foo->id, +); + +my $user = RT::Test->load_or_create_user( + Name => 'user', + Password => 'password', +); +ok $user && $user->id, 'loaded or created user'; + +ok( + RT::Test->set_rights( + { Principal => $user, Right => [qw(SeeQueue ShowTicket ModifyTicket)] }, + ), + 'set rights' +); + +my ( $url, $m ) = RT::Test->started_ok; +ok( $m->login( 'user', 'password' ), 'logged in' ); +$m->get_ok( $url . "/Ticket/ModifyPeople.html?id=" . $ticket->id ); + +ok( + !$m->find_link( + text => 'Enoch Root', + url_regex => qr!/Admin/Users/Modify\.html!, + ), + 'no link to modify user' +); +$m->content_contains('Enoch Root', 'still has the user name' ); + +ok( + !$m->find_link( + text => 'group_foo', + url_regex => qr!/Admin/Groups/Modify\.html!, + ), + 'no link to modify group' +); + +$m->content_contains('group_foo', 'still has the group name' ); + +ok( RT::Test->add_rights( { Principal => $user, Right => ['AdminUsers'] }, ), + 'added AdminUsers right' ); +$m->reload; +ok( + !$m->find_link( + text => 'Enoch Root', + url_regex => qr!/Admin/Users/Modify\.html!, + ), + 'still no link to modify user' +); +ok( + !$m->find_link( + text => 'group_foo', + url_regex => qr!/Admin/Groups/Modify\.html!, + ), + 'still no link to modify group' +); + +ok( + RT::Test->add_rights( { Principal => $user, Right => ['ShowConfigTab'] }, ), + 'added ShowConfigTab right', +); + +$m->reload; +ok( + $m->find_link( + text => 'Enoch Root', + url_regex => qr!/Admin/Users/Modify\.html!, + ), + 'got link to modify user' +); + +ok( + !$m->find_link( + text => 'group_foo', + url_regex => qr!/Admin/Groups/Modify\.html!, + ), + 'still no link to modify group' +); + +ok( + RT::Test->add_rights( { Principal => $user, Right => ['AdminGroup'] }, ), + 'added AdminGroup right' +); + +$m->reload; +ok( + $m->find_link( + text => 'group_foo', + url_regex => qr!/Admin/Groups/Modify\.html!, + ), + 'got link to modify group' +); + + +# TODO test Add|Delete people + diff --git a/rt/t/web/ticket_owner.t b/rt/t/web/ticket_owner.t index 0bacaf1bc..4db39e61a 100644 --- a/rt/t/web/ticket_owner.t +++ b/rt/t/web/ticket_owner.t @@ -3,7 +3,7 @@ use strict; use warnings; -use RT::Test tests => 91; +use RT::Test nodata => 1, tests => 105; my $queue = RT::Test->load_or_create_queue( Name => 'Regression' ); ok $queue && $queue->id, 'loaded or created queue'; @@ -18,26 +18,25 @@ my $user_b = RT::Test->load_or_create_user( ); ok $user_b && $user_b->id, 'loaded or created user'; -RT::Test->started_ok; +my ($baseurl, $agent_a) = RT::Test->started_ok; ok( RT::Test->set_rights( { Principal => $user_a, Right => [qw(SeeQueue ShowTicket CreateTicket ReplyToTicket)] }, { Principal => $user_b, Right => [qw(SeeQueue ShowTicket OwnTicket)] }, ), 'set rights'); -my $agent_a = RT::Test::Web->new; ok $agent_a->login('user_a', 'password'), 'logged in as user A'; -diag "current user has no right to own, nobody selected as owner on create" if $ENV{TEST_VERBOSE}; +diag "current user has no right to own, nobody selected as owner on create"; { $agent_a->get_ok('/', 'open home page'); $agent_a->form_name('CreateTicketInQueue'); $agent_a->select( 'Queue', $queue->id ); $agent_a->submit; - $agent_a->content_like(qr/Create a new ticket/i, 'opened create ticket page'); + $agent_a->content_contains('Create a new ticket', 'opened create ticket page'); my $form = $agent_a->form_name('TicketCreate'); - is $form->value('Owner'), $RT::Nobody->id, 'correct owner selected'; + is $form->value('Owner'), RT->Nobody->id, 'correct owner selected'; ok !grep($_ == $user_a->id, $form->find_input('Owner')->possible_values), 'user A can not own tickets'; $agent_a->submit; @@ -46,22 +45,22 @@ diag "current user has no right to own, nobody selected as owner on create" if $ my ($id) = ($agent_a->content =~ /Ticket (\d+) created in queue/); ok $id, 'found id of the ticket'; - my $ticket = RT::Ticket->new( $RT::SystemUser ); + my $ticket = RT::Ticket->new( RT->SystemUser ); $ticket->Load( $id ); ok $ticket->id, 'loaded the ticket'; - is $ticket->Owner, $RT::Nobody->id, 'correct owner'; + is $ticket->Owner, RT->Nobody->id, 'correct owner'; } -diag "user can chose owner of a new ticket" if $ENV{TEST_VERBOSE}; +diag "user can chose owner of a new ticket"; { $agent_a->get_ok('/', 'open home page'); $agent_a->form_name('CreateTicketInQueue'); $agent_a->select( 'Queue', $queue->id ); $agent_a->submit; - $agent_a->content_like(qr/Create a new ticket/i, 'opened create ticket page'); + $agent_a->content_contains('Create a new ticket', 'opened create ticket page'); my $form = $agent_a->form_name('TicketCreate'); - is $form->value('Owner'), $RT::Nobody->id, 'correct owner selected'; + is $form->value('Owner'), RT->Nobody->id, 'correct owner selected'; ok grep($_ == $user_b->id, $form->find_input('Owner')->possible_values), 'user B is listed as potential owner'; @@ -72,7 +71,7 @@ diag "user can chose owner of a new ticket" if $ENV{TEST_VERBOSE}; my ($id) = ($agent_a->content =~ /Ticket (\d+) created in queue/); ok $id, 'found id of the ticket'; - my $ticket = RT::Ticket->new( $RT::SystemUser ); + my $ticket = RT::Ticket->new( RT->SystemUser ); $ticket->Load( $id ); ok $ticket->id, 'loaded the ticket'; is $ticket->Owner, $user_b->id, 'correct owner'; @@ -81,7 +80,7 @@ diag "user can chose owner of a new ticket" if $ENV{TEST_VERBOSE}; my $agent_b = RT::Test::Web->new; ok $agent_b->login('user_b', 'password'), 'logged in as user B'; -diag "user A can not change owner after create" if $ENV{TEST_VERBOSE}; +diag "user A can not change owner after create"; { my $ticket = RT::Ticket->new( $user_a ); my ($id, $txn, $msg) = $ticket->Create( @@ -95,30 +94,29 @@ diag "user A can not change owner after create" if $ENV{TEST_VERBOSE}; # try the following group of tests twice with different agents(logins) my $test_cb = sub { my $agent = shift; - $agent->goto_ticket( $id ); - $agent->follow_link_ok({text => 'Basics'}, 'Ticket -> Basics'); - my $form = $agent->form_number(3); + $agent->get("/Ticket/Modify.html?id=$id"); + my $form = $agent->form_name('TicketModify'); is $form->value('Owner'), $user_b->id, 'correct owner selected'; - $agent->select('Owner', $RT::Nobody->id); + $agent->select('Owner', RT->Nobody->id); $agent->submit; - $agent->content_like( - qr/Permission denied/i, + $agent->content_contains( + 'Permission Denied', 'no way to change owner after create if you have no rights' ); - my $ticket = RT::Ticket->new( $RT::SystemUser ); + my $ticket = RT::Ticket->new( RT->SystemUser ); $ticket->Load( $id ); ok $ticket->id, 'loaded the ticket'; is $ticket->Owner, $user_b->id, 'correct owner'; }; $test_cb->($agent_a); - diag "even owner(user B) can not change owner" if $ENV{TEST_VERBOSE}; + diag "even owner(user B) can not change owner"; $test_cb->($agent_b); } -diag "on reply correct owner is selected" if $ENV{TEST_VERBOSE}; +diag "on reply correct owner is selected"; { my $ticket = RT::Ticket->new( $user_a ); my ($id, $txn, $msg) = $ticket->Create( @@ -130,13 +128,13 @@ diag "on reply correct owner is selected" if $ENV{TEST_VERBOSE}; is $ticket->Owner, $user_b->id, 'correct owner'; $agent_a->goto_ticket( $id ); - $agent_a->follow_link_ok({text => 'Reply'}, 'Ticket -> Basics'); + $agent_a->follow_link_ok({text => 'Reply'}, 'Ticket -> Reply'); - my $form = $agent_a->form_number(3); + my $form = $agent_a->form_name('TicketUpdate'); is $form->value('Owner'), '', 'empty value selected'; $agent_a->submit; - $ticket = RT::Ticket->new( $RT::SystemUser ); + $ticket = RT::Ticket->new( RT->SystemUser ); $ticket->Load( $id ); ok $ticket->id, 'loaded the ticket'; is $ticket->Owner, $user_b->id, 'correct owner'; @@ -147,7 +145,7 @@ ok( RT::Test->set_rights( { Principal => $user_b, Right => [qw(SeeQueue ShowTicket OwnTicket)] }, ), 'set rights'); -diag "Couldn't take without coresponding right" if $ENV{TEST_VERBOSE}; +diag "Couldn't take without coresponding right"; { my $ticket = RT::Ticket->new( $user_a ); my ($id, $txn, $msg) = $ticket->Create( @@ -155,7 +153,7 @@ diag "Couldn't take without coresponding right" if $ENV{TEST_VERBOSE}; Subject => 'test', ); ok $id, 'created a ticket #'. $id or diag "error: $msg"; - is $ticket->Owner, $RT::Nobody->id, 'correct owner'; + is $ticket->Owner, RT->Nobody->id, 'correct owner'; $agent_a->goto_ticket( $id ); ok !($agent_a->find_all_links( text => 'Take' ))[0], @@ -164,7 +162,7 @@ diag "Couldn't take without coresponding right" if $ENV{TEST_VERBOSE}; 'no Steal link as well'; } -diag "Couldn't steal without coresponding right" if $ENV{TEST_VERBOSE}; +diag "Couldn't steal without coresponding right"; { my $ticket = RT::Ticket->new( $user_a ); my ($id, $txn, $msg) = $ticket->Create( @@ -186,7 +184,7 @@ ok( RT::Test->set_rights( { Principal => $user_a, Right => [qw(SeeQueue ShowTicket CreateTicket TakeTicket)] }, ), 'set rights'); -diag "TakeTicket require OwnTicket to work" if $ENV{TEST_VERBOSE}; +diag "TakeTicket require OwnTicket to work"; { my $ticket = RT::Ticket->new( $user_a ); my ($id, $txn, $msg) = $ticket->Create( @@ -194,7 +192,7 @@ diag "TakeTicket require OwnTicket to work" if $ENV{TEST_VERBOSE}; Subject => 'test', ); ok $id, 'created a ticket #'. $id or diag "error: $msg"; - is $ticket->Owner, $RT::Nobody->id, 'correct owner'; + is $ticket->Owner, RT->Nobody->id, 'correct owner'; $agent_a->goto_ticket( $id ); ok !($agent_a->find_all_links( text => 'Take' ))[0], @@ -208,7 +206,7 @@ ok( RT::Test->set_rights( { Principal => $user_b, Right => [qw(SeeQueue ShowTicket OwnTicket)] }, ), 'set rights'); -diag "TakeTicket+OwnTicket work" if $ENV{TEST_VERBOSE}; +diag "TakeTicket+OwnTicket work"; { my $ticket = RT::Ticket->new( $user_a ); my ($id, $txn, $msg) = $ticket->Create( @@ -216,20 +214,20 @@ diag "TakeTicket+OwnTicket work" if $ENV{TEST_VERBOSE}; Subject => 'test', ); ok $id, 'created a ticket #'. $id or diag "error: $msg"; - is $ticket->Owner, $RT::Nobody->id, 'correct owner'; + is $ticket->Owner, RT->Nobody->id, 'correct owner'; $agent_a->goto_ticket( $id ); ok !($agent_a->find_all_links( text => 'Steal' ))[0], 'no Steal link'; $agent_a->follow_link_ok({text => 'Take'}, 'Ticket -> Take'); - $ticket = RT::Ticket->new( $RT::SystemUser ); + $ticket = RT::Ticket->new( RT->SystemUser ); $ticket->Load( $id ); ok $ticket->id, 'loaded the ticket'; is $ticket->Owner, $user_a->id, 'correct owner'; } -diag "TakeTicket+OwnTicket don't work when owner is not nobody" if $ENV{TEST_VERBOSE}; +diag "TakeTicket+OwnTicket don't work when owner is not nobody"; { my $ticket = RT::Ticket->new( $user_a ); my ($id, $txn, $msg) = $ticket->Create( @@ -252,7 +250,7 @@ ok( RT::Test->set_rights( { Principal => $user_b, Right => [qw(SeeQueue ShowTicket OwnTicket)] }, ), 'set rights'); -diag "StealTicket require OwnTicket to work" if $ENV{TEST_VERBOSE}; +diag "StealTicket require OwnTicket to work"; { my $ticket = RT::Ticket->new( $user_a ); my ($id, $txn, $msg) = $ticket->Create( @@ -275,7 +273,7 @@ ok( RT::Test->set_rights( { Principal => $user_b, Right => [qw(SeeQueue ShowTicket OwnTicket)] }, ), 'set rights'); -diag "StealTicket+OwnTicket work" if $ENV{TEST_VERBOSE}; +diag "StealTicket+OwnTicket work"; { my $ticket = RT::Ticket->new( $user_a ); my ($id, $txn, $msg) = $ticket->Create( @@ -291,13 +289,13 @@ diag "StealTicket+OwnTicket work" if $ENV{TEST_VERBOSE}; 'but no Take link'; $agent_a->follow_link_ok({text => 'Steal'}, 'Ticket -> Steal'); - $ticket = RT::Ticket->new( $RT::SystemUser ); + $ticket = RT::Ticket->new( RT->SystemUser ); $ticket->Load( $id ); ok $ticket->id, 'loaded the ticket'; is $ticket->Owner, $user_a->id, 'correct owner'; } -diag "StealTicket+OwnTicket don't work when owner is nobody" if $ENV{TEST_VERBOSE}; +diag "StealTicket+OwnTicket don't work when owner is nobody"; { my $ticket = RT::Ticket->new( $user_a ); my ($id, $txn, $msg) = $ticket->Create( @@ -305,7 +303,7 @@ diag "StealTicket+OwnTicket don't work when owner is nobody" if $ENV{TEST_VERBOS Subject => 'test', ); ok $id, 'created a ticket #'. $id or diag "error: $msg"; - is $ticket->Owner, $RT::Nobody->id, 'correct owner'; + is $ticket->Owner, RT->Nobody->id, 'correct owner'; $agent_a->goto_ticket( $id ); ok !($agent_a->find_all_links( text => 'Steal' ))[0], @@ -319,7 +317,7 @@ ok( RT::Test->set_rights( { Principal => $user_b, Right => [qw(SeeQueue ShowTicket OwnTicket)] }, ), 'set rights'); -diag "no Steal link when owner nobody" if $ENV{TEST_VERBOSE}; +diag "no Steal link when owner nobody"; { my $ticket = RT::Ticket->new( $user_a ); my ($id, $txn, $msg) = $ticket->Create( @@ -327,7 +325,7 @@ diag "no Steal link when owner nobody" if $ENV{TEST_VERBOSE}; Subject => 'test', ); ok $id, 'created a ticket #'. $id or diag "error: $msg"; - is $ticket->Owner, $RT::Nobody->id, 'correct owner'; + is $ticket->Owner, RT->Nobody->id, 'correct owner'; $agent_a->goto_ticket( $id ); ok !($agent_a->find_all_links( text => 'Steal' ))[0], @@ -336,7 +334,7 @@ diag "no Steal link when owner nobody" if $ENV{TEST_VERBOSE}; 'but have Take link'); } -diag "no Take link when owner is not nobody" if $ENV{TEST_VERBOSE}; +diag "no Take link when owner is not nobody"; { my $ticket = RT::Ticket->new( $user_a ); my ($id, $txn, $msg) = $ticket->Create( @@ -354,3 +352,68 @@ diag "no Take link when owner is not nobody" if $ENV{TEST_VERBOSE}; 'but have Steal link'); } +ok( + RT::Test->set_rights( + { + Principal => $user_a, + Right => [ + qw(SeeQueue ShowTicket CreateTicket ReplyToTicket OwnTicket TakeTicket StealTicket) + ] + }, + { Principal => $user_b, Right => [qw(SeeQueue ShowTicket OwnTicket)] }, + ), + 'set rights' +); + +diag +"action is Take if old owner is nobody and new owner is current user in update page"; +{ + my $ticket = RT::Ticket->new( $user_a ); + my ( $id, $txn, $msg ) = $ticket->Create( + Queue => $queue->id, + Subject => 'test', + ); + ok $id, 'created a ticket #'. $id or diag "error: $msg"; + is $ticket->Owner, RT->Nobody->id, 'correct owner'; + + $agent_a->goto_ticket( $id ); + $agent_a->content_lacks('Taken', 'no Taken'); + $agent_a->follow_link_ok({text => 'Reply'}, 'Ticket -> Reply'); + $agent_a->submit_form( + form_name => 'TicketUpdate', + fields => { Owner => $user_a->id }, + button => 'SubmitTicket', + ); + $agent_a->content_like( qr/user_a\s+-\s+Taken/, 'got user_a Taken message' ); + + $agent_b->goto_ticket($id); + $agent_b->content_like( qr/user_a\s+-\s+Taken/, 'got user_a Taken message for user b ' ); +} + +diag +"action is Take if old owner is nobody and new owner is current user in basics page"; +{ + my $ticket = RT::Ticket->new($user_a); + my ( $id, $txn, $msg ) = $ticket->Create( + Queue => $queue->id, + Subject => 'test', + ); + ok $id, 'created a ticket #' . $id or diag "error: $msg"; + is $ticket->Owner, RT->Nobody->id, 'correct owner'; + + $agent_a->goto_ticket($id); + $agent_a->content_lacks('Taken', 'no Taken'); + $agent_a->follow_link_ok( { text => 'Basics' }, 'Ticket -> Basics' ); + $agent_a->submit_form( + form_name => 'TicketModify', + fields => { Owner => $user_a->id }, + ); + $agent_a->content_contains( 'Owner changed from Nobody to user_a', + 'got set message in Basics' ); + $agent_a->goto_ticket($id); + $agent_a->content_like( qr/user_a\s+-\s+Taken/, 'got user_a Taken message' ); + + $agent_b->goto_ticket($id); + $agent_b->content_like( qr/user_a\s+-\s+Taken/, 'got user_a Taken message for user b ' ); +} + diff --git a/rt/t/web/ticket_owner_autocomplete.t b/rt/t/web/ticket_owner_autocomplete.t new file mode 100644 index 000000000..3aa3f282f --- /dev/null +++ b/rt/t/web/ticket_owner_autocomplete.t @@ -0,0 +1,185 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use RT::Test nodata => 1, tests => 43; +use JSON qw(from_json); + +my $queue = RT::Test->load_or_create_queue( Name => 'Regression' ); +ok $queue && $queue->id, 'loaded or created queue'; + +my $user_a = RT::Test->load_or_create_user( + Name => 'user_a', Password => 'password', +); +ok $user_a && $user_a->id, 'loaded or created user'; + +my $user_b = RT::Test->load_or_create_user( + Name => 'user_b', Password => 'password', +); +ok $user_b && $user_b->id, 'loaded or created user'; + +RT->Config->Set( AutocompleteOwners => 1 ); +my ($baseurl, $agent_a) = RT::Test->started_ok; + +ok( RT::Test->set_rights( + { Principal => $user_a, Right => [qw(SeeQueue ShowTicket CreateTicket ReplyToTicket)] }, + { Principal => $user_b, Right => [qw(SeeQueue ShowTicket OwnTicket)] }, +), 'set rights'); + +ok $agent_a->login('user_a', 'password'), 'logged in as user A'; + +diag "current user has no right to own, nobody selected as owner on create"; +{ + $agent_a->get_ok('/', 'open home page'); + $agent_a->form_name('CreateTicketInQueue'); + $agent_a->select( 'Queue', $queue->id ); + $agent_a->submit; + + $agent_a->content_contains('Create a new ticket', 'opened create ticket page'); + my $form = $agent_a->form_name('TicketCreate'); + is $form->value('Owner'), RT->Nobody->Name, 'correct owner selected'; + autocomplete_lacks( 'RT::Queue-'.$queue->id, 'user_a' ); + $agent_a->submit; + + $agent_a->content_like(qr/Ticket \d+ created in queue/i, 'created ticket'); + my ($id) = ($agent_a->content =~ /Ticket (\d+) created in queue/); + ok $id, 'found id of the ticket'; + + my $ticket = RT::Ticket->new( RT->SystemUser ); + $ticket->Load( $id ); + ok $ticket->id, 'loaded the ticket'; + is $ticket->Owner, RT->Nobody->id, 'correct owner'; +} + +diag "user can chose owner of a new ticket"; +{ + $agent_a->get_ok('/', 'open home page'); + $agent_a->form_name('CreateTicketInQueue'); + $agent_a->select( 'Queue', $queue->id ); + $agent_a->submit; + + $agent_a->content_contains('Create a new ticket', 'opened create ticket page'); + my $form = $agent_a->form_name('TicketCreate'); + is $form->value('Owner'), RT->Nobody->Name, 'correct owner selected'; + + autocomplete_contains( 'RT::Queue-'.$queue->id, 'user_b' ); + $form->value('Owner', $user_b->Name); + $agent_a->submit; + + $agent_a->content_like(qr/Ticket \d+ created in queue/i, 'created ticket'); + my ($id) = ($agent_a->content =~ /Ticket (\d+) created in queue/); + ok $id, 'found id of the ticket'; + + my $ticket = RT::Ticket->new( RT->SystemUser ); + $ticket->Load( $id ); + ok $ticket->id, 'loaded the ticket'; + is $ticket->Owner, $user_b->id, 'correct owner'; +} + +my $agent_b = RT::Test::Web->new; +ok $agent_b->login('user_b', 'password'), 'logged in as user B'; + +diag "user A can not change owner after create"; +{ + my $ticket = RT::Ticket->new( $user_a ); + my ($id, $txn, $msg) = $ticket->Create( + Queue => $queue->id, + Owner => $user_b->id, + Subject => 'test', + ); + ok $id, 'created a ticket #'. $id or diag "error: $msg"; + is $ticket->Owner, $user_b->id, 'correct owner'; + + # try the following group of tests twice with different agents(logins) + my $test_cb = sub { + my $agent = shift; + $agent->get("/Ticket/Modify.html?id=$id"); + my $form = $agent->form_name('TicketModify'); + is $form->value('Owner'), $user_b->Name, 'correct owner selected'; + $form->value('Owner', RT->Nobody->Name); + $agent->submit; + + $agent->content_contains( + 'Permission Denied', + 'no way to change owner after create if you have no rights' + ); + + my $ticket = RT::Ticket->new( RT->SystemUser ); + $ticket->Load( $id ); + ok $ticket->id, 'loaded the ticket'; + is $ticket->Owner, $user_b->id, 'correct owner'; + }; + + $test_cb->($agent_a); + diag "even owner(user B) can not change owner"; + $test_cb->($agent_b); +} + +diag "on reply correct owner is selected"; +{ + my $ticket = RT::Ticket->new( $user_a ); + my ($id, $txn, $msg) = $ticket->Create( + Queue => $queue->id, + Owner => $user_b->id, + Subject => 'test', + ); + ok $id, 'created a ticket #'. $id or diag "error: $msg"; + is $ticket->Owner, $user_b->id, 'correct owner'; + + $agent_a->goto_ticket( $id ); + $agent_a->follow_link_ok( { id => 'page-actions-reply' }, 'Reply' ); + + my $form = $agent_a->form_number(3); + is $form->value('Owner'), 'user_b', 'current user selected'; + $agent_a->submit; + + $ticket = RT::Ticket->new( RT->SystemUser ); + $ticket->Load( $id ); + ok $ticket->id, 'loaded the ticket'; + is $ticket->Owner, $user_b->id, 'correct owner'; +} + +sub autocomplete { + my $limit = shift; + my $agent = shift; + $agent->get_ok("/Helpers/Autocomplete/Owners?term=&limit=$limit&return=Name", "fetched autocomplete values"); + return from_json($agent->content); +} + +sub autocomplete_contains { + my $limit = shift; + my $expected = shift; + my $agent = shift; + + unless ( $agent ) { + $agent = RT::Test::Web->new; + $agent->login('user_a', 'password'); + } + + my $results = autocomplete( $limit, $agent ); + + my %seen; + $seen{$_->{value}}++ for @$results; + $expected = [$expected] unless ref $expected eq 'ARRAY'; + is((scalar grep { not $seen{$_} } @$expected), 0, "got all expected values"); +} + +sub autocomplete_lacks { + my $limit = shift; + my $lacks = shift; + my $agent = shift; + + unless ( $agent ) { + $agent = RT::Test::Web->new; + $agent->login('user_a', 'password'); + } + + my $results = autocomplete( $limit, $agent ); + + my %seen; + $seen{$_->{value}}++ for @$results; + $lacks = [$lacks] unless ref $lacks eq 'ARRAY'; + is((scalar grep { $seen{$_} } @$lacks), 0, "didn't get any unexpected values"); +} + diff --git a/rt/t/web/ticket_owner_issues_16656.t b/rt/t/web/ticket_owner_issues_16656.t new file mode 100644 index 000000000..a6306f740 --- /dev/null +++ b/rt/t/web/ticket_owner_issues_16656.t @@ -0,0 +1,63 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +use RT::Test tests => 19; + +my $queue = RT::Test->load_or_create_queue( Name => 'Test' ); +ok $queue && $queue->id, 'loaded or created queue'; + +my $user_a = RT::Test->load_or_create_user( + Name => 'user_a', + EmailAddress => 'user_a@example.com', + Password => 'password', +); +ok $user_a && $user_a->id, 'loaded or created user'; + +RT->Config->Set( AutocompleteOwners => 0 ); +my ($baseurl, $agent_root) = RT::Test->started_ok; + +ok( RT::Test->set_rights({ + Principal => 'Requestor', + Object => $queue, + Right => [qw(OwnTicket)] +}), 'set rights'); + +ok $agent_root->login('root', 'password'), 'logged in as user root'; + +diag "user_a doesn't show up in create form"; +{ + $agent_root->get_ok('/', 'open home page'); + $agent_root->form_name('CreateTicketInQueue'); + $agent_root->select( 'Queue', '1' ); + $agent_root->submit; + + $agent_root->content_contains('Create a new ticket', 'opened create ticket page'); + my $form = $agent_root->form_name('TicketCreate'); + my $input = $form->find_input('Owner'); + is $input->value, RT->Nobody->Id, 'correct owner selected'; + ok((not scalar grep { $_ == $user_a->Id } $input->possible_values), 'no user_a value in dropdown'); + $form->value('Requestors', 'user_a@example.com'); + $agent_root->submit; + + $agent_root->content_like(qr/Ticket \d+ created in queue/i, 'created ticket'); + my ($id) = ($agent_root->content =~ /Ticket (\d+) created in queue/); + ok $id, 'found id of the ticket'; + + my $ticket = RT::Ticket->new( RT->SystemUser ); + $ticket->Load( $id ); + ok $ticket->id, 'loaded the ticket'; + is $ticket->Queue, '1', 'correct queue'; + is $ticket->Owner, RT->Nobody->Id, 'correct owner'; + is $ticket->RequestorAddresses, 'user_a@example.com', 'correct requestor'; +} + +diag "user_a doesn't appear in owner list after being made requestor"; +{ + $agent_root->get("/Ticket/Modify.html?id=1"); + my $form = $agent_root->form_name('TicketModify'); + my $input = $form->find_input('Owner'); + is $input->value, RT->Nobody->Id, 'correct owner selected'; + ok((not scalar grep { $_ == $user_a->Id } $input->possible_values), 'no user_a value in dropdown'); +} + diff --git a/rt/t/web/ticket_seen.t b/rt/t/web/ticket_seen.t index 3a77a5899..8dacaf59f 100644 --- a/rt/t/web/ticket_seen.t +++ b/rt/t/web/ticket_seen.t @@ -3,7 +3,7 @@ use strict; use warnings; -use RT::Test tests => 21; +use RT::Test nodata => 1, tests => 23, config => 'Set($ShowUnreadMessageNotifications, 1);'; my $queue = RT::Test->load_or_create_queue( Name => 'Regression' ); ok $queue && $queue->id, 'loaded or created queue'; @@ -30,7 +30,7 @@ ok $agent_a->login('user_a', 'password'), 'logged in as user A'; my $agent_b = RT::Test::Web->new; ok $agent_b->login('user_b', 'password'), 'logged in as user B'; -diag "create a ticket for testing" if $ENV{TEST_VERBOSE}; +diag "create a ticket for testing"; my $tid; { my $ticket = RT::Ticket->new( $user_a ); @@ -44,7 +44,7 @@ my $tid; is $ticket->Owner, $user_a->id, 'correct owner'; } -diag "user B adds a message, we check that user A see notification and can clear it" if $ENV{TEST_VERBOSE}; +diag "user B adds a message, we check that user A see notification and can clear it"; { my $ticket = RT::Ticket->new( $user_b ); $ticket->Load( $tid ); @@ -62,10 +62,10 @@ diag "user B adds a message, we check that user A see notification and can clear ok( $reply_id, 'got correspond txn id' ); $agent_a->goto_ticket($tid); - $agent_a->content_like(qr/bla-bla/ims, 'the message on the page'); + $agent_a->content_contains('bla-bla', 'the message on the page'); - $agent_a->content_like( - qr/unread message/ims, + $agent_a->content_contains( + 'unread message', 'we have not seen something' ); @@ -76,20 +76,20 @@ diag "user B adds a message, we check that user A see notification and can clear like( $agent_a->base, qr/#txn-$reply_id$/, 'contains anchor' ); $agent_a->follow_link_ok({text => 'jump to the first unread message and mark all messages as seen'}, 'try to mark all as seen'); - $agent_a->content_like( - qr/Marked all messages as seen/ims, + $agent_a->content_contains( + 'Marked all messages as seen', 'see success message' ); like( $agent_a->base, qr/#txn-$reply_id$/, 'contains anchor' ); - $agent_a->content_like( - qr/Marked all messages as seen/ims, + $agent_a->content_contains( + 'Marked all messages as seen', 'see success message' ); $agent_a->goto_ticket($tid); - $agent_a->content_unlike( - qr/unread message/ims, + $agent_a->content_lacks( + 'unread message', 'we have seen everything, so no messages' ); } diff --git a/rt/t/web/ticket_txn_content.t b/rt/t/web/ticket_txn_content.t index 1c1056a3e..db4751218 100644 --- a/rt/t/web/ticket_txn_content.t +++ b/rt/t/web/ticket_txn_content.t @@ -1,37 +1,48 @@ #!/usr/bin/perl -w use strict; -use RT::Test tests => 37; -use File::Temp 'tempfile'; -use File::Spec; -my ( $plain_fh, $plain_file ) = - tempfile( 'rttestXXXXXX', SUFFIX => '.txt', UNLINK => 1, TMPDIR => 1 ); +use RT::Test tests => 63; +my $plain_file = File::Spec->catfile( RT::Test->temp_directory, 'attachment.txt' ); +open my $plain_fh, '>', $plain_file or die $!; print $plain_fh "this is plain content"; close $plain_fh; my $plain_name = (File::Spec->splitpath($plain_file))[-1]; -my ( $html_fh, $html_file ) = - tempfile( 'rttestXXXXXX', SUFFIX => '.html', UNLINK => 1, TMPDIR => 1 ); -print $html_fh "this is html content"; +my $html_file = File::Spec->catfile( RT::Test->temp_directory, 'attachment.html' ); +open my $html_fh, '>', $html_file or die $!; +print $html_fh "this is plain content"; close $html_fh; my $html_name = (File::Spec->splitpath($html_file))[-1]; my ($baseurl, $m) = RT::Test->started_ok; ok $m->login, 'logged in'; -my $queue = RT::Queue->new($RT::Nobody); +my $queue = RT::Queue->new(RT->Nobody); my $qid = $queue->Load('General'); ok( $qid, "Loaded General queue" ); -RT::Test->set_mail_catcher; RT::Test->clean_caught_mails; +sub follow_parent_with_headers_link { + my $m = shift; + my $link = $m->find_link(@_)->url; + $link =~ s{/(\d+)$}{"/" . ($1-1)}e; # get the parent attach + $m->get_ok($baseurl . $link); +} + +sub follow_with_headers_link { + my $m = shift; + my $link = $m->find_link(@_)->url; + $link =~ s{/\d+/(\d+)/.+$}{/WithHeaders/$1}; # frob into a with headers url + $m->get_ok($baseurl . $link); +} + for my $type ( 'text/plain', 'text/html' ) { $m->form_name('CreateTicketInQueue'); $m->field( 'Queue', $qid ); $m->submit; is( $m->status, 200, "request successful" ); - $m->content_like( qr/Create a new ticket/, 'ticket create page' ); + $m->content_contains('Create a new ticket', 'ticket create page' ); $m->form_name('TicketCreate'); $m->field( 'Subject', 'with plain attachment' ); @@ -40,16 +51,26 @@ for my $type ( 'text/plain', 'text/html' ) { $m->field( 'ContentType', $type ) unless $type eq 'text/plain'; $m->submit; is( $m->status, 200, "request successful" ); - $m->content_like( qr/with plain attachment/, + $m->content_contains('with plain attachment', 'we have subject on the page' ); - $m->content_like( qr/this is main content/, 'main content' ); - $m->content_like( qr/Download $plain_name/, 'download plain file link' ); + $m->content_contains('this is main content', 'main content' ); + $m->content_contains("Download $plain_name", 'download plain file link' ); + + # Check for Message-IDs + follow_parent_with_headers_link($m, text => 'with headers', n => 1); + $m->content_like(qr/^Message-ID:/im, 'create content has one Message-ID'); + $m->content_unlike(qr/^Message-ID:.+?Message-ID:/ism, 'but not two Message-IDs'); + $m->back; + + follow_with_headers_link($m, text => "Download $plain_name", n => 1); + $m->content_unlike(qr/^Message-ID:/im, 'attachment lacks a Message-ID'); + $m->back; my ( $mail ) = RT::Test->fetch_caught_mails; like( $mail, qr/this is main content/, 'email contains main content' ); # check the email link in page too $m->follow_link_ok( { text => 'Show' }, 'show the email outgoing' ); - $m->content_like( qr/this is main content/, 'email contains main content'); + $m->content_contains('this is main content', 'email contains main content'); $m->back; $m->follow_link_ok( { text => 'Reply' }, "reply to the ticket" ); @@ -67,13 +88,27 @@ for my $type ( 'text/plain', 'text/html' ) { $m->click('SubmitTicket'); is( $m->status, 200, "request successful" ); - $m->content_like( qr/this is main reply content/, 'main reply content' ); - $m->content_like( qr/Download $html_name/, 'download html file link' ); + $m->content_contains("this is main reply content", 'main reply content' ); + $m->content_contains("Download $html_name", 'download html file link' ); + + # Check for Message-IDs + follow_parent_with_headers_link($m, text => 'with headers', n => 2); + $m->content_like(qr/^Message-ID:/im, 'correspondence has one Message-ID'); + $m->content_unlike(qr/^Message-ID:.+?Message-ID:/ism, 'but not two Message-IDs'); + $m->back; + + follow_with_headers_link($m, text => "Download $plain_name", n => 2); + $m->content_unlike(qr/^Message-ID:/im, 'text/plain attach lacks a Message-ID'); + $m->back; + + follow_with_headers_link($m, text => "Download $html_name", n => 1); + $m->content_unlike(qr/^Message-ID:/im, 'text/html attach lacks a Message-ID'); + $m->back; ( $mail ) = RT::Test->fetch_caught_mails; like( $mail, qr/this is main reply content/, 'email contains main reply content' ); # check the email link in page too $m->follow_link_ok( { text => 'Show', n => 2 }, 'show the email outgoing' ); - $m->content_like( qr/this is main reply content/, 'email contains main reply content'); + $m->content_contains("this is main reply content", 'email contains main reply content'); $m->back; } diff --git a/rt/t/web/ticket_update_without_content.t b/rt/t/web/ticket_update_without_content.t index 595cb74e9..54f0c5a8a 100644 --- a/rt/t/web/ticket_update_without_content.t +++ b/rt/t/web/ticket_update_without_content.t @@ -2,11 +2,11 @@ use strict; use warnings; -use RT::Test tests => 10; +use RT::Test tests => 12; my ( $url, $m ) = RT::Test->started_ok; # merged tickets still show up in search -my $ticket = RT::Ticket->new($RT::SystemUser); +my $ticket = RT::Ticket->new(RT->SystemUser); my ( $ret, $msg ) = $ticket->Create( Subject => 'base ticket' . $$, Queue => 'general', @@ -30,10 +30,10 @@ $m->submit_form( fields => { Priority => '1', } ); -$m->content_like(qr/priority changed/i); -$m->content_unlike(qr/message recorded/i); +$m->content_contains("Priority changed"); +$m->content_lacks("message recorded"); -my $root = RT::User->new( $RT::SystemUser ); +my $root = RT::User->new( RT->SystemUser ); $root->Load('root'); ( $ret, $msg ) = $root->SetSignature(<<EOF); best wishes @@ -48,5 +48,5 @@ $m->submit_form( form_number => 3, fields => { Priority => '2', } ); -$m->content_like(qr/priority changed/i); -$m->content_unlike(qr/message recorded/i); +$m->content_contains("Priority changed"); +$m->content_lacks("message recorded"); diff --git a/rt/t/web/transaction_batch.t b/rt/t/web/transaction_batch.t new file mode 100644 index 000000000..ae04e1fca --- /dev/null +++ b/rt/t/web/transaction_batch.t @@ -0,0 +1,55 @@ +use strict; +use warnings; +use RT; +use RT::Test tests => 12; + + +my $q = RT::Test->load_or_create_queue ( Name => 'General' ); + +my $s1 = RT::Scrip->new(RT->SystemUser); +my ($val, $msg) =$s1->Create( Queue => $q->Id, + ScripCondition => 'User Defined', + ScripAction => 'User Defined', + CustomIsApplicableCode => 'return ($self->TransactionObj->Field||"") eq "TimeEstimated"', + CustomPrepareCode => 'return 1', + CustomCommitCode => '$self->TicketObj->SetPriority($self->TicketObj->Priority + 2); return 1;', + Template => 'Blank', + Stage => 'TransactionBatch', + ); +ok($val,$msg); + +my $ticket = RT::Ticket->new(RT->SystemUser); +my ($tv,$ttv,$tm) = $ticket->Create(Queue => $q->Id, + Subject => "hair on fire", + ); +ok($tv, $tm); + +# Flush the Create transaction off of the ticket +$ticket->ApplyTransactionBatch; + +my $testuser = RT::Test->load_or_create_user( Name => 'bob', EmailAddress => 'bob@example.com', Password => 'password' ); +ok($testuser->Id, "Created test user bob"); + +ok( RT::Test->add_rights({ Principal => 'Privileged', Right => [qw(ShowTicket ModifyTicket SeeQueue)]}), 'Granted ticket management rights'); + +my $test_current_user = RT::CurrentUser->new(); +$test_current_user->LoadByName($testuser->Name); +my $api_test = RT::Ticket->new($test_current_user); +$api_test->Load($ticket->Id); +is($api_test->Priority,0,"Ticket priority starts at 0"); +$api_test->SetTimeEstimated(12); +$api_test->ApplyTransactionBatch; +is($api_test->CurrentUser->UserObj->Name, $testuser->Name,"User didn't change running Transaction Batch scrips"); +$api_test->Load($api_test->Id); +is($api_test->Priority,2,"Ticket priority updated"); + +my ($baseurl, $m) = RT::Test->started_ok; +$m->login('bob','password'); +$m->get_ok("$baseurl/Ticket/Modify.html?id=".$ticket->Id); + $m->submit_form( form_name => 'TicketModify', + fields => { TimeEstimated => 5 } + ); + + +$ticket->Load($ticket->Id); +is ($ticket->Priority , 4, "Ticket priority is set right"); diff --git a/rt/t/web/unlimited_search.t b/rt/t/web/unlimited_search.t index d98baaac0..988a2918d 100644 --- a/rt/t/web/unlimited_search.t +++ b/rt/t/web/unlimited_search.t @@ -2,12 +2,12 @@ use strict; -use RT::Test tests => 8; -RT::Test->started_ok; +use RT::Test tests => 85; +my ($baseurl, $agent) = RT::Test->started_ok; -my $ticket = RT::Ticket->new($RT::SystemUser); +my $ticket = RT::Ticket->new(RT->SystemUser); for ( 1 .. 75 ) { - $ticket->Create( + ok $ticket->Create( Subject => 'Ticket ' . $_, Queue => 'General', Owner => 'root', @@ -15,7 +15,6 @@ for ( 1 .. 75 ) { ); } -my $agent = RT::Test::Web->new; ok $agent->login('root', 'password'), 'logged in as root'; $agent->get_ok('/Search/Build.html'); @@ -27,7 +26,7 @@ $agent->form_name('BuildQuery'); $agent->field('RowsPerPage', '0'); $agent->submit('DoSearch'); $agent->follow_link_ok({text=>'Show Results'}); -$agent->content_like(qr/Ticket 75/); +$agent->content_contains("Ticket 75"); $agent->follow_link_ok({text=>'New Search'}); $agent->form_name('BuildQuery'); @@ -38,4 +37,4 @@ $agent->form_name('BuildQuery'); $agent->field('RowsPerPage', '50'); $agent->submit('DoSearch'); $agent->follow_link_ok({text=>'Bulk Update'}); -$agent->content_unlike(qr/Ticket 51/); +$agent->content_lacks("Ticket 51"); diff --git a/rt/t/web/user_update.t b/rt/t/web/user_update.t new file mode 100644 index 000000000..dc908fc10 --- /dev/null +++ b/rt/t/web/user_update.t @@ -0,0 +1,32 @@ +#!/usr/bin/perl +use strict; +use warnings; +use utf8; +use RT::Test tests => 9; + +my ( $url, $m ) = RT::Test->started_ok; +ok( $m->login(), 'logged in' ); + +$m->follow_link_ok({text => 'About me'}); +$m->form_with_fields('Lang'); +$m->field(Lang => 'ja'); +$m->submit; + +$m->text_contains("Lang changed from (no value) to 'ja'"); + +# we only changed one field, and it wasn't the default, so this feedback is +# spurious and annoying +$m->content_lacks("That is already the current value"); + +# change back to English +$m->form_with_fields('Lang'); +$m->field(Lang => 'en_us'); +$m->submit; + +# This message shows up in Japanese +# $m->text_contains("Lang changed from 'ja' to 'en_us'"); +$m->text_contains("Langは「'ja'」から「'en_us'」に変更されました"); + +# another spurious update +$m->content_lacks("That is already the current value"); + diff --git a/rt/t/web/walk.t b/rt/t/web/walk.t new file mode 100644 index 000000000..34fab1476 --- /dev/null +++ b/rt/t/web/walk.t @@ -0,0 +1,92 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use RT::Test; +use HTML::TreeBuilder; + +my ( $baseurl, $m ) = RT::Test->started_ok; + +ok( $m->login( 'root' => 'password' ), 'login as root' ); + +my %viewed = ( '/NoAuth/Logout.html' => 1 ); # in case logout + +my $user = RT::User->new($RT::SystemUser); +$user->Load('root'); +ok( $user->id, 'loaded root' ); + +my $queue = RT::Queue->new($RT::SystemUser); +$queue->Load('General'); +ok( $queue->id, 'loaded General queue' ); + +my $group = RT::Group->new($RT::SystemUser); +ok( $group->CreateUserDefinedGroup( Name => 'group_foo' ) ); +my $cf = RT::CustomField->new($RT::SystemUser); +ok( + $cf->Create( + Name => 'cf_foo', + Type => 'Freeform', + LookupType => 'RT::Queue-RT::Ticket', + ) +); +ok( $cf->id, 'created cf_foo' ); + +my $class = RT::Class->new($RT::SystemUser); +ok( $class->Create( Name => 'class_foo' ) ); +ok( $class->id, 'created class_foo' ); + +# to make search have results +my $open_ticket = RT::Test->create_ticket( + Subject => 'ticket_foo', + Queue => 1, +); + +my $resolved_ticket = RT::Test->create_ticket( + Subject => 'ticket_bar', + Status => 'resolved', + Queue => 1, +); + +my @links = ( + '/', + '/Admin/Users/Modify.html?id=' . $user->id, + '/Admin/Groups/Modify.html?id=' . $group->id, + '/Admin/Queues/Modify.html?id=' . $queue->id, + '/Admin/CustomFields/Modify.html?id=' . $cf->id, + '/Admin/Global/Scrip.html?id=1', + '/Admin/Global/Template.html?Template=1', + '/Admin/Articles/Classes/Modify.html?id=' . $class->id, + '/Search/Build.html?Query=id<10', + '/Ticket/Display.html?id=' . $open_ticket->id, + '/Ticket/Display.html?id=' . $resolved_ticket->id, +); + +for my $link (@links) { + test_page($m, $link); +} + +$m->get_ok('/NoAuth/Logout.html'); + +sub test_page { + my $m = shift; + my $link = shift; + $m->get_ok( $link, $link ); + $m->no_warnings_ok($link); + + my $tree = HTML::TreeBuilder->new(); + $tree->parse( $m->content ); + $tree->elementify; + my ($top_menu) = $tree->look_down( id => 'main-navigation' ); + my ($page_menu) = $tree->look_down( id => 'page-navigation' ); + + my (@links) = + grep { !$viewed{$_}++ && /^[^#]/ } + map { $_->attr('href') || () } ( $top_menu ? $top_menu->find('a') : () ), + ( $page_menu ? $page_menu->find('a') : () ); + + for my $link (@links) { + test_page($m, $link); + } +} + |