Passed
Pull Request — master (#2)
by Samuel
01:59 queued 21s
created

HttpClientTest   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 133
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 13
eloc 56
dl 0
loc 133
c 1
b 0
f 0
rs 10

11 Methods

Rating   Name   Duplication   Size   Complexity  
A isValidOptionsArray() 0 16 3
A tearDown() 0 4 1
A setUp() 0 11 1
A createHttpClient() 0 8 1
A testOptions() 0 11 1
A testUnsafeMethod() 0 8 1
A provideForGetQueryString() 0 5 1
A provideForUnsafeMethod() 0 6 1
A testGetQueryString() 0 8 1
A isRequestFor() 0 10 1
A setUpBeforeClass() 0 3 1
1
<?php
2
3
namespace Elmage\TextNg\Test\Unit;
4
5
use Elmage\TextNg\Enum\Param;
6
use Elmage\TextNg\Authentication\ApiKeyAuthentication;
7
use Elmage\TextNg\Test\TestCase;
8
use Elmage\TextNg\HttpClient;
9
use Elmage\TextNg\Configuration;
10
use GuzzleHttp\Psr7\Response;
11
use PHPUnit\Framework\Constraint\Callback;
12
use PHPUnit\Framework\MockObject\MockObject;
13
use GuzzleHttp\ClientInterface;
14
use Psr\Http\Message\RequestInterface;
15
16
class HttpClientTest extends TestCase
17
{
18
    /** @var MockObject|ClientInterface */
19
    private $transport;
20
21
    /** @var HttpClient */
22
    private $client;
23
24
    public static function setUpBeforeClass(): void
25
    {
26
        date_default_timezone_set('Africa/Lagos');
27
    }
28
29
    protected function setUp(): void
30
    {
31
        $this->transport = $this->getMockBuilder(ClientInterface::class)->getMock();
32
33
        $authStub = $this->createStub(ApiKeyAuthentication::class);
34
35
        // Configure the stub.
36
        $authStub->method('getApiKey')
37
            ->will($this->returnValue("TEST_KEY"));
38
39
        $this->client = $this->createHttpClient($authStub);
40
    }
41
42
    protected function tearDown(): void
43
    {
44
        $this->transport = null;
45
        $this->client = null;
46
    }
47
48
    /**
49
     * @dataProvider provideForGetQueryString
50
     */
51
    public function testGetQueryString(string $path, string $expected): void
52
    {
53
        $this->transport->expects($this->once())
54
            ->method('send')
55
            ->with($this->isRequestFor('GET', $expected))
56
            ->will($this->returnValue(new Response()));
57
58
        $this->client->get($path, ['foo' => 'bar']);
59
    }
60
61
    public function provideForGetQueryString(): array
62
    {
63
        return [
64
            ['/', '/?foo=bar&key=TEST_KEY'],
65
            ['/?bar=foo', '/?bar=foo&foo=bar&key=TEST_KEY'],
66
        ];
67
    }
68
69
    /**
70
     * @dataProvider provideForUnsafeMethod
71
     */
72
    public function testUnsafeMethod(string $method): void
73
    {
74
        $this->transport->expects($this->once())
75
            ->method('send')
76
            ->with($this->isRequestFor(strtoupper($method), '/'))
77
            ->will($this->returnValue(new Response()));
78
79
        $this->client->$method('/', ['foo' => 'bar']);
80
    }
81
82
    public function provideForUnsafeMethod(): array
83
    {
84
        return [
85
            ['put'],
86
            ['post'],
87
            ['delete'],
88
        ];
89
    }
90
91
    public function testOptions(): void
92
    {
93
        $this->transport->expects($this->once())
94
            ->method('send')
95
            ->with(
96
                $this->isRequestFor('POST', '/'),
97
                $this->isValidOptionsArray([])
98
            )
99
            ->will($this->returnValue(new Response()));
100
101
        $this->client->post('/', ['foo' => 'bar']);
102
    }
103
104
    /*------------------------------------------------------------------------------
105
    | PRIVATE METHODS
106
    /*------------------------------------------------------------------------------*/
107
108
    private function isRequestFor(string $method, string $path): Callback
109
    {
110
        return $this->callback(
111
            function ($request) use ($method, $path) {
112
                /** @var RequestInterface $request */
113
                $this->assertInstanceOf(RequestInterface::class, $request);
114
                $this->assertEquals($method, $request->getMethod());
115
                $this->assertEquals($path, $request->getRequestTarget());
116
117
                return true;
118
            }
119
        );
120
    }
121
122
    private function isValidOptionsArray(array $headers = [], $json = true): Callback
123
    {
124
        return $this->callback(function ($options) use ($headers, $json) {
125
            $this->assertArrayHasKey('headers', $options);
126
            $this->assertArrayHasKey('User-Agent', $options['headers']);
127
            $this->assertArrayHasKey('Content-Type', $options['headers']);
128
129
            if ($json) {
130
                $this->assertArrayHasKey('json', $options);
131
            }
132
133
            foreach ($headers as $header) {
134
                $this->assertArrayHasKey($header, $options['headers']);
135
            }
136
137
            return true;
138
        });
139
    }
140
141
    private function createHttpClient(ApiKeyAuthentication $auth): HttpClient
142
    {
143
        return new HttpClient(
144
            Configuration::DEFAULT_API_URL,
145
            Configuration::DEFAULT_API_VERSION,
146
            $auth,
147
            "TestSender",
148
            $this->transport
149
        );
150
    }
151
152
}
153
154