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() |
|
|
|
|
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() |
|
|
|
|
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() |
|
|
|
|
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); |
|
|
|
|
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); |
|
|
|
|
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); |
|
|
|
|
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(); |
|
|
|
|
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
|
|
|
|
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.