Skip to content

Commit aa303b6

Browse files
committed
Require PSR-17 factories instead of a PHP-HTTP factory
1 parent d6aa5d7 commit aa303b6

File tree

3 files changed

+102
-83
lines changed

3 files changed

+102
-83
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) princip
66

77
## Unreleased
88

9-
- Nothing
9+
### Changed
10+
- The `ResponseBuilder` now requires PSR-17 factories instead of a PHP-HTTP factory, to align it with the `Client`. This is only a breaking change in the rare case where you provide your own factory to the `ResponseBuilder`.
1011

1112
## [2.3.2] - 2021-08-30
1213

src/ResponseBuilder.php

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22

33
namespace Swis\Http\Fixture;
44

5-
use Http\Discovery\MessageFactoryDiscovery;
6-
use Http\Message\ResponseFactory;
5+
use Http\Discovery\Psr17FactoryDiscovery;
76
use Psr\Http\Message\RequestInterface;
7+
use Psr\Http\Message\ResponseFactoryInterface;
88
use Psr\Http\Message\ResponseInterface;
9+
use Psr\Http\Message\StreamFactoryInterface;
10+
use Psr\Http\Message\StreamInterface;
911
use Stringy\Stringy;
1012

1113
class ResponseBuilder implements ResponseBuilderInterface
@@ -36,25 +38,36 @@ class ResponseBuilder implements ResponseBuilderInterface
3638
private $domainAliases;
3739

3840
/**
39-
* @var \Http\Message\ResponseFactory
41+
* @var \Psr\Http\Message\ResponseFactoryInterface
4042
*/
4143
private $responseFactory;
4244

45+
/**
46+
* @var \Psr\Http\Message\StreamFactoryInterface
47+
*/
48+
private $streamFactory;
49+
4350
/**
4451
* @var bool
4552
*/
4653
private $strictMode = false;
4754

4855
/**
49-
* @param string $fixturesPath
50-
* @param array $domainAliases
51-
* @param \Http\Message\ResponseFactory|null $responseFactory
56+
* @param string $fixturesPath
57+
* @param array $domainAliases
58+
* @param \Psr\Http\Message\ResponseFactoryInterface|null $responseFactory
59+
* @param \Psr\Http\Message\StreamFactoryInterface|null $streamFactory
5260
*/
53-
public function __construct(string $fixturesPath, array $domainAliases = [], ResponseFactory $responseFactory = null)
54-
{
61+
public function __construct(
62+
string $fixturesPath,
63+
array $domainAliases = [],
64+
ResponseFactoryInterface $responseFactory = null,
65+
StreamFactoryInterface $streamFactory = null
66+
) {
5567
$this->fixturesPath = $fixturesPath;
5668
$this->domainAliases = $domainAliases;
57-
$this->responseFactory = $responseFactory ?: MessageFactoryDiscovery::find();
69+
$this->responseFactory = $responseFactory ?: Psr17FactoryDiscovery::findResponseFactory();
70+
$this->streamFactory = $streamFactory ?: Psr17FactoryDiscovery::findStreamFactory();
5871
}
5972

6073
/**
@@ -87,12 +100,15 @@ public function setStrictMode(bool $strictMode): self
87100
*/
88101
public function build(RequestInterface $request): ResponseInterface
89102
{
90-
return $this->responseFactory->createResponse(
91-
$this->getMockStatusForRequest($request),
92-
'',
93-
$this->getMockHeadersForRequest($request),
94-
$this->getMockBodyForRequest($request)
95-
);
103+
$response = $this->responseFactory
104+
->createResponse($this->getMockStatusForRequest($request))
105+
->withBody($this->getMockBodyForRequest($request));
106+
107+
foreach ($this->getMockHeadersForRequest($request) as $name => $value) {
108+
$response = $response->withHeader($name, $value);
109+
}
110+
111+
return $response;
96112
}
97113

98114
/**
@@ -137,13 +153,13 @@ protected function getMockHeadersForRequest(RequestInterface $request): array
137153
* @throws \RuntimeException
138154
* @throws \Swis\Http\Fixture\MockNotFoundException
139155
*
140-
* @return string
156+
* @return \Psr\Http\Message\StreamInterface
141157
*/
142-
protected function getMockBodyForRequest(RequestInterface $request): string
158+
protected function getMockBodyForRequest(RequestInterface $request): StreamInterface
143159
{
144160
$file = $this->getMockFilePathForRequest($request, self::TYPE_BODY);
145161

146-
return file_get_contents($file);
162+
return $this->streamFactory->createStreamFromFile($file);
147163
}
148164

149165
/**

tests/ResponseBuilderTest.php

Lines changed: 66 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
namespace Swis\Http\Fixture\Tests;
44

55
use GuzzleHttp\Psr7\Utils;
6-
use Http\Discovery\MessageFactoryDiscovery;
6+
use Http\Discovery\Psr17FactoryDiscovery;
77
use PHPUnit\Framework\TestCase;
8+
use RuntimeException;
89
use Swis\Http\Fixture\MockNotFoundException;
910
use Swis\Http\Fixture\ResponseBuilder;
1011
use Swis\Http\Fixture\ResponseBuilderInterface;
@@ -19,147 +20,148 @@ class ResponseBuilderTest extends TestCase
1920
* @param string $method
2021
* @param string $expectedMock
2122
*/
22-
public function itCanBuildAResponse(string $url, string $method, string $expectedMock)
23+
public function itCanBuildAResponse(string $url, string $method, string $expectedMock): void
2324
{
24-
$builder = $this->getBuilder();
25+
// arrange
26+
$requestFactory = Psr17FactoryDiscovery::findRequestFactory();
27+
$responseFactory = Psr17FactoryDiscovery::findResponseFactory();
2528

26-
$messageFactory = MessageFactoryDiscovery::find();
29+
$expectedResponse = $responseFactory->createResponse()
30+
->withBody(Utils::streamFor(file_get_contents($this->getFixturesPath().'/'.$expectedMock)));
2731

28-
$expectedResponse = $messageFactory->createResponse(
29-
200,
30-
null,
31-
[],
32-
Utils::streamFor(file_get_contents($this->getFixturesPath().'/'.$expectedMock))
33-
);
34-
$actualResponse = $builder->build(
35-
$messageFactory->createRequest($method, $url)
36-
);
32+
// act
33+
$actualResponse = $this->getBuilder()->build($requestFactory->createRequest($method, $url));
3734

35+
// assert
3836
$this->assertEquals($expectedResponse->getBody()->__toString(), $actualResponse->getBody()->__toString());
3937
}
4038

4139
public function getResponses(): array
4240
{
4341
return [
4442
// Simple
45-
['http://example.com/api/articles', 'GET', 'example.com/api/articles.mock'],
43+
['https://example.com/api/articles', 'GET', 'example.com/api/articles.mock'],
4644
// Nested
47-
['http://example.com/api/articles/1', 'GET', 'example.com/api/articles/1.mock'],
45+
['https://example.com/api/articles/1', 'GET', 'example.com/api/articles/1.mock'],
4846
// With simple query
49-
['http://example.com/api/comments?query=json', 'GET', 'example.com/api/comments.query=json.mock'],
47+
['https://example.com/api/comments?query=json', 'GET', 'example.com/api/comments.query=json.mock'],
5048
// With complex query
51-
['http://example.com/api/comments?query=json&foo[]=bar&foo[]=baz', 'GET', 'example.com/api/comments.foo[]=bar&foo[]=baz&query=json.mock'],
49+
['https://example.com/api/comments?query=json&foo[]=bar&foo[]=baz', 'GET', 'example.com/api/comments.foo[]=bar&foo[]=baz&query=json.mock'],
5250
// With query fallback
53-
['http://example.com/api/comments?foo=bar', 'GET', 'example.com/api/comments.mock'],
51+
['https://example.com/api/comments?foo=bar', 'GET', 'example.com/api/comments.mock'],
5452
// With method
55-
['http://example.com/api/people', 'GET', 'example.com/api/people.get.mock'],
53+
['https://example.com/api/people', 'GET', 'example.com/api/people.get.mock'],
5654
// With method fallback
57-
['http://example.com/api/people', 'POST', 'example.com/api/people.mock'],
55+
['https://example.com/api/people', 'POST', 'example.com/api/people.mock'],
5856
// With query and method
59-
['http://example.com/api/tags?query=json', 'POST', 'example.com/api/tags.query=json.post.mock'],
57+
['https://example.com/api/tags?query=json', 'POST', 'example.com/api/tags.query=json.post.mock'],
6058
// With query and method fallback
61-
['http://example.com/api/tags?foo=bar', 'GET', 'example.com/api/tags.mock'],
59+
['https://example.com/api/tags?foo=bar', 'GET', 'example.com/api/tags.mock'],
6260
];
6361
}
6462

6563
/**
6664
* @test
6765
*/
68-
public function itCanBeSetToStrictMode()
66+
public function itCanBeSetToStrictMode(): void
6967
{
7068
$builder = $this->getBuilder();
69+
$requestFactory = Psr17FactoryDiscovery::findRequestFactory();
7170

7271
// Strict mode off
7372
$this->assertFalse($builder->useStrictMode());
74-
75-
$messageFactory = MessageFactoryDiscovery::find();
76-
$builder->build($messageFactory->createRequest('POST', 'http://example.com/api/articles?foo=bar'));
73+
$builder->build($requestFactory->createRequest('POST', 'https://example.com/api/articles?foo=bar'));
7774

7875
// Strict mode on
7976
$builder->setStrictMode(true);
8077
$this->assertTrue($builder->useStrictMode());
81-
8278
$this->expectException(MockNotFoundException::class);
83-
84-
$messageFactory = MessageFactoryDiscovery::find();
85-
$builder->build($messageFactory->createRequest('POST', 'http://example.com/api/articles?foo=bar'));
79+
$builder->build($requestFactory->createRequest('POST', 'https://example.com/api/articles?foo=bar'));
8680
}
8781

8882
/**
8983
* @test
9084
*/
91-
public function itThrowsAnExceptionWhenItCantFindAFixture()
85+
public function itThrowsAnExceptionWhenItCantFindAFixture(): void
9286
{
87+
// arrange
88+
$requestFactory = Psr17FactoryDiscovery::findRequestFactory();
89+
90+
// assert
9391
$this->expectException(MockNotFoundException::class);
9492

95-
$messageFactory = MessageFactoryDiscovery::find();
96-
$this->getBuilder()->build($messageFactory->createRequest('GET', 'http://example.com/api/lorem-ipsum'));
93+
// act
94+
$this->getBuilder()->build($requestFactory->createRequest('GET', 'https://example.com/api/lorem-ipsum'));
9795
}
9896

9997
/**
10098
* @test
10199
*/
102-
public function itThrowsAnExceptionWhenPathIsOutOfBounds()
100+
public function itThrowsAnExceptionWhenPathIsOutOfBounds(): void
103101
{
104-
$this->expectException(\RuntimeException::class);
102+
// arrange
103+
$requestFactory = Psr17FactoryDiscovery::findRequestFactory();
104+
105+
// assert
106+
$this->expectException(RuntimeException::class);
105107

106-
$messageFactory = MessageFactoryDiscovery::find();
107-
$this->getBuilder()->build($messageFactory->createRequest('GET', 'http://example.com/../../out-of-bounds'));
108+
// act
109+
$this->getBuilder()->build($requestFactory->createRequest('GET', 'https://example.com/../../out-of-bounds'));
108110
}
109111

110112
/**
111113
* @test
112114
*/
113-
public function itCanBuildAResponseUsingDomainAliases()
115+
public function itCanBuildAResponseUsingDomainAliases(): void
114116
{
115-
$messageFactory = MessageFactoryDiscovery::find();
117+
// arrange
118+
$requestFactory = Psr17FactoryDiscovery::findRequestFactory();
119+
$responseFactory = Psr17FactoryDiscovery::findResponseFactory();
116120

117-
$expectedResponse = $messageFactory->createResponse(
118-
200,
119-
'',
120-
[],
121-
Utils::streamFor(file_get_contents($this->getFixturesPath().'/example.com/api/articles.mock'))
122-
);
121+
$expectedResponse = $responseFactory->createResponse()
122+
->withBody(Utils::streamFor(file_get_contents($this->getFixturesPath().'/example.com/api/articles.mock')));
123123

124-
$actualResponse = $this->getBuilder()->build($messageFactory->createRequest('GET', 'http://foo.bar/api/articles'));
124+
// act
125+
$actualResponse = $this->getBuilder()->build($requestFactory->createRequest('GET', 'https://foo.bar/api/articles'));
125126

127+
// assert
126128
$this->assertEquals($expectedResponse->getBody()->__toString(), $actualResponse->getBody()->__toString());
127129
}
128130

129131
/**
130132
* @test
131133
*/
132-
public function itCanBuildAResponseWithCustomHeaders()
134+
public function itCanBuildAResponseWithCustomHeaders(): void
133135
{
134-
$messageFactory = MessageFactoryDiscovery::find();
136+
// arrange
137+
$requestFactory = Psr17FactoryDiscovery::findRequestFactory();
138+
$responseFactory = Psr17FactoryDiscovery::findResponseFactory();
135139

136-
$expectedResponse = $messageFactory->createResponse(
137-
200,
138-
'',
139-
['X-Made-With' => 'PHPUnit'],
140-
Utils::streamFor(file_get_contents($this->getFixturesPath().'/example.com/api/articles.mock'))
141-
);
140+
$expectedResponse = $responseFactory->createResponse()
141+
->withHeader('X-Made-With', 'PHPUnit');
142142

143-
$actualResponse = $this->getBuilder()->build($messageFactory->createRequest('GET', 'http://example.com/api/articles'));
143+
// act
144+
$actualResponse = $this->getBuilder()->build($requestFactory->createRequest('GET', 'https://example.com/api/articles'));
144145

146+
// assert
145147
$this->assertEquals($expectedResponse->getHeaders(), $actualResponse->getHeaders());
146148
}
147149

148150
/**
149151
* @test
150152
*/
151-
public function itCanBuildAResponseWithCustomStatus()
153+
public function itCanBuildAResponseWithCustomStatus(): void
152154
{
153-
$messageFactory = MessageFactoryDiscovery::find();
155+
// arrange
156+
$requestFactory = Psr17FactoryDiscovery::findRequestFactory();
157+
$responseFactory = Psr17FactoryDiscovery::findResponseFactory();
158+
159+
$expectedResponse = $responseFactory->createResponse(500);
154160

155-
$expectedResponse = $messageFactory->createResponse(
156-
500,
157-
'',
158-
[],
159-
Utils::streamFor(file_get_contents($this->getFixturesPath().'/example.com/api/articles.mock'))
160-
);
161-
$actualResponse = $this->getBuilder()->build($messageFactory->createRequest('GET', 'http://example.com/api/articles'));
161+
// act
162+
$actualResponse = $this->getBuilder()->build($requestFactory->createRequest('GET', 'https://example.com/api/articles'));
162163

164+
// assert
163165
$this->assertEquals($expectedResponse->getStatusCode(), $actualResponse->getStatusCode());
164166
}
165167

0 commit comments

Comments
 (0)