diff --git a/src/Context/JsonContext.php b/src/Context/JsonContext.php index 99630567..7a4628a2 100644 --- a/src/Context/JsonContext.php +++ b/src/Context/JsonContext.php @@ -3,13 +3,11 @@ namespace Behatch\Context; use Behat\Gherkin\Node\PyStringNode; - use Behat\Gherkin\Node\TableNode; -use Behat\Mink\Exception\ExpectationException; +use Behatch\HttpCall\HttpCallResultPool; use Behatch\Json\Json; -use Behatch\Json\JsonSchema; use Behatch\Json\JsonInspector; -use Behatch\HttpCall\HttpCallResultPool; +use Behatch\Json\JsonSchema; class JsonContext extends BaseContext { @@ -49,17 +47,19 @@ public function theResponseShouldNotBeInJson() /** * Checks, that given JSON node is equal to given value * - * @Then the JSON node :node should be equal to :text + * @Then the JSON node :node should be equal to :expected */ - public function theJsonNodeShouldBeEqualTo($node, $text) + public function theJsonNodeShouldBeEqualTo($node, $expected) { $json = $this->getJson(); + $expected = self::reespaceSpecialGherkinValue($expected); + $actual = $this->inspector->evaluate($json, $node); - if ($actual != $text) { + if ($actual != $expected) { throw new \Exception( - sprintf("The node value is '%s'", json_encode($actual)) + sprintf("The node '%s' value is '%s', '%s' expected", $node, json_encode($actual), $expected) ); } } @@ -71,8 +71,21 @@ public function theJsonNodeShouldBeEqualTo($node, $text) */ public function theJsonNodesShouldBeEqualTo(TableNode $nodes) { - foreach ($nodes->getRowsHash() as $node => $text) { - $this->theJsonNodeShouldBeEqualTo($node, $text); + $json = $this->getJson(); + + $errors = []; + foreach ($nodes->getRowsHash() as $node => $expected) { + $actual = $this->inspector->evaluate($json, $node); + + $expected = self::reespaceSpecialGherkinValue($expected); + + if ($actual != $expected) { + $errors[] = sprintf("The node '%s' value is '%s', '%s' expected", $node, json_encode($actual), $expected); + } + } + + if (!empty($errors)) { + throw new \Exception(implode("\n", $errors)); } } @@ -89,7 +102,7 @@ public function theJsonNodeShouldMatch($node, $pattern) if (preg_match($pattern, $actual) === 0) { throw new \Exception( - sprintf("The node value is '%s'", json_encode($actual)) + sprintf("The node '%s' value is '%s', '%s' pattern expected", $node, json_encode($actual), $pattern) ); } } @@ -107,7 +120,7 @@ public function theJsonNodeShouldBeNull($node) if (null !== $actual) { throw new \Exception( - sprintf('The node value is `%s`', json_encode($actual)) + sprintf("The node '%s' value is '%s', null expected", $node, json_encode($actual)) ); } } @@ -119,9 +132,15 @@ public function theJsonNodeShouldBeNull($node) */ public function theJsonNodeShouldNotBeNull($node) { - $this->not(function () use ($node) { - return $this->theJsonNodeShouldBeNull($node); - }, sprintf('The node %s should not be null', $node)); + $json = $this->getJson(); + + $actual = $this->inspector->evaluate($json, $node); + + if (null === $actual) { + throw new \Exception( + sprintf("The node '%s' value is null, non-null value expected", $node) + ); + } } /** @@ -137,7 +156,7 @@ public function theJsonNodeShouldBeTrue($node) if (true !== $actual) { throw new \Exception( - sprintf('The node value is `%s`', json_encode($actual)) + sprintf("The node '%s' value is '%s', 'true' expected", $node, json_encode($actual)) ); } } @@ -155,7 +174,7 @@ public function theJsonNodeShouldBeFalse($node) if (false !== $actual) { throw new \Exception( - sprintf('The node value is `%s`', json_encode($actual)) + sprintf("The node '%s' value is '%s', 'false' expected", $node, json_encode($actual)) ); } } @@ -163,17 +182,17 @@ public function theJsonNodeShouldBeFalse($node) /** * Checks, that given JSON node is equal to the given string * - * @Then the JSON node :node should be equal to the string :text + * @Then the JSON node :node should be equal to the string :expected */ - public function theJsonNodeShouldBeEqualToTheString($node, $text) + public function theJsonNodeShouldBeEqualToTheString($node, $expected) { $json = $this->getJson(); $actual = $this->inspector->evaluate($json, $node); - if ($actual !== $text) { + if ($actual !== $expected) { throw new \Exception( - sprintf('The node value is `%s`', json_encode($actual)) + sprintf("The node '%s' value is '%s', string '%s' expected", $node, json_encode($actual), $expected) ); } } @@ -191,7 +210,7 @@ public function theJsonNodeShouldBeEqualToTheNumber($node, $number) if ($actual !== (float) $number && $actual !== (int) $number) { throw new \Exception( - sprintf('The node value is `%s`', json_encode($actual)) + sprintf("The node '%s' value is '%s', number '%s' expected", $node, json_encode($actual), (string) $number) ); } } @@ -207,7 +226,7 @@ public function theJsonNodeShouldHaveElements($node, $count) $actual = $this->inspector->evaluate($json, $node); - $this->assertSame($count, sizeof((array) $actual)); + $this->assertSame($count, count((array) $actual)); } /** @@ -276,6 +295,7 @@ public function theJsonNodeShouldExist($name) } catch (\Exception $e) { throw new \Exception("The node '$name' does not exist."); } + return $node; } @@ -337,7 +357,7 @@ public function theJsonShouldBeInvalidAccordingToTheSchema($filename) $this->not(function () use ($filename) { return $this->theJsonShouldBeValidAccordingToTheSchema($filename); - }, "The schema was valid"); + }, 'The schema was valid'); } /** @@ -356,7 +376,7 @@ public function theJsonShouldBeEqualTo(PyStringNode $content) $this->assertSame( (string) $expected, (string) $actual, - "The json is equal to:\n". $actual->encode() + "The json is equal to:\n" . $actual->encode() ); } @@ -390,8 +410,8 @@ public function theJsonShouldBeValidAccordingToTheSwaggerSchema($dumpPath, $sche ) ); } + /** - * * Checks, that response JSON not matches with a swagger dump * * @Then the JSON should not be valid according to swagger :dumpPath dump schema :schemaName @@ -403,8 +423,6 @@ public function theJsonShouldNotBeValidAccordingToTheSwaggerSchema($dumpPath, $s }, 'JSON Schema matches but it should not'); } - - protected function getJson() { return new Json($this->httpCallResultPool->getResult()->getValue()); @@ -418,4 +436,9 @@ private function checkSchemaFile($filename) ); } } + + public static function reespaceSpecialGherkinValue(string $value): string + { + return str_replace("\\n", "\n", $value); + } } diff --git a/src/HttpCall/HttpCallResultPoolResolver.php b/src/HttpCall/HttpCallResultPoolResolver.php index 988d8533..a1d10376 100644 --- a/src/HttpCall/HttpCallResultPoolResolver.php +++ b/src/HttpCall/HttpCallResultPoolResolver.php @@ -24,10 +24,10 @@ public function resolveArguments(\ReflectionClass $classReflection, array $argum $parameters = $constructor->getParameters(); foreach ($parameters as $parameter) { if ( - null !== $parameter->getClass() - && isset($this->dependencies[$parameter->getClass()->name]) + null !== $parameter->getType() + && isset($this->dependencies[$parameter->getType()->getName()]) ) { - $arguments[$parameter->name] = $this->dependencies[$parameter->getClass()->name]; + $arguments[$parameter->name] = $this->dependencies[$parameter->getType()->getName()]; } } } diff --git a/tests/units/Context/JsonContext.php b/tests/units/Context/JsonContext.php new file mode 100644 index 00000000..1e138a71 --- /dev/null +++ b/tests/units/Context/JsonContext.php @@ -0,0 +1,195 @@ +mockGenerator->orphanize('__construct'); + $httpCallResult = $this->newMockInstance(HttpCallResult::class); + $httpCallResult->getMockController()->getValue = json_encode([ + 'a string node' => 'some string', + 'another string node' => 'some other string', + 'a null node' => null, + 'a true node' => true, + 'a false node' => false, + 'a number node' => 3, + 'an array node' => [ + 'one', + 'two', + 'three', + ], + ]); + + $this->httpCallResultPool = $this->newMockInstance(HttpCallResultPool::class); + $this->httpCallResultPool->getMockController()->getResult = $httpCallResult; + } + + public function testTheJsonNodeShouldBeEqualTo() + { + $this + ->given($this->newTestedInstance($this->httpCallResultPool)) + ->then + + ->if($this->testedInstance->theJsonNodeShouldBeEqualTo('a string node', 'some string')) + + ->exception(function () { + $this->testedInstance->theJsonNodeShouldBeEqualTo('a string node', 'expectedstring'); + }) + ->hasMessage("The node 'a string node' value is '\"some string\"', 'expectedstring' expected") + ; + } + + public function testTheJsonNodesShouldBeEqualTo() + { + $this + ->given($this->newTestedInstance($this->httpCallResultPool)) + ->and($validTableNode = new TableNode([ + 1 => ['a string node', 'some string'], + 2 => ['another string node', 'some other string'], + ])) + ->then + + ->if($this->testedInstance->theJsonNodesShouldBeEqualTo($validTableNode)) + + ->exception(function () { + $invalidTableNode = new TableNode([ + 1 => ['a string node', 'may the force'], + 2 => ['another string node', 'be with you'], + ]); + $this->testedInstance->theJsonNodesShouldBeEqualTo($invalidTableNode); + }) + ->hasMessage("The node 'a string node' value is '\"some string\"', 'may the force' expected\nThe node 'another string node' value is '\"some other string\"', 'be with you' expected") + ; + } + public function testTheJsonNodeShouldMatch() + { + $this + ->given($this->newTestedInstance($this->httpCallResultPool)) + ->then + + ->if($this->testedInstance->theJsonNodeShouldMatch('a string node', '/some/')) + + ->exception(function () { + $this->testedInstance->theJsonNodeShouldMatch('a string node', '/nomatch/'); + }) + ->hasMessage("The node 'a string node' value is '\"some string\"', '/nomatch/' pattern expected") + ; + } + + public function testTheJsonNodeShouldBeNull() + { + $this + ->given($this->newTestedInstance($this->httpCallResultPool)) + ->then + + ->if($this->testedInstance->theJsonNodeShouldBeNull('a null node')) + + ->exception(function () { + $this->testedInstance->theJsonNodeShouldBeNull('a string node'); + }) + ->hasMessage("The node 'a string node' value is '\"some string\"', null expected") + ; + } + + public function testTheJsonNodeShouldNotBeNull() + { + $this + ->given($this->newTestedInstance($this->httpCallResultPool)) + ->then + + ->if($this->testedInstance->theJsonNodeShouldNotBeNull('a string node')) + + ->exception(function () { + $this->testedInstance->theJsonNodeShouldNotBeNull('a null node'); + }) + ->hasMessage("The node 'a null node' value is null, non-null value expected") + ; + } + + public function testTheJsonNodeShouldBeTrue() + { + $this + ->given($this->newTestedInstance($this->httpCallResultPool)) + ->then + + ->if($this->testedInstance->theJsonNodeShouldBeTrue('a true node')) + + ->exception(function () { + $this->testedInstance->theJsonNodeShouldBeTrue('a false node'); + }) + ->hasMessage("The node 'a false node' value is 'false', 'true' expected") + ; + } + + public function testTheJsonNodeShouldBeFalse() + { + $this + ->given($this->newTestedInstance($this->httpCallResultPool)) + ->then + + ->if($this->testedInstance->theJsonNodeShouldBeFalse('a false node')) + + ->exception(function () { + $this->testedInstance->theJsonNodeShouldBeFalse('a true node'); + }) + ->hasMessage("The node 'a true node' value is 'true', 'false' expected") + ; + } + + public function testTheJsonNodeShouldBeEqualToTheString() + { + $this + ->given($this->newTestedInstance($this->httpCallResultPool)) + ->then + + ->if($this->testedInstance->theJsonNodeShouldBeEqualToTheString('a string node', 'some string')) + + ->exception(function () { + $this->testedInstance->theJsonNodeShouldBeEqualToTheString('a string node', 'expected'); + }) + ->hasMessage("The node 'a string node' value is '\"some string\"', string 'expected' expected") + ; + } + + public function testTheJsonNodeShouldBeEqualToTheNumber() + { + $this + ->given($this->newTestedInstance($this->httpCallResultPool)) + ->then + + ->if($this->testedInstance->theJsonNodeShouldBeEqualToTheNumber('a number node', 3)) + + ->exception(function () { + $this->testedInstance->theJsonNodeShouldBeEqualToTheNumber('a number node', 2); + }) + ->hasMessage("The node 'a number node' value is '3', number '2' expected") + ; + } + + public function testTheJsonNodeShouldExist() + { + $this + ->given($this->newTestedInstance($this->httpCallResultPool)) + ->then + + ->if($this->testedInstance->theJsonNodeShouldExist('a string node')) + + ->exception(function () { + $this->testedInstance->theJsonNodeShouldExist('invalid key'); + }) + ->hasMessage("The node 'invalid key' does not exist.") + ; + } +}