PageRenderTime 164ms CodeModel.GetById 23ms app.highlight 129ms RepoModel.GetById 2ms app.codeStats 0ms

/api/vendor/peej/tonic/features/bootstrap/FeatureContext.php

https://gitlab.com/x33n/respond
PHP | 519 lines | 330 code | 54 blank | 135 comment | 52 complexity | 8b7f42a23b1052cc464a1f85a5883dab MD5 | raw file
  1<?php
  2
  3use Behat\Behat\Context\ClosuredContextInterface,
  4    Behat\Behat\Context\TranslatedContextInterface,
  5    Behat\Behat\Context\BehatContext,
  6    Behat\Behat\Exception\PendingException;
  7use Behat\Gherkin\Node\PyStringNode,
  8    Behat\Gherkin\Node\TableNode;
  9
 10use Tonic\Application,
 11    Tonic\Request,
 12    Tonic\Resource,
 13    Tonic\Response;
 14
 15/**
 16 * Features context.
 17 */
 18class FeatureContext extends BehatContext
 19{
 20
 21    private $app, $request, $resource, $response, $exception, $error;
 22
 23    private $createMethod = array();
 24    private $data;
 25
 26    private $options = array();
 27
 28    /**
 29     * @BeforeFeature
 30     */
 31    public static function setupFeature()
 32    {
 33        unset($_SERVER);
 34        unset($_GET);
 35        unset($_POST);
 36    }
 37
 38    /**
 39     * @Given /^the request URI of "([^"]*)"$/
 40     */
 41    public function theRequestUriOf($uri)
 42    {
 43        $parsedUri = parse_url($uri);
 44        $_SERVER['REDIRECT_URL'] = $parsedUri['path'];
 45        if (isset($parsedUri['query'])) {
 46            $query = explode('&', $parsedUri['query']);
 47            foreach ($query as $item) {
 48                list($name, $value) = explode('=', $item);
 49                $_GET[$name] = $value;
 50            }
 51        }
 52        $_SERVER['SCRIPT_NAME'] = '';
 53    }
 54
 55    /**
 56     * @Given /^the request method of "([^"]*)"$/
 57     */
 58    public function theRequestMethodOf($method)
 59    {
 60        $_SERVER['REQUEST_METHOD'] = $method;
 61    }
 62
 63    /**
 64     * @When /^I create an application object$/
 65     */
 66    public function iCreateAnApplicationObject()
 67    {
 68        $this->app = new Application($this->options);
 69    }
 70
 71    /**
 72     * @When /^I create a request object$/
 73     */
 74    public function iCreateARequestObject()
 75    {
 76        if ($this->data) {
 77            $this->options['data'] = $this->data;
 78            $this->options['contentType'] = $_SERVER['CONTENT_TYPE'];
 79        }
 80        $this->request = new Request($this->options);
 81    }
 82
 83    /**
 84     * @Then /^I should see a request URI of "([^"]*)"$/
 85     */
 86    public function iShouldSeeARequestUriOf($uri)
 87    {
 88        if ($this->request->uri != $uri) throw new Exception;
 89    }
 90
 91    /**
 92     * @Then /^I should see a request method of "([^"]*)"$/
 93     */
 94    public function iShouldSeeARequestMethodOf($method)
 95    {
 96        if ($this->request->method != $method) throw new Exception;
 97    }
 98
 99    /**
100     * @Given /^an? "([^"]*)" header of ['"]([^']*)['"]$/
101     */
102    public function aHeaderOf($header, $value)
103    {
104        $headerMapping = array(
105            'accept' => 'HTTP_ACCEPT',
106            'accept language' => 'HTTP_ACCEPT_LANGUAGE',
107            'if-none-match' => 'HTTP_IF_NONE_MATCH',
108            'if-match' => 'HTTP_IF_MATCH',
109            'content-type' => 'CONTENT_TYPE',
110            'auth user' => 'PHP_AUTH_USER',
111            'auth password' => 'PHP_AUTH_PW',
112            'x-authentication' => 'HTTP_X_AUTHENTICATION'
113        );
114        $_SERVER[$headerMapping[$header]] = $value;
115    }
116
117    /**
118     * @Given /^I should see an? "([^"]*)" string of "([^"]*)"$/
119     */
120    public function iShouldSeeAStringOf($header, $string)
121    {
122        $propertyMapping = array(
123            'accept' => 'accept',
124            'accept language' => 'acceptLanguage',
125            'if-none-match' => 'ifNoneMatch',
126            'if-match' => 'ifMatch',
127            'content-type' => 'contentType'
128        );
129        if (is_array($this->request->$propertyMapping[$header])) {
130            $value = join(',', $this->request->$propertyMapping[$header]);
131        } else {
132            $value = $this->request->$propertyMapping[$header];
133        }
134        if ($value != $string)
135            throw new Exception($value);
136    }
137
138    /**
139     * @Given /^body data of \'([^\']*)\'$/
140     */
141    public function bodyDataOf($data)
142    {
143        $this->data = $data;
144    }
145
146    /**
147     * @Given /^I should see body data of "([^"]*)"$/
148     */
149    public function iShouldSeeBodyDataOf($data)
150    {
151        if ($this->request->data != $data)
152            throw new Exception();
153    }
154
155    /**
156     * @Given /^a resource definition "([^"]*)" with URI "([^"]*)" and priority of (\d+)$/
157     */
158    public function aResourceDefinitionWithUriAndPriorityOf($className, $uri, $priority)
159    {
160        $this->aResourceDefinition($className, $uri, $priority);
161    }
162
163    /**
164     * @Given /^a resource definition "([^"]*)" with URI "([^"]*)" and namespace of "([^"]*)"$/
165     */
166    public function aResourceDefinitionWithUriAndNamespaceOf($className, $uri, $namespace)
167    {
168        $this->aResourceDefinition($className, $uri, 1, $namespace);
169    }
170
171    /**
172     * @Given /^a resource definition "([^"]*)" with URI "([^"]*)" and namespace annotation of "([^"]*)"$/
173     */
174    public function aResourceDefinitionWithUriAndNamespaceAnnotationOf($className, $uri, $namespace)
175    {
176        $this->aResourceDefinition($className, $uri, 1, NULL, $namespace);
177    }
178
179    /**
180     * @Given /^a resource definition "([^"]*)" with URI "([^"]*)" and windows style line endings$/
181     */
182    public function aResourceDefinitionWithUriAndWindowsStyleLineEndings($className, $uri)
183    {
184        $this->aResourceDefinition($className, $uri, 1, NULL, NULL, "\r\n");
185    }
186
187    private function aResourceDefinition($className, $uri, $priority = 1, $namespace = NULL, $annotationNamespace = NULL, $lineEnding = "\n")
188    {
189        $classDefinition = '';
190        if ($namespace) $classDefinition .= 'namespace '.$namespace.';'.$lineEnding;
191        $classDefinition .= '/**'.$lineEnding.
192            ' * @uri '.$uri.$lineEnding.
193            ' * @priority '.$priority.$lineEnding;
194        if ($annotationNamespace) $classDefinition .= ' * @namespace '.$annotationNamespace.$lineEnding;
195        $classDefinition .= ' */'.$lineEnding.
196            'class '.$className.' extends \Tonic\Resource {'.$lineEnding;
197        foreach ($this->createMethod as $methodData) {
198            $classDefinition .= '    /**'.$lineEnding;
199            $classDefinition .= '     * @method '.(isset($methodData['method']) ? $methodData['method'] : 'GET').$lineEnding;
200            if (isset($methodData['lang'])) $classDefinition .= '     * @lang '.$methodData['lang'].$lineEnding;
201            if (isset($methodData['accepts'])) $classDefinition .= '     * @accepts '.$methodData['accepts'].$lineEnding;
202            if (isset($methodData['provides'])) $classDefinition .= '     * @provides '.$methodData['provides'].$lineEnding;
203            $classDefinition .= $lineEnding.'     */'.$lineEnding.
204                '    function '.$methodData['name'].'() {'.$lineEnding.
205                '        return "'.$methodData['name'].'";'.$lineEnding.
206                '    }'.$lineEnding;
207        }
208        $classDefinition .= '}'.$lineEnding;
209        eval($classDefinition);
210    }
211
212    /**
213     * @Given /^load the resource$/
214     */
215    public function loadTheResource()
216    {
217        try {
218            $this->resource = $this->app->getResource($this->request);
219        } catch (Tonic\Exception $e) {
220            $this->exception = $e;
221        }
222    }
223
224    /**
225     * @Then /^the loaded resource should have a class of "([^"]*)"$/
226     */
227    public function theLoadedResourceShouldHaveAClassOf($className)
228    {
229        $loadedClassName = get_class($this->resource);
230        if ($loadedClassName != $className) throw new Exception($loadedClassName.' != '.$className);
231    }
232
233    /**
234     * @Given /^the loaded resource should have a param "([^"]*)" with the value "([^"]*)"$/
235     */
236    public function theLoadedResourceShouldHaveAParamWithTheValue($name, $value)
237    {
238        if (!isset($this->resource->params[$name])) throw new Exception('Param '.$name.' not found');
239        if ($this->resource->params[$name] != $value) throw new Exception('Param '.$name.' does not equal '.$value);
240    }
241
242    /**
243     * @Given /^execute the resource$/
244     */
245    public function executeTheResource()
246    {
247        set_error_handler(function ($level, $message, $file, $line) {
248            throw new ErrorException($message, $level);
249        });
250        try {
251            if ($this->resource) {
252                $this->response = $this->resource->exec();
253            } else {
254                throw new Exception('Resource not loaded');
255            }
256        } catch (Tonic\Exception $e) {
257            $this->exception = $e;
258        } catch (ErrorException $e) {
259            $this->exception = $e;
260            $this->error = $e->getCode();
261        }
262        restore_error_handler();
263    }
264
265    /**
266     * @Then /^response should be "([^"]*)"$/
267     */
268    public function responseShouldBe($responseString)
269    {
270        if (!$this->response) throw new Exception('Response not loaded due to '.$this->exception);
271        if ($this->response->body != $responseString) throw new Exception('The response body is: "'.$this->response->body.'"');
272    }
273
274    /**
275     * @Given /^a "([^"]*)" resource method "([^"]*)"$/
276     */
277    public function aResourceMethod($method, $name)
278    {
279        $this->createMethod[] = array(
280            'method' => $method,
281            'name' => $name
282        );
283    }
284
285    /**
286     * @Given /^a "([^"]*)" resource method "([^"]*)" that provides "([^"]*)"$/
287     */
288    public function aResourceMethodThatProvides($method, $name, $provides)
289    {
290        $this->createMethod[] = array(
291            'method' => $method,
292            'name' => $name,
293            'provides' => $provides
294        );
295    }
296
297    /**
298     * @Given /^a "([^"]*)" resource method "([^"]*)" that accepts "([^"]*)"$/
299     */
300    public function aResourceMethodThatAccepts($method, $name, $accepts)
301    {
302        $this->createMethod[] = array(
303            'method' => $method,
304            'name' => $name,
305            'accepts' => $accepts
306        );
307    }
308
309    /**
310     * @Given /^the request content type of "([^"]*)"$/
311     */
312    public function theRequestContentTypeOf($contentType)
313    {
314        $_SERVER['CONTENT_TYPE'] = $contentType;
315    }
316
317    /**
318     * @Given /^the request data of "([^"]*)"$/
319     */
320    public function theRequestDataOf($data)
321    {
322        $this->data = $data;
323    }
324
325    /**
326     * @Then /^a "([^"]*)" should be thrown$/
327     */
328    public function aShouldBeThrown($exception)
329    {
330        if ($exception != get_class($this->exception)) throw new Exception($this->exception->getMessage());
331    }
332
333    /**
334     * @Then /^a PHP warning should occur$/
335     */
336    public function aPhpWarningShouldOccur()
337    {
338        if ($this->error != E_WARNING) throw new Exception('No PHP warning');
339    }
340
341    /**
342     * @Then /^a PHP notice should occur$/
343     */
344    public function aPhpNoticeShouldOccur()
345    {
346        if ($this->error != E_NOTICE) throw new Exception('No PHP notice');
347    }
348
349    /**
350     * @Given /^I mount "([^"]*)" at the URI "([^"]*)"$/
351     */
352    public function iMountAtTheUri($className, $uriSpace)
353    {
354        $this->app->mount($className, $uriSpace);
355    }
356
357    /**
358     * @Given /^a class definition:$/
359     */
360    public function aClassDefinition(PyStringNode $string)
361    {
362        eval($string);
363    }
364
365    /**
366     * @Given /^I set the request option "([^"]*)" to:$/
367     */
368    public function iSetTheRequestOptionTo($option, PyStringNode $json)
369    {
370        $this->options[$option] = json_decode($json, TRUE);
371    }
372
373    /**
374     * @Given /^I supply an empty cache object$/
375     */
376    public function iSupplyAnEmptyCacheObject()
377    {
378        $this->options['cache'] = new MockMetadataCache();
379    }
380
381    /**
382     * @Given /^a resource file "([^"]*)" to load$/
383     */
384    public function aResourceFileToLoad($filename)
385    {
386        $this->options['load'][] = $filename;
387    }
388
389    /**
390     * @Given /^the cache object should contain "([^"]*)" "([^"]*)"$/
391     */
392    public function theCacheObjectShouldContain($className, $methodName)
393    {
394        if (!$this->options['cache']->contains($className, $methodName)) throw new Exception;
395    }
396
397    /**
398     * @Given /^a cache object containing a class "([^"]*)" with a URL of "([^"]*)" and a method "([^"]*)" responding to HTTP "([^"]*)"$/
399     */
400    public function aCacheObjectContainingAClassWithAUrlOfAndAMethodRespondingToHttp($className, $uri, $methodName, $method)
401    {
402        $this->iSupplyAnEmptyCacheObject();
403        $this->options['cache']->save(array(
404            $className => array(
405                'class' => $className,
406                'uri' => $uri,
407                'methods' => array(
408                    $methodName => array(
409                        'method' => array(
410                            $method
411                        )
412                    )
413                )
414            )
415        ));
416    }
417
418    /**
419     * @Then /^the loaded resource "([^"]*)" should respond with the method "([^"]*)"$/
420     */
421    public function theLoadedResourceShouldRespondToWithTheMethod($className, $methodName)
422    {
423        $metadata = $this->app->getResourceMetadata($className);
424        if (!isset($metadata['methods'][$methodName])) throw new Exception;
425    }
426
427    /**
428     * @Then /^fetching the URI for the resource "([^"]*)" with the parameter "([^"]*)" should get "([^"]*)"$/
429     */
430    public function fetchingTheUriForTheResourceShouldGet($className, $params, $url)
431    {
432        $params = explode(':', $params);
433        if ($this->app->uri($className, $params) != $url)
434            throw new Exception($this->app->uri($className, $params).' != '.$url);
435    }
436
437    /**
438     * @Given /^a "([^"]*)" resource method "([^"]*)" with lang "([^"]*)"$/
439     */
440    public function aResourceMethodWithLang($method, $name, $language)
441    {
442        $this->createMethod[] = array(
443            'method' => $method,
444            'name' => $name,
445            'lang' => $language
446        );
447    }
448
449    /**
450     * @Then /^the resource "([^"]*)" should have the URI "([^"]*)"$/
451     */
452    public function theResourceShouldHaveTheURI($resourceName, $url)
453    {
454        $found = FALSE;
455        $metadata = $this->app->getResourceMetadata($resourceName);
456        foreach ($metadata['uri'] as $uri) {
457            if ($uri[0] == $url) {
458                $found = TRUE;
459                break;
460            }
461        }
462        if (!$found) throw new Exception;
463    }
464
465    /**
466     * @Then /^the resource "([^"]*)" should have the condition "([^"]*)" with the parameters "([^"]*)"$/
467     */
468    public function theResourceShouldHaveTheConditionWithTheParameters($className, $conditionName, $parameters)
469    {
470        $metadata = $this->app->getResourceMetadata($className);
471        if ($parameters) {
472            if ($parameters != join(',', $metadata['methods']['test'][$conditionName][0])) throw new Exception('Condition method not found');
473            
474            $resource = new $className($this->app, new Request, array());
475            $condition = call_user_func_array(array($resource, $conditionName), explode(',', $parameters));
476            if ($condition != explode(',', $parameters)) throw new Exception('Condition parameters not returned');
477        } else {
478            if (!isset($metadata['methods']['test'][$conditionName])) throw new Exception('Condition method not found');
479        }
480    }
481
482    /**
483     * @Given /^an issue "([^"]*)"$/
484     */
485    public function anIssue($issue)
486    {
487        require_once dirname(__FILE__).'/../../issues/'.$issue.'.php';
488    }
489
490    /**
491     * @Given /^the method priority for "([^"]*)" should be "([^"]*)"$/
492     */
493    public function theMethodPriorityForShouldBe($methodName, $value)
494    {
495        preg_match('/[\[ ]([0-9-]+)\] '.$methodName.' /', (string)$this->resource, $matches);
496        if (!$matches)
497            throw new Exception('"'.$methodName.'" not found');
498        if ($matches[1] != $value)
499            throw new Exception('"'.$methodName.'" has the priortiy of '.$matches[1]);
500    }
501
502    /**
503     * @Then /^the response should have the header "([^"]*)" with the value "([^"]*)"$/
504     */
505    public function theResponseShouldHaveTheHeaderWithTheValue($name, $value)
506    {
507        if ($this->response->headers[$name] != $value) throw new Exception('Response header '.$name.' does not equal '.$value);
508    }
509
510    /**
511     * @Then /^output the "([^"]*)"$/
512     */
513    public function outputThe($thing)
514    {
515        echo $this->$thing;
516    }
517
518
519}