summaryrefslogtreecommitdiff
path: root/rt/t/api
diff options
context:
space:
mode:
Diffstat (limited to 'rt/t/api')
-rw-r--r--rt/t/api/ace.t238
-rw-r--r--rt/t/api/action-createtickets.t240
-rw-r--r--rt/t/api/attachment.t45
-rw-r--r--rt/t/api/attribute-tests.t86
-rw-r--r--rt/t/api/attribute.t42
-rw-r--r--rt/t/api/cf.t224
-rw-r--r--rt/t/api/cf_combo_casacade.t46
-rw-r--r--rt/t/api/cf_external.t56
-rw-r--r--rt/t/api/cf_pattern.t53
-rw-r--r--rt/t/api/cf_single_values.t38
-rw-r--r--rt/t/api/cf_transaction.t60
-rw-r--r--rt/t/api/condition-ownerchange.t51
-rw-r--r--rt/t/api/condition-reject.t45
-rw-r--r--rt/t/api/currentuser.t32
-rw-r--r--rt/t/api/customfield.t74
-rw-r--r--rt/t/api/date.t564
-rw-r--r--rt/t/api/emailparser.t19
-rw-r--r--rt/t/api/group.t99
-rw-r--r--rt/t/api/groups.t139
-rw-r--r--rt/t/api/i18n.t30
-rw-r--r--rt/t/api/link.t24
-rw-r--r--rt/t/api/queue.t92
-rw-r--r--rt/t/api/record.t70
-rw-r--r--rt/t/api/reminders.t88
-rw-r--r--rt/t/api/rights.t197
-rw-r--r--rt/t/api/rights_show_ticket.t262
-rw-r--r--rt/t/api/rt.t18
-rw-r--r--rt/t/api/scrip.t49
-rw-r--r--rt/t/api/scrip_order.t56
-rw-r--r--rt/t/api/searchbuilder.t40
-rw-r--r--rt/t/api/system.t33
-rw-r--r--rt/t/api/template-insert.t26
-rw-r--r--rt/t/api/template.t26
-rw-r--r--rt/t/api/ticket.t257
-rw-r--r--rt/t/api/tickets.t104
-rw-r--r--rt/t/api/tickets_overlay_sql.t73
-rw-r--r--rt/t/api/uri-fsck_com_rt.t28
-rw-r--r--rt/t/api/uri-t.t21
-rw-r--r--rt/t/api/user.t339
-rw-r--r--rt/t/api/users.t80
40 files changed, 4064 insertions, 0 deletions
diff --git a/rt/t/api/ace.t b/rt/t/api/ace.t
new file mode 100644
index 0000000..4031046
--- /dev/null
+++ b/rt/t/api/ace.t
@@ -0,0 +1,238 @@
+
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 76;
+
+
+{
+
+ok(require RT::ACE);
+
+
+}
+
+{
+
+my $Queue = RT::Queue->new($RT::SystemUser);
+
+is ($Queue->AvailableRights->{'DeleteTicket'} , 'Delete tickets', "Found the delete ticket right");
+is ($RT::System->AvailableRights->{'SuperUser'}, 'Do anything and everything', "Found the superuser right");
+
+
+
+}
+
+{
+
+use_ok('RT::User');
+my $user_a = RT::User->new($RT::SystemUser);
+$user_a->Create( Name => 'DelegationA', Privileged => 1);
+ok ($user_a->Id, "Created delegation user a");
+
+my $user_b = RT::User->new($RT::SystemUser);
+$user_b->Create( Name => 'DelegationB', Privileged => 1);
+ok ($user_b->Id, "Created delegation user b");
+
+
+use_ok('RT::Queue');
+my $q = RT::Queue->new($RT::SystemUser);
+$q->Create(Name =>'DelegationTest');
+ok ($q->Id, "Created a delegation test queue");
+
+
+#------ First, we test whether a user can delegate a right that's been granted to him personally
+my ($val, $msg) = $user_a->PrincipalObj->GrantRight(Object => $RT::System, Right => 'AdminOwnPersonalGroups');
+ok($val, $msg);
+
+($val, $msg) = $user_a->PrincipalObj->GrantRight(Object =>$q, Right => 'OwnTicket');
+ok($val, $msg);
+
+ok($user_a->HasRight( Object => $RT::System, Right => 'AdminOwnPersonalGroups') ,"user a has the right 'AdminOwnPersonalGroups' directly");
+
+my $a_delegates = RT::Group->new($user_a);
+$a_delegates->CreatePersonalGroup(Name => 'Delegates');
+ok( $a_delegates->Id ,"user a creates a personal group 'Delegates'");
+ok( $a_delegates->AddMember($user_b->PrincipalId) ,"user a adds user b to personal group 'delegates'");
+
+ok( !$user_b->HasRight(Right => 'OwnTicket', Object => $q) ,"user b does not have the right to OwnTicket' in queue 'DelegationTest'");
+ok( $user_a->HasRight(Right => 'OwnTicket', Object => $q) ,"user a has the right to 'OwnTicket' in queue 'DelegationTest'");
+ok(!$user_a->HasRight( Object => $RT::System, Right => 'DelegateRights') ,"user a does not have the right 'delegate rights'");
+
+
+my $own_ticket_ace = RT::ACE->new($user_a);
+my $user_a_equiv_group = RT::Group->new($user_a);
+$user_a_equiv_group->LoadACLEquivalenceGroup($user_a->PrincipalObj);
+ok ($user_a_equiv_group->Id, "Loaded the user A acl equivalence group");
+my $user_b_equiv_group = RT::Group->new($user_b);
+$user_b_equiv_group->LoadACLEquivalenceGroup($user_b->PrincipalObj);
+ok ($user_b_equiv_group->Id, "Loaded the user B acl equivalence group");
+$own_ticket_ace->LoadByValues( PrincipalType => 'Group', PrincipalId => $user_a_equiv_group->PrincipalId, Object=>$q, RightName => 'OwnTicket');
+
+ok ($own_ticket_ace->Id, "Found the ACE we want to test with for now");
+
+
+($val, $msg) = $own_ticket_ace->Delegate(PrincipalId => $a_delegates->PrincipalId) ;
+ok( !$val ,"user a tries and fails to delegate the right 'ownticket' in queue 'DelegationTest' to personal group 'delegates' - $msg");
+
+
+($val, $msg) = $user_a->PrincipalObj->GrantRight( Right => 'DelegateRights');
+ok($val, "user a is granted the right to 'delegate rights' - $msg");
+
+ok($user_a->HasRight( Object => $RT::System, Right => 'DelegateRights') ,"user a has the right 'DeletgateRights'");
+
+($val, $msg) = $own_ticket_ace->Delegate(PrincipalId => $a_delegates->PrincipalId) ;
+
+ok( $val ,"user a tries and succeeds to delegate the right 'ownticket' in queue 'DelegationTest' to personal group 'delegates' - $msg");
+ok( $user_b->HasRight(Right => 'OwnTicket', Object => $q) ,"user b has the right to own tickets in queue 'DelegationTest'");
+my $delegated_ace = RT::ACE->new($user_a);
+$delegated_ace->LoadByValues ( Object => $q, RightName => 'OwnTicket', PrincipalType => 'Group',
+PrincipalId => $a_delegates->PrincipalId, DelegatedBy => $user_a->PrincipalId, DelegatedFrom => $own_ticket_ace->Id);
+ok ($delegated_ace->Id, "Found the delegated ACE");
+
+ok( $a_delegates->DeleteMember($user_b->PrincipalId) ,"user a removes b from pg 'delegates'");
+ok( !$user_b->HasRight(Right => 'OwnTicket', Object => $q) ,"user b does not have the right to own tickets in queue 'DelegationTest'");
+ok( $a_delegates->AddMember($user_b->PrincipalId) ,"user a adds user b to personal group 'delegates'");
+ok( $user_b->HasRight(Right => 'OwnTicket', Object=> $q) ,"user b has the right to own tickets in queue 'DelegationTest'");
+ok( $delegated_ace->Delete ,"user a revokes pg 'delegates' right to 'OwnTickets' in queue 'DelegationTest'");
+ok( ! $user_b->HasRight(Right => 'OwnTicket', Object => $q) ,"user b does not have the right to own tickets in queue 'DelegationTest'");
+
+($val, $msg) = $own_ticket_ace->Delegate(PrincipalId => $a_delegates->PrincipalId) ;
+ok( $val ,"user a delegates pg 'delegates' right to 'OwnTickets' in queue 'DelegationTest' - $msg");
+
+ok( $user_b->HasRight(Right => 'OwnTicket', Object => $q) ,"user b has the right to own tickets in queue 'DelegationTest'");
+
+($val, $msg) = $user_a->PrincipalObj->RevokeRight(Object=>$q, Right => 'OwnTicket');
+ok($val, "Revoked user a's right to own tickets in queue 'DelegationTest". $msg);
+
+ok( !$user_a->HasRight(Right => 'OwnTicket', Object => $q) ,"user a does not have the right to own tickets in queue 'DelegationTest'");
+
+ ok( !$user_b->HasRight(Right => 'OwnTicket', Object => $q) ,"user b does not have the right to own tickets in queue 'DelegationTest'");
+
+($val, $msg) = $user_a->PrincipalObj->GrantRight(Object=>$q, Right => 'OwnTicket');
+ok($val, $msg);
+
+ ok( $user_a->HasRight(Right => 'OwnTicket', Object => $q) ,"user a has the right to own tickets in queue 'DelegationTest'");
+
+ ok( !$user_b->HasRight(Right => 'OwnTicket', Object => $q) ,"user b does not have the right to own tickets in queue 'DelegationTest'");
+
+# {{{ get back to a known clean state
+($val, $msg) = $user_a->PrincipalObj->RevokeRight( Object => $q, Right => 'OwnTicket');
+ok($val, "Revoked user a's right to own tickets in queue 'DelegationTest -". $msg);
+ok( !$user_a->HasRight(Right => 'OwnTicket', Object => $q) ,"make sure that user a can't own tickets in queue 'DelegationTest'");
+# }}}
+
+
+# {{{ Set up some groups and membership
+my $del1 = RT::Group->new($RT::SystemUser);
+($val, $msg) = $del1->CreateUserDefinedGroup(Name => 'Del1');
+ok( $val ,"create a group del1 - $msg");
+
+my $del2 = RT::Group->new($RT::SystemUser);
+($val, $msg) = $del2->CreateUserDefinedGroup(Name => 'Del2');
+ok( $val ,"create a group del2 - $msg");
+($val, $msg) = $del1->AddMember($del2->PrincipalId);
+ok( $val,"make del2 a member of del1 - $msg");
+
+my $del2a = RT::Group->new($RT::SystemUser);
+($val, $msg) = $del2a->CreateUserDefinedGroup(Name => 'Del2a');
+ok( $val ,"create a group del2a - $msg");
+($val, $msg) = $del2->AddMember($del2a->PrincipalId);
+ok($val ,"make del2a a member of del2 - $msg");
+
+my $del2b = RT::Group->new($RT::SystemUser);
+($val, $msg) = $del2b->CreateUserDefinedGroup(Name => 'Del2b');
+ok( $val ,"create a group del2b - $msg");
+($val, $msg) = $del2->AddMember($del2b->PrincipalId);
+ok($val ,"make del2b a member of del2 - $msg");
+
+($val, $msg) = $del2->AddMember($user_a->PrincipalId) ;
+ok($val,"make 'user a' a member of del2 - $msg");
+
+($val, $msg) = $del2b->AddMember($user_a->PrincipalId) ;
+ok($val,"make 'user a' a member of del2b - $msg");
+
+# }}}
+
+# {{{ Grant a right to a group and make sure that a submember can delegate the right and that it does not get yanked
+# when a user is removed as a submember, when they're a submember through another path
+($val, $msg) = $del1->PrincipalObj->GrantRight( Object=> $q, Right => 'OwnTicket');
+ok( $val ,"grant del1 the right to 'OwnTicket' in queue 'DelegationTest' - $msg");
+
+ok( $user_a->HasRight(Right => 'OwnTicket', Object => $q) ,"make sure that user a can own tickets in queue 'DelegationTest'");
+
+my $group_ace= RT::ACE->new($user_a);
+$group_ace->LoadByValues( PrincipalType => 'Group', PrincipalId => $del1->PrincipalId, Object => $q, RightName => 'OwnTicket');
+
+ok ($group_ace->Id, "Found the ACE we want to test with for now");
+
+($val, $msg) = $group_ace->Delegate(PrincipalId => $a_delegates->PrincipalId);
+
+ok( $val ,"user a tries and succeeds to delegate the right 'ownticket' in queue 'DelegationTest' to personal group 'delegates' - $msg");
+ok( $user_b->HasRight(Right => 'OwnTicket', Object => $q) ,"user b has the right to own tickets in queue 'DelegationTest'");
+
+
+($val, $msg) = $del2b->DeleteMember($user_a->PrincipalId);
+ok( $val ,"remove user a from group del2b - $msg");
+ok( $user_a->HasRight(Right => 'OwnTicket', Object => $q) ,"user a has the right to own tickets in queue 'DelegationTest'");
+ok( $user_b->HasRight(Right => 'OwnTicket', Object => $q) ,"user b has the right to own tickets in queue 'DelegationTest'");
+
+# }}}
+
+# {{{ When a user is removed froom a group by the only path they're in there by, make sure the delegations go away
+($val, $msg) = $del2->DeleteMember($user_a->PrincipalId);
+ok( $val ,"remove user a from group del2 - $msg");
+ok( !$user_a->HasRight(Right => 'OwnTicket', Object => $q) ,"user a does not have the right to own tickets in queue 'DelegationTest' ");
+ok( !$user_b->HasRight(Right => 'OwnTicket', Object => $q) ,"user b does not have the right to own tickets in queue 'DelegationTest' ");
+# }}}
+
+($val, $msg) = $del2->AddMember($user_a->PrincipalId);
+ok( $val ,"make user a a member of group del2 - $msg");
+
+($val, $msg) = $del2->PrincipalObj->GrantRight(Object=>$q, Right => 'OwnTicket');
+ok($val, "grant the right 'own tickets' in queue 'DelegationTest' to group del2 - $msg");
+
+my $del2_right = RT::ACE->new($user_a);
+$del2_right->LoadByValues( PrincipalId => $del2->PrincipalId, PrincipalType => 'Group', Object => $q, RightName => 'OwnTicket');
+ok ($del2_right->Id, "Found the right");
+
+($val, $msg) = $del2_right->Delegate(PrincipalId => $a_delegates->PrincipalId);
+ok( $val ,"user a tries and succeeds to delegate the right 'ownticket' in queue 'DelegationTest' gotten via del2 to personal group 'delegates' - $msg");
+
+# They have it via del1 and del2
+ok( $user_b->HasRight(Right => 'OwnTicket', Object => $q) ,"user b has the right to own tickets in queue 'DelegationTest'");
+
+
+($val, $msg) = $del2->PrincipalObj->RevokeRight(Object=>$q, Right => 'OwnTicket');
+ok($val, "revoke the right 'own tickets' in queue 'DelegationTest' to group del2 - $msg");
+ok( $user_a->HasRight(Right => 'OwnTicket', Object => $q) ,"user a does has the right to own tickets in queue 'DelegationTest' via del1");
+ok( !$user_b->HasRight(Right => 'OwnTicket', Object => $q) ,"user b does not have the right to own tickets in queue 'DelegationTest'");
+
+($val, $msg) = $del2->PrincipalObj->GrantRight(Object=>$q, Right => 'OwnTicket');
+ok($val, "grant the right 'own tickets' in queue 'DelegationTest' to group del2 - $msg");
+
+
+$group_ace= RT::ACE->new($user_a);
+$group_ace->LoadByValues( PrincipalType => 'Group', PrincipalId => $del1->PrincipalId, Object=>$q, RightName => 'OwnTicket');
+
+ok ($group_ace->Id, "Found the ACE we want to test with for now");
+
+($val, $msg) = $group_ace->Delegate(PrincipalId => $a_delegates->PrincipalId);
+
+ok( $val ,"user a tries and succeeds to delegate the right 'ownticket' in queue 'DelegationTest' to personal group 'delegates' - $msg");
+
+ok( $user_b->HasRight(Right => 'OwnTicket', Object => $q) ,"user b has the right to own tickets in queue 'DelegationTest'");
+
+($val, $msg) = $del2->DeleteMember($user_a->PrincipalId);
+ok( $val ,"remove user a from group del2 - $msg");
+
+ok( !$user_a->HasRight(Right => 'OwnTicket', Object => $q) ,"user a does not have the right to own tickets in queue 'DelegationTest'");
+
+ok( !$user_b->HasRight(Right => 'OwnTicket', Object => $q) ,"user b does not have the right to own tickets in queue 'DelegationTest'");
+
+
+
+
+}
+
+1;
diff --git a/rt/t/api/action-createtickets.t b/rt/t/api/action-createtickets.t
new file mode 100644
index 0000000..69ceb8d
--- /dev/null
+++ b/rt/t/api/action-createtickets.t
@@ -0,0 +1,240 @@
+
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 49;
+
+
+{
+
+ok (require RT::Action::CreateTickets);
+use_ok('RT::Scrip');
+use_ok('RT::Template');
+use_ok('RT::ScripAction');
+use_ok('RT::ScripCondition');
+use_ok('RT::Ticket');
+
+my $approvalsq = RT::Queue->new($RT::SystemUser);
+$approvalsq->Create(Name => 'Approvals');
+ok ($approvalsq->Id, "Created Approvals test queue");
+
+
+my $approvals =
+'===Create-Ticket: approval
+Queue: Approvals
+Type: approval
+AdminCc: {join ("\nAdminCc: ",@admins) }
+Depended-On-By: {$Tickets{"TOP"}->Id}
+Refers-To: TOP
+Subject: Approval for ticket: {$Tickets{"TOP"}->Id} - {$Tickets{"TOP"}->Subject}
+Due: {time + 86400}
+Content-Type: text/plain
+Content: Your approval is requested for the ticket {$Tickets{"TOP"}->Id}: {$Tickets{"TOP"}->Subject}
+Blah
+Blah
+ENDOFCONTENT
+===Create-Ticket: two
+Subject: Manager approval.
+Depended-On-By: approval
+Queue: Approvals
+Content-Type: text/plain
+Content:
+Your minion approved ticket {$Tickets{"TOP"}->Id}. you ok with that?
+ENDOFCONTENT
+';
+
+like ($approvals , qr/Content/, "Read in the approvals template");
+
+my $apptemp = RT::Template->new($RT::SystemUser);
+$apptemp->Create( Content => $approvals, Name => "Approvals", Queue => "0");
+
+ok ($apptemp->Id);
+
+my $q = RT::Queue->new($RT::SystemUser);
+$q->Create(Name => 'WorkflowTest');
+ok ($q->Id, "Created workflow test queue");
+
+my $scrip = RT::Scrip->new($RT::SystemUser);
+my ($sval, $smsg) =$scrip->Create( ScripCondition => 'On Transaction',
+ ScripAction => 'Create Tickets',
+ Template => 'Approvals',
+ Queue => $q->Id);
+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) = $t->Create(Subject => "Sample workflow test",
+ Owner => "root",
+ Queue => $q->Id);
+
+ok ($tid,$tmsg);
+
+my $deps = $t->DependsOn;
+is ($deps->Count, 1, "The ticket we created depends on one other ticket");
+my $dependson= $deps->First->TargetObj;
+ok ($dependson->Id, "It depends on a real ticket");
+unlike ($dependson->Subject, qr/{/, "The subject doesn't have braces in it. that means we're interpreting expressions");
+is ($t->ReferredToBy->Count,1, "It's only referred to by one other ticket");
+is ($t->ReferredToBy->First->BaseObj->Id,$t->DependsOn->First->TargetObj->Id, "The same ticket that depends on it refers to it.");
+use RT::Action::CreateTickets;
+my $action = RT::Action::CreateTickets->new( CurrentUser => $RT::SystemUser);
+
+# comma-delimited templates
+my $commas = <<"EOF";
+id,Queue,Subject,Owner,Content
+ticket1,General,"foo, bar",root,blah
+ticket2,General,foo bar,root,blah
+ticket3,General,foo' bar,root,blah'boo
+ticket4,General,foo' bar,,blah'boo
+EOF
+
+
+# Comma delimited templates with missing data
+my $sparse_commas = <<"EOF";
+id,Queue,Subject,Owner,Requestor
+ticket14,General,,,bobby
+ticket15,General,,,tommy
+ticket16,General,,suzie,tommy
+ticket17,General,Foo "bar" baz,suzie,tommy
+ticket18,General,'Foo "bar" baz',suzie,tommy
+ticket19,General,'Foo bar' baz,suzie,tommy
+EOF
+
+
+# tab-delimited templates
+my $tabs = <<"EOF";
+id\tQueue\tSubject\tOwner\tContent
+ticket10\tGeneral\t"foo' bar"\troot\tblah'
+ticket11\tGeneral\tfoo, bar\troot\tblah
+ticket12\tGeneral\tfoo' bar\troot\tblah'boo
+ticket13\tGeneral\tfoo' bar\t\tblah'boo
+EOF
+
+my %expected;
+
+$expected{ticket1} = <<EOF;
+Queue: General
+Subject: foo, bar
+Owner: root
+Content: blah
+ENDOFCONTENT
+EOF
+
+$expected{ticket2} = <<EOF;
+Queue: General
+Subject: foo bar
+Owner: root
+Content: blah
+ENDOFCONTENT
+EOF
+
+$expected{ticket3} = <<EOF;
+Queue: General
+Subject: foo' bar
+Owner: root
+Content: blah'boo
+ENDOFCONTENT
+EOF
+
+$expected{ticket4} = <<EOF;
+Queue: General
+Subject: foo' bar
+Owner:
+Content: blah'boo
+ENDOFCONTENT
+EOF
+
+$expected{ticket10} = <<EOF;
+Queue: General
+Subject: foo' bar
+Owner: root
+Content: blah'
+ENDOFCONTENT
+EOF
+
+$expected{ticket11} = <<EOF;
+Queue: General
+Subject: foo, bar
+Owner: root
+Content: blah
+ENDOFCONTENT
+EOF
+
+$expected{ticket12} = <<EOF;
+Queue: General
+Subject: foo' bar
+Owner: root
+Content: blah'boo
+ENDOFCONTENT
+EOF
+
+$expected{ticket13} = <<EOF;
+Queue: General
+Subject: foo' bar
+Owner:
+Content: blah'boo
+ENDOFCONTENT
+EOF
+
+
+$expected{'ticket14'} = <<EOF;
+Queue: General
+Subject:
+Owner:
+Requestor: bobby
+EOF
+$expected{'ticket15'} = <<EOF;
+Queue: General
+Subject:
+Owner:
+Requestor: tommy
+EOF
+$expected{'ticket16'} = <<EOF;
+Queue: General
+Subject:
+Owner: suzie
+Requestor: tommy
+EOF
+$expected{'ticket17'} = <<EOF;
+Queue: General
+Subject: Foo "bar" baz
+Owner: suzie
+Requestor: tommy
+EOF
+$expected{'ticket18'} = <<EOF;
+Queue: General
+Subject: Foo "bar" baz
+Owner: suzie
+Requestor: tommy
+EOF
+$expected{'ticket19'} = <<EOF;
+Queue: General
+Subject: 'Foo bar' baz
+Owner: suzie
+Requestor: tommy
+EOF
+
+
+
+
+$action->Parse(Content =>$commas);
+$action->Parse(Content =>$sparse_commas);
+$action->Parse(Content => $tabs);
+
+my %got;
+foreach (@{ $action->{'create_tickets'} }) {
+ $got{$_} = $action->{'templates'}->{$_};
+}
+
+foreach my $id ( sort keys %expected ) {
+ ok(exists($got{"create-$id"}), "template exists for $id");
+ is($got{"create-$id"}, $expected{$id}, "template is correct for $id");
+}
+
+
+}
+
+1;
diff --git a/rt/t/api/attachment.t b/rt/t/api/attachment.t
new file mode 100644
index 0000000..07c46ba
--- /dev/null
+++ b/rt/t/api/attachment.t
@@ -0,0 +1,45 @@
+
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 4;
+
+
+{
+
+ok (require RT::Attachment);
+
+
+}
+
+{
+
+my $test1 = "From: jesse";
+my @headers = RT::Attachment->_SplitHeaders($test1);
+is ($#headers, 0, $test1 );
+
+my $test2 = qq{From: jesse
+To: bobby
+Subject: foo
+};
+
+@headers = RT::Attachment->_SplitHeaders($test2);
+is ($#headers, 2, "testing a bunch of singline multiple headers" );
+
+
+my $test3 = qq{From: jesse
+To: bobby,
+ Suzie,
+ Sally,
+ Joey: bizzy,
+Subject: foo
+};
+
+@headers = RT::Attachment->_SplitHeaders($test3);
+is ($#headers, 2, "testing a bunch of singline multiple headers" );
+
+
+
+}
+
+1;
diff --git a/rt/t/api/attribute-tests.t b/rt/t/api/attribute-tests.t
new file mode 100644
index 0000000..90c3ddb
--- /dev/null
+++ b/rt/t/api/attribute-tests.t
@@ -0,0 +1,86 @@
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 34;
+
+
+
+my $runid = rand(200);
+
+my $attribute = "squelch-$runid";
+
+ok(require RT::Attributes);
+
+my $user = RT::User->new($RT::SystemUser);
+ok (UNIVERSAL::isa($user, 'RT::User'));
+my ($id,$msg) = $user->Create(Name => 'attrtest-'.$runid);
+ok ($id, $msg);
+ok($user->id, "Created a test user");
+
+ok(1, $user->Attributes->BuildSelectQuery);
+my $attr = $user->Attributes;
+# XXX: Order by id as some tests depend on it
+$attr->OrderByCols({ FIELD => 'id' });
+
+ok(1, $attr->BuildSelectQuery);
+
+
+ok (UNIVERSAL::isa($attr,'RT::Attributes'), 'got the attributes object');
+
+($id, $msg) = $user->AddAttribute(Name => 'TestAttr', Content => 'The attribute has content');
+ok ($id, $msg);
+is ($attr->Count,1, " One attr after adding a first one");
+
+my $first_attr = $user->FirstAttribute('TestAttr');
+ok($first_attr, "got some sort of attribute");
+isa_ok($first_attr, 'RT::Attribute');
+is($first_attr->Content, 'The attribute has content', "got the right content back");
+
+($id, $msg) = $attr->DeleteEntry(Name => $runid);
+ok(!$id, "Deleted non-existant entry - $msg");
+is ($attr->Count,1, "1 attr after deleting an empty attr");
+
+my @names = $attr->Names;
+is ("@names", "TestAttr");
+
+
+($id, $msg) = $user->AddAttribute(Name => $runid, Content => "First");
+ok($id, $msg);
+
+my $runid_attr = $user->FirstAttribute($runid);
+ok($runid_attr, "got some sort of attribute");
+isa_ok($runid_attr, 'RT::Attribute');
+is($runid_attr->Content, 'First', "got the right content back");
+
+is ($attr->Count,2, " Two attrs after adding an attribute named $runid");
+($id, $msg) = $user->AddAttribute(Name => $runid, Content => "Second");
+ok($id, $msg);
+
+$runid_attr = $user->FirstAttribute($runid);
+ok($runid_attr, "got some sort of attribute");
+isa_ok($runid_attr, 'RT::Attribute');
+is($runid_attr->Content, 'First', "got the first content back still");
+
+is ($attr->Count,3, " Three attrs after adding a secondvalue to $runid");
+($id, $msg) = $attr->DeleteEntry(Name => $runid, Content => "First");
+ok($id, $msg);
+is ($attr->Count,2);
+
+#$attr->_DoSearch();
+($id, $msg) = $attr->DeleteEntry(Name => $runid, Content => "Second");
+ok($id, $msg);
+is ($attr->Count,1);
+
+#$attr->_DoSearch();
+ok(1, $attr->BuildSelectQuery);
+($id, $msg) = $attr->DeleteEntry(Name => "moose");
+ok(!$id, "Deleted non-existant entry - $msg");
+is ($attr->Count,1);
+
+ok(1, $attr->BuildSelectQuery);
+@names = $attr->Names;
+is("@names", "TestAttr");
+
+
+
+1;
diff --git a/rt/t/api/attribute.t b/rt/t/api/attribute.t
new file mode 100644
index 0000000..cb2626a
--- /dev/null
+++ b/rt/t/api/attribute.t
@@ -0,0 +1,42 @@
+
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 7;
+
+
+{
+
+my $user = $RT::SystemUser;
+my ($id, $msg) = $user->AddAttribute(Name => 'SavedSearch', Content => { Query => 'Foo'} );
+ok ($id, $msg);
+my $attr = RT::Attribute->new($RT::SystemUser);
+$attr->Load($id);
+is($attr->Name , 'SavedSearch');
+$attr->SetSubValues( Format => 'baz');
+
+my $format = $attr->SubValue('Format');
+is ($format , 'baz');
+
+$attr->SetSubValues( Format => 'bar');
+$format = $attr->SubValue('Format');
+is ($format , 'bar');
+
+$attr->DeleteAllSubValues();
+$format = $attr->SubValue('Format');
+is ($format, undef);
+
+$attr->SetSubValues(Format => 'This is a format');
+
+my $attr2 = RT::Attribute->new($RT::SystemUser);
+$attr2->Load($id);
+is ($attr2->SubValue('Format'), 'This is a format');
+$attr2->Delete;
+my $attr3 = RT::Attribute->new($RT::SystemUser);
+($id) = $attr3->Load($id);
+is ($id, 0);
+
+
+}
+
+1;
diff --git a/rt/t/api/cf.t b/rt/t/api/cf.t
new file mode 100644
index 0000000..98114c9
--- /dev/null
+++ b/rt/t/api/cf.t
@@ -0,0 +1,224 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings FATAL => 'all';
+
+use RT::Test tests => 139;
+
+# Before we get going, ditch all object_cfs; this will remove
+# all custom fields systemwide;
+my $object_cfs = RT::ObjectCustomFields->new($RT::SystemUser);
+$object_cfs->UnLimit();
+while (my $ocf = $object_cfs->Next) {
+ $ocf->Delete();
+}
+
+
+my $queue = RT::Queue->new( $RT::SystemUser );
+$queue->Create( Name => 'RecordCustomFields-'.$$ );
+ok ($queue->id, "Created the queue");
+
+my $queue2 = RT::Queue->new( $RT::SystemUser );
+$queue2->Create( Name => 'RecordCustomFields2' );
+
+my $ticket = RT::Ticket->new( $RT::SystemUser );
+$ticket->Create(
+ Queue => $queue->Id,
+ Requestor => 'root@localhost',
+ Subject => 'RecordCustomFields1',
+);
+
+my $cfs = $ticket->CustomFields;
+is( $cfs->Count, 0 );
+
+# Check that record has no any CF values yet {{{
+my $cfvs = $ticket->CustomFieldValues;
+is( $cfvs->Count, 0 );
+is( $ticket->FirstCustomFieldValue, undef );
+
+my $local_cf1 = RT::CustomField->new( $RT::SystemUser );
+$local_cf1->Create( Name => 'RecordCustomFields1-'.$$, Type => 'SelectSingle', Queue => $queue->id );
+$local_cf1->AddValue( Name => 'RecordCustomFieldValues11' );
+$local_cf1->AddValue( Name => 'RecordCustomFieldValues12' );
+
+my $local_cf2 = RT::CustomField->new( $RT::SystemUser );
+$local_cf2->Create( Name => 'RecordCustomFields2-'.$$, Type => 'SelectSingle', Queue => $queue->id );
+$local_cf2->AddValue( Name => 'RecordCustomFieldValues21' );
+$local_cf2->AddValue( Name => 'RecordCustomFieldValues22' );
+
+my $global_cf3 = RT::CustomField->new( $RT::SystemUser );
+$global_cf3->Create( Name => 'RecordCustomFields3-'.$$, Type => 'SelectSingle', Queue => 0 );
+$global_cf3->AddValue( Name => 'RecordCustomFieldValues31' );
+$global_cf3->AddValue( Name => 'RecordCustomFieldValues32' );
+
+my $local_cf4 = RT::CustomField->new( $RT::SystemUser );
+$local_cf4->Create( Name => 'RecordCustomFields4', Type => 'SelectSingle', Queue => $queue2->id );
+$local_cf4->AddValue( Name => 'RecordCustomFieldValues41' );
+$local_cf4->AddValue( Name => 'RecordCustomFieldValues42' );
+
+
+my @custom_fields = ($local_cf1, $local_cf2, $global_cf3);
+
+
+$cfs = $ticket->CustomFields;
+is( $cfs->Count, 3 );
+
+# Check that record has no any CF values yet {{{
+$cfvs = $ticket->CustomFieldValues;
+is( $cfvs->Count, 0 );
+is( $ticket->FirstCustomFieldValue, undef );
+
+# CF with ID -1 shouldnt exist at all
+$cfvs = $ticket->CustomFieldValues( -1 );
+is( $cfvs->Count, 0 );
+is( $ticket->FirstCustomFieldValue( -1 ), undef );
+
+$cfvs = $ticket->CustomFieldValues( 'SomeUnexpedCustomFieldName' );
+is( $cfvs->Count, 0 );
+is( $ticket->FirstCustomFieldValue( 'SomeUnexpedCustomFieldName' ), undef );
+
+for (@custom_fields) {
+ $cfvs = $ticket->CustomFieldValues( $_->id );
+ is( $cfvs->Count, 0 );
+
+ $cfvs = $ticket->CustomFieldValues( $_->Name );
+ is( $cfvs->Count, 0 );
+ is( $ticket->FirstCustomFieldValue( $_->id ), undef );
+ is( $ticket->FirstCustomFieldValue( $_->Name ), undef );
+}
+# }}}
+
+# try to add field value with fields that do not exist {{{
+my ($status, $msg) = $ticket->AddCustomFieldValue( Field => -1 , Value => 'foo' );
+ok(!$status, "shouldn't add value" );
+($status, $msg) = $ticket->AddCustomFieldValue( Field => 'SomeUnexpedCustomFieldName' , Value => 'foo' );
+ok(!$status, "shouldn't add value" );
+# }}}
+
+# {{{
+SKIP: {
+
+ skip "TODO: We want fields that are not allowed to set unexpected values", 10;
+ for (@custom_fields) {
+ ($status, $msg) = $ticket->AddCustomFieldValue( Field => $_ , Value => 'SomeUnexpectedCFValue' );
+ ok( !$status, 'value doesn\'t exist');
+
+ ($status, $msg) = $ticket->AddCustomFieldValue( Field => $_->id , Value => 'SomeUnexpectedCFValue' );
+ ok( !$status, 'value doesn\'t exist');
+
+ ($status, $msg) = $ticket->AddCustomFieldValue( Field => $_->Name , Value => 'SomeUnexpectedCFValue' );
+ ok( !$status, 'value doesn\'t exist');
+ }
+
+ # Let check that we did not add value to be sure
+ # using only FirstCustomFieldValue sub because
+ # we checked other variants allready
+ for (@custom_fields) {
+ is( $ticket->FirstCustomFieldValue( $_->id ), undef );
+ }
+
+}
+# Add some values to our custom fields
+for (@custom_fields) {
+ # this should be tested elsewhere
+ $_->AddValue( Name => 'Foo' );
+ $_->AddValue( Name => 'Bar' );
+}
+
+my $test_add_delete_cycle = sub {
+ my $cb = shift;
+ for (@custom_fields) {
+ ($status, $msg) = $ticket->AddCustomFieldValue( Field => $cb->($_) , Value => 'Foo' );
+ ok( $status, "message: $msg");
+ }
+
+ # does it exist?
+ $cfvs = $ticket->CustomFieldValues;
+ is( $cfvs->Count, 3, "We found all three custom fields on our ticket" );
+ for (@custom_fields) {
+ $cfvs = $ticket->CustomFieldValues( $_->id );
+ is( $cfvs->Count, 1 , "we found one custom field when searching by id");
+
+ $cfvs = $ticket->CustomFieldValues( $_->Name );
+ is( $cfvs->Count, 1 , " We found one custom field when searching by name for " . $_->Name);
+ is( $ticket->FirstCustomFieldValue( $_->id ), 'Foo' , "first value by id is foo");
+ is( $ticket->FirstCustomFieldValue( $_->Name ), 'Foo' , "first value by name is foo");
+ }
+ # because our CFs are SingleValue then new value addition should override
+ for (@custom_fields) {
+ ($status, $msg) = $ticket->AddCustomFieldValue( Field => $_ , Value => 'Bar' );
+ ok( $status, "message: $msg");
+ }
+ $cfvs = $ticket->CustomFieldValues;
+ is( $cfvs->Count, 3 );
+ for (@custom_fields) {
+ $cfvs = $ticket->CustomFieldValues( $_->id );
+ is( $cfvs->Count, 1 );
+
+ $cfvs = $ticket->CustomFieldValues( $_->Name );
+ is( $cfvs->Count, 1 );
+ is( $ticket->FirstCustomFieldValue( $_->id ), 'Bar' );
+ is( $ticket->FirstCustomFieldValue( $_->Name ), 'Bar' );
+ }
+ # delete it
+ for (@custom_fields ) {
+ ($status, $msg) = $ticket->DeleteCustomFieldValue( Field => $_ , Value => 'Bar' );
+ ok( $status, "Deleted a custom field value 'Bar' for field ".$_->id.": $msg");
+ }
+ $cfvs = $ticket->CustomFieldValues;
+ is( $cfvs->Count, 0, "The ticket (".$ticket->id.") no longer has any custom field values" );
+ for (@custom_fields) {
+ $cfvs = $ticket->CustomFieldValues( $_->id );
+ is( $cfvs->Count, 0, $ticket->id." has no values for cf ".$_->id );
+
+ $cfvs = $ticket->CustomFieldValues( $_->Name );
+ is( $cfvs->Count, 0 , $ticket->id." has no values for cf '".$_->Name. "'" );
+ is( $ticket->FirstCustomFieldValue( $_->id ), undef , "There is no first custom field value when loading by id" );
+ is( $ticket->FirstCustomFieldValue( $_->Name ), undef, "There is no first custom field value when loading by Name" );
+ }
+};
+
+# lets test cycle via CF id
+$test_add_delete_cycle->( sub { return $_[0]->id } );
+# lets test cycle via CF object reference
+$test_add_delete_cycle->( sub { return $_[0] } );
+
+$ticket->AddCustomFieldValue( Field => $local_cf2->id , Value => 'Baz' );
+$ticket->AddCustomFieldValue( Field => $global_cf3->id , Value => 'Baz' );
+# now if we ask for cf values on RecordCustomFields4 we should not get any
+$cfvs = $ticket->CustomFieldValues( 'RecordCustomFields4' );
+is( $cfvs->Count, 0, "No custom field values for non-Queue cf" );
+is( $ticket->FirstCustomFieldValue( 'RecordCustomFields4' ), undef, "No first custom field value for non-Queue cf" );
+
+{
+ my $cfname = $global_cf3->Name;
+ ($status, $msg) = $global_cf3->SetDisabled(1);
+ ok($status, "Disabled CF named $cfname");
+
+ my $load = RT::CustomField->new( $RT::SystemUser );
+ $load->LoadByName( Name => $cfname);
+ ok($load->Id, "Loaded CF named $cfname");
+ is($load->Id, $global_cf3->Id, "Can load disabled CFs");
+
+ my $dup = RT::CustomField->new( $RT::SystemUser );
+ $dup->Create( Name => $cfname, Type => 'SelectSingle', Queue => 0 );
+ ok($dup->Id, "Created CF with duplicate name");
+
+ $load->LoadByName( Name => $cfname);
+ is($load->Id, $dup->Id, "Loading by name gets non-disabled first");
+
+ $dup->SetDisabled(1);
+ $global_cf3->SetDisabled(0);
+
+ $load->LoadByName( Name => $cfname);
+ is($load->Id, $global_cf3->Id, "Loading by name gets non-disabled first, even with order swapped");
+}
+
+#SKIP: {
+# skip "TODO: should we add CF values to objects via CF Name?", 48;
+# names are not unique
+ # lets test cycle via CF Name
+# $test_add_delete_cycle->( sub { return $_[0]->Name } );
+#}
+
+
diff --git a/rt/t/api/cf_combo_casacade.t b/rt/t/api/cf_combo_casacade.t
new file mode 100644
index 0000000..b37345a
--- /dev/null
+++ b/rt/t/api/cf_combo_casacade.t
@@ -0,0 +1,46 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+
+use RT::Test tests => 11;
+
+sub fails { ok(!$_[0], "This should fail: $_[1]") }
+sub works { ok($_[0], $_[1] || 'This works') }
+
+sub new (*) {
+ my $class = shift;
+ return $class->new($RT::SystemUser);
+}
+
+my $q = new(RT::Queue);
+works($q->Create(Name => "CF-Pattern-".$$));
+
+my $cf = new(RT::CustomField);
+my @cf_args = (Name => $q->Name, Type => 'Combobox', Queue => $q->id);
+
+works($cf->Create(@cf_args));
+
+# Set some CFVs with Category markers
+
+my $t = new(RT::Ticket);
+my ($id,undef,$msg) = $t->Create(Queue => $q->id, Subject => 'CF Test');
+works($id,$msg);
+
+sub add_works {
+ works(
+ $cf->AddValue(Name => $_[0], Description => $_[0], Category => $_[1])
+ );
+};
+
+add_works('value1', '1. Category A');
+add_works('value2');
+add_works('value3', '1.1. A-sub one');
+add_works('value4', '1.2. A-sub two');
+add_works('value5', '');
+
+my $cfv = $cf->Values->First;
+is($cfv->Category, '1. Category A');
+works($cfv->SetCategory('1. Category AAA'));
+is($cfv->Category, '1. Category AAA');
+
+1;
diff --git a/rt/t/api/cf_external.t b/rt/t/api/cf_external.t
new file mode 100644
index 0000000..0768712
--- /dev/null
+++ b/rt/t/api/cf_external.t
@@ -0,0 +1,56 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use RT;
+use RT::Test nodata => 1, tests => 11;
+
+sub new (*) {
+ my $class = shift;
+ return $class->new($RT::SystemUser);
+}
+
+use constant VALUES_CLASS => 'RT::CustomFieldValues::Groups';
+
+my $q = new( RT::Queue );
+isa_ok( $q, 'RT::Queue' );
+my ($qid) = $q->Create( Name => "CF-External-". $$ );
+ok( $qid, "created queue" );
+my %arg = ( Name => $q->Name,
+ Type => 'Select',
+ Queue => $q->id,
+ MaxValues => 1,
+ ValuesClass => VALUES_CLASS );
+
+my $cf = new( RT::CustomField );
+isa_ok( $cf, 'RT::CustomField' );
+
+{
+ my ($cfid) = $cf->Create( %arg );
+ ok( $cfid, "created cf" );
+ is( $cf->ValuesClass, VALUES_CLASS, "right values class" );
+ ok( $cf->IsExternalValues, "custom field has external values" );
+}
+
+{
+ # create at least on group for the tests
+ my $group = RT::Group->new( $RT::SystemUser );
+ my ($ret, $msg) = $group->CreateUserDefinedGroup( Name => $q->Name );
+ ok $ret, 'created group' or diag "error: $msg";
+}
+
+{
+ my $values = $cf->Values;
+ isa_ok( $values, VALUES_CLASS );
+ ok( $values->Count, "we have values" );
+ my ($failure, $count) = (0, 0);
+ while( my $value = $values->Next ) {
+ $count++;
+ $failure = 1 unless $value->Name;
+ }
+ ok( !$failure, "all values have name" );
+ is( $values->Count, $count, "count is correct" );
+}
+
+exit(0);
diff --git a/rt/t/api/cf_pattern.t b/rt/t/api/cf_pattern.t
new file mode 100644
index 0000000..89db2fe
--- /dev/null
+++ b/rt/t/api/cf_pattern.t
@@ -0,0 +1,53 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+
+use RT;
+use RT::Test tests => 17;
+
+
+sub fails { ok(!$_[0], "This should fail: $_[1]") }
+sub works { ok($_[0], $_[1] || 'This works') }
+
+sub new (*) {
+ my $class = shift;
+ return $class->new($RT::SystemUser);
+}
+
+my $q = new(RT::Queue);
+works($q->Create(Name => "CF-Pattern-".$$));
+
+my $cf = new(RT::CustomField);
+my @cf_args = (Name => $q->Name, Type => 'Freeform', Queue => $q->id, MaxValues => 1);
+
+fails($cf->Create(@cf_args, Pattern => ')))bad!regex((('));
+works($cf->Create(@cf_args, Pattern => 'good regex'));
+
+my $t = new(RT::Ticket);
+my ($id,undef,$msg) = $t->Create(Queue => $q->id, Subject => 'CF Test');
+works($id,$msg);
+
+# OK, I'm thoroughly brain washed by HOP at this point now...
+sub cnt { $t->CustomFieldValues($cf->id)->Count };
+sub add { $t->AddCustomFieldValue(Field => $cf->id, Value => $_[0]) };
+sub del { $t->DeleteCustomFieldValue(Field => $cf->id, Value => $_[0]) };
+
+is(cnt(), 0, "No values yet");
+fails(add('not going to match'));
+is(cnt(), 0, "No values yet");
+works(add('here is a good regex'));
+is(cnt(), 1, "Value filled");
+fails(del('here is a good regex'));
+is(cnt(), 1, "Single CF - Value _not_ deleted");
+
+$cf->SetMaxValues(0); # Unlimited MaxValues
+
+works(del('here is a good regex'));
+is(cnt(), 0, "Multiple CF - Value deleted");
+
+fails($cf->SetPattern('(?{ "insert evil code here" })'));
+works($cf->SetPattern('(?!)')); # reject everything
+fails(add(''));
+fails(add('...'));
+
+1;
diff --git a/rt/t/api/cf_single_values.t b/rt/t/api/cf_single_values.t
new file mode 100644
index 0000000..8e96edd
--- /dev/null
+++ b/rt/t/api/cf_single_values.t
@@ -0,0 +1,38 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+
+use RT;
+use RT::Test tests => 8;
+
+
+
+my $q = RT::Queue->new($RT::SystemUser);
+my ($id,$msg) =$q->Create(Name => "CF-Single-".$$);
+ok($id,$msg);
+
+my $cf = RT::CustomField->new($RT::SystemUser);
+($id,$msg) = $cf->Create(Name => 'Single-'.$$, Type => 'Select', MaxValues => '1', Queue => $q->id);
+ok($id,$msg);
+
+
+($id,$msg) =$cf->AddValue(Name => 'First');
+ok($id,$msg);
+
+($id,$msg) =$cf->AddValue(Name => 'Second');
+ok($id,$msg);
+
+
+my $t = RT::Ticket->new($RT::SystemUser);
+($id,undef,$msg) = $t->Create(Queue => $q->id,
+ Subject => 'CF Test');
+
+ok($id,$msg);
+is($t->CustomFieldValues($cf->id)->Count, 0, "No values yet");
+$t->AddCustomFieldValue(Field => $cf->id, Value => 'First');
+is($t->CustomFieldValues($cf->id)->Count, 1, "One now");
+
+$t->AddCustomFieldValue(Field => $cf->id, Value => 'Second');
+is($t->CustomFieldValues($cf->id)->Count, 1, "Still one");
+
+1;
diff --git a/rt/t/api/cf_transaction.t b/rt/t/api/cf_transaction.t
new file mode 100644
index 0000000..1ed2ab9
--- /dev/null
+++ b/rt/t/api/cf_transaction.t
@@ -0,0 +1,60 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+use Data::Dumper;
+
+use RT::Test tests => 14;
+use_ok('RT');
+use_ok('RT::Transactions');
+
+
+my $q = RT::Queue->new($RT::SystemUser);
+my ($id,$msg) = $q->Create( Name => 'TxnCFTest'.$$);
+ok($id,$msg);
+
+my $cf = RT::CustomField->new($RT::SystemUser);
+($id,$msg) = $cf->Create(Name => 'Txnfreeform-'.$$, Type => 'Freeform', MaxValues => '0', LookupType => RT::Transaction->CustomFieldLookupType );
+
+ok($id,$msg);
+
+($id,$msg) = $cf->AddToObject($q);
+
+ok($id,$msg);
+
+
+my $ticket = RT::Ticket->new($RT::SystemUser);
+
+my $transid;
+($id,$transid, $msg) = $ticket->Create(Queue => $q->id,
+ Subject => 'TxnCF test',
+ );
+ok($id,$msg);
+
+my $trans = RT::Transaction->new($RT::SystemUser);
+$trans->Load($transid);
+
+is($trans->ObjectId,$id);
+is ($trans->ObjectType, 'RT::Ticket');
+is ($trans->Type, 'Create');
+my $txncfs = $trans->CustomFields;
+is ($txncfs->Count, 1, "We have one custom field");
+my $txn_cf = $txncfs->First;
+is ($txn_cf->id, $cf->id, "It's the right custom field");
+my $values = $trans->CustomFieldValues($txn_cf->id);
+is ($values->Count, 0, "It has no values");
+
+# Old API
+my %cf_updates = ( 'CustomField-'.$cf->id => 'Testing');
+$trans->UpdateCustomFields( ARGSRef => \%cf_updates);
+
+ $values = $trans->CustomFieldValues($txn_cf->id);
+is ($values->Count, 1, "It has one value");
+
+# New API
+
+$trans->UpdateCustomFields( 'CustomField-'.$cf->id => 'Test two');
+ $values = $trans->CustomFieldValues($txn_cf->id);
+is ($values->Count, 2, "it has two values");
+
+# TODO ok(0, "Should updating custom field values remove old values?");
diff --git a/rt/t/api/condition-ownerchange.t b/rt/t/api/condition-ownerchange.t
new file mode 100644
index 0000000..4c4c49b
--- /dev/null
+++ b/rt/t/api/condition-ownerchange.t
@@ -0,0 +1,51 @@
+
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 11;
+
+
+{
+
+my $q = RT::Queue->new($RT::SystemUser);
+$q->Create(Name =>'ownerChangeTest');
+
+ok($q->Id, "Created a scriptest queue");
+
+my $s1 = RT::Scrip->new($RT::SystemUser);
+my ($val, $msg) =$s1->Create( Queue => $q->Id,
+ ScripAction => 'User Defined',
+ ScripCondition => 'On Owner Change',
+ CustomIsApplicableCode => '',
+ CustomPrepareCode => 'return 1',
+ CustomCommitCode => '
+ $self->TicketObj->SetPriority($self->TicketObj->Priority+1);
+ return(1);
+ ',
+ Template => 'Blank'
+ );
+ok($val,$msg);
+
+my $ticket = RT::Ticket->new($RT::SystemUser);
+my ($tv,$ttv,$tm) = $ticket->Create(Queue => $q->Id,
+ Subject => "hair on fire",
+ InitialPriority => '20'
+ );
+ok($tv, $tm);
+ok($ticket->SetOwner('root'));
+is ($ticket->Priority , '21', "Ticket priority is set right");
+ok($ticket->Steal);
+is ($ticket->Priority , '22', "Ticket priority is set right");
+ok($ticket->Untake);
+is ($ticket->Priority , '23', "Ticket priority is set right");
+ok($ticket->Take);
+is ($ticket->Priority , '24', "Ticket priority is set right");
+
+
+
+
+
+
+}
+
+1;
diff --git a/rt/t/api/condition-reject.t b/rt/t/api/condition-reject.t
new file mode 100644
index 0000000..9678950
--- /dev/null
+++ b/rt/t/api/condition-reject.t
@@ -0,0 +1,45 @@
+#
+# Check that the "On Reject" scrip condition exists and is working
+#
+
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 7;
+
+
+{
+
+my $q = RT::Queue->new($RT::SystemUser);
+$q->Create(Name =>'rejectTest');
+
+ok($q->Id, "Created a scriptest queue");
+
+my $s1 = RT::Scrip->new($RT::SystemUser);
+my ($val, $msg) =$s1->Create( Queue => $q->Id,
+ ScripAction => 'User Defined',
+ ScripCondition => 'On reject',
+ CustomIsApplicableCode => '',
+ CustomPrepareCode => 'return 1',
+ CustomCommitCode => '
+ $self->TicketObj->SetPriority($self->TicketObj->Priority+1);
+ return(1);
+ ',
+ Template => 'Blank'
+ );
+ok($val,$msg);
+
+my $ticket = RT::Ticket->new($RT::SystemUser);
+my ($tv,$ttv,$tm) = $ticket->Create(Queue => $q->Id,
+ Subject => "hair on fire",
+ InitialPriority => '20'
+ );
+ok($tv, $tm);
+ok($ticket->SetStatus('rejected'), "Status set to \"rejected\"");
+is ($ticket->Priority , '21', "Condition is true, scrip triggered");
+ok($ticket->SetStatus('open'), "Status set to \"open\"");
+is ($ticket->Priority , '21', "Condition is false, scrip skipped");
+
+}
+
+1;
diff --git a/rt/t/api/currentuser.t b/rt/t/api/currentuser.t
new file mode 100644
index 0000000..c158048
--- /dev/null
+++ b/rt/t/api/currentuser.t
@@ -0,0 +1,32 @@
+
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 8;
+
+
+{
+
+ok (require RT::CurrentUser);
+
+
+}
+
+{
+
+ok (my $cu = RT::CurrentUser->new('root'));
+ok (my $lh = $cu->LanguageHandle('en-us'));
+isnt ($lh, undef, '$lh is defined');
+ok ($lh->isa('Locale::Maketext'));
+is ($cu->loc('TEST_STRING'), "Concrete Mixer", "Localized TEST_STRING into English");
+SKIP: {
+ skip "French localization is not enabled", 2
+ unless grep $_ && $_ =~ /^(\*|fr)$/, RT->Config->Get('LexiconLanguages');
+ ok ($lh = $cu->LanguageHandle('fr'));
+ is ($cu->loc('before'), "avant", "Localized TEST_STRING into French");
+}
+
+
+}
+
+1;
diff --git a/rt/t/api/customfield.t b/rt/t/api/customfield.t
new file mode 100644
index 0000000..44319c4
--- /dev/null
+++ b/rt/t/api/customfield.t
@@ -0,0 +1,74 @@
+
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 29;
+use Test::Warn;
+
+
+{
+
+use_ok('RT::CustomField');
+ok(my $cf = RT::CustomField->new($RT::SystemUser));
+ok(my ($id, $msg)= $cf->Create( Name => 'TestingCF',
+ Queue => '0',
+ SortOrder => '1',
+ Description => 'A Testing custom field',
+ Type=> 'SelectSingle'), 'Created a global CustomField');
+isnt($id , 0, 'Global custom field correctly created');
+ok ($cf->SingleValue);
+is($cf->Type, 'Select');
+is($cf->MaxValues, 1);
+
+(my $val, $msg) = $cf->SetMaxValues('0');
+ok($val, $msg);
+is($cf->Type, 'Select');
+is($cf->MaxValues, 0);
+ok(!$cf->SingleValue );
+ok(my ($bogus_val, $bogus_msg) = $cf->SetType('BogusType') , "Trying to set a custom field's type to a bogus type");
+is($bogus_val , 0, "Unable to set a custom field's type to a bogus type");
+
+ok(my $bad_cf = RT::CustomField->new($RT::SystemUser));
+ok(my ($bad_id, $bad_msg)= $cf->Create( Name => 'TestingCF-bad',
+ Queue => '0',
+ SortOrder => '1',
+ Description => 'A Testing custom field with a bogus Type',
+ Type=> 'SelectSingleton'), 'Created a global CustomField with a bogus type');
+is($bad_id , 0, 'Global custom field correctly decided to not create a cf with a bogus type ');
+
+
+}
+
+{
+
+ok(my $cf = RT::CustomField->new($RT::SystemUser));
+$cf->Load(1);
+is($cf->Id , 1);
+ok(my ($val,$msg) = $cf->AddValue(Name => 'foo' , Description => 'TestCFValue', SortOrder => '6'));
+isnt($val , 0);
+ok (my ($delval, $delmsg) = $cf->DeleteValue($val));
+ok ($delval,"Deleting a cf value: $delmsg");
+
+
+}
+
+{
+
+ok(my $cf = RT::CustomField->new($RT::SystemUser));
+
+warning_like {
+ok($cf->ValidateType('SelectSingle'));
+} qr/deprecated/;
+
+warning_like {
+ok($cf->ValidateType('SelectMultiple'));
+} qr/deprecated/;
+
+warning_like {
+ok(!$cf->ValidateType('SelectFooMultiple'));
+} qr/deprecated/;
+
+
+}
+
+1;
diff --git a/rt/t/api/date.t b/rt/t/api/date.t
new file mode 100644
index 0000000..bc1446f
--- /dev/null
+++ b/rt/t/api/date.t
@@ -0,0 +1,564 @@
+#!/usr/bin/perl
+
+use Test::MockTime qw(set_fixed_time restore_time);
+
+use Test::More;
+my $tests;
+
+my $localized_datetime_tests;
+BEGIN {
+ $tests = 167;
+ $localized_datetime_tests =
+ eval { require DateTime; 1; } && eval { require DateTime::Locale; 1; } &&
+ DateTime->can('format_cldr') && DateTime::Locale::root->can('date_format_full');
+
+ if ($localized_datetime_tests) {
+
+ # Include RT::Date::LocalizedDateTime tests
+ $tests += 7;
+ }
+}
+
+use warnings; use strict;
+use RT::Test tests => $tests;
+use RT::User;
+use Test::Warn;
+
+use_ok('RT::Date');
+{
+ my $date = RT::Date->new($RT::SystemUser);
+ isa_ok($date, 'RT::Date', "constructor returned RT::Date oject");
+ $date = $date->new($RT::SystemUser);
+ isa_ok($date, 'RT::Date', "constructor returned RT::Date oject");
+}
+
+{
+ # set timezone in all places to UTC
+ $RT::SystemUser->UserObj->__Set(Field => 'Timezone', Value => 'UTC')
+ if $RT::SystemUser->UserObj->Timezone;
+ RT->Config->Set( Timezone => 'UTC' );
+}
+
+my $current_user;
+{
+ my $user = RT::User->new($RT::SystemUser);
+ my($uid, $msg) = $user->Create(
+ Name => "date_api". rand(200),
+ Lang => 'en',
+ Privileged => 1,
+ );
+ ok($uid, "user was created") or diag("error: $msg");
+ $current_user = RT::CurrentUser->new($user);
+}
+
+{
+ my $date = RT::Date->new( $current_user );
+ is($date->Timezone, 'UTC', "dropped all timzones to UTC");
+ is($date->Timezone('user'), 'UTC', "dropped all timzones to UTC");
+ is($date->Timezone('server'), 'UTC', "dropped all timzones to UTC");
+ is($date->Timezone('unknown'), 'UTC', "with wrong context returns UTC");
+
+ $current_user->UserObj->__Set( Field => 'Timezone', Value => 'Europe/Moscow');
+ is($current_user->UserObj->Timezone,
+ 'Europe/Moscow',
+ "successfuly changed user's timezone");
+ is($date->Timezone('user'),
+ 'Europe/Moscow',
+ "in user context returns user's timezone");
+ is($date->Timezone, 'UTC', "the deafult value is always UTC");
+ is($date->Timezone('server'), 'UTC', "wasn't changed");
+
+ RT->Config->Set( Timezone => 'Africa/Ouagadougou' );
+ is($date->Timezone('server'),
+ 'Africa/Ouagadougou',
+ "timezone of the RT server was changed");
+ is($date->Timezone('user'),
+ 'Europe/Moscow',
+ "in user context still returns user's timezone");
+ is($date->Timezone, 'UTC', "the deafult value is always UTC");
+
+ $current_user->UserObj->__Set( Field => 'Timezone', Value => '');
+ is_empty($current_user->UserObj->Timezone,
+ "successfuly changed user's timezone");
+ is($date->Timezone('user'),
+ 'Africa/Ouagadougou',
+ "in user context returns timezone of the server if user's one is not defined");
+ is($date->Timezone, 'UTC', "the deafult value is always UTC");
+
+ RT->Config->Set( Timezone => 'GMT' );
+ is($date->Timezone('server'),
+ 'UTC',
+ "timezone is GMT which one is alias for UTC");
+
+ RT->Config->Set( Timezone => '' );
+ is($date->Timezone, 'UTC', "dropped all timzones to UTC");
+ is($date->Timezone('user'),
+ 'UTC',
+ "user's and server's timzones are not defined, so UTC");
+ is($date->Timezone('server'),
+ 'UTC',
+ "timezone of the server is not defined so UTC");
+
+ RT->Config->Set( Timezone => 'UTC' );
+}
+
+{
+ my $date = RT::Date->new($RT::SystemUser);
+ is($date->Unix, 0, "new date returns 0 in Unix format");
+ is($date->Get, '1970-01-01 00:00:00', "default is ISO format");
+ is($date->Get(Format =>'SomeBadFormat'),
+ '1970-01-01 00:00:00',
+ "don't know format, return ISO format");
+ is($date->Get(Format =>'W3CDTF'),
+ '1970-01-01T00:00:00Z',
+ "W3CDTF format with defaults");
+ is($date->Get(Format =>'RFC2822'),
+ 'Thu, 1 Jan 1970 00:00:00 +0000',
+ "RFC2822 format with defaults");
+ is($date->Get(Format =>'LocalizedDateTime'),
+ 'Thu, Jan 1, 1970 12:00:00 AM',
+ "LocalizedDateTime format with defaults") if ( $localized_datetime_tests );
+
+ is($date->ISO(Time => 0),
+ '1970-01-01',
+ "ISO format without time part");
+ is($date->W3CDTF(Time => 0),
+ '1970-01-01',
+ "W3CDTF format without time part");
+ is($date->RFC2822(Time => 0),
+ 'Thu, 1 Jan 1970',
+ "RFC2822 format without time part");
+ is($date->LocalizedDateTime(Time => 0),
+ 'Thu, Jan 1, 1970',
+ "LocalizedDateTime format without time part") if ( $localized_datetime_tests );
+
+ is($date->ISO(Date => 0),
+ '00:00:00',
+ "ISO format without date part");
+ is($date->W3CDTF(Date => 0),
+ '1970-01-01T00:00:00Z',
+ "W3CDTF format is incorrect without date part");
+ is($date->RFC2822(Date => 0),
+ '00:00:00 +0000',
+ "RFC2822 format without date part");
+ is($date->LocalizedDateTime(Date => 0),
+ '12:00:00 AM',
+ "LocalizedDateTime format without date part") if ( $localized_datetime_tests );
+
+ is($date->ISO(Date => 0, Seconds => 0),
+ '00:00',
+ "ISO format without date part and seconds");
+ is($date->W3CDTF(Date => 0, Seconds => 0),
+ '1970-01-01T00:00Z',
+ "W3CDTF format without seconds, but we ship date part even if Date is false");
+ is($date->RFC2822(Date => 0, Seconds => 0),
+ '00:00 +0000',
+ "RFC2822 format without date part and seconds");
+
+ is($date->RFC2822(DayOfWeek => 0),
+ '1 Jan 1970 00:00:00 +0000',
+ "RFC2822 format without 'day of week' part");
+ is($date->RFC2822(DayOfWeek => 0, Date => 0),
+ '00:00:00 +0000',
+ "RFC2822 format without 'day of week' and date parts(corner case test)");
+
+ is($date->LocalizedDateTime(AbbrDay => 0),
+ 'Thursday, Jan 1, 1970 12:00:00 AM',
+ "LocalizedDateTime format without abbreviation of day") if ( $localized_datetime_tests );
+ is($date->LocalizedDateTime(AbbrMonth => 0),
+ 'Thu, January 1, 1970 12:00:00 AM',
+ "LocalizedDateTime format without abbreviation of month") if ( $localized_datetime_tests );
+ is($date->LocalizedDateTime(DateFormat => 'date_format_short'),
+ '1/1/70 12:00:00 AM',
+ "LocalizedDateTime format with non default DateFormat") if ( $localized_datetime_tests );
+ is($date->LocalizedDateTime(TimeFormat => 'time_format_short'),
+ 'Thu, Jan 1, 1970 12:00 AM',
+ "LocalizedDateTime format with non default TimeFormat") if ( $localized_datetime_tests );
+
+ is($date->Date,
+ '1970-01-01',
+ "the default format for the 'Date' method is ISO");
+ is($date->Date(Format => 'W3CDTF'),
+ '1970-01-01',
+ "'Date' method, W3CDTF format");
+ is($date->Date(Format => 'RFC2822'),
+ 'Thu, 1 Jan 1970',
+ "'Date' method, RFC2822 format");
+ is($date->Date(Time => 1),
+ '1970-01-01',
+ "'Date' method doesn't pass through 'Time' argument");
+ is($date->Date(Date => 0),
+ '1970-01-01',
+ "'Date' method overrides 'Date' argument");
+
+ is($date->Time,
+ '00:00:00',
+ "the default format for the 'Time' method is ISO");
+ is($date->Time(Format => 'W3CDTF'),
+ '1970-01-01T00:00:00Z',
+ "'Time' method, W3CDTF format, date part is required by w3c doc");
+ is($date->Time(Format => 'RFC2822'),
+ '00:00:00 +0000',
+ "'Time' method, RFC2822 format");
+ is($date->Time(Date => 1),
+ '00:00:00',
+ "'Time' method doesn't pass through 'Date' argument");
+ is($date->Time(Time => 0),
+ '00:00:00',
+ "'Time' method overrides 'Time' argument");
+
+ is($date->DateTime,
+ '1970-01-01 00:00:00',
+ "the default format for the 'DateTime' method is ISO");
+ is($date->DateTime(Format =>'W3CDTF'),
+ '1970-01-01T00:00:00Z',
+ "'DateTime' method, W3CDTF format");
+ is($date->DateTime(Format =>'RFC2822'),
+ 'Thu, 1 Jan 1970 00:00:00 +0000',
+ "'DateTime' method, RFC2822 format");
+ is($date->DateTime(Date => 0, Time => 0),
+ '1970-01-01 00:00:00',
+ "the 'DateTime' method overrides both 'Date' and 'Time' arguments");
+}
+
+
+{ # positive timezone
+ $current_user->UserObj->__Set( Field => 'Timezone', Value => 'Europe/Moscow');
+ my $date = RT::Date->new( $current_user );
+ $date->Set( Format => 'ISO', Timezone => 'utc', Value => '2005-01-01 15:10:00' );
+ is($date->ISO( Timezone => 'user' ), '2005-01-01 18:10:00', "ISO");
+ is($date->W3CDTF( Timezone => 'user' ), '2005-01-01T18:10:00+03:00', "W3C DTF");
+ is($date->RFC2822( Timezone => 'user' ), 'Sat, 1 Jan 2005 18:10:00 +0300', "RFC2822");
+
+ # DST
+ $date = RT::Date->new( $current_user );
+ $date->Set( Format => 'ISO', Timezone => 'utc', Value => '2005-07-01 15:10:00' );
+ is($date->ISO( Timezone => 'user' ), '2005-07-01 19:10:00', "ISO");
+ is($date->W3CDTF( Timezone => 'user' ), '2005-07-01T19:10:00+04:00', "W3C DTF");
+ is($date->RFC2822( Timezone => 'user' ), 'Fri, 1 Jul 2005 19:10:00 +0400', "RFC2822");
+}
+
+{ # negative timezone
+ $current_user->UserObj->__Set( Field => 'Timezone', Value => 'America/New_York');
+ my $date = RT::Date->new( $current_user );
+ $date->Set( Format => 'ISO', Timezone => 'utc', Value => '2005-01-01 15:10:00' );
+ is($date->ISO( Timezone => 'user' ), '2005-01-01 10:10:00', "ISO");
+ is($date->W3CDTF( Timezone => 'user' ), '2005-01-01T10:10:00-05:00', "W3C DTF");
+ is($date->RFC2822( Timezone => 'user' ), 'Sat, 1 Jan 2005 10:10:00 -0500', "RFC2822");
+
+ # DST
+ $date = RT::Date->new( $current_user );
+ $date->Set( Format => 'ISO', Timezone => 'utc', Value => '2005-07-01 15:10:00' );
+ is($date->ISO( Timezone => 'user' ), '2005-07-01 11:10:00', "ISO");
+ is($date->W3CDTF( Timezone => 'user' ), '2005-07-01T11:10:00-04:00', "W3C DTF");
+ is($date->RFC2822( Timezone => 'user' ), 'Fri, 1 Jul 2005 11:10:00 -0400', "RFC2822");
+}
+
+warning_like
+{ # bad format
+ my $date = RT::Date->new($RT::SystemUser);
+ $date->Set( Format => 'bad' );
+ is($date->Unix, 0, "bad format");
+} qr'Unknown Date format: bad';
+
+
+{ # setting value via Unix method
+ my $date = RT::Date->new($RT::SystemUser);
+ $date->Unix(1);
+ is($date->ISO, '1970-01-01 00:00:01', "correct value");
+
+ foreach (undef, 0, ''){
+ $date->Unix(1);
+ is($date->ISO, '1970-01-01 00:00:01', "correct value");
+
+ $date->Set(Format => 'unix', Value => $_);
+ is($date->ISO, '1970-01-01 00:00:00', "Set a date to midnight 1/1/1970 GMT due to wrong call");
+ is($date->Unix, 0, "unix is 0 => unset");
+ }
+}
+
+my $year = (localtime(time))[5] + 1900;
+
+{ # set+ISO format
+ my $date = RT::Date->new($RT::SystemUser);
+ warning_like {
+ $date->Set(Format => 'ISO', Value => 'weird date');
+ } qr/Couldn't parse date 'weird date' as a ISO format/;
+ is($date->Unix, 0, "date was wrong => unix == 0");
+
+ # XXX: ISO format has more feature than we suport
+ # http://www.cl.cam.ac.uk/~mgk25/iso-time.html
+
+ $date->Set(Format => 'ISO', Value => '2005-11-28 15:10:00');
+ is($date->ISO, '2005-11-28 15:10:00', "YYYY-DD-MM hh:mm:ss");
+
+ $date->Set(Format => 'ISO', Value => '2005-11-28 15:10:00+00');
+ is($date->ISO, '2005-11-28 15:10:00', "YYYY-DD-MM hh:mm:ss+00");
+
+ $date->Set(Format => 'ISO', Value => '11-28 15:10:00');
+ is($date->ISO, $year .'-11-28 15:10:00', "DD-MM hh:mm:ss");
+
+ $date->Set(Format => 'ISO', Value => '11-28 15:10:00+00');
+ is($date->ISO, $year .'-11-28 15:10:00', "DD-MM hh:mm:ss+00");
+
+ $date->Set(Format => 'ISO', Value => '20051128151000');
+ is($date->ISO, '2005-11-28 15:10:00', "YYYYDDMMhhmmss");
+
+ $date->Set(Format => 'ISO', Value => '1128151000');
+ is($date->ISO, $year .'-11-28 15:10:00', "DDMMhhmmss");
+
+ $date->Set(Format => 'ISO', Value => '2005112815:10:00');
+ is($date->ISO, '2005-11-28 15:10:00', "YYYYDDMMhh:mm:ss");
+
+ $date->Set(Format => 'ISO', Value => '112815:10:00');
+ is($date->ISO, $year .'-11-28 15:10:00', "DDMMhh:mm:ss");
+
+ $date->Set(Format => 'ISO', Value => '2005-13-28 15:10:00');
+ is($date->Unix, 0, "wrong month value");
+
+ $date->Set(Format => 'ISO', Value => '2005-00-28 15:10:00');
+ is($date->Unix, 0, "wrong month value");
+
+ $date->Set(Format => 'ISO', Value => '1960-01-28 15:10:00');
+ is($date->Unix, 0, "too old, we don't support");
+}
+
+{ # set+datemanip format(Time::ParseDate)
+ my $date = RT::Date->new($RT::SystemUser);
+ $date->Set(Format => 'unknown', Value => 'weird date');
+ is($date->Unix, 0, "date was wrong");
+
+ RT->Config->Set( Timezone => 'Europe/Moscow' );
+ $date->Set(Format => 'datemanip', Value => '2005-11-28 15:10:00');
+ is($date->ISO, '2005-11-28 12:10:00', "YYYY-DD-MM hh:mm:ss");
+
+ RT->Config->Set( Timezone => 'UTC' );
+ $date->Set(Format => 'datemanip', Value => '2005-11-28 15:10:00');
+ is($date->ISO, '2005-11-28 15:10:00', "YYYY-DD-MM hh:mm:ss");
+
+ $current_user->UserObj->__Set( Field => 'Timezone', Value => 'Europe/Moscow');
+ $date = RT::Date->new( $current_user );
+ $date->Set(Format => 'datemanip', Value => '2005-11-28 15:10:00');
+ is($date->ISO, '2005-11-28 12:10:00', "YYYY-DD-MM hh:mm:ss");
+}
+
+{ # set+unknown format(Time::ParseDate)
+ my $date = RT::Date->new($RT::SystemUser);
+ $date->Set(Format => 'unknown', Value => 'weird date');
+ is($date->Unix, 0, "date was wrong");
+
+ RT->Config->Set( Timezone => 'Europe/Moscow' );
+ $date->Set(Format => 'unknown', Value => '2005-11-28 15:10:00');
+ is($date->ISO, '2005-11-28 12:10:00', "YYYY-DD-MM hh:mm:ss");
+
+ $date->Set(Format => 'unknown', Value => '2005-11-28 15:10:00', Timezone => 'utc' );
+ is($date->ISO, '2005-11-28 15:10:00', "YYYY-DD-MM hh:mm:ss");
+
+ # test relative dates
+ {
+ set_fixed_time("2005-11-28T15:10:00Z");
+ $date->Set(Format => 'unknown', Value => 'now');
+ is($date->ISO, '2005-11-28 15:10:00', "YYYY-DD-MM hh:mm:ss");
+
+ $date->Set(Format => 'unknown', Value => '1 day ago');
+ is($date->ISO, '2005-11-27 15:10:00', "YYYY-DD-MM hh:mm:ss");
+ restore_time();
+ }
+
+ RT->Config->Set( Timezone => 'UTC' );
+ $date->Set(Format => 'unknown', Value => '2005-11-28 15:10:00');
+ is($date->ISO, '2005-11-28 15:10:00', "YYYY-DD-MM hh:mm:ss");
+
+ $current_user->UserObj->__Set( Field => 'Timezone', Value => 'Europe/Moscow');
+ $date = RT::Date->new( $current_user );
+ $date->Set(Format => 'unknown', Value => '2005-11-28 15:10:00');
+ is($date->ISO, '2005-11-28 12:10:00', "YYYY-DD-MM hh:mm:ss");
+ $date->Set(Format => 'unknown', Value => '2005-11-28 15:10:00', Timezone => 'server' );
+ is($date->ISO, '2005-11-28 15:10:00', "YYYY-DD-MM hh:mm:ss");
+ $date->Set(Format => 'unknown', Value => '2005-11-28 15:10:00', Timezone => 'utc' );
+ is($date->ISO, '2005-11-28 15:10:00', "YYYY-DD-MM hh:mm:ss");
+}
+
+{ # SetToMidnight
+ my $date = RT::Date->new($RT::SystemUser);
+
+ RT->Config->Set( Timezone => 'Europe/Moscow' );
+ $date->Set(Format => 'ISO', Value => '2005-11-28 15:10:00');
+ $date->SetToMidnight;
+ is($date->ISO, '2005-11-28 00:00:00', "default is utc");
+ $date->Set(Format => 'ISO', Value => '2005-11-28 15:10:00');
+ $date->SetToMidnight(Timezone => 'utc');
+ is($date->ISO, '2005-11-28 00:00:00', "utc context");
+ $date->Set(Format => 'ISO', Value => '2005-11-28 15:10:00');
+ $date->SetToMidnight(Timezone => 'user');
+ is($date->ISO, '2005-11-27 21:00:00', "user context, user has no preference, fallback to server");
+ $date->Set(Format => 'ISO', Value => '2005-11-28 15:10:00');
+ $date->SetToMidnight(Timezone => 'server');
+ is($date->ISO, '2005-11-27 21:00:00', "server context");
+
+ $current_user->UserObj->__Set( Field => 'Timezone', Value => 'Europe/Moscow');
+ $date = RT::Date->new( $current_user );
+ $date->Set(Format => 'ISO', Value => '2005-11-28 15:10:00');
+ $date->SetToMidnight;
+ is($date->ISO, '2005-11-28 00:00:00', "default is utc");
+ $date->Set(Format => 'ISO', Value => '2005-11-28 15:10:00');
+ $date->SetToMidnight(Timezone => 'utc');
+ is($date->ISO, '2005-11-28 00:00:00', "utc context");
+ $date->Set(Format => 'ISO', Value => '2005-11-28 15:10:00');
+ $date->SetToMidnight(Timezone => 'user');
+ is($date->ISO, '2005-11-27 21:00:00', "user context");
+ $date->SetToMidnight(Timezone => 'server');
+ is($date->ISO, '2005-11-27 21:00:00', "server context");
+
+ RT->Config->Set( Timezone => 'UTC' );
+}
+
+{ # SetToNow
+ my $date = RT::Date->new($RT::SystemUser);
+ my $time = time;
+ $date->SetToNow;
+ ok($date->Unix >= $time, 'close enough');
+ ok($date->Unix < $time+5, 'difference is less than five seconds');
+}
+
+{
+ my $date = RT::Date->new($RT::SystemUser);
+
+ $date->Unix(0);
+ $date->AddSeconds;
+ is($date->ISO, '1970-01-01 00:00:00', "nothing changed");
+ $date->AddSeconds(0);
+ is($date->ISO, '1970-01-01 00:00:00', "nothing changed");
+
+ $date->Unix(0);
+ $date->AddSeconds(5);
+ is($date->ISO, '1970-01-01 00:00:05', "added five seconds");
+ $date->AddSeconds(-2);
+ is($date->ISO, '1970-01-01 00:00:03', "substracted two seconds");
+
+ $date->Unix(0);
+ $date->AddSeconds(3661);
+ is($date->ISO, '1970-01-01 01:01:01', "added one hour, minute and a second");
+
+# XXX: TODO, doesn't work with Test::Warn
+# TODO: {
+# local $TODO = "BUG or subject to change Date handling to support unix time <= 0";
+# $date->Unix(0);
+# $date->AddSeconds(-2);
+# ok($date->Unix > 0);
+# }
+
+ $date->Unix(0);
+ $date->AddDay;
+ is($date->ISO, '1970-01-02 00:00:00', "added one day");
+ $date->AddDays(2);
+ is($date->ISO, '1970-01-04 00:00:00', "added two days");
+ $date->AddDays(-1);
+ is($date->ISO, '1970-01-03 00:00:00', "substructed one day");
+
+ $date->Unix(0);
+ $date->AddDays(31);
+ is($date->ISO, '1970-02-01 00:00:00', "added one month");
+}
+
+{
+ $current_user->UserObj->__Set( Field => 'Timezone', Value => '');
+ my $date = RT::Date->new( $current_user );
+ is($date->AsString, "Not set", "AsString returns 'Not set'");
+
+ RT->Config->Set( DateTimeFormat => '');
+ $date->Unix(1);
+ is($date->AsString, 'Thu Jan 01 00:00:01 1970', "correct string");
+ is($date->AsString(Date => 0), '00:00:01', "correct string");
+ is($date->AsString(Time => 0), 'Thu Jan 01 1970', "correct string");
+ is($date->AsString(Date => 0, Time => 0), 'Thu Jan 01 00:00:01 1970', "invalid input");
+
+ RT->Config->Set( DateTimeFormat => 'RFC2822' );
+ $date->Unix(1);
+ is($date->AsString, 'Thu, 1 Jan 1970 00:00:01 +0000', "correct string");
+
+ RT->Config->Set( DateTimeFormat => { Format => 'RFC2822', Seconds => 0 } );
+ $date->Unix(1);
+ is($date->AsString, 'Thu, 1 Jan 1970 00:00 +0000', "correct string");
+ is($date->AsString(Seconds => 1), 'Thu, 1 Jan 1970 00:00:01 +0000', "correct string");
+}
+
+{ # DurationAsString
+ my $date = RT::Date->new($RT::SystemUser);
+
+ is($date->DurationAsString(1), '1 sec', '1 sec');
+ is($date->DurationAsString(59), '59 sec', '59 sec');
+ is($date->DurationAsString(60), '1 min', '1 min');
+ is($date->DurationAsString(60*119), '119 min', '119 min');
+ is($date->DurationAsString(60*60*2-1), '120 min', '120 min');
+ is($date->DurationAsString(60*60*2), '2 hours', '2 hours');
+ is($date->DurationAsString(60*60*48-1), '48 hours', '48 hours');
+ is($date->DurationAsString(60*60*48), '2 days', '2 days');
+ is($date->DurationAsString(60*60*24*14-1), '14 days', '14 days');
+ is($date->DurationAsString(60*60*24*14), '2 weeks', '2 weeks');
+ is($date->DurationAsString(60*60*24*7*8-1), '8 weeks', '8 weeks');
+ is($date->DurationAsString(60*60*24*61), '2 months', '2 months');
+ is($date->DurationAsString(60*60*24*365-1), '12 months', '12 months');
+ is($date->DurationAsString(60*60*24*366), '1 years', '1 years');
+
+ is($date->DurationAsString(-1), '1 sec ago', '1 sec ago');
+}
+
+{ # DiffAsString
+ my $date = RT::Date->new($RT::SystemUser);
+ is($date->DiffAsString(1), '', 'no diff, wrong input');
+ is($date->DiffAsString(-1), '', 'no diff, wrong input');
+ is($date->DiffAsString('qwe'), '', 'no diff, wrong input');
+
+ $date->Unix(2);
+ is($date->DiffAsString(-1), '', 'no diff, wrong input');
+
+ is($date->DiffAsString(3), '1 sec ago', 'diff: 1 sec ago');
+ is($date->DiffAsString(1), '1 sec', 'diff: 1 sec');
+
+ my $ndate = RT::Date->new($RT::SystemUser);
+ is($date->DiffAsString($ndate), '', 'no diff, wrong input');
+ $ndate->Unix(3);
+ is($date->DiffAsString($ndate), '1 sec ago', 'diff: 1 sec ago');
+}
+
+{ # Diff
+ my $date = RT::Date->new($RT::SystemUser);
+ $date->SetToNow;
+ my $diff = $date->Diff;
+ ok($diff <= 0, 'close enought');
+ ok($diff > -5, 'close enought');
+}
+
+{ # AgeAsString
+ my $date = RT::Date->new($RT::SystemUser);
+ $date->SetToNow;
+ my $diff = $date->AgeAsString;
+ like($diff, qr/^(0 sec|[1-5] sec ago)$/, 'close enought');
+}
+
+{ # GetWeekday
+ my $date = RT::Date->new($RT::SystemUser);
+ is($date->GetWeekday(7), '', '7 and greater are invalid');
+ is($date->GetWeekday(6), 'Sat', '6 is Saturday');
+ is($date->GetWeekday(0), 'Sun', '0 is Sunday');
+ is($date->GetWeekday(-1), 'Sat', '-1 is Saturday');
+ is($date->GetWeekday(-7), 'Sun', '-7 is Sunday');
+ is($date->GetWeekday(-8), '', '-8 and lesser are invalid');
+}
+
+{ # GetMonth
+ my $date = RT::Date->new($RT::SystemUser);
+ is($date->GetMonth(12), '', '12 and greater are invalid');
+ is($date->GetMonth(11), 'Dec', '11 is December');
+ is($date->GetMonth(0), 'Jan', '0 is January');
+ is($date->GetMonth(-1), 'Dec', '11 is December');
+ is($date->GetMonth(-12), 'Jan', '0 is January');
+ is($date->GetMonth(-13), '', '-13 and lesser are invalid');
+}
+
+#TODO: AsString
+#TODO: RFC2822, W3CDTF with Timezones
+
+exit(0);
+
diff --git a/rt/t/api/emailparser.t b/rt/t/api/emailparser.t
new file mode 100644
index 0000000..940c26f
--- /dev/null
+++ b/rt/t/api/emailparser.t
@@ -0,0 +1,19 @@
+
+use strict;
+use warnings;
+
+use RT::Test tests => 4;
+
+RT->Config->Set( RTAddressRegexp => qr/^rt\@example.com$/i );
+
+
+ok(require RT::EmailParser);
+
+is(RT::EmailParser::IsRTAddress("","rt\@example.com"),1, "Regexp matched rt address" );
+is(RT::EmailParser::IsRTAddress("","frt\@example.com"),undef, "Regexp didn't match non-rt address" );
+
+my @before = ("rt\@example.com", "frt\@example.com");
+my @after = ("frt\@example.com");
+ok(eq_array(RT::EmailParser::CullRTAddresses("",@before),@after), "CullRTAddresses only culls RT addresses");
+
+1;
diff --git a/rt/t/api/group.t b/rt/t/api/group.t
new file mode 100644
index 0000000..551d4f1
--- /dev/null
+++ b/rt/t/api/group.t
@@ -0,0 +1,99 @@
+
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 38;
+
+
+{
+
+# {{{ Tests
+ok (require RT::Group);
+
+ok (my $group = RT::Group->new($RT::SystemUser), "instantiated a group object");
+ok (my ($id, $msg) = $group->CreateUserDefinedGroup( Name => 'TestGroup', Description => 'A test group',
+ ), 'Created a new group');
+isnt ($id , 0, "Group id is $id");
+is ($group->Name , 'TestGroup', "The group's name is 'TestGroup'");
+my $ng = RT::Group->new($RT::SystemUser);
+
+ok($ng->LoadUserDefinedGroup('TestGroup'), "Loaded testgroup");
+is($ng->id , $group->id, "Loaded the right group");
+
+
+ok (($id,$msg) = $ng->AddMember('1'), "Added a member to the group");
+ok($id, $msg);
+ok (($id,$msg) = $ng->AddMember('2' ), "Added a member to the group");
+ok($id, $msg);
+ok (($id,$msg) = $ng->AddMember('3' ), "Added a member to the group");
+ok($id, $msg);
+
+# Group 1 now has members 1, 2 ,3
+
+my $group_2 = RT::Group->new($RT::SystemUser);
+ok (my ($id_2, $msg_2) = $group_2->CreateUserDefinedGroup( Name => 'TestGroup2', Description => 'A second test group'), , 'Created a new group');
+isnt ($id_2 , 0, "Created group 2 ok- $msg_2 ");
+ok (($id,$msg) = $group_2->AddMember($ng->PrincipalId), "Made TestGroup a member of testgroup2");
+ok($id, $msg);
+ok (($id,$msg) = $group_2->AddMember('1' ), "Added member RT_System to the group TestGroup2");
+ok($id, $msg);
+
+# Group 2 how has 1, g1->{1, 2,3}
+
+my $group_3 = RT::Group->new($RT::SystemUser);
+ok (my ($id_3, $msg_3) = $group_3->CreateUserDefinedGroup( Name => 'TestGroup3', Description => 'A second test group'), 'Created a new group');
+isnt ($id_3 , 0, "Created group 3 ok - $msg_3");
+ok (($id,$msg) =$group_3->AddMember($group_2->PrincipalId), "Made TestGroup a member of testgroup2");
+ok($id, $msg);
+
+# g3 now has g2->{1, g1->{1,2,3}}
+
+my $principal_1 = RT::Principal->new($RT::SystemUser);
+$principal_1->Load('1');
+
+my $principal_2 = RT::Principal->new($RT::SystemUser);
+$principal_2->Load('2');
+
+ok (($id,$msg) = $group_3->AddMember('1' ), "Added member RT_System to the group TestGroup2");
+ok($id, $msg);
+
+# g3 now has 1, g2->{1, g1->{1,2,3}}
+
+is($group_3->HasMember($principal_2), undef, "group 3 doesn't have member 2");
+ok($group_3->HasMemberRecursively($principal_2), "group 3 has member 2 recursively");
+ok($ng->HasMember($principal_2) , "group ".$ng->Id." has member 2");
+my ($delid , $delmsg) =$ng->DeleteMember($principal_2->Id);
+isnt ($delid ,0, "Sucessfully deleted it-".$delid."-".$delmsg);
+
+#Gotta reload the group objects, since we've been messing with various internals.
+# we shouldn't need to do this.
+#$ng->LoadUserDefinedGroup('TestGroup');
+#$group_2->LoadUserDefinedGroup('TestGroup2');
+#$group_3->LoadUserDefinedGroup('TestGroup');
+
+# G1 now has 1, 3
+# Group 2 how has 1, g1->{1, 3}
+# g3 now has 1, g2->{1, g1->{1, 3}}
+
+ok(!$ng->HasMember($principal_2) , "group ".$ng->Id." no longer has member 2");
+is($group_3->HasMemberRecursively($principal_2), undef, "group 3 doesn't have member 2");
+is($group_2->HasMemberRecursively($principal_2), undef, "group 2 doesn't have member 2");
+is($ng->HasMember($principal_2), undef, "group 1 doesn't have member 2");
+is($group_3->HasMemberRecursively($principal_2), undef, "group 3 has member 2 recursively");
+
+# }}}
+
+
+}
+
+{
+
+ok(my $u = RT::Group->new($RT::SystemUser));
+ok($u->Load(4), "Loaded the first user");
+is($u->PrincipalObj->ObjectId , 4, "user 4 is the fourth principal");
+is($u->PrincipalObj->PrincipalType , 'Group' , "Principal 4 is a group");
+
+
+}
+
+1;
diff --git a/rt/t/api/groups.t b/rt/t/api/groups.t
new file mode 100644
index 0000000..995c844
--- /dev/null
+++ b/rt/t/api/groups.t
@@ -0,0 +1,139 @@
+
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 28;
+
+
+{
+
+ok (require RT::Groups);
+
+
+}
+
+{
+
+# next had bugs
+# Groups->Limit( FIELD => 'id', OPERATOR => '!=', VALUE => xx );
+my $g = RT::Group->new($RT::SystemUser);
+my ($id, $msg) = $g->CreateUserDefinedGroup(Name => 'GroupsNotEqualTest');
+ok ($id, "created group #". $g->id) or diag("error: $msg");
+
+my $groups = RT::Groups->new($RT::SystemUser);
+$groups->Limit( FIELD => 'id', OPERATOR => '!=', VALUE => $g->id );
+$groups->LimitToUserDefinedGroups();
+my $bug = grep $_->id == $g->id, @{$groups->ItemsArrayRef};
+ok (!$bug, "didn't find group");
+
+
+}
+
+{
+
+my $u = RT::User->new($RT::SystemUser);
+my ($id, $msg) = $u->Create( Name => 'Membertests'. $$ );
+ok ($id, 'created user') or diag "error: $msg";
+
+my $g = RT::Group->new($RT::SystemUser);
+($id, $msg) = $g->CreateUserDefinedGroup(Name => 'Membertests');
+ok ($id, $msg);
+
+my ($aid, $amsg) =$g->AddMember($u->id);
+ok ($aid, $amsg);
+ok($g->HasMember($u->PrincipalObj),"G has member u");
+
+my $groups = RT::Groups->new($RT::SystemUser);
+$groups->LimitToUserDefinedGroups();
+$groups->WithMember(PrincipalId => $u->id);
+is ($groups->Count , 1,"found the 1 group - " . $groups->Count);
+is ($groups->First->Id , $g->Id, "it's the right one");
+
+
+}
+
+{
+ no warnings qw/redefine once/;
+
+my $q = RT::Queue->new($RT::SystemUser);
+my ($id, $msg) =$q->Create( Name => 'GlobalACLTest');
+ok ($id, $msg);
+
+my $testuser = RT::User->new($RT::SystemUser);
+($id,$msg) = $testuser->Create(Name => 'JustAnAdminCc');
+ok ($id,$msg);
+
+my $global_admin_cc = RT::Group->new($RT::SystemUser);
+$global_admin_cc->LoadSystemRoleGroup('AdminCc');
+ok($global_admin_cc->id, "Found the global admincc group");
+my $groups = RT::Groups->new($RT::SystemUser);
+$groups->WithRight(Right => 'OwnTicket', Object => $q);
+is($groups->Count, 1);
+($id, $msg) = $global_admin_cc->PrincipalObj->GrantRight(Right =>'OwnTicket', Object=> $RT::System);
+ok ($id,$msg);
+ok (!$testuser->HasRight(Object => $q, Right => 'OwnTicket') , "The test user does not have the right to own tickets in the test queue");
+($id, $msg) = $q->AddWatcher(Type => 'AdminCc', PrincipalId => $testuser->id);
+ok($id,$msg);
+ok ($testuser->HasRight(Object => $q, Right => 'OwnTicket') , "The test user does have the right to own tickets now. thank god.");
+
+$groups = RT::Groups->new($RT::SystemUser);
+$groups->WithRight(Right => 'OwnTicket', Object => $q);
+ok ($id,$msg);
+is($groups->Count, 3);
+
+my $RTxGroup = RT::Group->new($RT::SystemUser);
+($id, $msg) = $RTxGroup->CreateUserDefinedGroup( Name => 'RTxGroup', Description => "RTx extension group");
+ok ($id,$msg);
+is ($RTxGroup->id, $id, "group loaded");
+
+my $RTxSysObj = {};
+bless $RTxSysObj, 'RTx::System';
+*RTx::System::Id = sub { 1; };
+*RTx::System::id = *RTx::System::Id;
+my $ace = RT::Record->new($RT::SystemUser);
+$ace->Table('ACL');
+$ace->_BuildTableAttributes unless ($RT::Record::_TABLE_ATTR->{ref($ace)});
+($id, $msg) = $ace->Create( PrincipalId => $RTxGroup->id, PrincipalType => 'Group', RightName => 'RTxGroupRight', ObjectType => 'RTx::System', ObjectId => 1);
+ok ($id, "ACL for RTxSysObj created");
+
+my $RTxObj = {};
+bless $RTxObj, 'RTx::System::Record';
+*RTx::System::Record::Id = sub { 4; };
+*RTx::System::Record::id = *RTx::System::Record::Id;
+
+$groups = RT::Groups->new($RT::SystemUser);
+$groups->WithRight(Right => 'RTxGroupRight', Object => $RTxSysObj);
+is($groups->Count, 1, "RTxGroupRight found for RTxSysObj");
+
+$groups = RT::Groups->new($RT::SystemUser);
+$groups->WithRight(Right => 'RTxGroupRight', Object => $RTxObj);
+is($groups->Count, 0, "RTxGroupRight not found for RTxObj");
+
+$groups = RT::Groups->new($RT::SystemUser);
+$groups->WithRight(Right => 'RTxGroupRight', Object => $RTxObj, EquivObjects => [ $RTxSysObj ]);
+is($groups->Count, 1, "RTxGroupRight found for RTxObj using EquivObjects");
+
+$ace = RT::Record->new($RT::SystemUser);
+$ace->Table('ACL');
+$ace->_BuildTableAttributes unless ($RT::Record::_TABLE_ATTR->{ref($ace)});
+($id, $msg) = $ace->Create( PrincipalId => $RTxGroup->id, PrincipalType => 'Group', RightName => 'RTxGroupRight', ObjectType => 'RTx::System::Record', ObjectId => 5 );
+ok ($id, "ACL for RTxObj created");
+
+my $RTxObj2 = {};
+bless $RTxObj2, 'RTx::System::Record';
+*RTx::System::Record::Id = sub { 5; };
+
+$groups = RT::Groups->new($RT::SystemUser);
+$groups->WithRight(Right => 'RTxGroupRight', Object => $RTxObj2);
+is($groups->Count, 1, "RTxGroupRight found for RTxObj2");
+
+$groups = RT::Groups->new($RT::SystemUser);
+$groups->WithRight(Right => 'RTxGroupRight', Object => $RTxObj2, EquivObjects => [ $RTxSysObj ]);
+is($groups->Count, 1, "RTxGroupRight found for RTxObj2");
+
+
+
+
+}
+
+1;
diff --git a/rt/t/api/i18n.t b/rt/t/api/i18n.t
new file mode 100644
index 0000000..17d71b7
--- /dev/null
+++ b/rt/t/api/i18n.t
@@ -0,0 +1,30 @@
+
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 9;
+
+
+{
+
+use_ok ('RT::I18N');
+ok(RT::I18N->Init);
+
+
+}
+
+{
+
+ok(my $chinese = RT::I18N->get_handle('zh_tw'));
+ok(UNIVERSAL::can($chinese, 'maketext'));
+like($chinese->maketext('__Content-Type') , qr/utf-8/i, "Found the utf-8 charset for traditional chinese in the string ".$chinese->maketext('__Content-Type'));
+is($chinese->encoding , 'utf-8', "The encoding is 'utf-8' -".$chinese->encoding);
+
+ok(my $en = RT::I18N->get_handle('en'));
+ok(UNIVERSAL::can($en, 'maketext'));
+is($en->encoding , 'utf-8', "The encoding ".$en->encoding." is 'utf-8'");
+
+
+}
+
+1;
diff --git a/rt/t/api/link.t b/rt/t/api/link.t
new file mode 100644
index 0000000..1fd66bb
--- /dev/null
+++ b/rt/t/api/link.t
@@ -0,0 +1,24 @@
+
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 5;
+
+
+{
+
+
+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'));
+
+
+}
+
+1;
diff --git a/rt/t/api/queue.t b/rt/t/api/queue.t
new file mode 100644
index 0000000..44d5caf
--- /dev/null
+++ b/rt/t/api/queue.t
@@ -0,0 +1,92 @@
+
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 24;
+
+
+{
+
+use RT::Queue;
+
+
+}
+
+{
+
+my $q = RT::Queue->new($RT::SystemUser);
+is($q->IsValidStatus('new'), 1, 'New is a valid status');
+is($q->IsValidStatus('f00'), 0, 'f00 is not a valid status');
+
+
+}
+
+{
+
+my $q = RT::Queue->new($RT::SystemUser);
+is($q->IsActiveStatus('new'), 1, 'New is a Active status');
+is($q->IsActiveStatus('rejected'), 0, 'Rejected is an inactive status');
+is($q->IsActiveStatus('f00'), 0, 'f00 is not a Active status');
+
+
+}
+
+{
+
+my $q = RT::Queue->new($RT::SystemUser);
+is($q->IsInactiveStatus('new'), 0, 'New is a Active status');
+is($q->IsInactiveStatus('rejected'), 1, 'rejeected is an Inactive status');
+is($q->IsInactiveStatus('f00'), 0, 'f00 is not a Active status');
+
+
+}
+
+{
+
+my $queue = RT::Queue->new($RT::SystemUser);
+my ($id, $val) = $queue->Create( Name => 'Test1');
+ok($id, $val);
+
+($id, $val) = $queue->Create( Name => '66');
+ok(!$id, $val);
+
+
+}
+
+{
+
+my $Queue = RT::Queue->new($RT::SystemUser);
+my ($id, $msg) = $Queue->Create(Name => "Foo");
+ok ($id, "Foo $id was created");
+ok(my $group = RT::Group->new($RT::SystemUser));
+ok($group->LoadQueueRoleGroup(Queue => $id, Type=> 'Requestor'));
+ok ($group->Id, "Found the requestors object for this Queue");
+
+{
+ my ($status, $msg) = $Queue->AddWatcher(Type => 'Cc', Email => 'bob@fsck.com');
+ ok ($status, "Added bob at fsck.com as a requestor") or diag "error: $msg";
+}
+
+ok(my $bob = RT::User->new($RT::SystemUser), "Creating a bob rt::user");
+$bob->LoadByEmail('bob@fsck.com');
+ok($bob->Id, "Found the bob rt user");
+ok ($Queue->IsWatcher(Type => 'Cc', PrincipalId => $bob->PrincipalId), "The Queue actually has bob at fsck.com as a requestor");
+
+{
+ my ($status, $msg) = $Queue->DeleteWatcher(Type =>'Cc', Email => 'bob@fsck.com');
+ ok ($status, "Deleted bob from Ccs") or diag "error: $msg";
+ ok (!$Queue->IsWatcher(Type => 'Cc', PrincipalId => $bob->PrincipalId),
+ "The Queue no longer has bob at fsck.com as a requestor");
+}
+
+$group = RT::Group->new($RT::SystemUser);
+ok($group->LoadQueueRoleGroup(Queue => $id, Type=> 'Cc'));
+ok ($group->Id, "Found the cc object for this Queue");
+$group = RT::Group->new($RT::SystemUser);
+ok($group->LoadQueueRoleGroup(Queue => $id, Type=> 'AdminCc'));
+ok ($group->Id, "Found the AdminCc object for this Queue");
+
+
+}
+
+1;
diff --git a/rt/t/api/record.t b/rt/t/api/record.t
new file mode 100644
index 0000000..6bf1af8
--- /dev/null
+++ b/rt/t/api/record.t
@@ -0,0 +1,70 @@
+
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 22;
+
+
+{
+
+ok (require RT::Record);
+
+
+}
+
+{
+
+my $ticket = RT::Ticket->new($RT::SystemUser);
+my $group = RT::Group->new($RT::SystemUser);
+is($ticket->ObjectTypeStr, 'Ticket', "Ticket returns correct typestring");
+is($group->ObjectTypeStr, 'Group', "Group returns correct typestring");
+
+
+}
+
+{
+
+my $t1 = RT::Ticket->new($RT::SystemUser);
+my ($id, $trans, $msg) = $t1->Create(Subject => 'DepTest1', Queue => 'general');
+ok($id, "Created dep test 1 - $msg");
+
+my $t2 = RT::Ticket->new($RT::SystemUser);
+(my $id2, $trans, my $msg2) = $t2->Create(Subject => 'DepTest2', Queue => 'general');
+ok($id2, "Created dep test 2 - $msg2");
+my $t3 = RT::Ticket->new($RT::SystemUser);
+(my $id3, $trans, my $msg3) = $t3->Create(Subject => 'DepTest3', Queue => 'general', Type => 'approval');
+ok($id3, "Created dep test 3 - $msg3");
+my ($addid, $addmsg);
+ok (($addid, $addmsg) =$t1->AddLink( Type => 'DependsOn', Target => $t2->id));
+ok ($addid, $addmsg);
+ok (($addid, $addmsg) =$t1->AddLink( Type => 'DependsOn', Target => $t3->id));
+
+ok ($addid, $addmsg);
+my $link = RT::Link->new($RT::SystemUser);
+(my $rv, $msg) = $link->Load($addid);
+ok ($rv, $msg);
+is ($link->LocalTarget , $t3->id, "Link LocalTarget is correct");
+is ($link->LocalBase , $t1->id, "Link LocalBase is correct");
+
+ok ($t1->HasUnresolvedDependencies, "Ticket ".$t1->Id." has unresolved deps");
+ok (!$t1->HasUnresolvedDependencies( Type => 'blah' ), "Ticket ".$t1->Id." has no unresolved blahs");
+ok ($t1->HasUnresolvedDependencies( Type => 'approval' ), "Ticket ".$t1->Id." has unresolved approvals");
+ok (!$t2->HasUnresolvedDependencies, "Ticket ".$t2->Id." has no unresolved deps");
+;
+
+my ($rid, $rmsg)= $t1->Resolve();
+ok(!$rid, $rmsg);
+my ($rid2, $rmsg2) = $t2->Resolve();
+ok ($rid2, $rmsg2);
+($rid, $rmsg)= $t1->Resolve();
+ok(!$rid, $rmsg);
+my ($rid3,$rmsg3) = $t3->Resolve;
+ok ($rid3,$rmsg3);
+($rid, $rmsg)= $t1->Resolve();
+ok($rid, $rmsg);
+
+
+
+}
+
+1;
diff --git a/rt/t/api/reminders.t b/rt/t/api/reminders.t
new file mode 100644
index 0000000..fd1c6a6
--- /dev/null
+++ b/rt/t/api/reminders.t
@@ -0,0 +1,88 @@
+
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 20;
+
+
+{
+
+# Create test queues
+use_ok ('RT::Queue');
+
+ok(my $testqueue = RT::Queue->new($RT::SystemUser), 'Instantiate RT::Queue');
+ok($testqueue->Create( Name => 'reminders tests'), 'Create new queue: reminders tests');
+isnt($testqueue->Id , 0, 'Success creating queue');
+
+ok($testqueue->Create( Name => 'reminders tests 2'), 'Create new queue: reminders tests 2');
+isnt($testqueue->Id , 0, 'Success creating queue');
+
+# Create test ticket
+use_ok('RT::Ticket');
+
+my $u = RT::User->new($RT::SystemUser);
+$u->Load("root");
+ok ($u->Id, "Found the root user");
+ok(my $t = RT::Ticket->new($RT::SystemUser), 'Instantiate RT::Ticket');
+ok(my ($id, $msg) = $t->Create( Queue => $testqueue->Id,
+ Subject => 'Testing',
+ Owner => $u->Id
+ ), 'Create sample ticket');
+isnt($id , 0, 'Success creating ticket');
+
+# Add reminder
+my $due_obj = RT::Date->new( $RT::SystemUser );
+$due_obj->SetToNow;
+ok(my ( $add_id, $add_msg, $txnid ) = $t->Reminders->Add(
+ Subject => 'TestReminder',
+ Owner => 'root',
+ Due => $due_obj->ISO
+ ), 'Add reminder');
+
+# Check that the new Reminder is here
+my $reminders = $t->Reminders->Collection;
+ok($reminders, 'Loading reminders for this ticket');
+my $found = 0;
+while ( my $reminder = $reminders->Next ) {
+ next unless $found == 0;
+ $found = 1 if ( $reminder->Subject =~ m/TestReminder/ );
+}
+
+is($found, 1, 'Reminder successfully added');
+
+# Change queue
+ok (my ($move_val, $move_msg) = $t->SetQueue('reminders tests 2'), 'Moving ticket from queue "reminders tests" to "reminders tests 2"');
+
+is ($t->QueueObj->Name, 'reminders tests 2', 'Ticket successfully moved');
+
+# Check that the new reminder is still there and moved to the new queue
+$reminders = $t->Reminders->Collection;
+ok($reminders, 'Loading reminders for this ticket');
+$found = 0;
+my $ok_queue = 0;
+while ( my $reminder = $reminders->Next ) {
+ next unless $found == 0;
+ if ( $reminder->Subject =~ m/TestReminder/ ) {
+ $found = 1;
+ $ok_queue = 1 if ( $reminder->QueueObj->Name eq 'reminders tests 2' );
+ }
+}
+is($found, 1, 'Reminder successfully added');
+
+is($ok_queue, 1, 'Reminder automatically moved to new queue');
+
+# Resolve reminder
+my $r_resolved = 0;
+while ( my $reminder = $reminders->Next ) {
+ if ( $reminder->Subject =~ m/TestReminder/ ) {
+ if ( $reminder->Status ne 'resolved' ) {
+ $t->Reminders->Resolve($reminder);
+ $r_resolved = 1 if ( $reminder->Status eq 'resolved' );
+ }
+ }
+}
+
+is($r_resolved, 1, 'Reminder resolved');
+
+}
+1;
diff --git a/rt/t/api/rights.t b/rt/t/api/rights.t
new file mode 100644
index 0000000..a38bcea
--- /dev/null
+++ b/rt/t/api/rights.t
@@ -0,0 +1,197 @@
+#!/usr/bin/perl -w
+# BEGIN BPS TAGGED BLOCK {{{
+#
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2007 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 }}}
+
+use RT::Test tests => 30;
+
+use strict;
+use warnings;
+
+# clear all global right
+{
+ my $acl = RT::ACL->new($RT::SystemUser);
+ $acl->Limit( FIELD => 'RightName', OPERATOR => '!=', VALUE => 'SuperUser' );
+ $acl->LimitToObject( $RT::System );
+ while( my $ace = $acl->Next ) {
+ $ace->Delete;
+ }
+}
+
+my $queue = RT::Test->load_or_create_queue( Name => 'Regression' );
+ok $queue && $queue->id, 'loaded or created queue';
+my $qname = $queue->Name;
+
+my $user = RT::Test->load_or_create_user(
+ Name => 'user', Password => 'password',
+);
+ok $user && $user->id, 'loaded or created user';
+
+{
+ ok( !$user->HasRight( Right => 'OwnTicket', Object => $queue ),
+ "user can't own ticket"
+ );
+ ok( !$user->HasRight( Right => 'ReplyToTicket', Object => $queue ),
+ "user can't reply to ticket"
+ );
+}
+
+{
+ my $group = RT::Group->new( $RT::SystemUser );
+ ok( $group->LoadQueueRoleGroup( Queue => $queue->id, Type=> 'Owner' ),
+ "load queue owners role group"
+ );
+ my $ace = RT::ACE->new( $RT::SystemUser );
+ my ($ace_id, $msg) = $group->PrincipalObj->GrantRight(
+ Right => 'ReplyToTicket', Object => $queue
+ );
+ ok( $ace_id, "Granted queue owners role group with ReplyToTicket right: $msg" );
+ ok( $group->PrincipalObj->HasRight( Right => 'ReplyToTicket', Object => $queue ),
+ "role group can reply to ticket"
+ );
+ ok( !$user->HasRight( Right => 'ReplyToTicket', Object => $queue ),
+ "user can't reply to ticket"
+ );
+}
+
+my $ticket;
+{
+ # new ticket
+ $ticket = RT::Ticket->new($RT::SystemUser);
+ my ($ticket_id) = $ticket->Create( Queue => $queue->id, Subject => 'test');
+ ok( $ticket_id, 'new ticket created' );
+ is( $ticket->Owner, $RT::Nobody->Id, 'owner of the new ticket is nobody' );
+
+ ok( !$user->HasRight( Right => 'OwnTicket', Object => $ticket ),
+ "user can't reply to ticket"
+ );
+ my ($status, $msg) = $ticket->SetOwner( $user->id );
+ ok( !$status, "no permissions to be an owner" );
+}
+
+{
+ my ($status, $msg) = $user->PrincipalObj->GrantRight(
+ Object => $queue, Right => 'OwnTicket'
+ );
+ ok( $status, "successfuly granted right: $msg" );
+ ok( $user->HasRight( Right => 'OwnTicket', Object => $queue ),
+ "user can own ticket"
+ );
+ ok( $user->HasRight( Right => 'OwnTicket', Object => $ticket ),
+ "user can own ticket"
+ );
+
+ ($status, $msg) = $ticket->SetOwner( $user->id );
+ ok( $status, "successfuly set owner: $msg" );
+ is( $ticket->Owner, $user->id, "set correct owner" );
+
+ ok( $user->HasRight( Right => 'ReplyToTicket', Object => $ticket ),
+ "user is owner and can reply to ticket"
+ );
+}
+
+{
+ # Testing of EquivObjects
+ my $group = RT::Group->new( $RT::SystemUser );
+ ok( $group->LoadQueueRoleGroup( Queue => $queue->id, Type=> 'AdminCc' ),
+ "load queue AdminCc role group"
+ );
+ my $ace = RT::ACE->new( $RT::SystemUser );
+ my ($ace_id, $msg) = $group->PrincipalObj->GrantRight(
+ Right => 'ModifyTicket', Object => $queue
+ );
+ ok( $ace_id, "Granted queue AdminCc role group with ModifyTicket right: $msg" );
+ ok( $group->PrincipalObj->HasRight( Right => 'ModifyTicket', Object => $queue ),
+ "role group can modify ticket"
+ );
+ ok( !$user->HasRight( Right => 'ModifyTicket', Object => $ticket ),
+ "user is not AdminCc and can't modify ticket"
+ );
+}
+
+{
+ my ($status, $msg) = $ticket->AddWatcher(
+ Type => 'AdminCc', PrincipalId => $user->PrincipalId
+ );
+ ok( $status, "successfuly added user as AdminCc");
+ ok( $user->HasRight( Right => 'ModifyTicket', Object => $ticket ),
+ "user is AdminCc and can modify ticket"
+ );
+}
+
+my $ticket2;
+{
+ $ticket2 = RT::Ticket->new($RT::SystemUser);
+ my ($id) = $ticket2->Create( Queue => $queue->id, Subject => 'test2');
+ ok( $id, 'new ticket created' );
+ ok( !$user->HasRight( Right => 'ModifyTicket', Object => $ticket2 ),
+ "user is not AdminCc and can't modify ticket2"
+ );
+
+ # now we can finally test EquivObjectsa
+ my $has = $user->HasRight(
+ Right => 'ModifyTicket',
+ Object => $ticket2,
+ EquivObjects => [$ticket],
+ );
+ ok( $has, "user is not AdminCc but can modify ticket2 because of EquivObjects" );
+}
+
+{
+ # the first a third test below are the same, so they should both pass
+ # make sure passed equive list is not changed
+ my @list = ();
+ ok( !$user->HasRight( Right => 'ModifyTicket', Object => $ticket2, EquivObjects => \@list ),
+ "user is not AdminCc and can't modify ticket2"
+ );
+ ok( $user->HasRight( Right => 'ModifyTicket', Object => $ticket, EquivObjects => \@list ),
+ "user is AdminCc and can modify ticket"
+ );
+ ok( !$user->HasRight( Right => 'ModifyTicket', Object => $ticket2, EquivObjects => \@list ),
+ "user is not AdminCc and can't modify ticket2 (same question different answer)"
+ );
+}
diff --git a/rt/t/api/rights_show_ticket.t b/rt/t/api/rights_show_ticket.t
new file mode 100644
index 0000000..3e1d074
--- /dev/null
+++ b/rt/t/api/rights_show_ticket.t
@@ -0,0 +1,262 @@
+#!/usr/bin/perl -w
+
+use RT::Test tests => 264;
+
+use strict;
+use warnings;
+
+
+my $queue_a = RT::Test->load_or_create_queue( Name => 'A' );
+ok $queue_a && $queue_a->id, 'loaded or created queue_a';
+my $qa_id = $queue_a->id;
+
+my $queue_b = RT::Test->load_or_create_queue( Name => 'B' );
+ok $queue_b && $queue_b->id, 'loaded or created queue_b';
+my $qb_id = $queue_b->id;
+
+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';
+
+foreach my $option (0 .. 1 ) { RT->Config->Set( 'UseSQLForACLChecks' => $option );
+
+diag "Testing with UseSQLForACLChecks => $option";
+
+# Global Cc has right, a User is nobody
+{
+ cleanup();
+ RT::Test->set_rights(
+ { Principal => 'Everyone', Right => [qw(SeeQueue)] },
+ { Principal => 'Cc', Right => [qw(ShowTicket)] },
+ );
+ create_tickets_set();
+ have_no_rights($user_a, $user_b);
+}
+
+# Global Cc has right, a User is Queue Cc
+{
+ cleanup();
+ RT::Test->set_rights(
+ { Principal => 'Everyone', Right => [qw(SeeQueue)] },
+ { Principal => 'Cc', Right => [qw(ShowTicket)] },
+ );
+ create_tickets_set();
+ have_no_rights($user_a, $user_b);
+
+ my ($status, $msg) = $queue_a->AddWatcher( Type => 'Cc', PrincipalId => $user_a->id );
+ ok($status, "user A is now queue A watcher");
+
+ foreach my $q (
+ '',
+ "Queue = $qa_id OR Queue = $qb_id",
+ "Queue = $qb_id OR Queue = $qa_id",
+ ) {
+ my $tickets = RT::Tickets->new( RT::CurrentUser->new( $user_a ) );
+ $q? $tickets->FromSQL($q) : $tickets->UnLimit;
+ my $found = 0;
+ while ( my $t = $tickets->Next ) {
+ $found++;
+ is( $t->Queue, $queue_a->id, "user sees tickets only in queue A" );
+ }
+ is($found, 2, "user sees tickets");
+ }
+ have_no_rights( $user_b );
+}
+
+# global Cc has right, a User is ticket Cc
+{
+ cleanup();
+ RT::Test->set_rights(
+ { Principal => 'Everyone', Right => [qw(SeeQueue)] },
+ { Principal => 'Cc', Right => [qw(ShowTicket)] },
+ );
+ my @tickets = create_tickets_set();
+ have_no_rights($user_a, $user_b);
+
+ my ($status, $msg) = $tickets[1]->AddWatcher( Type => 'Cc', PrincipalId => $user_a->id );
+ ok($status, "user A is now queue A watcher");
+
+ foreach my $q (
+ '',
+ "Queue = $qa_id OR Queue = $qb_id",
+ "Queue = $qb_id OR Queue = $qa_id",
+ ) {
+ my $tickets = RT::Tickets->new( RT::CurrentUser->new( $user_a ) );
+ $q? $tickets->FromSQL($q) : $tickets->UnLimit;
+ my $found = 0;
+ while ( my $t = $tickets->Next ) {
+ $found++;
+ is( $t->Queue, $queue_a->id, "user sees tickets only in queue A" );
+ is( $t->id, $tickets[1]->id, "correct ticket");
+ }
+ is($found, 1, "user sees tickets");
+ }
+ have_no_rights($user_b);
+}
+
+# Queue Cc has right, a User is nobody
+{
+ cleanup();
+ RT::Test->set_rights(
+ { Principal => 'Everyone', Right => [qw(SeeQueue)] },
+ { Principal => 'Cc', Object => $queue_a, Right => [qw(ShowTicket)] },
+ );
+ create_tickets_set();
+ have_no_rights($user_a, $user_b);
+}
+
+# Queue Cc has right, Users are Queue Ccs
+{
+ cleanup();
+ RT::Test->set_rights(
+ { Principal => 'Everyone', Right => [qw(SeeQueue)] },
+ { Principal => 'Cc', Object => $queue_a, Right => [qw(ShowTicket)] },
+ );
+ create_tickets_set();
+ have_no_rights($user_a, $user_b);
+
+ my ($status, $msg) = $queue_a->AddWatcher( Type => 'Cc', PrincipalId => $user_a->id );
+ ok($status, "user A is now queue A watcher");
+
+ ($status, $msg) = $queue_b->AddWatcher( Type => 'Cc', PrincipalId => $user_b->id );
+ ok($status, "user B is now queue B watcher");
+
+ foreach my $q (
+ '',
+ "Queue = $qa_id OR Queue = $qb_id",
+ "Queue = $qb_id OR Queue = $qa_id",
+ ) {
+ my $tickets = RT::Tickets->new( RT::CurrentUser->new( $user_a ) );
+ $q? $tickets->FromSQL($q) : $tickets->UnLimit;
+ my $found = 0;
+ while ( my $t = $tickets->Next ) {
+ $found++;
+ is( $t->Queue, $queue_a->id, "user sees tickets only in queue A" );
+ }
+ is($found, 2, "user sees tickets");
+ }
+ have_no_rights( $user_b );
+}
+
+# Queue Cc has right, Users are ticket Ccs
+{
+ cleanup();
+ RT::Test->set_rights(
+ { Principal => 'Everyone', Right => [qw(SeeQueue)] },
+ { Principal => 'Cc', Object => $queue_a, Right => [qw(ShowTicket)] },
+ );
+ my @tickets = create_tickets_set();
+ have_no_rights($user_a, $user_b);
+
+ my ($status, $msg) = $tickets[1]->AddWatcher( Type => 'Cc', PrincipalId => $user_a->id );
+ ok($status, "user A is now Cc on a ticket in queue A");
+
+ ($status, $msg) = $tickets[2]->AddWatcher( Type => 'Cc', PrincipalId => $user_b->id );
+ ok($status, "user B is now Cc on a ticket in queue B");
+
+ foreach my $q (
+ '',
+ "Queue = $qa_id OR Queue = $qb_id",
+ "Queue = $qb_id OR Queue = $qa_id",
+ ) {
+ my $tickets = RT::Tickets->new( RT::CurrentUser->new( $user_a ) );
+ $q? $tickets->FromSQL($q) : $tickets->UnLimit;
+ my $found = 0;
+ while ( my $t = $tickets->Next ) {
+ $found++;
+ is( $t->Queue, $queue_a->id, "user sees tickets only in queue A" );
+ is( $t->id, $tickets[1]->id, )
+ }
+ is($found, 1, "user sees tickets");
+ }
+ have_no_rights( $user_b );
+}
+
+# Users has direct right on queue
+{
+ cleanup();
+ RT::Test->set_rights(
+ { Principal => 'Everyone', Right => [qw(SeeQueue)] },
+ { Principal => $user_a, Object => $queue_a, Right => [qw(ShowTicket)] },
+ );
+ my @tickets = create_tickets_set();
+
+ foreach my $q (
+ '',
+ "Queue = $qa_id OR Queue = $qb_id",
+ "Queue = $qb_id OR Queue = $qa_id",
+ ) {
+ my $tickets = RT::Tickets->new( RT::CurrentUser->new( $user_a ) );
+ $q? $tickets->FromSQL($q) : $tickets->UnLimit;
+ my $found = 0;
+ while ( my $t = $tickets->Next ) {
+ $found++;
+ is( $t->Queue, $queue_a->id, "user sees tickets only in queue A" );
+ }
+ is($found, 2, "user sees tickets");
+ }
+ have_no_rights( $user_b );
+}
+
+
+}
+
+sub have_no_rights {
+ $SIG{'INT'} = $SIG{'TERM'} = sub { print STDERR Carp::longmess('boo'); exit 1 };
+ local $Test::Builder::Level = $Test::Builder::Level + 1;
+ foreach my $u ( @_ ) {
+ foreach my $q (
+ '',
+ "Queue = $qa_id OR Queue = $qb_id",
+ "Queue = $qb_id OR Queue = $qa_id",
+ ) {
+ my $tickets = RT::Tickets->new( RT::CurrentUser->new( $u ) );
+ $q? $tickets->FromSQL($q) : $tickets->UnLimit;
+ ok(!$tickets->First, "no tickets");
+ }
+ }
+}
+
+sub create_tickets_set{
+ local $Test::Builder::Level = $Test::Builder::Level + 1;
+ my @res;
+ foreach my $q ($queue_a, $queue_b) {
+ foreach my $n (1 .. 2) {
+ my $ticket = RT::Ticket->new( $RT::SystemUser );
+ my ($tid) = $ticket->Create(
+ Queue => $q->id, Subject => $q->Name .' - '. $n
+ );
+ ok( $tid, "created ticket #$tid");
+ push @res, $ticket;
+ }
+ }
+ return @res;
+}
+
+sub cleanup { delete_tickets(); delete_watchers() };
+
+sub delete_tickets {
+ my $tickets = RT::Tickets->new( $RT::SystemUser );
+ $tickets->FromSQL( "Queue = $qa_id OR Queue = $qb_id" );
+ while ( my $ticket = $tickets->Next ) {
+ $ticket->Delete;
+ }
+}
+
+sub delete_watchers {
+ foreach my $q ($queue_a, $queue_b) {
+ foreach my $u ($user_a, $user_b) {
+ foreach my $t (qw(Cc AdminCc) ) {
+ $q->DeleteWatcher( Type => $t, PrincipalId => $u->id )
+ if $q->IsWatcher( Type => $t, PrincipalId => $u->id );
+ }
+ }
+ }
+}
+
diff --git a/rt/t/api/rt.t b/rt/t/api/rt.t
new file mode 100644
index 0000000..3c06b58
--- /dev/null
+++ b/rt/t/api/rt.t
@@ -0,0 +1,18 @@
+
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 4;
+
+
+{
+
+is ($RT::Nobody->Name() , 'Nobody', "Nobody is nobody");
+isnt ($RT::Nobody->Name() , 'root', "Nobody isn't named root");
+is ($RT::SystemUser->Name() , 'RT_System', "The system user is RT_System");
+isnt ($RT::SystemUser->Name() , 'noname', "The system user isn't noname");
+
+
+}
+
+1;
diff --git a/rt/t/api/scrip.t b/rt/t/api/scrip.t
new file mode 100644
index 0000000..8e8f962
--- /dev/null
+++ b/rt/t/api/scrip.t
@@ -0,0 +1,49 @@
+
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 7;
+
+
+{
+
+ok (require RT::Scrip);
+
+
+my $q = RT::Queue->new($RT::SystemUser);
+$q->Create(Name => 'ScripTest');
+ok($q->Id, "Created a scriptest queue");
+
+my $s1 = RT::Scrip->new($RT::SystemUser);
+my ($val, $msg) =$s1->Create( Queue => $q->Id,
+ ScripAction => 'User Defined',
+ ScripCondition => 'User Defined',
+ CustomIsApplicableCode => 'if ($self->TicketObj->Subject =~ /fire/) { return (1);} else { return(0)}',
+ CustomPrepareCode => 'return 1',
+ CustomCommitCode => '$self->TicketObj->SetPriority("87");',
+ Template => 'Blank'
+ );
+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);
+
+is ($ticket->Priority , '87', "Ticket priority is set right");
+
+
+my $ticket2 = RT::Ticket->new($RT::SystemUser);
+my ($t2v,$t2tv,$t2m) = $ticket2->Create(Queue => $q->Id,
+ Subject => "hair in water",
+ );
+ok($t2v, $t2m);
+
+isnt ($ticket2->Priority , '87', "Ticket priority is set right");
+
+
+
+}
+
+1;
diff --git a/rt/t/api/scrip_order.t b/rt/t/api/scrip_order.t
new file mode 100644
index 0000000..9738db9
--- /dev/null
+++ b/rt/t/api/scrip_order.t
@@ -0,0 +1,56 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+use RT;
+use RT::Test tests => 7;
+
+
+# {{{ test scrip ordering based on description
+
+my $scrip_queue = RT::Queue->new($RT::SystemUser);
+my ($queue_id, $msg) = $scrip_queue->Create( Name => "ScripOrdering-$$",
+ Description => 'Test scrip ordering by description' );
+ok($queue_id, "Created scrip-ordering test queue? ".$msg);
+
+my $priority_ten_scrip = RT::Scrip->new($RT::SystemUser);
+(my $id, $msg) = $priority_ten_scrip->Create(
+ Description => "10 set priority $$",
+ Queue => $queue_id,
+ ScripCondition => 'On Create',
+ ScripAction => 'User Defined',
+ CustomPrepareCode => '$RT::Logger->debug("Setting priority to 10..."); return 1;',
+ CustomCommitCode => '$self->TicketObj->SetPriority(10);',
+ Template => 'Blank',
+ Stage => 'TransactionCreate',
+);
+ok($id, "Created priority-10 scrip? ".$msg);
+
+my $priority_five_scrip = RT::Scrip->new($RT::SystemUser);
+($id, $msg) = $priority_ten_scrip->Create(
+ Description => "05 set priority $$",
+ Queue => $queue_id,
+ ScripCondition => 'On Create',
+ ScripAction => 'User Defined',
+ CustomPrepareCode => '$RT::Logger->debug("Setting priority to 5..."); return 1;',
+ CustomCommitCode => '$self->TicketObj->SetPriority(5);',
+ Template => 'Blank',
+ Stage => 'TransactionCreate',
+);
+ok($id, "Created priority-5 scrip? ".$msg);
+
+my $ticket = RT::Ticket->new($RT::SystemUser);
+($id, $msg) = $ticket->Create(
+ Queue => $queue_id,
+ Requestor => 'order@example.com',
+ Subject => "Scrip order test $$",
+);
+ok($ticket->id, "Created ticket? id=$id");
+
+isnt($ticket->Priority , 0, "Ticket shouldn't be priority 0");
+isnt($ticket->Priority , 5, "Ticket shouldn't be priority 5");
+is ($ticket->Priority , 10, "Ticket should be priority 10");
+
+# }}}
+
+1;
diff --git a/rt/t/api/searchbuilder.t b/rt/t/api/searchbuilder.t
new file mode 100644
index 0000000..cb11890
--- /dev/null
+++ b/rt/t/api/searchbuilder.t
@@ -0,0 +1,40 @@
+
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 11;
+
+
+{
+
+ok (require RT::SearchBuilder);
+
+
+}
+
+{
+
+use_ok('RT::Queues');
+ok(my $queues = RT::Queues->new($RT::SystemUser), 'Created a queues object');
+ok( $queues->UnLimit(),'Unlimited the result set of the queues object');
+my $items = $queues->ItemsArrayRef();
+my @items = @{$items};
+
+ok($queues->NewItem->_Accessible('Name','read'));
+my @sorted = sort {lc($a->Name) cmp lc($b->Name)} @items;
+ok (@sorted, "We have an array of queues, sorted". join(',',map {$_->Name} @sorted));
+
+ok (@items, "We have an array of queues, raw". join(',',map {$_->Name} @items));
+my @sorted_ids = map {$_->id } @sorted;
+my @items_ids = map {$_->id } @items;
+
+is ($#sorted, $#items);
+is ($sorted[0]->Name, $items[0]->Name);
+is ($sorted[-1]->Name, $items[-1]->Name);
+is_deeply(\@items_ids, \@sorted_ids, "ItemsArrayRef sorts alphabetically by name");
+
+
+
+}
+
+1;
diff --git a/rt/t/api/system.t b/rt/t/api/system.t
new file mode 100644
index 0000000..3077115
--- /dev/null
+++ b/rt/t/api/system.t
@@ -0,0 +1,33 @@
+
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 7;
+
+
+{
+
+my $s = RT::System->new($RT::SystemUser);
+my $rights = $s->AvailableRights;
+ok ($rights, "Rights defined");
+ok ($rights->{'AdminUsers'},"AdminUsers right found");
+ok ($rights->{'CreateTicket'},"CreateTicket right found");
+ok ($rights->{'AdminGroupMembership'},"ModifyGroupMembers right found");
+ok (!$rights->{'CasdasdsreateTicket'},"bogus right not found");
+
+
+
+
+}
+
+{
+
+use RT::System;
+my $sys = RT::System->new();
+is( $sys->Id, 1);
+is ($sys->id, 1);
+
+
+}
+
+1;
diff --git a/rt/t/api/template-insert.t b/rt/t/api/template-insert.t
new file mode 100644
index 0000000..47bbd79
--- /dev/null
+++ b/rt/t/api/template-insert.t
@@ -0,0 +1,26 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+
+use RT;
+use RT::Test tests => 7;
+
+
+
+# This tiny little test script triggers an interaction bug between DBD::Oracle 1.16, SB 1.15 and RT 3.4
+
+use_ok('RT::Template');
+my $template = RT::Template->new($RT::SystemUser);
+
+isa_ok($template, 'RT::Template');
+my ($val,$msg) = $template->Create(Queue => 1,
+ Name => 'InsertTest',
+ Content => 'This is template content');
+ok($val,$msg);
+is($template->Name, 'InsertTest');
+is($template->Content, 'This is template content', "We created the object right");
+($val, $msg) = $template->SetContent( 'This is new template content');
+ok($val,$msg);
+is($template->Content, 'This is new template content', "We managed to _Set_ the content");
diff --git a/rt/t/api/template.t b/rt/t/api/template.t
new file mode 100644
index 0000000..1612b8f
--- /dev/null
+++ b/rt/t/api/template.t
@@ -0,0 +1,26 @@
+
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 2;
+
+
+{
+
+ok(require RT::Template);
+
+
+}
+
+{
+
+my $t = RT::Template->new($RT::SystemUser);
+$t->Create(Name => "Foo", Queue => 1);
+my $t2 = RT::Template->new($RT::Nobody);
+$t2->Load($t->Id);
+ok($t2->QueueObj->id, "Got the template's queue objet");
+
+
+}
+
+1;
diff --git a/rt/t/api/ticket.t b/rt/t/api/ticket.t
new file mode 100644
index 0000000..2ca0997
--- /dev/null
+++ b/rt/t/api/ticket.t
@@ -0,0 +1,257 @@
+
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 87;
+
+
+{
+
+use_ok ('RT::Queue');
+ok(my $testqueue = RT::Queue->new($RT::SystemUser));
+ok($testqueue->Create( Name => 'ticket tests'));
+isnt($testqueue->Id , 0);
+use_ok('RT::CustomField');
+ok(my $testcf = RT::CustomField->new($RT::SystemUser));
+my ($ret, $cmsg) = $testcf->Create( Name => 'selectmulti',
+ Queue => $testqueue->id,
+ Type => 'SelectMultiple');
+ok($ret,"Created the custom field - ".$cmsg);
+($ret,$cmsg) = $testcf->AddValue ( Name => 'Value1',
+ SortOrder => '1',
+ Description => 'A testing value');
+
+ok($ret, "Added a value - ".$cmsg);
+
+ok($testcf->AddValue ( Name => 'Value2',
+ SortOrder => '2',
+ Description => 'Another testing value'));
+ok($testcf->AddValue ( Name => 'Value3',
+ SortOrder => '3',
+ Description => 'Yet Another testing value'));
+
+is($testcf->Values->Count , 3);
+
+use_ok('RT::Ticket');
+
+my $u = RT::User->new($RT::SystemUser);
+$u->Load("root");
+ok ($u->Id, "Found the root user");
+ok(my $t = RT::Ticket->new($RT::SystemUser));
+ok(my ($id, $msg) = $t->Create( Queue => $testqueue->Id,
+ Subject => 'Testing',
+ Owner => $u->Id
+ ));
+isnt($id , 0);
+is ($t->OwnerObj->Id , $u->Id, "Root is the ticket owner");
+ok(my ($cfv, $cfm) =$t->AddCustomFieldValue(Field => $testcf->Id,
+ Value => 'Value1'));
+isnt($cfv , 0, "Custom field creation didn't return an error: $cfm");
+is($t->CustomFieldValues($testcf->Id)->Count , 1);
+ok($t->CustomFieldValues($testcf->Id)->First &&
+ $t->CustomFieldValues($testcf->Id)->First->Content eq 'Value1');
+
+ok(my ($cfdv, $cfdm) = $t->DeleteCustomFieldValue(Field => $testcf->Id,
+ Value => 'Value1'));
+isnt ($cfdv , 0, "Deleted a custom field value: $cfdm");
+is($t->CustomFieldValues($testcf->Id)->Count , 0);
+
+ok(my $t2 = RT::Ticket->new($RT::SystemUser));
+ok($t2->Load($id));
+is($t2->Subject, 'Testing');
+is($t2->QueueObj->Id, $testqueue->id);
+is($t2->OwnerObj->Id, $u->Id);
+
+my $t3 = RT::Ticket->new($RT::SystemUser);
+my ($id3, $msg3) = $t3->Create( Queue => $testqueue->Id,
+ Subject => 'Testing',
+ Owner => $u->Id);
+my ($cfv1, $cfm1) = $t->AddCustomFieldValue(Field => $testcf->Id,
+ Value => 'Value1');
+isnt($cfv1 , 0, "Adding a custom field to ticket 1 is successful: $cfm");
+my ($cfv2, $cfm2) = $t3->AddCustomFieldValue(Field => $testcf->Id,
+ Value => 'Value2');
+isnt($cfv2 , 0, "Adding a custom field to ticket 2 is successful: $cfm");
+my ($cfv3, $cfm3) = $t->AddCustomFieldValue(Field => $testcf->Id,
+ Value => 'Value3');
+isnt($cfv3 , 0, "Adding a custom field to ticket 1 is successful: $cfm");
+is($t->CustomFieldValues($testcf->Id)->Count , 2,
+ "This ticket has 2 custom field values");
+is($t3->CustomFieldValues($testcf->Id)->Count , 1,
+ "This ticket has 1 custom field value");
+
+
+}
+
+{
+
+
+ok(require RT::Ticket, "Loading the RT::Ticket library");
+
+
+}
+
+{
+
+my $t = RT::Ticket->new($RT::SystemUser);
+
+ok( $t->Create(Queue => 'General', Due => '2002-05-21 00:00:00', ReferredToBy => 'http://www.cpan.org', RefersTo => 'http://fsck.com', Subject => 'This is a subject'), "Ticket Created");
+
+ok ( my $id = $t->Id, "Got ticket id");
+like ($t->RefersTo->First->Target , qr/fsck.com/, "Got refers to");
+like ($t->ReferredToBy->First->Base , qr/cpan.org/, "Got referredtoby");
+is ($t->ResolvedObj->Unix, 0, "It hasn't been resolved - ". $t->ResolvedObj->Unix);
+
+
+}
+
+{
+
+my $ticket = RT::Ticket->new($RT::SystemUser);
+my ($id, $msg) = $ticket->Create(Subject => "Foo",
+ Owner => $RT::SystemUser->Id,
+ Status => 'open',
+ Requestor => ['jesse@example.com'],
+ Queue => '1'
+ );
+ok ($id, "Ticket $id was created");
+ok(my $group = RT::Group->new($RT::SystemUser));
+ok($group->LoadTicketRoleGroup(Ticket => $id, Type=> 'Requestor'));
+ok ($group->Id, "Found the requestors object for this ticket");
+
+ok(my $jesse = RT::User->new($RT::SystemUser), "Creating a jesse rt::user");
+$jesse->LoadByEmail('jesse@example.com');
+ok($jesse->Id, "Found the jesse rt user");
+
+
+ok ($ticket->IsWatcher(Type => 'Requestor', PrincipalId => $jesse->PrincipalId), "The ticket actually has jesse at fsck.com as a requestor");
+ok (my ($add_id, $add_msg) = $ticket->AddWatcher(Type => 'Requestor', Email => 'bob@fsck.com'), "Added bob at fsck.com as a requestor");
+ok ($add_id, "Add succeeded: ($add_msg)");
+ok(my $bob = RT::User->new($RT::SystemUser), "Creating a bob rt::user");
+$bob->LoadByEmail('bob@fsck.com');
+ok($bob->Id, "Found the bob rt user");
+ok ($ticket->IsWatcher(Type => 'Requestor', PrincipalId => $bob->PrincipalId), "The ticket actually has bob at fsck.com as a requestor");
+ok ( ($add_id, $add_msg) = $ticket->DeleteWatcher(Type =>'Requestor', Email => 'bob@fsck.com'), "Added bob at fsck.com as a requestor");
+ok (!$ticket->IsWatcher(Type => 'Requestor', PrincipalId => $bob->PrincipalId), "The ticket no longer has bob at fsck.com as a requestor");
+
+
+$group = RT::Group->new($RT::SystemUser);
+ok($group->LoadTicketRoleGroup(Ticket => $id, Type=> 'Cc'));
+ok ($group->Id, "Found the cc object for this ticket");
+$group = RT::Group->new($RT::SystemUser);
+ok($group->LoadTicketRoleGroup(Ticket => $id, Type=> 'AdminCc'));
+ok ($group->Id, "Found the AdminCc object for this ticket");
+$group = RT::Group->new($RT::SystemUser);
+ok($group->LoadTicketRoleGroup(Ticket => $id, Type=> 'Owner'));
+ok ($group->Id, "Found the Owner object for this ticket");
+ok($group->HasMember($RT::SystemUser->UserObj->PrincipalObj), "the owner group has the member 'RT_System'");
+
+
+}
+
+{
+
+my $t = RT::Ticket->new($RT::SystemUser);
+ok($t->Create(Queue => 'general', Subject => 'SquelchTest', SquelchMailTo => 'nobody@example.com'));
+
+my @returned = $t->SquelchMailTo();
+is($#returned, 0, "The ticket has one squelched recipients");
+
+my ($ret, $msg) = $t->UnsquelchMailTo('nobody@example.com');
+ok($ret, "Removed nobody as a squelched recipient - ".$msg);
+@returned = $t->SquelchMailTo();
+is($#returned, -1, "The ticket has no squelched recipients". join(',',@returned));
+
+
+
+@returned = $t->SquelchMailTo('nobody@example.com');
+is($#returned, 0, "The ticket has one squelched recipients");
+
+my @names = $t->Attributes->Names;
+is(shift @names, 'SquelchMailTo', "The attribute we have is SquelchMailTo");
+@returned = $t->SquelchMailTo('nobody@example.com');
+
+
+is($#returned, 0, "The ticket has one squelched recipients");
+
+@names = $t->Attributes->Names;
+is(shift @names, 'SquelchMailTo', "The attribute we have is SquelchMailTo");
+
+
+($ret, $msg) = $t->UnsquelchMailTo('nobody@example.com');
+ok($ret, "Removed nobody as a squelched recipient - ".$msg);
+@returned = $t->SquelchMailTo();
+is($#returned, -1, "The ticket has no squelched recipients". join(',',@returned));
+
+
+
+}
+
+{
+
+my $t1 = RT::Ticket->new($RT::SystemUser);
+$t1->Create ( Subject => 'Merge test 1', Queue => 'general', Requestor => 'merge1@example.com');
+my $t1id = $t1->id;
+my $t2 = RT::Ticket->new($RT::SystemUser);
+$t2->Create ( Subject => 'Merge test 2', Queue => 'general', Requestor => 'merge2@example.com');
+my $t2id = $t2->id;
+my ($msg, $val) = $t1->MergeInto($t2->id);
+ok ($msg,$val);
+$t1 = RT::Ticket->new($RT::SystemUser);
+is ($t1->id, undef, "ok. we've got a blank ticket1");
+$t1->Load($t1id);
+
+is ($t1->id, $t2->id);
+
+is ($t1->Requestors->MembersObj->Count, 2);
+
+
+
+}
+
+{
+
+my $root = RT::User->new($RT::SystemUser);
+$root->Load('root');
+ok ($root->Id, "Loaded the root user");
+my $t = RT::Ticket->new($RT::SystemUser);
+$t->Load(1);
+$t->SetOwner('root');
+is ($t->OwnerObj->Name, 'root' , "Root owns the ticket");
+$t->Steal();
+is ($t->OwnerObj->id, $RT::SystemUser->id , "SystemUser owns the ticket");
+my $txns = RT::Transactions->new($RT::SystemUser);
+$txns->OrderBy(FIELD => 'id', ORDER => 'DESC');
+$txns->Limit(FIELD => 'ObjectId', VALUE => '1');
+$txns->Limit(FIELD => 'ObjectType', VALUE => 'RT::Ticket');
+$txns->Limit(FIELD => 'Type', OPERATOR => '!=', VALUE => 'EmailRecord');
+
+my $steal = $txns->First;
+is($steal->OldValue , $root->Id , "Stolen from root");
+is($steal->NewValue , $RT::SystemUser->Id , "Stolen by the systemuser");
+
+
+}
+
+{
+
+my $tt = RT::Ticket->new($RT::SystemUser);
+my ($id, $tid, $msg)= $tt->Create(Queue => 'general',
+ Subject => 'test');
+ok($id, $msg);
+is($tt->Status, 'new', "New ticket is created as new");
+
+($id, $msg) = $tt->SetStatus('open');
+ok($id, $msg);
+like($msg, qr/open/i, "Status message is correct");
+($id, $msg) = $tt->SetStatus('resolved');
+ok($id, $msg);
+like($msg, qr/resolved/i, "Status message is correct");
+($id, $msg) = $tt->SetStatus('resolved');
+ok(!$id,$msg);
+
+
+
+}
+
+1;
diff --git a/rt/t/api/tickets.t b/rt/t/api/tickets.t
new file mode 100644
index 0000000..9148a88
--- /dev/null
+++ b/rt/t/api/tickets.t
@@ -0,0 +1,104 @@
+
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 16;
+
+
+{
+
+ok (require RT::Tickets);
+ok( my $testtickets = RT::Tickets->new( $RT::SystemUser ) );
+ok( $testtickets->LimitStatus( VALUE => 'deleted' ) );
+# Should be zero until 'allow_deleted_search'
+is( $testtickets->Count , 0 );
+
+
+}
+
+{
+
+# Test to make sure that you can search for tickets by requestor address and
+# by requestor name.
+
+my ($id,$msg);
+my $u1 = RT::User->new($RT::SystemUser);
+($id, $msg) = $u1->Create( Name => 'RequestorTestOne', EmailAddress => 'rqtest1@example.com');
+ok ($id,$msg);
+my $u2 = RT::User->new($RT::SystemUser);
+($id, $msg) = $u2->Create( Name => 'RequestorTestTwo', EmailAddress => 'rqtest2@example.com');
+ok ($id,$msg);
+
+my $t1 = RT::Ticket->new($RT::SystemUser);
+my ($trans);
+($id,$trans,$msg) =$t1->Create (Queue => 'general', Subject => 'Requestor test one', Requestor => [$u1->EmailAddress]);
+ok ($id, $msg);
+
+my $t2 = RT::Ticket->new($RT::SystemUser);
+($id,$trans,$msg) =$t2->Create (Queue => 'general', Subject => 'Requestor test one', Requestor => [$u2->EmailAddress]);
+ok ($id, $msg);
+
+
+my $t3 = RT::Ticket->new($RT::SystemUser);
+($id,$trans,$msg) =$t3->Create (Queue => 'general', Subject => 'Requestor test one', Requestor => [$u2->EmailAddress, $u1->EmailAddress]);
+ok ($id, $msg);
+
+
+my $tix1 = RT::Tickets->new($RT::SystemUser);
+$tix1->FromSQL('Requestor.EmailAddress LIKE "rqtest1" OR Requestor.EmailAddress LIKE "rqtest2"');
+
+is ($tix1->Count, 3);
+
+my $tix2 = RT::Tickets->new($RT::SystemUser);
+$tix2->FromSQL('Requestor.Name LIKE "TestOne" OR Requestor.Name LIKE "TestTwo"');
+
+is ($tix2->Count, 3);
+
+
+my $tix3 = RT::Tickets->new($RT::SystemUser);
+$tix3->FromSQL('Requestor.EmailAddress LIKE "rqtest1"');
+
+is ($tix3->Count, 2);
+
+my $tix4 = RT::Tickets->new($RT::SystemUser);
+$tix4->FromSQL('Requestor.Name LIKE "TestOne" ');
+
+is ($tix4->Count, 2);
+
+# Searching for tickets that have two requestors isn't supported
+# There's no way to differentiate "one requestor name that matches foo and bar"
+# and "two requestors, one matching foo and one matching bar"
+
+# my $tix5 = RT::Tickets->new($RT::SystemUser);
+# $tix5->FromSQL('Requestor.Name LIKE "TestOne" AND Requestor.Name LIKE "TestTwo"');
+#
+# is ($tix5->Count, 1);
+#
+# my $tix6 = RT::Tickets->new($RT::SystemUser);
+# $tix6->FromSQL('Requestor.EmailAddress LIKE "rqtest1" AND Requestor.EmailAddress LIKE "rqtest2"');
+#
+# is ($tix6->Count, 1);
+
+
+
+}
+
+{
+
+my $t1 = RT::Ticket->new($RT::SystemUser);
+$t1->Create(Queue => 'general', Subject => "LimitWatchers test", Requestors => \['requestor1@example.com']);
+
+
+}
+
+{
+
+# We assume that we've got some tickets hanging around from before.
+ok( my $unlimittickets = RT::Tickets->new( $RT::SystemUser ) );
+ok( $unlimittickets->UnLimit );
+ok( $unlimittickets->Count > 0, "UnLimited tickets object should return tickets" );
+
+
+}
+
+1;
diff --git a/rt/t/api/tickets_overlay_sql.t b/rt/t/api/tickets_overlay_sql.t
new file mode 100644
index 0000000..7980886
--- /dev/null
+++ b/rt/t/api/tickets_overlay_sql.t
@@ -0,0 +1,73 @@
+
+use RT;
+use RT::Test tests => 7;
+
+
+{
+
+use RT::Tickets;
+use strict;
+
+my $tix = RT::Tickets->new($RT::SystemUser);
+{
+ my $query = "Status = 'open'";
+ my ($status, $msg) = $tix->FromSQL($query);
+ ok ($status, "correct query") or diag("error: $msg");
+}
+
+
+my (@created,%created);
+my $string = 'subject/content SQL test';
+{
+ my $t = RT::Ticket->new($RT::SystemUser);
+ ok( $t->Create(Queue => 'General', Subject => $string), "Ticket Created");
+ $created{ $t->Id }++; push @created, $t->Id;
+}
+
+{
+ my $Message = MIME::Entity->build(
+ Subject => 'this is my subject',
+ From => 'jesse@example.com',
+ Data => [ $string ],
+ );
+
+ my $t = RT::Ticket->new($RT::SystemUser);
+ ok( $t->Create( Queue => 'General',
+ Subject => 'another ticket',
+ MIMEObj => $Message,
+ MemberOf => $created[0]
+ ),
+ "Ticket Created"
+ );
+ $created{ $t->Id }++; push @created, $t->Id;
+}
+
+{
+ my $query = ("Subject LIKE '$string' OR Content LIKE '$string'");
+ my ($status, $msg) = $tix->FromSQL($query);
+ ok ($status, "correct query") or diag("error: $msg");
+
+ my $count = 0;
+ while (my $tick = $tix->Next) {
+ $count++ if $created{ $tick->id };
+ }
+ is ($count, scalar @created, "number of returned tickets same as entered");
+}
+
+{
+ my $query = "id = $created[0] OR MemberOf = $created[0]";
+ my ($status, $msg) = $tix->FromSQL($query);
+ ok ($status, "correct query") or diag("error: $msg");
+
+ my $count = 0;
+ while (my $tick = $tix->Next) {
+ $count++ if $created{ $tick->id };
+ }
+ is ($count, scalar @created, "number of returned tickets same as entered");
+}
+
+
+
+}
+
+1;
diff --git a/rt/t/api/uri-fsck_com_rt.t b/rt/t/api/uri-fsck_com_rt.t
new file mode 100644
index 0000000..d62e580
--- /dev/null
+++ b/rt/t/api/uri-fsck_com_rt.t
@@ -0,0 +1,28 @@
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 8;
+
+use_ok("RT::URI::fsck_com_rt");
+my $uri = RT::URI::fsck_com_rt->new($RT::SystemUser);
+
+my $t1 = RT::Ticket->new($RT::SystemUser);
+my ($id,$trans,$msg) =$t1->Create (Queue => 'general', Subject => 'Requestor test one', );
+ok ($id, $msg);
+
+ok(ref($uri));
+
+ok (UNIVERSAL::isa($uri,"RT::URI::fsck_com_rt"), "It's an RT::URI::fsck_com_rt");
+
+ok ($uri->isa('RT::URI::base'), "It's an RT::URI::base");
+ok ($uri->isa('RT::Base'), "It's an RT::Base");
+
+is ($uri->LocalURIPrefix , 'fsck.com-rt://'.RT->Config->Get('Organization'));
+
+
+my $ticket = RT::Ticket->new($RT::SystemUser);
+$ticket->Load(1);
+$uri = RT::URI::fsck_com_rt->new($ticket->CurrentUser);
+is($uri->LocalURIPrefix. "/ticket/1" , $uri->URIForObject($ticket));
+
+1;
diff --git a/rt/t/api/uri-t.t b/rt/t/api/uri-t.t
new file mode 100644
index 0000000..4695629
--- /dev/null
+++ b/rt/t/api/uri-t.t
@@ -0,0 +1,21 @@
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 6;
+
+my $t1 = RT::Ticket->new($RT::SystemUser);
+my ($id,$trans,$msg) =$t1->Create (Queue => 'general', Subject => 'Requestor test one', );
+ok ($id, $msg);
+
+use_ok("RT::URI::t");
+my $uri = RT::URI::t->new($RT::SystemUser);
+ok(ref($uri), "URI object exists");
+
+my $uristr = "t:1";
+$uri->ParseURI($uristr);
+is(ref($uri->Object), "RT::Ticket", "Object loaded is a ticket");
+is($uri->Object->Id, 1, "Object loaded has correct ID");
+is($uri->URI, 'fsck.com-rt://'.RT->Config->Get('Organization').'/ticket/1',
+ "URI object has correct URI string");
+
+1;
diff --git a/rt/t/api/user.t b/rt/t/api/user.t
new file mode 100644
index 0000000..25cf747
--- /dev/null
+++ b/rt/t/api/user.t
@@ -0,0 +1,339 @@
+
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 108;
+
+
+{
+
+ok(require RT::User);
+
+
+}
+
+{
+
+# Make sure we can create a user
+
+my $u1 = RT::User->new($RT::SystemUser);
+is(ref($u1), 'RT::User');
+my ($id, $msg) = $u1->Create(Name => 'CreateTest1'.$$, EmailAddress => $$.'create-test-1@example.com');
+ok ($id, "Creating user CreateTest1 - " . $msg );
+
+# Make sure we can't create a second user with the same name
+my $u2 = RT::User->new($RT::SystemUser);
+($id, $msg) = $u2->Create(Name => 'CreateTest1'.$$, EmailAddress => $$.'create-test-2@example.com');
+ok (!$id, $msg);
+
+
+# Make sure we can't create a second user with the same EmailAddress address
+my $u3 = RT::User->new($RT::SystemUser);
+($id, $msg) = $u3->Create(Name => 'CreateTest2'.$$, EmailAddress => $$.'create-test-1@example.com');
+ok (!$id, $msg);
+
+# Make sure we can create a user with no EmailAddress address
+my $u4 = RT::User->new($RT::SystemUser);
+($id, $msg) = $u4->Create(Name => 'CreateTest3'.$$);
+ok ($id, $msg);
+
+# make sure we can create a second user with no EmailAddress address
+my $u5 = RT::User->new($RT::SystemUser);
+($id, $msg) = $u5->Create(Name => 'CreateTest4'.$$);
+ok ($id, $msg);
+
+# make sure we can create a user with a blank EmailAddress address
+my $u6 = RT::User->new($RT::SystemUser);
+($id, $msg) = $u6->Create(Name => 'CreateTest6'.$$, EmailAddress => '');
+ok ($id, $msg);
+# make sure we can create a second user with a blankEmailAddress address
+my $u7 = RT::User->new($RT::SystemUser);
+($id, $msg) = $u7->Create(Name => 'CreateTest7'.$$, EmailAddress => '');
+ok ($id, $msg);
+
+# Can we change the email address away from from "";
+($id,$msg) = $u7->SetEmailAddress('foo@bar'.$$);
+ok ($id, $msg);
+# can we change the address back to "";
+($id,$msg) = $u7->SetEmailAddress('');
+ok ($id, $msg);
+is_empty ($u7->EmailAddress);
+
+RT->Config->Set('ValidateUserEmailAddresses' => 1);
+# Make sur we can't create a user with multiple email adresses separated by comma
+my $u8 = RT::User->new($RT::SystemUser);
+($id, $msg) = $u8->Create(Name => 'CreateTest8'.$$, EmailAddress => $$.'create-test-81@example.com, '.$$.'create-test-82@example.com');
+ok (!$id, $msg);
+
+# Make sur we can't create a user with multiple email adresses separated by space
+my $u9 = RT::User->new($RT::SystemUser);
+($id, $msg) = $u9->Create(Name => 'CreateTest9'.$$, EmailAddress => $$.'create-test-91@example.com '.$$.'create-test-92@example.com');
+ok (!$id, $msg);
+
+# Make sur we can't create a user with invalid email address
+my $u10 = RT::User->new($RT::SystemUser);
+($id, $msg) = $u10->Create(Name => 'CreateTest10'.$$, EmailAddress => $$.'create-test10}@[.com');
+ok (!$id, $msg);
+RT->Config->Set('ValidateUserEmailAddresses' => undef);
+
+}
+
+{
+
+
+ok(my $user = RT::User->new($RT::SystemUser));
+ok($user->Load('root'), "Loaded user 'root'");
+ok($user->Privileged, "User 'root' is privileged");
+ok(my ($v,$m) = $user->SetPrivileged(0));
+is ($v ,1, "Set unprivileged suceeded ($m)");
+ok(!$user->Privileged, "User 'root' is no longer privileged");
+ok(my ($v2,$m2) = $user->SetPrivileged(1));
+is ($v2 ,1, "Set privileged suceeded ($m2");
+ok($user->Privileged, "User 'root' is privileged again");
+
+
+}
+
+{
+
+ok(my $u = RT::User->new($RT::SystemUser));
+ok($u->Load(1), "Loaded the first user");
+is($u->PrincipalObj->ObjectId , 1, "user 1 is the first principal");
+is($u->PrincipalObj->PrincipalType, 'User' , "Principal 1 is a user, not a group");
+
+
+}
+
+{
+
+my $root = RT::User->new($RT::SystemUser);
+$root->Load('root');
+ok($root->Id, "Found the root user");
+my $rootq = RT::Queue->new($root);
+$rootq->Load(1);
+ok($rootq->Id, "Loaded the first queue");
+
+ok ($rootq->CurrentUser->HasRight(Right=> 'CreateTicket', Object => $rootq), "Root can create tickets");
+
+my $new_user = RT::User->new($RT::SystemUser);
+my ($id, $msg) = $new_user->Create(Name => 'ACLTest'.$$);
+
+ok ($id, "Created a new user for acl test $msg");
+
+my $q = RT::Queue->new($new_user);
+$q->Load(1);
+ok($q->Id, "Loaded the first queue");
+
+
+ok (!$q->CurrentUser->HasRight(Right => 'CreateTicket', Object => $q), "Some random user doesn't have the right to create tickets");
+ok (my ($gval, $gmsg) = $new_user->PrincipalObj->GrantRight( Right => 'CreateTicket', Object => $q), "Granted the random user the right to create tickets");
+ok ($gval, "Grant succeeded - $gmsg");
+
+
+ok ($q->CurrentUser->HasRight(Right => 'CreateTicket', Object => $q), "The user can create tickets after we grant him the right");
+ok ( ($gval, $gmsg) = $new_user->PrincipalObj->RevokeRight( Right => 'CreateTicket', Object => $q), "revoked the random user the right to create tickets");
+ok ($gval, "Revocation succeeded - $gmsg");
+ok (!$q->CurrentUser->HasRight(Right => 'CreateTicket', Object => $q), "The user can't create tickets anymore");
+
+
+
+
+
+# Create a ticket in the queue
+my $new_tick = RT::Ticket->new($RT::SystemUser);
+my ($tickid, $tickmsg) = $new_tick->Create(Subject=> 'ACL Test', Queue => 'General');
+ok($tickid, "Created ticket: $tickid");
+# Make sure the user doesn't have the right to modify tickets in the queue
+ok (!$new_user->HasRight( Object => $new_tick, Right => 'ModifyTicket'), "User can't modify the ticket without group membership");
+# Create a new group
+my $group = RT::Group->new($RT::SystemUser);
+$group->CreateUserDefinedGroup(Name => 'ACLTest'.$$);
+ok($group->Id, "Created a new group Ok");
+# Grant a group the right to modify tickets in a queue
+ok(my ($gv,$gm) = $group->PrincipalObj->GrantRight( Object => $q, Right => 'ModifyTicket'),"Granted the group the right to modify tickets");
+ok($gv,"Grant succeeed - $gm");
+# Add the user to the group
+ok( my ($aid, $amsg) = $group->AddMember($new_user->PrincipalId), "Added the member to the group");
+ok ($aid, "Member added to group: $amsg");
+# Make sure the user does have the right to modify tickets in the queue
+ok ($new_user->HasRight( Object => $new_tick, Right => 'ModifyTicket'), "User can modify the ticket with group membership");
+
+
+# Remove the user from the group
+ok( my ($did, $dmsg) = $group->DeleteMember($new_user->PrincipalId), "Deleted the member from the group");
+ok ($did,"Deleted the group member: $dmsg");
+# Make sure the user doesn't have the right to modify tickets in the queue
+ok (!$new_user->HasRight( Object => $new_tick, Right => 'ModifyTicket'), "User can't modify the ticket without group membership");
+
+
+my $q_as_system = RT::Queue->new($RT::SystemUser);
+$q_as_system->Load(1);
+ok($q_as_system->Id, "Loaded the first queue");
+
+# Create a ticket in the queue
+my $new_tick2 = RT::Ticket->new($RT::SystemUser);
+(my $tick2id, $tickmsg) = $new_tick2->Create(Subject=> 'ACL Test 2', Queue =>$q_as_system->Id);
+ok($tick2id, "Created ticket: $tick2id");
+is($new_tick2->QueueObj->id, $q_as_system->Id, "Created a new ticket in queue 1");
+
+
+# make sure that the user can't do this without subgroup membership
+ok (!$new_user->HasRight( Object => $new_tick2, Right => 'ModifyTicket'), "User can't modify the ticket without group membership");
+
+# Create a subgroup
+my $subgroup = RT::Group->new($RT::SystemUser);
+$subgroup->CreateUserDefinedGroup(Name => 'Subgrouptest'.$$);
+ok($subgroup->Id, "Created a new group ".$subgroup->Id."Ok");
+#Add the subgroup as a subgroup of the group
+my ($said, $samsg) = $group->AddMember($subgroup->PrincipalId);
+ok ($said, "Added the subgroup as a member of the group");
+# Add the user to a subgroup of the group
+
+my ($usaid, $usamsg) = $subgroup->AddMember($new_user->PrincipalId);
+ok($usaid,"Added the user ".$new_user->Id."to the subgroup");
+# Make sure the user does have the right to modify tickets in the queue
+ok ($new_user->HasRight( Object => $new_tick2, Right => 'ModifyTicket'), "User can modify the ticket with subgroup membership");
+
+# {{{ Deal with making sure that members of subgroups of a disabled group don't have rights
+
+($id, $msg) = $group->SetDisabled(1);
+ok ($id,$msg);
+ok (!$new_user->HasRight( Object => $new_tick2, Right => 'ModifyTicket'), "User can't modify the ticket when the group ".$group->Id. " is disabled");
+ ($id, $msg) = $group->SetDisabled(0);
+ok($id,$msg);
+# Test what happens when we disable the group the user is a member of directly
+
+($id, $msg) = $subgroup->SetDisabled(1);
+ ok ($id,$msg);
+ok (!$new_user->HasRight( Object => $new_tick2, Right => 'ModifyTicket'), "User can't modify the ticket when the group ".$subgroup->Id. " is disabled");
+ ($id, $msg) = $subgroup->SetDisabled(0);
+ ok ($id,$msg);
+ok ($new_user->HasRight( Object => $new_tick2, Right => 'ModifyTicket'), "User can modify the ticket without group membership");
+
+# }}}
+
+
+my ($usrid, $usrmsg) = $subgroup->DeleteMember($new_user->PrincipalId);
+ok($usrid,"removed the user from the group - $usrmsg");
+# Make sure the user doesn't have the right to modify tickets in the queue
+ok (!$new_user->HasRight( Object => $new_tick2, Right => 'ModifyTicket'), "User can't modify the ticket without group membership");
+
+#revoke the right to modify tickets in a queue
+ok(($gv,$gm) = $group->PrincipalObj->RevokeRight( Object => $q, Right => 'ModifyTicket'),"Granted the group the right to modify tickets");
+ok($gv,"revoke succeeed - $gm");
+
+# {{{ Test the user's right to modify a ticket as a _queue_ admincc for a right granted at the _queue_ level
+
+# Grant queue admin cc the right to modify ticket in the queue
+ok(my ($qv,$qm) = $q_as_system->AdminCc->PrincipalObj->GrantRight( Object => $q_as_system, Right => 'ModifyTicket'),"Granted the queue adminccs the right to modify tickets");
+ok($qv, "Granted the right successfully - $qm");
+
+# Add the user as a queue admincc
+ok (my ($add_id, $add_msg) = $q_as_system->AddWatcher(Type => 'AdminCc', PrincipalId => $new_user->PrincipalId) , "Added the new user as a queue admincc");
+ok ($add_id, "the user is now a queue admincc - $add_msg");
+
+# Make sure the user does have the right to modify tickets in the queue
+ok ($new_user->HasRight( Object => $new_tick2, Right => 'ModifyTicket'), "User can modify the ticket as an admincc");
+# Remove the user from the role group
+ok (my ($del_id, $del_msg) = $q_as_system->DeleteWatcher(Type => 'AdminCc', PrincipalId => $new_user->PrincipalId) , "Deleted the new user as a queue admincc");
+
+# Make sure the user doesn't have the right to modify tickets in the queue
+ok (!$new_user->HasRight( Object => $new_tick2, Right => 'ModifyTicket'), "User can't modify the ticket without group membership");
+
+# }}}
+
+# {{{ Test the user's right to modify a ticket as a _ticket_ admincc with the right granted at the _queue_ level
+
+# Add the user as a ticket admincc
+ok (my( $uadd_id, $uadd_msg) = $new_tick2->AddWatcher(Type => 'AdminCc', PrincipalId => $new_user->PrincipalId) , "Added the new user as a queue admincc");
+ok ($add_id, "the user is now a queue admincc - $add_msg");
+
+# Make sure the user does have the right to modify tickets in the queue
+ok ($new_user->HasRight( Object => $new_tick2, Right => 'ModifyTicket'), "User can modify the ticket as an admincc");
+
+# Remove the user from the role group
+ok (( $del_id, $del_msg) = $new_tick2->DeleteWatcher(Type => 'AdminCc', PrincipalId => $new_user->PrincipalId) , "Deleted the new user as a queue admincc");
+
+# Make sure the user doesn't have the right to modify tickets in the queue
+ok (!$new_user->HasRight( Object => $new_tick2, Right => 'ModifyTicket'), "User can't modify the ticket without group membership");
+
+
+# Revoke the right to modify ticket in the queue
+ok(my ($rqv,$rqm) = $q_as_system->AdminCc->PrincipalObj->RevokeRight( Object => $q_as_system, Right => 'ModifyTicket'),"Revokeed the queue adminccs the right to modify tickets");
+ok($rqv, "Revoked the right successfully - $rqm");
+
+# }}}
+
+
+
+# {{{ Test the user's right to modify a ticket as a _queue_ admincc for a right granted at the _system_ level
+
+# Before we start Make sure the user does not have the right to modify tickets in the queue
+ok (!$new_user->HasRight( Object => $new_tick2, Right => 'ModifyTicket'), "User can not modify the ticket without it being granted");
+ok (!$new_user->HasRight( Object => $new_tick2->QueueObj, Right => 'ModifyTicket'), "User can not modify tickets in the queue without it being granted");
+
+# Grant queue admin cc the right to modify ticket in the queue
+ok(($qv,$qm) = $q_as_system->AdminCc->PrincipalObj->GrantRight( Object => $RT::System, Right => 'ModifyTicket'),"Granted the queue adminccs the right to modify tickets");
+ok($qv, "Granted the right successfully - $qm");
+
+# Make sure the user can't modify the ticket before they're added as a watcher
+ok (!$new_user->HasRight( Object => $new_tick2, Right => 'ModifyTicket'), "User can not modify the ticket without being an admincc");
+ok (!$new_user->HasRight( Object => $new_tick2->QueueObj, Right => 'ModifyTicket'), "User can not modify tickets in the queue without being an admincc");
+
+# Add the user as a queue admincc
+ok (($add_id, $add_msg) = $q_as_system->AddWatcher(Type => 'AdminCc', PrincipalId => $new_user->PrincipalId) , "Added the new user as a queue admincc");
+ok ($add_id, "the user is now a queue admincc - $add_msg");
+
+# Make sure the user does have the right to modify tickets in the queue
+ok ($new_user->HasRight( Object => $new_tick2, Right => 'ModifyTicket'), "User can modify the ticket as an admincc");
+ok ($new_user->HasRight( Object => $new_tick2->QueueObj, Right => 'ModifyTicket'), "User can modify tickets in the queue as an admincc");
+# Remove the user from the role group
+ok (($del_id, $del_msg) = $q_as_system->DeleteWatcher(Type => 'AdminCc', PrincipalId => $new_user->PrincipalId) , "Deleted the new user as a queue admincc");
+
+# Make sure the user doesn't have the right to modify tickets in the queue
+ok (!$new_user->HasRight( Object => $new_tick2, Right => 'ModifyTicket'), "User can't modify the ticket without group membership");
+ok (!$new_user->HasRight( Object => $new_tick2->QueueObj, Right => 'ModifyTicket'), "User can't modify tickets in the queue without group membership");
+
+# }}}
+
+# {{{ Test the user's right to modify a ticket as a _ticket_ admincc with the right granted at the _queue_ level
+
+ok (!$new_user->HasRight( Object => $new_tick2, Right => 'ModifyTicket'), "User can not modify the ticket without being an admincc");
+ok (!$new_user->HasRight( Object => $new_tick2->QueueObj, Right => 'ModifyTicket'), "User can not modify tickets in the queue obj without being an admincc");
+
+
+# Add the user as a ticket admincc
+ok ( ($uadd_id, $uadd_msg) = $new_tick2->AddWatcher(Type => 'AdminCc', PrincipalId => $new_user->PrincipalId) , "Added the new user as a queue admincc");
+ok ($add_id, "the user is now a queue admincc - $add_msg");
+
+# Make sure the user does have the right to modify tickets in the queue
+ok ($new_user->HasRight( Object => $new_tick2, Right => 'ModifyTicket'), "User can modify the ticket as an admincc");
+ok (!$new_user->HasRight( Object => $new_tick2->QueueObj, Right => 'ModifyTicket'), "User can not modify tickets in the queue obj being only a ticket admincc");
+
+# Remove the user from the role group
+ok ( ($del_id, $del_msg) = $new_tick2->DeleteWatcher(Type => 'AdminCc', PrincipalId => $new_user->PrincipalId) , "Deleted the new user as a queue admincc");
+
+# Make sure the user doesn't have the right to modify tickets in the queue
+ok (!$new_user->HasRight( Object => $new_tick2, Right => 'ModifyTicket'), "User can't modify the ticket without being an admincc");
+ok (!$new_user->HasRight( Object => $new_tick2->QueueObj, Right => 'ModifyTicket'), "User can not modify tickets in the queue obj without being an admincc");
+
+
+# Revoke the right to modify ticket in the queue
+ok(($rqv,$rqm) = $q_as_system->AdminCc->PrincipalObj->RevokeRight( Object => $RT::System, Right => 'ModifyTicket'),"Revokeed the queue adminccs the right to modify tickets");
+ok($rqv, "Revoked the right successfully - $rqm");
+
+# }}}
+
+
+
+
+# Grant "privileged users" the system right to create users
+# Create a privileged user.
+# have that user create another user
+# Revoke the right for privileged users to create users
+# have the privileged user try to create another user and fail the ACL check
+
+
+}
+
+1;
diff --git a/rt/t/api/users.t b/rt/t/api/users.t
new file mode 100644
index 0000000..d1ff174
--- /dev/null
+++ b/rt/t/api/users.t
@@ -0,0 +1,80 @@
+
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => 11;
+
+
+{
+
+ok(require RT::Users);
+
+
+}
+
+{
+ no warnings qw(redefine once);
+
+ok(my $users = RT::Users->new($RT::SystemUser));
+$users->WhoHaveRight(Object =>$RT::System, Right =>'SuperUser');
+is($users->Count , 1, "There is one privileged superuser - Found ". $users->Count );
+# TODO: this wants more testing
+
+my $RTxUser = RT::User->new($RT::SystemUser);
+my ($id, $msg) = $RTxUser->Create( Name => 'RTxUser', Comments => "RTx extension user", Privileged => 1);
+ok ($id,$msg);
+
+my $group = RT::Group->new($RT::SystemUser);
+$group->LoadACLEquivalenceGroup($RTxUser->PrincipalObj);
+
+my $RTxSysObj = {};
+bless $RTxSysObj, 'RTx::System';
+*RTx::System::Id = sub { 1; };
+*RTx::System::id = *RTx::System::Id;
+my $ace = RT::Record->new($RT::SystemUser);
+$ace->Table('ACL');
+$ace->_BuildTableAttributes unless ($RT::Record::_TABLE_ATTR->{ref($ace)});
+($id, $msg) = $ace->Create( PrincipalId => $group->id, PrincipalType => 'Group', RightName => 'RTxUserRight', ObjectType => 'RTx::System', ObjectId => 1 );
+ok ($id, "ACL for RTxSysObj created");
+
+my $RTxObj = {};
+bless $RTxObj, 'RTx::System::Record';
+*RTx::System::Record::Id = sub { 4; };
+*RTx::System::Record::id = *RTx::System::Record::Id;
+
+$users = RT::Users->new($RT::SystemUser);
+$users->WhoHaveRight(Right => 'RTxUserRight', Object => $RTxSysObj);
+is($users->Count, 1, "RTxUserRight found for RTxSysObj");
+
+$users = RT::Users->new($RT::SystemUser);
+$users->WhoHaveRight(Right => 'RTxUserRight', Object => $RTxObj);
+is($users->Count, 0, "RTxUserRight not found for RTxObj");
+
+$users = RT::Users->new($RT::SystemUser);
+$users->WhoHaveRight(Right => 'RTxUserRight', Object => $RTxObj, EquivObjects => [ $RTxSysObj ]);
+is($users->Count, 1, "RTxUserRight found for RTxObj using EquivObjects");
+
+$ace = RT::Record->new($RT::SystemUser);
+$ace->Table('ACL');
+$ace->_BuildTableAttributes unless ($RT::Record::_TABLE_ATTR->{ref($ace)});
+($id, $msg) = $ace->Create( PrincipalId => $group->id, PrincipalType => 'Group', RightName => 'RTxUserRight', ObjectType => 'RTx::System::Record', ObjectId => 5 );
+ok ($id, "ACL for RTxObj created");
+
+my $RTxObj2 = {};
+bless $RTxObj2, 'RTx::System::Record';
+*RTx::System::Record::Id = sub { 5; };
+*RTx::System::Record::id = sub { 5; };
+
+$users = RT::Users->new($RT::SystemUser);
+$users->WhoHaveRight(Right => 'RTxUserRight', Object => $RTxObj2);
+is($users->Count, 1, "RTxUserRight found for RTxObj2");
+
+$users = RT::Users->new($RT::SystemUser);
+$users->WhoHaveRight(Right => 'RTxUserRight', Object => $RTxObj2, EquivObjects => [ $RTxSysObj ]);
+is($users->Count, 1, "RTxUserRight found for RTxObj2");
+
+
+
+}
+
+1;