Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Illuminate\Http\Client;
4
 
5
use Closure;
6
use GuzzleHttp\Promise\PromiseInterface;
7
use GuzzleHttp\Psr7\Response as Psr7Response;
8
use GuzzleHttp\TransferStats;
9
use Illuminate\Contracts\Events\Dispatcher;
10
use Illuminate\Support\Str;
11
use Illuminate\Support\Traits\Macroable;
12
use PHPUnit\Framework\Assert as PHPUnit;
13
 
14
/**
15
 * @mixin \Illuminate\Http\Client\PendingRequest
16
 */
17
class Factory
18
{
19
    use Macroable {
20
        __call as macroCall;
21
    }
22
 
23
    /**
24
     * The event dispatcher implementation.
25
     *
26
     * @var \Illuminate\Contracts\Events\Dispatcher|null
27
     */
28
    protected $dispatcher;
29
 
30
    /**
31
     * The stub callables that will handle requests.
32
     *
33
     * @var \Illuminate\Support\Collection
34
     */
35
    protected $stubCallbacks;
36
 
37
    /**
38
     * Indicates if the factory is recording requests and responses.
39
     *
40
     * @var bool
41
     */
42
    protected $recording = false;
43
 
44
    /**
45
     * The recorded response array.
46
     *
47
     * @var array
48
     */
49
    protected $recorded = [];
50
 
51
    /**
52
     * All created response sequences.
53
     *
54
     * @var array
55
     */
56
    protected $responseSequences = [];
57
 
58
    /**
59
     * Indicates that an exception should be thrown if any request is not faked.
60
     *
61
     * @var bool
62
     */
63
    protected $preventStrayRequests = false;
64
 
65
    /**
66
     * Create a new factory instance.
67
     *
68
     * @param  \Illuminate\Contracts\Events\Dispatcher|null  $dispatcher
69
     * @return void
70
     */
71
    public function __construct(Dispatcher $dispatcher = null)
72
    {
73
        $this->dispatcher = $dispatcher;
74
 
75
        $this->stubCallbacks = collect();
76
    }
77
 
78
    /**
79
     * Create a new response instance for use during stubbing.
80
     *
81
     * @param  array|string|null  $body
82
     * @param  int  $status
83
     * @param  array  $headers
84
     * @return \GuzzleHttp\Promise\PromiseInterface
85
     */
86
    public static function response($body = null, $status = 200, $headers = [])
87
    {
88
        if (is_array($body)) {
89
            $body = json_encode($body);
90
 
91
            $headers['Content-Type'] = 'application/json';
92
        }
93
 
94
        $response = new Psr7Response($status, $headers, $body);
95
 
96
        return class_exists(\GuzzleHttp\Promise\Create::class)
97
            ? \GuzzleHttp\Promise\Create::promiseFor($response)
98
            : \GuzzleHttp\Promise\promise_for($response);
99
    }
100
 
101
    /**
102
     * Get an invokable object that returns a sequence of responses in order for use during stubbing.
103
     *
104
     * @param  array  $responses
105
     * @return \Illuminate\Http\Client\ResponseSequence
106
     */
107
    public function sequence(array $responses = [])
108
    {
109
        return $this->responseSequences[] = new ResponseSequence($responses);
110
    }
111
 
112
    /**
113
     * Register a stub callable that will intercept requests and be able to return stub responses.
114
     *
115
     * @param  callable|array|null  $callback
116
     * @return $this
117
     */
118
    public function fake($callback = null)
119
    {
120
        $this->record();
121
 
122
        $this->recorded = [];
123
 
124
        if (is_null($callback)) {
125
            $callback = function () {
126
                return static::response();
127
            };
128
        }
129
 
130
        if (is_array($callback)) {
131
            foreach ($callback as $url => $callable) {
132
                $this->stubUrl($url, $callable);
133
            }
134
 
135
            return $this;
136
        }
137
 
138
        $this->stubCallbacks = $this->stubCallbacks->merge(collect([
139
            function ($request, $options) use ($callback) {
140
                $response = $callback instanceof Closure
141
                                ? $callback($request, $options)
142
                                : $callback;
143
 
144
                if ($response instanceof PromiseInterface) {
145
                    $options['on_stats'](new TransferStats(
146
                        $request->toPsrRequest(),
147
                        $response->wait(),
148
                    ));
149
                }
150
 
151
                return $response;
152
            },
153
        ]));
154
 
155
        return $this;
156
    }
157
 
158
    /**
159
     * Register a response sequence for the given URL pattern.
160
     *
161
     * @param  string  $url
162
     * @return \Illuminate\Http\Client\ResponseSequence
163
     */
164
    public function fakeSequence($url = '*')
165
    {
166
        return tap($this->sequence(), function ($sequence) use ($url) {
167
            $this->fake([$url => $sequence]);
168
        });
169
    }
170
 
171
    /**
172
     * Stub the given URL using the given callback.
173
     *
174
     * @param  string  $url
175
     * @param  \Illuminate\Http\Client\Response|\GuzzleHttp\Promise\PromiseInterface|callable  $callback
176
     * @return $this
177
     */
178
    public function stubUrl($url, $callback)
179
    {
180
        return $this->fake(function ($request, $options) use ($url, $callback) {
181
            if (! Str::is(Str::start($url, '*'), $request->url())) {
182
                return;
183
            }
184
 
185
            return $callback instanceof Closure || $callback instanceof ResponseSequence
186
                        ? $callback($request, $options)
187
                        : $callback;
188
        });
189
    }
190
 
191
    /**
192
     * Indicate that an exception should be thrown if any request is not faked.
193
     *
194
     * @param  bool  $prevent
195
     * @return $this
196
     */
197
    public function preventStrayRequests($prevent = true)
198
    {
199
        $this->preventStrayRequests = $prevent;
200
 
201
        return $this;
202
    }
203
 
204
    /**
205
     * Indicate that an exception should not be thrown if any request is not faked.
206
     *
207
     * @return $this
208
     */
209
    public function allowStrayRequests()
210
    {
211
        return $this->preventStrayRequests(false);
212
    }
213
 
214
    /**
215
     * Begin recording request / response pairs.
216
     *
217
     * @return $this
218
     */
219
    protected function record()
220
    {
221
        $this->recording = true;
222
 
223
        return $this;
224
    }
225
 
226
    /**
227
     * Record a request response pair.
228
     *
229
     * @param  \Illuminate\Http\Client\Request  $request
230
     * @param  \Illuminate\Http\Client\Response  $response
231
     * @return void
232
     */
233
    public function recordRequestResponsePair($request, $response)
234
    {
235
        if ($this->recording) {
236
            $this->recorded[] = [$request, $response];
237
        }
238
    }
239
 
240
    /**
241
     * Assert that a request / response pair was recorded matching a given truth test.
242
     *
243
     * @param  callable  $callback
244
     * @return void
245
     */
246
    public function assertSent($callback)
247
    {
248
        PHPUnit::assertTrue(
249
            $this->recorded($callback)->count() > 0,
250
            'An expected request was not recorded.'
251
        );
252
    }
253
 
254
    /**
255
     * Assert that the given request was sent in the given order.
256
     *
257
     * @param  array  $callbacks
258
     * @return void
259
     */
260
    public function assertSentInOrder($callbacks)
261
    {
262
        $this->assertSentCount(count($callbacks));
263
 
264
        foreach ($callbacks as $index => $url) {
265
            $callback = is_callable($url) ? $url : function ($request) use ($url) {
266
                return $request->url() == $url;
267
            };
268
 
269
            PHPUnit::assertTrue($callback(
270
                $this->recorded[$index][0],
271
                $this->recorded[$index][1]
272
            ), 'An expected request (#'.($index + 1).') was not recorded.');
273
        }
274
    }
275
 
276
    /**
277
     * Assert that a request / response pair was not recorded matching a given truth test.
278
     *
279
     * @param  callable  $callback
280
     * @return void
281
     */
282
    public function assertNotSent($callback)
283
    {
284
        PHPUnit::assertFalse(
285
            $this->recorded($callback)->count() > 0,
286
            'Unexpected request was recorded.'
287
        );
288
    }
289
 
290
    /**
291
     * Assert that no request / response pair was recorded.
292
     *
293
     * @return void
294
     */
295
    public function assertNothingSent()
296
    {
297
        PHPUnit::assertEmpty(
298
            $this->recorded,
299
            'Requests were recorded.'
300
        );
301
    }
302
 
303
    /**
304
     * Assert how many requests have been recorded.
305
     *
306
     * @param  int  $count
307
     * @return void
308
     */
309
    public function assertSentCount($count)
310
    {
311
        PHPUnit::assertCount($count, $this->recorded);
312
    }
313
 
314
    /**
315
     * Assert that every created response sequence is empty.
316
     *
317
     * @return void
318
     */
319
    public function assertSequencesAreEmpty()
320
    {
321
        foreach ($this->responseSequences as $responseSequence) {
322
            PHPUnit::assertTrue(
323
                $responseSequence->isEmpty(),
324
                'Not all response sequences are empty.'
325
            );
326
        }
327
    }
328
 
329
    /**
330
     * Get a collection of the request / response pairs matching the given truth test.
331
     *
332
     * @param  callable  $callback
333
     * @return \Illuminate\Support\Collection
334
     */
335
    public function recorded($callback = null)
336
    {
337
        if (empty($this->recorded)) {
338
            return collect();
339
        }
340
 
341
        $callback = $callback ?: function () {
342
            return true;
343
        };
344
 
345
        return collect($this->recorded)->filter(function ($pair) use ($callback) {
346
            return $callback($pair[0], $pair[1]);
347
        });
348
    }
349
 
350
    /**
351
     * Create a new pending request instance for this factory.
352
     *
353
     * @return \Illuminate\Http\Client\PendingRequest
354
     */
355
    protected function newPendingRequest()
356
    {
357
        return new PendingRequest($this);
358
    }
359
 
360
    /**
361
     * Get the current event dispatcher implementation.
362
     *
363
     * @return \Illuminate\Contracts\Events\Dispatcher|null
364
     */
365
    public function getDispatcher()
366
    {
367
        return $this->dispatcher;
368
    }
369
 
370
    /**
371
     * Execute a method against a new pending request instance.
372
     *
373
     * @param  string  $method
374
     * @param  array  $parameters
375
     * @return mixed
376
     */
377
    public function __call($method, $parameters)
378
    {
379
        if (static::hasMacro($method)) {
380
            return $this->macroCall($method, $parameters);
381
        }
382
 
383
        return tap($this->newPendingRequest(), function ($request) {
384
            $request->stub($this->stubCallbacks)->preventStrayRequests($this->preventStrayRequests);
385
        })->{$method}(...$parameters);
386
    }
387
}