Passed
Pull Request — master (#43)
by Baptiste
02:06
created

AbstractContext::theJsonPathShouldNotBeEqualTo()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 2
1
<?php declare(strict_types=1);
2
namespace Behapi\Json;
3
4
use stdClass;
5
use Datetime;
6
7
use Throwable;
8
use InvalidArgumentException;
9
10
use Behat\Behat\Context\Context;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Behapi\Json\Context.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
11
use Behat\Gherkin\Node\PyStringNode;
12
13
use Symfony\Component\PropertyAccess\PropertyAccess;
14
use Symfony\Component\PropertyAccess\PropertyAccessor;
15
16
use Webmozart\Assert\Assert;
17
18
use function preg_match;
19
use function json_last_error;
20
21
use const JSON_ERROR_NONE;
22
use const PREG_OFFSET_CAPTURE;
23
24
abstract class AbstractContext implements Context
25
{
26
    /** @var PropertyAccessor */
27
    private $accessor;
28
29
    public function __construct()
30
    {
31
        $this->accessor = PropertyAccess::createPropertyAccessor();
32
    }
33
34
    /**
35
     * Get the latest json response
36
     *
37
     * @return stdClass decoded json into an object
38
     */
39
    abstract protected function getJson();
40
41
    /**
42
     * Get the value for a path
43
     *
44
     * @param string $path Path to parse
45
     *
46
     * @return mixed
47
     * @throws AccessException path not valid
48
     */
49
    protected function getValue(string $path)
50
    {
51
        return $this->accessor->getValue($this->getJson(), $path);
52
    }
53
54
    /**
55
     * @Then the response should be a valid json response
56
     *
57
     * ---
58
     *
59
     * This method is built-on the default php's json extension. You should
60
     * overwrite it if you want to add supplementary checks or use something
61
     * else instead (such as Seldaek's JsonLint package).
62
     */
63
    public function responseIsValidjson()
64
    {
65
        $this->getJson();
66
67
        Assert::same(json_last_error(), JSON_ERROR_NONE, 'The latest json response should be a valid json response');
68
    }
69
70
    /** @Then :path should be accessible in the latest json response */
71
    public function pathShouldBeReadable(string $path)
72
    {
73
        Assert::true($this->accessor->isReadable($this->getJson(), $path), "The path $path should be a valid path");
74
    }
75
76
    /** @Then :path should not exist in the latest json response */
77
    public function pathShouldNotBeReadable(string $path)
78
    {
79
        Assert::false($this->accessor->isReadable($this->getJson(), $path), "The path $path should not be a valid path");
80
    }
81
82
    /** @Then in the json, :path should be equal to :expected */
83
    public function theJsonPathShouldBeEqualTo(string $path, $expected)
84
    {
85
        Assert::eq($this->getValue($path), $expected);
86
    }
87
88
    /** @Then in the json, :path should not be equal to :expected */
89
    public function theJsonPathShouldNotBeEqualTo(string $path, $expected)
90
    {
91
        Assert::notEq($this->getValue($path), $expected);
92
    }
93
94
    /** @Then in the json, :path should be: */
95
    public function theJsonPathShouldBePyString(string $path, PyStringNode $expected)
96
    {
97
        Assert::same($this->getValue($path), $expected->getRaw());
98
    }
99
100
    /** @Then /^in the json, "(?P<path>(?:[^"]|\\")*)" should be (?P<expected>true|false)$/ */
101
    public function theJsonPathShouldBe(string $path, string $expected)
102
    {
103
        Assert::same($this->getValue($path), 'true' === $expected);
104
    }
105
106
    /** @Then /^in the json, "(?P<path>(?:[^"]|\\")*)" should not be (?P<expected>true|false)$/ */
107
    public function theJsonPathShouldNotBe(string $path, string $expected)
108
    {
109
        Assert::notSame($this->getValue($path), 'true' === $expected);
110
    }
111
112
    /** @Then in the json, :path should be null */
113
    public function theJsonPathShouldBeNull(string $path)
114
    {
115
        Assert::null($this->getValue($path));
116
    }
117
118
    /** @Then in the json, :path should not be null */
119
    public function theJsonPathShouldNotBeNull(string $path)
120
    {
121
        Assert::notNull($this->getValue($path));
122
    }
123
124
    /** @Then in the json, :path should be empty */
125
    public function theJsonPathShouldBeEmpty(string $path)
126
    {
127
        Assert::isEmpty($this->getValue($path));
128
    }
129
130
    /** @Then in the json, :path should not be empty */
131
    public function theJsonPathShouldNotBeEmpty(string $path)
132
    {
133
        Assert::notEmpty($this->getValue($path));
134
    }
135
136
    /** @Then in the json, :path should contain :expected */
137
    public function theJsonPathContains(string $path, $expected)
138
    {
139
        Assert::contains($this->getValue($path), $expected);
140
    }
141
142
    /** @Then /^in the json, :path should not contain :expected */
143
    public function theJsonPathNotContains(string $path, $expected)
144
    {
145
        Assert::notContains($this->getValue($path), $expected);
146
    }
147
148
    /** @Then in the json, :path collection should contain an element with :value equal to :expected */
149
    public function theJsonPathCollectionContains(string $path, string $value, $expected)
150
    {
151
        $collection = $this->accessor->getValue($this->getJson(), $path);
152
153
        foreach ($collection as $element) {
154
            if ($expected === $this->accessor->getValue($element, $value)) {
155
                return;
156
            }
157
        }
158
159
        throw new InvalidArgumentException("$path collection does not contain an element with $value equal to $expected");
160
    }
161
162
    /** @Then in the json, :path should be a valid date(time) */
163
    public function theJsonPathShouldBeAValidDate(string $path)
164
    {
165
        try {
166
            new Datetime($this->getValue($path));
167
        } catch (Throwable $t) {
168
            throw new InvalidArgumentException("$path does not contain a valid date");
169
        }
170
    }
171
172
    /** @Then in the json, :path should be greater than :expected */
173
    public function theJsonPathShouldBeGreaterThan(string $path, int $expected)
174
    {
175
        Assert::greaterThan($this->getValue($path), $expected);
176
    }
177
178
    /** @Then in the json, :path should be greater than or equal to :expected */
179
    public function theJsonPathShouldBeGreaterOrEqualThan(string $path, int $expected)
180
    {
181
        Assert::greaterThanEq($this->getValue($path), $expected);
182
    }
183
184
    /** @Then in the json, :path should be less than :expected */
185
    public function theJsonPathShouldBeLessThan(string $path, int $expected)
186
    {
187
        Assert::lessThan($this->getValue($path), $expected);
188
    }
189
190
    /** @Then in the json, :path should be less than or equal to :expected */
191
    public function theJsonPathShouldBeLessOrEqualThan(string $path, int $expected)
192
    {
193
        Assert::lessThanEq($this->getValue($path), $expected);
194
    }
195
196
    /** @Then in the json, :path should be an array */
197
    public function shouldBeAnArray(string $path)
198
    {
199
        Assert::isArray($this->getValue($path));
200
    }
201
202
    /** @Then in the json, :path should have at least :count element(s) */
203
    public function theJsonPathShouldHaveAtLeastElements(string $path, int $count)
204
    {
205
        $value = $this->getValue($path);
206
207
        Assert::isArray($value);
208
        Assert::greaterThanEq(count($value), $count);
209
    }
210
211
    /** @Then in the json, :path should have :count element(s) */
212
    public function theJsonPathShouldHaveElements(string $path, int $count)
213
    {
214
        Assert::count($this->getValue($path), $count);
215
    }
216
217
    /** @Then in the json, :path should have at most :count element(s) */
218
    public function theJsonPathShouldHaveAtMostElements(string $path, int $count)
219
    {
220
        $value = $this->getValue($path);
221
222
        Assert::isArray($value);
223
        Assert::lessThanEq(count($value), $count);
224
    }
225
226
    /** @Then in the json, :path should match :pattern */
227
    public function theJsonPathShouldMatch(string $path, string $pattern)
228
    {
229
        Assert::regex($this->getValue($path), $pattern);
230
    }
231
232
    /**
233
     * @Then in the json, :path should not match :pattern
234
     *
235
     * -----
236
     *
237
     * Note :: The body of this assertion should be replaced by a
238
     * `Assert::notRegex` as soon as the Assert's PR
239
     * https://github.com/webmozart/assert/pull/58 is merged and released.
240
     */
241
    public function theJsonPathShouldNotMatch(string $path, string $pattern)
242
    {
243
        if (!preg_match($pattern, $this->getValue($path), $matches, PREG_OFFSET_CAPTURE)) {
244
            // it's all good, it is supposed not to match. :}
245
            return;
246
        }
247
248
        throw new InvalidArgumentException("The value matches {$pattern} at offset {$matches[0][1]}");
249
    }
250
251
    /** @Then in the json, the root should be an array */
252
    public function rootShouldBeAnArray()
253
    {
254
        Assert::isArray($this->getJson());
255
    }
256
257
    /** @Then in the json, the root should have :count element(s) */
258
    public function theRootShouldHaveElements(int $count)
259
    {
260
        $value = $this->getJson();
261
262
        Assert::isArray($value);
263
        Assert::count($value, $count);
264
    }
265
266
    /** @Then in the json, the root should have at most :count element(s) */
267
    public function theRootShouldHaveAtMostElements(int $count)
268
    {
269
        $value = $this->getJson();
270
271
        Assert::isArray($value);
272
        Assert::lessThanEq($value, $count);
273
    }
274
275
    /** @Then in the json, :path should be a valid json encoded string */
276
    public function theJsonPathShouldBeAValidJsonEncodedString(string $path)
277
    {
278
        $value = json_decode($this->getValue($path));
279
280
        Assert::notNull($value);
281
        Assert::same(json_last_error(), JSON_ERROR_NONE);
282
    }
283
}
284