-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMock_Http_Response.php
More file actions
312 lines (275 loc) · 7.6 KB
/
Copy pathMock_Http_Response.php
File metadata and controls
312 lines (275 loc) · 7.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
<?php
/**
* This file contains the Mock_Http_Response class
*
* @package Mantle
*/
namespace Mantle\Testing;
use Mantle\Contracts\Support\Arrayable;
use Mantle\Support\Traits\Conditionable;
use Mantle\Support\Traits\Macroable;
/**
* This class provides a mock HTTP response to be able to simulate HTTP requests
* in WordPress.
*
* Example:
*
* Mock_Http_Response::create()
* ->with_response_code( 404 )
* ->with_body( '{"error":true}' )
* ->with_header( 'Content-Type', 'application/json' );
*
* @phpstan-import-type WpHttpRequestResponse from \Mantle\Http_Client\Response
*/
class Mock_Http_Response implements Arrayable {
use Concerns\Snapshots\Mocks_Http_Requests;
use Conditionable;
use Macroable;
/**
* Response data.
*
* @var WpHttpRequestResponse
*/
public array $response;
/**
* Http Sequences
* Support for faking a series of fake responses in a specific order.
*/
public static function sequence(): Mock_Http_Sequence {
return new Mock_Http_Sequence();
}
/**
* Mock_Http_Response constructor.
*
* @param string $body Response body.
* @param array<string, string> $headers Response headers.
*/
public function __construct( string $body = '', array $headers = [] ) {
$this->response = [
'headers' => $headers,
'body' => $body,
'response' => [
'code' => 200,
'message' => get_status_header_desc( 200 ),
],
'cookies' => [],
'filename' => '',
];
}
/**
* Ensure that a response is an instance of Mock_Http_Response.
*
* @param mixed $response Response.
*/
public static function ensure( mixed $response ): Mock_Http_Response {
if ( $response instanceof self ) {
return $response;
}
return static::create( $response );
}
/**
* Helper method to create a response.
*
* @param string $body Response body.
* @param array $headers Response headers.
*/
public static function create( string $body = '', array $headers = [] ): Mock_Http_Response {
return new static( $body, $headers );
}
/**
* Create a JSON response.
*
* @param array $body Response body.
* @param array $headers Response headers.
*/
public static function json( array $body, array $headers = [] ): Mock_Http_Response {
return static::create()
->with_json( $body )
->with_headers( $headers );
}
/**
* Add a header to the response.
*
* @param string $key Header key.
* @param string $value Header value.
* @return Mock_Http_Response This object.
*/
public function with_header( string $key, string $value ): Mock_Http_Response {
$this->response['headers'][ $key ] = $value;
return $this;
}
/**
* Add an array of headers to the response.
*
* @param array<string, string> $headers Headers to append.
*/
public function with_headers( array $headers ): Mock_Http_Response {
foreach ( $headers as $key => $value ) {
$this->with_header( $key, $value );
}
return $this;
}
/**
* Set the response code. The response message will be inferred from that.
*
* @param int $code HTTP response code.
* @return Mock_Http_Response This object.
*/
public function with_response_code( int $code ): Mock_Http_Response {
$this->response['response'] = [
'code' => $code,
'message' => get_status_header_desc( $code ),
];
return $this;
}
/**
* Alias for with_response_code().
*
* @param int $code HTTP response code.
* @return Mock_Http_Response This object.
*/
public function with_status( int $code ): Mock_Http_Response {
return $this->with_response_code( $code );
}
/**
* Set the response body.
*
* @param string $body Response body.
* @return Mock_Http_Response This object.
*/
public function with_body( string $body ): Mock_Http_Response {
$this->response['body'] = $body;
return $this;
}
/**
* Set a response cookie.
*
* @param \WP_Http_Cookie $cookie Cookie.
* @return Mock_Http_Response This object.
*/
public function with_cookie( \WP_Http_Cookie $cookie ): Mock_Http_Response {
$this->response['cookies'][] = $cookie;
return $this;
}
/**
* Set the filename value for the mock response.
*
* @param string $filename Filename.
* @return Mock_Http_Response This object.
*/
public function with_filename( string $filename ): Mock_Http_Response {
$this->response['filename'] = $filename;
return $this;
}
/**
* Set the JSON body for the response.
*
* Also sets the proper JSON Content-Type header.
*
* @param array|string $payload JSON Payload to use.
* @return Mock_Http_Response This object.
*/
public function with_json( $payload ): Mock_Http_Response {
return $this
->with_body( is_string( $payload ) ? $payload : (string) wp_json_encode( $payload ) )
->with_header( 'Content-Type', 'application/json' );
}
/**
* Set the XML body for the response.
*
* Also sets the proper application/xml Content-Type header.
*
* @param string $payload JSON Payload to use.
* @return Mock_Http_Response This object.
*/
public function with_xml( string $payload ): Mock_Http_Response {
return $this
->with_body( $payload )
->with_header( 'Content-Type', 'application/xml' );
}
/**
* Set the response as a 301 redirect
*
* @param string $url Redirect URL.
* @param int $code Status code.
* @return Mock_Http_Response This object.
*/
public function with_redirect( string $url, int $code = 301 ): Mock_Http_Response {
return $this
->with_header( 'Location', $url )
->with_response_code( $code );
}
/**
* Set the response as a 302 temporary redirect
*
* @param string $url Redirect URL.
* @return Mock_Http_Response This object.
*/
public function with_temporary_redirect( string $url ): Mock_Http_Response {
return $this
->with_header( 'Location', $url )
->with_response_code( 302 );
}
/**
* Create a response with the file contents as the body.
*
* @throws \InvalidArgumentException If the file is not readable.
*
* @param string $file File path.
* @param string $filename Optional. Filename to use in the Content-Disposition header.
*/
public function with_file( string $file, ?string $filename = null ): Mock_Http_Response {
if ( ! is_readable( $file ) ) {
throw new \InvalidArgumentException( "File '{$file}' is not readable." );
}
if ( ! $filename ) {
$filename = basename( $file );
}
// Determine the mime type.
$mime_type = wp_check_filetype( $file );
// Set the headers.
if ( ! empty( $mime_type['type'] ) ) {
$this->with_header( 'Content-Type', $mime_type['type'] );
}
if ( ! empty( $mime_type['ext'] ) ) {
$this->with_header(
'Content-Disposition',
sprintf(
'attachment; filename="%s.%s"',
pathinfo( $filename, PATHINFO_FILENAME ),
$mime_type['ext'],
),
);
}
return $this
->with_filename( $file )
->with_body( (string) file_get_contents( $file ) ); // phpcs:ignore WordPressVIPMinimum.Performance.FetchingRemoteData.FileGetContentsUnknown
}
/**
* Create a response with an image file as the body.
*
* The image will be a JPEG file.
*
* @param string|null $filename Optional. Filename to use in the Content-Disposition header.
*/
public function with_image( ?string $filename = null ): Mock_Http_Response {
return $this->with_file(
__DIR__ . '/data/images/canola.jpg',
$filename,
);
}
/**
* Returns the combined response array.
*
* @return array WP_Http response array, per WP_Http::request().
*/
public function to_array(): array {
return $this->response;
}
/**
* Returns a Http_Client response object.
*/
public function to_response(): \Mantle\Http_Client\Response {
return \Mantle\Http_Client\Response::create( $this->response );
}
}