Passed
Pull Request — master (#52)
by Baptiste
02:38
created

AbstractContext::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
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\Gherkin\Node\PyStringNode;
11
use Behat\Behat\Context\Context as BehatContext;
12
13
use Symfony\Component\PropertyAccess\PropertyAccess;
14
use Symfony\Component\PropertyAccess\PropertyAccessor;
15
16
use Webmozart\Assert\Assert;
17
18
use function count;
19
use function preg_match;
20
use function json_last_error;
21
22
use const JSON_ERROR_NONE;
23
use const PREG_OFFSET_CAPTURE;
24
25
abstract class AbstractContext implements BehatContext
26
{
27
    /** @var PropertyAccessor */
28
    private $accessor;
29
30
    public function __construct()
31
    {
32
        $this->accessor = PropertyAccess::createPropertyAccessor();
33
    }
34
35
    abstract protected function getJson();
36
37
    protected function getValue(string $path)
38
    {
39
        return $this->accessor->getValue($this->getJson(), $path);
40
    }
41
42
    /** @Then :path should be accessible in the latest json response */
43
    final public function path_should_be_readable(string $path): void
44
    {
45
        Assert::true($this->accessor->isReadable($this->getJson(), $path), "The path $path should be a valid path");
46
    }
47
48
    /** @Then :path should not exist in the latest json response */
49
    final public function path_should_not_be_readable(string $path): void
50
    {
51
        Assert::false($this->accessor->isReadable($this->getJson(), $path), "The path $path should not be a valid path");
52
    }
53
54
    /**
55
     * @Then in the json, :path should be equal to :expected
56
     * @Then in the json, :path should :not be equal to :expected
57
     */
58
    final public function the_json_path_should_be_equal_to(string $path, ?string $not = null, $expected): void
59
    {
60
        $assert = [Assert::class, $not !== null ? 'notEq' : 'eq'];
61
        assert(is_callable($assert));
62
63
        $assert($this->getValue($path), $expected);
64
    }
65
66
    /** @Then in the json, :path should be: */
67
    final public function the_json_path_should_be_py_string(string $path, PyStringNode $expected): void
68
    {
69
        Assert::same($this->getValue($path), $expected->getRaw());
70
    }
71
72
    /**
73
     * @Then /^in the json, "(?P<path>(?:[^"]|\\")*)" should be (?P<expected>true|false)$/
74
     * @Then /^in the json, "(?P<path>(?:[^"]|\\")*)" should :not be (?P<expected>true|false)$/
75
     */
76
    final public function the_json_path_should_be(string $path, ?string $not = null, string $expected): void
77
    {
78
        $assert = [Assert::class, $not !== null ? 'notSame' : 'same'];
79
        assert(is_callable($assert));
80
81
        $assert($this->getValue($path), 'true' === $expected);
82
    }
83
84
    /**
85
     * @Then in the json, :path should be null
86
     * @Then in the json, :path should :not be null
87
     */
88
    final public function the_json_path_should_be_null(string $path, ?string $not = null): void
89
    {
90
        $assert = [Assert::class, $not !== null ? 'notNull' : 'null'];
91
        assert(is_callable($assert));
92
93
        $assert($this->getValue($path));
94
    }
95
96
    /**
97
     * @Then in the json, :path should be empty
98
     * @Then in the json, :path should :not be empty
99
     */
100
    final public function the_json_path_should_be_empty(string $path, ?string $not = null): void
101
    {
102
        $assert = [Assert::class, $not !== null ? 'notEmpty' : 'isEmpty'];
103
        assert(is_callable($assert));
104
105
        $assert($this->getValue($path));
106
    }
107
108
    /**
109
     * @Then in the json, :path should contain :expected
110
     * @Then in the json, :path should :not contain :expected
111
     */
112
    final public function the_json_path_contains(string $path, ?string $not = null, $expected): void
113
    {
114
        $assert = [Assert::class, $not !== null ? 'notContains' : 'contains'];
115
        assert(is_callable($assert));
116
117
        $assert($this->getValue($path), $expected);
118
    }
119
120
    /** @Then in the json, :path collection should contain an element with :value equal to :expected */
121
    final public function the_json_path_collection_contains(string $path, string $value, $expected): void
122
    {
123
        $collection = $this->accessor->getValue($this->getJson(), $path);
124
        Assert::isIterable($collection);
125
126
        foreach ($collection as $element) {
127
            if ($expected === $this->accessor->getValue($element, $value)) {
128
                return;
129
            }
130
        }
131
132
        throw new InvalidArgumentException("$path collection does not contain an element with $value equal to $expected");
133
    }
134
135
    /** @Then in the json, :path should be a valid date(time) */
136
    final public function the_json_path_should_be_a_valid_date(string $path): void
137
    {
138
        try {
139
            new DateTime($this->getValue($path));
140
        } catch (Throwable $t) {
141
            throw new InvalidArgumentException("$path does not contain a valid date");
142
        }
143
    }
144
145
    /** @Then in the json, :path should be greater than :expected */
146
    final public function the_json_path_should_be_greater_than(string $path, int $expected): void
147
    {
148
        Assert::greaterThan($this->getValue($path), $expected);
149
    }
150
151
    /** @Then in the json, :path should be greater than or equal to :expected */
152
    final public function the_json_path_should_be_greater_or_equal_than(string $path, int $expected): void
153
    {
154
        Assert::greaterThanEq($this->getValue($path), $expected);
155
    }
156
157
    /** @Then in the json, :path should be less than :expected */
158
    final public function the_json_path_should_be_less_than(string $path, int $expected): void
159
    {
160
        Assert::lessThan($this->getValue($path), $expected);
161
    }
162
163
    /** @Then in the json, :path should be less than or equal to :expected */
164
    final public function the_json_path_should_be_less_or_equal_than(string $path, int $expected): void
165
    {
166
        Assert::lessThanEq($this->getValue($path), $expected);
167
    }
168
169
    /** @Then in the json, (?:root|\"(?P<path>(?:[^"]|\\")*)\") should be an array */
170
    final public function should_be_an_array(string $path): void
171
    {
172
        Assert::isArray(empty($path) ? $this->getJson() : $this->getValue($path));
173
    }
174
175
    /** @Then in the json, (?:root|\"(?P<path>(?:[^"]|\\")*)\") collection should have at least (?P<count>[1-9][0-9]*) element(s) */
176
    final public function the_json_collection_should_have_at_least_elements(string $path, int $count): void
177
    {
178
        $value = empty($path) ? $this->getJson() : $this->getValue($path);
179
180
        Assert::isCountable($value);
181
        Assert::minCount($value, $count);
182
    }
183
184
    /** @Then in the json, (?:root|\"(?P<path>(?:[^"]|\\")*)\") collection should have (?P<count>[1-9][0-9]*) element(s) */
185
    final public function the_json_path_should_have_elements(string $path, int $count): void
186
    {
187
        $value = empty($path) ? $this->getJson() : $this->getValue($path);
188
189
        Assert::isCountable($value);
190
        Assert::count($value, $count);
191
    }
192
193
    /** @Then in the json, (?:root|\"(?P<path>(?:[^"]|\\")*)\") collection should have at most (?P<count>[1-9][0-9]*) element(s) */
194
    final public function the_json_path_should_have_at_most_elements(string $path, int $count): void
195
    {
196
        $value = empty($path) ? $this->getJson() : $this->getValue($path);
197
198
        Assert::isCountable($value);
199
        Assert::maxCount($value, $count);
200
    }
201
202
    /** @Then in the json, :path should match :pattern */
203
    final public function the_json_path_should_match(string $path, string $pattern): void
204
    {
205
        Assert::regex($this->getValue($path), $pattern);
206
    }
207
208
    /**
209
     * @Then in the json, :path should not match :pattern
210
     *
211
     * -----
212
     *
213
     * Note :: The body of this assertion should be replaced by a
214
     * `Assert::notRegex` as soon as the Assert's PR
215
     * https://github.com/webmozart/assert/pull/58 is merged and released.
216
     */
217
    final public function the_json_path_should_not_match(string $path, string $pattern): void
218
    {
219
        if (!preg_match($pattern, $this->getValue($path), $matches, PREG_OFFSET_CAPTURE)) {
220
            // it's all good, it is supposed not to match. :}
221
            return;
222
        }
223
224
        throw new InvalidArgumentException("The value matches {$pattern} at offset {$matches[0][1]}");
225
    }
226
227
    /** @Then in the json, :path should be a valid json encoded string */
228
    final public function the_json_path_should_be_a_valid_json_encoded_string(string $path): void
229
    {
230
        $value = json_decode($this->getValue($path));
231
232
        Assert::notNull($value);
233
        Assert::same(json_last_error(), JSON_ERROR_NONE);
234
    }
235
236
    /**
237
     * @Then /^in the json, all the elements in the (?:root|\"(?P<path>(?:[^"]|\\")*)\") collection should have a(?:n?) "(?P<property>(?:[^"]|\\")*)" property$/
238
     * @Then /^in the json, all the elements in the (?:root|\"(?P<path>(?:[^"]|\\")*)\") collection should (?P<not>not) have a(?:n?) "(?P<property>(?:[^"]|\\")*)" property$/
239
     **/
240
    final public function the_json_path_elements_in_collection_should_have_a_property(string $path, ?string $not = null, string $property): void
241
    {
242
        $assert = [Assert::class, $not !== null ? 'allPropertyNotExists' : 'allPropertyExists'];
243
        assert(is_callable($assert));
244
245
        $assert(empty($path) ? $this->getJson() : $this->getValue($path), $property);
246
    }
247
248
    /**
249
     * @Then /^in the json, each "(?P<property>(?:[^"]|\\")*)" property in the (?:root|\"(?P<path>(?:[^"]|\\")*)\") collection should be equal to "(?P<expected>(?:[^"]|\\")*)"$/
250
     * @Then /^in the json, each "(?P<property>(?:[^"]|\\")*)" property in the (?:root|\"(?P<path>(?:[^"]|\\")*)\") collection should (?P<not>not) be equal to "(?P<expected>(?:[^"]|\\")*)"$/
251
     */
252
    final public function the_json_each_elements_in_collection_should_be_equal_to(string $path, string $property, ?string $not = null, string $expected): void
253
    {
254
        $values = empty($path) ? $this->getJson() : $this->getValue($path);
255
        Assert::isIterable($values);
256
257
        $assert = [Assert::class, $not !== null ? 'notSame' : 'same'];
258
        assert(is_callable($assert));
259
260
        foreach ($values as $element) {
261
            $assert($this->accessor->getValue($element, $property), $expected);
262
        }
263
    }
264
265
    /**
266
     * @Then /^in the json, each "(?P<property>(?:[^"]|\\")*)" property in the (?:root|\"(?P<path>(?:[^"]|\\")*)\") collection should be (?P<expected>true|false)$/
267
     * @Then /^in the json, each "(?P<property>(?:[^"]|\\")*)" property in the (?:root|\"(?P<path>(?:[^"]|\\")*)\") collection should (?P<not>not) be (?P<expected>true|false)$/
268
     */
269
    final public function the_json_each_elements_in_collection_should_be_bool(string $path, string $property, ?string $not = null, string $expected): void
270
    {
271
        $values = empty($path) ? $this->getJson() : $this->getValue($path);
272
        Assert::isIterable($values);
273
274
        $assert = [Assert::class, $not !== null ? 'notSame' : 'same'];
275
        assert(is_callable($assert));
276
277
        foreach ($values as $element) {
278
            $assert($this->accessor->getValue($element, $property), $expected === 'true');
279
        }
280
    }
281
282
    /**
283
     * @Then /^in the json, each "(?P<property>(?:[^"]|\\")*)" property in the (?:root|\"(?P<path>(?:[^"]|\\")*)\") collection should be equal to (?P<expected>[0-9]+)$/
284
     * @Then /^in the json, each "(?P<property>(?:[^"]|\\")*)" property in the (?:root|\"(?P<path>(?:[^"]|\\")*)\") collection should (?P<not>not) be equal to (?P<expected>[0-9]+)$/
285
     */
286
    final public function the_json_each_elements_in_collection_should_be_equal_to_int(string $path, string $property, ?string $not = null, int $expected): void
287
    {
288
        $values = empty($path) ? $this->getJson() : $this->getValue($path);
289
        Assert::isIterable($values);
290
291
        $assert = [Assert::class, $not !== null ? 'notSame' : 'same'];
292
        assert(is_callable($assert));
293
294
        foreach ($values as $element) {
295
            $assert($this->accessor->getValue($element, $property), $expected);
296
        }
297
    }
298
299
    /**
300
     * @Then /^in the json, each "(?P<property>(?:[^"]|\\")*)" property in the (?:root|\"(?P<path>(?:[^"]|\\")*)\") collection should contain "(?P<expected>(?:[^"]|\\")*)"$/
301
     * @Then /^in the json, each "(?P<property>(?:[^"]|\\")*)" property in the (?:root|\"(?P<path>(?:[^"]|\\")*)\") collection should (?P<not>not) contain "(?P<expected>(?:[^"]|\\")*)"$/
302
     **/
303
    final public function the_json_each_elements_in_collection_should_contain(string $path, string $property, ?string $not = null, string $expected): void
304
    {
305
        $values = empty($path) ? $this->getJson() : $this->getValue($path);
306
        Assert::isIterable($values);
307
308
        $assert = [Assert::class, $not !== null ? 'notSame' : 'same'];
309
        assert(is_callable($assert));
310
311
        foreach ($values as $element) {
312
            $assert($this->accessor->getValue($element, $property), $expected);
313
        }
314
    }
315
}
316