--- /dev/null
+#!/usr/bin/env perl
+
+use warnings;
+use strict;
+
+use FindBin '$Bin';
+use lib "$Bin/lib";
+
+use Test::Deep;
+use Test::Exception;
+use Test::More;
+
+use Future;
+use GraphQL::Client::http;
+
+HTTP::AnyUA->register_backend(MockUA => '+MockUA');
+
+my $URL = 'http://localhost:4000/graphql';
+
+subtest 'attributes' => sub {
+ my $http = GraphQL::Client::http->new;
+
+ is($http->method, 'POST', 'default method is POST');
+ is($http->url, undef, 'default url is undefined');
+
+ $http = GraphQL::Client::http->new(method => 'HEAD', url => $URL);
+
+ is($http->method, 'HEAD', 'method getter returns correctly');
+ is($http->url, $URL, 'url getter returns correctly');
+};
+
+subtest 'bad arguments to execute' => sub {
+ my $http = GraphQL::Client::http->new(ua => 'MockUA');
+ my $mock = $http->any_ua->backend;
+
+ throws_ok {
+ $http->execute('blah');
+ } qr/^Usage:/, 'first argument must be a hashref';
+
+ throws_ok {
+ $http->execute({});
+ } qr/^Request must have a query/, 'request must have a query';
+
+ throws_ok {
+ $http->execute({query => '{hello}'});
+ } qr/^URL must be provided/, 'request must have a URL';
+};
+
+subtest 'POST request' => sub {
+ my $http = GraphQL::Client::http->new(ua => 'MockUA', url => $URL);
+ my $mock = $http->any_ua->backend;
+
+ my $resp = $http->execute({
+ query => '{hello}',
+ });
+ my $req = ($mock->requests)[-1];
+
+ is($req->[0], 'POST', 'method is POST');
+ is($req->[2]{content}, '{"query":"{hello}"}', 'encoded body as JSON');
+ is($req->[2]{headers}{'content-type'}, 'application/json', 'set content-type to json');
+};
+
+subtest 'GET request' => sub {
+ my $http = GraphQL::Client::http->new(ua => 'MockUA', url => $URL);
+ my $mock = $http->any_ua->backend;
+
+ $http->execute({
+ query => '{hello}',
+ }, {
+ method => 'GET',
+ });
+ my $req = ($mock->requests)[-1];
+
+ is($req->[0], 'GET', 'method is GET');
+ is($req->[1], "$URL?query=%7Bhello%7D", 'encoded query in params');
+ is($req->[2]{content}, undef, 'no content');
+
+ $http->execute({
+ query => '{hello}',
+ }, {
+ method => 'GET',
+ url => "$URL?foo=bar",
+ });
+ $req = ($mock->requests)[-1];
+
+ is($req->[1], "$URL?foo=bar&query=%7Bhello%7D", 'encoded query in params with existing param');
+};
+
+subtest 'plain response' => sub {
+ my $http = GraphQL::Client::http->new(ua => 'MockUA', url => $URL);
+ my $mock = $http->any_ua->backend;
+
+ $mock->response({
+ content => '{"data":{"foo":"bar"}}',
+ reason => 'OK',
+ status => 200,
+ success => 1,
+ });
+ my $r = $http->execute({query => '{hello}'});
+ my $expected = {
+ response => {
+ data => {foo => 'bar'},
+ },
+ details => {
+ http_response => $mock->response,
+ },
+ };
+ is_deeply($r, $expected, 'success response') or diag explain $r;
+
+ $mock->response({
+ content => '{"data":{"foo":"bar"},"errors":[{"message":"uh oh"}]}',
+ reason => 'OK',
+ status => 200,
+ success => 1,
+ });
+ $r = $http->execute({query => '{hello}'});
+ $expected = {
+ response => {
+ data => {foo => 'bar'},
+ errors => [{message => 'uh oh'}],
+ },
+ details => {
+ http_response => $mock->response,
+ },
+ };
+ is_deeply($r, $expected, 'response with graphql errors') or diag explain $r;
+
+ $mock->response({
+ content => 'The agent failed',
+ reason => 'Internal Exception',
+ status => 599,
+ success => '',
+ });
+ my $resp = $http->execute({query => '{hello}'});
+ $expected = {
+ error => 'HTTP transport returned 599 (Internal Exception): The agent failed',
+ response => undef,
+ details => {
+ http_response => $mock->response,
+ },
+ };
+ is_deeply($resp, $expected, 'response with http error') or diag explain $resp;
+
+ $mock->response({
+ content => 'not json',
+ reason => 'OK',
+ status => 200,
+ success => 1,
+ });
+ $r = $http->execute({query => '{hello}'});
+ $expected = {
+ error => re('^HTTP transport failed to decode response:'),
+ response => undef,
+ details => {
+ http_response => $mock->response,
+ },
+ };
+ cmp_deeply($r, $expected, 'response with invalid response') or diag explain $r;
+};
+
+subtest 'future response' => sub {
+ my $http = GraphQL::Client::http->new(ua => 'MockUA', url => $URL);
+ my $mock = $http->any_ua->backend;
+
+ $mock->response(Future->done({
+ content => '{"data":{"foo":"bar"}}',
+ reason => 'OK',
+ status => 200,
+ success => 1,
+ }));
+ my $f = $http->execute({query => '{hello}'});
+ my $expected = {
+ response => {
+ data => {foo => 'bar'},
+ },
+ details => {
+ http_response => $mock->response->get,
+ },
+ };
+ is_deeply($f->get, $expected, 'success response') or diag explain $f->get;
+
+ $mock->response(Future->done({
+ content => '{"data":{"foo":"bar"},"errors":[{"message":"uh oh"}]}',
+ reason => 'OK',
+ status => 200,
+ success => 1,
+ }));
+ $f = $http->execute({query => '{hello}'});
+ $expected = {
+ response => {
+ data => {foo => 'bar'},
+ errors => [{message => 'uh oh'}],
+ },
+ details => {
+ http_response => $mock->response->get,
+ },
+ };
+ is_deeply($f->get, $expected, 'response with graphql errors') or diag explain $f->get;
+
+ $mock->response(Future->fail({
+ content => 'The agent failed',
+ reason => 'Internal Exception',
+ status => 599,
+ success => '',
+ }));
+ $expected = {
+ error => 'HTTP transport returned 599 (Internal Exception): The agent failed',
+ response => undef,
+ details => {
+ http_response => ($mock->response->failure)[0],
+ },
+ };
+ $f = $http->execute({query => '{hello}'});
+ is_deeply($f->get, $expected, 'response with http error') or diag explain $f->get;
+};
+
+done_testing;