287 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			PHP
		
	
	
		
		
			
		
	
	
			287 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			PHP
		
	
	
|  | <?php | ||
|  | 
 | ||
|  | namespace think\tests; | ||
|  | 
 | ||
|  | use Closure; | ||
|  | use Mockery as m; | ||
|  | use Mockery\MockInterface; | ||
|  | use PHPUnit\Framework\TestCase; | ||
|  | use think\helper\Str; | ||
|  | use think\Request; | ||
|  | use think\response\Redirect; | ||
|  | use think\response\View; | ||
|  | use think\Route; | ||
|  | 
 | ||
|  | class RouteTest extends TestCase | ||
|  | { | ||
|  |     use InteractsWithApp; | ||
|  | 
 | ||
|  |     /** @var Route|MockInterface */ | ||
|  |     protected $route; | ||
|  | 
 | ||
|  |     protected function tearDown(): void | ||
|  |     { | ||
|  |         m::close(); | ||
|  |     } | ||
|  | 
 | ||
|  |     protected function setUp() | ||
|  |     { | ||
|  |         $this->prepareApp(); | ||
|  |         $this->route = new Route($this->app); | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * @param $path | ||
|  |      * @param string $method | ||
|  |      * @param string $host | ||
|  |      * @return m\Mock|Request | ||
|  |      */ | ||
|  |     protected function makeRequest($path, $method = 'GET', $host = 'localhost') | ||
|  |     { | ||
|  |         $request = m::mock(Request::class)->makePartial(); | ||
|  |         $request->shouldReceive('host')->andReturn($host); | ||
|  |         $request->shouldReceive('pathinfo')->andReturn($path); | ||
|  |         $request->shouldReceive('url')->andReturn('/' . $path); | ||
|  |         $request->shouldReceive('method')->andReturn(strtoupper($method)); | ||
|  |         return $request; | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testSimpleRequest() | ||
|  |     { | ||
|  |         $this->route->get('foo', function () { | ||
|  |             return 'get-foo'; | ||
|  |         }); | ||
|  | 
 | ||
|  |         $this->route->put('foo', function () { | ||
|  |             return 'put-foo'; | ||
|  |         }); | ||
|  | 
 | ||
|  |         $this->route->group(function () { | ||
|  |             $this->route->post('foo', function () { | ||
|  |                 return 'post-foo'; | ||
|  |             }); | ||
|  |         }); | ||
|  | 
 | ||
|  |         $request  = $this->makeRequest('foo', 'post'); | ||
|  |         $response = $this->route->dispatch($request); | ||
|  |         $this->assertEquals(200, $response->getCode()); | ||
|  |         $this->assertEquals('post-foo', $response->getContent()); | ||
|  | 
 | ||
|  |         $request  = $this->makeRequest('foo', 'get'); | ||
|  |         $response = $this->route->dispatch($request); | ||
|  |         $this->assertEquals(200, $response->getCode()); | ||
|  |         $this->assertEquals('get-foo', $response->getContent()); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testOptionsRequest() | ||
|  |     { | ||
|  |         $this->route->get('foo', function () { | ||
|  |             return 'get-foo'; | ||
|  |         }); | ||
|  | 
 | ||
|  |         $this->route->put('foo', function () { | ||
|  |             return 'put-foo'; | ||
|  |         }); | ||
|  | 
 | ||
|  |         $this->route->group(function () { | ||
|  |             $this->route->post('foo', function () { | ||
|  |                 return 'post-foo'; | ||
|  |             }); | ||
|  |         }); | ||
|  |         $this->route->group('abc', function () { | ||
|  |             $this->route->post('foo/:id', function () { | ||
|  |                 return 'post-abc-foo'; | ||
|  |             }); | ||
|  |         }); | ||
|  | 
 | ||
|  |         $this->route->post('foo/:id', function () { | ||
|  |             return 'post-abc-foo'; | ||
|  |         }); | ||
|  | 
 | ||
|  |         $this->route->resource('bar', 'SomeClass'); | ||
|  | 
 | ||
|  |         $request  = $this->makeRequest('foo', 'options'); | ||
|  |         $response = $this->route->dispatch($request); | ||
|  |         $this->assertEquals(204, $response->getCode()); | ||
|  |         $this->assertEquals('GET, PUT, POST', $response->getHeader('Allow')); | ||
|  | 
 | ||
|  |         $request  = $this->makeRequest('bar', 'options'); | ||
|  |         $response = $this->route->dispatch($request); | ||
|  |         $this->assertEquals(204, $response->getCode()); | ||
|  |         $this->assertEquals('GET, POST', $response->getHeader('Allow')); | ||
|  | 
 | ||
|  |         $request  = $this->makeRequest('bar/1', 'options'); | ||
|  |         $response = $this->route->dispatch($request); | ||
|  |         $this->assertEquals(204, $response->getCode()); | ||
|  |         $this->assertEquals('GET, PUT, DELETE', $response->getHeader('Allow')); | ||
|  | 
 | ||
|  |         $request  = $this->makeRequest('xxxx', 'options'); | ||
|  |         $response = $this->route->dispatch($request); | ||
|  |         $this->assertEquals(204, $response->getCode()); | ||
|  |         $this->assertEquals('GET, POST, PUT, DELETE', $response->getHeader('Allow')); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testAllowCrossDomain() | ||
|  |     { | ||
|  |         $this->route->get('foo', function () { | ||
|  |             return 'get-foo'; | ||
|  |         })->allowCrossDomain(['some' => 'bar']); | ||
|  | 
 | ||
|  |         $request  = $this->makeRequest('foo', 'get'); | ||
|  |         $response = $this->route->dispatch($request); | ||
|  | 
 | ||
|  |         $this->assertEquals('bar', $response->getHeader('some')); | ||
|  |         $this->assertArrayHasKey('Access-Control-Allow-Credentials', $response->getHeader()); | ||
|  | 
 | ||
|  |         $request  = $this->makeRequest('foo2', 'options'); | ||
|  |         $response = $this->route->dispatch($request); | ||
|  | 
 | ||
|  |         $this->assertEquals(204, $response->getCode()); | ||
|  |         $this->assertArrayHasKey('Access-Control-Allow-Credentials', $response->getHeader()); | ||
|  |         $this->assertEquals('GET, POST, PUT, DELETE', $response->getHeader('Allow')); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testControllerDispatch() | ||
|  |     { | ||
|  |         $this->route->get('foo', 'foo/bar'); | ||
|  | 
 | ||
|  |         $controller = m::Mock(\stdClass::class); | ||
|  | 
 | ||
|  |         $this->app->shouldReceive('parseClass')->with('controller', 'Foo')->andReturn($controller->mockery_getName()); | ||
|  |         $this->app->shouldReceive('make')->with($controller->mockery_getName(), [], true)->andReturn($controller); | ||
|  | 
 | ||
|  |         $controller->shouldReceive('bar')->andReturn('bar'); | ||
|  | 
 | ||
|  |         $request  = $this->makeRequest('foo'); | ||
|  |         $response = $this->route->dispatch($request); | ||
|  |         $this->assertEquals('bar', $response->getContent()); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testEmptyControllerDispatch() | ||
|  |     { | ||
|  |         $this->route->get('foo', 'foo/bar'); | ||
|  | 
 | ||
|  |         $controller = m::Mock(\stdClass::class); | ||
|  | 
 | ||
|  |         $this->app->shouldReceive('parseClass')->with('controller', 'Error')->andReturn($controller->mockery_getName()); | ||
|  |         $this->app->shouldReceive('make')->with($controller->mockery_getName(), [], true)->andReturn($controller); | ||
|  | 
 | ||
|  |         $controller->shouldReceive('bar')->andReturn('bar'); | ||
|  | 
 | ||
|  |         $request  = $this->makeRequest('foo'); | ||
|  |         $response = $this->route->dispatch($request); | ||
|  |         $this->assertEquals('bar', $response->getContent()); | ||
|  |     } | ||
|  | 
 | ||
|  |     protected function createMiddleware($times = 1) | ||
|  |     { | ||
|  |         $middleware = m::mock(Str::random(5)); | ||
|  |         $middleware->shouldReceive('handle')->times($times)->andReturnUsing(function ($request, Closure $next) { | ||
|  |             return $next($request); | ||
|  |         }); | ||
|  |         $this->app->shouldReceive('make')->with($middleware->mockery_getName())->andReturn($middleware); | ||
|  | 
 | ||
|  |         return $middleware; | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testControllerWithMiddleware() | ||
|  |     { | ||
|  |         $this->route->get('foo', 'foo/bar'); | ||
|  | 
 | ||
|  |         $controller = m::mock(FooClass::class); | ||
|  | 
 | ||
|  |         $controller->middleware = [ | ||
|  |             $this->createMiddleware()->mockery_getName() . ":params1:params2", | ||
|  |             $this->createMiddleware(0)->mockery_getName() => ['except' => 'bar'], | ||
|  |             $this->createMiddleware()->mockery_getName()  => ['only' => 'bar'], | ||
|  |         ]; | ||
|  | 
 | ||
|  |         $this->app->shouldReceive('parseClass')->with('controller', 'Foo')->andReturn($controller->mockery_getName()); | ||
|  |         $this->app->shouldReceive('make')->with($controller->mockery_getName(), [], true)->andReturn($controller); | ||
|  | 
 | ||
|  |         $controller->shouldReceive('bar')->once()->andReturn('bar'); | ||
|  | 
 | ||
|  |         $request  = $this->makeRequest('foo'); | ||
|  |         $response = $this->route->dispatch($request); | ||
|  |         $this->assertEquals('bar', $response->getContent()); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testUrlDispatch() | ||
|  |     { | ||
|  |         $controller = m::mock(FooClass::class); | ||
|  |         $controller->shouldReceive('index')->andReturn('bar'); | ||
|  | 
 | ||
|  |         $this->app->shouldReceive('parseClass')->once()->with('controller', 'Foo')->andReturn($controller->mockery_getName()); | ||
|  |         $this->app->shouldReceive('make')->with($controller->mockery_getName(), [], true)->andReturn($controller); | ||
|  | 
 | ||
|  |         $request  = $this->makeRequest('foo'); | ||
|  |         $response = $this->route->dispatch($request); | ||
|  |         $this->assertEquals('bar', $response->getContent()); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testRedirectDispatch() | ||
|  |     { | ||
|  |         $this->route->redirect('foo', 'http://localhost', 302); | ||
|  | 
 | ||
|  |         $request = $this->makeRequest('foo'); | ||
|  |         $this->app->shouldReceive('make')->with(Request::class)->andReturn($request); | ||
|  |         $response = $this->route->dispatch($request); | ||
|  | 
 | ||
|  |         $this->assertInstanceOf(Redirect::class, $response); | ||
|  |         $this->assertEquals(302, $response->getCode()); | ||
|  |         $this->assertEquals('http://localhost', $response->getData()); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testViewDispatch() | ||
|  |     { | ||
|  |         $this->route->view('foo', 'index/hello', ['city' => 'shanghai']); | ||
|  | 
 | ||
|  |         $request  = $this->makeRequest('foo'); | ||
|  |         $response = $this->route->dispatch($request); | ||
|  | 
 | ||
|  |         $this->assertInstanceOf(View::class, $response); | ||
|  |         $this->assertEquals(['city' => 'shanghai'], $response->getVars()); | ||
|  |         $this->assertEquals('index/hello', $response->getData()); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testResponseDispatch() | ||
|  |     { | ||
|  |         $this->route->get('hello/:name', response() | ||
|  |             ->data('Hello,ThinkPHP') | ||
|  |             ->code(200) | ||
|  |             ->contentType('text/plain')); | ||
|  | 
 | ||
|  |         $request  = $this->makeRequest('hello/some'); | ||
|  |         $response = $this->route->dispatch($request); | ||
|  | 
 | ||
|  |         $this->assertEquals('Hello,ThinkPHP', $response->getContent()); | ||
|  |         $this->assertEquals(200, $response->getCode()); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function testDomainBindResponse() | ||
|  |     { | ||
|  |         $this->route->domain('test', function () { | ||
|  |             $this->route->get('/', function () { | ||
|  |                 return 'Hello,ThinkPHP'; | ||
|  |             }); | ||
|  |         }); | ||
|  | 
 | ||
|  |         $request  = $this->makeRequest('', 'get', 'test.domain.com'); | ||
|  |         $response = $this->route->dispatch($request); | ||
|  | 
 | ||
|  |         $this->assertEquals('Hello,ThinkPHP', $response->getContent()); | ||
|  |         $this->assertEquals(200, $response->getCode()); | ||
|  |     } | ||
|  | 
 | ||
|  | } | ||
|  | 
 | ||
|  | class FooClass | ||
|  | { | ||
|  |     public $middleware = []; | ||
|  | 
 | ||
|  |     public function bar() | ||
|  |     { | ||
|  | 
 | ||
|  |     } | ||
|  | } |