diff options
Diffstat (limited to 'rt/t')
27 files changed, 1730 insertions, 86 deletions
diff --git a/rt/t/api/attachment.t b/rt/t/api/attachment.t index 07c46bad0..282d2a3de 100644 --- a/rt/t/api/attachment.t +++ b/rt/t/api/attachment.t @@ -2,7 +2,7 @@ use strict; use warnings; use RT; -use RT::Test tests => 4; +use RT::Test tests => 7; { @@ -42,4 +42,28 @@ is ($#headers, 2, "testing a bunch of singline multiple headers" ); } + +{ + my $iso_8859_1_ticket_email = + RT::Test::get_relocatable_file( 'new-ticket-from-iso-8859-1', + ( File::Spec->updir(), 'data', 'emails' ) ); + my $content = RT::Test->file_content($iso_8859_1_ticket_email); + + my $parser = RT::EmailParser->new; + $parser->ParseMIMEEntityFromScalar($content); + my $attachment = RT::Attachment->new( $RT::SystemUser ); + my ( $id, $msg ) = + $attachment->Create( TransactionId => 1, Attachment => $parser->Entity ); + ok( $id, $msg ); + my $mime = $attachment->ContentAsMIME; + like( $mime->head->get('Content-Type'), + qr/charset="iso-8859-1"/, 'content type of ContentAsMIME is original' ); + require Encode; + is( + Encode::decode( 'iso-8859-1', $mime->stringify_body ), + Encode::decode( 'utf8', "Håvard\n" ), + 'body of ContentAsMIME is original' + ); +} + 1; diff --git a/rt/t/api/attachment_filename.t b/rt/t/api/attachment_filename.t new file mode 100644 index 000000000..2eced0127 --- /dev/null +++ b/rt/t/api/attachment_filename.t @@ -0,0 +1,39 @@ +use RT::Test tests => 5; +use MIME::Entity; +my $ticket = RT::Ticket->new($RT::SystemUser); +my $mime = MIME::Entity->build( + From => 'test@example.com', + Type => 'text/html', + Data => ["test attachment's filename\n"], +); + +$mime->attach( + Path => 'share/html/NoAuth/images/bplogo.gif', + Type => 'image/gif', +); + +$mime->attach( + Path => 'share/html/NoAuth/images/bplogo.gif', + Type => 'image/gif', + Filename => 'bplogo.gif', +); + +$mime->attach( + Path => 'share/html/NoAuth/images/bplogo.gif', + Filename => 'images/bplogo.gif', + Type => 'image/gif', +); + +my $id = $ticket->Create( MIMEObj => $mime, Queue => 'General' ); +ok( $id, "created ticket $id" ); + +my $atts = RT::Attachments->new( $RT::SystemUser ); +$atts->Limit( FIELD => 'ContentType', VALUE => 'image/gif' ); +is( $atts->Count, 3, 'got 3 gif files' ); + +# no matter if mime's filename include path or not, +# we should throw away the path all the time. +while ( my $att = $atts->Next ) { + is( $att->Filename, 'bplogo.gif', "attachment's filename" ); +} + diff --git a/rt/t/api/cf_rights.t b/rt/t/api/cf_rights.t new file mode 100644 index 000000000..f55214a66 --- /dev/null +++ b/rt/t/api/cf_rights.t @@ -0,0 +1,51 @@ +#!/usr/bin/perl +use warnings; +use strict; + +use RT; +use RT::Test tests => 12; + +my $q = RT::Queue->new($RT::SystemUser); +my ($id,$msg) =$q->Create(Name => "CF-Rights-".$$); +ok($id,$msg); + +my $cf = RT::CustomField->new($RT::SystemUser); +($id,$msg) = $cf->Create(Name => 'CF-'.$$, Type => 'Select', MaxValues => '1', Queue => $q->id); +ok($id,$msg); + + +($id,$msg) =$cf->AddValue(Name => 'First'); +ok($id,$msg); + +my $u = RT::User->new($RT::SystemUser); +($id,$msg) = $u->Create( Name => 'User1', Privileged => 1 ); +ok ($id,$msg); + +($id,$msg) = $u->PrincipalObj->GrantRight( Object => $cf, Right => 'SeeCustomField' ); +ok ($id,$msg); + +my $ucf = RT::CustomField->new($u); +($id,$msg) = $ucf->Load( $cf->Id ); +ok ($id,$msg); + +my $cfv = $ucf->Values->First; + +($id,$msg) = $cfv->SetName( 'First1' ); +ok (!$id,$msg); + +($id,$msg) = $u->PrincipalObj->GrantRight( Object => $cf, Right => 'AdminCustomFieldValues' ); +ok ($id,$msg); + +($id,$msg) = $cfv->SetName( 'First2' ); +ok ($id,$msg); + +($id,$msg) = $u->PrincipalObj->RevokeRight( Object => $cf, Right => 'AdminCustomFieldValues' ); +ok ($id,$msg); + +($id,$msg) = $u->PrincipalObj->GrantRight( Object => $cf, Right => 'AdminCustomField' ); +ok ($id,$msg); + +($id,$msg) = $cfv->SetName( 'First3' ); +ok ($id,$msg); + +1; diff --git a/rt/t/api/link.t b/rt/t/api/link.t index 1fd66bb64..eac9ae29a 100644 --- a/rt/t/api/link.t +++ b/rt/t/api/link.t @@ -1,24 +1,209 @@ use strict; use warnings; -use RT; -use RT::Test tests => 5; - - -{ +use RT::Test tests => 77; +use RT::Test::Web; use RT::Link; my $link = RT::Link->new($RT::SystemUser); ok (ref $link); -ok (UNIVERSAL::isa($link, 'RT::Link')); -ok (UNIVERSAL::isa($link, 'RT::Base')); -ok (UNIVERSAL::isa($link, 'RT::Record')); -ok (UNIVERSAL::isa($link, 'DBIx::SearchBuilder::Record')); +isa_ok( $link, 'RT::Link'); +isa_ok( $link, 'RT::Base'); +isa_ok( $link, 'RT::Record'); +isa_ok( $link, 'DBIx::SearchBuilder::Record'); + +my $queue = RT::Test->load_or_create_queue(Name => 'General'); +ok($queue->Id, "loaded the General queue"); + +my $parent = RT::Ticket->new($RT::SystemUser); +my ($pid, undef, $msg) = $parent->Create( + Queue => $queue->id, + Subject => 'parent', +); +ok $pid, 'created a ticket #'. $pid or diag "error: $msg"; + +my $child = RT::Ticket->new($RT::SystemUser); +my ($cid, undef, $msg) = $child->Create( + Queue => $queue->id, + Subject => 'child', +); +ok $cid, 'created a ticket #'. $cid or diag "error: $msg"; + +{ + clean_links(); + my ($status, $msg) = $parent->AddLink; + ok(!$status, "didn't create a link: $msg"); + + ($status, $msg) = $parent->AddLink( Base => $parent->id ); + ok(!$status, "didn't create a link: $msg"); + + ($status, $msg) = $parent->AddLink( Base => $parent->id, Type => 'HasMember' ); + ok(!$status, "didn't create a link: $msg"); +} + +{ + clean_links(); + my ($status, $msg) = $parent->AddLink( + Type => 'MemberOf', Base => $child->id, + ); + ok($status, "created a link: $msg"); + + my $children = $parent->Members; + $children->RedoSearch; $children->GotoFirstItem; + is $children->Count, 1, 'link is there'; + + my $link = $children->First; + ok $link->id, 'correct link'; + + is $link->Type, 'MemberOf', 'type'; + is $link->LocalTarget, $parent->id, 'local target'; + is $link->LocalBase, $child->id, 'local base'; + is $link->Target, 'fsck.com-rt://example.com/ticket/'. $parent->id, 'local target'; + is $link->Base, 'fsck.com-rt://example.com/ticket/'. $child->id, 'local base'; + + isa_ok $link->TargetObj, 'RT::Ticket'; + is $link->TargetObj->id, $parent->id, 'correct ticket'; + + isa_ok $link->TargetURI, 'RT::URI'; + is $link->TargetURI->Scheme, 'fsck.com-rt', 'correct scheme'; + is $link->TargetURI->URI, + 'fsck.com-rt://example.com/ticket/'. $parent->id, + 'correct URI' + ; + ok $link->TargetURI->IsLocal, 'local object'; + is $link->TargetURI->AsHREF, + RT::Test::Web->rt_base_url .'Ticket/Display.html?id='. $parent->id, + 'correct href' + ; + + isa_ok $link->BaseObj, 'RT::Ticket'; + is $link->BaseObj->id, $child->id, 'correct ticket'; + + isa_ok $link->BaseURI, 'RT::URI'; + is $link->BaseURI->Scheme, 'fsck.com-rt', 'correct scheme'; + is $link->BaseURI->URI, + 'fsck.com-rt://example.com/ticket/'. $child->id, + 'correct URI' + ; + ok $link->BaseURI->IsLocal, 'local object'; + is $link->BaseURI->AsHREF, + RT::Test::Web->rt_base_url .'Ticket/Display.html?id='. $child->id, + 'correct href' + ; +} + +{ + clean_links(); + my ($status, $msg) = $parent->AddLink( + Type => 'MemberOf', Base => $child->URI, + ); + ok($status, "created a link: $msg"); + + my $children = $parent->Members; + $children->RedoSearch; $children->GotoFirstItem; + is $children->Count, 1, 'link is there'; + + my $link = $children->First; + ok $link->id, 'correct link'; + + is $link->Type, 'MemberOf', 'type'; + is $link->LocalTarget, $parent->id, 'local target'; + is $link->LocalBase, $child->id, 'local base'; + is $link->Target, 'fsck.com-rt://example.com/ticket/'. $parent->id, 'local target'; + is $link->Base, 'fsck.com-rt://example.com/ticket/'. $child->id, 'local base'; + + isa_ok $link->TargetObj, 'RT::Ticket'; + is $link->TargetObj->id, $parent->id, 'correct ticket'; + + isa_ok $link->TargetURI, 'RT::URI'; + is $link->TargetURI->Scheme, 'fsck.com-rt', 'correct scheme'; + is $link->TargetURI->URI, + 'fsck.com-rt://example.com/ticket/'. $parent->id, + 'correct URI' + ; + ok $link->TargetURI->IsLocal, 'local object'; + is $link->TargetURI->AsHREF, + RT::Test::Web->rt_base_url .'Ticket/Display.html?id='. $parent->id, + 'correct href' + ; + + isa_ok $link->BaseObj, 'RT::Ticket'; + is $link->BaseObj->id, $child->id, 'correct ticket'; + + isa_ok $link->BaseURI, 'RT::URI'; + is $link->BaseURI->Scheme, 'fsck.com-rt', 'correct scheme'; + is $link->BaseURI->URI, + 'fsck.com-rt://example.com/ticket/'. $child->id, + 'correct URI' + ; + ok $link->BaseURI->IsLocal, 'local object'; + is $link->BaseURI->AsHREF, + RT::Test::Web->rt_base_url .'Ticket/Display.html?id='. $child->id, + 'correct href' + ; +} + +{ + clean_links(); + my ($status, $msg) = $parent->AddLink( + Type => 'MemberOf', Base => 't:'. $child->id, + ); + ok($status, "created a link: $msg"); + + my $children = $parent->Members; + $children->RedoSearch; $children->GotoFirstItem; + is $children->Count, 1, 'link is there'; + + my $link = $children->First; + ok $link->id, 'correct link'; + is $link->Type, 'MemberOf', 'type'; + is $link->LocalTarget, $parent->id, 'local target'; + is $link->LocalBase, $child->id, 'local base'; + is $link->Target, 'fsck.com-rt://example.com/ticket/'. $parent->id, 'local target'; + is $link->Base, 'fsck.com-rt://example.com/ticket/'. $child->id, 'local base'; + + isa_ok $link->TargetObj, 'RT::Ticket'; + is $link->TargetObj->id, $parent->id, 'correct ticket'; + + isa_ok $link->TargetURI, 'RT::URI'; + is $link->TargetURI->Scheme, 'fsck.com-rt', 'correct scheme'; + is $link->TargetURI->URI, + 'fsck.com-rt://example.com/ticket/'. $parent->id, + 'correct URI' + ; + ok $link->TargetURI->IsLocal, 'local object'; + is $link->TargetURI->AsHREF, + RT::Test::Web->rt_base_url .'Ticket/Display.html?id='. $parent->id, + 'correct href' + ; + + isa_ok $link->BaseObj, 'RT::Ticket'; + is $link->BaseObj->id, $child->id, 'correct ticket'; + + isa_ok $link->BaseURI, 'RT::URI'; + is $link->BaseURI->Scheme, 'fsck.com-rt', 'correct scheme'; + is $link->BaseURI->URI, + 'fsck.com-rt://example.com/ticket/'. $child->id, + 'correct URI' + ; + ok $link->BaseURI->IsLocal, 'local object'; + is $link->BaseURI->AsHREF, + RT::Test::Web->rt_base_url .'Ticket/Display.html?id='. $child->id, + 'correct href' + ; +} +sub clean_links { + my $links = RT::Links->new( $RT::SystemUser ); + while ( my $link = $links->Next ) { + my ($status, $msg) = $link->Delete; + $RT::Logger->error("Couldn't delete a link: $msg") + unless $status; + } } 1; diff --git a/rt/t/api/password-types.t b/rt/t/api/password-types.t new file mode 100644 index 000000000..267a6ede4 --- /dev/null +++ b/rt/t/api/password-types.t @@ -0,0 +1,31 @@ +#!/usr/bin/perl -w +use strict; +use warnings; + +use RT::Test; +use Digest::MD5; + +my $root = RT::User->new(RT->SystemUser); +$root->Load("root"); + +# Salted truncated SHA-256 +my $old = $root->__Value("Password"); +is(length($old), 40, "Stored as truncated salted SHA-256"); +ok($root->IsPassword("password")); +is($root->__Value("Password"), $old, "Unchanged after password check"); + +# Crypt +$root->_Set( Field => "Password", Value => crypt("something", "salt")); +ok($root->IsPassword("something"), "crypt()ed password works"); +is(length($root->__Value("Password")), 40, "And is now upgraded to truncated salted SHA-256"); + +# MD5, hex +$root->_Set( Field => "Password", Value => Digest::MD5::md5_hex("changed")); +ok($root->IsPassword("changed"), "Unsalted MD5 hex works"); +is(length($root->__Value("Password")), 40, "And is now upgraded to truncated salted SHA-256"); + +# MD5, base64 +$root->_Set( Field => "Password", Value => Digest::MD5::md5_base64("new")); +ok($root->IsPassword("new"), "Unsalted MD5 base64 works"); +is(length($root->__Value("Password")), 40, "And is now upgraded to truncated salted SHA-256"); + diff --git a/rt/t/api/scrip.t b/rt/t/api/scrip.t index 8e8f96213..9d97e7344 100644 --- a/rt/t/api/scrip.t +++ b/rt/t/api/scrip.t @@ -2,7 +2,7 @@ use strict; use warnings; use RT; -use RT::Test tests => 7; +use RT::Test tests => 25; { @@ -46,4 +46,76 @@ isnt ($ticket2->Priority , '87', "Ticket priority is set right"); } + +{ + my $scrip = RT::Scrip->new($RT::SystemUser); + my ( $val, $msg ) = $scrip->Create( + ScripCondition => 'On Comment', + ScripAction => 'Notify Owner', + ); + ok( !$val, "missing template: $msg" ); + ( $val, $msg ) = $scrip->Create( + ScripCondition => 'On Comment', + ScripAction => 'Notify Owner', + Template => 'not exists', + ); + ok( !$val, "invalid template: $msg" ); + + ( $val, $msg ) = $scrip->Create( + ScripAction => 'Notify Owner', + Template => 'Blank', + ); + ok( !$val, "missing condition: $msg" ); + ( $val, $msg ) = $scrip->Create( + ScripCondition => 'not exists', + ScripAction => 'Notify Owner', + Template => 'Blank', + ); + ok( !$val, "invalid condition: $msg" ); + + ( $val, $msg ) = $scrip->Create( + ScripCondition => 'On Comment', + Template => 'Blank', + ); + ok( !$val, "missing action: $msg" ); + ( $val, $msg ) = $scrip->Create( + ScripCondition => 'On Comment', + ScripAction => 'not exists', + Template => 'Blank', + ); + ok( !$val, "invalid action: $msg" ); + + ( $val, $msg ) = $scrip->Create( + ScripAction => 'Notify Owner', + ScripCondition => 'On Comment', + Template => 'Blank', + ); + ok( $val, "created scrip: $msg" ); + $scrip->Load($val); + ok( $scrip->id, 'loaded scrip ' . $scrip->id ); + + ( $val, $msg ) = $scrip->SetScripCondition(); + ok( !$val, "missing condition: $msg" ); + ( $val, $msg ) = $scrip->SetScripCondition('not exists'); + ok( !$val, "invalid condition: $msg" ); + ( $val, $msg ) = $scrip->SetScripCondition('On Correspond'); + ok( $val, "updated condition to 'On Correspond': $msg" ); + + ( $val, $msg ) = $scrip->SetScripAction(); + ok( !$val, "missing action: $msg" ); + ( $val, $msg ) = $scrip->SetScripAction('not exists'); + ok( !$val, "invalid action: $msg" ); + ( $val, $msg ) = $scrip->SetScripAction('Notify AdminCcs'); + ok( $val, "updated action to 'Notify AdminCcs': $msg" ); + + ( $val, $msg ) = $scrip->SetTemplate(); + ok( !$val, "missing template $msg" ); + ( $val, $msg ) = $scrip->SetTemplate('not exists'); + ok( !$val, "invalid template $msg" ); + ( $val, $msg ) = $scrip->SetTemplate('Forward'); + ok( $val, "updated template to 'Forward': $msg" ); + + ok( $scrip->Delete, 'delete the scrip' ); +} + 1; diff --git a/rt/t/api/txn_content.t b/rt/t/api/txn_content.t new file mode 100644 index 000000000..0f5d78ca9 --- /dev/null +++ b/rt/t/api/txn_content.t @@ -0,0 +1,19 @@ +use warnings; +use strict; + +use RT::Test tests => 3; +use MIME::Entity; +my $ticket = RT::Ticket->new($RT::SystemUser); +my $mime = MIME::Entity->build( + From => 'test@example.com', + Type => 'text/html', + Data => ["this is body\n"], +); +$mime->attach( Data => ['this is attachment'] ); +my $id = $ticket->Create( MIMEObj => $mime, Queue => 'General' ); +ok( $id, "created ticket $id" ); +my $txns = $ticket->Transactions; +$txns->Limit( FIELD => 'Type', VALUE => 'Create' ); +my $txn = $txns->First; +ok( $txn, 'got Create txn' ); +is( $txn->Content, "this is body\n", "txn's content" ); diff --git a/rt/t/approval/admincc.t b/rt/t/approval/admincc.t new file mode 100644 index 000000000..7915b6a78 --- /dev/null +++ b/rt/t/approval/admincc.t @@ -0,0 +1,271 @@ + +use strict; +use warnings; +use Test::More; +BEGIN { + eval { require Email::Abstract; require Test::Email; 1 } + or plan skip_all => 'require Email::Abstract and Test::Email'; +} + + +use RT; +use RT::Test tests => 58; +use RT::Test::Email; + +RT->Config->Set( LogToScreen => 'debug' ); +RT->Config->Set( UseTransactionBatch => 1 ); +my ($baseurl, $m) = RT::Test->started_ok; + +my $q = RT::Queue->new($RT::SystemUser); +$q->Load('___Approvals'); +$q->SetDisabled(0); + +my %users; +# minion is the requestor, cto is the approval owner, coo and ceo are approval +# adminccs +for my $user_name (qw(minion cto coo ceo )) { + my $user = $users{$user_name} = RT::User->new($RT::SystemUser); + $user->Create( Name => uc($user_name), + Privileged => 1, + EmailAddress => $user_name.'@company.com', + Password => 'password', + ); + my ($val, $msg); + ($val, $msg) = $user->PrincipalObj->GrantRight(Object =>$q, Right => $_) + for qw(ModifyTicket OwnTicket ShowTicket); +} + +# XXX: we need to make the first approval ticket open so notification is sent. +my $approvals = +'===Create-Ticket: for-CTO +Queue: ___Approvals +Type: approval +Owner: CTO +AdminCCs: COO, CEO +Requestors: {$Tickets{"TOP"}->Requestors} +DependedOnBy: TOP +Subject: CTO Approval for PO: {$Tickets{"TOP"}->Id} - {$Tickets{"TOP"}->Subject} +Due: {time + 86400} +Content-Type: text/plain +Content: Your approval is requested for the PO ticket {$Tickets{"TOP"}->Id}: {$Tickets{"TOP"}->Subject} +Blah +Blah +ENDOFCONTENT +'; + +my $apptemp = RT::Template->new($RT::SystemUser); +$apptemp->Create( Content => $approvals, Name => "PO Approvals", Queue => "0"); + +ok($apptemp->Id); + +$q = RT::Queue->new($RT::SystemUser); +$q->Create(Name => 'PO'); +ok ($q->Id, "Created PO queue"); + +my $scrip = RT::Scrip->new($RT::SystemUser); +my ($sval, $smsg) =$scrip->Create( ScripCondition => 'On Create', + ScripAction => 'Create Tickets', + Template => 'PO Approvals', + Queue => $q->Id, + Description => 'Create Approval Tickets'); +ok ($sval, $smsg); +ok ($scrip->Id, "Created the scrip"); +ok ($scrip->TemplateObj->Id, "Created the scrip template"); +ok ($scrip->ConditionObj->Id, "Created the scrip condition"); +ok ($scrip->ActionObj->Id, "Created the scrip action"); + +my $t = RT::Ticket->new($RT::SystemUser); +my ($tid, $ttrans, $tmsg); + +mail_ok { + ( $tid, $ttrans, $tmsg ) = $t->Create( + Subject => "PO for stationary", + Owner => "root", + Requestor => 'minion', + Queue => $q->Id, + ); +} { from => qr/RT System/, + bcc => qr/ceo.*coo|coo.*ceo/i, + subject => qr/PO for stationary/i, +}, +{ from => qr/RT System/, + to => 'cto@company.com', + subject => qr/New Pending Approval: CTO Approval/, + body => qr/pending your approval.*Your approval is requested.*Blah/s +}, +{ from => qr/PO via RT/, + to => 'minion@company.com', + subject => qr/PO for stationary/, + body => qr/automatically generated in response/ +}; + +ok ($tid,$tmsg); + +is ($t->DependsOn->Count, 1, "depends on one ticket"); +my $t_cto = RT::Ticket->new( $RT::SystemUser ); +$t_cto->Load( $t->DependsOn->First->TargetObj->id ); + +is_deeply( + [ $t->Status, $t_cto->Status ], + [ 'new', 'open' ], + 'tickets in correct state' +); + +mail_ok { + my $cto = RT::CurrentUser->new; + $cto->Load( $users{cto} ); + + $t_cto->CurrentUser($cto); + my $notes = MIME::Entity->build( + Data => [ 'Resources exist to be consumed.' ] + ); + RT::I18N::SetMIMEEntityToUTF8($notes); # convert text parts into utf-8 + + my ( $notesval, $notesmsg ) = $t_cto->Correspond( MIMEObj => $notes ); + ok($notesval, $notesmsg); + + my ($ok, $msg) = $t_cto->SetStatus( Status => 'resolved' ); + ok($ok, "cto can approve - $msg"); + } +{ + from => qr/CTO/, + bcc => qr/ceo.*coo|coo.*ceo/i, + body => qr/Resources exist to be consumed/, +}, +{ + from => qr/RT System/, + to => 'minion@company.com', + subject => qr/Ticket Approved:/, + body => qr/approved by CTO.*notes: Resources exist to be consumed/s +}, +{ + from => qr/CTO/, + to => 'root@localhost', + subject => qr/Ticket Approved:/, + body => qr/The ticket has been approved, you may now start to act on it/, +}; + +is_deeply( + [ $t->Status, $t_cto->Status ], + [ 'new', 'resolved' ], + 'ticket state after coo approval' +); + +for my $admin (qw/coo ceo/) { + $t_cto->_Set( + Field => 'Status', + Value => 'open', + ); + + RT::Test->clean_caught_mails; + + mail_ok { + my $user = RT::CurrentUser->new; + $user->Load( $users{$admin} ); + + $t_cto->CurrentUser($user); + my $notes = + MIME::Entity->build( Data => ['Resources exist to be consumed.'] ); + RT::I18N::SetMIMEEntityToUTF8($notes); # convert text parts into utf-8 + + my ( $notesval, $notesmsg ) = $t_cto->Correspond( MIMEObj => $notes ); + ok( $notesval, $notesmsg ); + + my ( $ok, $msg ) = $t_cto->SetStatus( Status => 'resolved' ); + ok( $ok, "cto can approve - $msg" ); + } + { + from => qr/\U$admin/, + bcc => $admin eq 'coo' ? qr/ceo/i : qr/coo/, + body => qr/Resources exist to be consumed/, + }, + { + from => qr/RT System/, + to => 'minion@company.com', + subject => qr/Ticket Approved:/, + body => qr/approved by \U$admin\E.*notes: Resources exist to be consumed/s + }, + { + from => qr/\U$admin/, + to => 'root@localhost', + subject => qr/Ticket Approved:/, + body => + qr/The ticket has been approved, you may now start to act on it/, + }; +} + +# now we test the web +my $approval_link = $baseurl . '/Approvals/'; + +$t = RT::Ticket->new($RT::SystemUser); +( $tid, $ttrans, $tmsg ) = $t->Create( + Subject => "first approval", + Owner => "root", + Requestor => 'minion', + Queue => $q->Id, +); +ok( $tid, $tmsg ); + +my $first_ticket = RT::Ticket->new( $RT::SystemUser ); +$first_ticket->Load( $tid ); +my $first_approval = $first_ticket->DependsOn->First->TargetObj; + +$t = RT::Ticket->new($RT::SystemUser); +( $tid, $ttrans, $tmsg ) = $t->Create( + Subject => "second approval", + Owner => "root", + Requestor => 'minion', + Queue => $q->Id, +); + +my $second_ticket = RT::Ticket->new( $RT::SystemUser ); +$second_ticket->Load( $tid ); +my $second_approval = $second_ticket->DependsOn->First->TargetObj; + + +ok( $m->login( 'cto', 'password' ), 'logged in as coo' ); + +my $m_coo = RT::Test::Web->new; +ok( $m_coo->login( 'coo', 'password' ), 'logged in as coo' ); + +my $m_ceo = RT::Test::Web->new; +ok( $m_ceo->login( 'ceo', 'password' ), 'logged in as coo' ); + + +$m->get_ok( $approval_link ); +$m_coo->get_ok( $approval_link ); +$m_ceo->get_ok( $approval_link ); + +$m->content_like( qr/first approval.*second approval/s, 'cto: see both approvals' ); +$m_coo->content_like( qr/first approval.*second approval/s, 'coo: see both approvals' ); +$m_ceo->content_like( qr/first approval.*second approval/s, 'ceo: see both approvals' ); + +# now let's approve the first one via cto +$m->content_like( qr/first approval.*second approval/s, 'cto can see both approvals' ); +$m->submit_form( + form_number => 3, + fields => { 'Approval-' . $first_approval->id . '-Action' => 'approve', }, +); + +$m->content_lacks( 'first approval', 'cto: first approval is gone' ); +$m->content_contains( 'second approval', 'cto: second approval is still here' ); +$m_coo->get_ok( $approval_link ); +$m_ceo->get_ok( $approval_link ); +$m_coo->content_lacks( 'first approval', 'coo: first approval is gone' ); +$m_coo->content_contains( 'second approval', 'coo: second approval is still here' ); +$m_ceo->content_lacks( 'first approval', 'ceo: first approval is gone' ); +$m_ceo->content_contains( 'second approval', 'ceo: second approval is still here' ); + +$m_coo->submit_form( + form_number => 3, + fields => { 'Approval-' . $second_approval->id . '-Action' => 'approve', }, +); + +$m->get_ok( $approval_link ); +$m_ceo->get_ok( $approval_link ); + +$m->content_lacks( 'second approval', 'cto: second approval is gone too' ); +$m_coo->content_lacks( 'second approval', 'coo: second approval is gone too' ); +$m_ceo->content_lacks( 'second approval', 'ceo: second approval is gone too' ); + +RT::Test->clean_caught_mails; diff --git a/rt/t/data/gnupg/emails/special/quoted_inline_signature.txt b/rt/t/data/gnupg/emails/special/quoted_inline_signature.txt new file mode 100644 index 000000000..131d27adc --- /dev/null +++ b/rt/t/data/gnupg/emails/special/quoted_inline_signature.txt @@ -0,0 +1,26 @@ +To: rt-recipient@example.com +Subject: Test Email ID:4 +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +From: root@localhost + +Forwarded email with signature quoted. RT shouldn't bother +about it. + +> ------ Forwarded Message +> From: Xxx Yyy <xxx.yyy@localhost> +> Subject: test email +> +> -----BEGIN PGP SIGNED MESSAGE----- +> Hash: SHA1 +> +> This is a test email with inline signature. +> ID:4 +> -----BEGIN PGP SIGNATURE----- +> Version: GnuPG v1.4.6 (GNU/Linux) +> +> iD8DBQFGwLI50ygDXYSIHxsRAp40AJ9ErYdLH2SVRXtgRtx7n/FVFOmKDwCgl/0T +> BeRSaF4Xbi8uGhVIkmU+YCs= +> =e4u6 +> -----END PGP SIGNATURE----- diff --git a/rt/t/mail/gnupg-incoming.t b/rt/t/mail/gnupg-incoming.t index ec313330a..230aa9c58 100644 --- a/rt/t/mail/gnupg-incoming.t +++ b/rt/t/mail/gnupg-incoming.t @@ -34,8 +34,7 @@ RT->Config->Set( 'MailPlugins' => 'Auth::MailFrom', 'Auth::GnuPG' ); my ($baseurl, $m) = RT::Test->started_ok; # configure key for General queue -$m->get( $baseurl."?user=root;pass=password" ); -$m->content_like(qr/Logout/, 'we did log in'); +ok( $m->login, 'we did log in' ); $m->get( $baseurl.'/Admin/Queues/'); $m->follow_link_ok( {text => 'General'} ); $m->submit_form( form_number => 3, diff --git a/rt/t/mail/gnupg-realmail.t b/rt/t/mail/gnupg-realmail.t index de1d95815..198402b23 100644 --- a/rt/t/mail/gnupg-realmail.t +++ b/rt/t/mail/gnupg-realmail.t @@ -2,7 +2,7 @@ use strict; use warnings; -use RT::Test tests => 197; +use RT::Test tests => 196; plan skip_all => 'GnuPG required.' unless eval 'use GnuPG::Interface; 1'; @@ -37,20 +37,11 @@ $m->submit_form( form_number => 3, fields => { CorrespondAddress => 'rt-recipient@example.com' } ); $m->content_like(qr/rt-recipient\@example.com.* - never/, 'has key info.'); -diag "load Everyone group" if $ENV{'TEST_VERBOSE'}; -my $everyone; -{ - $everyone = RT::Group->new( $RT::SystemUser ); - $everyone->LoadSystemInternalGroup('Everyone'); - ok $everyone->id, "loaded 'everyone' group"; -} - RT::Test->set_rights( - Principal => $everyone, + Principal => 'Everyone', Right => ['CreateTicket'], ); - my $eid = 0; for my $usage (qw/signed encrypted signed&encrypted/) { for my $format (qw/MIME inline/) { diff --git a/rt/t/mail/gnupg-special.t b/rt/t/mail/gnupg-special.t new file mode 100644 index 000000000..7e50819e8 --- /dev/null +++ b/rt/t/mail/gnupg-special.t @@ -0,0 +1,86 @@ +#!/usr/bin/perl +use strict; +use warnings; + +use RT::Test tests => 11; + +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 File::Temp qw(tempdir); +my $homedir = tempdir( CLEANUP => 1 ); + +# catch any outgoing emails +RT::Test->set_mail_catcher; + +RT->Config->Set( 'GnuPG', + Enable => 1, + OutgoingMessagesFormat => 'RFC' ); + +RT->Config->Set( 'GnuPGOptions', + homedir => $homedir, + 'no-permission-warning' => undef); + +RT->Config->Set( 'MailPlugins' => 'Auth::MailFrom', 'Auth::GnuPG' ); + +RT::Test->import_gnupg_key('rt-recipient@example.com'); +RT::Test->import_gnupg_key('rt-test@example.com', 'public'); + +my ($baseurl, $m) = RT::Test->started_ok; + +ok( $m->login, 'we did log in' ); + +# configure key for General queue +{ + $m->get( $baseurl.'/Admin/Queues/'); + $m->follow_link_ok( {text => 'General'} ); + $m->submit_form( + form_number => 3, + fields => { CorrespondAddress => 'rt-recipient@example.com' }, + ); + $m->content_like(qr/rt-recipient\@example.com.* - never/, 'has key info.'); +} + +ok(my $user = RT::User->new($RT::SystemUser)); +ok($user->Load('root'), "Loaded user 'root'"); +$user->SetEmailAddress('recipient@example.com'); + +RT::Test->set_rights( + Principal => 'Everyone', + Right => ['CreateTicket'], +); + +{ + my $id = send_via_mailgate('quoted_inline_signature.txt'); + + my $tick = RT::Ticket->new( $RT::SystemUser ); + $tick->Load( $id ); + ok ($tick->id, "loaded ticket #$id"); + + my $txn = $tick->Transactions->First; + my ($msg, @attachments) = @{$txn->Attachments->ItemsArrayRef}; + + is( $msg->GetHeader('X-RT-Privacy'), + undef, + "no privacy is set as this ticket is not encrypted" + ); + + my @mail = RT::Test->fetch_caught_mails; + is(scalar @mail, 1, "autoreply only"); +} + +sub send_via_mailgate { + my $fname = shift; + my $emaildatadir = RT::Test::get_relocatable_dir(File::Spec->updir(), + qw(data gnupg emails special)); + my $file = File::Spec->catfile( $emaildatadir, $fname ); + my $mail = RT::Test->file_content($file); + + my ($status, $id) = RT::Test->send_via_mailgate($mail); + is ($status >> 8, 0, "the mail gateway exited normally"); + ok ($id, "got id of a newly created ticket - $id"); + return $id; +} + diff --git a/rt/t/mail/outlook.t b/rt/t/mail/outlook.t new file mode 100644 index 000000000..15bfa21bc --- /dev/null +++ b/rt/t/mail/outlook.t @@ -0,0 +1,272 @@ +#!/usr/bin/perl -w +# BEGIN BPS TAGGED BLOCK {{{ +# +# COPYRIGHT: +# +# This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC +# <jesse.com> +# +# (Except where explicitly superseded by other copyright notices) +# +# +# LICENSE: +# +# This work is made available to you under the terms of Version 2 of +# the GNU General Public License. A copy of that license should have +# been provided with this software, but in any event can be snarfed +# from www.gnu.org. +# +# This work is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 or visit their web page on the internet at +# http://www.gnu.org/copyleft/gpl.html. +# +# +# CONTRIBUTION SUBMISSION POLICY: +# +# (The following paragraph is not intended to limit the rights granted +# to you to modify and distribute this software under the terms of +# the GNU General Public License and is only of importance to you if +# you choose to contribute your changes and enhancements to the +# community by submitting them to Best Practical Solutions, LLC.) +# +# By intentionally submitting any modifications, corrections or +# derivatives to this work, or any other work intended for use with +# Request Tracker, to Best Practical Solutions, LLC, you confirm that +# you are the copyright holder for those contributions and you grant +# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +# royalty-free, perpetual, license to use, copy, create derivative +# works based on those contributions, and sublicense and distribute +# those contributions and any derivatives thereof. +# +# END BPS TAGGED BLOCK }}} + +=head1 NAME + +rt-mailgate - Mail interface to RT3. + +=cut + +use strict; +use warnings; + +use RT::Test tests => 43; +my ($baseurl, $m) = RT::Test->started_ok; +# 12.0 is outlook 2007, 14.0 is 2010 +for my $mailer ( 'Microsoft Office Outlook 12.0', 'Microsoft Outlook 14.0' ) { + diag "Test mail with multipart/alternative" if $ENV{'TEST_VERBOSE'}; + { + my $text = <<EOF; +From: root\@localhost +X-Mailer: $mailer +To: rt\@@{[RT->Config->Get('rtname')]} +Subject: outlook basic test +Content-Type: multipart/alternative; + boundary="----=_NextPart_000_0004_01CB045C.A5A075D0" + +------=_NextPart_000_0004_01CB045C.A5A075D0 +Content-Type: text/plain; + charset="us-ascii" +Content-Transfer-Encoding: 7bit + +here is the content + + + +blahmm + +another line + + +------=_NextPart_000_0004_01CB045C.A5A075D0 +Content-Type: text/html; + charset="us-ascii" +Content-Transfer-Encoding: quoted-printable + +<html>this is fake</html> + + +------=_NextPart_000_0004_01CB045C.A5A075D0-- + +EOF + + my $content = <<EOF; +here is the content + +blahmm +another line +EOF + test_email( $text, $content, + $mailer . ' with multipart/alternative, \n\n are replaced' ); + } + + diag "Test mail with multipart/mixed, with multipart/alternative in it" + if $ENV{'TEST_VERBOSE'}; + { + my $text = <<EOF; +From: root\@localhost +X-Mailer: $mailer +To: rt\@@{[RT->Config->Get('rtname')]} +Subject: outlook basic test +Content-Type: multipart/mixed; + boundary="----=_NextPart_000_000F_01CB045E.5222CB40" + +------=_NextPart_000_000F_01CB045E.5222CB40 +Content-Type: multipart/alternative; + boundary="----=_NextPart_001_0010_01CB045E.5222CB40" + + +------=_NextPart_001_0010_01CB045E.5222CB40 +Content-Type: text/plain; + charset="us-ascii" +Content-Transfer-Encoding: 7bit + +foo + + + +bar + +baz + + +------=_NextPart_001_0010_01CB045E.5222CB40 +Content-Type: text/html; + charset="us-ascii" +Content-Transfer-Encoding: quoted-printable + +<html>this is fake</html> + +------=_NextPart_001_0010_01CB045E.5222CB40-- + +------=_NextPart_000_000F_01CB045E.5222CB40 +Content-Type: text/plain; + name="att.txt" +Content-Transfer-Encoding: quoted-printable +Content-Disposition: attachment; + filename="att.txt" + +this is the attachment! :)=0A= + +------=_NextPart_000_000F_01CB045E.5222CB40-- +EOF + + my $content = <<EOF; +foo + +bar +baz +EOF + test_email( $text, $content, + $mailer . ' with multipart/multipart, \n\n are replaced' ); + } + + diag "Test mail with with outlook, but the content type is text/plain" + if $ENV{'TEST_VERBOSE'}; + { + my $text = <<EOF; +From: root\@localhost +X-Mailer: $mailer +To: rt\@@{[RT->Config->Get('rtname')]} +Subject: outlook basic test +Content-Type: text/plain; charset="us-ascii" +Content-Transfer-Encoding: 7bit + +foo + + + +bar + +baz + +EOF + + my $content = <<EOF; +foo + + + +bar + +baz + +EOF + test_email( $text, $content, + $mailer . ' with only text/plain, \n\n are not replaced' ); + } +} + +diag "Test mail with with multipart/alternative but x-mailer is not outlook " + if $ENV{'TEST_VERBOSE'}; +{ + my $text = <<EOF; +From: root\@localhost +X-Mailer: Mutt +To: rt\@@{[RT->Config->Get('rtname')]} +Subject: outlook basic test +Content-Type: multipart/alternative; + boundary="----=_NextPart_000_0004_01CB045C.A5A075D0" + +------=_NextPart_000_0004_01CB045C.A5A075D0 +Content-Type: text/plain; + charset="us-ascii" +Content-Transfer-Encoding: 7bit + +foo + + + +bar + +baz + + +------=_NextPart_000_0004_01CB045C.A5A075D0 +Content-Type: text/html; + charset="us-ascii" +Content-Transfer-Encoding: quoted-printable + +<html>this is fake</html> + + +------=_NextPart_000_0004_01CB045C.A5A075D0-- + +EOF + + my $content = <<EOF; +foo + + + +bar + +baz + +EOF + test_email( $text, $content, 'without outlook, \n\n are not replaced' ); +} + +sub test_email { + my ( $text, $content, $msg ) = @_; + my ( $status, $id ) = RT::Test->send_via_mailgate($text); + is( $status >> 8, 0, "The mail gateway exited normally" ); + ok( $id, "Created ticket" ); + + my $ticket = RT::Test->last_ticket; + isa_ok( $ticket, 'RT::Ticket' ); + is( $ticket->Id, $id, "correct ticket id" ); + is( $ticket->Subject, 'outlook basic test', "subject of ticket $id" ); + my $txns = $ticket->Transactions; + $txns->Limit( FIELD => 'Type', VALUE => 'Create' ); + my $txn = $txns->First; + + is( $txn->Content, $content, $msg ); +} + diff --git a/rt/t/mail/wrong_mime_charset.t b/rt/t/mail/wrong_mime_charset.t new file mode 100644 index 000000000..f53c872e5 --- /dev/null +++ b/rt/t/mail/wrong_mime_charset.t @@ -0,0 +1,25 @@ +#!/usr/bin/perl +use strict; +use warnings; +use RT::Test nodata => 1, tests => 3; + +use_ok('RT::I18N'); +use utf8; +use Encode; +my $test_string = 'À'; +my $encoded_string = encode( 'iso-8859-1', $test_string ); +my $mime = MIME::Entity->build( + Subject => $encoded_string, + Data => [$encoded_string], +); + +# set the wrong charset mime in purpose +$mime->head->mime_attr( "Content-Type.charset" => 'utf8' ); + +RT::I18N::SetMIMEEntityToEncoding( $mime, 'iso-8859-1' ); +my $subject = decode( 'iso-8859-1', $mime->head->get('Subject') ); +chomp $subject; +is( $subject, $test_string, 'subject is set to iso-8859-1' ); +my $body = decode( 'iso-8859-1', $mime->stringify_body ); +chomp $body; +is( $body, $test_string, 'body is set to iso-8859-1' ); diff --git a/rt/t/web/attachment_encoding.t b/rt/t/web/attachment_encoding.t new file mode 100644 index 000000000..6796c9969 --- /dev/null +++ b/rt/t/web/attachment_encoding.t @@ -0,0 +1,103 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use RT::Test tests => 28; +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; + +diag 'test without attachments' if $ENV{TEST_VERBOSE}; + +{ + $m->get_ok( $baseurl . '/Ticket/Create.html?Queue=1' ); + + $m->form_number(3); + $m->submit_form( + form_number => 3, + fields => { Subject => '标题', Content => '测试' }, + ); + $m->content_like( qr/Ticket \d+ created/i, 'created the ticket' ); + $m->follow_link_ok( { text => 'with headers' }, + '-> /Ticket/Attachment/WithHeaders/...' ); + $m->content_contains( '标题', 'has subject 标题' ); + $m->content_contains( '测试', 'has content 测试' ); + + my ( $id ) = $m->uri =~ /(\d+)$/; + ok( $id, 'found attachment id' ); + my $attachment = RT::Attachment->new( $RT::SystemUser ); + ok($attachment->Load($id), "load att $id"); + # let make original encoding to gbk + ok( $attachment->SetHeader( 'X-RT-Original-Encoding' => 'gbk' ), + 'set original encoding to gbk' ); + $m->get( $m->uri ); + $m->content_contains( '标题', 'has subject 标题' ); + $m->content_contains( '测试', 'has content 测试' ); +} + +diag 'test with attachemnts' if $ENV{TEST_VERBOSE}; + +{ + + my $file = + File::Spec->catfile( File::Spec->tmpdir, 'rt_attachemnt_abcde.txt' ); + open my $fh, '>', $file or die $!; + binmode $fh, ':utf8'; + print $fh '附件'; + close $fh; + + $m->get_ok( $baseurl . '/Ticket/Create.html?Queue=1' ); + + $m->form_number(3); + $m->submit_form( + form_number => 3, + fields => { Subject => '标题', Content => '测试', Attach => $file }, + ); + $m->content_like( qr/Ticket \d+ created/i, 'created the ticket' ); + $m->follow_link_ok( { text => 'with headers' }, + '-> /Ticket/Attachment/WithHeaders/...' ); + + # subject is in the parent attachment, so there is no 标题 + $m->content_lacks( '标题', 'does not have content 标题' ); + $m->content_contains( '测试', 'has content 测试' ); + + my ( $id ) = $m->uri =~ /(\d+)$/; + ok( $id, 'found attachment id' ); + my $attachment = RT::Attachment->new( $RT::SystemUser ); + ok($attachment->Load($id), "load att $id"); + # let make original encoding to gbk + ok( $attachment->SetHeader( 'X-RT-Original-Encoding' => 'gbk' ), + 'set original encoding to gbk' ); + $m->get( $m->uri ); + $m->content_lacks( '标题', 'does not have content 标题' ); + $m->content_contains( '测试', 'has content 测试' ); + + + $m->back; + $m->back; + $m->follow_link_ok( { text_regex => qr/by Enoch Root/ }, + '-> /Ticket/Attachment/...' ); + $m->content_contains( '附件', 'has content 附件' ); + + ( $id ) = $m->uri =~ /(\d+)\D+$/; + ok( $id, 'found attachment id' ); + $attachment = RT::Attachment->new( $RT::SystemUser ); + ok($attachment->Load($id), "load att $id"); + + # let make original encoding to gbk + ok( $attachment->SetHeader( 'X-RT-Original-Encoding' => 'gbk' ), + 'set original encoding to gbk' ); + $m->get( $m->uri ); + $m->content_contains( '附件', 'has content 附件' ); + + unlink $file; +} + + diff --git a/rt/t/web/basic.t b/rt/t/web/basic.t index bc4d65587..3f94e732f 100644 --- a/rt/t/web/basic.t +++ b/rt/t/web/basic.t @@ -4,7 +4,7 @@ use strict; use warnings; use Encode; -use RT::Test tests => 24; +use RT::Test tests => 21; $RT::Test::SKIP_REQUEST_WORK_AROUND = 1; my ($baseurl, $agent) = RT::Test->started_ok; @@ -20,15 +20,8 @@ diag $url if $ENV{TEST_VERBOSE}; # test a login { - ok($agent->{form}->find_input('user')); - ok($agent->{form}->find_input('pass')); - - ok($agent->{'content'} =~ /username:/i); - $agent->field( 'user' => 'root' ); - $agent->field( 'pass' => 'password' ); - + $agent->login('root' => 'password'); # the field isn't named, so we have to click link 0 - $agent->click(0); is( $agent->{'status'}, 200, "Fetched the page ok"); ok( $agent->{'content'} =~ /Logout/i, "Found a logout link"); } diff --git a/rt/t/web/cf_select_one.t b/rt/t/web/cf_select_one.t index 39a808083..26c1fcf65 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 => 41; +use RT::Test tests => 46; my ($baseurl, $m) = RT::Test->started_ok; ok $m->login, 'logged in as root'; @@ -31,9 +31,9 @@ diag "Create a CF" if $ENV{'TEST_VERBOSE'}; ok $cfid, "found id of the CF in the form, it's #$cfid"; } -diag "add 'qwe', 'ASD' and '0' as values to the CF" if $ENV{'TEST_VERBOSE'}; +diag "add 'qwe', 'ASD', '0' and ' foo ' as values to the CF" if $ENV{'TEST_VERBOSE'}; { - foreach my $value(qw(qwe ASD 0)) { + foreach my $value(qw(qwe ASD 0), 'foo ') { $m->submit_form( form_name => "ModifyCustomField", fields => { @@ -42,6 +42,10 @@ diag "add 'qwe', 'ASD' and '0' as values to the CF" if $ENV{'TEST_VERBOSE'}; button => 'Update', ); $m->content_like( qr/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' ); } } diff --git a/rt/t/web/compilation_errors.t b/rt/t/web/compilation_errors.t index 46a862868..4fd9c40e9 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$/; } - my $tests = 7; + my $tests = 4; find( sub { wanted() and $tests += 4 }, 'share/html/' ); plan tests => $tests; } @@ -36,15 +36,7 @@ is ($agent->{'status'}, 200, "Loaded a page"); # {{{ test a login # follow the link marked "Login" - -ok($agent->{form}->find_input('user')); - -ok($agent->{form}->find_input('pass')); -like ($agent->{'content'} , qr/username:/i); -$agent->field( 'user' => 'root' ); -$agent->field( 'pass' => 'password' ); -# the field isn't named, so we have to click link 0 -$agent->click(0); +$agent->login(root => 'password'); is($agent->{'status'}, 200, "Fetched the page ok"); like( $agent->{'content'} , qr/Logout/i, "Found a logout link"); diff --git a/rt/t/web/html_template.t b/rt/t/web/html_template.t new file mode 100644 index 000000000..a2461dc97 --- /dev/null +++ b/rt/t/web/html_template.t @@ -0,0 +1,78 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use RT::Test tests => 19; +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( { text => 'Autoreply' }, '-> Autoreply' ); + + $m->form_number(3); + $m->submit_form( + fields => { + Content => <<'EOF', +Subject: AutoReply: {$Ticket->Subject} +Content-Type: text/html + +你好 éèà€ +{$Ticket->Subject} +------------------------------------------------------------------------- +{$Transaction->Content()} + +EOF + }, + ); + $m->content_like( qr/Content changed/, 'content is changed' ); + $m->content_contains( '你好', 'content is really updated' ); +} + +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, + fields => { Subject => '标题', Content => '<h1>测试</h1>', + ContentType => 'text/html' }, + ); + $m->content_like( qr/Ticket \d+ created/i, 'created the ticket' ); + $m->follow_link( text => 'Show' ); + $m->content_contains( '你好', 'html has 你好' ); + $m->content_contains( 'éèà€', 'html has éèà€' ); + $m->content_contains( '标题', + 'html has ticket subject 标题' ); + $m->content_contains( '<h1>测试</h1>', + 'html has ticket html content 测试' ); +} + +diag('test real mail outgoing') if $ENV{TEST_VERBOSE}; + +{ + + # $mail is utf8 encoded + my ($mail) = RT::Test->fetch_caught_mails; + $mail = decode_utf8 $mail; + like( $mail, qr/你好.*你好/s, 'mail has éèà€' ); + like( $mail, qr/éèà€.*éèà€/s, 'mail has éèà€' ); + like( $mail, qr/标题.*标题/s, 'mail has ticket subject 标题' ); + like( $mail, qr/测试.*测试/s, 'mail has ticket content 测试' ); + like( $mail, qr!<h1>测试</h1>!, 'mail has ticket html content 测试' ); +} + diff --git a/rt/t/web/offline_messages_utf8.t b/rt/t/web/offline_messages_utf8.t index c32e0bc27..9901b4555 100644 --- a/rt/t/web/offline_messages_utf8.t +++ b/rt/t/web/offline_messages_utf8.t @@ -8,7 +8,7 @@ use Encode; use RT::Ticket; my ( $url, $m ) = RT::Test->started_ok; -$m->default_header( 'Accept-Language' => "zh-cn" ); +$m->default_header( 'Accept-Language' => "zh-tw" ); ok( $m->login, 'logged in' ); my $ticket_id; @@ -38,7 +38,7 @@ EOF button => 'UpdateTickets', ); my $content = encode 'utf8', $m->content; - ok( $content =~ qr/申请单 #(\d+) 成功新增于 'General' 表单/, 'message is shown right' ); + ok( $content =~ m/申請單 #(\d+) 成功新增於 'General' 表單/, 'message is shown right' ); $ticket_id = $1; } @@ -60,7 +60,7 @@ EOF my $content = encode 'utf8', $m->content; ok( $content =~ -qr/主题\s*的值从\s*'test message'\s*改为\s*'test message update'/, +qr/主題\s*的值從\s*'test message'\s*改為\s*'test message update'/, 'subject is updated' ); } diff --git a/rt/t/web/query_builder.t b/rt/t/web/query_builder.t index 02ed1297f..fa2c56da8 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 => 42; +use RT::Test tests => 44; my $cookie_jar = HTTP::Cookies->new; my ($baseurl, $agent) = RT::Test->started_ok; @@ -246,4 +246,13 @@ diag "input a condition, select (several conditions), click delete" ); } -1; +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, + "Priority > -2", + "query is the same" + ); +} diff --git a/rt/t/web/redirect-after-login.t b/rt/t/web/redirect-after-login.t new file mode 100644 index 000000000..d39bb58c8 --- /dev/null +++ b/rt/t/web/redirect-after-login.t @@ -0,0 +1,243 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use RT::Test tests => 120; + +my ($baseurl, $agent) = RT::Test->started_ok; + +my $url = $agent->rt_base_url; +diag $url if $ENV{TEST_VERBOSE}; + +# test a login from the main page +{ + $agent->get_ok($url); + is($agent->{'status'}, 200, "Loaded a page"); + is($agent->uri, $url, "didn't redirect to /NoAuth/Login.html for base URL"); + 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"); + + ok($agent->content =~ /username:/i); + $agent->field( 'user' => 'root' ); + $agent->field( 'pass' => 'password' ); + + # the field isn't named, so we have to click link 0 + $agent->click(0); + is( $agent->status, 200, "Fetched the page ok"); + ok( $agent->content =~ /Logout/i, "Found a logout link"); + is( $agent->uri, $url, "right URL" ); + like( $agent->{redirected_uri}, qr{/NoAuth/Login\.html$}, "We redirected from login"); + $agent->logout(); +} + +# test a bogus login from the main page +{ + $agent->get_ok($url); + is($agent->{'status'}, 200, "Loaded a page"); + is($agent->uri, $url, "didn't redirect to /NoAuth/Login.html for base URL"); + 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"); + + ok($agent->content =~ /username:/i); + $agent->field( 'user' => 'root' ); + $agent->field( 'pass' => 'wrongpass' ); + + # the field isn't named, so we have to click link 0 + $agent->click(0); + is( $agent->status, 200, "Fetched the page ok"); + + 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"); +} + +# test a login from a non-front page, both with a double leading slash and without +for my $path (qw(Prefs/Other.html /Prefs/Other.html)) { + my $requested = $url.$path; + $agent->get_ok($requested); + is($agent->status, 200, "Loaded a page"); + like($agent->uri, qr'/NoAuth/Login\.html\?next=[a-z0-9]{32}', "on login page, with next page hash"); + is($agent->{redirected_uri}, $requested, "redirected from our requested page"); + + ok($agent->current_form->find_input('user')); + ok($agent->current_form->find_input('pass')); + 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"); + + ok($agent->content =~ /username:/i); + $agent->field( 'user' => 'root' ); + $agent->field( 'pass' => 'password' ); + + # the field isn't named, so we have to click link 0 + $agent->click(0); + is( $agent->status, 200, "Fetched the page ok"); + ok( $agent->content =~ /Logout/i, "Found a logout link"); + + if ($path =~ m{/}) { + (my $collapsed = $path) =~ s{^/}{}; + is( $agent->uri, $url.$collapsed, "right URL, with leading slashes in path collapsed" ); + } else { + is( $agent->uri, $requested, "right URL" ); + } + + like( $agent->{redirected_uri}, qr{/NoAuth/Login\.html}, "We redirected from login"); + $agent->logout(); +} + +# test a bogus login from a non-front page +{ + my $requested = $url.'Prefs/Other.html'; + $agent->get_ok($requested); + is($agent->status, 200, "Loaded a page"); + like($agent->uri, qr'/NoAuth/Login\.html\?next=[a-z0-9]{32}', "on login page, with next page hash"); + is($agent->{redirected_uri}, $requested, "redirected from our requested page"); + + ok($agent->current_form->find_input('user')); + ok($agent->current_form->find_input('pass')); + 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"); + + ok($agent->content =~ /username:/i); + $agent->field( 'user' => 'root' ); + $agent->field( 'pass' => 'wrongpass' ); + + # the field isn't named, so we have to click link 0 + $agent->click(0); + is( $agent->status, 200, "Fetched the page ok"); + + 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" ); + + # try to login again + ok($agent->current_form->find_input('user')); + ok($agent->current_form->find_input('pass')); + 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"); + + ok($agent->content =~ /username:/i); + $agent->field( 'user' => 'root' ); + $agent->field( 'pass' => 'password' ); + + # the field isn't named, so we have to click link 0 + $agent->click(0); + is( $agent->status, 200, "Fetched the page ok"); + + # check out where we got to + 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 +{ + my $requested = $url."?user=root;pass=password"; + $agent->get_ok($requested); + is($agent->{'status'}, 200, "Loaded a page"); + is($agent->uri, $requested, "didn't redirect to /NoAuth/Login.html for base URL"); + ok($agent->content =~ /Logout/i, "Found a logout link - we're logged in"); + $agent->logout(); +} + +# test a bogus login from the main page with query params +{ + my $requested = $url."?user=root;pass=wrongpass"; + $agent->get_ok($requested); + is($agent->{'status'}, 200, "Loaded a page"); + is($agent->uri, $requested, "didn't redirect to /NoAuth/Login.html for base URL"); + + ok($agent->content =~ /Your username or password is incorrect/i, "Found the error message"); + 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"); +} + +# test a bogus login from a non-front page with query params +{ + my $requested = $url."Prefs/Other.html?user=root;pass=wrongpass"; + $agent->get_ok($requested); + is($agent->status, 200, "Loaded a page"); + like($agent->uri, qr'/NoAuth/Login\.html\?next=[a-z0-9]{32}', "on login page, with next page hash"); + is($agent->{redirected_uri}, $requested, "redirected from our requested page"); + ok( $agent->content =~ /Your username or password is incorrect/i, "Found the error message"); + + ok($agent->current_form->find_input('user')); + ok($agent->current_form->find_input('pass')); + 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"); + + # Try to login again + ok($agent->content =~ /username:/i); + $agent->field( 'user' => 'root' ); + $agent->field( 'pass' => 'password' ); + + # the field isn't named, so we have to click link 0 + $agent->click(0); + is( $agent->status, 200, "Fetched the page ok"); + + # check out where we got to + 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 +{ + my $requested = $url."REST/1.0/?user=root;pass=password"; + $agent->get($requested); + is($agent->status, 200, "Loaded a page"); + is($agent->uri, $requested, "didn't redirect to /NoAuth/Login.html for REST"); + $agent->get_ok($url); + $agent->logout(); +} + +# test REST login response for wrong pass +{ + my $requested = $url."REST/1.0/?user=root;pass=passwrong"; + $agent->get_ok($requested); + is($agent->status, 200, "Loaded a page"); + 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"); +} + +# test REST login response for no creds +{ + my $requested = $url."REST/1.0/"; + $agent->get_ok($requested); + is($agent->status, 200, "Loaded a page"); + is($agent->uri, $requested, "didn't redirect to /NoAuth/Login.html for REST"); + like($agent->content, qr/401 Credentials required/i, "got error status"); + unlike($agent->content, qr/Your username or password is incorrect/, "didn't get any error message"); +} + +# XXX TODO: we should also be testing WebExternalAuth here, but we don't have +# the framework for dealing with that + +1; diff --git a/rt/t/web/rest-non-ascii-subject.t b/rt/t/web/rest-non-ascii-subject.t index 70c910afe..371b2ffc0 100644 --- a/rt/t/web/rest-non-ascii-subject.t +++ b/rt/t/web/rest-non-ascii-subject.t @@ -49,7 +49,4 @@ is($ticket->Subject, $subject, "ticket subject successfully set"); my $attach = $ticket->Transactions->First->Attachments->First; is($attach->Subject, $subject, "attachement subject successfully set"); -TODO: { - local $TODO = "Not fixed yet, but not a regression"; - is($attach->GetHeader('Subject'), $subject, "attachement header subject successfully set"); -} +is($attach->GetHeader('Subject'), $subject, "attachement header subject successfully set"); diff --git a/rt/t/web/rights1.t b/rt/t/web/rights1.t index 6da204cc9..c8892f2fe 100644 --- a/rt/t/web/rights1.t +++ b/rt/t/web/rights1.t @@ -2,7 +2,7 @@ use strict; use HTTP::Cookies; -use RT::Test tests => 35; +use RT::Test tests => 29; my ($baseurl, $agent) = RT::Test->started_ok; # Create a user with basically no rights, to start. @@ -26,7 +26,7 @@ $agent->cookie_jar($cookie_jar); no warnings 'once'; # get the top page -login($agent, $user_obj); +$agent->login( $user_obj->Name, 'customer'); # Test for absence of Configure and Preferences tabs. ok(!$agent->find_link( url => "$RT::WebPath/Admin/", @@ -107,28 +107,4 @@ 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"); -sub login { - my $agent = shift; - - my $url = "http://localhost:" . RT->Config->Get('WebPort') . RT->Config->Get('WebPath') . "/"; - $agent->get($url); - is( $agent->{'status'}, 200, - "Loaded a page - http://localhost" . RT->Config->Get('WebPath') ); - - # {{{ test a login - - # follow the link marked "Login" - - ok( $agent->{form}->find_input('user') ); - - ok( $agent->{form}->find_input('pass') ); - like( $agent->{'content'} , qr/username:/i ); - $agent->field( 'user' => $user_obj->Name ); - $agent->field( 'pass' => 'customer' ); - - # the field isn't named, so we have to click link 0 - $agent->click(0); - is( $agent->{'status'}, 200, "Fetched the page ok" ); - like( $agent->{'content'} , qr/Logout/i, "Found a logout link" ); -} 1; diff --git a/rt/t/web/saved_search_update.t b/rt/t/web/saved_search_update.t new file mode 100644 index 000000000..9b2724e82 --- /dev/null +++ b/rt/t/web/saved_search_update.t @@ -0,0 +1,63 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use RT::Test tests => 16; + +my $root = RT::User->new( $RT::SystemUser ); +$root->Load('root'); +my $uid = $root->id; +ok( $uid, 'loaded root' ); + +my $group = RT::Group->new( $RT::SystemUser ); +my ($gid) = $group->CreateUserDefinedGroup( Name => 'foo' ); +ok( $gid, 'created group foo'); +ok( $group->AddMember( $root->PrincipalId ) ); + +my ( $baseurl, $m ) = RT::Test->started_ok; +ok($m->login, 'logged in'); + +$m->follow_link_ok({text => "Tickets"}, "to query builder"); + +$m->form_name("BuildQuery"); + +$m->field(ValueOfid => 10 ); +$m->click("AddClause"); +$m->content_contains( 'id < 10', "added new clause"); + +$m->form_name("BuildQuery"); +$m->field(SavedSearchDescription => 'user_saved'); +$m->click("SavedSearchSave"); + +$m->form_name("BuildQuery"); +is($m->value('SavedSearchDescription'), 'user_saved', "name is correct"); +like($m->value('SavedSearchOwner'), qr/^RT::User-\d+$/, "name is correct"); +ok( + scalar grep { $_ eq "RT::Group-$gid" } + $m->current_form->find_input('SavedSearchOwner')->possible_values, + 'found group foo' +); +$m->field(SavedSearchDescription => 'group_saved'); +$m->select(SavedSearchOwner => "RT::Group-$gid"); +$m->click("SavedSearchSave"); + +$m->form_name("BuildQuery"); +is($m->value('SavedSearchOwner'), "RT::Group-$gid", "privacy is correct"); +is($m->value('SavedSearchDescription'), 'group_saved', "name is correct"); +$m->select(SavedSearchOwner => "RT::User-$uid"); +$m->field(SavedSearchDescription => 'user_saved'); +$m->click("SavedSearchSave"); + + +$m->form_name("BuildQuery"); +is($m->value('SavedSearchOwner'), "RT::User-$uid", "privacy is correct"); +is($m->value('SavedSearchDescription'), 'user_saved', "name is correct"); +$m->select(SavedSearchOwner => "RT::System-1"); +$m->field(SavedSearchDescription => 'system_saved'); +$m->click("SavedSearchSave"); + +$m->form_name("BuildQuery"); +is($m->value('SavedSearchOwner'), "RT::System-1", "privacy is correct"); +is($m->value('SavedSearchDescription'), 'system_saved', "name is correct"); + diff --git a/rt/t/web/ticket_seen.t b/rt/t/web/ticket_seen.t index 00b2632d8..3a77a5899 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 => 16; +use RT::Test tests => 21; my $queue = RT::Test->load_or_create_queue( Name => 'Regression' ); ok $queue && $queue->id, 'loaded or created queue'; @@ -52,6 +52,14 @@ diag "user B adds a message, we check that user A see notification and can clear my ($status, $msg) = $ticket->Correspond( Content => 'bla-bla' ); ok $status, 'added reply' or diag "error: $msg"; + my $txns = $ticket->Transactions; + $txns->Limit( + FIELD => 'Type', + VALUE => "Correspond", + ); + my $txn = $txns->Last; + my $reply_id = $txn->id; + 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'); @@ -61,11 +69,23 @@ diag "user B adds a message, we check that user A see notification and can clear 'we have not seen something' ); + $agent_a->follow_link_ok( + { text => 'jump to the first unread message' }, + 'try to jump to first unread message' + ); + 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, 'see success message' ); + like( $agent_a->base, qr/#txn-$reply_id$/, 'contains anchor' ); + + $agent_a->content_like( + qr/Marked all messages as seen/ims, + 'see success message' + ); $agent_a->goto_ticket($tid); $agent_a->content_unlike( @@ -74,7 +94,3 @@ diag "user B adds a message, we check that user A see notification and can clear ); } - - - - diff --git a/rt/t/web/ticket_txn_content.t b/rt/t/web/ticket_txn_content.t new file mode 100644 index 000000000..1c1056a3e --- /dev/null +++ b/rt/t/web/ticket_txn_content.t @@ -0,0 +1,79 @@ +#!/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 ); +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"; +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 $qid = $queue->Load('General'); +ok( $qid, "Loaded General queue" ); + +RT::Test->set_mail_catcher; +RT::Test->clean_caught_mails; + +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->form_name('TicketCreate'); + $m->field( 'Subject', 'with plain attachment' ); + $m->field( 'Attach', $plain_file ); + $m->field( 'Content', 'this is main content' ); + $m->field( 'ContentType', $type ) unless $type eq 'text/plain'; + $m->submit; + is( $m->status, 200, "request successful" ); + $m->content_like( qr/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' ); + + 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->back; + + $m->follow_link_ok( { text => 'Reply' }, "reply to the ticket" ); + $m->form_name('TicketUpdate'); + $m->field( 'Attach', $plain_file ); + $m->click('AddMoreAttach'); + is( $m->status, 200, "request successful" ); + + $m->form_name('TicketUpdate'); + $m->field( 'Attach', $html_file ); + # add UpdateCc so we can get email record + $m->field( 'UpdateCc', 'rt-test@example.com' ); + $m->field( 'UpdateContent', 'this is main reply content' ); + $m->field( 'UpdateContentType', $type ) unless $type eq 'text/plain'; + $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' ); + + ( $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->back; +} |