--- /dev/null
+#!/usr/bin/env perl
+
+use warnings;
+use strict;
+
+use FindBin '$Bin';
+use lib "$Bin/lib";
+
+use Test::Exception;
+use Test::More;
+
+use Future;
+use GraphQL::Client;
+use MockTransport;
+
+subtest 'transport' => sub {
+ my $client = GraphQL::Client->new(class => 'http');
+ isa_ok($client->transport, 'GraphQL::Client::http', 'decide transport from class');
+
+ $client = GraphQL::Client->new(url => 'https://localhost:4000/graphql');
+ isa_ok($client->transport, 'GraphQL::Client::http', 'decide transport from url');
+
+ $client = GraphQL::Client->new(class => 'not a real class');
+ is($client->class, 'not a real class', 'class constructor works');
+ throws_ok { $client->transport } qr/^Failed to load transport/, 'throws if invalid transport';
+};
+
+subtest 'request to transport' => sub {
+ my $mock = MockTransport->new;
+ my $client = GraphQL::Client->new(transport => $mock);
+
+ $client->execute('{hello}');
+ my $req = ($mock->requests)[-1];
+ is_deeply($req->[0], {
+ query => '{hello}',
+ }, 'query is passed to transport');
+
+ $client->execute('{hello}', {foo => 'bar'});
+ $req = ($mock->requests)[-1];
+ is_deeply($req->[0], {
+ query => '{hello}',
+ variables => {foo => 'bar'},
+ }, 'vars passed to transport');
+
+ $client->execute('{hello}', {foo => 'bar'}, 'opname');
+ $req = ($mock->requests)[-1];
+ is_deeply($req->[0], {
+ query => '{hello}',
+ variables => {foo => 'bar'},
+ operationName => 'opname',
+ }, 'operationName passed to transport');
+
+ $client->execute('{hello}', {foo => 'bar'}, 'opname', {baz => 'qux'});
+ $req = ($mock->requests)[-1];
+ is_deeply($req->[1], {
+ baz => 'qux',
+ }, 'transport options passed to transport');
+
+ $client->execute('{hello}', {foo => 'bar'}, {baz => 'qux'});
+ $req = ($mock->requests)[-1];
+ is_deeply($req->[1], {
+ baz => 'qux',
+ }, 'operation name can be ommitted with transport options');
+};
+
+subtest 'success response' => sub {
+ my $mock = MockTransport->new;
+ my $client = GraphQL::Client->new(transport => $mock);
+
+ $mock->response({
+ response => {
+ data => {
+ hello => 'Hello world!',
+ },
+ },
+ });
+ my $resp = $client->execute('{hello}');
+ is_deeply($resp, {
+ data => {hello => 'Hello world!'},
+ }, 'response is packed') or diag explain $resp;
+ {
+ local $client->{unpack} = 1;
+ my $resp = $client->execute('{hello}');
+ is_deeply($resp, {
+ hello => 'Hello world!',
+ }, 'success response is unpacked') or diag explain $resp;
+ };
+
+ $mock->response(Future->done({
+ response => {
+ data => {
+ hello => 'Hello world!',
+ },
+ },
+ }));
+ my $f = $client->execute('{hello}');
+ is_deeply($f->get, {
+ data => {hello => 'Hello world!'},
+ }, 'future response is packed') or diag explain $f->get;
+ {
+ local $client->{unpack} = 1;
+ my $f = $client->execute('{hello}');
+ is_deeply($f->get, {
+ hello => 'Hello world!',
+ }, 'future success response is unpacked') or diag explain $f->get;
+ };
+};
+
+subtest 'response with errors' => sub {
+ my $mock = MockTransport->new;
+ my $client = GraphQL::Client->new(transport => $mock);
+
+ $mock->response({
+ response => {
+ data => {
+ hello => 'Hello world!',
+ },
+ errors => [
+ {
+ message => 'Uh oh',
+ },
+ ],
+ },
+ });
+ my $resp = $client->execute('{hello}');
+ is_deeply($resp, {
+ data => {hello => 'Hello world!'},
+ errors => [{message => 'Uh oh'}],
+ }, 'response is packed') or diag explain $resp;
+ {
+ local $client->{unpack} = 1;
+ throws_ok { $client->execute('{hello}') } qr/^Uh oh$/, 'error response thrown';
+ my $err = $@;
+ is($err->error, 'Uh oh', 'error message is from first error');
+ is($err->type, 'graphql', 'error type is "graphql"');
+ my $resp = $err->{response};
+ is_deeply($resp, {
+ data => {hello => 'Hello world!'},
+ errors => [{message => 'Uh oh'}],
+ }, 'error includes the response') or diag explain $resp;
+ };
+
+ $mock->response({
+ response => undef,
+ error => 'Transport error',
+ details => {
+ foo => 'bar',
+ },
+ });
+ $resp = $client->execute('{hello}');
+ is_deeply($resp, {
+ errors => [{message => 'Transport error'}],
+ }, 'unpacked response munges error into response') or diag explain $resp;
+ {
+ local $client->{unpack} = 1;
+ throws_ok { $client->execute('{hello}') } qr/^Transport error$/, 'error response thrown';
+ my $err = $@;
+ my $resp = $err->{response};
+ is_deeply($resp, {
+ errors => [{message => 'Transport error'}],
+ }, 'error includes the constructed response') or diag explain $resp;
+ };
+};
+
+done_testing;