1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Behatch\Context; |
4
|
|
|
|
5
|
|
|
use Behat\Gherkin\Node\PyStringNode; |
6
|
|
|
|
7
|
|
|
use Behat\Gherkin\Node\TableNode; |
8
|
|
|
use Behatch\Json\Json; |
9
|
|
|
use Behatch\Json\JsonSchema; |
10
|
|
|
use Behatch\Json\JsonInspector; |
11
|
|
|
use Behatch\HttpCall\HttpCallResultPool; |
12
|
|
|
|
13
|
|
|
class JsonContext extends BaseContext |
14
|
|
|
{ |
15
|
|
|
protected $inspector; |
16
|
|
|
|
17
|
|
|
protected $httpCallResultPool; |
18
|
|
|
|
19
|
|
|
public function __construct(HttpCallResultPool $httpCallResultPool, $evaluationMode = 'javascript') |
20
|
|
|
{ |
21
|
|
|
$this->inspector = new JsonInspector($evaluationMode); |
22
|
|
|
$this->httpCallResultPool = $httpCallResultPool; |
23
|
|
|
} |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* Checks, that the response is correct JSON |
27
|
|
|
* |
28
|
|
|
* @Then the response should be in JSON |
29
|
|
|
*/ |
30
|
|
|
public function theResponseShouldBeInJson() |
31
|
|
|
{ |
32
|
|
|
$this->getJson(); |
33
|
|
|
} |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* Checks, that the response is not correct JSON |
37
|
|
|
* |
38
|
|
|
* @Then the response should not be in JSON |
39
|
|
|
*/ |
40
|
|
|
public function theResponseShouldNotBeInJson() |
41
|
|
|
{ |
42
|
|
|
$this->not( |
43
|
|
|
[$this, 'theResponseShouldBeInJson'], |
44
|
|
|
'The response is in JSON' |
45
|
|
|
); |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* Checks, that given JSON node is equal to given value |
50
|
|
|
* |
51
|
|
|
* @Then the JSON node :node should be equal to :text |
52
|
|
|
*/ |
53
|
|
|
public function theJsonNodeShouldBeEqualTo($node, $text) |
54
|
|
|
{ |
55
|
|
|
$json = $this->getJson(); |
56
|
|
|
|
57
|
|
|
$actual = $this->inspector->evaluate($json, $node); |
58
|
|
|
|
59
|
|
|
if ($actual != $text) { |
60
|
|
|
throw new \Exception( |
61
|
|
|
sprintf("The node value is '%s'", json_encode($actual)) |
62
|
|
|
); |
63
|
|
|
} |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* Checks, that given JSON nodes are equal to givens values |
68
|
|
|
* |
69
|
|
|
* @Then the JSON nodes should be equal to: |
70
|
|
|
*/ |
71
|
|
|
public function theJsonNodesShoudBeEqualTo(TableNode $nodes) |
72
|
|
|
{ |
73
|
|
|
foreach ($nodes->getRowsHash() as $node => $text) { |
74
|
|
|
$this->theJsonNodeShouldBeEqualTo($node, $text); |
75
|
|
|
} |
76
|
|
|
} |
77
|
|
|
|
78
|
|
|
/** |
79
|
|
|
* Checks, that given JSON node is null |
80
|
|
|
* |
81
|
|
|
* @Then the JSON node :node should be null |
82
|
|
|
*/ |
83
|
|
|
public function theJsonNodeShouldBeNull($node) |
84
|
|
|
{ |
85
|
|
|
$json = $this->getJson(); |
86
|
|
|
|
87
|
|
|
$actual = $this->inspector->evaluate($json, $node); |
88
|
|
|
|
89
|
|
|
if (null !== $actual) { |
90
|
|
|
throw new \Exception( |
91
|
|
|
sprintf('The node value is `%s`', json_encode($actual)) |
92
|
|
|
); |
93
|
|
|
} |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* Checks, that given JSON node is not null. |
98
|
|
|
* |
99
|
|
|
* @Then the JSON node :node should not be null |
100
|
|
|
*/ |
101
|
|
|
public function theJsonNodeShouldNotBeNull($name) |
102
|
|
|
{ |
103
|
|
|
$this->not(function () use ($name) { |
104
|
|
|
return $this->theJsonNodeShouldBeNull($name); |
105
|
|
|
}, sprintf('The node %s should not be null', $name)); |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* Checks, that given JSON node is true |
110
|
|
|
* |
111
|
|
|
* @Then the JSON node :node should be true |
112
|
|
|
*/ |
113
|
|
|
public function theJsonNodeShouldBeTrue($node) |
114
|
|
|
{ |
115
|
|
|
$json = $this->getJson(); |
116
|
|
|
|
117
|
|
|
$actual = $this->inspector->evaluate($json, $node); |
118
|
|
|
|
119
|
|
|
if (true !== $actual) { |
120
|
|
|
throw new \Exception( |
121
|
|
|
sprintf('The node value is `%s`', json_encode($actual)) |
122
|
|
|
); |
123
|
|
|
} |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* Checks, that given JSON node is false |
128
|
|
|
* |
129
|
|
|
* @Then the JSON node :node should be false |
130
|
|
|
*/ |
131
|
|
|
public function theJsonNodeShouldBeFalse($node) |
132
|
|
|
{ |
133
|
|
|
$json = $this->getJson(); |
134
|
|
|
|
135
|
|
|
$actual = $this->inspector->evaluate($json, $node); |
136
|
|
|
|
137
|
|
|
if (false !== $actual) { |
138
|
|
|
throw new \Exception( |
139
|
|
|
sprintf('The node value is `%s`', json_encode($actual)) |
140
|
|
|
); |
141
|
|
|
} |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* Checks, that given JSON node is equal to the given string |
146
|
|
|
* |
147
|
|
|
* @Then the JSON node :node should be equal to the string :text |
148
|
|
|
*/ |
149
|
|
View Code Duplication |
public function theJsonNodeShouldBeEqualToTheString($node, $text) |
|
|
|
|
150
|
|
|
{ |
151
|
|
|
$json = $this->getJson(); |
152
|
|
|
|
153
|
|
|
$actual = $this->inspector->evaluate($json, $node); |
154
|
|
|
|
155
|
|
|
if ($actual !== $text) { |
156
|
|
|
throw new \Exception( |
157
|
|
|
sprintf('The node value is `%s`', json_encode($actual)) |
158
|
|
|
); |
159
|
|
|
} |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
/** |
163
|
|
|
* Checks, that given JSON node is equal to the given number |
164
|
|
|
* |
165
|
|
|
* @Then the JSON node :node should be equal to the number :number |
166
|
|
|
*/ |
167
|
|
View Code Duplication |
public function theJsonNodeShouldBeEqualToTheNumber($node, $number) |
|
|
|
|
168
|
|
|
{ |
169
|
|
|
$json = $this->getJson(); |
170
|
|
|
|
171
|
|
|
$actual = $this->inspector->evaluate($json, $node); |
172
|
|
|
|
173
|
|
|
if ($actual !== (float) $number && $actual !== (int) $number) { |
174
|
|
|
throw new \Exception( |
175
|
|
|
sprintf('The node value is `%s`', json_encode($actual)) |
176
|
|
|
); |
177
|
|
|
} |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
/** |
181
|
|
|
* Checks, that given JSON node has N element(s) |
182
|
|
|
* |
183
|
|
|
* @Then the JSON node :node should have :count element(s) |
184
|
|
|
*/ |
185
|
|
|
public function theJsonNodeShouldHaveElements($node, $count) |
186
|
|
|
{ |
187
|
|
|
$json = $this->getJson(); |
188
|
|
|
|
189
|
|
|
$actual = $this->inspector->evaluate($json, $node); |
190
|
|
|
|
191
|
|
|
$this->assertSame($count, sizeof((array) $actual)); |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
/** |
195
|
|
|
* Checks, that given JSON node contains given value |
196
|
|
|
* |
197
|
|
|
* @Then the JSON node :node should contain :text |
198
|
|
|
*/ |
199
|
|
View Code Duplication |
public function theJsonNodeShouldContain($node, $text) |
|
|
|
|
200
|
|
|
{ |
201
|
|
|
$json = $this->getJson(); |
202
|
|
|
|
203
|
|
|
$actual = $this->inspector->evaluate($json, $node); |
204
|
|
|
|
205
|
|
|
$this->assertContains($text, (string) $actual); |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
/** |
209
|
|
|
* Checks, that given JSON nodes contains values |
210
|
|
|
* |
211
|
|
|
* @Then the JSON nodes should contain: |
212
|
|
|
*/ |
213
|
|
|
public function theJsonNodesShoudContain(TableNode $nodes) |
214
|
|
|
{ |
215
|
|
|
foreach ($nodes->getRowsHash() as $node => $text) { |
216
|
|
|
$this->theJsonNodeShouldContain($node, $text); |
217
|
|
|
} |
218
|
|
|
} |
219
|
|
|
|
220
|
|
|
/** |
221
|
|
|
* Checks, that given JSON node does not contain given value |
222
|
|
|
* |
223
|
|
|
* @Then the JSON node :node should not contain :text |
224
|
|
|
*/ |
225
|
|
View Code Duplication |
public function theJsonNodeShouldNotContain($node, $text) |
|
|
|
|
226
|
|
|
{ |
227
|
|
|
$json = $this->getJson(); |
228
|
|
|
|
229
|
|
|
$actual = $this->inspector->evaluate($json, $node); |
230
|
|
|
|
231
|
|
|
$this->assertNotContains($text, (string) $actual); |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
/** |
235
|
|
|
* Checks, that given JSON nodes does not contain given value |
236
|
|
|
* |
237
|
|
|
* @Then the JSON nodes should not contain: |
238
|
|
|
*/ |
239
|
|
|
public function theJsonNodesShoudNotContain(TableNode $nodes) |
240
|
|
|
{ |
241
|
|
|
foreach ($nodes->getRowsHash() as $node => $text) { |
242
|
|
|
$this->theJsonNodeShouldNotContain($node, $text); |
243
|
|
|
} |
244
|
|
|
} |
245
|
|
|
|
246
|
|
|
/** |
247
|
|
|
* Checks, that given JSON node exist |
248
|
|
|
* |
249
|
|
|
* @Given the JSON node :name should exist |
250
|
|
|
*/ |
251
|
|
|
public function theJsonNodeShouldExist($name) |
252
|
|
|
{ |
253
|
|
|
$json = $this->getJson(); |
254
|
|
|
|
255
|
|
|
try { |
256
|
|
|
$node = $this->inspector->evaluate($json, $name); |
257
|
|
|
} |
258
|
|
|
catch (\Exception $e) { |
259
|
|
|
throw new \Exception("The node '$name' does not exist."); |
260
|
|
|
} |
261
|
|
|
return $node; |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
/** |
265
|
|
|
* Checks, that given JSON node does not exist |
266
|
|
|
* |
267
|
|
|
* @Given the JSON node :name should not exist |
268
|
|
|
*/ |
269
|
|
|
public function theJsonNodeShouldNotExist($name) |
270
|
|
|
{ |
271
|
|
|
$this->not(function () use($name) { |
272
|
|
|
return $this->theJsonNodeShouldExist($name); |
273
|
|
|
}, "The node '$name' exists."); |
274
|
|
|
} |
275
|
|
|
|
276
|
|
|
/** |
277
|
|
|
* @Then the JSON should be valid according to this schema: |
278
|
|
|
*/ |
279
|
|
|
public function theJsonShouldBeValidAccordingToThisSchema(PyStringNode $schema) |
280
|
|
|
{ |
281
|
|
|
$this->inspector->validate( |
282
|
|
|
$this->getJson(), |
283
|
|
|
new JsonSchema($schema) |
284
|
|
|
); |
285
|
|
|
} |
286
|
|
|
|
287
|
|
|
/** |
288
|
|
|
* @Then the JSON should be valid according to the schema :filename |
289
|
|
|
*/ |
290
|
|
|
public function theJsonShouldBeValidAccordingToTheSchema($filename) |
291
|
|
|
{ |
292
|
|
|
$this->checkSchemaFile($filename); |
293
|
|
|
|
294
|
|
|
$this->inspector->validate( |
295
|
|
|
$this->getJson(), |
296
|
|
|
new JsonSchema( |
297
|
|
|
file_get_contents($filename), |
298
|
|
|
'file://' . getcwd() . '/' . $filename |
299
|
|
|
) |
300
|
|
|
); |
301
|
|
|
} |
302
|
|
|
|
303
|
|
|
/** |
304
|
|
|
* @Then the JSON should be invalid according to the schema :filename |
305
|
|
|
*/ |
306
|
|
|
public function theJsonShouldBeInvalidAccordingToTheSchema($filename) |
307
|
|
|
{ |
308
|
|
|
$this->checkSchemaFile($filename); |
309
|
|
|
|
310
|
|
|
$this->not(function () use($filename) { |
311
|
|
|
return $this->theJsonShouldBeValidAccordingToTheSchema($filename); |
312
|
|
|
}, "The schema was valid"); |
313
|
|
|
} |
314
|
|
|
|
315
|
|
|
/** |
316
|
|
|
* @Then the JSON should be equal to: |
317
|
|
|
*/ |
318
|
|
|
public function theJsonShouldBeEqualTo(PyStringNode $content) |
319
|
|
|
{ |
320
|
|
|
$actual = $this->getJson(); |
321
|
|
|
|
322
|
|
|
try { |
323
|
|
|
$expected = new Json($content); |
324
|
|
|
} |
325
|
|
|
catch (\Exception $e) { |
326
|
|
|
throw new \Exception('The expected JSON is not a valid'); |
327
|
|
|
} |
328
|
|
|
|
329
|
|
|
$this->assertSame( |
330
|
|
|
(string) $expected, |
331
|
|
|
(string) $actual, |
332
|
|
|
"The json is equal to:\n". $actual->encode() |
333
|
|
|
); |
334
|
|
|
} |
335
|
|
|
|
336
|
|
|
/** |
337
|
|
|
* @Then print last JSON response |
338
|
|
|
*/ |
339
|
|
|
public function printLastJsonResponse() |
340
|
|
|
{ |
341
|
|
|
echo $this->getJson() |
342
|
|
|
->encode(); |
343
|
|
|
} |
344
|
|
|
|
345
|
|
|
protected function getJson() |
346
|
|
|
{ |
347
|
|
|
return new Json($this->httpCallResultPool->getResult()->getValue()); |
348
|
|
|
} |
349
|
|
|
|
350
|
|
|
private function checkSchemaFile($filename) |
351
|
|
|
{ |
352
|
|
|
if (false === is_file($filename)) { |
353
|
|
|
throw new \RuntimeException( |
354
|
|
|
'The JSON schema doesn\'t exist' |
355
|
|
|
); |
356
|
|
|
} |
357
|
|
|
} |
358
|
|
|
} |
359
|
|
|
|
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.