Completed
Pull Request — behat-2.x (#43)
by Timothée
02:50
created

XmlContext::getSimpleXml()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 2
Metric Value
dl 0
loc 4
rs 10
c 2
b 0
f 2
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace Rezzza\RestApiBehatExtension\Xml;
4
5
use Behat\Behat\Context\BehatContext;
6
use Behat\Gherkin\Node\PyStringNode;
7
use Rezzza\RestApiBehatExtension\Response\ResponseStorage;
8
use Rezzza\RestApiBehatExtension\Response\ResponseStorageAware;
9
use mageekguy\atoum\asserter\generator as asserter;
10
11
class XmlContext extends BehatContext implements ResponseStorageAware
12
{
13
    private $asserter;
14
15
    private $xmlStorage;
16
17
    public function __construct(asserter $asserter)
18
    {
19
        $this->asserter = $asserter;
20
    }
21
22
    public function setResponseStorage(ResponseStorage $responseStorage)
23
    {
24
        $this->xmlStorage = new XmlStorage($responseStorage);
25
    }
26
27
    /**
28
     * @When /^I load XML:$/
29
     */
30
    public function iLoadXml(PyStringNode $jsonContent)
31
    {
32
        $this->xmlStorage->writeRawContent($jsonContent);
33
    }
34
35
    /**
36
     * Checks that the response is correct XML
37
     *
38
     * @Then /^the response should be in XML$/
39
     */
40
    public function theResponseShouldBeInXml()
41
    {
42
        $this->xmlStorage->readXml(true);
43
    }
44
45
    /**
46
     * Checks that the response is not correct XML
47
     *
48
     * @Then /^the response should not be in XML$/
49
     */
50
    public function theResponseShouldNotBeInXml()
51
    {
52
        try {
53
            $this->xmlStorage->readXml(true);
54
        } catch (\Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
55
        }
56
57
        if (!isset($e)) {
58
            throw new \Exception("The response is in XML");
59
        }
60
    }
61
62
    /**
63
     * Checks that the specified XML element exists
64
     *
65
     * @param string $element
66
     * @throws \Exception
67
     * @return \DomNodeList
68
     *
69
     * @Then /^the XML element "(?P<element>[^"]*)" should exists?$/
70
     */
71 View Code Duplication
    public function theXmlElementShouldExist($element)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
72
    {
73
        $elements = $this->xpath($element);
74
        if ($elements->length == 0) {
75
            throw new \Exception(sprintf("The element '%s' does not exist.", $element));
76
        }
77
        return $elements;
78
    }
79
80
    /**
81
     * Checks that the specified XML element does not exist
82
     *
83
     * @Then /^the XML element "(?P<element>[^"]*)" should not exists?$/
84
     */
85 View Code Duplication
    public function theXmlElementShouldNotExist($element)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
86
    {
87
        $elements = $this->xpath($element);
88
        if ($elements->length != 0) {
89
            throw new \Exception(sprintf("The element '%s' exists.", $element));
90
        }
91
    }
92
93
    /**
94
     * @Then /^the XML response should be equal to:$/
95
     */
96
    public function theResponseXmlShouldBeEqualTo(PyStringNode $expected)
97
    {
98
        $expected = new Xml(str_replace('\\"', '"', $expected));
99
        $actual   = $this->xmlStorage->readXml(false);
100
101
        if (false === $actual->isEqual($expected)) {
102
            throw new \Exception(sprintf(
103
                'The string "%s" is not equal to the response of the current page: %s',
104
                $expected->read(),
105
                $actual->read()
106
            ));
107
        }
108
    }
109
110
    /**
111
     * Checks that the specified XML element is equal to the given value
112
     *
113
     * @Then /^the XML element "(?P<element>(?:[^"]|\\")*)" should be equal to "(?P<text>[^"]*)"$/
114
     */
115 View Code Duplication
    public function theXmlElementShouldBeEqualTo($element, $text)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
116
    {
117
        $elements = $this->theXmlElementShouldExist($element);
118
        $actual = $elements->item(0)->nodeValue;
119
        if ($text != $actual) {
120
            throw new \Exception(sprintf("The element value is `%s`", $actual));
121
        }
122
    }
123
124
    /**
125
     * Checks that the specified XML element is not equal to the given value
126
     *
127
     * @Then /^the XML element "(?P<element>(?:[^"]|\\")*)" should not be equal to "(?P<text>[^"]*)"$/
128
     */
129 View Code Duplication
    public function theXmlElementShouldNotBeEqualTo($element, $text)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
130
    {
131
        $elements = $this->theXmlElementShouldExist($element);
132
        $actual = $elements->item(0)->nodeValue;
133
        if ($text == $actual) {
134
            throw new \Exception(sprintf("The element value is `%s`", $actual));
135
        }
136
    }
137
138
    /**
139
     * Checks that the XML attribute on the specified element exists
140
     *
141
     * @Then /^the XML attribute "(?P<attribute>[^"]*)" on element "(?P<element>(?:[^"]|\\")*)" should exists?$/
142
     */
143 View Code Duplication
    public function theXmlAttributeShouldExist($attribute, $element)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
144
    {
145
        $elements = $this->theXmlElementShouldExist("{$element}[@{$attribute}]");
146
        $actual = $elements->item(0)->getAttribute($attribute);
147
        if (empty($actual)) {
148
            throw new \Exception(sprintf("The attribute value is `%s`", $actual));
149
        }
150
        return $actual;
151
    }
152
153
    /**
154
     * Checks that the XML attribute on the specified element does not exist
155
     *
156
     * @Then /^the XML attribute "(?P<attribute>[^"]*)" on element "(?P<element>(?:[^"]|\\")*)" should not exists?$/
157
     */
158 View Code Duplication
    public function theXmlAttributeShouldNotExist($attribute, $element)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
159
    {
160
        try {
161
            $elements = $this->theXmlElementShouldExist("{$element}[@{$attribute}]");
162
            $actual = $elements->item(0)->getAttribute($attribute);
163
            if (!empty($actual)) {
164
                throw new \Exception(sprintf("The element '%s' exists and contains '%s'.", $element , $elements));
165
            }
166
        }
167
        catch (\Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
168
        }
169
    }
170
171
    /**
172
     * Checks that the XML attribute on the specified element is equal to the given value
173
     *
174
     * @Then /^the XML attribute "(?P<attribute>[^"]*)" on element "(?P<element>(?:[^"]|\\")*)" should be equal to "(?P<text>[^"]*)"$/
175
     */
176 View Code Duplication
    public function theXmlAttributeShouldBeEqualTo($attribute, $element, $text)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
177
    {
178
        $actual = $this->theXmlAttributeShouldExist($attribute, $element);
179
        if ($text != $actual) {
180
            throw new \Exception(sprintf("The attribute value is `%s`", $actual));
181
        }
182
    }
183
184
    /**
185
     * Checks that the XML attribute on the specified element is not equal to the given value
186
     *
187
     * @Then /^the XML attribute "(?P<attribute>[^"]*)" on element "(?P<element>(?:[^"]|\\")*)" should not be equal to "(?P<text>[^"]*)"$/
188
     */
189 View Code Duplication
    public function theXmlAttributeShouldNotBeEqualTo($attribute, $element, $text)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
190
    {
191
        $actual = $this->theXmlAttributeShouldExist($attribute, $element);
192
        if ($text === $actual) {
193
            throw new \Exception(sprintf("The attribute value is `%s`", $actual));
194
        }
195
    }
196
197
    /**
198
     * Checks that the given XML element has N child element(s)
199
     *
200
     * @Then /^the XML element "(?P<element>[^"]*)" should have (?P<nth>\d+) elements?$/
201
     */
202
203
    public function theXmlElementShouldHaveNChildElements($element, $nth)
204
    {
205
        $elements = $this->theXmlElementShouldExist($element);
206
        $length = 0;
207
        foreach ($elements->item(0)->childNodes as $node) {
208
            if ($node->hasAttributes() || (trim($node->nodeValue) != '')) {
209
                ++$length;
210
            }
211
        }
212
213
        $this->asserter
214
            ->integer((int) $nth)
215
            ->isEqualTo($length);
216
    }
217
218
    /**
219
     * Checks that the given XML element contains the given value
220
     *
221
     * @Then /^the XML element "(?P<element>[^"]*)" should contain "(?P<text>[^"]*)"$/
222
     */
223
    public function theXmlElementShouldContain($element, $text)
224
    {
225
        $elements = $this->theXmlElementShouldExist($element);
226
227
        $this->asserter
228
            ->phpString($elements->item(0)->nodeValue)
229
            ->contains($text);
230
    }
231
232
    /**
233
     * Checks that the given XML element does not contain the given value
234
     *
235
     * @Then /^the XML element "(?P<element>[^"]*)" should not contain "(?P<text>[^"]*)"$/
236
     */
237
    public function theXmlElementShouldNotContain($element, $text)
238
    {
239
        $elements = $this->theXmlElementShouldExist($element);
240
241
        $this->asserter
242
            ->phpString($elements->item(0)->nodeValue)
243
            ->notContains($text);
244
    }
245
246
    /**
247
     * Checks that the XML uses the specified namespace
248
     *
249
     * @Then /^[Tt]he XML should use the namespace "(?P<namespace>[^"]*)"$/
250
     */
251 View Code Duplication
    public function theXmlShouldUseTheNamespace($namespace)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
252
    {
253
        $namespaces = $this->getNamespaces();
254
        if (!in_array($namespace, $namespaces)) {
255
            throw new \Exception(sprintf("The namespace '%s' is not used", $namespace));
256
        }
257
    }
258
259
    /**
260
     * Checks that the XML does not use the specified namespace
261
     *
262
     * @Then /^[Tt]he XML should not use the namespace "(?P<namespace>[^"]*)"$/
263
     */
264 View Code Duplication
    public function theXmlShouldNotUseTheNamespace($namespace)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
265
    {
266
        $namespaces = $this->getNamespaces();
267
        if (in_array($namespace, $namespaces)) {
268
            throw new \Exception(sprintf("The namespace '%s' is used", $namespace));
269
        }
270
    }
271
272
    /**
273
     * Optimistically (ignoring errors) attempt to pretty-print the last XML response
274
     *
275
     * @Then /^print last XML response$/
276
     */
277
    public function printLastXmlResponse()
278
    {
279
        $xml = $this->xmlStorage->readXml(false);
280
        $this->printDebug($xml->pretty());
281
    }
282
283
    /**
284
     * @param string $element
285
     * @return \DomNodeList
286
     */
287
    public function xpath($element)
288
    {
289
        $elements = $this->xmlStorage->readXml(false)->xpath($element);
290
291
        return ($elements === false) ? new \DOMNodeList() : $elements;
292
    }
293
294
    /**
295
     * @return array
296
     */
297
    private function getNamespaces()
298
    {
299
        return $this->xmlStorage->readXml(false)->getNamespaces();
300
    }
301
302
    /**
303
     * @BeforeScenario
304
     */
305
    public function beforeScenario()
306
    {
307
        libxml_clear_errors();
308
        libxml_use_internal_errors(true);
309
    }
310
}
311