CrawlerTrait.php 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: yunwuxin <448901948@qq.com>
  10. // +----------------------------------------------------------------------
  11. namespace think\testing;
  12. use think\App;
  13. use think\Config;
  14. use think\Cookie;
  15. use think\Error;
  16. use think\Exception;
  17. use think\helper\Arr;
  18. use think\helper\Str;
  19. use think\Request;
  20. use think\Response;
  21. trait CrawlerTrait
  22. {
  23. use InteractsWithPages;
  24. protected $currentUri;
  25. protected $serverVariables = [];
  26. /** @var Response */
  27. protected $response;
  28. public function get($uri, array $headers = [])
  29. {
  30. $server = $this->transformHeadersToServerVars($headers);
  31. $this->call('GET', $uri, [], [], [], $server);
  32. return $this;
  33. }
  34. public function post($uri, array $data = [], array $headers = [])
  35. {
  36. $server = $this->transformHeadersToServerVars($headers);
  37. $this->call('POST', $uri, $data, [], [], $server);
  38. return $this;
  39. }
  40. public function put($uri, array $data = [], array $headers = [])
  41. {
  42. $server = $this->transformHeadersToServerVars($headers);
  43. $this->call('PUT', $uri, $data, [], [], $server);
  44. return $this;
  45. }
  46. public function delete($uri, array $data = [], array $headers = [])
  47. {
  48. $server = $this->transformHeadersToServerVars($headers);
  49. $this->call('DELETE', $uri, $data, [], [], $server);
  50. return $this;
  51. }
  52. public function call($method, $uri, $parameters = [], $cookies = [], $files = [], $server = [], $content = null)
  53. {
  54. $this->currentUri = $this->prepareUrlForRequest($uri);
  55. $request = Request::create(
  56. $this->currentUri, $method, $parameters,
  57. $cookies, $files, array_replace($this->serverVariables, $server)
  58. );
  59. try {
  60. $response = App::run($request);
  61. } catch (Exception $e) {
  62. $response = Error::getExceptionHandler()->render($e);
  63. } catch (\Throwable $e) {
  64. $response = Error::getExceptionHandler()->render($e);
  65. }
  66. return $this->response = $response;
  67. }
  68. public function seeJson($data = null, $negate = false)
  69. {
  70. if (is_null($data)) {
  71. $this->assertJson(
  72. $this->response->getContent(), "JSON was not returned from [{$this->currentUri}]."
  73. );
  74. return $this;
  75. }
  76. return $this->seeJsonContains($data, $negate);
  77. }
  78. public function seeJsonEquals(array $data)
  79. {
  80. $actual = json_encode(Arr::sortRecursive(
  81. json_decode($this->response->getContent(), true)
  82. ));
  83. $this->assertEquals(json_encode(Arr::sortRecursive($data)), $actual);
  84. return $this;
  85. }
  86. protected function seeJsonContains(array $data, $negate = false)
  87. {
  88. $method = $negate ? 'assertFalse' : 'assertTrue';
  89. $actual = json_decode($this->response->getContent(), true);
  90. if (is_null($actual) || $actual === false) {
  91. return $this->fail('Invalid JSON was returned from the route. Perhaps an exception was thrown?');
  92. }
  93. $actual = json_encode(Arr::sortRecursive(
  94. (array)$actual
  95. ));
  96. foreach (Arr::sortRecursive($data) as $key => $value) {
  97. $expected = $this->formatToExpectedJson($key, $value);
  98. $this->{$method}(
  99. Str::contains($actual, $expected),
  100. ($negate ? 'Found unexpected' : 'Unable to find') . " JSON fragment [{$expected}] within [{$actual}]."
  101. );
  102. }
  103. return $this;
  104. }
  105. /**
  106. * Format the given key and value into a JSON string for expectation checks.
  107. *
  108. * @param string $key
  109. * @param mixed $value
  110. * @return string
  111. */
  112. protected function formatToExpectedJson($key, $value)
  113. {
  114. $expected = json_encode([$key => $value]);
  115. if (Str::startsWith($expected, '{')) {
  116. $expected = substr($expected, 1);
  117. }
  118. if (Str::endsWith($expected, '}')) {
  119. $expected = substr($expected, 0, -1);
  120. }
  121. return $expected;
  122. }
  123. protected function seeModule($module)
  124. {
  125. $this->assertEquals($module, request()->module());
  126. return $this;
  127. }
  128. protected function seeController($controller)
  129. {
  130. $this->assertEquals($controller, request()->controller());
  131. return $this;
  132. }
  133. protected function seeAction($action)
  134. {
  135. $this->assertEquals($action, request()->action());
  136. return $this;
  137. }
  138. protected function seeStatusCode($status)
  139. {
  140. $this->assertEquals($status, $this->response->getCode());
  141. return $this;
  142. }
  143. protected function seeHeader($headerName, $value = null)
  144. {
  145. $headers = $this->response->getHeader();
  146. $this->assertTrue(!empty($headers[$headerName]), "Header [{$headerName}] not present on response.");
  147. if (!is_null($value)) {
  148. $this->assertEquals(
  149. $headers[$headerName], $value,
  150. "Header [{$headerName}] was found, but value [{$headers[$headerName]}] does not match [{$value}]."
  151. );
  152. }
  153. return $this;
  154. }
  155. protected function seeCookie($cookieName, $value = null)
  156. {
  157. $exist = Cookie::has($cookieName);
  158. $this->assertTrue($exist, "Cookie [{$cookieName}] not present on response.");
  159. if (!is_null($value)) {
  160. $cookie = Cookie::get($cookieName);
  161. $this->assertEquals(
  162. $cookie, $value,
  163. "Cookie [{$cookieName}] was found, but value [{$cookie}] does not match [{$value}]."
  164. );
  165. }
  166. return $this;
  167. }
  168. protected function withServerVariables(array $server)
  169. {
  170. $this->serverVariables = $server;
  171. return $this;
  172. }
  173. protected function transformHeadersToServerVars(array $headers)
  174. {
  175. $server = [];
  176. $prefix = 'HTTP_';
  177. foreach ($headers as $name => $value) {
  178. $name = strtr(strtoupper($name), '-', '_');
  179. if (!Str::startsWith($name, $prefix) && $name != 'CONTENT_TYPE') {
  180. $name = $prefix . $name;
  181. }
  182. $server[$name] = $value;
  183. }
  184. return $server;
  185. }
  186. }