diff --git a/composer.json b/composer.json index 330e538..d804027 100644 --- a/composer.json +++ b/composer.json @@ -20,13 +20,14 @@ }, "autoload-dev": { "psr-4": { - "SwoftTest\\HttpServer\\": "test/Cases" + "SwoftTest\\HttpServer\\": "test/Cases", + "SwoftTest\\Testing\\": "test/Testing" } }, "repositories": [ { "type": "composer", - "url": "https://packagist.phpcomposer.com" + "url": "https://packagist.laravel-china.org" } ], "require-dev": { diff --git a/src/Validator/HttpValidator.php b/src/Validator/HttpValidator.php index 99bc44a..0ab8565 100644 --- a/src/Validator/HttpValidator.php +++ b/src/Validator/HttpValidator.php @@ -6,6 +6,7 @@ use Swoft\Bean\Annotation\ValidatorFrom; use Swoft\Helper\ArrayHelper; use Swoft\Helper\JsonHelper; +use Swoft\Helper\StringHelper; use Swoft\Http\Message\Server\Request; use Swoft\Http\Message\Stream\SwooleStream; use Swoft\Validator\AbstractValidator; @@ -58,7 +59,8 @@ private function validateField($request, array $matches, string $type, array $va $post = $request->getParsedBody(); $contentType = $request->getHeader('content-type'); $isPostJson = false; - if ($contentType && \in_array('application/json', $contentType)) { + + if (isset($contentType[0]) && StringHelper::startsWith($contentType[0], 'application/json')) { $isPostJson = true; $post = $request->json(); } diff --git a/test/Cases/AbstractTestCase.php b/test/Cases/AbstractTestCase.php index 8886fcc..381f7ac 100644 --- a/test/Cases/AbstractTestCase.php +++ b/test/Cases/AbstractTestCase.php @@ -3,15 +3,179 @@ namespace SwoftTest\HttpServer; use PHPUnit\Framework\TestCase; +use Swoft\App; +use Swoft\Helper\ArrayHelper; +use Swoft\Testing\SwooleRequest as TestSwooleRequest; +use Swoft\Testing\SwooleResponse as TestSwooleResponse; +use Swoft\Http\Message\Testing\Web\Request; +use Swoft\Http\Message\Testing\Web\Response; /** - * @uses AbstractTestCase - * @version 2017年11月03日 - * @author huangzhhui - * @copyright Copyright 2010-2017 Swoft software - * @license PHP Version 7.x {@link http://www.php.net/license/3_0.txt} + * Class AbstractTestCase + * + * @package Swoft\Test\Cases */ -abstract class AbstractTestCase extends TestCase +class AbstractTestCase extends TestCase { + const ACCEPT_VIEW = 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8'; + const ACCEPT_JSON = 'application/json'; + + const ACCEPT_RAW = 'text/plain'; + + /** + * Send a mock request + * + * @param string $method + * @param string $uri + * @param array $parameters + * @param string $accept + * @param array $headers + * @param string $rawContent + * @return bool|\Swoft\Http\Message\Testing\Web\Response + */ + public function request( + string $method, + string $uri, + array $parameters = [], + string $accept = self::ACCEPT_JSON, + array $headers = [], + string $rawContent = '' + ) { + $method = strtoupper($method); + $swooleResponse = new TestSwooleResponse(); + $swooleRequest = new TestSwooleRequest(); + + $this->buildMockRequest($method, $uri, $parameters, $accept, $swooleRequest, $headers); + + $swooleRequest->setRawContent($rawContent); + + $request = Request::loadFromSwooleRequest($swooleRequest); + $response = new Response($swooleResponse); + + /** @var \Swoft\Http\Server\ServerDispatcher $dispatcher */ + $dispatcher = App::getBean('serverDispatcher'); + return $dispatcher->dispatch($request, $response); + } + + /** + * Send a mock json request + * + * @param string $method + * @param string $uri + * @param array $parameters + * @param array $headers + * @param string $rawContent + * @return bool|\Swoft\Http\Message\Testing\Web\Response + */ + public function json( + string $method, + string $uri, + array $parameters = [], + array $headers = [], + string $rawContent = '' + ) { + return $this->request($method, $uri, $parameters, self::ACCEPT_JSON, $headers, $rawContent); + } + + /** + * Send a mock view request + * + * @param string $method + * @param string $uri + * @param array $parameters + * @param array $headers + * @param string $rawContent + * @return bool|\Swoft\Http\Message\Testing\Web\Response + */ + public function view( + string $method, + string $uri, + array $parameters = [], + array $headers = [], + string $rawContent = '' + ) { + return $this->request($method, $uri, $parameters, self::ACCEPT_VIEW, $headers, $rawContent); + } + + /** + * Send a mock raw content request + * + * @param string $method + * @param string $uri + * @param array $parameters + * @param array $headers + * @param string $rawContent + * @return bool|\Swoft\Http\Message\Testing\Web\Response + */ + public function raw( + string $method, + string $uri, + array $parameters = [], + array $headers = [], + string $rawContent = '' + ) { + return $this->request($method, $uri, $parameters, self::ACCEPT_RAW, $headers, $rawContent); + } + + /** + * @param string $method + * @param string $uri + * @param array $parameters + * @param string $accept + * @param \Swoole\Http\Request $swooleRequest + * @param array $headers + */ + protected function buildMockRequest( + string $method, + string $uri, + array $parameters, + string $accept, + &$swooleRequest, + array $headers = [] + ) { + $urlAry = parse_url($uri); + $urlParams = []; + if (isset($urlAry['query'])) { + parse_str($urlAry['query'], $urlParams); + } + $defaultHeaders = [ + 'host' => '127.0.0.1', + 'connection' => 'keep-alive', + 'cache-control' => 'max-age=0', + 'user-agent' => 'PHPUnit', + 'upgrade-insecure-requests' => '1', + 'accept' => $accept, + 'dnt' => '1', + 'accept-encoding' => 'gzip, deflate, br', + 'accept-language' => 'zh-CN,zh;q=0.8,en;q=0.6,it-IT;q=0.4,it;q=0.2', + ]; + + $swooleRequest->fd = 1; + $swooleRequest->header = ArrayHelper::merge($headers, $defaultHeaders); + $swooleRequest->server = [ + 'request_method' => $method, + 'request_uri' => $uri, + 'path_info' => '/', + 'request_time' => microtime(), + 'request_time_float' => microtime(true), + 'server_port' => 80, + 'remote_port' => 54235, + 'remote_addr' => '10.0.2.2', + 'master_time' => microtime(), + 'server_protocol' => 'HTTP/1.1', + 'server_software' => 'swoole-http-server', + ]; + + if ($method == 'GET') { + $swooleRequest->get = $parameters; + } elseif ($method == 'POST') { + $swooleRequest->post = $parameters; + } + + if (! empty($urlParams)) { + $get = empty($swooleRequest->get) ? [] : $swooleRequest->get; + $swooleRequest->get = array_merge($urlParams, $get); + } + } } \ No newline at end of file diff --git a/test/Cases/ValidatorTest.php b/test/Cases/ValidatorTest.php new file mode 100644 index 0000000..197c1ad --- /dev/null +++ b/test/Cases/ValidatorTest.php @@ -0,0 +1,35 @@ + 'application/json' + ]; + $raw = JsonHelper::encode([ + 'test' => [ + 'id' => 1 + ] + ]); + $res = $this->raw('POST', '/validator/json', [], $headers, $raw)->getBody()->getContents(); + $this->assertEquals('[1,"limx"]', $res); + + $headers = [ + 'Content-Type' => 'application/json;charset=UTF-8' + ]; + $raw = JsonHelper::encode([ + 'test' => [ + 'id' => 1 + ] + ]); + $res = $this->raw('POST', '/validator/json', [], $headers, $raw)->getBody()->getContents(); + $this->assertEquals('[1,"limx"]', $res); + } + + +} diff --git a/test/Testing/Controllers/ValidatorController.php b/test/Testing/Controllers/ValidatorController.php new file mode 100644 index 0000000..12e0dfe --- /dev/null +++ b/test/Testing/Controllers/ValidatorController.php @@ -0,0 +1,30 @@ +json('test.id'); + $name = $request->json('test.name'); + + return $response->json([$id, $name]); + } +} \ No newline at end of file diff --git a/test/config/beans/base.php b/test/config/beans/base.php index b993871..9ef09d4 100644 --- a/test/config/beans/base.php +++ b/test/config/beans/base.php @@ -1,3 +1,17 @@ [ + 'class' => ServerDispatcher::class, + ], + 'httpRouter' => [ + 'class' => HandlerMapping::class, + ], + 'requestParser' => [ + 'class' => RequestParser::class, + ], +]; \ No newline at end of file diff --git a/test/config/properties/app.php b/test/config/properties/app.php index c39014a..7e788ef 100644 --- a/test/config/properties/app.php +++ b/test/config/properties/app.php @@ -3,7 +3,8 @@ "version" => '1.0', 'autoInitBean' => true, 'beanScan' => [ - 'Swoft\\Http\\Server\\Test\\Testing' => BASE_PATH."/Testing" + 'SwoftTest\\Testing' => BASE_PATH . "/Testing", + 'Swoft\\Http\\Server' => BASE_PATH . '/../src', ], 'I18n' => [ 'sourceLanguage' => '@root/resources/messages/',