Completed
Push — master ( b716f1...2f9340 )
by Kamil
18:43
created

Page::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 8
rs 9.4285
c 1
b 0
f 0
cc 1
eloc 5
nc 1
nop 3
1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Sylius\Behat\PageObjectExtension\PageObject;
13
14
use Behat\Mink\Driver\DriverInterface;
15
use Behat\Mink\Element\DocumentElement;
16
use Behat\Mink\Exception\DriverException;
17
use Behat\Mink\Session;
18
use SensioLabs\Behat\PageObjectExtension\PageObject\Element;
19
use SensioLabs\Behat\PageObjectExtension\PageObject\Exception\ElementNotFoundException;
20
use SensioLabs\Behat\PageObjectExtension\PageObject\Exception\UnexpectedPageException;
21
use SensioLabs\Behat\PageObjectExtension\PageObject\Factory;
22
use SensioLabs\Behat\PageObjectExtension\PageObject\PageObject;
23
24
/**
25
 * @author Kamil Kokot <[email protected]>
26
 */
27
abstract class Page implements PageObject
28
{
29
    /**
30
     * @var array
31
     */
32
    protected $elements = [];
33
34
    /**
35
     * @var Session
36
     */
37
    private $session;
38
39
    /**
40
     * @var Factory
41
     */
42
    private $factory;
43
44
    /**
45
     * @var array
46
     */
47
    private $parameters;
48
49
    /**
50
     * @var DocumentElement
51
     */
52
    private $document;
53
54
    /**
55
     * @param Session $session
56
     * @param Factory $factory
57
     * @param array $parameters
58
     */
59
    public function __construct(Session $session, Factory $factory, array $parameters = [])
60
    {
61
        $this->session = $session;
62
        $this->factory = $factory;
63
        $this->parameters = $parameters;
64
65
        $this->document = new DocumentElement($session);
66
    }
67
68
    /**
69
     * @param array $urlParameters
70
     *
71
     * @return Page
72
     */
73
    public function open(array $urlParameters = [])
74
    {
75
        $url = $this->getUrl($urlParameters);
76
77
        $this->getDriver()->visit($url);
78
79
        $this->verify($urlParameters);
80
81
        return $this;
82
    }
83
84
    /**
85
     * @param array $urlParameters
86
     */
87
    public function verify(array $urlParameters)
88
    {
89
        $this->verifyResponse();
90
        $this->verifyUrl($urlParameters);
91
        $this->verifyPage();
92
    }
93
94
    /**
95
     * @param array $urlParameters
96
     *
97
     * @return bool
98
     */
99
    public function isOpen(array $urlParameters = [])
100
    {
101
        try {
102
            $this->verify($urlParameters);
103
        } catch (\Exception $e) {
104
            return false;
105
        }
106
107
        return true;
108
    }
109
110
    /**
111
     * @return string
112
     */
113
    abstract protected function getPath();
114
115
    /**
116
     * @return string
117
     */
118
    protected function getName()
119
    {
120
        return preg_replace('/^.*\\\(.*?)$/', '$1', get_called_class());
121
    }
122
123
    /**
124
     * @param array $urlParameters
125
     *
126
     * @return string
127
     */
128
    protected function getUrl(array $urlParameters = [])
129
    {
130
        return $this->makeSurePathIsAbsolute($this->unmaskUrl($urlParameters));
131
    }
132
133
    /**
134
     * @throws UnexpectedPageException
135
     */
136
    protected function verifyResponse()
137
    {
138
        try {
139
            $statusCode = $this->getDriver()->getStatusCode();
140
141
            if ($this->isErrorResponse($statusCode)) {
142
                $currentUrl = $this->getDriver()->getCurrentUrl();
143
                $message = sprintf('Could not open the page: "%s". Received an error status code: %s', $currentUrl, $statusCode);
144
145
                throw new UnexpectedPageException($message);
146
            }
147
        } catch (DriverException $exception) {
148
            // ignore drivers which cannot check the response status code
149
        }
150
    }
151
152
    /**
153
     * Overload to verify if the current url matches the expected one. Throw an exception otherwise.
154
     *
155
     * @param array $urlParameters
156
     */
157
    protected function verifyUrl(array $urlParameters = [])
158
    {
159
        if ($this->getDriver()->getCurrentUrl() !== $this->getUrl($urlParameters)) {
160
            throw new UnexpectedPageException(sprintf('Expected to be on "%s" but found "%s" instead', $this->getUrl($urlParameters), $this->getDriver()->getCurrentUrl()));
161
        }
162
    }
163
164
    /**
165
     * Overload to verify if we're on an expected page. Throw an exception otherwise.
166
     */
167
    protected function verifyPage()
168
    {
169
    }
170
171
    /**
172
     * @param int $statusCode
173
     *
174
     * @return bool
175
     */
176
    protected function isErrorResponse($statusCode)
177
    {
178
        return 400 <= $statusCode && $statusCode < 600;
179
    }
180
181
    /**
182
     * @param string $name
183
     *
184
     * @return string|null
185
     */
186
    protected function getParameter($name)
187
    {
188
        return isset($this->parameters[$name]) ? $this->parameters[$name] : null;
189
    }
190
191
    /**
192
     * @param string $name
193
     *
194
     * @return Element
195
     */
196
    public function getElement($name)
197
    {
198
        $element = $this->createElement($name);
199
200
        if (!$this->getDocument()->has('xpath', $element->getXpath())) {
201
            throw new ElementNotFoundException(sprintf('"%s" element is not present on the page', $name));
202
        }
203
204
        return $element;
205
    }
206
207
    /**
208
     * @param string $name
209
     *
210
     * @return bool
211
     */
212
    protected function hasElement($name)
213
    {
214
        return $this->getDocument()->has('xpath', $this->createElement($name)->getXpath());
215
    }
216
217
    /**
218
     * @param string $name
219
     *
220
     * @return Element
221
     */
222
    protected function createElement($name)
223
    {
224
        if (isset($this->elements[$name])) {
225
            return $this->factory->createInlineElement($this->elements[$name]);
226
        }
227
228
        return $this->factory->createElement($name);
229
    }
230
231
    /**
232
     * @return Session
233
     */
234
    protected function getSession()
235
    {
236
        return $this->session;
237
    }
238
239
    /**
240
     * @return DriverInterface
241
     */
242
    protected function getDriver()
243
    {
244
        return $this->session->getDriver();
245
    }
246
247
    /**
248
     * @return DocumentElement
249
     */
250
    protected function getDocument()
251
    {
252
        return $this->document;
253
    }
254
255
    /**
256
     * @param string $path
257
     *
258
     * @return string
259
     */
260
    private function makeSurePathIsAbsolute($path)
261
    {
262
        $baseUrl = rtrim($this->getParameter('base_url'), '/').'/';
263
264
        return 0 !== strpos($path, 'http') ? $baseUrl.ltrim($path, '/') : $path;
265
    }
266
267
    /**
268
     * @param array $urlParameters
269
     *
270
     * @return string
271
     */
272
    private function unmaskUrl(array $urlParameters)
273
    {
274
        $url = $this->getPath();
275
276
        foreach ($urlParameters as $parameter => $value) {
277
            $url = str_replace(sprintf('{%s}', $parameter), $value, $url);
278
        }
279
280
        return $url;
281
    }
282
}
283