BuilderTest.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. <?php
  2. namespace Stack;
  3. use InvalidArgumentException;
  4. use PHPUnit\Framework\TestCase;
  5. use Symfony\Component\HttpFoundation\Request;
  6. use Symfony\Component\HttpFoundation\Response;
  7. use Symfony\Component\HttpKernel\HttpKernelInterface;
  8. use Symfony\Component\HttpKernel\TerminableInterface;
  9. /** @covers Stack\Builder */
  10. class BuilderTest extends TestCase
  11. {
  12. /** @test */
  13. public function withoutMiddlewaresItShouldReturnOriginalResponse()
  14. {
  15. $app = $this->getHttpKernelMock(new Response('ok'));
  16. $stack = new Builder();
  17. $resolved = $stack->resolve($app);
  18. $request = Request::create('/');
  19. $response = $resolved->handle($request);
  20. $this->assertInstanceOf('Stack\StackedHttpKernel', $resolved);
  21. $this->assertSame('ok', $response->getContent());
  22. }
  23. /** @test */
  24. public function resolvedKernelShouldDelegateTerminateCalls()
  25. {
  26. $app = $this->getTerminableMock();
  27. $stack = new Builder();
  28. $resolved = $stack->resolve($app);
  29. $request = Request::create('/');
  30. $response = new Response('ok');
  31. $resolved->handle($request);
  32. $resolved->terminate($request, $response);
  33. }
  34. /** @test */
  35. public function pushShouldReturnSelf()
  36. {
  37. $stack = new Builder();
  38. $this->assertSame($stack, $stack->push('Stack\AppendA'));
  39. }
  40. /** @test */
  41. public function pushShouldThrowOnInvalidInput()
  42. {
  43. $this->expectException(InvalidArgumentException::class);
  44. $this->expectExceptionMessage('Missing argument(s) when calling push');
  45. $stack = new Builder();
  46. $stack->push();
  47. }
  48. /** @test */
  49. public function unshiftShouldReturnSelf()
  50. {
  51. $stack = new Builder();
  52. $this->assertSame($stack, $stack->unshift('Stack\AppendA'));
  53. }
  54. /** @test */
  55. public function unshiftShouldThrowOnInvalidInput()
  56. {
  57. $this->expectException(InvalidArgumentException::class);
  58. $this->expectExceptionMessage('Missing argument(s) when calling unshift');
  59. $stack = new Builder();
  60. $stack->unshift();
  61. }
  62. /** @test */
  63. public function appendMiddlewareShouldAppendToBody()
  64. {
  65. $app = $this->getHttpKernelMock(new Response('ok'));
  66. $stack = new Builder();
  67. $stack->push('Stack\AppendA');
  68. $resolved = $stack->resolve($app);
  69. $request = Request::create('/');
  70. $response = $resolved->handle($request);
  71. $this->assertSame('ok.A', $response->getContent());
  72. }
  73. /** @test */
  74. public function unshiftMiddlewareShouldPutMiddlewareBeforePushed()
  75. {
  76. $app = $this->getHttpKernelMock(new Response('ok'));
  77. $stack = new Builder();
  78. $stack->push('Stack\Append', '2.');
  79. $stack->unshift('Stack\Append', '1.');
  80. $resolved = $stack->resolve($app);
  81. $request = Request::create('/');
  82. $response = $resolved->handle($request);
  83. $this->assertSame('ok2.1.', $response->getContent());
  84. }
  85. /** @test */
  86. public function stackedMiddlewaresShouldWrapInReverseOrder()
  87. {
  88. $app = $this->getHttpKernelMock(new Response('ok'));
  89. $stack = new Builder();
  90. $stack->push('Stack\AppendA');
  91. $stack->push('Stack\AppendB');
  92. $resolved = $stack->resolve($app);
  93. $request = Request::create('/');
  94. $response = $resolved->handle($request);
  95. $this->assertSame('ok.B.A', $response->getContent());
  96. }
  97. /** @test */
  98. public function resolveShouldPassPushArgumentsToMiddlewareConstructor()
  99. {
  100. $app = $this->getHttpKernelMock(new Response('ok'));
  101. $stack = new Builder();
  102. $stack->push('Stack\Append', '.foo');
  103. $stack->push('Stack\Append', '.bar');
  104. $resolved = $stack->resolve($app);
  105. $request = Request::create('/');
  106. $response = $resolved->handle($request);
  107. $this->assertSame('ok.bar.foo', $response->getContent());
  108. }
  109. /** @test */
  110. public function resolveShouldCallSpecFactories()
  111. {
  112. $app = $this->getHttpKernelMock(new Response('ok'));
  113. $stack = new Builder();
  114. $stack->push(function ($app) { return new Append($app, '.foo'); });
  115. $stack->push(function ($app) { return new Append($app, '.bar'); });
  116. $resolved = $stack->resolve($app);
  117. $request = Request::create('/');
  118. $response = $resolved->handle($request);
  119. $this->assertSame('ok.bar.foo', $response->getContent());
  120. }
  121. private function getHttpKernelMock(Response $response)
  122. {
  123. $app = $this->createMock(HttpKernelInterface::class);
  124. $app->expects($this->any())
  125. ->method('handle')
  126. ->with($this->isInstanceOf('Symfony\Component\HttpFoundation\Request'))
  127. ->will($this->returnValue($response));
  128. return $app;
  129. }
  130. private function getTerminableMock()
  131. {
  132. $app = $this->createMock(TerminableHttpKernel::class);
  133. $app->expects($this->once())
  134. ->method('terminate')
  135. ->with(
  136. $this->isInstanceOf('Symfony\Component\HttpFoundation\Request'),
  137. $this->isInstanceOf('Symfony\Component\HttpFoundation\Response')
  138. );
  139. return $app;
  140. }
  141. }
  142. abstract class TerminableHttpKernel implements HttpKernelInterface, TerminableInterface
  143. {
  144. }
  145. class Append implements HttpKernelInterface
  146. {
  147. private $app;
  148. private $appendix;
  149. public function __construct(HttpKernelInterface $app, $appendix)
  150. {
  151. $this->app = $app;
  152. $this->appendix = $appendix;
  153. }
  154. public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
  155. {
  156. $response = clone $this->app->handle($request, $type, $catch);
  157. $response->setContent($response->getContent().$this->appendix);
  158. return $response;
  159. }
  160. }
  161. class AppendA extends Append
  162. {
  163. public function __construct(HttpKernelInterface $app)
  164. {
  165. parent::__construct($app, '.A');
  166. }
  167. }
  168. class AppendB extends Append
  169. {
  170. public function __construct(HttpKernelInterface $app)
  171. {
  172. parent::__construct($app, '.B');
  173. }
  174. }