chadicus /
marvel-api-client
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 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
|
|||
| 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
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
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
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 This is often the case, when 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
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 This is often the case, when 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
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 This is often the case, when 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
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 This is often the case, when 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 |
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.