Passed
Pull Request — master (#52)
by Baptiste
05:10
created

AbstractContext::root_should_be_an_array()   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 DateTimeImmutable;
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 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 BehatContext
25
{
26
    use CountTrait;
27
    use RegexTrait;
28
    use ComparisonTrait;
29
    use EachInCollectionTrait;
30
31
    /** @var PropertyAccessor */
32
    private $accessor;
33
34
    public function __construct()
35
    {
36
        $this->accessor = PropertyAccess::createPropertyAccessor();
37
    }
38
39
    abstract protected function getJson();
40
41
    protected function getValue(?string $path)
42
    {
43
        $json = $this->getJson();
44
45
        return $path === null ? $json : $this->accessor->getValue($json, $path);
46
    }
47
48
    /** @Then :path should be accessible in the latest json response */
49
    final public function path_should_be_readable(string $path): void
50
    {
51
        Assert::true($this->accessor->isReadable($this->getValue(null), $path), "The path $path should be a valid path");
52
    }
53
54
    /** @Then :path should not exist in the latest json response */
55
    final public function path_should_not_be_readable(string $path): void
56
    {
57
        Assert::false($this->accessor->isReadable($this->getValue(null), $path), "The path $path should not be a valid path");
58
    }
59
60
    /**
61
     * @Then in the json, :path should be equal to :expected
62
     * @Then in the json, :path should :not be equal to :expected
63
     */
64
    final public function the_json_path_should_be_equal_to(string $path, ?string $not = null, $expected): void
65
    {
66
        $assert = [Assert::class, $not !== null ? 'notEq' : 'eq'];
67
        assert(is_callable($assert));
68
69
        $assert($this->getValue($path), $expected);
70
    }
71
72
    /** @Then in the json, :path should be: */
73
    final public function the_json_path_should_be_py_string(string $path, PyStringNode $expected): void
74
    {
75
        Assert::same($this->getValue($path), $expected->getRaw());
76
    }
77
78
    /**
79
     * @Then /^in the json, "(?P<path>(?:[^"]|\\")*)" should be (?P<expected>true|false)$/
80
     * @Then /^in the json, "(?P<path>(?:[^"]|\\")*)" should :not be (?P<expected>true|false)$/
81
     */
82
    final public function the_json_path_should_be(string $path, ?string $not = null, string $expected): void
83
    {
84
        $assert = [Assert::class, $not !== null ? 'notSame' : 'same'];
85
        assert(is_callable($assert));
86
87
        $assert($this->getValue($path), 'true' === $expected);
88
    }
89
90
    /**
91
     * @Then in the json, :path should be null
92
     * @Then in the json, :path should :not be null
93
     */
94
    final public function the_json_path_should_be_null(string $path, ?string $not = null): void
95
    {
96
        $assert = [Assert::class, $not !== null ? 'notNull' : 'null'];
97
        assert(is_callable($assert));
98
99
        $assert($this->getValue($path));
100
    }
101
102
    /**
103
     * @Then in the json, :path should be empty
104
     * @Then in the json, :path should :not be empty
105
     */
106
    final public function the_json_path_should_be_empty(string $path, ?string $not = null): void
107
    {
108
        $assert = [Assert::class, $not !== null ? 'notEmpty' : 'isEmpty'];
109
        assert(is_callable($assert));
110
111
        $assert($this->getValue($path));
112
    }
113
114
    /**
115
     * @Then in the json, :path should contain :expected
116
     * @Then in the json, :path should :not contain :expected
117
     */
118
    final public function the_json_path_contains(string $path, ?string $not = null, $expected): void
119
    {
120
        $assert = [Assert::class, $not !== null ? 'notContains' : 'contains'];
121
        assert(is_callable($assert));
122
123
        $assert($this->getValue($path), $expected);
124
    }
125
126
    /** @Then in the json, :path collection should contain an element with :value equal to :expected */
127
    final public function the_json_path_collection_contains(string $path, string $value, $expected): void
128
    {
129
        $collection = $this->getValue($path);
130
        Assert::isIterable($collection);
131
132
        foreach ($collection as $element) {
133
            if ($expected === $this->accessor->getValue($element, $value)) {
134
                return;
135
            }
136
        }
137
138
        throw new InvalidArgumentException("$path collection does not contain an element with $value equal to $expected");
139
    }
140
141
    /** @Then in the json, :path should be a valid date(time) */
142
    final public function the_json_path_should_be_a_valid_date(string $path): void
143
    {
144
        try {
145
            new DateTimeImmutable($this->getValue($path));
146
        } catch (Throwable $t) {
147
            throw new InvalidArgumentException("$path does not contain a valid date");
148
        }
149
    }
150
151
    /**
152
     * @Then in the json, the root should be an array
153
     * @Then in the json, :path should be an array
154
     */
155
    final public function should_be_an_array(?string $path = null): void
156
    {
157
        Assert::isArray($this->getValue($path));
158
    }
159
160
    /** @Then in the json, :path should be a valid json encoded string */
161
    final public function the_json_path_should_be_a_valid_json_encoded_string(string $path): void
162
    {
163
        $value = json_decode($this->getValue($path));
164
165
        Assert::notNull($value);
166
        Assert::same(json_last_error(), JSON_ERROR_NONE);
167
    }
168
}
169