Failed Conditions
Pull Request — master (#25)
by Chad
02:50
created

ClientTest::callInvalidEntity()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 0
1
<?php
2
3
namespace Chadicus\Marvel\Api;
4
5
use Chadicus\Marvel\Api\Assets;
6
use Chadicus\Marvel\Api\Adapter\AdapterInterface;
7
8
/**
9
 * Unit tests for the Client class.
10
 *
11
 * @coversDefaultClass \Chadicus\Marvel\Api\Client
12
 * @covers ::<private>
13
 */
14
final class ClientTest extends \PHPUnit_Framework_TestCase
15
{
16
    /**
17
     * Set up each test.
18
     *
19
     * @return void
20
     */
21
    public function setUp()
22
    {
23
        \Chadicus\FunctionRegistry::reset(__NAMESPACE__, ['date']);
24
    }
25
26
    /**
27
     * Verify basic behavior of search().
28
     *
29
     * @test
30
     * @covers ::__construct
31
     * @covers ::search
32
     *
33
     * @return void
34
     */
35 View Code Duplication
    public function search()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
36
    {
37
        \Chadicus\FunctionRegistry::set(
38
            __NAMESPACE__,
39
            'time',
40
            function () {
41
                return 1;
42
            }
43
        );
44
45
        $adapter = new Assets\FakeAdapter();
46
        $client = new Client('aPrivateKey', 'aPublicKey', $adapter);
47
        $client->search('a Resource', ['key' => 'value']);
48
        $request = $adapter->getRequest();
49
        $hash = md5('1aPrivateKeyaPublicKey');
50
        $expectedUrl = Client::BASE_URL . "a+Resource?key=value&apikey=aPublicKey&ts=1&hash={$hash}";
51
52
        $this->assertSame('GET', $request->getMethod());
53
        $this->assertSame($expectedUrl, $request->getUrl());
54
    }
55
56
    /**
57
     * Verify proper exceptions thrown when Client is constructed with bad data.
58
     *
59
     * @param string           $privateApiKey The private api key issued by Marvel.
60
     * @param string           $publicApiKey  The public api key issued by Marvel.
61
     * @param AdapterInterface $adapter       Implementation of a client adapter.
62
     *
63
     * @test
64
     * @covers ::__construct
65
     * @dataProvider badConstructorData
66
     * @expectedException \InvalidArgumentException
67
     *
68
     * @return void
69
     */
70
    public function constructWithBadData($privateApiKey, $publicApiKey, AdapterInterface $adapter)
71
    {
72
        new Client($privateApiKey, $publicApiKey, $adapter);
73
    }
74
75
    /**
76
     * Data adapter for constructWithBadData test.
77
     *
78
     * @return array
79
     */
80
    public function badConstructorData()
81
    {
82
        return [
83
            // privateApiKey
84
            'privateApiKey is null' => [null, 'a public key', new Assets\FakeAdapter()],
85
            'privateApiKey is empty' => ['', 'a public key', new Assets\FakeAdapter()],
86
            'privateApiKey is whitespace' => [" \n\t", 'a public key', new Assets\FakeAdapter()],
87
            'privateApiKey is not a string' => [true, 'a public key', new Assets\FakeAdapter()],
88
            // publicApiKey
89
            'publicApiKey is null' => ['a private key', null, new Assets\FakeAdapter()],
90
            'publicApiKey is empty' => ['a private key', '', new Assets\FakeAdapter()],
91
            'publicApiKey is whitespace' => ['a private key', "\n \t", new Assets\FakeAdapter()],
92
            'publicApiKey is not a string' => ['a private key', false, new Assets\FakeAdapter()],
93
        ];
94
    }
95
96
    /**
97
     * Verify proper exceptions thrown when Client is constructed with bad data.
98
     *
99
     * @param string $resource The API resource to search for.
100
     * @param array  $filters  Array of search criteria to use in request.
101
     *
102
     * @test
103
     * @covers ::search
104
     * @dataProvider badSearchData
105
     * @expectedException \InvalidArgumentException
106
     *
107
     * @return void
108
     */
109
    public function searchtWithBadData($resource, array $filters)
110
    {
111
        (new Client('not under test', 'not under test', new Assets\FakeAdapter()))->search($resource, $filters);
112
    }
113
114
    /**
115
     * Data adapter for searchWithBadData test.
116
     *
117
     * @return array
118
     */
119 View Code Duplication
    public function badSearchData()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
120
    {
121
        return [
122
            // resource
123
            'resource is null' => [null, []],
124
            'resource is empty' => ['', []],
125
            'resource is whitespace' => [" \n\t", []],
126
            'resource is not a string' => [true, []],
127
        ];
128
    }
129
130
    /**
131
     * Verify basic behavior of get().
132
     *
133
     * @test
134
     * @covers ::__construct
135
     * @covers ::get
136
     *
137
     * @return void
138
     */
139 View Code Duplication
    public function get()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
140
    {
141
        \Chadicus\FunctionRegistry::set(
142
            __NAMESPACE__,
143
            'time',
144
            function () {
145
                return 1;
146
            }
147
        );
148
149
        $adapter = new Assets\FakeAdapter();
150
        $client = new Client('aPrivateKey', 'aPublicKey', $adapter);
151
        $client->get('a Resource', 1);
152
        $request = $adapter->getRequest();
153
        $hash = md5('1aPrivateKeyaPublicKey');
154
        $expectedUrl = Client::BASE_URL . "a+Resource/1?apikey=aPublicKey&ts=1&hash={$hash}";
155
156
        $this->assertSame('GET', $request->getMethod());
157
        $this->assertSame($expectedUrl, $request->getUrl());
158
    }
159
160
    /**
161
     * Verify proper exceptions thrown when Client is constructed with bad data.
162
     *
163
     * @param string  $resource The API resource to search for.
164
     * @param integer $id       The id of the API resource.
165
     *
166
     * @test
167
     * @covers ::get
168
     * @dataProvider badGetData
169
     * @expectedException \InvalidArgumentException
170
     *
171
     * @return void
172
     */
173
    public function gettWithBadData($resource, $id)
174
    {
175
        (new Client('not under test', 'not under test', new Assets\FakeAdapter()))->get($resource, $id);
176
    }
177
178
    /**
179
     * Data adapter for getWithBadData test.
180
     *
181
     * @return array
182
     */
183
    public function badGetData()
184
    {
185
        return [
186
            // resource
187
            'resource is null' => [null, 1],
188
            'resource is empty' => ['',1],
189
            'resource is whitespace' => [" \n\t",1],
190
            'resource is not a string' => [true,1],
191
            // id
192
            'id is null' => ['a resource', null],
193
            'id is not an integer' => ['a resource', true],
194
        ];
195
    }
196
197
    /**
198
     * Verfiy response is return from cache.
199
     *
200
     * @test
201
     * @covers ::get
202
     *
203
     * @return void
204
     */
205
    public function getFromCache()
206
    {
207
        \Chadicus\FunctionRegistry::set(
208
            __NAMESPACE__,
209
            'time',
210
            function () {
211
                return 1;
212
            }
213
        );
214
215
        $hash = md5('1aPrivateKeyaPublicKey');
216
        $cache = new Cache\ArrayCache();
217
        $cache->set(
218
            new Request(Client::BASE_URL . "a+Resource/1?apikey=aPublicKey&ts=1&hash={$hash}", 'GET'),
219
            new Response(599, ['custom' => 'header'], ['key' => 'value'])
220
        );
221
        $adapter = new Assets\FakeAdapter();
222
        $client = new Client('aPrivateKey', 'aPublicKey', $adapter, $cache);
223
        $response = $client->get('a Resource', 1);
224
        $this->assertSame(599, $response->getHttpCode());
225
        $this->assertSame(['custom' => 'header'], $response->getHeaders());
226
        $this->assertSame(['key' => 'value'], $response->getBody());
227
228
        // assert the adapter was not used
229
        $this->assertNull($adapter->getRequest());
230
    }
231
232
    /**
233
     * Verfiy response is return from cache.
234
     *
235
     * @test
236
     * @covers ::get
237
     *
238
     * @return void
239
     */
240
    public function getSetsCache()
241
    {
242
        \Chadicus\FunctionRegistry::set(
243
            __NAMESPACE__,
244
            'time',
245
            function () {
246
                return 1;
247
            }
248
        );
249
250
        $hash = md5('1aPrivateKeyaPublicKey');
251
        $request = new Request(Client::BASE_URL . "a+Resource/1?apikey=aPublicKey&ts=1&hash={$hash}", 'GET');
252
253
        $cache = new Cache\ArrayCache();
254
        $adapter = new Assets\FakeAdapter();
255
        $client = new Client('aPrivateKey', 'aPublicKey', $adapter, $cache);
256
        $response = $client->get('a Resource', 1);
257
258
        $cachedResponse = $cache->get($request);
259
        $this->assertSame($response->getHttpCode(), $cachedResponse->getHttpCode());
260
        $this->assertSame($response->getHeaders(), $cachedResponse->getHeaders());
261
        $this->assertSame($response->getBody(), $cachedResponse->getBody());
262
    }
263
264
    /**
265
     * Verify bahvior of __call() for single entity.
266
     *
267
     * @test
268
     * @covers ::__call
269
     *
270
     * @return void
271
     */
272
    public function callEntity()
273
    {
274
        $client = new Client('not under test', 'not under test', new Assets\ComicAdapter());
275
        $comic = $client->comics(2);
0 ignored issues
show
Documentation Bug introduced by
The method comics does not exist on object<Chadicus\Marvel\Api\Client>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
276
        $this->assertInstanceOf('Chadicus\Marvel\Api\Entities\Comic', $comic);
277
        $this->assertSame(2, $comic->getId());
278
    }
279
280
    /**
281
     * Verify bahvior of __call() for entity that is not found.
282
     *
283
     * @test
284
     * @covers ::__call
285
     *
286
     * @return void
287
     */
288
    public function callEntityNotFound()
289
    {
290
        $client = new Client('not under test', 'not under test', new Assets\EmptyAdapter());
291
        $comic = $client->comics(1);
0 ignored issues
show
Documentation Bug introduced by
The method comics does not exist on object<Chadicus\Marvel\Api\Client>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
292
        $this->assertNull($comic);
293
    }
294
295
    /**
296
     * Verify bahvior of __call() for entity that is invalid.
297
     *
298
     * @test
299
     * @covers ::__call
300
     *
301
     * @return void
302
     */
303
    public function callInvalidEntity()
304
    {
305
        $client = new Client('not under test', 'not under test', new Assets\ErrorAdapter());
306
        $result = $client->batman(1);
0 ignored issues
show
Documentation Bug introduced by
The method batman does not exist on object<Chadicus\Marvel\Api\Client>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
307
        $this->assertNull($result);
308
    }
309
310
    /**
311
     * Verify basic bahvior of __call() for entity collection.
312
     *
313
     * @test
314
     * @covers ::__call
315
     *
316
     * @return void
317
     */
318
    public function callCollection()
319
    {
320
        $client = new Client('not under test', 'not under test', new Assets\ComicAdapter());
321
        $comics = $client->comics();
0 ignored issues
show
Documentation Bug introduced by
The method comics does not exist on object<Chadicus\Marvel\Api\Client>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
322
        $this->assertInstanceOf('Chadicus\Marvel\Api\Collection', $comics);
323
        $this->assertSame(5, $comics->count());
324
        foreach ($comics as $key => $comic) {
325
            $this->assertSame($key + 1, $comic->getId());
326
        }
327
    }
328
}
329