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