Test Setup Failed
Pull Request — master (#249)
by benjamin
02:29
created

JsonContext::theJsonShouldMatch()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 8
nc 1
nop 1
1
<?php
2
3
namespace Behatch\Context;
4
5
use Behat\Gherkin\Node\PyStringNode;
6
7
use Behat\Gherkin\Node\TableNode;
8
use Behat\Mink\Exception\ExpectationException;
9
use Behatch\Json\Json;
10
use Behatch\Json\JsonSchema;
11
use Behatch\Json\JsonInspector;
12
use Behatch\HttpCall\HttpCallResultPool;
13
use Behatch\PHPVersionNotSupported;
14
use Coduo\PHPMatcher\PHPMatcher;
15
16
class JsonContext extends BaseContext
17
{
18
    protected $inspector;
19
20
    protected $httpCallResultPool;
21
22
    public function __construct(HttpCallResultPool $httpCallResultPool, $evaluationMode = 'javascript')
23
    {
24
        $this->inspector = new JsonInspector($evaluationMode);
25
        $this->httpCallResultPool = $httpCallResultPool;
26
    }
27
28
    /**
29
     * Checks, that the response is correct JSON
30
     *
31
     * @Then the response should be in JSON
32
     */
33
    public function theResponseShouldBeInJson()
34
    {
35
        $this->getJson();
36
    }
37
38
    /**
39
     * Checks, that the response is not correct JSON
40
     *
41
     * @Then the response should not be in JSON
42
     */
43
    public function theResponseShouldNotBeInJson()
44
    {
45
        $this->not(
46
            [$this, 'theResponseShouldBeInJson'],
47
            'The response is in JSON'
48
        );
49
    }
50
51
    /**
52
     * Checks, that given JSON node is equal to given value
53
     *
54
     * @Then the JSON node :node should be equal to :text
55
     */
56 View Code Duplication
    public function theJsonNodeShouldBeEqualTo($node, $text)
57
    {
58
        $json = $this->getJson();
59
60
        $actual = $this->inspector->evaluate($json, $node);
61
62
        if ($actual != $text) {
63
            throw new \Exception(
64
                sprintf("The node value is '%s'", json_encode($actual))
65
            );
66
        }
67
    }
68
69
    /**
70
     * Checks, that given JSON nodes are equal to givens values
71
     *
72
     * @Then the JSON nodes should be equal to:
73
     */
74
    public function theJsonNodesShouldBeEqualTo(TableNode $nodes)
75
    {
76
        foreach ($nodes->getRowsHash() as $node => $text) {
77
            $this->theJsonNodeShouldBeEqualTo($node, $text);
78
        }
79
    }
80
81
    /**
82
     * Checks, that given JSON node matches given pattern
83
     *
84
     * @Then the JSON node :node should match :pattern
85
     */
86
    public function theJsonNodeShouldMatch($node, $pattern)
87
    {
88
        $json = $this->getJson();
89
90
        $actual = $this->inspector->evaluate($json, $node);
91
92
        if (preg_match($pattern, $actual) !== 0) {
93
            return;
94
        }
95
96
        try {
97
            $this->assertMatch($pattern, $actual);
98
        } catch (PHPVersionNotSupported $e) {
99
            throw new \Exception(
100
                sprintf("The node value is '%s'", json_encode($actual))
101
            );
102
        }
103
    }
104
105
    /**
106
     * Checks, that given JSON node is null
107
     *
108
     * @Then the JSON node :node should be null
109
     */
110
    public function theJsonNodeShouldBeNull($node)
111
    {
112
        $json = $this->getJson();
113
114
        $actual = $this->inspector->evaluate($json, $node);
115
116
        if (null !== $actual) {
117
            throw new \Exception(
118
                sprintf('The node value is `%s`', json_encode($actual))
119
            );
120
        }
121
    }
122
123
    /**
124
     * Checks, that given JSON node is not null.
125
     *
126
     * @Then the JSON node :node should not be null
127
     */
128
    public function theJsonNodeShouldNotBeNull($node)
129
    {
130
        $this->not(function () use ($node) {
131
            return $this->theJsonNodeShouldBeNull($node);
132
        }, sprintf('The node %s should not be null', $node));
133
    }
134
135
    /**
136
     * Checks, that given JSON node is true
137
     *
138
     * @Then the JSON node :node should be true
139
     */
140
    public function theJsonNodeShouldBeTrue($node)
141
    {
142
        $json = $this->getJson();
143
144
        $actual = $this->inspector->evaluate($json, $node);
145
146
        if (true !== $actual) {
147
            throw new \Exception(
148
                sprintf('The node value is `%s`', json_encode($actual))
149
            );
150
        }
151
    }
152
153
    /**
154
     * Checks, that given JSON node is false
155
     *
156
     * @Then the JSON node :node should be false
157
     */
158
    public function theJsonNodeShouldBeFalse($node)
159
    {
160
        $json = $this->getJson();
161
162
        $actual = $this->inspector->evaluate($json, $node);
163
164
        if (false !== $actual) {
165
            throw new \Exception(
166
                sprintf('The node value is `%s`', json_encode($actual))
167
            );
168
        }
169
    }
170
171
    /**
172
     * Checks, that given JSON node is equal to the given string
173
     *
174
     * @Then the JSON node :node should be equal to the string :text
175
     */
176 View Code Duplication
    public function theJsonNodeShouldBeEqualToTheString($node, $text)
177
    {
178
        $json = $this->getJson();
179
180
        $actual = $this->inspector->evaluate($json, $node);
181
182
        if ($actual !== $text) {
183
            throw new \Exception(
184
                sprintf('The node value is `%s`', json_encode($actual))
185
            );
186
        }
187
    }
188
189
    /**
190
     * Checks, that given JSON node is equal to the given number
191
     *
192
     * @Then the JSON node :node should be equal to the number :number
193
     */
194 View Code Duplication
    public function theJsonNodeShouldBeEqualToTheNumber($node, $number)
195
    {
196
        $json = $this->getJson();
197
198
        $actual = $this->inspector->evaluate($json, $node);
199
200
        if ($actual !== (float) $number && $actual !== (int) $number) {
201
            throw new \Exception(
202
                sprintf('The node value is `%s`', json_encode($actual))
203
            );
204
        }
205
    }
206
207
    /**
208
     * Checks, that given JSON node has N element(s)
209
     *
210
     * @Then the JSON node :node should have :count element(s)
211
     */
212
    public function theJsonNodeShouldHaveElements($node, $count)
213
    {
214
        $json = $this->getJson();
215
216
        $actual = $this->inspector->evaluate($json, $node);
217
218
        $this->assertSame($count, sizeof((array) $actual));
219
    }
220
221
    /**
222
     * Checks, that given JSON node contains given value
223
     *
224
     * @Then the JSON node :node should contain :text
225
     */
226 View Code Duplication
    public function theJsonNodeShouldContain($node, $text)
227
    {
228
        $json = $this->getJson();
229
230
        $actual = $this->inspector->evaluate($json, $node);
231
232
        $this->assertContains($text, (string) $actual);
233
    }
234
235
    /**
236
     * Checks, that given JSON nodes contains values
237
     *
238
     * @Then the JSON nodes should contain:
239
     */
240
    public function theJsonNodesShouldContain(TableNode $nodes)
241
    {
242
        foreach ($nodes->getRowsHash() as $node => $text) {
243
            $this->theJsonNodeShouldContain($node, $text);
244
        }
245
    }
246
247
    /**
248
     * Checks, that given JSON node does not contain given value
249
     *
250
     * @Then the JSON node :node should not contain :text
251
     */
252 View Code Duplication
    public function theJsonNodeShouldNotContain($node, $text)
253
    {
254
        $json = $this->getJson();
255
256
        $actual = $this->inspector->evaluate($json, $node);
257
258
        $this->assertNotContains($text, (string) $actual);
259
    }
260
261
    /**
262
     * Checks, that given JSON nodes does not contain given value
263
     *
264
     * @Then the JSON nodes should not contain:
265
     */
266
    public function theJsonNodesShouldNotContain(TableNode $nodes)
267
    {
268
        foreach ($nodes->getRowsHash() as $node => $text) {
269
            $this->theJsonNodeShouldNotContain($node, $text);
270
        }
271
    }
272
273
    /**
274
     * Checks, that given JSON node exist
275
     *
276
     * @Then the JSON node :name should exist
277
     */
278
    public function theJsonNodeShouldExist($name)
279
    {
280
        $json = $this->getJson();
281
282
        try {
283
            $node = $this->inspector->evaluate($json, $name);
284
        } catch (\Exception $e) {
285
            throw new \Exception("The node '$name' does not exist.");
286
        }
287
        return $node;
288
    }
289
290
    /**
291
     * Checks, that given JSON node does not exist
292
     *
293
     * @Then the JSON node :name should not exist
294
     */
295
    public function theJsonNodeShouldNotExist($name)
296
    {
297
        $this->not(function () use ($name) {
298
            return $this->theJsonNodeShouldExist($name);
299
        }, "The node '$name' exists.");
300
    }
301
302
    /**
303
     * @Then the JSON should be valid according to this schema:
304
     */
305
    public function theJsonShouldBeValidAccordingToThisSchema(PyStringNode $schema)
306
    {
307
        $this->inspector->validate(
308
            $this->getJson(),
309
            new JsonSchema($schema)
310
        );
311
    }
312
313
    /**
314
     * @Then the JSON should be invalid according to this schema:
315
     */
316
    public function theJsonShouldBeInvalidAccordingToThisSchema(PyStringNode $schema)
317
    {
318
        $this->not(function () use ($schema) {
319
            return $this->theJsonShouldBeValidAccordingToThisSchema($schema);
320
        }, 'Expected to receive invalid json, got valid one');
321
    }
322
323
    /**
324
     * @Then the JSON should be valid according to the schema :filename
325
     */
326
    public function theJsonShouldBeValidAccordingToTheSchema($filename)
327
    {
328
        $this->checkSchemaFile($filename);
329
330
        $this->inspector->validate(
331
            $this->getJson(),
332
            new JsonSchema(
333
                file_get_contents($filename),
334
                'file://' . realpath($filename)
335
            )
336
        );
337
    }
338
339
    /**
340
     * @Then the JSON should be invalid according to the schema :filename
341
     */
342
    public function theJsonShouldBeInvalidAccordingToTheSchema($filename)
343
    {
344
        $this->checkSchemaFile($filename);
345
346
        $this->not(function () use ($filename) {
347
            return $this->theJsonShouldBeValidAccordingToTheSchema($filename);
348
        }, "The schema was valid");
349
    }
350
351
    /**
352
     * @Then the JSON should be equal to:
353
     */
354
    public function theJsonShouldBeEqualTo(PyStringNode $content)
355
    {
356
        $actual = $this->getJson();
357
358
        try {
359
            $expected = new Json($content);
360
        } catch (\Exception $e) {
361
            throw new \Exception('The expected JSON is not a valid');
362
        }
363
364
        $this->assertSame(
365
            (string) $expected,
366
            (string) $actual,
367
            "The json is equal to:\n". $actual->encode()
368
        );
369
    }
370
371
    /**
372
     * @Then the JSON should match:
373
     */
374
    public function theJsonShouldMatch(PyStringNode $content)
375
    {
376
        $expected = $content->getRaw();
377
        $actual = $this->getJson();
378
379
        // Remove all useless whitespaces
380
        $expected = preg_replace('/\s(?=([^"]*"[^"]*")*[^"]*$)/', '', $expected);
381
382
        $this->assertMatch(
383
            (string) $expected,
384
            (string) $actual,
385
            "The json do not match:\n". $actual->encode()
386
        );
387
    }
388
389
    /**
390
     * @Then print last JSON response
391
     */
392
    public function printLastJsonResponse()
393
    {
394
        echo $this->getJson()
395
            ->encode();
396
    }
397
398
    /**
399
     * Checks, that response JSON matches with a swagger dump
400
     *
401
     * @Then the JSON should be valid according to swagger :dumpPath dump schema :schemaName
402
     */
403
    public function theJsonShouldBeValidAccordingToTheSwaggerSchema($dumpPath, $schemaName)
404
    {
405
        $this->checkSchemaFile($dumpPath);
406
407
        $dumpJson = file_get_contents($dumpPath);
408
        $schemas = json_decode($dumpJson, true);
409
        $definition = json_encode(
410
            $schemas['definitions'][$schemaName]
411
        );
412
        $this->inspector->validate(
413
            $this->getJson(),
414
            new JsonSchema(
415
                $definition
416
            )
417
        );
418
    }
419
    /**
420
     *
421
     * Checks, that response JSON not matches with a swagger dump
422
     *
423
     * @Then the JSON should not be valid according to swagger :dumpPath dump schema :schemaName
424
     */
425
    public function theJsonShouldNotBeValidAccordingToTheSwaggerSchema($dumpPath, $schemaName)
426
    {
427
        $this->not(function () use ($dumpPath, $schemaName) {
428
            return $this->theJsonShouldBeValidAccordingToTheSwaggerSchema($dumpPath, $schemaName);
429
        }, 'JSON Schema matches but it should not');
430
    }
431
432
433
434
    protected function getJson()
435
    {
436
        return new Json($this->httpCallResultPool->getResult()->getValue());
437
    }
438
439
    private function checkSchemaFile($filename)
440
    {
441
        if (false === is_file($filename)) {
442
            throw new \RuntimeException(
443
                'The JSON schema doesn\'t exist'
444
            );
445
        }
446
    }
447
}
448