summaryrefslogtreecommitdiff
path: root/rt/t/api
diff options
context:
space:
mode:
authorIvan Kohler <ivan@freeside.biz>2015-07-09 22:18:55 -0700
committerIvan Kohler <ivan@freeside.biz>2015-07-09 22:18:55 -0700
commit1c538bfabc2cd31f27067505f0c3d1a46cba6ef0 (patch)
tree96922ad4459eda1e649327fd391d60c58d454c53 /rt/t/api
parent4f5619288413a185e9933088d9dd8c5afbc55dfa (diff)
RT 4.2.11, ticket#13852
Diffstat (limited to 'rt/t/api')
-rw-r--r--rt/t/api/attachment_filename.t6
-rw-r--r--rt/t/api/cfsearch.t24
-rw-r--r--rt/t/api/config.t8
-rw-r--r--rt/t/api/cron.t26
-rw-r--r--rt/t/api/customfield.t423
-rw-r--r--rt/t/api/date.t98
-rw-r--r--rt/t/api/db_indexes.t165
-rw-r--r--rt/t/api/group-rights.t2
-rw-r--r--rt/t/api/group.t2
-rw-r--r--rt/t/api/groups.t5
-rw-r--r--rt/t/api/i18n_guess.t4
-rw-r--r--rt/t/api/i18n_mime_encoding.t32
-rw-r--r--rt/t/api/initialdata.t16
-rw-r--r--rt/t/api/link.t6
-rw-r--r--rt/t/api/password-types.t16
-rw-r--r--rt/t/api/queue.t12
-rw-r--r--rt/t/api/record.t4
-rw-r--r--rt/t/api/reminder-permissions.t49
-rw-r--r--rt/t/api/rights.t12
-rw-r--r--rt/t/api/rtname.t7
-rw-r--r--rt/t/api/savedsearch.t66
-rw-r--r--rt/t/api/scrip.t221
-rw-r--r--rt/t/api/scrip_order.t313
-rw-r--r--rt/t/api/searchbuilder.t2
-rw-r--r--rt/t/api/system-available-rights.t65
-rw-r--r--rt/t/api/system.t54
-rw-r--r--rt/t/api/template.t179
-rw-r--r--rt/t/api/ticket.t72
-rw-r--r--rt/t/api/tickets.t35
-rw-r--r--rt/t/api/txn_content.t8
-rw-r--r--rt/t/api/user-prefs.t59
-rw-r--r--rt/t/api/user.t31
-rw-r--r--rt/t/api/users.t2
33 files changed, 1740 insertions, 284 deletions
diff --git a/rt/t/api/attachment_filename.t b/rt/t/api/attachment_filename.t
index 6bfc7072f..aa8acd2d9 100644
--- a/rt/t/api/attachment_filename.t
+++ b/rt/t/api/attachment_filename.t
@@ -10,18 +10,18 @@ my $mime = MIME::Entity->build(
);
$mime->attach(
- Path => 'share/html/NoAuth/images/bpslogo.png',
+ Path => 'share/static/images/bpslogo.png',
Type => 'image/png',
);
$mime->attach(
- Path => 'share/html/NoAuth/images/bpslogo.png',
+ Path => 'share/static/images/bpslogo.png',
Type => 'image/png',
Filename => 'bpslogo.png',
);
$mime->attach(
- Path => 'share/html/NoAuth/images/bpslogo.png',
+ Path => 'share/static/images/bpslogo.png',
Filename => 'images/bpslogo.png',
Type => 'image/png',
);
diff --git a/rt/t/api/cfsearch.t b/rt/t/api/cfsearch.t
index 7a460ce2e..4df6e0af2 100644
--- a/rt/t/api/cfsearch.t
+++ b/rt/t/api/cfsearch.t
@@ -36,9 +36,9 @@ my $cfvalue1 = 'Foo';
{
my ($id, $msg) = $u1->AddCustomFieldValue(
- Field => $cfname,
- Value => $cfvalue1,
- RecordTransaction => 0 );
+ Field => $cfname,
+ Value => $cfvalue1,
+ RecordTransaction => 0 );
ok( $id, "Adding CF value '$cfvalue1' - " . $msg );
}
@@ -51,18 +51,18 @@ my $cfvalue1 = 'Foo';
{
my ($id, $msg) = $u1->DeleteCustomFieldValue(
- Field => $cfname,
- Value => $cfvalue1,
- RecordTransaction => 0 );
+ Field => $cfname,
+ Value => $cfvalue1,
+ RecordTransaction => 0 );
ok( $id, "Deleting CF value - " . $msg );
}
my $cfvalue2 = 'Bar';
{
my ($id, $msg) = $u1->AddCustomFieldValue(
- Field => $cfname,
- Value => $cfvalue2,
- RecordTransaction => 0 );
+ Field => $cfname,
+ Value => $cfvalue2,
+ RecordTransaction => 0 );
ok( $id, "Adding second CF value '$cfvalue2' - " . $msg );
}
@@ -92,9 +92,9 @@ sub QueryCFValue{
isa_ok( $users, 'RT::Users' );
$users->LimitCustomField(
- CUSTOMFIELD => $cf_id,
- OPERATOR => "=",
- VALUE => $cf_value );
+ CUSTOMFIELD => $cf_id,
+ OPERATOR => "=",
+ VALUE => $cf_value );
while ( my $filtered_user = $users->Next() ){
my $cf_values = $filtered_user->CustomFieldValues($cf->id);
diff --git a/rt/t/api/config.t b/rt/t/api/config.t
index 62b77dffa..b87531139 100644
--- a/rt/t/api/config.t
+++ b/rt/t/api/config.t
@@ -1,7 +1,7 @@
use strict;
use warnings;
use RT;
-use RT::Test nodb => 1, tests => 11;
+use RT::Test nodb => 1, tests => undef;
use Test::Warn;
ok(
@@ -39,5 +39,11 @@ my @encodings = qw(utf-8-strict iso-8859-1 ascii);
warning_is {RT::Config->PostLoadCheck} "Unknown encoding 'foo' in \@EmailInputEncodings option",
'Correct warning for encoding foo';
+RT::Config->Set( WebDefaultStylesheet => 'non-existent-skin-name' );
+warning_like {RT::Config->PostLoadCheck} qr{rudder},
+ 'Correct warning for default stylesheet';
+
my @canonical_encodings = RT::Config->Get('EmailInputEncodings');
is_deeply(\@encodings, \@canonical_encodings, 'Got correct encoding list');
+
+done_testing; \ No newline at end of file
diff --git a/rt/t/api/cron.t b/rt/t/api/cron.t
index 6bd992df3..b16adde82 100644
--- a/rt/t/api/cron.t
+++ b/rt/t/api/cron.t
@@ -24,10 +24,10 @@ This is a content string with no content.';
my $template_obj = RT::Template->new($CurrentUser);
$template_obj->Create(Queue => '0',
- Name => 'recordtest',
- Description => 'testing Record actions',
- Content => $template_content,
- );
+ Name => 'recordtest',
+ Description => 'testing Record actions',
+ Content => $template_content,
+ );
# Create a queue and some tickets.
@@ -36,17 +36,17 @@ my $queue_obj = RT::Queue->new($CurrentUser);
ok($ret, 'record test queue creation');
my $ticket1 = RT::Ticket->new($CurrentUser);
-my ($id, $tobj, $msg2) = $ticket1->Create(Queue => $queue_obj,
- Requestor => ['tara@example.com'],
- Subject => 'bork bork bork',
- Priority => 22,
- );
+my ($id, $tobj, $msg2) = $ticket1->Create(Queue => $queue_obj,
+ Requestor => ['tara@example.com'],
+ Subject => 'bork bork bork',
+ Priority => 22,
+ );
ok($id, 'record test ticket creation 1');
my $ticket2 = RT::Ticket->new($CurrentUser);
($id, $tobj, $msg2) = $ticket2->Create(Queue => $queue_obj,
- Requestor => ['root@localhost'],
- Subject => 'hurdy gurdy'
- );
+ Requestor => ['root@localhost'],
+ Subject => 'hurdy gurdy'
+ );
ok($id, 'record test ticket creation 2');
@@ -58,7 +58,7 @@ ok(require RT::Search::FromSQL, "Search::FromSQL loaded");
my $ticketsqlstr = "Requestor.EmailAddress = '" . $CurrentUser->EmailAddress .
"' AND Priority > '20'";
my $search = RT::Search::FromSQL->new(Argument => $ticketsqlstr, TicketsObj => RT::Tickets->new($CurrentUser),
- );
+ );
is(ref($search), 'RT::Search::FromSQL', "search created");
ok($search->Prepare(), "fromsql search run");
my $counter = 0;
diff --git a/rt/t/api/customfield.t b/rt/t/api/customfield.t
index 6be50bb3a..df8f66df2 100644
--- a/rt/t/api/customfield.t
+++ b/rt/t/api/customfield.t
@@ -2,72 +2,393 @@
use strict;
use warnings;
use RT;
-use RT::Test nodata => 1, tests => 29;
+use RT::Test tests => undef;
use Test::Warn;
+use_ok('RT::CustomField');
-{
+my $queue = RT::Queue->new( RT->SystemUser );
+$queue->Load( "General" );
+ok( $queue->id, "found the General queue" );
-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));
+my $cf = RT::CustomField->new(RT->SystemUser);
+ok($cf, "Have a CustomField object");
+
+# Use the old Queue field to set up a ticket CF
+my ($ok, $msg) = $cf->Create(
+ Name => 'TestingCF',
+ Queue => '0',
+ Description => 'A Testing custom field',
+ Type => 'SelectSingle'
+);
+ok($ok, 'Global custom field correctly created');
+is($cf->Type, 'Select', "Is a select CF");
+ok($cf->SingleValue, "Also a single-value CF");
+is($cf->MaxValues, 1, "...meaning only one value, max");
+
+($ok, $msg) = $cf->SetMaxValues('0');
+ok($ok, "Set to infinite values: $msg");
+is($cf->Type, 'Select', "Still a select CF");
+ok( ! $cf->SingleValue, "No longer single-value" );
+is($cf->MaxValues, 0, "...meaning no maximum values");
+
+# Test our sanity checking of CF types
+($ok, $msg) = $cf->SetType('BogusType');
+ok( ! $ok, "Unable to set a custom field's type to a bogus type: $msg");
+
+$cf = RT::CustomField->new(RT->SystemUser);
+($ok, $msg) = $cf->Create(
+ Name => 'TestingCF-bad',
+ Queue => '0',
+ SortOrder => '1',
+ Description => 'A Testing custom field with a bogus Type',
+ Type=> 'SelectSingleton'
+);
+ok( ! $ok, "Correctly could not create with bogus type: $msg");
+
+
+# Deprecated types
+warning_like {
+ ok($cf->ValidateType('SelectSingle'), "ValidateType accepts SelectSingle");
+} qr/deprecated/, "...but warns of deprecation";
+
+warning_like {
+ ok($cf->ValidateType('SelectMultiple'), "ValidateType accepts SelectMultiple");
+} qr/deprecated/, "...but warns of deprecation";
+
+warning_like {
+ ok( ! $cf->ValidateType('SelectFooMultiple'), "ValidateType does not accept SelectFooMultiple");
+} qr/deprecated/, "...and also warns of deprecation";
+
+
+# Test adding and removing CFVs
$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, $msg) = $cf->AddValue(Name => 'foo' , Description => 'TestCFValue', SortOrder => '6');
+ok($ok, "Added a new value to the select options");
+($ok, $msg) = $cf->DeleteValue($ok);
+ok($ok, "Deleting it again");
+
+
+# Loading, and context objects
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName( Name => "TestingCF" );
+ok($cf->id, "Load finds it, given just a name" );
+ok( ! $cf->ContextObject, "Did not get a context object");
+
+# Old Queue => form should find the global, gain no context object
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', Queue => 0);
+ok($cf->id, "Load finds it, given a Name and Queue => 0" );
+ok( ! $cf->ContextObject, 'Context object not set when queue is 0');
+
+# We don't default to also searching global -- but do pick up a contextobject
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', Queue => 1);
+ok( ! $cf->id, "Load does not finds it, given a Name and Queue => 1" );
+ok($cf->ContextObject->id, 'Context object is now set');
+# If we IncludeGlobal, we find it
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', Queue => 1, IncludeGlobal => 1 );
+ok($cf->id, "Load now finds it, given a Name and Queue => 1 and IncludeGlobal" );
+ok($cf->ContextObject->id, 'Context object is also set');
-}
+# The explicit LookupType works
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', LookupType => RT::Ticket->CustomFieldLookupType );
+ok($cf->id, "Load now finds it, given a Name and LookupType" );
+ok( ! $cf->ContextObject, 'No context object gained');
-{
+# The explicit LookupType, ObjectId, and IncludeGlobal -- what most folks want
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', LookupType => RT::Ticket->CustomFieldLookupType,
+ ObjectId => 1, IncludeGlobal => 1 );
+ok($cf->id, "Load now finds it, given a Name, LookupType, ObjectId, IncludeGlobal" );
+ok($cf->ContextObject->id, 'And gains a context obj');
-ok(my $cf = RT::CustomField->new(RT->SystemUser));
+# Look for a queue by name
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', Queue => "General" );
+ok( ! $cf->id, "No IncludeGlobal, so queue by name fails" );
+ok($cf->ContextObject->id, 'But gains a context object');
+# Look for a queue by name, include global
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', Queue => "General", IncludeGlobal => 1 );
+ok($cf->id, "By name, and queue name works with IncludeGlobal" );
+ok($cf->ContextObject->id, 'And gains a context object');
+
+
+
+# A bogus Queue gets you no results, but a warning
+$cf = RT::CustomField->new( RT->SystemUser );
warning_like {
-ok($cf->ValidateType('SelectSingle'));
-} qr/deprecated/;
+ $cf->LoadByName(Name => 'TestingCF', Queue => "Bogus" );
+ ok( ! $cf->id, "With a bogus queue name gets no results" );
+ ok( ! $cf->ContextObject, 'And also no context object');
+} qr/Failed to load RT::Queue 'Bogus'/, "Generates a warning";
+# Ditto by number which is bogus
+$cf = RT::CustomField->new( RT->SystemUser );
warning_like {
-ok($cf->ValidateType('SelectMultiple'));
-} qr/deprecated/;
+ $cf->LoadByName(Name => 'TestingCF', Queue => "9000" );
+ ok( ! $cf->id, "With a bogus queue number gets no results" );
+ ok( ! $cf->ContextObject, 'And also no context object');
+} qr/Failed to load RT::Queue '9000'/, "Generates a warning";
+# But if they also wanted global results, we might have an answer
+$cf = RT::CustomField->new( RT->SystemUser );
warning_like {
-ok(!$cf->ValidateType('SelectFooMultiple'));
-} qr/deprecated/;
+ $cf->LoadByName(Name => 'TestingCF', Queue => "9000", IncludeGlobal => 1 );
+ ok($cf->id, "Bogus queue but IncludeGlobal founds it" );
+ ok( ! $cf->ContextObject, 'But no context object');
+} qr/Failed to load RT::Queue '9000'/, "And generates a warning";
+
+
+# Make it only apply to one queue
+$cf->Load(1);
+my $ocf = RT::ObjectCustomField->new( RT->SystemUser );
+( $ok, $msg ) = $ocf->LoadByCols( CustomField => $cf->id, ObjectId => 0 );
+ok( $ok, "Found global application of CF" );
+( $ok, $msg ) = $ocf->Delete;
+ok( $ok, "...and deleted it");
+( $ok, $msg ) = $ocf->Add( CustomField => $cf->id, ObjectId => 1 );
+ok($ok, "Applied to just queue 1" );
+
+# Looking for it globally with Queue => 0 should fail, gain no context object
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', Queue => 0);
+ok( ! $cf->id, "Load fails to find, given a Name and Queue => 0" );
+ok( ! $cf->ContextObject, 'Context object not set when queue is 0');
+
+# Looking it up by Queue => 1 works fine, and gets context object
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', Queue => 1);
+ok($cf->id, "Load does finds it, given a Name and Queue => 1" );
+ok($cf->ContextObject->id, 'Context object is now set');
+
+# Also find it with IncludeGlobal
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', Queue => 1, IncludeGlobal => 1 );
+ok($cf->id, "Load also finds it, given a Name and Queue => 1 and IncludeGlobal" );
+ok($cf->ContextObject->id, 'Context object is also set');
+
+# The explicit LookupType works
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', LookupType => RT::Ticket->CustomFieldLookupType );
+ok($cf->id, "Load also finds it, given a Name and LookupType" );
+ok( ! $cf->ContextObject, 'But no context object gained');
+
+# Explicit LookupType, ObjectId works
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', LookupType => RT::Ticket->CustomFieldLookupType,
+ ObjectId => 1 );
+ok($cf->id, "Load still finds it, given a Name, LookupType, ObjectId" );
+ok($cf->ContextObject->id, 'And gains a context obj');
+
+# Explicit LookupType, ObjectId works
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', LookupType => RT::Ticket->CustomFieldLookupType,
+ ObjectId => 1, IncludeGlobal => 1 );
+ok($cf->id, "Load also finds it, given a Name, LookupType, ObjectId, and IncludeGlobal" );
+ok($cf->ContextObject->id, 'And gains a context obj');
+
+# Look for a queue by name
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', Queue => "General" );
+ok($cf->id, "Finds it by queue name" );
+ok($cf->ContextObject->id, 'But gains a context object');
+
+# Look for a queue by name, include global
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', Queue => "General", IncludeGlobal => 1 );
+ok($cf->id, "By name, and queue name works with IncludeGlobal" );
+ok($cf->ContextObject->id, 'And gains a context object');
+
+
+
+
+# Change the lookup type to be a _queue_ CF
+($ok, $msg) = $cf->SetLookupType( RT::Queue->CustomFieldLookupType );
+ok($ok, "Changed CF type to be a CF on queues" );
+$ocf = RT::ObjectCustomField->new( RT->SystemUser );
+( $ok, $msg ) = $ocf->Add( CustomField => $cf->id, ObjectId => 0 );
+ok($ok, "Applied globally" );
+
+# Just looking by name gets you CFs of any type
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF');
+ok($cf->id, "Find the CF by name, with no queue" );
+
+# Queue => 0 means "ticket CF", so doesn't find it
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', Queue => 0);
+ok( ! $cf->id, "Wrong lookup type to find with Queue => 0" );
+
+# Queue => 1 and IncludeGlobal also doesn't find it
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', Queue => 0, IncludeGlobal => 1);
+ok( ! $cf->id, "Also doesn't find with Queue => 0 and IncludeGlobal" );
+
+# Find it with the right LookupType
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', LookupType => RT::Queue->CustomFieldLookupType );
+ok($cf->id, "Found for the right lookup type" );
+
+# Found globally
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', LookupType => RT::Queue->CustomFieldLookupType, ObjectId => 0 );
+ok($cf->id, "Found for the right lookup type and ObjectId 0" );
+
+# Also works with Queue instead of ObjectId
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', LookupType => RT::Queue->CustomFieldLookupType, Queue => 0 );
+ok($cf->id, "Found for the right lookup type and Queue 0" );
+
+# Not found without IncludeGlobal
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', LookupType => RT::Queue->CustomFieldLookupType, ObjectId => 1 );
+ok( ! $cf->id, "Not found for ObjectId 1 and no IncludeGlobal" );
+
+# Found with IncludeGlobal
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', LookupType => RT::Queue->CustomFieldLookupType,
+ ObjectId => 1, IncludeGlobal => 1 );
+ok($cf->id, "Found for ObjectId 1 and IncludeGlobal" );
+
+# Found with IncludeGlobal and Queue instead of ObjectId
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', LookupType => RT::Queue->CustomFieldLookupType,
+ ObjectId => 1, IncludeGlobal => 1 );
+ok($cf->id, "Found for Queue 1 and IncludeGlobal" );
+
+
+
+# Change the lookup type to be a _transaction_ CF
+($ok, $msg) = $cf->SetLookupType( RT::Transaction->CustomFieldLookupType );
+ok($ok, "Changed CF type to be a CF on transactions" );
+$ocf = RT::ObjectCustomField->new( RT->SystemUser );
+( $ok, $msg ) = $ocf->Add( CustomField => $cf->id, ObjectId => 0 );
+ok($ok, "Applied globally" );
+
+# Just looking by name gets you CFs of any type
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF');
+ok($cf->id, "Find the CF by name, with no queue" );
+
+# Queue => 0 means "ticket CF", so doesn't find it
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', Queue => 0);
+ok( ! $cf->id, "Wrong lookup type to find with Queue => 0" );
+
+# Queue => 1 and IncludeGlobal also doesn't find it
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', Queue => 0, IncludeGlobal => 1);
+ok( ! $cf->id, "Also doesn't find with Queue => 0 and IncludeGlobal" );
+
+
+# Change the lookup type to be a _user_ CF
+$cf->Load(1);
+($ok, $msg) = $cf->SetLookupType( RT::User->CustomFieldLookupType );
+ok($ok, "Changed CF type to be a CF on users" );
+$ocf = RT::ObjectCustomField->new( RT->SystemUser );
+( $ok, $msg ) = $ocf->Add( CustomField => $cf->id, ObjectId => 0 );
+ok($ok, "Applied globally" );
+
+# Just looking by name gets you CFs of any type
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF');
+ok($cf->id, "Find the CF by name, with no queue" );
+
+# Queue => 0 means "ticket CF", so doesn't find it
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', Queue => 0);
+ok( ! $cf->id, "Wrong lookup type to find with Queue => 0" );
+
+# Queue => 1 and IncludeGlobal also doesn't find it
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', Queue => 0, IncludeGlobal => 1);
+ok( ! $cf->id, "Also doesn't find with Queue => 0 and IncludeGlobal" );
+
+# But RT::User->CustomFieldLookupType does
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', LookupType => RT::User->CustomFieldLookupType );
+ok($cf->id, "User lookuptype does" );
+
+# Also with an explicit global
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', LookupType => RT::User->CustomFieldLookupType, ObjectId => 0 );
+ok($cf->id, "Also with user CF and explicit global" );
+
+
+
+# Add a second, queue-specific CF to test load order
+$cf->Load(1);
+($ok, $msg) = $cf->SetLookupType( RT::Ticket->CustomFieldLookupType );
+ok($ok, "Changed CF type back to be a CF on tickets" );
+$ocf = RT::ObjectCustomField->new( RT->SystemUser );
+( $ok, $msg ) = $ocf->Add( CustomField => $cf->id, ObjectId => 0 );
+ok($ok, "Applied globally" );
+($ok, $msg) = $cf->SetDescription( "Global CF" );
+ok($ok, "Changed CF type back to be a CF on tickets" );
+
+($ok, $msg) = $cf->Create(
+ Name => 'TestingCF',
+ Queue => '1',
+ Description => 'Queue-specific CF',
+ Type => 'SelectSingle'
+);
+ok($ok, "Created second CF successfully");
+
+# If passed just a name, you get the first by id
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF' );
+like($cf->Description, qr/Global/, "Gets the first (global) one if just loading by name" );
+
+# Ditto if also limited to lookuptype
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', LookupType => RT::Ticket->CustomFieldLookupType );
+like($cf->Description, qr/Global/, "Same, if one adds a LookupType" );
+
+# Gets the global with Queue => 0
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', Queue => 0 );
+like($cf->Description, qr/Global/, "Specify Queue => 0 and get global" );
+
+# Gets the queue with Queue => 1
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', Queue => 1 );
+like($cf->Description, qr/Queue/, "Specify Queue => 1 and get the queue" );
+
+# Gets the queue with Queue => 1 and IncludeGlobal
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', Queue => 1, IncludeGlobal => 1 );
+like($cf->Description, qr/Queue/, "Specify Queue => 1 and IncludeGlobal and get the queue" );
+
+
+# Disable one of them
+($ok, $msg) = $cf->SetDisabled(1);
+ok($ok, "Disabled the Queue-specific one");
+
+# With just a name, prefers the non-disabled
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF' );
+like($cf->Description, qr/Global/, "Prefers non-disabled CFs" );
+
+# Still finds the queue one, if asked
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', Queue => 1 );
+like($cf->Description, qr/Queue/, "Still loads the disabled queue CF" );
+
+# Prefers the global one if IncludeGlobal
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', Queue => 1, IncludeGlobal => 1 );
+like($cf->Description, qr/Global/, "Prefers the global one with IncludeGlobal" );
+# IncludeDisabled allows filtering out the disabled one
+$cf = RT::CustomField->new( RT->SystemUser );
+$cf->LoadByName(Name => 'TestingCF', Queue => 1, IncludeDisabled => 0 );
+ok( ! $cf->id, "Doesn't find it if IncludeDisabled => 0" );
-}
+done_testing;
diff --git a/rt/t/api/date.t b/rt/t/api/date.t
index 22c6f1b58..dd22943c1 100644
--- a/rt/t/api/date.t
+++ b/rt/t/api/date.t
@@ -4,7 +4,7 @@ use DateTime;
use warnings;
use strict;
-use RT::Test tests => 175;
+use RT::Test tests => undef;
use RT::User;
use Test::Warn;
@@ -57,7 +57,7 @@ my $current_user;
is($date->Timezone('user'),
'Europe/Moscow',
"in user context still returns user's timezone");
-
+
$current_user->UserObj->__Set( Field => 'Timezone', Value => '');
is_empty($current_user->UserObj->Timezone,
"successfuly changed user's timezone");
@@ -83,6 +83,7 @@ my $current_user;
{
my $date = RT::Date->new(RT->SystemUser);
+ is($date->IsSet,0, "new date isn't set");
is($date->Unix, 0, "new date returns 0 in Unix format");
is($date->Get, '1970-01-01 00:00:00', "default is ISO format");
warning_like {
@@ -207,6 +208,7 @@ my $current_user;
$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->IsSet,1,"Date has been set");
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, 01 Jan 2005 18:10:00 +0300', "RFC2822");
@@ -239,7 +241,7 @@ warning_like
{ # bad format
my $date = RT::Date->new(RT->SystemUser);
$date->Set( Format => 'bad' );
- is($date->Unix, 0, "bad format");
+ ok(!$date->IsSet, "bad format");
} qr{Unknown Date format: bad};
@@ -248,13 +250,26 @@ warning_like
$date->Unix(1);
is($date->ISO, '1970-01-01 00:00:01', "correct value");
- foreach (undef, 0, ''){
+ foreach (undef, 0, '', -5){
$date->Unix(1);
is($date->ISO, '1970-01-01 00:00:01', "correct value");
+ is($date->IsSet,1,"Date has been set to a 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");
+ is($date->IsSet,0,"Date has been unset");
+ }
+
+ foreach (undef, 0, '', -5){
+ $date->Unix(1);
+ is($date->ISO, '1970-01-01 00:00:01', "correct value");
+ is($date->IsSet,1,"Date has been set to a value");
+
+ $date->Unix($_);
+ 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");
+ is($date->IsSet,0,"Date has been unset");
}
}
@@ -265,7 +280,7 @@ my $year = (localtime(time))[5] + 1900;
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");
+ ok(!$date->IsSet, "date was wrong => unix == 0");
# XXX: ISO format has more feature than we suport
# http://www.cl.cam.ac.uk/~mgk25/iso-time.html
@@ -294,14 +309,18 @@ my $year = (localtime(time))[5] + 1900;
$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");
+ warning_like {
+ $date->Set(Format => 'ISO', Value => '2005-13-28 15:10:00');
+ } qr/Invalid date/;
+ ok(!$date->IsSet, "wrong month value");
- $date->Set(Format => 'ISO', Value => '2005-00-28 15:10:00');
- is($date->Unix, 0, "wrong month value");
+ warning_like {
+ $date->Set(Format => 'ISO', Value => '2005-00-28 15:10:00');
+ } qr/Invalid date/;
+ ok(!$date->IsSet, "wrong month value");
$date->Set(Format => 'ISO', Value => '1960-01-28 15:10:00');
- is($date->Unix, 0, "too old, we don't support");
+ ok(!$date->IsSet, "too old, we don't support");
}
{ # set+datemanip format(Time::ParseDate)
@@ -326,7 +345,7 @@ my $year = (localtime(time))[5] + 1900;
warnings_like {
$date->Set(Format => 'unknown', Value => 'weird date');
} qr{Couldn't parse date 'weird date' by Time::ParseDate};
- is($date->Unix, 0, "date was wrong");
+ ok(!$date->IsSet, "date was wrong");
RT->Config->Set( Timezone => 'Europe/Moscow' );
$date->Set(Format => 'unknown', Value => '2005-11-28 15:10:00');
@@ -360,6 +379,34 @@ my $year = (localtime(time))[5] + 1900;
is($date->ISO, '2005-11-28 15:10:00', "YYYY-DD-MM hh:mm:ss");
}
+{ # 'tomorrow 10am' with TZ
+ $current_user->UserObj->__Set( Field => 'Timezone', Value => 'Europe/Moscow');
+
+ set_fixed_time("2012-06-14T15:10:00Z"); # 14th in UTC and Moscow
+ my $date = RT::Date->new( $current_user );
+ $date->Set(Format => 'unknown', Value => 'tomorrow 10am');
+ is($date->ISO, '2012-06-15 06:00:00', "YYYY-DD-MM hh:mm:ss");
+
+ set_fixed_time("2012-06-13T23:10:00Z"); # 13th in UTC and 14th in Moscow
+ $date = RT::Date->new( $current_user );
+ $date->Set(Format => 'unknown', Value => 'tomorrow 10am');
+ is($date->ISO, '2012-06-15 06:00:00', "YYYY-DD-MM hh:mm:ss");
+
+ $current_user->UserObj->__Set( Field => 'Timezone', Value => 'US/Hawaii');
+
+ set_fixed_time("2012-06-14T20:10:00Z"); # 14th in UTC and Hawaii
+ $date = RT::Date->new( $current_user );
+ $date->Set(Format => 'unknown', Value => 'tomorrow 10am');
+ is($date->ISO, '2012-06-15 20:00:00', "YYYY-DD-MM hh:mm:ss");
+
+ set_fixed_time("2012-06-15T05:10:00Z"); # 15th in UTC and 14th in Hawaii
+ $date = RT::Date->new( $current_user );
+ $date->Set(Format => 'unknown', Value => 'tomorrow 10am');
+ is($date->ISO, '2012-06-15 20:00:00', "YYYY-DD-MM hh:mm:ss");
+
+ restore_time();
+}
+
{ # SetToMidnight
my $date = RT::Date->new(RT->SystemUser);
@@ -475,11 +522,11 @@ my $year = (localtime(time))[5] + 1900;
{ # 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(1), '1 second', '1 sec');
+ is($date->DurationAsString(59), '59 seconds', '59 sec');
+ is($date->DurationAsString(60), '1 minute', '1 min');
+ is($date->DurationAsString(60*119), '119 minutes', '119 min');
+ is($date->DurationAsString(60*60*2-1), '120 minutes', '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');
@@ -488,9 +535,9 @@ my $year = (localtime(time))[5] + 1900;
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(60*60*24*366), '1 year', '1 year');
- is($date->DurationAsString(-1), '1 sec ago', '1 sec ago');
+ is($date->DurationAsString(-1), '1 second ago', '1 sec ago');
}
{ # DiffAsString
@@ -502,13 +549,13 @@ my $year = (localtime(time))[5] + 1900;
$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');
+ is($date->DiffAsString(3), '1 second ago', 'diff: 1 sec ago');
+ is($date->DiffAsString(1), '1 second', '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');
+ is($date->DiffAsString($ndate), '1 second ago', 'diff: 1 sec ago');
}
{ # Diff
@@ -523,7 +570,7 @@ my $year = (localtime(time))[5] + 1900;
my $date = RT::Date->new(RT->SystemUser);
$date->SetToNow;
my $diff = $date->AgeAsString;
- like($diff, qr/^(0 sec|[1-5] sec ago)$/, 'close enought');
+ like($diff, qr/^(0 seconds|(1 second|[2-5] seconds) ago)$/, 'close enought');
}
{ # GetWeekday
@@ -550,15 +597,16 @@ my $year = (localtime(time))[5] + 1900;
# set unknown format: edge cases
my $date = RT::Date->new(RT->SystemUser);
$date->Set( Value => 0, Format => 'unknown' );
- is( $date->Unix(), 0, "unix is 0 with Value => 0, Format => 'unknown'" );
+ ok( !$date->IsSet, "unix is 0 with Value => 0, Format => 'unknown'" );
$date->Set( Value => '', Format => 'unknown' );
- is( $date->Unix(), 0, "unix is 0 with Value => '', Format => 'unknown'" );
+ ok( !$date->IsSet, "unix is 0 with Value => '', Format => 'unknown'" );
$date->Set( Value => ' ', Format => 'unknown' );
- is( $date->Unix(), 0, "unix is 0 with Value => ' ', Format => 'unknown'" );
+ ok( !$date->IsSet, "unix is 0 with Value => ' ', Format => 'unknown'" );
}
#TODO: AsString
#TODO: RFC2822, W3CDTF with Timezones
+done_testing;
diff --git a/rt/t/api/db_indexes.t b/rt/t/api/db_indexes.t
new file mode 100644
index 000000000..3c305d84d
--- /dev/null
+++ b/rt/t/api/db_indexes.t
@@ -0,0 +1,165 @@
+use strict;
+use warnings;
+use Test::Warn;
+
+use RT::Test tests => undef;
+
+my $handle = $RT::Handle;
+my $db_type = RT->Config->Get('DatabaseType');
+
+# Pg,Oracle needs DBA
+RT::Test::__reconnect_rt('as dba');
+ok( $handle->dbh->do("ALTER SESSION SET CURRENT_SCHEMA=". RT->Config->Get('DatabaseUser') ) )
+ if $db_type eq 'Oracle';
+
+note "test handle->Indexes method";
+{
+ my %indexes = $handle->Indexes;
+ ok grep $_ eq 'tickets1', @{ $indexes{'tickets'} };
+ ok grep $_ eq 'tickets2', @{ $indexes{'tickets'} };
+ ok grep $_ eq 'users1', @{ $indexes{'users'} };
+ ok grep $_ eq 'users4', @{ $indexes{'users'} };
+}
+
+note "test handle->DropIndex method";
+{
+ my ($status, $msg) = $handle->DropIndex( Table => 'Tickets', Name => 'Tickets1' );
+ ok $status, $msg;
+
+ my %indexes = $handle->Indexes;
+ ok !grep $_ eq 'tickets1', @{ $indexes{'tickets'} };
+
+ ($status, $msg) = $handle->DropIndex( Table => 'Tickets', Name => 'Tickets1' );
+ ok !$status, $msg;
+}
+
+note "test handle->DropIndexIfExists method";
+{
+ my ($status, $msg) = $handle->DropIndexIfExists( Table => 'Tickets', Name => 'Tickets2' );
+ ok $status, $msg;
+
+ my %indexes = $handle->Indexes;
+ ok !grep $_ eq 'tickets2', @{ $indexes{'tickets'} };
+
+ ($status, $msg) = $handle->DropIndexIfExists( Table => 'Tickets', Name => 'Tickets2' );
+ ok $status, $msg;
+}
+
+note "test handle->IndexInfo method";
+{
+ if ($db_type ne 'Oracle' && $db_type ne 'mysql') {
+ my %res = $handle->IndexInfo( Table => 'Attachments', Name => 'Attachments1' );
+ is_deeply(
+ \%res,
+ {
+ Table => 'attachments', Name => 'attachments1',
+ Unique => 0, Functional => 0,
+ Columns => ['parent']
+ }
+ );
+ } else {
+ my %res = $handle->IndexInfo( Table => 'Attachments', Name => 'Attachments2' );
+ is_deeply(
+ \%res,
+ {
+ Table => 'attachments', Name => 'attachments2',
+ Unique => 0, Functional => 0,
+ Columns => ['transactionid']
+ }
+ );
+ }
+
+ my %res = $handle->IndexInfo( Table => 'GroupMembers', Name => 'GroupMembers1' );
+ is_deeply(
+ \%res,
+ {
+ Table => 'groupmembers', Name => 'groupmembers1',
+ Unique => 1, Functional => 0,
+ Columns => ['groupid', 'memberid']
+ }
+ );
+
+ if ( $db_type eq 'Pg' || $db_type eq 'Oracle' ) {
+ %res = $handle->IndexInfo( Table => 'Queues', Name => 'Queues1' );
+ is_deeply(
+ \%res,
+ {
+ Table => 'queues', Name => 'queues1',
+ Unique => 1, Functional => 1,
+ Columns => ['name'],
+ CaseInsensitive => { name => 1 },
+ }
+ );
+ }
+}
+
+note "test ->CreateIndex and ->IndexesThatBeginWith methods";
+{
+ {
+ my ($name, $msg) = $handle->CreateIndex(
+ Table => 'Users', Name => 'test_users1',
+ Columns => ['Organization'],
+ );
+ ok $name, $msg;
+ }
+ {
+ my ($name, $msg) = $handle->CreateIndex(
+ Table => 'Users', Name => 'test_users2',
+ Columns => ['Organization', 'Name'],
+ );
+ ok $name, $msg;
+ }
+
+ my @list = $handle->IndexesThatBeginWith( Table => 'Users', Columns => ['Organization'] );
+ is_deeply([sort map $_->{Name}, @list], [qw(test_users1 test_users2)]);
+
+ my ($status, $msg) = $handle->DropIndex( Table => 'Users', Name => 'test_users1' );
+ ok $status, $msg;
+ ($status, $msg) = $handle->DropIndex( Table => 'Users', Name => 'test_users2' );
+ ok $status, $msg;
+}
+
+note "Test some cases sensitivity aspects";
+{
+ {
+ my %res = $handle->IndexInfo( Table => 'groupmembers', Name => 'groupmembers1' );
+ is_deeply(
+ \%res,
+ {
+ Table => 'groupmembers', Name => 'groupmembers1',
+ Unique => 1, Functional => 0,
+ Columns => ['groupid', 'memberid']
+ }
+ );
+ }
+
+ {
+ my ($status, $msg) = $handle->DropIndex( Table => 'groupmembers', Name => 'groupmembers1' );
+ ok $status, $msg;
+
+ my %indexes = $handle->Indexes;
+ ok !grep $_ eq 'groupmembers1', @{ $indexes{'groupmembers'} };
+ }
+
+ {
+ my ($name, $msg) = $handle->CreateIndex(
+ Table => 'groupmembers', Name => 'groupmembers1',
+ Unique => 1,
+ Columns => ['groupid', 'memberid']
+ );
+ ok $name, $msg;
+
+ my %indexes = $handle->Indexes;
+ ok grep $_ eq 'groupmembers1', @{ $indexes{'groupmembers'} };
+ }
+
+ {
+ my ($status, $msg) = $handle->DropIndexIfExists( Table => 'groupmembers', Name => 'groupmembers1' );
+ ok $status, $msg;
+
+ my %indexes = $handle->Indexes;
+ ok !grep $_ eq 'groupmembers1', @{ $indexes{'groupmembers'} };
+ }
+}
+
+done_testing();
diff --git a/rt/t/api/group-rights.t b/rt/t/api/group-rights.t
index 0494c286e..4f5f03d0d 100644
--- a/rt/t/api/group-rights.t
+++ b/rt/t/api/group-rights.t
@@ -2,7 +2,7 @@ use strict;
use warnings;
use RT::Test nodata => 1, tests => 114;
-RT::Group->AddRights(
+RT::Group->AddRight( General =>
'RTxGroupRight' => 'Just a right for testing rights',
);
diff --git a/rt/t/api/group.t b/rt/t/api/group.t
index d55fc5c4a..f82dfc57e 100644
--- a/rt/t/api/group.t
+++ b/rt/t/api/group.t
@@ -96,7 +96,7 @@ is($group_3->HasMemberRecursively($principal_2), undef, "group 3 has member 2 re
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->id , 4, "user 4 is the fourth principal");
is($u->PrincipalObj->PrincipalType , 'Group' , "Principal 4 is a group");
diff --git a/rt/t/api/groups.t b/rt/t/api/groups.t
index d2dc126dc..c2e7fc583 100644
--- a/rt/t/api/groups.t
+++ b/rt/t/api/groups.t
@@ -2,7 +2,7 @@ use strict;
use warnings;
use RT::Test nodata => 1, tests => 27;
-RT::Group->AddRights(
+RT::Group->AddRight( General =>
'RTxGroupRight' => 'Just a right for testing rights',
);
@@ -49,8 +49,7 @@ 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');
+my $global_admin_cc = RT->System->RoleGroup( 'AdminCc' );
ok($global_admin_cc->id, "Found the global admincc group");
my $groups = RT::Groups->new(RT->SystemUser);
$groups->WithRight(Right => 'OwnTicket', Object => $q);
diff --git a/rt/t/api/i18n_guess.t b/rt/t/api/i18n_guess.t
index a64b2952c..0a99011f2 100644
--- a/rt/t/api/i18n_guess.t
+++ b/rt/t/api/i18n_guess.t
@@ -4,8 +4,8 @@ use warnings;
use RT::Test tests => 16;
-use constant HAS_ENCODE_GUESS => do { local $@; eval { require Encode::Guess; 1 } };
-use constant HAS_ENCODE_DETECT => do { local $@; eval { require Encode::Detect::Detector; 1 } };
+use constant HAS_ENCODE_GUESS => Encode::Guess->require;
+use constant HAS_ENCODE_DETECT => Encode::Detect::Detector->require;
my $string = "\x{442}\x{435}\x{441}\x{442} \x{43f}\x{43e}\x{434}\x{434}\x{435}\x{440}\x{436}\x{43a}\x{430}";
diff --git a/rt/t/api/i18n_mime_encoding.t b/rt/t/api/i18n_mime_encoding.t
new file mode 100644
index 000000000..5ad532ed2
--- /dev/null
+++ b/rt/t/api/i18n_mime_encoding.t
@@ -0,0 +1,32 @@
+use warnings;
+use strict;
+
+use RT::Test nodata => 1, tests => undef;
+use RT::I18N;
+use Test::Warn;
+
+diag "normal mime encoding conversion: utf8 => iso-8859-1";
+{
+ my $mime = MIME::Entity->build(
+ Type => 'text/plain; charset=utf-8',
+ Data => ['À中文'],
+ );
+
+ warning_like {
+ RT::I18N::SetMIMEEntityToEncoding( $mime, 'iso-8859-1', );
+ }
+ [ qr/does not map to iso-8859-1/ ], 'got one "not map" error';
+ is( $mime->stringify_body, 'À中文', 'body is not changed' );
+ is( $mime->head->mime_attr('Content-Type'), 'application/octet-stream' );
+}
+
+diag "mime encoding conversion: utf8 => iso-8859-1";
+{
+ my $mime = MIME::Entity->build(
+ Type => 'text/plain; charset=utf-8',
+ Data => ['À中文'],
+ );
+ is( $mime->stringify_body, 'À中文', 'body is not changed' );
+}
+
+done_testing;
diff --git a/rt/t/api/initialdata.t b/rt/t/api/initialdata.t
new file mode 100644
index 000000000..5856528a3
--- /dev/null
+++ b/rt/t/api/initialdata.t
@@ -0,0 +1,16 @@
+use strict;
+use warnings;
+
+use RT::Test tests => 'no_declare';
+
+# This test script processes the sample initialdata file in
+# ../data/initialdata/initialdata
+# To add initialdata tests, add the data to the initialdata file and it
+# will be processed by this script.
+
+my $initialdata = RT::Test::get_relocatable_file("initialdata" => "..", "data", "initialdata");
+my ($rv, $msg) = RT->DatabaseHandle->InsertData( $initialdata, undef, disconnect_after => 0 );
+ok($rv, "Inserted test data from $initialdata")
+ or diag "Error: $msg";
+
+done_testing(); \ No newline at end of file
diff --git a/rt/t/api/link.t b/rt/t/api/link.t
index a9e54a716..3066388f2 100644
--- a/rt/t/api/link.t
+++ b/rt/t/api/link.t
@@ -1,7 +1,7 @@
use strict;
use warnings;
-use RT::Test nodata => 1, tests => 84;
+use RT::Test nodata => 1, tests => 83;
use RT::Test::Web;
use Test::Warn;
@@ -35,9 +35,7 @@ ok $cid, 'created a ticket #'. $cid or diag "error: $msg";
my ($status, $msg);
clean_links();
- warning_like {
- ($status, $msg) = $parent->AddLink;
- } qr/Base or Target must be specified/, "warned about linking a ticket to itself";
+ ($status, $msg) = $parent->AddLink;
ok(!$status, "didn't create a link: $msg");
warning_like {
diff --git a/rt/t/api/password-types.t b/rt/t/api/password-types.t
index 4cb634248..9eeded499 100644
--- a/rt/t/api/password-types.t
+++ b/rt/t/api/password-types.t
@@ -4,17 +4,29 @@ use warnings;
use RT::Test;
use Digest::MD5;
-my $default = "sha512";
+my $default = "bcrypt";
my $root = RT::User->new(RT->SystemUser);
$root->Load("root");
-# Salted SHA-512 (default)
+# bcrypt (default)
my $old = $root->__Value("Password");
like($old, qr/^\!$default\!/, "Stored as salted $default");
ok($root->IsPassword("password"));
is($root->__Value("Password"), $old, "Unchanged after password check");
+# bcrypt (smaller number of rounds)
+my $salt = Crypt::Eksblowfish::Bcrypt::en_base64("a"x16);
+$root->_Set( Field => "Password", Value => RT::User->_GeneratePassword_bcrypt("smaller", 6, $salt) );
+like($root->__Value("Password"), qr/^\!$default\!06\!/, "Stored with a smaller number of rounds");
+ok($root->IsPassword("smaller"), "Smaller number of bcrypt rounds works");
+like($root->__Value("Password"), qr/^\!$default\!10\!/, "And is now upgraded to salted $default");
+
+# Salted SHA-512, one round
+$root->_Set( Field => "Password", Value => RT::User->_GeneratePassword_sha512("other", "salt") );
+ok($root->IsPassword("other"), "SHA-512 password works");
+like($root->__Value("Password"), qr/^\!$default\!/, "And is now upgraded to salted $default");
+
# Crypt
$root->_Set( Field => "Password", Value => crypt("something", "salt"));
ok($root->IsPassword("something"), "crypt()ed password works");
diff --git a/rt/t/api/queue.t b/rt/t/api/queue.t
index 07b8ed479..71efb4d39 100644
--- a/rt/t/api/queue.t
+++ b/rt/t/api/queue.t
@@ -2,7 +2,7 @@
use strict;
use warnings;
use RT;
-use RT::Test nodata => 1, tests => 24;
+use RT::Test nodata => 1, tests => undef;
{
@@ -58,8 +58,7 @@ 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(my $group = $Queue->RoleGroup('Requestor'));
ok ($group->Id, "Found the requestors object for this Queue");
{
@@ -79,13 +78,12 @@ ok ($Queue->IsWatcher(Type => 'Cc', PrincipalId => $bob->PrincipalId), "The Queu
"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'));
+$group = $Queue->RoleGroup('Cc');
ok ($group->Id, "Found the cc object for this Queue");
-$group = RT::Group->new(RT->SystemUser);
-ok($group->LoadQueueRoleGroup(Queue => $id, Type=> 'AdminCc'));
+$group = $Queue->RoleGroup('AdminCc');
ok ($group->Id, "Found the AdminCc object for this Queue");
}
+done_testing;
diff --git a/rt/t/api/record.t b/rt/t/api/record.t
index 4b6b0b89c..7abd41ca5 100644
--- a/rt/t/api/record.t
+++ b/rt/t/api/record.t
@@ -16,8 +16,8 @@ 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");
+is($ticket->RecordType, 'Ticket', "Ticket returns correct typestring");
+is($group->RecordType, 'Group', "Group returns correct typestring");
}
diff --git a/rt/t/api/reminder-permissions.t b/rt/t/api/reminder-permissions.t
new file mode 100644
index 000000000..8253d67af
--- /dev/null
+++ b/rt/t/api/reminder-permissions.t
@@ -0,0 +1,49 @@
+use strict;
+use warnings;
+use RT::Test tests => 9;
+
+my $user_a = RT::Test->load_or_create_user(
+ Name => 'user_a',
+ Password => 'password',
+);
+
+ok( $user_a && $user_a->id, 'created user_a' );
+ok(
+ RT::Test->add_rights(
+ {
+ Principal => $user_a,
+ Right => [qw/SeeQueue CreateTicket ShowTicket OwnTicket/]
+ },
+ ),
+ 'add basic rights for user_a'
+);
+
+my $ticket = RT::Test->create_ticket(
+ Subject => 'test reminder permission',
+ Queue => 'General',
+);
+ok( $ticket->id, 'created a ticket' );
+$ticket->CurrentUser($user_a);
+
+my ( $status, $msg ) = $ticket->Reminders->Add(
+ Subject => 'user a reminder',
+ Owner => $user_a->id,
+);
+ok( !$status, "couldn't create reminders without ModifyTicket: $msg" );
+
+ok(
+ RT::Test->add_rights(
+ {
+ Principal => $user_a,
+ Right => [qw/ModifyTicket/]
+ },
+ ),
+ 'add ModifyTicket right for user_a'
+);
+
+( $status, $msg ) = $ticket->Reminders->Add(
+ Subject => 'user a reminder',
+ Owner => $user_a->id,
+);
+ok( $status, "created a reminder with ModifyTicket: $msg" );
+
diff --git a/rt/t/api/rights.t b/rt/t/api/rights.t
index 5cf3a0008..a6346a737 100644
--- a/rt/t/api/rights.t
+++ b/rt/t/api/rights.t
@@ -29,10 +29,8 @@ ok $user && $user->id, 'loaded or created user';
}
{
- my $group = RT::Group->new( RT->SystemUser );
- ok( $group->LoadQueueRoleGroup( Queue => $queue->id, Type=> 'Owner' ),
- "load queue owners role group"
- );
+ my $group = $queue->RoleGroup( 'Owner' );
+ ok( $group->Id, "load queue owners role group" );
my $ace = RT::ACE->new( RT->SystemUser );
my ($ace_id, $msg) = $group->PrincipalObj->GrantRight(
Right => 'ReplyToTicket', Object => $queue
@@ -84,10 +82,8 @@ my $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 $group = $queue->RoleGroup( 'AdminCc' );
+ ok( $group->Id, "load queue AdminCc role group" );
my $ace = RT::ACE->new( RT->SystemUser );
my ($ace_id, $msg) = $group->PrincipalObj->GrantRight(
Right => 'ModifyTicket', Object => $queue
diff --git a/rt/t/api/rtname.t b/rt/t/api/rtname.t
index 8b7b54bd1..f2bffd559 100644
--- a/rt/t/api/rtname.t
+++ b/rt/t/api/rtname.t
@@ -1,7 +1,7 @@
use strict;
use warnings;
-use RT::Test nodata => 1, tests => 9;
+use RT::Test nodata => 1, tests => 12;
use RT::Interface::Email;
@@ -31,3 +31,8 @@ is(RT::Interface::Email::ParseTicketId("[site #123] test"), 123);
is(RT::Interface::Email::ParseTicketId("[newsite #123] test"), 123);
is(RT::Interface::Email::ParseTicketId("[othersite #123] test"), undef);
+# Parens work fine
+RT->Config->Set( EmailSubjectTagRegex => qr/(new|)(site)/ );
+is(RT::Interface::Email::ParseTicketId("[site #123] test"), 123);
+is(RT::Interface::Email::ParseTicketId("[newsite #123] test"), 123);
+is(RT::Interface::Email::ParseTicketId("[othersite #123] test"), undef);
diff --git a/rt/t/api/savedsearch.t b/rt/t/api/savedsearch.t
index 0aa67eeda..2e924bf7b 100644
--- a/rt/t/api/savedsearch.t
+++ b/rt/t/api/savedsearch.t
@@ -13,9 +13,9 @@ use Test::Warn;
my $searchuser = RT::User->new(RT->SystemUser);
my ($ret, $msg) = $searchuser->Create(Name => 'searchuser'.$$,
- Privileged => 1,
- EmailAddress => "searchuser\@p$$.example.com",
- RealName => 'Search user');
+ Privileged => 1,
+ EmailAddress => "searchuser\@p$$.example.com",
+ RealName => 'Search user');
ok($ret, "created searchuser: $msg");
$searchuser->PrincipalObj->GrantRight(Right => 'LoadSavedSearch');
$searchuser->PrincipalObj->GrantRight(Right => 'CreateSavedSearch');
@@ -26,9 +26,9 @@ my $ingroup = RT::Group->new(RT->SystemUser);
$ingroup->CreateUserDefinedGroup(Name => 'searchgroup1'.$$);
$ingroup->AddMember($searchuser->Id);
$searchuser->PrincipalObj->GrantRight(Right => 'EditSavedSearches',
- Object => $ingroup);
+ Object => $ingroup);
$searchuser->PrincipalObj->GrantRight(Right => 'ShowSavedSearches',
- Object => $ingroup);
+ Object => $ingroup);
# This is the group whose searches searchuser should not be able to see.
my $outgroup = RT::Group->new(RT->SystemUser);
@@ -44,9 +44,9 @@ $searchuser->PrincipalObj->GrantRight(Right => 'OwnTicket', Object => $queue);
my $ticket = RT::Ticket->new(RT->SystemUser);
$ticket->Create(Queue => $queue->Id,
- Requestor => [ $searchuser->Name ],
- Owner => $searchuser,
- Subject => 'saved search test');
+ Requestor => [ $searchuser->Name ],
+ Owner => $searchuser,
+ Subject => 'saved search test');
# Now start the search madness.
@@ -67,41 +67,41 @@ my $format = '\' <b><a href="/Ticket/Display.html?id=__id__">__id__</a></b>/TI
my $mysearch = RT::SavedSearch->new($curruser);
($ret, $msg) = $mysearch->Save(Privacy => 'RT::User-' . $searchuser->Id,
- Type => 'Ticket',
- Name => 'owned by me',
- SearchParams => {'Format' => $format,
- 'Query' => "Owner = '"
- . $searchuser->Name
- . "'"});
+ Type => 'Ticket',
+ Name => 'owned by me',
+ SearchParams => {'Format' => $format,
+ 'Query' => "Owner = '"
+ . $searchuser->Name
+ . "'"});
ok($ret, "mysearch was created");
my $groupsearch = RT::SavedSearch->new($curruser);
($ret, $msg) = $groupsearch->Save(Privacy => 'RT::Group-' . $ingroup->Id,
- Type => 'Ticket',
- Name => 'search queue',
- SearchParams => {'Format' => $format,
- 'Query' => "Queue = '"
- . $queue->Name . "'"});
+ Type => 'Ticket',
+ Name => 'search queue',
+ SearchParams => {'Format' => $format,
+ 'Query' => "Queue = '"
+ . $queue->Name . "'"});
ok($ret, "groupsearch was created");
my $othersearch = RT::SavedSearch->new($curruser);
($ret, $msg) = $othersearch->Save(Privacy => 'RT::Group-' . $outgroup->Id,
- Type => 'Ticket',
- Name => 'searchuser requested',
- SearchParams => {'Format' => $format,
- 'Query' =>
- "Requestor.Name LIKE 'search'"});
+ Type => 'Ticket',
+ Name => 'searchuser requested',
+ SearchParams => {'Format' => $format,
+ 'Query' =>
+ "Requestor.Name LIKE 'search'"});
ok(!$ret, "othersearch NOT created");
like($msg, qr/Failed to load object for/, "...for the right reason");
$othersearch = RT::SavedSearch->new(RT->SystemUser);
($ret, $msg) = $othersearch->Save(Privacy => 'RT::Group-' . $outgroup->Id,
- Type => 'Ticket',
- Name => 'searchuser requested',
- SearchParams => {'Format' => $format,
- 'Query' =>
- "Requestor.Name LIKE 'search'"});
+ Type => 'Ticket',
+ Name => 'searchuser requested',
+ SearchParams => {'Format' => $format,
+ 'Query' =>
+ "Requestor.Name LIKE 'search'"});
ok($ret, "othersearch created by systemuser");
# Now try to load some searches.
@@ -148,8 +148,8 @@ warning_like {
isnt($loadedsearch4->Id, $othersearch->Id, "Did not load othersearch");
# Try to update an existing search.
-$loadedsearch1->Update( SearchParams => {'Format' => $format,
- 'Query' => "Queue = '" . $queue->Name . "'" } );
+$loadedsearch1->Update( SearchParams => {'Format' => $format,
+ 'Query' => "Queue = '" . $queue->Name . "'" } );
like($loadedsearch1->GetParameter('Query'), qr/Queue/,
"Updated mysearch parameter");
is($loadedsearch1->Type, 'Ticket', "mysearch is still for tickets");
@@ -162,8 +162,8 @@ like($mysearch->GetParameter('Query'), qr/Queue/, "other mysearch object updated
my $genericsearch = RT::SavedSearch->new($curruser);
$genericsearch->Save(Name => 'generic search',
- Type => 'all',
- SearchParams => {'Query' => "Queue = 'General'"});
+ Type => 'all',
+ SearchParams => {'Query' => "Queue = 'General'"});
my $ticketsearches = RT::SavedSearches->new($curruser);
$ticketsearches->LimitToPrivacy('RT::User-'.$curruser->Id, 'Ticket');
diff --git a/rt/t/api/scrip.t b/rt/t/api/scrip.t
index eb543476b..d6019a082 100644
--- a/rt/t/api/scrip.t
+++ b/rt/t/api/scrip.t
@@ -1,52 +1,44 @@
use strict;
use warnings;
-use RT;
-use RT::Test tests => 25;
+use RT::Test;
+my $queue = RT::Test->load_or_create_queue( Name => 'General' );
+ok $queue && $queue->id, 'loaded or created queue';
+note 'basic scrips functionality test: create+execute';
{
-
-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'
+ my $s1 = RT::Scrip->new(RT->SystemUser);
+ my ($val, $msg) = $s1->Create(
+ Queue => $queue->Id,
+ ScripAction => 'User Defined',
+ ScripCondition => 'User Defined',
+ CustomIsApplicableCode => '$self->TicketObj->Subject =~ /fire/? 1 : 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");
+ ok($val,$msg);
+ my $ticket = RT::Ticket->new(RT->SystemUser);
+ my ($tv,$ttv,$tm) = $ticket->Create(
+ Queue => $queue->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 => $queue->Id,
+ Subject => "hair in water",
+ );
+ ok($t2v, $t2m);
+ isnt ($ticket2->Priority , '87', "Ticket priority is set right");
}
-
+note 'modify properties of a scrip';
{
my $scrip = RT::Scrip->new($RT::SystemUser);
my ( $val, $msg ) = $scrip->Create(
@@ -117,3 +109,158 @@ isnt ($ticket2->Priority , '87', "Ticket priority is set right");
ok( $scrip->Delete, 'delete the scrip' );
}
+
+my $queue_B = RT::Test->load_or_create_queue( Name => 'B' );
+ok $queue_B && $queue_B->id, 'loaded or created queue';
+
+note 'check creation errors vs. templates';
+{
+ my $scrip = RT::Scrip->new(RT->SystemUser);
+ my ($status, $msg) = $scrip->Create(
+ Queue => $queue->id,
+ ScripAction => 'User Defined',
+ ScripCondition => 'User Defined',
+ Template => 'not exist',
+ );
+ ok(!$status, "couldn't create scrip, not existing template");
+
+ ($status, $msg) = $scrip->Create(
+ ScripAction => 'User Defined',
+ ScripCondition => 'User Defined',
+ Template => 'not exist',
+ );
+ ok(!$status, "couldn't create scrip, not existing template");
+
+ ($status, $msg) = $scrip->Create(
+ Queue => $queue->id,
+ ScripAction => 'User Defined',
+ ScripCondition => 'User Defined',
+ Template => 54321,
+ );
+ ok(!$status, "couldn't create scrip, not existing template");
+
+ ($status, $msg) = $scrip->Create(
+ ScripAction => 'User Defined',
+ ScripCondition => 'User Defined',
+ Template => 54321,
+ );
+ ok(!$status, "couldn't create scrip, not existing template");
+
+ my $template = RT::Template->new( RT->SystemUser );
+ ($status, $msg) = $template->Create( Queue => $queue->id, Name => 'bar' );
+ ok $status, 'created a template';
+
+ ($status, $msg) = $scrip->Create(
+ ScripAction => 'User Defined',
+ ScripCondition => 'User Defined',
+ Template => $template->id,
+ );
+ ok(!$status, "couldn't create scrip, wrong template");
+
+ ($status, $msg) = $scrip->Create(
+ Queue => $queue_B->id,
+ ScripAction => 'User Defined',
+ ScripCondition => 'User Defined',
+ Template => $template->id,
+ );
+ ok(!$status, "couldn't create scrip, wrong template");
+}
+
+note 'check applications vs. templates';
+{
+ my $template = RT::Template->new( RT->SystemUser );
+ my ($status, $msg) = $template->Create( Queue => $queue->id, Name => 'foo' );
+ ok $status, 'created a template';
+
+ my $scrip = RT::Scrip->new(RT->SystemUser);
+ ($status, $msg) = $scrip->Create(
+ Queue => $queue->Id,
+ ScripAction => 'User Defined',
+ ScripCondition => 'User Defined',
+ Template => 'foo',
+ CustomIsApplicableCode => "1;",
+ CustomPrepareCode => "1;",
+ CustomCommitCode => "1;",
+ );
+ ok($status, 'created a scrip') or diag "error: $msg";
+ RT::Test->object_scrips_are($scrip, [$queue], [0, $queue_B]);
+
+ ($status, $msg) = $scrip->AddToObject( $queue_B->id );
+ ok(!$status, $msg);
+ RT::Test->object_scrips_are($scrip, [$queue], [0, $queue_B]);
+ my $obj_scrip = RT::ObjectScrip->new( RT->SystemUser );
+ ok($obj_scrip->LoadByCols( Scrip => $scrip->id, ObjectId => $queue->id ));
+ is($obj_scrip->Stage, 'TransactionCreate');
+ is($obj_scrip->FriendlyStage, 'Normal');
+
+ $template = RT::Template->new( RT->SystemUser );
+ ($status, $msg) = $template->Create( Queue => $queue_B->id, Name => 'foo' );
+ ok $status, 'created a template';
+
+ ($status, $msg) = $scrip->AddToObject( $queue_B->id );
+ ok($status, 'added scrip to another queue');
+ RT::Test->object_scrips_are($scrip, [$queue, $queue_B], [0]);
+
+ ($status, $msg) = $scrip->RemoveFromObject( $queue_B->id );
+ ok($status, 'removed scrip from queue');
+
+ ($status, $msg) = $template->Delete;
+ ok $status, 'deleted template foo in queue B';
+
+ ($status, $msg) = $scrip->AddToObject( $queue_B->id );
+ ok(!$status, $msg);
+ RT::Test->object_scrips_are($scrip, [$queue], [0, $queue_B]);
+
+ ($status, $msg) = $template->Create( Queue => 0, Name => 'foo' );
+ ok $status, 'created a global template';
+
+ ($status, $msg) = $scrip->AddToObject( $queue_B->id );
+ ok($status, 'added scrip');
+ RT::Test->object_scrips_are($scrip, [$queue, $queue_B], [0]);
+}
+
+note 'basic check for disabling scrips';
+{
+ my $scrip = RT::Scrip->new(RT->SystemUser);
+ my ($status, $msg) = $scrip->Create(
+ Queue => $queue->id,
+ ScripCondition => 'On Create',
+ ScripAction => 'User Defined',
+ CustomPrepareCode => 'return 1',
+ CustomCommitCode => '$self->TicketObj->SetPriority("87"); return 1',
+ Template => 'Blank'
+ );
+ ok($status, "created scrip");
+ is($scrip->Disabled, 0, "not disabled");
+
+ {
+ my $ticket = RT::Ticket->new(RT->SystemUser);
+ my ($tid, undef, $msg) = $ticket->Create(
+ Queue => $queue->id,
+ Subject => "test",
+ );
+ ok($tid, "created ticket") or diag "error: $msg";
+ is ($ticket->Priority , '87', "Ticket priority is set right");
+ }
+
+ ($status,$msg) = $scrip->SetDisabled(1);
+ is($scrip->Disabled, 1, "disabled");
+
+ {
+ my $ticket = RT::Ticket->new(RT->SystemUser);
+ my ($tid, undef, $msg) = $ticket->Create(
+ Queue => $queue->id,
+ Subject => "test",
+ );
+ ok($tid, "created ticket") or diag "error: $msg";
+ isnt ($ticket->Priority , '87', "Ticket priority is set right");
+ }
+
+ is($scrip->FriendlyStage('TransactionCreate'), 'Normal',
+ 'Correct stage wording for TransactionCreate');
+ is($scrip->FriendlyStage('TransactionBatch'), 'Batch',
+ 'Correct stage wording for TransactionBatch');
+ RT->Config->Set('UseTransactionBatch', 0);
+ is($scrip->FriendlyStage('TransactionBatch'), 'Batch (disabled by config)',
+ 'Correct stage wording for TransactionBatch with UseTransactionBatch disabled');
+}
diff --git a/rt/t/api/scrip_order.t b/rt/t/api/scrip_order.t
index 6fba7e579..689b55970 100644
--- a/rt/t/api/scrip_order.t
+++ b/rt/t/api/scrip_order.t
@@ -2,52 +2,271 @@
use strict;
use warnings;
-use RT;
-use RT::Test tests => 7;
-
-
-
-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");
+use RT::Test tests => 204;
+
+my $queue = RT::Test->load_or_create_queue( Name => 'General' );
+ok $queue && $queue->id, 'loaded or created queue';
+
+note "check that execution order reflects sort order";
+{
+ my $ten = main->create_scrip_ok(
+ Description => "Set priority to 10",
+ Queue => $queue->id,
+ CustomCommitCode => '$self->TicketObj->SetPriority(10);',
+ );
+
+ my $five = main->create_scrip_ok(
+ Description => "Set priority to 5",
+ Queue => $queue->id,
+ CustomCommitCode => '$self->TicketObj->SetPriority(5);',
+ );
+
+ my $ticket = RT::Ticket->new(RT->SystemUser);
+ my ($id, $msg) = $ticket->Create(
+ Queue => $queue->id,
+ Subject => "Scrip order test $$",
+ );
+ ok($ticket->id, "Created ticket? id=$id");
+ is($ticket->Priority , 5, "By default newer scrip is last");
+
+ main->move_scrip_ok( $five, $queue->id, 'up' );
+
+ $ticket = RT::Ticket->new(RT->SystemUser);
+ ($id, $msg) = $ticket->Create(
+ Queue => $queue->id,
+ Subject => "Scrip order test $$",
+ );
+ ok($ticket->id, "Created ticket? id=$id");
+ is($ticket->Priority , 10, "Moved scrip and result is different");
+}
+
+my $queue_B = RT::Test->load_or_create_queue( Name => 'Other' );
+ok $queue_B && $queue_B->id, 'loaded or created queue';
+
+note "move around two local scrips";
+{
+ main->delete_all_scrips();
+
+ my @scrips;
+ push @scrips, main->create_scrip_ok( Queue => $queue->id );
+ push @scrips, main->create_scrip_ok( Queue => $queue->id );
+ main->check_scrips_order(\@scrips, [$queue]);
+
+ main->move_scrip_ok( $scrips[0], $queue->id, 'down' );
+ @scrips = @scrips[1, 0];
+ main->check_scrips_order(\@scrips, [$queue]);
+
+ main->move_scrip_ok( $scrips[0], $queue->id, 'down' );
+ @scrips = @scrips[1, 0];
+ main->check_scrips_order(\@scrips, [$queue]);
+
+ main->move_scrip_ok( $scrips[1], $queue->id, 'up' );
+ @scrips = @scrips[1, 0];
+ main->check_scrips_order(\@scrips, [$queue]);
+
+ main->move_scrip_ok( $scrips[1], $queue->id, 'up' );
+ @scrips = @scrips[1, 0];
+ main->check_scrips_order(\@scrips, [$queue]);
+}
+
+note "move around two global scrips";
+{
+ main->delete_all_scrips();
+
+ my @scrips;
+ push @scrips, main->create_scrip_ok( Queue => 0 );
+ push @scrips, main->create_scrip_ok( Queue => 0 );
+ main->check_scrips_order(\@scrips, [$queue]);
+
+ main->move_scrip_ok( $scrips[0], 0, 'down' );
+ @scrips = @scrips[1, 0];
+ main->check_scrips_order(\@scrips, [$queue]);
+
+ main->move_scrip_ok( $scrips[0], 0, 'down' );
+ @scrips = @scrips[1, 0];
+ main->check_scrips_order(\@scrips, [$queue]);
+
+ main->move_scrip_ok( $scrips[1], 0, 'up' );
+ @scrips = @scrips[1, 0];
+ main->check_scrips_order(\@scrips, [$queue]);
+
+ main->move_scrip_ok( $scrips[1], 0, 'up' );
+ @scrips = @scrips[1, 0];
+ main->check_scrips_order(\@scrips, [$queue]);
+}
+
+note "move local scrip below global";
+{
+ main->delete_all_scrips();
+ my @scrips;
+ push @scrips, main->create_scrip_ok( Queue => $queue->id );
+ push @scrips, main->create_scrip_ok( Queue => $queue_B->id );
+ push @scrips, main->create_scrip_ok( Queue => 0 );
+ push @scrips, main->create_scrip_ok( Queue => $queue->id );
+ main->check_scrips_order(\@scrips, [$queue, $queue_B]);
+
+ main->move_scrip_ok( $scrips[0], $queue->id, 'down' );
+ @scrips = @scrips[1, 2, 0, 3];
+ main->check_scrips_order(\@scrips, [$queue, $queue_B]);
+}
+
+note "move local scrip above global";
+{
+ main->delete_all_scrips();
+ my @scrips;
+ push @scrips, main->create_scrip_ok( Queue => $queue_B->id );
+ push @scrips, main->create_scrip_ok( Queue => 0 );
+ push @scrips, main->create_scrip_ok( Queue => $queue->id );
+ push @scrips, main->create_scrip_ok( Queue => $queue_B->id );
+ main->check_scrips_order(\@scrips, [$queue, $queue_B]);
+
+ main->move_scrip_ok( $scrips[-1], $queue_B->id, 'up' );
+ @scrips = @scrips[0, 3, 1, 2];
+ main->check_scrips_order(\@scrips, [$queue, $queue_B]);
+}
+
+note "move global scrip down with local in between";
+{
+ main->delete_all_scrips();
+ my @scrips;
+ push @scrips, main->create_scrip_ok( Queue => 0 );
+ push @scrips, main->create_scrip_ok( Queue => $queue_B->id );
+ push @scrips, main->create_scrip_ok( Queue => $queue->id );
+ push @scrips, main->create_scrip_ok( Queue => 0 );
+ push @scrips, main->create_scrip_ok( Queue => $queue->id );
+ main->check_scrips_order(\@scrips, [$queue, $queue_B]);
+
+ main->move_scrip_ok( $scrips[0], 0, 'down' );
+ @scrips = @scrips[1, 2, 3, 0, 4];
+ main->check_scrips_order(\@scrips, [$queue, $queue_B]);
+}
+
+note "move global scrip up with local in between";
+{
+ main->delete_all_scrips();
+ my @scrips;
+ push @scrips, main->create_scrip_ok( Queue => $queue->id );
+ push @scrips, main->create_scrip_ok( Queue => 0 );
+ push @scrips, main->create_scrip_ok( Queue => $queue_B->id );
+ push @scrips, main->create_scrip_ok( Queue => $queue->id );
+ push @scrips, main->create_scrip_ok( Queue => 0 );
+ main->check_scrips_order(\@scrips, [$queue, $queue_B]);
+
+ main->move_scrip_ok( $scrips[-1], 0, 'up' );
+ @scrips = @scrips[0, 4, 1, 2, 3];
+ main->check_scrips_order(\@scrips, [$queue, $queue_B]);
+}
+
+note "delete scrips one by one";
+{
+ main->delete_all_scrips();
+ my @scrips;
+ push @scrips, main->create_scrip_ok( Queue => $queue->id );
+ push @scrips, main->create_scrip_ok( Queue => $queue_B->id );
+ push @scrips, main->create_scrip_ok( Queue => 0 );
+ push @scrips, main->create_scrip_ok( Queue => $queue_B->id );
+ push @scrips, main->create_scrip_ok( Queue => $queue->id );
+ push @scrips, main->create_scrip_ok( Queue => 0 );
+ main->check_scrips_order(\@scrips, [$queue, $queue_B]);
+
+ foreach my $idx (3, 2, 0 ) {
+ $_->Delete foreach splice @scrips, $idx, 1;
+ main->check_scrips_order(\@scrips, [$queue, $queue_B]);
+ }
+}
+
+sub create_scrip_ok {
+ local $Test::Builder::Level = $Test::Builder::Level + 1;
+ my $self = shift;
+ my %args = (
+ ScripCondition => 'On Create',
+ ScripAction => 'User Defined',
+ CustomPrepareCode => 'return 1',
+ CustomCommitCode => 'return 1',
+ Template => 'Blank',
+ Stage => 'TransactionCreate',
+ @_
+ );
+
+ my $scrip = RT::Scrip->new( RT->SystemUser );
+ my ($id, $msg) = $scrip->Create( %args );
+ ok($id, "Created scrip") or diag "error: $msg";
+
+ return $scrip;
+}
+
+sub delete_all_scrips {
+ local $Test::Builder::Level = $Test::Builder::Level + 1;
+ my $self = shift;
+ my $scrips = RT::Scrips->new( RT->SystemUser );
+ $scrips->UnLimit;
+ $_->Delete foreach @{ $scrips->ItemsArrayRef };
+}
+
+sub move_scrip_ok {
+ local $Test::Builder::Level = $Test::Builder::Level + 1;
+ my $self = shift;
+ my ($scrip, $queue, $dir) = @_;
+
+ my $rec = RT::ObjectScrip->new( RT->SystemUser );
+ $rec->LoadByCols( Scrip => $scrip->id, ObjectId => $queue );
+ ok $rec->id, 'found application of the scrip';
+
+ my $method = 'Move'. ucfirst lc $dir;
+ my ($status, $msg) = $rec->$method();
+ ok $status, "moved scrip $dir" or diag "error: $msg";
+}
+
+sub check_scrips_order {
+ local $Test::Builder::Level = $Test::Builder::Level + 1;
+ my $self = shift;
+ my $scrips = shift;
+ my $queues = shift;
+
+ foreach my $qid ( 0, map $_->id, @$queues ) {
+ my $list = RT::Scrips->new( RT->SystemUser );
+ $list->LimitToGlobal;
+ $list->LimitToQueue( $qid ) if $qid;
+ $list->ApplySortOrder;
+ is_deeply(
+ [map $_->id, @{ $list->ItemsArrayRef } ],
+ [map $_->id, grep $_->IsAdded( $qid ) || $_->IsGlobal, @$scrips],
+ 'list of scrips match expected'
+ )
+ }
+
+ foreach my $qid ( map $_->id, @$queues ) {
+ my $list = RT::ObjectScrips->new( RT->SystemUser );
+ $list->LimitToObjectId( 0 );
+ $list->LimitToObjectId( $qid );
+
+ my %so;
+ $so{ $_->SortOrder }++ foreach @{ $list->ItemsArrayRef };
+ ok( !grep( {$_ != 1} values %so), 'no dublicate order' );
+ }
+ {
+ my $list = RT::ObjectScrips->new( RT->SystemUser );
+ $list->UnLimit;
+ $list->OrderBy( FIELD => 'SortOrder', ORDER => 'ASC' );
+
+ my $prev;
+ foreach my $rec ( @{ $list->ItemsArrayRef } ) {
+ my $so = $rec->SortOrder;
+ do { $prev = $so; next } unless defined $prev;
+
+ ok $so == $prev || $so == $prev+1, "sequential order";
+ $prev = $so;
+ }
+ }
+}
+
+sub dump_sort_order {
+
+ diag " id oid so";
+ diag join "\n", map { join "\t", @$_ } map @$_, $RT::Handle->dbh->selectall_arrayref(
+ "select Scrip, ObjectId, SortOrder from ObjectScrips ORDER BY SortOrder"
+ );
+
+}
diff --git a/rt/t/api/searchbuilder.t b/rt/t/api/searchbuilder.t
index 84568718d..9237dcd37 100644
--- a/rt/t/api/searchbuilder.t
+++ b/rt/t/api/searchbuilder.t
@@ -20,7 +20,7 @@ ok( $queues->UnLimit(),'Unlimited the result set of the queues object');
my $items = $queues->ItemsArrayRef();
my @items = @{$items};
-ok($queues->NewItem->_Accessible('Name','read'));
+ok($queues->RecordClass->_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));
diff --git a/rt/t/api/system-available-rights.t b/rt/t/api/system-available-rights.t
new file mode 100644
index 000000000..d7b6f5e8d
--- /dev/null
+++ b/rt/t/api/system-available-rights.t
@@ -0,0 +1,65 @@
+use strict;
+use warnings;
+
+use RT::Test tests => undef;
+use Set::Tiny;
+
+my @warnings;
+local $SIG{__WARN__} = sub {
+ push @warnings, "@_";
+};
+
+my $requestor = RT::Group->new( RT->SystemUser );
+$requestor->LoadRoleGroup(
+ Object => RT->System,
+ Name => "Requestor",
+);
+ok $requestor->id, "Loaded global requestor role group";
+
+$requestor = $requestor->PrincipalObj;
+ok $requestor->id, "Loaded global requestor role group principal";
+
+note "Try granting an article right to a system role group";
+{
+ my ($ok, $msg) = $requestor->GrantRight(
+ Right => "ShowArticle",
+ Object => RT->System,
+ );
+ ok !$ok, "Couldn't grant nonsensical right to global Requestor role: $msg";
+ like shift @warnings, qr/Couldn't validate right name.*?ShowArticle/;
+
+ ($ok, $msg) = $requestor->GrantRight(
+ Right => "ShowTicket",
+ Object => RT->System,
+ );
+ ok $ok, "Granted queue right to global queue role: $msg";
+
+ ($ok, $msg) = RT->PrivilegedUsers->PrincipalObj->GrantRight(
+ Right => "ShowArticle",
+ Object => RT->System,
+ );
+ ok $ok, "Granted article right to non-role global group: $msg";
+
+ reset_rights();
+}
+
+note "AvailableRights";
+{
+ my @available = (
+ [ keys %{RT->System->AvailableRights} ],
+ [ keys %{RT->System->AvailableRights( $requestor )} ],
+ );
+
+ my $all = Set::Tiny->new( @{$available[0]} );
+ my $role = Set::Tiny->new( @{$available[1]} );
+
+ ok $role->is_proper_subset($all), "role rights are a proper subset of all";
+}
+
+ok !@warnings, "No uncaught warnings"
+ or diag explain \@warnings;
+
+# for clarity
+sub reset_rights { RT::Test->set_rights() }
+
+done_testing;
diff --git a/rt/t/api/system.t b/rt/t/api/system.t
index f1100d332..f3d9226cf 100644
--- a/rt/t/api/system.t
+++ b/rt/t/api/system.t
@@ -2,8 +2,18 @@
use strict;
use warnings;
use RT;
-use RT::Test nodata => 1, tests => 7;
+use RT::Test nodata => 1, tests => 16;
+BEGIN{
+ use_ok('RT::System');
+}
+
+# Skipping most of the methods added just to make RT::System
+# look like RT::Record.
+
+can_ok('RT::System', qw( AvailableRights RightCategories AddRight
+ id Id SubjectTag Name QueueCacheNeedsUpdate AddUpgradeHistory
+ UpgradeHistory ));
{
@@ -15,18 +25,50 @@ ok ($rights->{'CreateTicket'},"CreateTicket right found");
ok ($rights->{'AdminGroupMembership'},"ModifyGroupMembers right found");
ok (!$rights->{'CasdasdsreateTicket'},"bogus right not found");
+}
+{
+my $sys = RT::System->new();
+is( $sys->Id, 1, 'Id is 1');
+is ($sys->id, 1, 'id is 1');
}
{
-use RT::System;
-my $sys = RT::System->new();
-is( $sys->Id, 1);
-is ($sys->id, 1);
+# Test upgrade history methods.
+my $sys = RT::System->new(RT->SystemUser);
+isa_ok($sys, 'RT::System');
-}
+my $file = 'test_file.txt';
+my $content = 'Some file contents.';
+my $upgrade_history = RT->System->UpgradeHistory();
+
+is( keys %$upgrade_history, 0, 'No history in test DB');
+
+RT->System->AddUpgradeHistory(RT =>{
+ action => 'insert',
+ filename => $file,
+ content => $content,
+ stage => 'before',
+ });
+
+$upgrade_history = RT->System->UpgradeHistory();
+ok( exists($upgrade_history->{'RT'}), 'History has an RT key.');
+is( @{$upgrade_history->{'RT'}}, 1, '1 item in history array');
+is($upgrade_history->{RT}[0]{stage}, 'before', 'stage is before for item 1');
+RT->System->AddUpgradeHistory(RT =>{
+ action => 'insert',
+ filename => $file,
+ content => $content,
+ stage => 'after',
+ });
+
+$upgrade_history = RT->System->UpgradeHistory();
+is( @{$upgrade_history->{'RT'}}, 2, '2 item in history array');
+is($upgrade_history->{RT}[1]{stage}, 'after', 'stage is after for item 2');
+
+}
diff --git a/rt/t/api/template.t b/rt/t/api/template.t
index 331d9f996..1baac44b6 100644
--- a/rt/t/api/template.t
+++ b/rt/t/api/template.t
@@ -2,23 +2,31 @@
use warnings;
use strict;
-use RT;
-use RT::Test tests => 10;
+use RT::Test tests => 37;
+
+use_ok('RT::Template');
my $queue = RT::Test->load_or_create_queue( Name => 'Templates' );
ok $queue && $queue->id, "loaded or created a queue";
+my $alt_queue = RT::Test->load_or_create_queue( Name => 'Alternative' );
+ok $alt_queue && $alt_queue->id, 'loaded or created queue';
+
{
- my $template = RT::Template->new( RT->SystemUser );
+ my $template = RT::Template->new(RT->SystemUser);
isa_ok($template, 'RT::Template');
+}
+
+{
+ my $template = RT::Template->new( RT->SystemUser );
my ($val,$msg) = $template->Create(
Queue => $queue->id,
- Name => 'InsertTest',
+ Name => 'Test',
Content => 'This is template content'
);
ok $val, "created a template" or diag "error: $msg";
ok my $id = $template->id, "id is defined";
- is $template->Name, 'InsertTest';
+ is $template->Name, 'Test';
is $template->Content, 'This is template content', "We created the object right";
($val, $msg) = $template->SetContent( 'This is new template content');
@@ -32,3 +40,164 @@ ok $queue && $queue->id, "loaded or created a queue";
$template->Load($id);
ok !$template->id, "can not load template after deletion";
}
+
+note "can not create template w/o Name";
+{
+ clean_templates( Queue => $queue->id );
+ my $template = RT::Template->new( RT->SystemUser );
+ my ($val,$msg) = $template->Create( Queue => $queue->id );
+ ok(!$val,$msg);
+}
+
+note "can not create template with duplicate name";
+{
+ clean_templates( Queue => $queue->id );
+ my $template = RT::Template->new( RT->SystemUser );
+ my ($val,$msg) = $template->Create( Queue => $queue->id, Name => 'Test' );
+ ok($val,$msg);
+
+ ($val,$msg) = $template->Create( Queue => $queue->id, Name => 'Test' );
+ ok(!$val,$msg);
+}
+
+note "change template's name";
+{
+ clean_templates( Queue => $queue->id );
+ my $template = RT::Template->new( RT->SystemUser );
+ my ($val,$msg) = $template->Create( Queue => $queue->id, Name => 'Test' );
+ ok($val,$msg);
+
+ ($val,$msg) = $template->SetName( 'Some' );
+ ok($val,$msg);
+ is $template->Name, 'Some';
+}
+
+note "can not change name to empty";
+{
+ clean_templates( Queue => $queue->id );
+ my $template = RT::Template->new( RT->SystemUser );
+ my ($val,$msg) = $template->Create( Queue => $queue->id, Name => 'Test' );
+ ok($val,$msg);
+
+ ($val,$msg) = $template->Create( Queue => $queue->id, Name => '' );
+ ok(!$val,$msg);
+ ($val,$msg) = $template->Create( Queue => $queue->id, Name => undef );
+ ok(!$val,$msg);
+}
+
+note "can not change name to duplicate";
+{
+ clean_templates( Queue => $queue->id );
+ my $template = RT::Template->new( RT->SystemUser );
+ my ($val,$msg) = $template->Create( Queue => $queue->id, Name => 'Test' );
+ ok($val,$msg);
+
+ ($val,$msg) = $template->Create( Queue => $queue->id, Name => 'Some' );
+ ok($val,$msg);
+}
+
+note "changing queue of template is not implemented";
+{
+ clean_templates( Queue => $queue->id );
+ my $template = RT::Template->new( RT->SystemUser );
+ my ($val,$msg) = $template->Create( Queue => $queue->id, Name => 'Test' );
+ ok($val,$msg);
+
+ ($val,$msg) = $template->SetQueue( $alt_queue->id );
+ ok(!$val,$msg);
+}
+
+note "make sure template can not be deleted if it has scrips";
+{
+ clean_templates( Queue => $queue->id );
+ my $template = RT::Template->new( RT->SystemUser );
+ my ($val,$msg) = $template->Create( Queue => $queue->id, Name => 'Test' );
+ ok($val,$msg);
+
+ my $scrip = RT::Scrip->new( RT->SystemUser );
+ ($val,$msg) = $scrip->Create(
+ Queue => $queue->id,
+ ScripCondition => "On Create",
+ ScripAction => 'Autoreply To Requestors',
+ Template => $template->Name,
+ );
+ ok($val, $msg);
+
+ ($val, $msg) = $template->Delete;
+ ok(!$val,$msg);
+}
+
+note "make sure template can be deleted if it's an override";
+{
+ clean_templates( Queue => $queue->id );
+ my $template = RT::Template->new( RT->SystemUser );
+ my ($val,$msg) = $template->Create( Queue => $queue->id, Name => 'Overrided' );
+ ok($val,$msg);
+
+ $template = RT::Template->new( RT->SystemUser );
+ ($val,$msg) = $template->Create( Queue => 0, Name => 'Overrided' );
+ ok($val,$msg);
+
+ my $scrip = RT::Scrip->new( RT->SystemUser );
+ ($val,$msg) = $scrip->Create(
+ Queue => $queue->id,
+ ScripCondition => "On Create",
+ ScripAction => 'Autoreply To Requestors',
+ Template => $template->Name,
+ );
+ ok($val, $msg);
+
+ ($val, $msg) = $template->Delete;
+ ok($val,$msg);
+}
+
+note "make sure template can be deleted if it has an override";
+{
+ clean_templates( Queue => $queue->id );
+ my $template = RT::Template->new( RT->SystemUser );
+ my ($val,$msg) = $template->Create( Queue => 0, Name => 'Overrided' );
+ ok($val,$msg);
+
+ $template = RT::Template->new( RT->SystemUser );
+ ($val,$msg) = $template->Create( Queue => $queue->id, Name => 'Overrided' );
+ ok($val,$msg);
+
+ my $scrip = RT::Scrip->new( RT->SystemUser );
+ ($val,$msg) = $scrip->Create(
+ Queue => $queue->id,
+ ScripCondition => "On Create",
+ ScripAction => 'Autoreply To Requestors',
+ Template => $template->Name,
+ );
+ ok($val, $msg);
+
+ ($val, $msg) = $template->Delete;
+ ok($val,$msg);
+}
+
+
+{
+ my $t = RT::Template->new(RT->SystemUser);
+ $t->Create(Name => "Foo", Queue => $queue->id);
+ my $t2 = RT::Template->new(RT->Nobody);
+ $t2->Load($t->Id);
+ ok($t2->QueueObj->id, "Got the template's queue objet");
+}
+
+sub clean_templates {
+ my %args = (@_);
+
+ my $templates = RT::Templates->new( RT->SystemUser );
+ $templates->Limit( FIELD => 'Queue', VALUE => $args{'Queue'} )
+ if defined $args{'Queue'};
+ $templates->Limit( FIELD => 'Name', VALUE => $_ )
+ foreach ref $args{'Name'}? @{$args{'Name'}} : ($args{'Name'}||());
+ while ( my $t = $templates->Next ) {
+ my ($status) = $t->Delete;
+ unless ( $status ) {
+ $_->Delete foreach @{ $t->UsedBy->ItemsArrayRef };
+ $t->Delete;
+ }
+ }
+}
+
diff --git a/rt/t/api/ticket.t b/rt/t/api/ticket.t
index da287a607..c5f1e240f 100644
--- a/rt/t/api/ticket.t
+++ b/rt/t/api/ticket.t
@@ -100,7 +100,7 @@ ok( $t->Create(Queue => 'General', Due => '2002-05-21 00:00:00', ReferredToBy =>
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);
+ok (!$t->ResolvedObj->IsSet, "It hasn't been resolved");
}
@@ -115,8 +115,7 @@ my ($id, $msg) = $ticket->Create(Subject => "Foo",
Queue => '1'
);
ok ($id, "Ticket $id was created");
-ok(my $group = RT::Group->new(RT->SystemUser));
-ok($group->LoadTicketRoleGroup(Ticket => $id, Type=> 'Requestor'));
+ok(my $group = $ticket->RoleGroup('Requestor'));
ok ($group->Id, "Found the requestors object for this ticket");
ok(my $jesse = RT::User->new(RT->SystemUser), "Creating a jesse rt::user");
@@ -135,14 +134,11 @@ ok ( ($add_id, $add_msg) = $ticket->DeleteWatcher(Type =>'Requestor', Email => '
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'));
+$group = $ticket->RoleGroup('Cc');
ok ($group->Id, "Found the cc object for this ticket");
-$group = RT::Group->new(RT->SystemUser);
-ok($group->LoadTicketRoleGroup(Ticket => $id, Type=> 'AdminCc'));
+$group = $ticket->RoleGroup('AdminCc');
ok ($group->Id, "Found the AdminCc object for this ticket");
-$group = RT::Group->new(RT->SystemUser);
-ok($group->LoadTicketRoleGroup(Ticket => $id, Type=> 'Owner'));
+$group = $ticket->RoleGroup('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'");
@@ -209,20 +205,32 @@ is ($t1->Requestors->MembersObj->Count, 2);
}
+diag "Test owner changes";
{
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');
+my ($val, $msg) = $t->Create( Subject => 'Owner test 1', Queue => 'General');
+ok( $t->Id, "Created a new ticket with id $val: $msg");
+
+($val, $msg) = $t->SetOwner('bogususer');
+ok( !$val, "Can't set owner to bogus user");
+is( $msg, "That user does not exist", "Got message: $msg");
+
+($val, $msg) = $t->SetOwner('root');
is ($t->OwnerObj->Name, 'root' , "Root owns the ticket");
+
+($val, $msg) = $t->SetOwner('root');
+ok( !$val, "User already owns ticket");
+is( $msg, "That user already owns that ticket", "Got message: $msg");
+
$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 => 'ObjectId', VALUE => $t->Id);
$txns->Limit(FIELD => 'ObjectType', VALUE => 'RT::Ticket');
$txns->Limit(FIELD => 'Type', OPERATOR => '!=', VALUE => 'EmailRecord');
@@ -230,6 +238,37 @@ my $steal = $txns->First;
is($steal->OldValue , $root->Id , "Stolen from root");
is($steal->NewValue , RT->SystemUser->Id , "Stolen by the systemuser");
+ok(my $user1 = RT::User->new(RT->SystemUser), "Creating a user1 rt::user");
+($val, $msg) = $user1->Create(Name => 'User1', EmailAddress => 'user1@example.com');
+ok( $val, "Created new user with id: $val");
+ok( $user1->Id, "Found the user1 rt user");
+
+my $t1 = RT::Ticket->new($user1);
+($val, $msg) = $t1->Load($t->Id);
+ok( $t1->Id, "Loaded ticket with id $val");
+
+($val, $msg) = $t1->SetOwner('root');
+ok( !$val, "user1 can't set owner to root: $msg");
+is ($t->OwnerObj->id, RT->SystemUser->id , "SystemUser still owns ticket " . $t1->Id);
+
+my $queue = RT::Queue->new(RT->SystemUser);
+$queue->Load("General");
+
+($val, $msg) = $user1->PrincipalObj->GrantRight(
+ Object => $queue, Right => 'ModifyTicket'
+ );
+
+($val, $msg) = $t1->SetOwner('root');
+ok( !$val, "With ModifyTicket user1 can't set owner to root: $msg");
+is ($t->OwnerObj->id, RT->SystemUser->id , "SystemUser still owns ticket " . $t1->Id);
+
+($val, $msg) = $user1->PrincipalObj->GrantRight(
+ Object => $queue, Right => 'ReassignTicket'
+ );
+
+($val, $msg) = $t1->SetOwner('root');
+ok( $val, "With ReassignTicket user1 reassigned ticket " . $t1->Id . " to root: $msg");
+is ($t1->OwnerObj->Name, 'root' , "Root owns ticket " . $t1->Id);
}
@@ -250,7 +289,16 @@ like($msg, qr/resolved/i, "Status message is correct");
($id, $msg) = $tt->SetStatus('resolved');
ok(!$id,$msg);
+my $dep = RT::Ticket->new( RT->SystemUser );
+my ( $dep_id, undef, $dep_msg ) = $dep->Create(
+ Queue => 'general',
+ Subject => 'dep ticket',
+ 'DependedOnBy' => $tt->id,
+);
+ok( $dep->id, $dep_msg );
+($id, $msg) = $tt->SetStatus('rejected');
+ok( $id, $msg );
}
diff --git a/rt/t/api/tickets.t b/rt/t/api/tickets.t
index 50d08f756..172965c3b 100644
--- a/rt/t/api/tickets.t
+++ b/rt/t/api/tickets.t
@@ -2,8 +2,7 @@
use strict;
use warnings;
use RT;
-use RT::Test tests => 18;
-
+use RT::Test tests => undef;
{
@@ -114,3 +113,35 @@ ok( $unlimittickets->Count > 0, "UnLimited tickets object should return tickets"
ok $count == 1, "found one ticket";
}
+{
+ my $tickets = RT::Tickets->new( RT->SystemUser );
+ my ($ret, $msg) = $tickets->FromSQL("Resolved IS NULL");
+ ok $ret, "Ran query with IS NULL: $msg";
+ my $count = $tickets->Count();
+ ok $count > 1, "Found more than one ticket";
+ undef $count;
+}
+
+{
+ my $ticket = RT::Ticket->new( RT->SystemUser );
+ ok $ticket->Load(1), "Loaded test ticket 1";
+ ok $ticket->SetStatus('resolved'), "Set to resolved";
+
+ my $tickets = RT::Tickets->new( RT->SystemUser );
+ my ($ret, $msg) = $tickets->FromSQL("Resolved IS NOT NULL");
+ ok $ret, "Ran query with IS NOT NULL: $msg";
+ my $count = $tickets->Count();
+ ok $count == 1, "Found one ticket";
+ undef $count;
+}
+
+{
+ my $tickets = RT::Tickets->new( RT->SystemUser );
+ $tickets->LimitDate( FIELD => "Resolved", OPERATOR => "IS", VALUE => "NULL" );
+ $tickets->LimitDate( FIELD => "Resolved", OPERATOR => "IS NOT", VALUE => "NULL" );
+ my $count = $tickets->Count();
+ ok $count > 1, "Found more than one ticket";
+ undef $count;
+}
+
+done_testing;
diff --git a/rt/t/api/txn_content.t b/rt/t/api/txn_content.t
index 392b6a73b..672d6c2e0 100644
--- a/rt/t/api/txn_content.t
+++ b/rt/t/api/txn_content.t
@@ -1,7 +1,7 @@
use warnings;
use strict;
-use RT::Test tests => 3;
+use RT::Test tests => 4;
use MIME::Entity;
my $ticket = RT::Ticket->new(RT->SystemUser);
my $mime = MIME::Entity->build(
@@ -16,4 +16,8 @@ my $txns = $ticket->Transactions;
$txns->Limit( FIELD => 'Type', VALUE => 'Create' );
my $txn = $txns->First;
ok( $txn, 'got Create txn' );
-is( $txn->Content, "this is body\n", "txn's content" );
+
+# ->Content converts from text/html to plain text if we don't explicitly ask
+# for html. Our html -> text converter seems to add an extra trailing newline
+like( $txn->Content, qr/^\s*this is body\s*$/, "txn's html content converted to plain text" );
+is( $txn->Content(Type => 'text/html'), "this is body\n", "txn's html content" );
diff --git a/rt/t/api/user-prefs.t b/rt/t/api/user-prefs.t
new file mode 100644
index 000000000..a4aa49f1b
--- /dev/null
+++ b/rt/t/api/user-prefs.t
@@ -0,0 +1,59 @@
+
+use strict;
+use warnings;
+use RT;
+use RT::Test tests => undef;
+
+use_ok( 'RT::User' );
+
+my $create_user = RT::User->new(RT->SystemUser);
+isa_ok($create_user, 'RT::User');
+my ($ret, $msg) = $create_user->Create(Name => 'CreateTest1'.$$,
+ EmailAddress => $$.'create-test-1@example.com');
+ok ($ret, "Creating user CreateTest1 - " . $msg );
+
+# Create object to operate as the test user
+my $user1 = RT::User->new($create_user);
+($ret, $msg) = $user1->Load($create_user->Id);
+ok ($ret, "Loaded the new user $msg");
+
+diag "Set a search preference";
+my $prefs = {
+ 'Order' => 'DESC|ASC|ASC|ASC',
+ 'OrderBy' => 'Due',
+ 'Format' => '\'<a href="__WebPath__/Ticket/Display.html?id=__id__">__id__</a>/TITLE:#\',
+\'<a href="__WebPath__/Ticket/Display.html?id=__id__">__Subject__</a>/TITLE:Subject\',
+\'__Priority__\',
+\'__QueueName__\',
+\'__ExtendedStatus__\',
+\'__Due__\'',
+ 'RowsPerPage' => '50'
+};
+
+ok (!$user1->HasRight( Right => 'ModifySelf', Object => $RT::System), "Can't ModifySelf");
+($ret, $msg) = $user1->SetPreferences("SearchDisplay", $prefs);
+ok( !$ret, "No permission to set preferences");
+ok (($ret, $msg) = $create_user->PrincipalObj->GrantRight( Right => 'ModifySelf'),
+ "Granted ModifySelf");
+($ret, $msg) = $user1->SetPreferences("SearchDisplay", $prefs);
+ok( $ret, "Search preference set");
+
+diag "Fetch preference";
+ok (my $saved_prefs = $user1->Preferences("SearchDisplay"), "Fetched prefs");
+is ($prefs->{OrderBy}, 'Due', "Prefs look ok");
+
+diag "Delete prefs";
+ok (($ret, $msg) = $create_user->PrincipalObj->RevokeRight( Right => 'ModifySelf'),
+ "Revoked ModifySelf");
+($ret, $msg) = $user1->DeletePreferences("SearchDisplay");
+ok( !$ret, "No permission to delete preferences");
+ok (($ret, $msg) = $create_user->PrincipalObj->GrantRight( Right => 'ModifySelf'),
+ "Granted ModifySelf");
+($ret, $msg) = $user1->DeletePreferences("SearchDisplay");
+ok( $ret, "Search preference deleted");
+
+$saved_prefs = $user1->Preferences("SearchDisplay");
+ok (!$saved_prefs, "No saved preferences returned");
+
+done_testing;
+
diff --git a/rt/t/api/user.t b/rt/t/api/user.t
index e6b891f73..94494f162 100644
--- a/rt/t/api/user.t
+++ b/rt/t/api/user.t
@@ -2,7 +2,7 @@
use strict;
use warnings;
use RT;
-use RT::Test tests => 111;
+use RT::Test tests => 122;
{
@@ -106,7 +106,7 @@ 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->id , 1, "user 1 is the first principal");
is($u->PrincipalObj->PrincipalType, 'User' , "Principal 1 is a user, not a group");
@@ -335,3 +335,30 @@ ok($rqv, "Revoked the right successfully - $rqm");
}
+{
+ my $root = RT::Test->load_or_create_user( Name => 'root' );
+ ok $root && $root->id;
+
+ my $queue = RT::Test->load_or_create_queue( Name => 'General' );
+ ok $queue && $queue->id;
+
+ my $ticket = RT::Ticket->new( RT->SystemUser );
+ my ($id) = $ticket->Create( Subject => 'test', Queue => $queue );
+ ok $id;
+
+ my $b_ticket = RT::Ticket->new( RT->SystemUser );
+ ($id) = $b_ticket->Create( Subject => 'test', Queue => $queue );
+ ok $id;
+
+ ok $root->ToggleBookmark($b_ticket);
+ ok !$root->ToggleBookmark($b_ticket);
+ ok $root->ToggleBookmark($b_ticket);
+
+ ok $root->HasBookmark( $b_ticket );
+ ok !$root->HasBookmark( $ticket );
+
+ my @marks = $root->Bookmarks;
+ is scalar @marks, 1;
+ is $marks[0], $b_ticket->id;
+}
+
diff --git a/rt/t/api/users.t b/rt/t/api/users.t
index 1f3a48770..e65f9a9b5 100644
--- a/rt/t/api/users.t
+++ b/rt/t/api/users.t
@@ -2,7 +2,7 @@ use strict;
use warnings;
use RT::Test tests => 10;
-RT::System->AddRights(
+RT::System->AddRight( General =>
'RTxUserRight' => 'Just a right for testing rights',
);