Skip to content

Commit 8c86169

Browse files
authored
Create PipelineFactoryTest.php
1 parent 66de2c5 commit 8c86169

File tree

1 file changed

+235
-0
lines changed

1 file changed

+235
-0
lines changed

tests/PipelineFactoryTest.php

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Bermuda\Http\Middleware\Tests;
6+
7+
use Bermuda\Http\Middleware\PipelineFactory;
8+
use Bermuda\Http\Middleware\PipelineFactoryInterface;
9+
use Bermuda\Http\Middleware\PipelineInterface;
10+
use PHPUnit\Framework\TestCase;
11+
use PHPUnit\Framework\Attributes\Test;
12+
use Psr\Http\Message\ResponseInterface;
13+
use Psr\Http\Message\ServerRequestInterface;
14+
use Psr\Http\Server\MiddlewareInterface;
15+
use Psr\Http\Server\RequestHandlerInterface;
16+
17+
/**
18+
* Test suite for PipelineFactory.
19+
*
20+
* Validates that the factory correctly creates Pipeline instances with:
21+
* - Various middleware configurations
22+
* - Custom and default fallback handlers
23+
* - Different iterable types (array, generator)
24+
* - Proper interface compliance
25+
*
26+
* These tests ensure the factory serves as a reliable dependency injection
27+
* point for creating pipelines throughout an application.
28+
*/
29+
final class PipelineFactoryTest extends TestCase
30+
{
31+
private PipelineFactoryInterface $factory;
32+
private ServerRequestInterface $request;
33+
private ResponseInterface $response;
34+
35+
protected function setUp(): void
36+
{
37+
$this->factory = new PipelineFactory();
38+
$this->request = $this->createMock(ServerRequestInterface::class);
39+
$this->response = $this->createMock(ResponseInterface::class);
40+
}
41+
42+
#[Test]
43+
public function itImplementsPipelineFactoryInterface(): void
44+
{
45+
$this->assertInstanceOf(PipelineFactoryInterface::class, $this->factory);
46+
}
47+
48+
#[Test]
49+
public function itCreatesEmptyPipeline(): void
50+
{
51+
$pipeline = $this->factory->createMiddlewarePipeline();
52+
53+
$this->assertInstanceOf(PipelineInterface::class, $pipeline);
54+
$this->assertTrue($pipeline->isEmpty());
55+
$this->assertSame(0, $pipeline->count());
56+
}
57+
58+
#[Test]
59+
public function itCreatesPipelineWithMiddlewares(): void
60+
{
61+
$middleware1 = $this->createMock(MiddlewareInterface::class);
62+
$middleware2 = $this->createMock(MiddlewareInterface::class);
63+
$middleware3 = $this->createMock(MiddlewareInterface::class);
64+
65+
$pipeline = $this->factory->createMiddlewarePipeline([
66+
$middleware1,
67+
$middleware2,
68+
$middleware3,
69+
]);
70+
71+
$this->assertInstanceOf(PipelineInterface::class, $pipeline);
72+
$this->assertFalse($pipeline->isEmpty());
73+
$this->assertSame(3, $pipeline->count());
74+
$this->assertTrue($pipeline->has($middleware1));
75+
$this->assertTrue($pipeline->has($middleware2));
76+
$this->assertTrue($pipeline->has($middleware3));
77+
}
78+
79+
#[Test]
80+
public function itCreatesPipelineWithCustomHandler(): void
81+
{
82+
$executionOrder = [];
83+
84+
$middleware = $this->createMiddleware(function ($request, $handler) use (&$executionOrder) {
85+
$executionOrder[] = 'middleware';
86+
return $handler->handle($request);
87+
});
88+
89+
$customHandler = $this->createHandler(function () use (&$executionOrder) {
90+
$executionOrder[] = 'custom-handler';
91+
return $this->response;
92+
});
93+
94+
$pipeline = $this->factory->createMiddlewarePipeline(
95+
[$middleware],
96+
$customHandler
97+
);
98+
99+
$response = $pipeline->handle($this->request);
100+
101+
$this->assertSame($this->response, $response);
102+
$this->assertSame(['middleware', 'custom-handler'], $executionOrder);
103+
}
104+
105+
#[Test]
106+
public function itCreatesPipelineWithDefaultHandler(): void
107+
{
108+
$pipeline = $this->factory->createMiddlewarePipeline();
109+
110+
$this->expectException(\RuntimeException::class);
111+
$this->expectExceptionMessage('Failed to process the request. The pipeline is empty!');
112+
113+
$pipeline->handle($this->request);
114+
}
115+
116+
#[Test]
117+
public function itCreatesPipelineFromGenerator(): void
118+
{
119+
$middleware1 = $this->createMock(MiddlewareInterface::class);
120+
$middleware2 = $this->createMock(MiddlewareInterface::class);
121+
122+
$generator = function () use ($middleware1, $middleware2) {
123+
yield $middleware1;
124+
yield $middleware2;
125+
};
126+
127+
$pipeline = $this->factory->createMiddlewarePipeline($generator());
128+
129+
$this->assertInstanceOf(PipelineInterface::class, $pipeline);
130+
$this->assertSame(2, $pipeline->count());
131+
$this->assertTrue($pipeline->has($middleware1));
132+
$this->assertTrue($pipeline->has($middleware2));
133+
}
134+
135+
#[Test]
136+
public function itCreatesIndependentPipelineInstances(): void
137+
{
138+
$middleware1 = $this->createMock(MiddlewareInterface::class);
139+
$middleware2 = $this->createMock(MiddlewareInterface::class);
140+
141+
$pipeline1 = $this->factory->createMiddlewarePipeline([$middleware1]);
142+
$pipeline2 = $this->factory->createMiddlewarePipeline([$middleware2]);
143+
144+
$this->assertNotSame($pipeline1, $pipeline2);
145+
$this->assertSame(1, $pipeline1->count());
146+
$this->assertSame(1, $pipeline2->count());
147+
$this->assertTrue($pipeline1->has($middleware1));
148+
$this->assertFalse($pipeline1->has($middleware2));
149+
$this->assertTrue($pipeline2->has($middleware2));
150+
$this->assertFalse($pipeline2->has($middleware1));
151+
}
152+
153+
#[Test]
154+
public function itThrowsExceptionWhenCreatingPipelineWithInvalidMiddleware(): void
155+
{
156+
$this->expectException(\InvalidArgumentException::class);
157+
$this->expectExceptionMessage('Middleware at position 0 must implement');
158+
159+
$this->factory->createMiddlewarePipeline(['not a middleware']);
160+
}
161+
162+
#[Test]
163+
public function itCreatesFunctionalPipeline(): void
164+
{
165+
$executionOrder = [];
166+
167+
$middleware1 = $this->createMiddleware(function ($request, $handler) use (&$executionOrder) {
168+
$executionOrder[] = 1;
169+
return $handler->handle($request);
170+
});
171+
172+
$middleware2 = $this->createMiddleware(function ($request, $handler) use (&$executionOrder) {
173+
$executionOrder[] = 2;
174+
return $handler->handle($request);
175+
});
176+
177+
$middleware3 = $this->createMiddleware(function ($request, $handler) use (&$executionOrder) {
178+
$executionOrder[] = 3;
179+
return $handler->handle($request);
180+
});
181+
182+
$handler = $this->createHandler(function () use (&$executionOrder) {
183+
$executionOrder[] = 'handler';
184+
return $this->response;
185+
});
186+
187+
$pipeline = $this->factory->createMiddlewarePipeline(
188+
[$middleware1, $middleware2, $middleware3],
189+
$handler
190+
);
191+
192+
$response = $pipeline->handle($this->request);
193+
194+
$this->assertSame($this->response, $response);
195+
$this->assertSame([1, 2, 3, 'handler'], $executionOrder);
196+
}
197+
198+
/**
199+
* Creates a test middleware with custom callback logic.
200+
*
201+
* @param callable $callback The callback to execute when middleware processes a request.
202+
* @return MiddlewareInterface A middleware instance that delegates to the callback.
203+
*/
204+
private function createMiddleware(callable $callback): MiddlewareInterface
205+
{
206+
return new class($callback) implements MiddlewareInterface {
207+
public function __construct(private $callback) {}
208+
209+
public function process(
210+
ServerRequestInterface $request,
211+
RequestHandlerInterface $handler
212+
): ResponseInterface {
213+
return ($this->callback)($request, $handler);
214+
}
215+
};
216+
}
217+
218+
/**
219+
* Creates a test request handler with custom callback logic.
220+
*
221+
* @param callable $callback The callback to execute when handler processes a request.
222+
* @return RequestHandlerInterface A handler instance that delegates to the callback.
223+
*/
224+
private function createHandler(callable $callback): RequestHandlerInterface
225+
{
226+
return new class($callback) implements RequestHandlerInterface {
227+
public function __construct(private $callback) {}
228+
229+
public function handle(ServerRequestInterface $request): ResponseInterface
230+
{
231+
return ($this->callback)($request);
232+
}
233+
};
234+
}
235+
}

0 commit comments

Comments
 (0)