Completed
Push — master ( 21eeea...bc883e )
by Sébastien
13s
created

theJsonArrayNodeShouldContainElements()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 7
Ratio 100 %

Importance

Changes 0
Metric Value
dl 7
loc 7
rs 9.4285
c 0
b 0
f 0
nc 1
cc 1
eloc 4
nop 2
1
<?php
2
3
namespace Rezzza\RestApiBehatExtension\Json;
4
5
use mageekguy\atoum\asserter\generator as asserter;
6
use Behat\Behat\Context\Context;
7
use Behat\Behat\Context\SnippetAcceptingContext;
8
use Behat\Gherkin\Node\PyStringNode;
9
10
class JsonContext implements Context, SnippetAcceptingContext
0 ignored issues
show
Deprecated Code introduced by
The interface Behat\Behat\Context\SnippetAcceptingContext has been deprecated with message: will be removed in 4.0. Use --snippets-for CLI option instead

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
11
{
12
    private $jsonInspector;
13
14
    private $asserter;
15
16
    private $jsonSchemaBaseUrl;
17
18
    public function __construct(JsonInspector $jsonInspector, $jsonSchemaBaseUrl = null)
19
    {
20
        $this->jsonInspector = $jsonInspector;
21
        $this->asserter = new asserter;
22
        $this->jsonSchemaBaseUrl = rtrim($jsonSchemaBaseUrl, '/');
23
    }
24
25
    /**
26
     * @When /^I load JSON:$/
27
     */
28
    public function iLoadJson(PyStringNode $jsonContent)
29
    {
30
        $this->jsonInspector->writeJson((string) $jsonContent);
31
    }
32
33
    /**
34
     * @Then /^the response should be in JSON$/
35
     */
36
    public function responseShouldBeInJson()
37
    {
38
        $this->jsonInspector->readJson();
39
    }
40
41
    /**
42
     * @Then /^the JSON node "(?P<jsonNode>[^"]*)" should be equal to "(?P<expectedValue>.*)"$/
43
     */
44
    public function theJsonNodeShouldBeEqualTo($jsonNode, $expectedValue)
45
    {
46
        $this->assert(function () use ($jsonNode, $expectedValue) {
47
            $realValue = $this->evaluateJsonNodeValue($jsonNode);
48
            $expectedValue = $this->evaluateExpectedValue($expectedValue);
0 ignored issues
show
Bug introduced by
Consider using a different name than the imported variable $expectedValue, or did you forget to import by reference?

It seems like you are assigning to a variable which was imported through a use statement which was not imported by reference.

For clarity, we suggest to use a different name or import by reference depending on whether you would like to have the change visibile in outer-scope.

Change not visible in outer-scope

$x = 1;
$callable = function() use ($x) {
    $x = 2; // Not visible in outer scope. If you would like this, how
            // about using a different variable name than $x?
};

$callable();
var_dump($x); // integer(1)

Change visible in outer-scope

$x = 1;
$callable = function() use (&$x) {
    $x = 2;
};

$callable();
var_dump($x); // integer(2)
Loading history...
49
            $this->asserter->variable($realValue)->isEqualTo($expectedValue);
50
        });
51
    }
52
53
    /**
54
     * @Then /^the JSON node "(?P<jsonNode>[^"]*)" should have (?P<expectedNth>\d+) elements?$/
55
     * @Then /^the JSON array node "(?P<jsonNode>[^"]*)" should have (?P<expectedNth>\d+) elements?$/
56
     */
57
    public function theJsonNodeShouldHaveElements($jsonNode, $expectedNth)
58
    {
59
        $this->assert(function () use ($jsonNode, $expectedNth) {
60
            $realValue = $this->evaluateJsonNodeValue($jsonNode);
61
            $this->asserter->phpArray($realValue)->hasSize($expectedNth);
62
        });
63
    }
64
65
    /**
66
     * @Then /^the JSON array node "(?P<jsonNode>[^"]*)" should contain "(?P<expectedValue>.*)" element$/
67
     */
68 View Code Duplication
    public function theJsonArrayNodeShouldContainElements($jsonNode, $expectedValue)
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...
69
    {
70
        $this->assert(function () use ($jsonNode, $expectedValue) {
71
            $realValue = $this->evaluateJsonNodeValue($jsonNode);
72
            $this->asserter->phpArray($realValue)->contains($expectedValue);
73
        });
74
    }
75
76
    /**
77
     * @Then /^the JSON array node "(?P<jsonNode>[^"]*)" should not contain "(?P<expectedValue>.*)" element$/
78
     */
79
    public function theJsonArrayNodeShouldNotContainElements($jsonNode, $expectedValue)
80
    {
81
        $this->assert(function () use ($jsonNode, $expectedValue) {
82
            $realValue = $this->evaluateJsonNodeValue($jsonNode);
83
            $this->asserter->phpArray($realValue)->notContains($expectedValue);
84
        });
85
    }
86
87
    /**
88
     * @Then /^the JSON node "(?P<jsonNode>[^"]*)" should contain "(?P<expectedValue>.*)"$/
89
     */
90 View Code Duplication
    public function theJsonNodeShouldContain($jsonNode, $expectedValue)
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...
91
    {
92
        $this->assert(function () use ($jsonNode, $expectedValue) {
93
            $realValue = $this->evaluateJsonNodeValue($jsonNode);
94
            $this->asserter->string((string) $realValue)->contains($expectedValue);
95
        });
96
    }
97
98
    /**
99
     * Checks, that given JSON node does not contain given value
100
     *
101
     * @Then /^the JSON node "(?P<jsonNode>[^"]*)" should not contain "(?P<unexpectedValue>.*)"$/
102
     */
103 View Code Duplication
    public function theJsonNodeShouldNotContain($jsonNode, $unexpectedValue)
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...
104
    {
105
        $this->assert(function () use ($jsonNode, $unexpectedValue) {
106
            $realValue = $this->evaluateJsonNodeValue($jsonNode);
107
            $this->asserter->string((string) $realValue)->notContains($unexpectedValue);
108
        });
109
    }
110
111
    /**
112
     * Checks, that given JSON node exist
113
     *
114
     * @Given /^the JSON node "(?P<jsonNode>[^"]*)" should exist$/
115
     */
116
    public function theJsonNodeShouldExist($jsonNode)
117
    {
118
        try {
119
            $this->evaluateJsonNodeValue($jsonNode);
120
        } catch (\Exception $e) {
121
            throw new WrongJsonExpectation(sprintf("The node '%s' does not exist.", $jsonNode), $this->readJson(), $e);
122
        }
123
    }
124
125
    /**
126
     * Checks, that given JSON node does not exist
127
     *
128
     * @Given /^the JSON node "(?P<jsonNode>[^"]*)" should not exist$/
129
     */
130
    public function theJsonNodeShouldNotExist($jsonNode)
131
    {
132
        $e = null;
133
134
        try {
135
            $realValue = $this->evaluateJsonNodeValue($jsonNode);
136
        } catch (\Exception $e) {
137
            // If the node does not exist an exception should be throwed
138
        }
139
140
        if ($e === null) {
141
            throw new WrongJsonExpectation(
142
                sprintf("The node '%s' exists and contains '%s'.", $jsonNode, json_encode($realValue)),
143
                $this->readJson(),
144
                $e
145
            );
146
        }
147
    }
148
149
    /**
150
     * @Then /^the JSON should be valid according to this schema:$/
151
     */
152
    public function theJsonShouldBeValidAccordingToThisSchema(PyStringNode $jsonSchemaContent)
153
    {
154
        $tempFilename = tempnam(sys_get_temp_dir(), 'rae');
155
        file_put_contents($tempFilename, $jsonSchemaContent);
156
        $this->assert(function () use ($tempFilename) {
157
            $this->jsonInspector->validateJson(
158
                new JsonSchema($tempFilename)
159
            );
160
        });
161
        unlink($tempFilename);
162
    }
163
164
    /**
165
     * @Then /^the JSON should be valid according to the schema "(?P<filename>[^"]*)"$/
166
     */
167
    public function theJsonShouldBeValidAccordingToTheSchema($filename)
168
    {
169
        $filename = $this->resolveFilename($filename);
170
171
        $this->assert(function () use ($filename) {
172
            $this->jsonInspector->validateJson(
173
                new JsonSchema($filename)
174
            );
175
        });
176
    }
177
178
    /**
179
     * @Then /^the JSON should be equal to:$/
180
     */
181
    public function theJsonShouldBeEqualTo(PyStringNode $jsonContent)
182
    {
183
        $realJsonValue = $this->readJson();
184
185
        try {
186
            $expectedJsonValue = new Json($jsonContent);
187
        } catch (\Exception $e) {
188
            throw new \Exception('The expected JSON is not a valid');
189
        }
190
191
        $this->assert(function () use ($realJsonValue, $expectedJsonValue) {
192
            $this->asserter->castToString($realJsonValue)->isEqualTo((string) $expectedJsonValue);
193
        });
194
    }
195
196
    /**
197
     * @Then the JSON path expression :pathExpression should be equal to json :expectedJson
198
     */
199
    public function theJsonPathExpressionShouldBeEqualToJson($pathExpression, $expectedJson)
200
    {
201
        $expectedJson = new Json($expectedJson);
202
        $actualJson = Json::fromRawContent($this->jsonInspector->searchJsonPath($pathExpression));
203
204
        $this->asserter->castToString($actualJson)->isEqualTo((string) $expectedJson);
205
    }
206
207
    /**
208
     * @Then the JSON path expression :pathExpression should be equal to:
209
     */
210
    public function theJsonExpressionShouldBeEqualTo($pathExpression, PyStringNode $expectedJson)
211
    {
212
        $this->theJsonPathExpressionShouldBeEqualToJson($pathExpression, (string) $expectedJson);
213
    }
214
215
    /**
216
     * @Then the JSON path expression :pathExpression should have result
217
     */
218
    public function theJsonPathExpressionShouldHaveResult($pathExpression)
219
    {
220
        $json = $this->jsonInspector->searchJsonPath($pathExpression);
221
        $this->asserter->variable($json)->isNotNull();
222
    }
223
224
    /**
225
     * @Then the JSON path expression :pathExpression should not have result
226
     */
227
    public function theJsonPathExpressionShouldNotHaveResult($pathExpression)
228
    {
229
        $json = $this->jsonInspector->searchJsonPath($pathExpression);
230
        $this->asserter->variable($json)->isNull();
231
    }
232
233
    private function evaluateJsonNodeValue($jsonNode)
234
    {
235
        return $this->jsonInspector->readJsonNodeValue($jsonNode);
236
    }
237
    
238
    private function evaluateExpectedValue($expectedValue) 
239
    {
240
        if (in_array($expectedValue, array('true', 'false'))) {
241
            return filter_var($expectedValue, FILTER_VALIDATE_BOOLEAN);
242
        }
243
        
244
        if ($expectedValue === 'null') {
245
            return null;
246
        }
247
248
        return $expectedValue;
249
    }    
250
251
    private function readJson()
252
    {
253
        return $this->jsonInspector->readJson();
254
    }
255
256
    private function resolveFilename($filename)
257
    {
258
        if (true === is_file($filename)) {
259
            return realpath($filename);
260
        }
261
262
        if (null === $this->jsonSchemaBaseUrl) {
263
            throw new \RuntimeException(sprintf(
264
                'The JSON schema file "%s" doesn\'t exist',
265
                $filename
266
            ));
267
        }
268
269
        $filename = $this->jsonSchemaBaseUrl . '/' . $filename;
270
271
        if (false === is_file($filename)) {
272
            throw new \RuntimeException(sprintf(
273
                'The JSON schema file "%s" doesn\'t exist',
274
                $filename
275
            ));
276
        }
277
278
        return realpath($filename);
279
    }
280
281
    private function assert(callable $assertion)
282
    {
283
        try {
284
            $assertion();
285
        } catch (\Exception $e) {
286
            throw new WrongJsonExpectation($e->getMessage(), $this->readJson(), $e);
287
        }
288
    }
289
}
290