import rt 3.8.7
[freeside.git] / rt / t / approval / basic.t
1
2 use strict;
3 use warnings;
4 use Test::More;
5 BEGIN {
6     eval { require Email::Abstract; require Test::Email; 1 }
7         or plan skip_all => 'require Email::Abstract and Test::Email';
8 }
9
10
11 use RT;
12 use RT::Test tests => 39;
13 use RT::Test::Email;
14
15 RT->Config->Set( LogToScreen => 'debug' );
16 RT->Config->Set( UseTransactionBatch => 1 );
17 my ($baseurl, $m) = RT::Test->started_ok;
18
19 my $q = RT::Queue->new($RT::SystemUser);
20 $q->Load('___Approvals');
21 $q->SetDisabled(0);
22
23 my %users;
24 for my $user_name (qw(minion cfo ceo )) {
25     my $user = $users{$user_name} = RT::User->new($RT::SystemUser);
26     $user->Create( Name => uc($user_name),
27                    Privileged => 1,
28                    EmailAddress => $user_name.'@company.com');
29     my ($val, $msg);
30     ($val, $msg) = $user->PrincipalObj->GrantRight(Object =>$q, Right => $_)
31         for qw(ModifyTicket OwnTicket ShowTicket);
32 }
33
34 # XXX: we need to make the first approval ticket open so notification is sent.
35 my $approvals = 
36 '===Create-Ticket: for-CFO
37 Queue: ___Approvals
38 Type: approval
39 Owner: CFO
40 Requestors: {$Tickets{"TOP"}->Requestors}
41 Refers-To: TOP
42 Subject: CFO Approval for PO: {$Tickets{"TOP"}->Id} - {$Tickets{"TOP"}->Subject}
43 Due: {time + 86400}
44 Content-Type: text/plain
45 Content: Your approval is requested for the PO ticket {$Tickets{"TOP"}->Id}: {$Tickets{"TOP"}->Subject}
46 Blah
47 Blah
48 ENDOFCONTENT
49 ===Create-Ticket: for-CEO
50 Queue: ___Approvals
51 Type: approval
52 Owner: CEO
53 Requestors: {$Tickets{"TOP"}->Requestors}
54 Subject: PO approval request for {$Tickets{"TOP"}->Subject}
55 Refers-To: TOP
56 Depends-On: for-CFO
57 Depended-On-By: {$Tickets{"TOP"}->Id}
58 Content-Type: text/plain
59 Content: 
60 Your CFO approved PO ticket {$Tickets{"TOP"}->Id} for minion. you ok with that?
61 ENDOFCONTENT
62 ';
63
64 my $apptemp = RT::Template->new($RT::SystemUser);
65 $apptemp->Create( Content => $approvals, Name => "PO Approvals", Queue => "0");
66
67 ok($apptemp->Id);
68
69 $q = RT::Queue->new($RT::SystemUser);
70 $q->Create(Name => 'PO');
71 ok ($q->Id, "Created PO queue");
72
73 my $scrip = RT::Scrip->new($RT::SystemUser);
74 my ($sval, $smsg) =$scrip->Create( ScripCondition => 'On Create',
75                 ScripAction => 'Create Tickets',
76                 Template => 'PO Approvals',
77                 Queue => $q->Id,
78                 Description => 'Create Approval Tickets');
79 ok ($sval, $smsg);
80 ok ($scrip->Id, "Created the scrip");
81 ok ($scrip->TemplateObj->Id, "Created the scrip template");
82 ok ($scrip->ConditionObj->Id, "Created the scrip condition");
83 ok ($scrip->ActionObj->Id, "Created the scrip action");
84
85 my $t = RT::Ticket->new($RT::SystemUser);
86 my ($tid, $ttrans, $tmsg);
87
88 mail_ok {
89     ($tid, $ttrans, $tmsg) =
90         $t->Create(Subject => "PO for stationary",
91                    Owner => "root", Requestor => 'minion',
92                    Queue => $q->Id);
93 } { from => qr/RT System/,
94     to => 'cfo@company.com',
95     subject => qr/New Pending Approval: CFO Approval/,
96     body => qr/pending your approval.*Your approval is requested.*Blah/s
97 },{ from => qr/PO via RT/,
98     to => 'minion@company.com',
99     subject => qr/PO for stationary/,
100     body => qr/automatically generated in response/
101 };
102
103 ok ($tid,$tmsg);
104
105 is ($t->ReferredToBy->Count,2, "referred to by the two tickets");
106
107 my $deps = $t->DependsOn;
108 is ($deps->Count, 1, "The ticket we created depends on one other ticket");
109 my $dependson_ceo= $deps->First->TargetObj;
110 ok ($dependson_ceo->Id, "It depends on a real ticket");
111 like($dependson_ceo->Subject, qr/PO approval request.*stationary/);
112
113 $deps = $dependson_ceo->DependsOn;
114 is ($deps->Count, 1, "The ticket we created depends on one other ticket");
115 my $dependson_cfo = $deps->First->TargetObj;
116 ok ($dependson_cfo->Id, "It depends on a real ticket");
117
118 like($dependson_cfo->Subject, qr/CFO Approval for PO.*stationary/);
119
120 is_deeply([ $t->Status, $dependson_cfo->Status, $dependson_ceo->Status ],
121           [ 'new', 'open', 'new'], 'tickets in correct state');
122
123 mail_ok {
124     my $cfo = RT::CurrentUser->new;
125     $cfo->Load( $users{cfo} );
126
127     $dependson_cfo->CurrentUser($cfo);
128     my $notes = MIME::Entity->build(
129         Data => [ 'Resources exist to be consumed.' ]
130     );
131     RT::I18N::SetMIMEEntityToUTF8($notes); # convert text parts into utf-8
132
133     my ( $notesval, $notesmsg ) = $dependson_cfo->Correspond( MIMEObj => $notes );
134     ok($notesval, $notesmsg);
135
136     my ($ok, $msg) = $dependson_cfo->SetStatus( Status => 'resolved' );
137     ok($ok, "cfo can approve - $msg");
138
139 } { from => qr/RT System/,
140     to => 'ceo@company.com',
141     subject => qr/New Pending Approval: PO approval request for PO/,
142     body => qr/pending your approval.*CFO approved.*ok with that\?/s
143 },{ from => qr/RT System/,
144     to => 'minion@company.com',
145     subject => qr/Ticket Approved:/,
146     body => qr/approved by CFO.*notes: Resources exist to be consumed/s
147 };
148
149 is ($t->DependsOn->Count, 1, "still depends only on the CEO approval");
150 is ($t->ReferredToBy->Count,2, "referred to by the two tickets");
151
152 is_deeply([ $t->Status, $dependson_cfo->Status, $dependson_ceo->Status ],
153           [ 'new', 'resolved', 'open'], 'ticket state after cfo approval');
154
155 mail_ok {
156     my $ceo = RT::CurrentUser->new;
157     $ceo->Load( $users{ceo} );
158
159     $dependson_ceo->CurrentUser($ceo);
160     my $notes = MIME::Entity->build(
161         Data => [ 'And consumed they will be.' ]
162     );
163     RT::I18N::SetMIMEEntityToUTF8($notes); # convert text parts into utf-8
164
165     my ( $notesval, $notesmsg ) = $dependson_ceo->Correspond( MIMEObj => $notes );
166     ok($notesval, $notesmsg);
167
168     my ($ok, $msg) = $dependson_ceo->SetStatus( Status => 'resolved' );
169     ok($ok, "ceo can approve - $msg");
170
171 } { from => qr/RT System/,
172     to => 'minion@company.com',
173     subject => qr/Ticket Approved:/,
174     body => qr/approved by CEO.*Its Owner may now start to act on it.*notes: And consumed they will be/s,
175 }, { from => qr'CEO via RT',
176      to => 'root@localhost',
177      subject => qr/Ticket Approved/,
178      body => qr/The ticket has been approved, you may now start to act on it/,
179 };
180
181
182 is_deeply([ $t->Status, $dependson_cfo->Status, $dependson_ceo->Status ],
183           [ 'new', 'resolved', 'resolved'], 'ticket state after ceo approval');
184
185 $dependson_cfo->_Set(
186     Field => 'Status',
187     Value => 'open');
188
189 $dependson_ceo->_Set(
190     Field => 'Status',
191     Value => 'new');
192
193 mail_ok {
194     my $cfo = RT::CurrentUser->new;
195     $cfo->Load( $users{cfo} );
196
197     $dependson_cfo->CurrentUser($cfo);
198     my $notes = MIME::Entity->build(
199         Data => [ 'sorry, out of resources.' ]
200     );
201     RT::I18N::SetMIMEEntityToUTF8($notes); # convert text parts into utf-8
202
203     my ( $notesval, $notesmsg ) = $dependson_cfo->Correspond( MIMEObj => $notes );
204     ok($notesval, $notesmsg);
205
206     my ($ok, $msg) = $dependson_cfo->SetStatus( Status => 'rejected' );
207     ok($ok, "cfo can approve - $msg");
208
209 } { from => qr/RT System/,
210     to => 'minion@company.com',
211     subject => qr/Ticket Rejected: PO for stationary/,
212     body => qr/rejected by CFO.*out of resources/s,
213 };
214
215 $t->Load($t->id);$dependson_ceo->Load($dependson_ceo->id);
216 is_deeply([ $t->Status, $dependson_cfo->Status, $dependson_ceo->Status ],
217           [ 'rejected', 'rejected', 'deleted'], 'ticket state after cfo rejection');
218