Completed
Push — master ( 47b9ab...741c62 )
by Thomas Mauro
01:54
created

StylesheetHandlerTest   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 214
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
dl 0
loc 214
c 0
b 0
f 0
wmc 8
lcom 1
cbo 4
rs 10
1
<?php
2
3
namespace Facile\ZFLinkHeadersModule\Listener;
4
5
use Facile\ZFLinkHeadersModule\OptionsInterface;
6
use PHPUnit\Framework\TestCase;
7
use Prophecy\Argument;
8
use Zend\Http\Header\GenericMultiHeader;
9
use Zend\Http\Headers;
10
use Zend\Http\PhpEnvironment;
11
use Zend\Http\Response;
12
use Zend\Mvc\MvcEvent;
13
use Zend\View\Helper\HeadLink;
14
use Zend\View\Helper\Placeholder\Container\AbstractContainer;
15
16
class StylesheetHandlerTest extends TestCase
17
{
18
    public function testInvokeWithAnotherResponse()
19
    {
20
        $headLink = $this->prophesize(HeadLink::class);
21
        $options = $this->prophesize(OptionsInterface::class);
22
        $event = $this->prophesize(MvcEvent::class);
23
        $response = $this->prophesize(Response::class);
24
25
        $headLink->getContainer()->shouldNotBeCalled();
26
        $response->getHeaders()->shouldNotBeCalled();
27
        $event->getResponse()->willReturn($response->reveal());
28
        $options->isStylesheetEnabled()->willReturn(true);
29
30
        $injector = new StylesheetHandler($headLink->reveal(), $options->reveal());
31
32
        $injector($event->reveal());
33
    }
34
35
    public function testInvokeWithDisabled()
36
    {
37
        $headLink = $this->prophesize(HeadLink::class);
38
        $options = $this->prophesize(OptionsInterface::class);
39
        $event = $this->prophesize(MvcEvent::class);
40
        $response = $this->prophesize(PhpEnvironment\Response::class);
41
42
        $headLink->getContainer()->shouldNotBeCalled();
43
        $response->getHeaders()->shouldNotBeCalled();
44
        $event->getResponse()->willReturn($response->reveal());
45
        $options->isStylesheetEnabled()->willReturn(false);
46
47
        $injector = new StylesheetHandler($headLink->reveal(), $options->reveal());
48
49
        $injector($event->reveal());
50
    }
51
52
    public function testInvokeWithNoPush()
53
    {
54
        $links = [
55
            $this->createStdClass([
56
                'href' => '/foo.css',
57
                'rel' => OptionsInterface::MODE_PRELOAD,
58
            ]),
59
            $this->createStdClass([
60
                'href' => '/bar.css',
61
                'rel' => 'stylesheet',
62
                'type' => 'text/style',
63
                'media' => '(min-width: 100px)',
64
            ]),
65
        ];
66
67
        $headLink = $this->prophesize(HeadLink::class);
68
        $options = $this->prophesize(OptionsInterface::class);
69
        $event = $this->prophesize(MvcEvent::class);
70
        $responseHeaders = $this->prophesize(Headers::class);
71
        $headContainer = $this->prophesize(AbstractContainer::class);
72
        $response = $this->prophesize(PhpEnvironment\Response::class);
73
74
        $options->getStylesheetMode()->willReturn('preload');
75
        $options->isHttp2PushEnabled()->willReturn(false);
76
        $options->isStylesheetEnabled()->willReturn(true);
77
78
        $headContainer->getIterator()->willReturn(new \ArrayIterator($links));
79
80
        $headLink->getContainer()->willReturn($headContainer->reveal());
81
        $response->getHeaders()->willReturn($responseHeaders->reveal());
82
        $event->getResponse()->willReturn($response->reveal());
83
84
        $responseHeaders->addHeader(Argument::allOf(
85
            Argument::type(GenericMultiHeader::class),
86
            Argument::which('getFieldName', 'Link'),
87
            Argument::which('getFieldValue', '</bar.css>; rel="preload"; as="style"; type="text/style"; media="(min-width: 100px)"; nopush')
88
        ))
89
            ->shouldBeCalled();
90
91
        $injector = new StylesheetHandler($headLink->reveal(), $options->reveal());
92
93
        $injector($event->reveal());
94
    }
95
96
    public function testInvokeWithPushAndPrefetch()
97
    {
98
        $links = [
99
            $this->createStdClass([
100
                'rel' => OptionsInterface::MODE_PRELOAD,
101
                'href' => '/foo.css',
102
            ]),
103
            $this->createStdClass([
104
                'rel' => 'stylesheet',
105
                'href' => '/bar.css',
106
                'type' => 'text/style',
107
                'media' => '(min-width: 100px)',
108
            ]),
109
        ];
110
111
        $headLink = $this->prophesize(HeadLink::class);
112
        $options = $this->prophesize(OptionsInterface::class);
113
        $event = $this->prophesize(MvcEvent::class);
114
        $responseHeaders = $this->prophesize(Headers::class);
115
        $headContainer = $this->prophesize(AbstractContainer::class);
116
        $response = $this->prophesize(PhpEnvironment\Response::class);
117
118
        $options->getStylesheetMode()->willReturn('prefetch');
119
        $options->isHttp2PushEnabled()->willReturn(true);
120
        $options->isStylesheetEnabled()->willReturn(true);
121
122
        $headContainer->getIterator()->willReturn(new \ArrayIterator($links));
123
124
        $headLink->getContainer()->willReturn($headContainer->reveal());
125
        $response->getHeaders()->willReturn($responseHeaders->reveal());
126
        $event->getResponse()->willReturn($response->reveal());
127
128
        $responseHeaders->addHeader(Argument::allOf(
129
            Argument::type(GenericMultiHeader::class),
130
            Argument::which('getFieldName', 'Link'),
131
            Argument::which('getFieldValue', '</bar.css>; rel="prefetch"; as="style"; type="text/style"; media="(min-width: 100px)"')
132
        ))
133
            ->shouldBeCalled();
134
135
        $injector = new StylesheetHandler($headLink->reveal(), $options->reveal());
136
137
        $injector($event->reveal());
138
    }
139
140
    public function testInvokeWithNoRelAttribute()
141
    {
142
        $links = [
143
            $this->createStdClass([
144
                'rel' => OptionsInterface::MODE_PRELOAD,
145
                'href' => '/foo.css',
146
            ]),
147
            $this->createStdClass([
148
                'href' => '/bar.css',
149
            ]),
150
        ];
151
152
        $headLink = $this->prophesize(HeadLink::class);
153
        $options = $this->prophesize(OptionsInterface::class);
154
        $event = $this->prophesize(MvcEvent::class);
155
        $responseHeaders = $this->prophesize(Headers::class);
156
        $headContainer = $this->prophesize(AbstractContainer::class);
157
        $response = $this->prophesize(PhpEnvironment\Response::class);
158
159
        $options->getStylesheetMode()->willReturn('preload');
160
        $options->isHttp2PushEnabled()->willReturn(true);
161
        $options->isStylesheetEnabled()->willReturn(true);
162
163
        $headContainer->getIterator()->willReturn(new \ArrayIterator($links));
164
165
        $headLink->getContainer()->willReturn($headContainer->reveal());
166
        $response->getHeaders()->willReturn($responseHeaders->reveal());
167
        $event->getResponse()->willReturn($response->reveal());
168
169
        $responseHeaders->addHeaderLine(Argument::any())->shouldNotBeCalled();
170
171
        $injector = new StylesheetHandler($headLink->reveal(), $options->reveal());
172
173
        $injector($event->reveal());
174
    }
175
176
    public function testInvokeWithNoHrefAttribute()
177
    {
178
        $links = [
179
            $this->createStdClass([
180
                'rel' => OptionsInterface::MODE_PRELOAD,
181
                'href' => '/foo.css',
182
            ]),
183
            $this->createStdClass([
184
                'rel' => OptionsInterface::MODE_PRELOAD,
185
            ]),
186
            $this->createStdClass([
187
                'rel' => 'stylesheet',
188
            ]),
189
        ];
190
191
        $headLink = $this->prophesize(HeadLink::class);
192
        $options = $this->prophesize(OptionsInterface::class);
193
        $event = $this->prophesize(MvcEvent::class);
194
        $responseHeaders = $this->prophesize(Headers::class);
195
        $headContainer = $this->prophesize(AbstractContainer::class);
196
        $response = $this->prophesize(PhpEnvironment\Response::class);
197
198
        $options->getStylesheetMode()->willReturn('preload');
199
        $options->isHttp2PushEnabled()->willReturn(true);
200
        $options->isStylesheetEnabled()->willReturn(true);
201
202
        $headContainer->getIterator()->willReturn(new \ArrayIterator($links));
203
204
        $headLink->getContainer()->willReturn($headContainer->reveal());
205
        $response->getHeaders()->willReturn($responseHeaders->reveal());
206
        $event->getResponse()->willReturn($response->reveal());
207
208
        $responseHeaders->addHeaderLine(Argument::any())->shouldNotBeCalled();
209
210
        $injector = new StylesheetHandler($headLink->reveal(), $options->reveal());
211
212
        $injector($event->reveal());
213
    }
214
215
    /**
216
     * @param array $properties
217
     * @return \stdClass
218
     */
219
    private function createStdClass(array $properties): \stdClass
220
    {
221
        $item = new \stdClass();
222
223
        foreach ($properties as $name => $value) {
224
            $item->{$name} = $value;
225
        }
226
227
        return $item;
228
    }
229
}
230