[Bps-public-commit] rt-extension-rest2 branch, master, updated. b5222f00615ff4618f4e141bc92b779cef7f5a18

Shawn Moore shawn at bestpractical.com
Fri Jun 16 18:42:26 EDT 2017


The branch, master has been updated
       via  b5222f00615ff4618f4e141bc92b779cef7f5a18 (commit)
       via  bcdadd27ca9744032865ce37d987ffd186b673ca (commit)
       via  a1e31e02f8dd75a319636d3cc3581499b6e3c5e0 (commit)
      from  f840702d2d80e4e0c8557968fc6ba2a1986e0a5d (commit)

Summary of changes:
 lib/RT/Extension/REST2/Resource/Record/Writable.pm |  38 ++++
 t/ticket-customfields.t                            | 244 +++++++++++++++++++++
 t/tickets.t                                        |  17 ++
 3 files changed, 299 insertions(+)
 create mode 100644 t/ticket-customfields.t

- Log -----------------------------------------------------------------
commit a1e31e02f8dd75a319636d3cc3581499b6e3c5e0
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Fri Jun 16 19:56:37 2017 +0000

    Basic ticket CF tests

diff --git a/t/ticket-customfields.t b/t/ticket-customfields.t
new file mode 100644
index 0000000..a60a349
--- /dev/null
+++ b/t/ticket-customfields.t
@@ -0,0 +1,141 @@
+use strict;
+use warnings;
+use lib 't/lib';
+use RT::Extension::REST2::Test tests => undef;
+
+my $mech = RT::Extension::REST2::Test->mech;
+
+my $auth = RT::Extension::REST2::Test->authorization_header;
+my $rest_base_path = '/REST/2.0';
+my $user = RT::Extension::REST2::Test->user;
+
+my $queue = RT::Test->load_or_create_queue( Name => "General" );
+
+my $cf = RT::CustomField->new( RT->SystemUser );
+$cf->Create( Name => 'Freeform', Type => 'FreeformSingle', Queue => $queue->Id );
+
+# Ticket Creation with no ModifyCustomField
+my ($ticket_url, $ticket_id);
+{
+    my $payload = {
+        Subject => 'Ticket creation using REST',
+        From    => 'test at bestpractical.com',
+        To      => 'rt at localhost',
+        Queue   => 'General',
+        Content => 'Testing ticket creation using REST API.',
+        'CustomField-' . $cf->Id => 'Hello world!',
+    };
+
+    # Rights Test - No CreateTicket
+    my $res = $mech->post_json("$rest_base_path/ticket",
+        $payload,
+        'Authorization' => $auth,
+    );
+    TODO: {
+        local $TODO = "this should return 403";
+        is($res->code, 403);
+    }
+
+    my @warnings;
+    local $SIG{__WARN__} = sub {
+        push @warnings, @_;
+    };
+
+    # Rights Test - With CreateTicket
+    $user->PrincipalObj->GrantRight( Right => 'CreateTicket' );
+    $res = $mech->post_json("$rest_base_path/ticket",
+        $payload,
+        'Authorization' => $auth,
+    );
+    is($res->code, 201);
+    ok($ticket_url = $res->header('location'));
+    ok(($ticket_id) = $ticket_url =~ qr[/ticket/(\d+)]);
+
+   TODO: {
+       local $TODO = "this warns due to specifying a CF with no permission to see";
+       is(@warnings, 0, "no warnings");
+   }
+}
+
+# Ticket Display
+{
+    # Rights Test - No ShowTicket
+    my $res = $mech->get($ticket_url,
+        'Authorization' => $auth,
+    );
+    is($res->code, 403);
+}
+
+# Rights Test - With ShowTicket but no SeeCustomField
+{
+    $user->PrincipalObj->GrantRight( Right => 'ShowTicket' );
+
+    my $res = $mech->get($ticket_url,
+        'Authorization' => $auth,
+    );
+    is($res->code, 200);
+
+    my $content = $mech->json_response;
+    is($content->{id}, $ticket_id);
+    is($content->{Type}, 'ticket');
+    is($content->{Status}, 'new');
+    is($content->{Subject}, 'Ticket creation using REST');
+    is_deeply($content->{'CF.Freeform'}, undef, 'Ticket custom field not present');
+}
+
+# Rights Test - With ShowTicket and SeeCustomField
+{
+    $user->PrincipalObj->GrantRight( Right => 'SeeCustomField', Object => $cf);
+
+    my $res = $mech->get($ticket_url,
+        'Authorization' => $auth,
+    );
+    is($res->code, 200);
+
+    my $content = $mech->json_response;
+    is($content->{id}, $ticket_id);
+    is($content->{Type}, 'ticket');
+    is($content->{Status}, 'new');
+    is($content->{Subject}, 'Ticket creation using REST');
+    is_deeply($content->{'CF.Freeform'}, [], 'Ticket custom field');
+}
+
+# Ticket Creation with ModifyCustomField
+{
+    $user->PrincipalObj->GrantRight( Right => 'ModifyCustomField', Object => $cf);
+
+    my $payload = {
+        Subject => 'Ticket creation using REST',
+        From    => 'test at bestpractical.com',
+        To      => 'rt at localhost',
+        Queue   => 'General',
+        Content => 'Testing ticket creation using REST API.',
+        'CustomField-' . $cf->Id => 'Hello world!',
+    };
+
+    my $res = $mech->post_json("$rest_base_path/ticket",
+        $payload,
+        'Authorization' => $auth,
+    );
+    is($res->code, 201);
+    ok($ticket_url = $res->header('location'));
+    ok(($ticket_id) = $ticket_url =~ qr[/ticket/(\d+)]);
+}
+
+# Rights Test - With ShowTicket and SeeCustomField
+{
+    my $res = $mech->get($ticket_url,
+        'Authorization' => $auth,
+    );
+    is($res->code, 200);
+
+    my $content = $mech->json_response;
+    is($content->{id}, $ticket_id);
+    is($content->{Type}, 'ticket');
+    is($content->{Status}, 'new');
+    is($content->{Subject}, 'Ticket creation using REST');
+    is_deeply($content->{'CF.Freeform'}, ['Hello world!'], 'Ticket custom field');
+}
+
+done_testing;
+

commit bcdadd27ca9744032865ce37d987ffd186b673ca
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Fri Jun 16 21:35:09 2017 +0000

    Single-value CF updates

diff --git a/lib/RT/Extension/REST2/Resource/Record/Writable.pm b/lib/RT/Extension/REST2/Resource/Record/Writable.pm
index 3c14152..1edb800 100644
--- a/lib/RT/Extension/REST2/Resource/Record/Writable.pm
+++ b/lib/RT/Extension/REST2/Resource/Record/Writable.pm
@@ -44,12 +44,50 @@ sub update_record {
         ARGSRef       => $data,
         AttributesRef => [ $self->record->WritableAttributes ],
     );
+
+    push @results, $self->_update_custom_fields($data);
+
     # XXX TODO: Figure out how to return success/failure?  Core RT::Record's
     # ->Update will need to be replaced or improved.
     $self->response->body( JSON::encode_json(\@results) );
     return;
 }
 
+sub _update_custom_fields {
+    my $self = shift;
+    my $data = shift;
+
+    my $record = $self->record;
+    my @results;
+
+    foreach my $arg ( keys %$data ) {
+        next unless $arg =~ /^CustomField-(\d+)$/i;
+        my $cfid = $1;
+        my $cf = $record->LoadCustomFieldByIdentifier($cfid);
+        next unless $cf->ObjectTypeFromLookupType($cf->__Value('LookupType'))->isa(ref $record);
+
+        if ($cf->SingleValue) {
+            my $val = $data->{$arg};
+            if (ref($val) eq 'ARRAY') {
+                $val = $val->[0];
+            }
+            elsif (ref($val)) {
+                die "Invalid value type for $arg";
+            }
+
+            my ($ok, $msg) = $record->AddCustomFieldValue(
+                Field => $cf,
+                Value => $val,
+            );
+            push @results, $msg;
+        }
+        else {
+        }
+    }
+
+    return @results;
+}
+
 sub update_resource {
     my $self = shift;
     my $data = shift;
diff --git a/t/ticket-customfields.t b/t/ticket-customfields.t
index a60a349..89a432f 100644
--- a/t/ticket-customfields.t
+++ b/t/ticket-customfields.t
@@ -11,8 +11,13 @@ my $user = RT::Extension::REST2::Test->user;
 
 my $queue = RT::Test->load_or_create_queue( Name => "General" );
 
-my $cf = RT::CustomField->new( RT->SystemUser );
-$cf->Create( Name => 'Freeform', Type => 'FreeformSingle', Queue => $queue->Id );
+my $single_cf = RT::CustomField->new( RT->SystemUser );
+my ($ok, $msg) = $single_cf->Create( Name => 'Freeform', Type => 'FreeformSingle', Queue => $queue->Id );
+ok($ok, $msg);
+
+my $multi_cf = RT::CustomField->new( RT->SystemUser );
+($ok, $msg) = $multi_cf->Create( Name => 'Multi', Type => 'FreeformMultiple', Queue => $queue->Id );
+ok($ok, $msg);
 
 # Ticket Creation with no ModifyCustomField
 my ($ticket_url, $ticket_id);
@@ -23,7 +28,7 @@ my ($ticket_url, $ticket_id);
         To      => 'rt at localhost',
         Queue   => 'General',
         Content => 'Testing ticket creation using REST API.',
-        'CustomField-' . $cf->Id => 'Hello world!',
+        'CustomField-' . $single_cf->Id => 'Hello world!',
     };
 
     # Rights Test - No CreateTicket
@@ -85,7 +90,7 @@ my ($ticket_url, $ticket_id);
 
 # Rights Test - With ShowTicket and SeeCustomField
 {
-    $user->PrincipalObj->GrantRight( Right => 'SeeCustomField', Object => $cf);
+    $user->PrincipalObj->GrantRight( Right => 'SeeCustomField', Object => $single_cf);
 
     my $res = $mech->get($ticket_url,
         'Authorization' => $auth,
@@ -100,17 +105,115 @@ my ($ticket_url, $ticket_id);
     is_deeply($content->{'CF.Freeform'}, [], 'Ticket custom field');
 }
 
-# Ticket Creation with ModifyCustomField
+# Ticket Update without ModifyCustomField
 {
-    $user->PrincipalObj->GrantRight( Right => 'ModifyCustomField', Object => $cf);
+    my $payload = {
+        Subject  => 'Ticket update using REST',
+        Priority => 42,
+        'CustomField-'.$single_cf->Id => 'Modified CF',
+    };
+
+    # Rights Test - No ModifyTicket
+    my $res = $mech->put_json($ticket_url,
+        $payload,
+        'Authorization' => $auth,
+    );
+    TODO: {
+        local $TODO = "RT ->Update isn't introspectable";
+        is($res->code, 403);
+    };
+    is_deeply($mech->json_response, ['Ticket 1: Permission Denied', 'Ticket 1: Permission Denied', 'Could not add new custom field value: Permission Denied']);
+
+    $user->PrincipalObj->GrantRight( Right => 'ModifyTicket' );
 
+    $res = $mech->put_json($ticket_url,
+        $payload,
+        'Authorization' => $auth,
+    );
+    is($res->code, 200);
+    is_deeply($mech->json_response, ["Ticket 1: Priority changed from (no value) to '42'", "Ticket 1: Subject changed from 'Ticket creation using REST' to 'Ticket update using REST'", 'Could not add new custom field value: Permission Denied']);
+
+    $res = $mech->get($ticket_url,
+        'Authorization' => $auth,
+    );
+    is($res->code, 200);
+
+    my $content = $mech->json_response;
+    is($content->{Subject}, 'Ticket update using REST');
+    is($content->{Priority}, 42);
+    is_deeply($content->{'CF.Freeform'}, [], 'No update to CF');
+}
+
+# Ticket Update with ModifyCustomField
+{
+    $user->PrincipalObj->GrantRight( Right => 'ModifyCustomField', Object => $single_cf);
+    my $payload = {
+        Subject  => 'More updates using REST',
+        Priority => 43,
+        'CustomField-'.$single_cf->Id => 'Modified CF',
+    };
+    my $res = $mech->put_json($ticket_url,
+        $payload,
+        'Authorization' => $auth,
+    );
+    is($res->code, 200);
+    is_deeply($mech->json_response, ["Ticket 1: Priority changed from '42' to '43'", "Ticket 1: Subject changed from 'Ticket update using REST' to 'More updates using REST'", 'Freeform Modified CF added']);
+
+    $res = $mech->get($ticket_url,
+        'Authorization' => $auth,
+    );
+    is($res->code, 200);
+
+    my $content = $mech->json_response;
+    is($content->{Subject}, 'More updates using REST');
+    is($content->{Priority}, 43);
+    is_deeply($content->{'CF.Freeform'}, ['Modified CF'], 'New CF value');
+
+    # make sure changing the CF doesn't add a second OCFV
+    $payload->{'CustomField-'.$single_cf->Id} = 'Modified Again';
+    $res = $mech->put_json($ticket_url,
+        $payload,
+        'Authorization' => $auth,
+    );
+    is($res->code, 200);
+    is_deeply($mech->json_response, ['Freeform Modified CF changed to Modified Again']);
+
+    $res = $mech->get($ticket_url,
+        'Authorization' => $auth,
+    );
+    is($res->code, 200);
+
+    $content = $mech->json_response;
+    is_deeply($content->{'CF.Freeform'}, ['Modified Again'], 'New CF value');
+
+    # stop changing the CF, change something else, make sure CF sticks around
+    delete $payload->{'CustomField-'.$single_cf->Id};
+    $payload->{Subject} = 'No CF change';
+    $res = $mech->put_json($ticket_url,
+        $payload,
+        'Authorization' => $auth,
+    );
+    is($res->code, 200);
+    is_deeply($mech->json_response, ["Ticket 1: Subject changed from 'More updates using REST' to 'No CF change'"]);
+
+    $res = $mech->get($ticket_url,
+        'Authorization' => $auth,
+    );
+    is($res->code, 200);
+
+    $content = $mech->json_response;
+    is_deeply($content->{'CF.Freeform'}, ['Modified Again'], 'Same CF value');
+}
+
+# Ticket Creation with ModifyCustomField
+{
     my $payload = {
         Subject => 'Ticket creation using REST',
         From    => 'test at bestpractical.com',
         To      => 'rt at localhost',
         Queue   => 'General',
         Content => 'Testing ticket creation using REST API.',
-        'CustomField-' . $cf->Id => 'Hello world!',
+        'CustomField-' . $single_cf->Id => 'Hello world!',
     };
 
     my $res = $mech->post_json("$rest_base_path/ticket",

commit b5222f00615ff4618f4e141bc92b779cef7f5a18
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Fri Jun 16 21:40:01 2017 +0000

    Make sure posting the same update doesn't result in changes

diff --git a/t/tickets.t b/t/tickets.t
index db19564..b0d3a28 100644
--- a/t/tickets.t
+++ b/t/tickets.t
@@ -210,6 +210,23 @@ my ($ticket_url, $ticket_id);
     is($links->[4]{update}, 'Respond');
     is($links->[4]{from}, 'new');
     is($links->[4]{to}, 'rejected');
+
+    # update again with no changes
+    $res = $mech->put_json($ticket_url,
+        $payload,
+        'Authorization' => $auth,
+    );
+    is($res->code, 200);
+    is_deeply($mech->json_response, []);
+
+    $res = $mech->get($ticket_url,
+        'Authorization' => $auth,
+    );
+    is($res->code, 200);
+
+    $content = $mech->json_response;
+    is($content->{Subject}, 'Ticket update using REST');
+    is($content->{Priority}, 42);
 }
 
 # Transactions

-----------------------------------------------------------------------


More information about the Bps-public-commit mailing list