request = $this->prophesize('Psr\Http\Message\ServerRequestInterface'); $this->response = $this->prophesize('Psr\Http\Message\ResponseInterface'); $this->response->hasHeader("Content-length")->willReturn(true); $this->response->getStatusCode()->willReturn(200); $this->routeMap = $this->prophesize('WellRESTed\Routing\RouteMapInterface'); $this->routeMap->add(Argument::cetera())->willReturn(); $this->routeMap->dispatch(Argument::cetera())->willReturn(); $this->router = $this->getMockBuilder('WellRESTed\Routing\Router') ->setMethods(["getRouteMap"]) ->disableOriginalConstructor() ->getMock(); $this->router->expects($this->any()) ->method("getRouteMap") ->will($this->returnValue($this->routeMap->reveal())); $this->router->__construct(); } // ------------------------------------------------------------------------ // Construction /** * @covers ::__construct * @covers ::getDispatcher * @covers ::getRouteMap * @covers ::getPreRouteHooks * @covers ::getPostRouteHooks * @covers ::getFinalizationHooks * @covers ::getStatusHooks */ public function testCreatesInstance() { $router = new Router(); $this->assertNotNull($router); } // ------------------------------------------------------------------------ // Routes /** * @covers ::add */ public function testAddRegistersRouteWithRouteMap() { $method = "GET"; $target = "/path/{id}"; $middleware = "Middleware"; $this->router->add($method, $target, $middleware); $this->routeMap->add($method, $target, $middleware)->shouldHaveBeenCalled(); } /** * @covers ::dispatch */ public function testDispatchesRouteMap() { $request = $this->request->reveal(); $resonse = $this->response->reveal(); $this->router->dispatch($request, $resonse); $this->routeMap->dispatch($request, Argument::any())->shouldHaveBeenCalled(); } // ------------------------------------------------------------------------ // Hooks /** * @covers ::addPreRouteHook * @covers ::dispatchPreRouteHooks */ public function testDispatchesPreRouteHooks() { $hook = $this->prophesize('\WellRESTed\Routing\MiddlewareInterface'); $hook->dispatch(Argument::cetera())->willReturn(); $this->router->addPreRouteHook($hook->reveal()); $request = $this->request->reveal(); $response = $this->response->reveal(); $this->router->dispatch($request, $response); $hook->dispatch(Argument::cetera())->shouldHaveBeenCalled(); } /** * @covers ::dispatch * @covers ::dispatchStatusHooks * @covers ::setStatusHook */ public function testDispatchesHookForStatusCode() { $this->response->getStatusCode()->willReturn(403); $statusMiddleware = $this->prophesize('\WellRESTed\Routing\MiddlewareInterface'); $statusMiddleware->dispatch(Argument::cetera())->willReturn(); $this->router->setStatusHook(403, $statusMiddleware->reveal()); $request = $this->request->reveal(); $response = $this->response->reveal(); $this->router->dispatch($request, $response); $statusMiddleware->dispatch(Argument::cetera())->shouldHaveBeenCalled(); } /** * @covers ::dispatch * @covers ::dispatchStatusHooks * @covers ::setStatusHook */ public function testConvertsHttpExceptionToResponse() { $statusMiddleware = $this->prophesize('\WellRESTed\Routing\MiddlewareInterface'); $statusMiddleware->dispatch(Argument::cetera())->willReturn(); $this->routeMap->dispatch(Argument::cetera())->willThrow(new NotFoundException()); $this->response->withStatus(Argument::any())->will( function ($args) { $this->getStatusCode()->willReturn($args[0]); return $this; } ); $this->response->withBody(Argument::any())->willReturn($this->response->reveal()); $request = $this->request->reveal(); $response = $this->response->reveal(); $this->router->dispatch($request, $response); $this->response->withStatus(404)->shouldHaveBeenCalled(); } /** * @covers ::addPostRouteHook * @covers ::dispatchPostRouteHooks */ public function testDispatchesPostRouteHooks() { $hook = $this->prophesize('\WellRESTed\Routing\MiddlewareInterface'); $hook->dispatch(Argument::cetera())->willReturn(); $this->router->addPostRouteHook($hook->reveal()); $request = $this->request->reveal(); $response = $this->response->reveal(); $this->router->dispatch($request, $response); $hook->dispatch(Argument::cetera())->shouldHaveBeenCalled(); } /** * @covers ::addFinalizationHook * @covers ::dispatchFinalizationHooks */ public function testDispatchesFinalizationHooks() { $hook = $this->prophesize('\WellRESTed\Routing\MiddlewareInterface'); $hook->dispatch(Argument::cetera())->willReturn(); $this->router->addFinalizationHook($hook->reveal()); $request = $this->request->reveal(); $response = $this->response->reveal(); $this->router->dispatch($request, $response); $hook->dispatch(Argument::cetera())->shouldHaveBeenCalled(); } /** * @coversNothing */ public function testDispatchesMiddlewareInCorrectSequence() { // Each middleware will push a value onto this array. $stack = []; $response = $this->response; $this->routeMap->dispatch(Argument::cetera())->will(function () use ($response, &$stack) { $stack[] = "routeMap"; $response->getStatusCode()->willReturn(404); }); $this->router->addPreRouteHook($this->createStackHook("pre1", $stack)); $this->router->addPreRouteHook($this->createStackHook("pre2", $stack)); $this->router->addPostRouteHook($this->createStackHook("post1", $stack)); $this->router->addPostRouteHook($this->createStackHook("post2", $stack)); $this->router->addFinalizationHook($this->createStackHook("final1", $stack)); $this->router->addFinalizationHook($this->createStackHook("final2", $stack)); $this->router->setStatusHook(404, $this->createStackHook("404", $stack)); $request = $this->request->reveal(); $response = $this->response->reveal(); $this->router->dispatch($request, $response); $this->assertEquals(["pre1","pre2","routeMap","404","post1","post2","final1","final2"], $stack); } private function createStackHook($name, &$stack) { $hook = $this->prophesize('\WellRESTed\Routing\MiddlewareInterface'); $hook->dispatch(Argument::cetera())->will(function () use ($name, &$stack) { $stack[] = $name; }); return $hook->reveal(); } /** * @coversNothing */ public function testProvidesContentLengthHeader() { $this->request->getMethod()->willReturn("HEAD"); $body = $this->prophesize('Psr\Http\Message\StreamInterface'); $body->getSize()->willReturn(1024); $this->response->getBody()->willReturn($body->reveal()); $this->response->hasHeader("Content-length")->willReturn(false); $this->response->getHeaderLine("Transfer-encoding")->willReturn(""); $this->response->withHeader(Argument::cetera())->will( function () { $this->hasHeader("Content-length")->willReturn(true); return $this; } ); $this->response->withBody(Argument::any())->willReturn($this->response->reveal()); $request = $this->request->reveal(); $response = $this->response->reveal(); $this->router->dispatch($request, $response); $this->response->withHeader(Argument::cetera())->shouldHaveBeenCalled(); } /** * @coversNothing */ public function testRemovesBodyForHeadRequest() { $this->request->getMethod()->willReturn("HEAD"); $body = $this->prophesize('Psr\Http\Message\StreamInterface'); $body->getSize()->willReturn(1024); $this->response->getBody()->willReturn($body->reveal()); $this->response->hasHeader("Content-length")->willReturn(false); $this->response->getHeaderLine("Transfer-encoding")->willReturn(""); $this->response->withHeader(Argument::cetera())->will( function () { $this->hasHeader("Content-length")->willReturn(true); return $this; } ); $this->response->withBody(Argument::any())->willReturn($this->response->reveal()); $request = $this->request->reveal(); $response = $this->response->reveal(); $this->router->dispatch($request, $response); $this->response->withBody(Argument::that(function ($body) { return $body->getSize() === 0; }))->shouldHaveBeenCalled(); } // ------------------------------------------------------------------------ // Respond /** * @covers ::respond * @covers ::getRequest * @covers ::getResponse * @covers ::getResponder */ public function testRespondDispatchesRequest() { $middleware = $this->prophesize('\WellRESTed\Routing\MiddlewareInterface'); $middleware->dispatch(Argument::cetera())->willReturn(); $responder = $this->prophesize('WellRESTed\Routing\ResponderInterface'); $responder->respond(Argument::any())->willReturn(); $routeMap = $this->prophesize('WellRESTed\Routing\RouteMapInterface'); $routeMap->dispatch(Argument::cetera())->will( function ($args) use ($middleware) { $middleware->reveal()->dispatch($args[0], $args[1]); } ); $router = $this->getMockBuilder('WellRESTed\Routing\Router') ->setMethods(["getRequest", "getResponse", "getResponder", "getRouteMap"]) ->disableOriginalConstructor() ->getMock(); $router->expects($this->any()) ->method("getRequest") ->will($this->returnValue($this->request->reveal())); $router->expects($this->any()) ->method("getResponse") ->will($this->returnValue($this->response->reveal())); $router->expects($this->any()) ->method("getResponder") ->will($this->returnValue($responder->reveal())); $router->expects($this->any()) ->method("getRouteMap") ->will($this->returnValue($routeMap->reveal())); $router->__construct(); $router->respond(); $middleware->dispatch(Argument::cetera())->shouldHaveBeenCalled(); } /** * @covers ::respond * @covers ::getRequest * @covers ::getResponse * @covers ::getResponder */ public function testSendsResponseToResponder() { $middleware = $this->prophesize('\WellRESTed\Routing\MiddlewareInterface'); $middleware->dispatch(Argument::cetera())->willReturn(); $responder = $this->prophesize('WellRESTed\Routing\ResponderInterface'); $responder->respond(Argument::any())->willReturn(); $routeMap = $this->prophesize('WellRESTed\Routing\RouteMapInterface'); $routeMap->dispatch(Argument::cetera())->will( function ($args) use ($middleware) { $middleware->reveal()->dispatch($args[0], $args[1]); } ); $router = $this->getMockBuilder('WellRESTed\Routing\Router') ->setMethods(["getRequest", "getResponse", "getResponder", "getRouteMap"]) ->disableOriginalConstructor() ->getMock(); $router->expects($this->any()) ->method("getRequest") ->will($this->returnValue($this->request->reveal())); $router->expects($this->any()) ->method("getResponse") ->will($this->returnValue($this->response->reveal())); $router->expects($this->any()) ->method("getResponder") ->will($this->returnValue($responder->reveal())); $router->expects($this->any()) ->method("getRouteMap") ->will($this->returnValue($routeMap->reveal())); $router->__construct(); $router->respond(); $responder->respond($this->response->reveal())->shouldHaveBeenCalled(); } }