Completed
Push — master ( 299de3...93b43e )
by Alexander
02:01
created

SapiEmitterTest::setUp()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
namespace Yiisoft\Yii\Web\Tests\Emitter;
3
4
include 'httpFunctionMocks.php';
5
6
use Nyholm\Psr7\Response;
7
use PHPUnit\Framework\TestCase;
8
use Psr\Http\Message\ResponseInterface;
9
use Psr\Http\Message\StreamInterface;
10
use Yiisoft\Yii\Web\Emitter\EmitterInterface;
11
use Yiisoft\Yii\Web\Emitter\SapiEmitter;
12
13
/**
14
 * @runTestsInSeparateProcesses
15
 */
16
class SapiEmitterTest extends TestCase
17
{
18
    public function setUp(): void
19
    {
20
        HTTPFunctions::reset();
21
    }
22
23
    public static function tearDownAfterClass(): void
24
    {
25
        HTTPFunctions::reset();
26
    }
27
28
    public function noBodyHTTPCodeProvider(): array
29
    {
30
        return [[100], [101], [102], [204], [205], [304]];
31
    }
32
33
    public function testEmit(): void
34
    {
35
        $body = 'Example body';
36
        $response = $this->createResponse(200, ['X-Test' => 1], $body);
37
38
        $this->createEmitter()->emit($response);
39
40
        $this->assertEquals(200, $this->getResponseCode());
41
        $this->assertCount(2, $this->getHeaders());
42
        $this->assertContains('X-Test: 1', $this->getHeaders());
43
        $this->assertContains('Content-Length: ' . strlen($body), $this->getHeaders());
44
        $this->expectOutputString($body);
45
    }
46
47
    /**
48
     * @test
49
     * @dataProvider noBodyHTTPCodeProvider
50
     */
51
    public function shouldNotOutputBodyByResponseCode(int $code): void
52
    {
53
        $response = $this->createResponse($code, ['X-Test' => 1], 'Example body');
54
55
        $this->createEmitter()->emit($response);
56
57
        $this->assertEquals($code, $this->getResponseCode());
58
        $this->assertTrue(HTTPFunctions::hasHeader('X-Test'));
59
        $this->assertFalse(HTTPFunctions::hasHeader('Content-Length'));
60
        $this->expectOutputString('');
61
    }
62
63
    /**
64
     * @test
65
     */
66
    public function shouldNotOutputBodyAndContentLengthIfEmitToldSo(): void
67
    {
68
        $response = $this->createResponse(200, ['X-Test' => 1], 'Example body');
69
70
        $this->createEmitter()->emit($response, true);
71
72
        $this->assertEquals(200, $this->getResponseCode());
73
        $this->assertTrue(HTTPFunctions::hasHeader('X-Test'));
74
        $this->assertFalse(HTTPFunctions::hasHeader('Content-Length'));
75
        $this->expectOutputString('');
76
    }
77
78
    /**
79
     * @test
80
     */
81
    public function contentLengthShouldNotBeOverwrittenIfPresent(): void
82
    {
83
        $length = 100;
84
        $response = $this->createResponse(200, ['Content-Length' => $length, 'X-Test' => 1], 'Example body');
85
86
        $this->createEmitter()->emit($response);
87
88
        $this->assertEquals(200, $this->getResponseCode());
89
        $this->assertCount(2, $this->getHeaders());
90
        $this->assertContains('X-Test: 1', $this->getHeaders());
91
        $this->assertContains('Content-Length: ' . $length, $this->getHeaders());
92
        $this->expectOutputString('Example body');
93
    }
94
95
    /**
96
     * @test
97
     */
98
    public function contentLengthShouldNotOutputWhenBodyIsEmpty(): void
99
    {
100
        $length = 100;
101
        $response = $this->createResponse(200, ['Content-Length' => $length, 'X-Test' => 1], '');
102
103
        $this->createEmitter()->emit($response);
104
105
        $this->assertEquals(200, $this->getResponseCode());
106
        $this->assertEquals(['X-Test: 1'], $this->getHeaders());
107
        $this->expectOutputString('');
108
    }
109
110
    /**
111
     * @test
112
     */
113
    public function contentAlwaysShouldBeFullyEmitted(): void
114
    {
115
        $body = 'Example body';
116
        $response = $this->createResponse(200, ['Content-length' => 1, 'X-Test' => 1], $body);
117
118
        $this->createEmitter()->emit($response);
119
120
        $this->expectOutputString($body);
121
    }
122
123
    /**
124
     * @test
125
     */
126
    public function sentHeadersShouldBeRemoved(): void
127
    {
128
        HTTPFunctions::header('Cookie-Set: First Cookie');
129
        HTTPFunctions::header('X-Test: 1');
130
        $body = 'Example body';
131
        $response = $this->createResponse(200, [], $body);
132
133
        $this->createEmitter()->emit($response);
134
135
        $this->assertEquals(['Content-Length: ' . strlen($body)], $this->getHeaders());
136
        $this->expectOutputString($body);
137
    }
138
139
    /**
140
     * @test
141
     */
142
    public function shouldEmitDuplicateHeaders(): void
143
    {
144
        $body = 'Example body';
145
        $response = $this->createResponse(200, [], $body)
146
                         ->withHeader('X-Test', '1')
147
                         ->withAddedHeader('X-Test', '2')
148
                         ->withAddedHeader('X-Test', '3; 3.5')
149
                         ->withHeader('Cookie-Set', '1')
150
                         ->withAddedHeader('cookie-Set', '2')
151
                         ->withAddedHeader('Cookie-set', '3');
152
153
        $this->createEmitter()->emit($response);
154
        $this->assertEquals(200, $this->getResponseCode());
155
        $this->assertContains('X-Test: 1', $this->getHeaders());
156
        $this->assertContains('X-Test: 2', $this->getHeaders());
157
        $this->assertContains('X-Test: 3; 3.5', $this->getHeaders());
158
        $this->assertContains('Cookie-Set: 1', $this->getHeaders());
159
        $this->assertContains('Cookie-Set: 2', $this->getHeaders());
160
        $this->assertContains('Cookie-Set: 3', $this->getHeaders());
161
        $this->assertContains('Content-Length: ' . strlen($body), $this->getHeaders());
162
        $this->expectOutputString($body);
163
    }
164
165
    private function createEmitter(?int $bufferSize = null): EmitterInterface
166
    {
167
        return new SapiEmitter($bufferSize);
168
    }
169
170
    private function createResponse(
171
        int $status = 200,
172
        array $headers = [],
173
        $body = null,
174
        string $version = '1.1'
175
    ): ResponseInterface {
176
        $response = (new Response())
177
            ->withStatus($status)
178
            ->withProtocolVersion($version);
179
        foreach ($headers as $header => $value) {
180
            $response = $response->withHeader($header, $value);
181
        }
182
        if ($body instanceof StreamInterface) {
183
            $response = $response->withBody($body);
184
        } elseif (is_string($body)) {
185
            $response->getBody()->write($body);
186
        }
187
        return $response;
188
    }
189
190
    private function getHeaders(): array
191
    {
192
        return HTTPFunctions::headers_list();
193
    }
194
195
    private function getResponseCode(): int
196
    {
197
        return HTTPFunctions::http_response_code();
198
    }
199
}
200