#!perl # vim: softtabstop=4 tabstop=4 shiftwidth=4 ft=perl expandtab smarttab # This test is for testing RT::Client::REST with a real instance of RT. # This is so that we can verify bug reports and compare functionality # (and bugs) between different versions of RT. use strict; use warnings; use Test::More; use File::Spec::Functions qw/ splitpath /; BEGIN { unless ( $ENV{RELEASE_TESTING} ) { plan( skip_all => 'these tests are for release candidate testing' ); } if ( grep { not defined $ENV{$_} } (qw(RTSERVER RTPASS RTUSER)) ) { plan( skip_all => 'one of RTSERVER, RTPASS, or RTUSER is not set' ); } } { # We will only use letters, because this string may be used for names of # queues and users in RT and we don't want to fail because of RT rules. my @chars = ( 'a' .. 'z', 'A' .. 'Z' ); sub random_string { my $retval = ''; for ( 1 .. 10 ) { $retval .= $chars[ int( rand( scalar(@chars) ) ) ]; } return $retval; } } plan 'no_plan'; use Try::Tiny; use File::Temp qw(tempfile); use RT::Client::REST; use RT::Client::REST::Queue; use RT::Client::REST::User; my $rt = RT::Client::REST->new( server => $ENV{RTSERVER}, ); ok( $rt, 'RT instance is created' ); # Log in with wrong credentials and see that we get expected error { my $e; try { $rt->login( username => $ENV{RTUSER}, password => 'WRONG' . $ENV{RTPASS} ); } catch { die $_ unless blessed $_ && $_->can('rethrow'); if ( $_->isa('RT::Client::REST::AuthenticationFailureException') ) { $e = $_; } else { $_->rethrow; } }; ok( defined($e), 'Logging in with wrong credentials throws expected error' ); } # Now log in successfully { my $e; try { $rt->login( username => $ENV{RTUSER}, password => $ENV{RTPASS} ); } catch { die $_ unless blessed $_ && $_->can('rethrow'); if ( $_->isa('RT::Client::REST::Exception') ) { $e = $_; } else { $_->rethrow; } }; ok( !defined($e), 'login is successful' ); } # Create a user my $user_id; my %user_props = ( name => random_string(), password => random_string(), comments => random_string(), real_name => random_string(), ); { my ( $user, $e ); try { $user = RT::Client::REST::User->new( rt => $rt, %user_props, )->store; } catch { die $_ unless blessed $_ && $_->can('rethrow'); if ( $_->isa('RT::Client::REST::CouldNotCreateObjectException') ) { $e = $_; } else { $_->rethrow; } }; ok( defined($user), "user $user_props{name} created successfully, id: " . ( defined $user ? $user->id : 'UNDEF' ) ); ok( !defined($e), '...and no exception was thrown' ); $user_id = $user->id; } # Retrieve the user we just created and verify its properties { my $user = RT::Client::REST::User->new( rt => $rt, id => $user_id ); my $e; try { $user->retrieve; } catch { die $_ unless blessed $_ && $_->can('rethrow'); if ( $_->isa('Exception::Class::Base') ) { $e = $_; diag("fetching user threw $e"); } else { $_->rethrow; } }; ok( !defined($e), 'fetched user without exception being thrown' ); while ( my ( $prop, $val ) = each(%user_props) ) { next if $prop eq 'password'; # This property comes back obfuscated is( $user->$prop, $val, "user property `$prop' matches" ); } } # Create a queue my $queue_name = 'A queue named ' . random_string(); my $queue_id; my $queue; { my $e; try { $queue = RT::Client::REST::Queue->new( rt => $rt, name => $queue_name, )->store; $queue_id = $queue->id; } catch { die $_ unless blessed $_ && $_->can('rethrow'); if ( $_->isa('Exception::Class::Base') ) { $e = $_; diag("test queue store: $e"); } else { $_->rethrow; } }; ok( $queue, "Create test queue '$queue_name'" ); ok( !defined($e), 'created test queue without exception being thrown' ); } { my $e; try { $queue = RT::Client::REST::Queue->new( rt => $rt, id => $queue_id, )->retrieve; } catch { die $_ unless blessed $_ && $_->can('rethrow'); if ( $_->isa('Exception::Class::Base') ) { $e = $_; diag("queue retrieve $e"); } else { $_->rethrow; } }; is( $queue->name, $queue_name, 'test queue name matches' ); # TODO: with 4.2.3, warning "Unknown key: disabled" is printed } # Create a ticket my $ticket; { my $e; my $subject = 'This is a subject ' . random_string(); try { $ticket = RT::Client::REST::Ticket->new( rt => $rt, queue => $queue_id, subject => $subject, )->store( text => 'Some random text ' . random_string() ); } catch { die $_ unless blessed $_ && $_->can('rethrow'); if ( $_->isa('Exception::Class::Base') ) { $e = $_; diag("ticket store: $e"); } else { $_->rethrow; } }; ok( defined($ticket), "Created ticket '$subject' ID " . ( defined $ticket ? $ticket->id : 'UNDEF' ) ); ok( !defined($e), 'No exception thrown when ticket created' ); } # Attach something to the ticket and verify its count and contents { my $att_contents = "dude this is a text attachment\n"; my ( $fh, $filename ) = tempfile; $fh->print($att_contents); $fh->close; my $message = 'This is a message ' . random_string(), my $e; try { $ticket->comment( message => $message, attachments => [$filename], ); } catch { die $_ unless blessed $_ && $_->can('rethrow'); if ( $_->isa('Exception::Class::Base') ) { $e = $_; diag("attach to ticket: $e"); } else { $_->rethrow; } }; ok( !defined($e), 'Create attachment and no exception thrown' ); unlink $filename; $e = undef; try { my $atts = $ticket->attachments; # XXX With RT 4.2.3, the count is 4. Is it the same with previous # versions or is this a change in behavior? is( $atts->count, 4, 'There are 4 attachment to ticket ' . $ticket->id ); my $att_iter = $atts->get_iterator; my $basename = (splitpath($filename))[2]; my ($att) = grep { $_->file_name eq $basename } &$att_iter; if ($att) { ok(1, "Found attachment with filename: $basename"); is( $att->content, $att_contents, 'Attachment content matches' ); } else { ok(0, "Found attachment with filename: $basename"); } } catch { die $_ unless blessed $_ && $_->can('rethrow'); if ( $_->isa('Exception::Class::Base') ) { $e = $_; diag("attach to ticket: $e"); } else { $_->rethrow; } }; ok( !defined($e), 'listed attachments and no exception thrown' ); } # Comment with HTML { my $message = sprintf('Some <b>html</b> message text <pre>%s</pre>', random_string()); my $e; try { $ticket->comment( message => $message, html => 1 ); } catch { die $_ unless blessed $_ && $_->can('rethrow'); if ( $_->isa('Exception::Class::Base') ) { $e = $_; diag("attach to ticket: $e"); } else { $_->rethrow; } }; ok( !defined($e), 'Add html comment and no exception thrown' ); try { my $atts = $ticket->attachments; my $att_iter = $atts->get_iterator; my $att = (&$att_iter)[-1]; if ($att) { ok(1, 'Retrieved final attachment'); is( $att->content_type, 'text/html', 'Content-Type is text/html' ); } else { ok(0, 'Retrieved final attachment'); } } catch { die $_ unless blessed $_ && $_->can('rethrow'); if ( $_->isa('Exception::Class::Base') ) { $e = $_; diag("attach to ticket: $e"); } else { $_->rethrow; } }; ok( !defined($e), 'listed attachments and no exception thrown' ); } # Search for tickets (with format s) { my (@results, $e); try { @results = $rt->search( type => 'ticket', query => "Queue='$queue_name'", format => 's' ) } catch { die $_ unless blessed $_ && $_->can('rethrow'); if ( $_->isa('Exception::Class::Base') ) { $e = $_; diag("searching for tickets (with format s): $e"); } else { $_->rethrow; } }; ok( scalar @results > 0, 'Found some results (with format s)' ); is_deeply( \@results, [[ $ticket->id, $ticket->subject ]], 'Search results as expected (with format s)' ); ok( !defined($e), 'No exception thrown when searching tickets (with format s)' ); } # Delete the ticket { my $e; try { $ticket->status('deleted'); $ticket->store; } catch { die $_ unless blessed $_ && $_->can('rethrow'); if ( $_->isa('Exception::Class::Base') ) { $e = $_; diag("delete ticket: $e"); } else { $_->rethrow; } }; ok( !defined($e), 'ticket deleted and no exception thrown' ); } # TODO: RT 90112: Attachment retrieval returns wrongly decoded files # Disable the queue { my $e; try { $queue->disabled(1); $queue->store; } catch { die $_ unless blessed $_ && $_->can('rethrow'); if ( $_->isa('Exception::Class::Base') ) { $e = $_; diag("disable test queue: $e"); } else { $_->rethrow; } }; ok( !defined($e), 'disabled queue without exception being thrown' ); }