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