scriptotek /
php-alma-client
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
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 spec\Scriptotek\Alma; |
||
| 4 | |||
| 5 | use GuzzleHttp\Psr7\Response; |
||
| 6 | use Http\Client\Common\Exception\ServerErrorException; |
||
| 7 | use Http\Mock\Client as MockHttp; |
||
| 8 | use PhpSpec\ObjectBehavior; |
||
| 9 | use Scriptotek\Alma\Exception\InvalidApiKey; |
||
| 10 | use Scriptotek\Alma\Exception\RequestFailed; |
||
| 11 | use Scriptotek\Alma\Exception\ResourceNotFound; |
||
| 12 | use Scriptotek\Alma\Zones; |
||
| 13 | |||
| 14 | function str_random() |
||
| 15 | { |
||
| 16 | return strval(rand(10000, 99999)); |
||
| 17 | } |
||
| 18 | |||
| 19 | class ClientSpec extends ObjectBehavior |
||
| 20 | { |
||
| 21 | public function let() |
||
| 22 | { |
||
| 23 | $http = new MockHttp(); |
||
| 24 | $apiKey = 'DummyApiKey'; |
||
| 25 | $region = 'eu'; |
||
| 26 | $this->beConstructedWith($apiKey, $region, Zones::INSTITUTION, $http); |
||
| 27 | |||
| 28 | return $http; |
||
| 29 | } |
||
| 30 | |||
| 31 | public function it_can_be_configured_with_custom_base_url() |
||
| 32 | { |
||
| 33 | $this->beConstructedWith('DummyKey'); |
||
| 34 | $this->setEntryPoint('http://proxy.foxy'); |
||
| 35 | $this->entrypoint->shouldBe('http://proxy.foxy'); |
||
|
0 ignored issues
–
show
|
|||
| 36 | } |
||
| 37 | |||
| 38 | |||
| 39 | protected function httpWithResponseBody($body, $statusCode = 200, $headers = []) |
||
| 40 | { |
||
| 41 | $http = $this->let(); |
||
| 42 | $http->addResponse(new Response($statusCode, $headers, $body)); |
||
| 43 | |||
| 44 | return $http; |
||
| 45 | } |
||
| 46 | |||
| 47 | public function it_is_initializable() |
||
| 48 | { |
||
| 49 | $this->shouldHaveType('Scriptotek\Alma\Client'); |
||
| 50 | } |
||
| 51 | |||
| 52 | public function it_only_accepts_valid_regions() |
||
| 53 | { |
||
| 54 | $this->shouldThrow('Scriptotek\Alma\Exception\ClientException') |
||
| 55 | ->duringSetRegion('ux'); |
||
| 56 | } |
||
| 57 | |||
| 58 | public function it_can_make_GET_requests() |
||
| 59 | { |
||
| 60 | $responseBody = str_random(); |
||
| 61 | $this->httpWithResponseBody($responseBody); |
||
| 62 | $this->get(str_random())->shouldBe($responseBody); |
||
| 63 | } |
||
| 64 | |||
| 65 | public function it_sends_an_API_key_with_each_request() |
||
| 66 | { |
||
| 67 | $http = $this->httpWithResponseBody(str_random()); |
||
| 68 | $this->getJSON(str_random()); |
||
| 69 | |||
| 70 | // Query string should include apikey |
||
| 71 | expect($http->getRequests()[0])->getHeaderLine('authorization')->toBe('apikey DummyApiKey'); |
||
| 72 | } |
||
| 73 | |||
| 74 | public function it_can_request_and_parse_JSON() |
||
| 75 | { |
||
| 76 | $responseBody = json_encode(['some_key' => 'some_value']); |
||
| 77 | $http = $this->httpWithResponseBody($responseBody); |
||
| 78 | |||
| 79 | $this->getJSON(str_random())->some_key->shouldBe('some_value'); |
||
| 80 | |||
| 81 | $request = $http->getRequests()[0]; |
||
| 82 | expect($request->getHeader('Accept')[0])->toBe('application/json'); |
||
| 83 | } |
||
| 84 | |||
| 85 | public function it_can_post_and_parse_JSON() |
||
| 86 | { |
||
| 87 | $http = $this->httpWithResponseBody(SpecHelper::getDummyData('create_loan_response.json', false)); |
||
| 88 | |||
| 89 | $this->postJSON(str_random())->loan_id->shouldBe('7329587120002204'); |
||
| 90 | |||
| 91 | $request = $http->getRequests()[0]; |
||
| 92 | expect($request->getHeader('Content-Type')[0])->toBe('application/json'); |
||
| 93 | expect($request->getHeader('Accept')[0])->toBe('application/json'); |
||
| 94 | } |
||
| 95 | |||
| 96 | public function it_can_request_and_parse_XML() |
||
| 97 | { |
||
| 98 | $responseBody = "<?xml version=\"1.0\"?>\n<some_key>some_value</some_key>\n"; |
||
| 99 | $http = $this->httpWithResponseBody($responseBody); |
||
| 100 | |||
| 101 | $xml = $this->getXML(str_random()); |
||
| 102 | |||
| 103 | // Request headers should include Accept: application/xml |
||
| 104 | expect($http->getRequests()[0])->getHeader('Accept')[0]->toBe('application/xml'); |
||
| 105 | |||
| 106 | // Response should be of type QuiteSimpleXMLElement |
||
| 107 | $xml->shouldHaveType('Danmichaelo\QuiteSimpleXMLElement\QuiteSimpleXMLElement'); |
||
| 108 | |||
| 109 | // and have the expected value |
||
| 110 | $xml->asXML()->shouldBe($responseBody); |
||
| 111 | } |
||
| 112 | |||
| 113 | public function it_can_make_PUT_requests() |
||
| 114 | { |
||
| 115 | $responseBody = str_random(); |
||
| 116 | $http = $this->httpWithResponseBody($responseBody); |
||
| 117 | |||
| 118 | $this->put(str_random(), str_random(), 'application/json')->shouldBe($responseBody); |
||
| 119 | |||
| 120 | expect($http->getRequests())->toHaveCount(1); |
||
| 121 | expect($http->getRequests()[0])->getMethod()->toBe('PUT'); |
||
| 122 | } |
||
| 123 | |||
| 124 | public function it_can_get_redirect_locations() |
||
| 125 | { |
||
| 126 | $http = $this->let(); |
||
| 127 | $response = new Response(); |
||
| 128 | $response = $response->withHeader('Location', 'http://test.test'); |
||
| 129 | $http->addResponse($response); |
||
| 130 | |||
| 131 | $this->getRedirectLocation('/')->shouldBe('http://test.test'); |
||
| 132 | } |
||
| 133 | |||
| 134 | public function it_processes_json_error_responses() |
||
| 135 | { |
||
| 136 | $http = $this->let(); |
||
| 137 | |||
| 138 | $exception = SpecHelper::makeExceptionResponse( |
||
| 139 | SpecHelper::getDummyData('error_response.json', false) |
||
| 140 | ); |
||
| 141 | $http->addException($exception); |
||
| 142 | |||
| 143 | $this->shouldThrow(new RequestFailed( |
||
| 144 | 'Mandatory field is missing: library', |
||
| 145 | '401664' |
||
| 146 | ))->during('getJSON', ['/items/123']); |
||
| 147 | |||
| 148 | expect($http->getRequests())->toHaveCount(1); |
||
| 149 | } |
||
| 150 | |||
| 151 | View Code Duplication | public function it_processes_xml_error_responses() |
|
| 152 | { |
||
| 153 | $http = $this->let(); |
||
| 154 | |||
| 155 | $exception = SpecHelper::makeExceptionResponse( |
||
| 156 | SpecHelper::getDummyData('error_response.xml', false), |
||
| 157 | 400, |
||
| 158 | 'application/xml;charset=utf-8' |
||
| 159 | ); |
||
| 160 | $http->addException($exception); |
||
| 161 | |||
| 162 | $this->shouldThrow(new RequestFailed( |
||
| 163 | 'Mandatory field is missing: library', |
||
| 164 | '401664' |
||
| 165 | ))->during('getXML', ['/items/123']); |
||
| 166 | |||
| 167 | expect($http->getRequests())->toHaveCount(1); |
||
| 168 | } |
||
| 169 | |||
| 170 | public function it_can_throw_resource_not_found() |
||
| 171 | { |
||
| 172 | $http = $this->let(); |
||
| 173 | |||
| 174 | $exception = SpecHelper::makeExceptionResponse( |
||
| 175 | SpecHelper::getDummyData('item_barcode_error_response.json', false) |
||
| 176 | ); |
||
| 177 | $http->addException($exception); |
||
| 178 | |||
| 179 | $this->shouldThrow(new ResourceNotFound('No items found for barcode 123.', '401689')) |
||
| 180 | ->during('getJSON', ['/items/123']); |
||
| 181 | |||
| 182 | expect($http->getRequests())->toHaveCount(1); |
||
| 183 | } |
||
| 184 | |||
| 185 | public function it_can_throw_resource_not_found_for_500_errors_too() |
||
| 186 | { |
||
| 187 | $http = $this->let(); |
||
| 188 | |||
| 189 | // For Analytics reports, Alma will return 500, not 4xx |
||
| 190 | $exception = SpecHelper::makeExceptionResponse( |
||
| 191 | SpecHelper::getDummyData('report_not_found_response.xml', false), |
||
| 192 | 500, |
||
| 193 | 'application/xml;charset=utf-8', |
||
| 194 | ServerErrorException::class |
||
| 195 | ); |
||
| 196 | $http->addException($exception); |
||
| 197 | |||
| 198 | $this->shouldThrow(new ResourceNotFound('Path not found (/test/path)', 'INTERNAL_SERVER_ERROR')) |
||
| 199 | ->during('getXML', ['/analytics/reports', ['path' => '/test/path']]); |
||
| 200 | |||
| 201 | expect($http->getRequests())->toHaveCount(1); |
||
| 202 | } |
||
| 203 | |||
| 204 | View Code Duplication | public function it_can_throw_invalid_api_key() |
|
| 205 | { |
||
| 206 | $http = $this->let(); |
||
| 207 | |||
| 208 | $exception = SpecHelper::makeExceptionResponse( |
||
| 209 | 'Invalid API Key', |
||
| 210 | 400, |
||
| 211 | 'text/plain;charset=UTF-8' |
||
| 212 | ); |
||
| 213 | $http->addException($exception); |
||
| 214 | |||
| 215 | $this->shouldThrow(new InvalidApiKey('Invalid API Key', 0)) |
||
| 216 | ->during('getJSON', ['/items/123']); |
||
| 217 | |||
| 218 | expect($http->getRequests())->toHaveCount(1); |
||
| 219 | } |
||
| 220 | |||
| 221 | public function it_will_retry_when_reaching_rate_limit() |
||
| 222 | { |
||
| 223 | $http = $this->let(); |
||
| 224 | |||
| 225 | $exception = SpecHelper::makeExceptionResponse( |
||
| 226 | SpecHelper::getDummyData('per_second_threshold_error_response.json', false), |
||
| 227 | 400, |
||
| 228 | 'application/json;charset=utf-8' |
||
| 229 | ); |
||
| 230 | $http->addException($exception); |
||
| 231 | |||
| 232 | $this->getJSON('/items/123'); |
||
| 233 | |||
| 234 | expect($http->getRequests())->toHaveCount(2); |
||
| 235 | } |
||
| 236 | } |
||
| 237 |
Since your code implements the magic getter
_get, this function will be called for any read access on an undefined variable. You can add the@propertyannotation to your class or interface to document the existence of this variable.If the property has read access only, you can use the @property-read annotation instead.
Of course, you may also just have mistyped another name, in which case you should fix the error.
See also the PhpDoc documentation for @property.