Passed
Pull Request — master (#278)
by
unknown
02:59
created

JsonContext   B

Complexity

Total Complexity 45

Size/Duplication

Total Lines 433
Duplicated Lines 9.24 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 0
Metric Value
wmc 45
lcom 1
cbo 6
dl 40
loc 433
rs 8.8
c 0
b 0
f 0

31 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A theResponseShouldBeInJson() 0 4 1
A theResponseShouldNotBeInJson() 0 7 1
A theJsonNodeShouldBeEqualTo() 0 12 2
A theJsonNodesShouldBeEqualTo() 0 6 2
A theJsonNodeShouldMatch() 0 12 2
A theJsonNodeShouldBeNull() 0 12 2
A theJsonNodeShouldNotBeNull() 0 6 1
A theJsonNodeShouldBeTrue() 0 12 2
A theJsonNodeShouldBeFalse() 0 12 2
A theJsonNodeShouldBeEqualToTheString() 12 12 2
A theJsonNodeShouldBeEqualToTheNumber() 12 12 3
A theJsonNodeShouldHaveElements() 0 8 1
A theJsonNodeShouldContain() 8 8 1
A theJsonNodesShouldContain() 0 6 2
A theJsonNodeShouldNotContain() 8 8 1
A theJsonNodesShouldNotContain() 0 6 2
A theJsonNodeShouldExist() 0 11 2
A theJsonNodeShouldNotExist() 0 6 1
A theJsonShouldBeValidAccordingToThisSchema() 0 7 1
A theJsonShouldBeInvalidAccordingToThisSchema() 0 6 1
A theJsonShouldBeValidAccordingToTheSchema() 0 12 1
A theJsonShouldBeInvalidAccordingToTheSchema() 0 8 1
A theJsonShouldBeEqualTo() 0 16 2
A printLastJsonResponse() 0 5 1
A theJsonShouldBeValidAccordingToTheSwaggerSchema() 0 16 1
A theJSONNodeShouldBeaBoolean() 0 6 1
A theJSONNodeShouldBeanInteger() 0 6 1
A theJsonShouldNotBeValidAccordingToTheSwaggerSchema() 0 6 1
A getJson() 0 4 1
A checkSchemaFile() 0 8 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like JsonContext often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use JsonContext, and based on these observations, apply Extract Interface, too.

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

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
416
    }
417
418
    /**
419
     *
420
     * Checks, that response JSON not matches with a swagger dump
421
     *
422
     * @Then the JSON should not be valid according to swagger :dumpPath dump schema :schemaName
423
     */
424
    public function theJsonShouldNotBeValidAccordingToTheSwaggerSchema($dumpPath, $schemaName)
425
    {
426
        $this->not(function () use ($dumpPath, $schemaName) {
427
            return $this->theJsonShouldBeValidAccordingToTheSwaggerSchema($dumpPath, $schemaName);
428
        }, 'JSON Schema matches but it should not');
429
    }
430
431
432
433
    protected function getJson()
434
    {
435
        return new Json($this->httpCallResultPool->getResult()->getValue());
436
    }
437
438
    private function checkSchemaFile($filename)
439
    {
440
        if (false === is_file($filename)) {
441
            throw new \RuntimeException(
442
                'The JSON schema doesn\'t exist'
443
            );
444
        }
445
    }
446
}
447