• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zfegg / expressive-test / 5770564942

pending completion
5770564942

push

github

web-flow
Merge pull request #15 from zfegg/develop

Fix serverVariables

1 of 1 new or added line in 1 file covered. (100.0%)

353 of 372 relevant lines covered (94.89%)

4.79 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.69
/src/TestResponse.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Zfegg\ExpressiveTest;
6

7
use Dflydev\FigCookies\SetCookie;
8
use Dflydev\FigCookies\SetCookies;
9
use PHPUnit\Framework\Assert;
10
use Psr\Http\Message\ResponseInterface;
11

12
/**
13
 * @mixin ResponseInterface
14
 */
15
class TestResponse
16
{
17
    /**
18
     * The response to delegate to.
19
     *
20
     * @var ResponseInterface
21
     */
22
    public $baseResponse;
23

24
    /**
25
     * The streamed content of the response.
26
     *
27
     * @var string
28
     */
29
    protected $streamedContent;
30

31
    /**
32
     * Create a new test response instance.
33
     *
34
     * @param  ResponseInterface  $response
35
     * @return void
36
     */
37
    public function __construct(ResponseInterface $response)
38
    {
39
        $this->baseResponse = $response;
35✔
40
    }
41

42
    /**
43
     * Create a new TestResponse from another response.
44
     *
45
     * @param  ResponseInterface  $response
46
     * @return static
47
     */
48
    public static function fromBaseResponse(ResponseInterface $response)
49
    {
50
        return new static($response);
11✔
51
    }
52

53
    /**
54
     * Assert that the response has a successful status code.
55
     *
56
     * @return $this
57
     */
58
    public function assertSuccessful()
59
    {
60
        Assert::assertTrue(
1✔
61
            $this->getStatusCode() >= 200 && $this->getStatusCode() < 300,
1✔
62
            'Response status code [' . $this->getStatusCode() . '] is not a successful status code.'
1✔
63
        );
1✔
64

65
        return $this;
1✔
66
    }
67

68
    /**
69
     * Assert that the response has a 200 status code.
70
     *
71
     * @return $this
72
     */
73
    public function assertOk()
74
    {
75
        Assert::assertEquals(
11✔
76
            200,
11✔
77
            $this->getStatusCode(),
11✔
78
            'Response status code [' . $this->getStatusCode() . '] does not match expected 200 status code.'
11✔
79
        );
11✔
80

81
        return $this;
11✔
82
    }
83

84
    /**
85
     * Assert that the response has a 201 status code.
86
     *
87
     * @return $this
88
     */
89
    public function assertCreated()
90
    {
91
        $actual = $this->getStatusCode();
1✔
92

93
        Assert::assertTrue(
1✔
94
            201 === $actual,
1✔
95
            'Response status code [' . $actual . '] does not match expected 201 status code.'
1✔
96
        );
1✔
97

98
        return $this;
1✔
99
    }
100

101
    /**
102
     * Assert that the response has the given status code and no content.
103
     *
104
     * @param  int  $status
105
     * @return $this
106
     */
107
    public function assertNoContent($status = 204)
108
    {
109
        $this->assertStatus($status);
2✔
110

111
        Assert::assertEmpty((string)$this->getBody(), 'Response content is not empty.');
2✔
112

113
        return $this;
2✔
114
    }
115

116
    /**
117
     * Assert that the response has a not found status code.
118
     *
119
     * @return $this
120
     */
121
    public function assertNotFound()
122
    {
123
        Assert::assertEquals(
1✔
124
            404,
1✔
125
            $this->getStatusCode(),
1✔
126
            'Response status code [' . $this->getStatusCode() . '] is not a not found status code.'
1✔
127
        );
1✔
128

129
        return $this;
1✔
130
    }
131

132
    /**
133
     * Assert that the response has a forbidden status code.
134
     *
135
     * @return $this
136
     */
137
    public function assertForbidden()
138
    {
139
        Assert::assertTrue(
1✔
140
            $this->getStatusCode() == 403,
1✔
141
            'Response status code [' . $this->getStatusCode() . '] is not a forbidden status code.'
1✔
142
        );
1✔
143

144
        return $this;
1✔
145
    }
146

147
    /**
148
     * Assert that the response has an unauthorized status code.
149
     *
150
     * @return $this
151
     */
152
    public function assertUnauthorized()
153
    {
154
        $actual = $this->getStatusCode();
1✔
155

156
        Assert::assertTrue(
1✔
157
            401 === $actual,
1✔
158
            'Response status code [' . $actual . '] is not an unauthorized status code.'
1✔
159
        );
1✔
160

161
        return $this;
1✔
162
    }
163

164
    /**
165
     * Assert that the response has the given status code.
166
     *
167
     * @param  int  $status
168
     * @return $this
169
     */
170
    public function assertStatus($status)
171
    {
172
        $actual = $this->getStatusCode();
3✔
173

174
        Assert::assertTrue(
3✔
175
            $actual === $status,
3✔
176
            "Expected status code {$status} but received {$actual}."
3✔
177
        );
3✔
178

179
        return $this;
3✔
180
    }
181

182
    /**
183
     * Assert whether the response is redirecting to a given URI.
184
     *
185
     * @param  string|null  $uri
186
     * @return $this
187
     */
188
    public function assertRedirect($uri = null)
189
    {
190
        Assert::assertTrue(
1✔
191
            $this->getStatusCode() == 301 || $this->getStatusCode() == 302,
1✔
192
            'Response status code [' . $this->getStatusCode() . '] is not a redirect status code.'
1✔
193
        );
1✔
194

195
        if (! is_null($uri)) {
1✔
196
            $this->assertLocation($uri);
1✔
197
        }
198

199
        return $this;
1✔
200
    }
201

202
    /**
203
     * Asserts that the response contains the given header and equals the optional value.
204
     *
205
     * @param  string  $headerName
206
     * @param  mixed  $value
207
     * @return $this
208
     */
209
    public function assertHeader($headerName, $value = null)
210
    {
211
        Assert::assertTrue(
1✔
212
            $this->hasHeader($headerName),
1✔
213
            "Header [{$headerName}] not present on response."
1✔
214
        );
1✔
215

216
        $actual = $this->getHeaderLine($headerName);
1✔
217

218
        if (! is_null($value)) {
1✔
219
            Assert::assertEquals(
1✔
220
                $value,
1✔
221
                $actual,
1✔
222
                "Header [{$headerName}] was found, but value [{$actual}] does not match [{$value}]."
1✔
223
            );
1✔
224
        }
225

226
        return $this;
1✔
227
    }
228

229
    /**
230
     * Asserts that the response does not contains the given header.
231
     *
232
     * @param  string  $headerName
233
     * @return $this
234
     */
235
    public function assertHeaderMissing($headerName)
236
    {
237
        Assert::assertFalse(
1✔
238
            $this->hasHeader($headerName),
1✔
239
            "Unexpected header [{$headerName}] is present on response."
1✔
240
        );
1✔
241

242
        return $this;
1✔
243
    }
244

245
    /**
246
     * Assert that the current location header matches the given URI.
247
     *
248
     * @param  string  $uri
249
     * @return $this
250
     */
251
    public function assertLocation($uri)
252
    {
253
        Assert::assertEquals(
1✔
254
            $uri,
1✔
255
            $this->getHeaderLine('Location')
1✔
256
        );
1✔
257

258
        return $this;
1✔
259
    }
260

261

262
    /**
263
     * Asserts that the response contains the given cookie and equals the optional value.
264
     *
265
     * @param  string  $cookieName
266
     * @param  mixed  $value
267
     * @return $this
268
     */
269
    public function assertCookie($cookieName, $value = null)
270
    {
271
        Assert::assertNotNull(
1✔
272
            $cookie = $this->getCookie($cookieName),
1✔
273
            "Cookie [{$cookieName}] not present on response."
1✔
274
        );
1✔
275

276
        if (! $cookie || is_null($value)) {
1✔
277
            return $this;
×
278
        }
279

280
        $cookieValue = $cookie->getValue();
1✔
281

282
        Assert::assertEquals(
1✔
283
            $value,
1✔
284
            $cookieValue,
1✔
285
            "Cookie [{$cookieName}] was found, but value [{$cookieValue}] does not match [{$value}]."
1✔
286
        );
1✔
287

288
        return $this;
1✔
289
    }
290

291
    /**
292
     * Asserts that the response contains the given cookie and is expired.
293
     *
294
     * @param  string  $cookieName
295
     * @return $this
296
     */
297
    public function assertCookieExpired($cookieName)
298
    {
299
        Assert::assertNotNull(
1✔
300
            $cookie = $this->getCookie($cookieName),
1✔
301
            "Cookie [{$cookieName}] not present on response."
1✔
302
        );
1✔
303

304
        Assert::assertLessThan(
1✔
305
            time(),
1✔
306
            $cookie->getExpires(),
1✔
307
            "Cookie [{$cookieName}] is not expired, it expires at [{$cookie->getExpires()}]."
1✔
308
        );
1✔
309

310
        return $this;
1✔
311
    }
312

313
    /**
314
     * Asserts that the response contains the given cookie and is not expired.
315
     *
316
     * @param  string  $cookieName
317
     * @return $this
318
     */
319
    public function assertCookieNotExpired($cookieName)
320
    {
321
        Assert::assertNotNull(
1✔
322
            $cookie = $this->getCookie($cookieName),
1✔
323
            "Cookie [{$cookieName}] not present on response."
1✔
324
        );
1✔
325

326
        Assert::assertGreaterThan(
1✔
327
            time(),
1✔
328
            $cookie->getExpires(),
1✔
329
            "Cookie [{$cookieName}] is expired, it expired at [{$cookie->getExpires()}]."
1✔
330
        );
1✔
331

332
        return $this;
1✔
333
    }
334

335
    /**
336
     * Asserts that the response does not contains the given cookie.
337
     *
338
     * @param  string  $cookieName
339
     * @return $this
340
     */
341
    public function assertCookieMissing($cookieName)
342
    {
343
        Assert::assertNull(
1✔
344
            $this->getCookie($cookieName),
1✔
345
            "Cookie [{$cookieName}] is present on response."
1✔
346
        );
1✔
347

348
        return $this;
1✔
349
    }
350

351
    /**
352
     * Get the given cookie from the response.
353
     *
354
     * @param  string $cookieName
355
     *
356
     * @return SetCookie|null
357
     */
358
    public function getCookie($cookieName): ?SetCookie
359
    {
360
        return SetCookies::fromResponse($this->baseResponse)->get($cookieName);
2✔
361
    }
362

363
    /**
364
     * Assert that the given string is contained within the response.
365
     *
366
     * @param  string  $value
367
     * @return $this
368
     */
369
    public function assertSee($value)
370
    {
371
        Assert::assertStringContainsString((string) $value, (string)$this->getBody());
1✔
372

373
        return $this;
1✔
374
    }
375

376
    /**
377
     * Assert that the given string is contained within the response text.
378
     *
379
     * @param  string  $value
380
     * @return $this
381
     */
382
    public function assertSeeText($value)
383
    {
384
        Assert::assertStringContainsString((string) $value, strip_tags((string)$this->getBody()));
1✔
385

386
        return $this;
1✔
387
    }
388

389
    /**
390
     * Assert that the given string is not contained within the response.
391
     *
392
     * @param  string  $value
393
     * @return $this
394
     */
395
    public function assertDontSee($value)
396
    {
397
        Assert::assertStringNotContainsString((string) $value, (string)$this->getBody());
1✔
398

399
        return $this;
1✔
400
    }
401

402
    /**
403
     * Assert that the given string is not contained within the response text.
404
     *
405
     * @param  string  $value
406
     * @return $this
407
     */
408
    public function assertDontSeeText($value)
409
    {
410
        Assert::assertStringNotContainsString((string) $value, strip_tags((string)$this->getBody()));
1✔
411

412
        return $this;
1✔
413
    }
414

415
    /**
416
     * Assert that the response is a superset of the given JSON.
417
     *
418
     * @param  array  $data
419
     * @param  bool  $strict
420
     * @return $this
421
     */
422
    public function assertJson(array $data, bool $strict = true)
423
    {
424
        Assert::{$strict ? 'assertSame' : 'assertEquals'}(
5✔
425
            $data,
5✔
426
            array_intersect_key($this->json(), $data),
5✔
427
            $this->assertJsonMessage($data)
5✔
428
        );
5✔
429

430
        return $this;
5✔
431
    }
432

433
    /**
434
     * Get the assertion message for assertJson.
435
     *
436
     * @param  array  $data
437
     * @return string
438
     */
439
    protected function assertJsonMessage(array $data)
440
    {
441
        $expected = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
5✔
442

443
        $actual = json_encode($this->json(), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
5✔
444

445
        return 'Unable to find JSON: ' . PHP_EOL . PHP_EOL .
5✔
446
            "[{$expected}]" . PHP_EOL . PHP_EOL .
5✔
447
            'within response JSON:' . PHP_EOL . PHP_EOL .
5✔
448
            "[{$actual}]." . PHP_EOL . PHP_EOL;
5✔
449
    }
450

451
    /**
452
     * Assert that the expected value exists at the given path in the response.
453
     *
454
     * @param  string  $path
455
     * @param  mixed  $expect
456
     * @param  bool  $strict
457
     * @return $this
458
     */
459
    public function assertJsonPath(string $path, $expect, $strict = false)
460
    {
461
        if ($strict) {
1✔
462
            Assert::assertSame($expect, $this->json($path));
1✔
463
        } else {
464
            Assert::assertEquals($expect, $this->json($path));
1✔
465
        }
466

467
        return $this;
1✔
468
    }
469

470
    /**
471
     * Assert that the response has the exact given JSON.
472
     *
473
     * @param  array  $data
474
     * @return $this
475
     */
476
    public function assertExactJson(array $data)
477
    {
478
        Assert::assertEquals($data, (array) $this->json());
1✔
479

480
        return $this;
1✔
481
    }
482

483
    /**
484
     * Assert that the response does not contain the given JSON fragment.
485
     *
486
     * @param  array  $data
487
     * @param  bool   $exact
488
     * @return $this
489
     */
490
    public function assertJsonMissing(array $data, $exact = false)
491
    {
492
        if ($exact) {
1✔
493
            return $this->assertJsonMissingExact($data);
1✔
494
        }
495

496
        $actual = (string)$this->getBody();
1✔
497

498
        foreach ($data as $key => $value) {
1✔
499
            $unexpected = $this->jsonSearchStrings($key, $value);
1✔
500

501
            foreach ($unexpected as $value2) {
1✔
502
                Assert::assertStringNotContainsString(
1✔
503
                    $value2,
1✔
504
                    $actual,
1✔
505
                    'Found unexpected JSON fragment: ' . PHP_EOL . PHP_EOL .
1✔
506
                    '[' . json_encode([$key => $value]) . ']' . PHP_EOL . PHP_EOL .
1✔
507
                    'within' . PHP_EOL . PHP_EOL .
1✔
508
                    "[{$actual}]."
1✔
509
                );
1✔
510
            }
511
        }
512

513
        return $this;
1✔
514
    }
515

516

517
    /**
518
     * Assert that the response does not contain the exact JSON fragment.
519
     *
520
     * @param  array  $data
521
     * @return $this
522
     */
523
    public function assertJsonMissingExact(array $data)
524
    {
525
        $actual = (string)$this->getBody();
2✔
526

527
        foreach ($data as $key => $value) {
2✔
528
            $unexpected = $this->jsonSearchStrings($key, $value);
2✔
529

530
            $rs = array_filter($unexpected, function ($val) use ($actual) {
2✔
531
                return strpos($actual, $val) !== false;
2✔
532
            });
2✔
533
            if (count($rs) === 0) {
2✔
534
                Assert::assertEquals(0, count($rs));
2✔
535
                return $this;
2✔
536
            }
537
        }
538

539
        Assert::fail(
×
540
            'Found unexpected JSON fragment: ' . PHP_EOL . PHP_EOL .
×
541
            '[' . json_encode($data) . ']' . PHP_EOL . PHP_EOL .
×
542
            'within' . PHP_EOL . PHP_EOL .
×
543
            "[{$actual}]."
×
544
        );
×
545
    }
546

547
    /**
548
     * Get the strings we need to search for when examining the JSON.
549
     *
550
     * @param  string  $key
551
     * @param  string  $value
552
     * @return array
553
     */
554
    protected function jsonSearchStrings($key, $value)
555
    {
556
        $needle = substr(json_encode([$key => $value]), 1, -1);
2✔
557

558
        return [
2✔
559
            $needle . ']',
2✔
560
            $needle . '}',
2✔
561
            $needle . ',',
2✔
562
        ];
2✔
563
    }
564

565
    /**
566
     * Assert that the response has a given JSON structure.
567
     *
568
     * @param  array|null  $structure
569
     * @param  array|null  $responseData
570
     * @return $this
571
     */
572
    public function assertJsonStructure(array $structure = null, $responseData = null)
573
    {
574
        if (is_null($structure)) {
1✔
575
            return $this->assertExactJson($this->json());
×
576
        }
577

578
        if (is_null($responseData)) {
1✔
579
            $responseData = $this->json();
1✔
580
        }
581

582
        foreach ($structure as $key => $value) {
1✔
583
            if (is_array($value) && $key === '*') {
1✔
584
                Assert::assertIsArray($responseData);
1✔
585

586
                foreach ($responseData as $responseDataItem) {
1✔
587
                    $this->assertJsonStructure($structure['*'], $responseDataItem);
1✔
588
                }
589
            } elseif (is_array($value)) {
1✔
590
                Assert::assertArrayHasKey($key, $responseData);
×
591

592
                $this->assertJsonStructure($structure[$key], $responseData[$key]);
×
593
            } else {
594
                Assert::assertArrayHasKey($value, $responseData);
1✔
595
            }
596
        }
597

598
        return $this;
1✔
599
    }
600

601
    /**
602
     * Assert that the response JSON has the expected count of items at the given key.
603
     *
604
     * @param  int  $count
605
     * @param  string|null  $key
606
     * @return $this
607
     */
608
    public function assertJsonCount(int $count, $key = null)
609
    {
610
        if ($key) {
1✔
611
            Assert::assertCount(
1✔
612
                $count,
1✔
613
                self::arrayGet($this->json(), $key),
1✔
614
                "Failed to assert that the response count matched the expected {$count}"
1✔
615
            );
1✔
616

617
            return $this;
1✔
618
        }
619

620
        Assert::assertCount(
1✔
621
            $count,
1✔
622
            $this->json(),
1✔
623
            "Failed to assert that the response count matched the expected {$count}"
1✔
624
        );
1✔
625

626
        return $this;
1✔
627
    }
628

629

630
    /**
631
     * Validate and return the decoded response JSON.
632
     *
633
     * @param  string|null  $key
634
     * @return mixed
635
     */
636
    public function json($key = null)
637
    {
638
        $decodedResponse = json_decode((string)$this->getBody(), true);
10✔
639

640
        if (is_null($decodedResponse) || $decodedResponse === false) {
10✔
641
            Assert::fail('Invalid JSON was returned from the route.');
1✔
642
        }
643

644
        return $key ? self::arrayGet($decodedResponse, $key) : $decodedResponse;
10✔
645
    }
646

647

648
    /**
649
     * Handle dynamic calls into macros or pass missing methods to the base response.
650
     *
651
     * @param  string  $method
652
     * @param  array  $args
653
     * @return mixed
654
     */
655
    public function __call($method, $args)
656
    {
657
        return $this->baseResponse->{$method}(...$args);
33✔
658
    }
659

660
    private static function arrayGet($target, $key, $default = null)
661
    {
662
        if (is_null($key)) {
3✔
663
            return $target;
×
664
        }
665

666
        $key = is_array($key) ? $key : explode('.', $key);
3✔
667

668
        while (! is_null($segment = array_shift($key))) {
3✔
669
            if ($segment === '*') {
3✔
670
                $result = [];
2✔
671

672
                foreach ($target as $item) {
2✔
673
                    $result[] = self::arrayGet($item, $key);
2✔
674
                }
675

676
                return in_array('*', $key) ? array_merge([], ...$result) : $result;
2✔
677
            }
678

679
            if (is_array($target) && array_key_exists($segment, $target)) {
3✔
680
                $target = $target[$segment];
3✔
681
            } elseif (is_object($target) && isset($target->{$segment})) {
×
682
                $target = $target->{$segment};
×
683
            } else {
684
                return $default;
×
685
            }
686
        }
687

688
        return $target;
3✔
689
    }
690
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc