import rt 3.8.9
[freeside.git] / rt / lib / t / regression / 26command_line.t
1 #!/usr/bin/perl -w
2
3 use strict;
4 use Test::Expect;
5 #use Test::More qw/no_plan/;
6 use Test::More tests => 222;
7
8 use RT;
9 RT::LoadConfig();
10 RT::Init;
11
12 use RT::User;
13 use RT::Queue;
14
15 my $rt_tool_path = "$RT::BinPath/rt";
16
17 # {{{  test configuration options
18
19 # config directives:
20 #    (in $CWD/.rtrc)
21 #    - server <URL>          URL to RT server.
22 #    - user <username>       RT username.
23 #    - passwd <passwd>       RT user's password.
24 #    - query <RT Query>      Default RT Query for list action
25 #    - orderby <order>       Default RT order for list action
26 #
27 #    Blank and #-commented lines are ignored.
28
29 # environment variables
30 #    The following environment variables override any corresponding
31 #    values defined in configuration files:
32 #
33 #    - RTUSER
34 $ENV{'RTUSER'} = 'root';
35 #    - RTPASSWD
36 $ENV{'RTPASSWD'} = 'password';
37 #    - RTSERVER
38 $RT::Logger->debug("Connecting to server at $RT::WebBaseURL...");
39 $ENV{'RTSERVER'} = $RT::WebBaseURL;
40 #    - RTDEBUG       Numeric debug level. (Set to 3 for full logs.)
41 $ENV{'RTDEBUG'} = '1';
42 #    - RTCONFIG      Specifies a name other than ".rtrc" for the
43 #                    configuration file.
44 #
45 #    - RTQUERY       Default RT Query for rt list
46 #    - RTORDERBY     Default order for rt list
47
48
49 # }}}
50
51 # {{{ test ticket manipulation
52
53 # create a ticket
54 expect_run(
55     command => "$rt_tool_path shell",
56     prompt => 'rt> ',
57     quit => 'quit',
58 );
59 expect_send(q{create -t ticket set subject='new ticket' add cc=foo@example.com}, "Creating a ticket...");
60 expect_like(qr/Ticket \d+ created/, "Created the ticket");
61 expect_handle->before() =~ /Ticket (\d+) created/;
62 my $ticket_id = $1;
63 ok($ticket_id, "Got ticket id=$ticket_id");
64 expect_send(q{create -t ticket set subject='new ticket'}, "Creating a ticket as just a subject...");
65 expect_like(qr/Ticket \d+ created/, "Created the ticket");
66
67 # make sure we can request things as 'rt foo'
68 expect_send(q{rt create -t ticket set subject='rt ticket'}, "Creating a ticket with 'rt create'...");
69 expect_like(qr/Ticket \d+ created/, "Created the ticket");
70
71 # {{{ test queue manipulation
72
73 # creating queues
74 expect_send("create -t queue set Name='NewQueue$$'", 'Creating a queue...');
75 expect_like(qr/Queue \d+ created/, 'Created the queue');
76 expect_handle->before() =~ /Queue (\d+) created/;
77 my $queue_id = $1;
78 ok($queue_id, "Got queue id=$queue_id");
79 # updating users
80 expect_send("edit queue/$queue_id set Name='EditedQueue$$'", 'Editing the queue');
81 expect_like(qr/Queue $queue_id updated/, 'Edited the queue');
82 expect_send("show queue/$queue_id", 'Showing the queue...');
83 expect_like(qr/id: queue\/$queue_id/, 'Saw the queue');
84 expect_like(qr/Name: EditedQueue$$/, 'Saw the modification');
85 TODO: { 
86     todo_skip "Listing non-ticket items doesn't work", 2;
87     expect_send("list -t queue 'id > 0'", 'Listing the queues...');
88     expect_like(qr/$queue_id: EditedQueue$$/, 'Found the queue');
89 }
90
91 # }}}
92
93
94 # Set up a custom field for editing tests
95 my $cf = RT::CustomField->new($RT::SystemUser);
96 my ($val,$msg) = $cf->Create(Name => 'MyCF'.$$, Type => 'FreeformSingle', Queue => $queue_id);
97 ok($val,$msg);
98
99 my $othercf = RT::CustomField->new($RT::SystemUser);
100 ($val,$msg) = $othercf->Create(Name => 'My CF'.$$, Type => 'FreeformSingle', Queue => $queue_id);
101 ok($val,$msg);
102
103
104
105 # add a comment to ticket
106     expect_send("comment -m 'comment-$$' $ticket_id", "Adding a comment...");
107     expect_like(qr/Message recorded/, "Added the comment");
108     ### should test to make sure it actually got added
109     # add correspondance to ticket (?)
110     expect_send("correspond -m 'correspond-$$' $ticket_id", "Adding correspondence...");
111     expect_like(qr/Message recorded/, "Added the correspondence");
112     ### should test to make sure it actually got added
113
114     # add attachments to a ticket
115     # text attachment
116     check_attachment("$RT::BasePath/lib/t/data/lorem-ipsum");
117     # binary attachment
118     check_attachment($RT::MasonComponentRoot.'/NoAuth/images/bplogo.gif');
119
120 # change a ticket's Owner
121 expect_send("edit ticket/$ticket_id set owner=root", 'Changing owner...');
122 expect_like(qr/Ticket $ticket_id updated/, 'Changed owner');
123 expect_send("show ticket/$ticket_id -f owner", 'Verifying change...');
124 expect_like(qr/Owner: root/, 'Verified change');
125 # change a ticket's Requestor
126 expect_send("edit ticket/$ticket_id set requestors=foo\@example.com", 'Changing Requestor...');
127 expect_like(qr/Ticket $ticket_id updated/, 'Changed Requestor');
128 expect_send("show ticket/$ticket_id -f requestors", 'Verifying change...');
129 expect_like(qr/Requestors: foo\@example.com/, 'Verified change');
130 # change a ticket's Cc
131 expect_send("edit ticket/$ticket_id set cc=bar\@example.com", 'Changing Cc...');
132 expect_like(qr/Ticket $ticket_id updated/, 'Changed Cc');
133 expect_send("show ticket/$ticket_id -f cc", 'Verifying change...');
134 expect_like(qr/Cc: bar\@example.com/, 'Verified change');
135 # change a ticket's priority
136 expect_send("edit ticket/$ticket_id set priority=10", 'Changing priority...');
137 expect_like(qr/Ticket $ticket_id updated/, 'Changed priority');
138 expect_send("show ticket/$ticket_id -f priority", 'Verifying change...');
139 expect_like(qr/Priority: 10/, 'Verified change');
140 # move a ticket to a different queue
141 expect_send("edit ticket/$ticket_id set queue=EditedQueue$$", 'Changing queue...');
142 expect_like(qr/Ticket $ticket_id updated/, 'Changed queue');
143 expect_send("show ticket/$ticket_id -f queue", 'Verifying change...');
144 expect_like(qr/Queue: EditedQueue$$/, 'Verified change');
145 # cannot move ticket to a nonexistent queue
146 expect_send("edit ticket/$ticket_id set queue=nonexistent-$$", 'Changing to nonexistent queue...');
147 expect_like(qr/queue does not exist/i, 'Errored out');
148 expect_send("show ticket/$ticket_id -f queue", 'Verifying lack of change...');
149 expect_like(qr/Queue: EditedQueue$$/, 'Verified lack of change');
150
151 # Test reading and setting custom fields without spaces
152 expect_send("show ticket/$ticket_id -f CF-myCF$$", 'Checking initial value');
153 expect_like(qr/CF-myCF$$:/i, 'Verified initial empty value');
154 expect_send("edit ticket/$ticket_id set 'CF-myCF$$=VALUE' ", 'Changing CF...');
155 expect_like(qr/Ticket $ticket_id updated/, 'Changed cf');
156 expect_send("show ticket/$ticket_id -f CF-myCF$$", 'Checking new value');
157 expect_like(qr/CF-myCF$$: VALUE/i, 'Verified change');
158 # Test setting 0 as value of the custom field
159 expect_send("edit ticket/$ticket_id set 'CF-myCF$$=0' ", 'Changing CF...');
160 expect_like(qr/Ticket $ticket_id updated/, 'Changed cf');
161 expect_send("show ticket/$ticket_id -f CF-myCF$$", 'Checking new value');
162 expect_like(qr/CF-myCF$$: 0/i, 'Verified change');
163 # Test reading and setting custom fields with spaces
164 expect_send("show ticket/$ticket_id -f 'CF-my CF$$'", 'Checking initial value');
165 expect_like(qr/my CF$$:/i, 'Verified change');
166 expect_send("edit ticket/$ticket_id set 'CF-my CF$$=VALUE' ", 'Changing CF...');
167 expect_like(qr/Ticket $ticket_id updated/, 'Changed cf');
168 expect_send("show ticket/$ticket_id -f 'CF-my CF$$'", 'Checking new value');
169 expect_like(qr/my CF$$: VALUE/i, 'Verified change');
170 expect_send("ls 'id = $ticket_id' -f 'CF-my CF$$'", 'Checking new value');
171 expect_like(qr/my CF$$: VALUE/i, 'Verified change');
172
173 # ...
174 # change a ticket's ...[other properties]...
175 # ...
176 # stall a ticket
177 expect_send("edit ticket/$ticket_id set status=stalled", 'Changing status to "stalled"...');
178 expect_like(qr/Ticket $ticket_id updated/, 'Changed status');
179 expect_send("show ticket/$ticket_id -f status", 'Verifying change...');
180 expect_like(qr/Status: stalled/, 'Verified change');
181 # resolve a ticket
182 expect_send("edit ticket/$ticket_id set status=resolved", 'Changing status to "resolved"...');
183 expect_like(qr/Ticket $ticket_id updated/, 'Changed status');
184 expect_send("show ticket/$ticket_id -f status", 'Verifying change...');
185 expect_like(qr/Status: resolved/, 'Verified change');
186 # try to set status to an illegal value
187 expect_send("edit ticket/$ticket_id set status=quux", 'Changing status to an illegal value...');
188 expect_like(qr/illegal value/i, 'Errored out');
189 expect_send("show ticket/$ticket_id -f status", 'Verifying lack of change...');
190 expect_like(qr/Status: resolved/, 'Verified change');
191
192 # }}}
193
194 # {{{ display
195
196 # show ticket list
197 expect_send("ls -s -t ticket -o +id \"Status='resolved'\"", 'Listing resolved tickets...');
198 expect_like(qr/$ticket_id: new ticket/, 'Found our ticket');
199 # show ticket list verbosely
200 expect_send("ls -l -t ticket -o +id \"Status='resolved'\"", 'Listing resolved tickets verbosely...');
201 expect_like(qr/id: ticket\/$ticket_id/, 'Found our ticket');
202 # show ticket
203 expect_send("show -t ticket $ticket_id", 'Showing our ticket...');
204 expect_like(qr/id: ticket\/$ticket_id/, 'Got our ticket');
205 # show ticket history
206 expect_send("show ticket/$ticket_id/history", 'Showing our ticket\'s history...');
207 expect_like(qr/Ticket created by root/, 'Got our history');
208 TODO: {
209     local $TODO = "Cannot show verbose ticket history right now";
210     # show ticket history verbosely
211     expect_send("show -v ticket/$ticket_id/history", 'Showing our ticket\'s history verbosely...');
212     expect_like(qr/Ticket created by root/, 'Got our history');
213 }
214 # get attachments from a ticket
215 expect_send("show ticket/$ticket_id/attachments", 'Showing ticket attachments...');
216 expect_like(qr/id: ticket\/$ticket_id\/attachments/, 'Got our ticket\'s attachments');
217 expect_like(qr/Attachments: \d+:\s*\(\S+ \/ \d+\w+\)/, 'Our ticket has an attachment');
218 expect_handle->before() =~ /Attachments: (\d+):\s*\((\S+)/;
219 my $attachment_id = $1;
220 my $attachment_type = $2;
221 ok($attachment_id, "Got attachment id=$attachment_id $attachment_type");
222 expect_send("show ticket/$ticket_id/attachments/$attachment_id", "Showing attachment $attachment_id...");
223 expect_like(qr/ContentType: $attachment_type/, 'Got the attachment');
224
225 # }}}
226
227 # {{{ test user manipulation
228
229 # creating users
230 expect_send("create -t user set Name='NewUser$$' EmailAddress='fbar$$\@example.com'", 'Creating a user...');
231 expect_like(qr/User \d+ created/, 'Created the user');
232 expect_handle->before() =~ /User (\d+) created/;
233 my $user_id = $1;
234 ok($user_id, "Got user id=$user_id");
235 # updating users
236 expect_send("edit user/$user_id set Name='EditedUser$$'", 'Editing the user');
237 expect_like(qr/User $user_id updated/, 'Edited the user');
238 expect_send("show user/$user_id", 'Showing the user...');
239 expect_like(qr/id: user\/$user_id/, 'Saw the user');
240 expect_like(qr/Name: EditedUser$$/, 'Saw the modification');
241 TODO: { 
242     todo_skip "Listing non-ticket items doesn't work", 2;
243     expect_send("list -t user 'id > 0'", 'Listing the users...');
244     expect_like(qr/$user_id: EditedUser$$/, 'Found the user');
245 }
246
247 # }}}
248
249 # {{{ test group manipulation
250
251 TODO: {
252 todo_skip "Group manipulation doesn't work right now", 8;
253 # creating groups
254 expect_send("create -t group set Name='NewGroup$$'", 'Creating a group...');
255 expect_like(qr/Group \d+ created/, 'Created the group');
256 expect_handle->before() =~ /Group (\d+) created/;
257 my $group_id = $1;
258 ok($group_id, "Got group id=$group_id");
259 # updating groups
260 expect_send("edit group/$group_id set Name='EditedGroup$$'", 'Editing the group');
261 expect_like(qr/Group $group_id updated/, 'Edited the group');
262 expect_send("show group/$group_id", 'Showing the group...');
263 expect_like(qr/id: group\/$group_id/, 'Saw the group');
264 expect_like(qr/Name: EditedGroup$$/, 'Saw the modification');
265 TODO: { 
266     local $TODO = "Listing non-ticket items doesn't work";
267     expect_send("list -t group 'id > 0'", 'Listing the groups...');
268     expect_like(qr/$group_id: EditedGroup$$/, 'Found the group');
269 }
270 }
271
272 # }}}
273
274 TODO: {
275 todo_skip "Custom field manipulation not yet implemented", 8;
276 # {{{ test custom field manipulation
277
278 # creating custom fields
279 expect_send("create -t custom_field set Name='NewCF$$'", 'Creating a custom field...');
280 expect_like(qr/Custom Field \d+ created/, 'Created the custom field');
281 expect_handle->before() =~ /Custom Field (\d+) created/;
282 my $cf_id = $1;
283 ok($cf_id, "Got custom field id=$cf_id");
284 # updating custom fields
285 expect_send("edit cf/$cf_id set Name='EditedCF$$'", 'Editing the custom field');
286 expect_like(qr/Custom field $cf_id updated/, 'Edited the custom field');
287 expect_send("show cf/$cf_id", 'Showing the queue...');
288 expect_like(qr/id: custom_field\/$cf_id/, 'Saw the custom field');
289 expect_like(qr/Name: EditedCF$$/, 'Saw the modification');
290 TODO: { 
291     todo_skip "Listing non-ticket items doesn't work", 2;
292     expect_send("list -t custom_field 'id > 0'", 'Listing the CFs...');
293     expect_like(qr/$cf_id: EditedCF$$/, 'Found the custom field');
294 }
295 }
296
297 # }}}
298
299 # {{{ test merging tickets
300 expect_send("create -t ticket set subject='CLIMergeTest1-$$'", 'Creating first ticket to merge...');
301 expect_like(qr/Ticket \d+ created/, 'Created first ticket');
302 expect_handle->before() =~ /Ticket (\d+) created/;
303 my $merge_ticket_A = $1;
304 ok($merge_ticket_A, "Got first ticket to merge id=$merge_ticket_A");
305 expect_send("create -t ticket set subject='CLIMergeTest2-$$'", 'Creating second ticket to merge...');
306 expect_like(qr/Ticket \d+ created/, 'Created second ticket');
307 expect_handle->before() =~ /Ticket (\d+) created/;
308 my $merge_ticket_B = $1;
309 ok($merge_ticket_B, "Got second ticket to merge id=$merge_ticket_B");
310 expect_send("merge $merge_ticket_B $merge_ticket_A", 'Merging the tickets...');
311 expect_like(qr/Merge completed/, 'Merged the tickets');
312 expect_send("show ticket/$merge_ticket_A/history", 'Checking merge on first ticket');
313 expect_like(qr/Merged into ticket #$merge_ticket_A by root/, 'Merge recorded in first ticket');
314 expect_send("show ticket/$merge_ticket_B/history", 'Checking merge on second ticket');
315 expect_like(qr/Merged into ticket #$merge_ticket_A by root/, 'Merge recorded in second ticket');
316 # }}}
317
318 # {{{ test taking/stealing tickets
319 {
320     # create a user; give them privileges to take and steal
321     ### TODO: implement 'grant' in the CLI tool; use that here instead.
322     ###       this breaks the abstraction barrier, like, a lot.
323     my $steal_user = RT::User->new($RT::SystemUser);
324     my ($steal_user_id, $msg) = $steal_user->Create( Name => "fooser$$",
325                                           EmailAddress => "fooser$$\@localhost",
326                                           Privileged => 1,
327                                           Password => 'foobar',
328                                         );
329     ok($steal_user_id, "Created the user? $msg");
330     my $steal_queue = RT::Queue->new($RT::SystemUser);
331     my $steal_queue_id;
332     ($steal_queue_id, $msg) = $steal_queue->Create( Name => "Steal$$" );
333     ok($steal_queue_id, "Got the queue? $msg");
334     ok($steal_queue->id, "queue obj has id");
335     my $status;
336     ($status, $msg) = $steal_user->PrincipalObj->GrantRight( Right => 'ShowTicket', Object => $steal_queue );
337     ok($status, "Gave 'SeeTicket' to our user? $msg");
338     ($status, $msg) = $steal_user->PrincipalObj->GrantRight( Right => 'OwnTicket', Object => $steal_queue );
339     ok($status, "Gave 'OwnTicket' to our user? $msg");
340     ($status, $msg) = $steal_user->PrincipalObj->GrantRight( Right => 'StealTicket', Object => $steal_queue );
341     ok($status, "Gave 'StealTicket' to our user? $msg");
342     ($status, $msg) = $steal_user->PrincipalObj->GrantRight( Right => 'TakeTicket', Object => $steal_queue );
343     ok($status, "Gave 'TakeTicket' to our user? $msg");
344
345     # create a ticket to take/steal
346     expect_send("create -t ticket set queue=$steal_queue_id subject='CLIStealTest-$$'", 'Creating ticket to steal...');
347     expect_like(qr/Ticket \d+ created/, 'Created ticket');
348     expect_handle->before() =~ /Ticket (\d+) created/;
349     my $steal_ticket_id = $1;
350     ok($steal_ticket_id, "Got ticket to steal id=$steal_ticket_id");
351
352     # root takes the ticket
353     expect_send("take $steal_ticket_id", 'root takes the ticket...');
354     expect_like(qr/Owner changed from Nobody to root/, 'root took the ticket');
355
356     # log in as the non-root user
357     #expect_quit();      # this is apparently unnecessary, but I'll leave it in
358                          # until I'm sure
359     $ENV{'RTUSER'} = "fooser$$";
360     $ENV{'RTPASSWD'} = 'foobar';
361     expect_run( command => "$rt_tool_path shell", prompt => 'rt> ', quit => 'quit',);
362
363     # user tries to take the ticket, fails
364     # shouldn't be able to 'take' a ticket which someone else has taken out from
365     # under you; that should produce an error.  should have to explicitly 
366     # 'steal' it back from them.  'steal' can automatically 'take' a ticket,
367     # though.
368     expect_send("take $steal_ticket_id", 'user tries to take the ticket...');
369     expect_like(qr/You can only take tickets that are unowned/, '...and fails.');
370     expect_send("show ticket/$steal_ticket_id -f owner", 'Double-checking...');
371     expect_like(qr/Owner: root/, '...no change.');
372
373     # user steals the ticket
374     expect_send("steal $steal_ticket_id", 'user tries to *steal* the ticket...');
375     expect_like(qr/Owner changed from root to fooser$$/, '...and succeeds!');
376     expect_send("show ticket/$steal_ticket_id -f owner", 'Double-checking...');
377     expect_like(qr/Owner: fooser$$/, '...yup, it worked.');
378
379     # log back in as root
380     #expect_quit();     # ditto
381     $ENV{'RTUSER'} = 'root';
382     $ENV{'RTPASSWD'} = 'password';
383     expect_run( command => "$rt_tool_path shell", prompt => 'rt> ', quit => 'quit',);
384
385     # root steals the ticket back
386     expect_send("steal $steal_ticket_id", 'root steals the ticket back...');
387     expect_like(qr/Owner changed from fooser$$ to root/, '...and succeeds.');
388 }
389 # }}}
390
391 # {{{ test ticket linking
392     my @link_relns = ( 'DependsOn', 'DependedOnBy', 'RefersTo', 'ReferredToBy',
393                        'MemberOf', 'HasMember', );
394     my %display_relns = map { $_ => $_ } @link_relns;
395     $display_relns{HasMember} = 'Members';
396
397     my $link1_id = ok_create_ticket( "LinkTicket1-$$" );
398     my $link2_id = ok_create_ticket( "LinkTicket2-$$" );
399
400     foreach my $reln (@link_relns) {
401         # create link
402         expect_send("link $link1_id $reln $link2_id", "Link by $reln...");
403         expect_like(qr/Created link $link1_id $reln $link2_id/, 'Linked');
404         expect_send("show ticket/$link1_id/links", "Checking creation of $reln...");
405         expect_like(qr/$display_relns{reln}: [\w\d\.\-]+:\/\/[\w\d\.]+\/ticket\/$link2_id/, "Created link $reln");
406
407         # delete link
408         expect_send("link -d $link1_id $reln $link2_id", "Delete $reln...");
409         expect_like(qr/Deleted link $link1_id $reln $link2_id/, 'Deleted');
410         expect_send("show ticket/$link1_id/links", "Checking removal of $reln...");
411         ok( expect_handle->before() !~ /\Q$display_relns{$reln}: \E[\w\d\.\-]+:\/\/[w\d\.]+\/ticket\/$link2_id/, "Removed link $reln" );
412         #expect_unlike(qr/\Q$reln: \E[\w\d\.]+\Q://\E[w\d\.]+\/ticket\/$link2_id/, "Removed link $reln");
413
414     }
415 # }}}
416
417
418 # helper function
419 sub ok_create_ticket {
420     my $subject = shift;
421
422     expect_send("create -t ticket set subject='$subject'", 'Creating ticket...');
423     expect_like(qr/Ticket \d+ created/, "Created ticket '$subject'");
424     expect_handle->before() =~ /Ticket (\d+) created/;
425     my $id = $1;
426     ok($id, "Got ticket id=$id");
427     
428     return $id;
429 }
430
431 # wrap up all the file handling stuff for attachment testing
432 sub check_attachment {
433     my $attachment_path = shift;
434     (my $filename = $attachment_path) =~ s/.*\/(.*?)$/$1/;
435     expect_send("comment -m 'attach file' -a $attachment_path $ticket_id", "Adding an attachment ($filename)");
436     expect_like(qr/Message recorded/, "Added the attachment");
437     expect_send("show ticket/$ticket_id/attachments","Finding Attachment");
438     my $attachment_regex = qr/(\d+):\s+$filename/;
439     expect_like($attachment_regex,"Attachment Uploaded");
440     expect_handle->before() =~ $attachment_regex;
441     my $attachment_id = $1;
442     expect_send("show ticket/$ticket_id/attachments/$attachment_id/content","Fetching Attachment");
443     open (my $fh, $attachment_path) or die "Can't open $attachment_path: $!";
444     my $attachment_content = do { local($/); <$fh> };
445     close $fh;
446     chomp $attachment_content;
447     expect_is($attachment_content,"Attachment contains original text");
448 }
449
450 1;