Completed
Push — master ( 01e9a3...b0156c )
by Kamil
18:54
created

Page::unmaskUrl()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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