Skip to content

Commit

Permalink
[feature] add Json::assertMatchesSchema() (#102)
Browse files Browse the repository at this point in the history
  • Loading branch information
nikophil committed Aug 26, 2022
1 parent 1466827 commit 29171b7
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 1 deletion.
5 changes: 5 additions & 0 deletions composer.json
Expand Up @@ -24,6 +24,7 @@
},
"require-dev": {
"dbrekelmans/bdi": "^1.0",
"justinrainbow/json-schema": "^5.2",
"mtdowling/jmespath.php": "^2.6",
"phpstan/phpstan": "^1.4",
"phpunit/phpunit": "^9.5",
Expand All @@ -33,6 +34,10 @@
"symfony/security-bundle": "^5.4|^6.0",
"zenstruck/foundry": "^1.17"
},
"suggest": {
"justinrainbow/json-schema": "Json schema validator. Needed to use Json::assertMatchesSchema().",
"mtdowling/jmespath.php": "PHP implementation for JMESPath. Needed to use Json assertions."
},
"config": {
"preferred-install": "dist",
"sort-packages": true
Expand Down
23 changes: 22 additions & 1 deletion src/Browser/Json.php
Expand Up @@ -2,6 +2,7 @@

namespace Zenstruck\Browser;

use JsonSchema\Validator;
use Zenstruck\Assert;
use Zenstruck\Assert\Expectation;

Expand Down Expand Up @@ -97,7 +98,7 @@ public function assertThat(string $selector, callable $assert): self
/**
* @param callable(Json):mixed $assert
*/
public function assertThatEach(string $selector, callable $assert): void
public function assertThatEach(string $selector, callable $assert): self
{
$value = $this->search($selector);

Expand All @@ -110,6 +111,26 @@ public function assertThatEach(string $selector, callable $assert): void
foreach ($value as $item) {
$assert(self::encode($item));
}

return $this;
}

public function assertMatchesSchema(string $jsonSchema): self
{
if (!\class_exists(Validator::class)) {
throw new \LogicException('"justinrainbow/json-schema" is required to check JSON schema (composer require --dev justinrainbow/json-schema".');
}

$validator = new Validator();
$decoded = \json_decode($this->source, null, 512, \JSON_THROW_ON_ERROR);
$validator->validate(
$decoded,
\json_decode($jsonSchema, true, 512, \JSON_THROW_ON_ERROR)
);

Assert::that($validator->isValid())->is(true, (string) \json_encode($validator->getErrors()));

return $this;
}

/**
Expand Down
25 changes: 25 additions & 0 deletions tests/JsonTest.php
Expand Up @@ -137,4 +137,29 @@ public function invalidArrayChildAssertionProvider(): iterable
yield ['{"foo": "bar"}', 'foo', static function(Json $json) {}];
yield ['{"foo": []}', 'foo', static function(Json $json) {}];
}

/** @test */
public function can_match_json_schema(): void
{
(new Json('{"foo1": "bar", "foo2": [1, 2], "foo3": {"bar": "baz"}, "foo4": [{"bar": "baz"}]}'))->assertMatchesSchema(
<<<'JSON'
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"foo1": { "type": "string" },
"foo2": { "type": "array", "items": [ { "type": "integer" }, { "type": "integer" } ] },
"foo3": { "type": "object", "properties": { "bar": { "type": "string" } }, "required": [ "bar" ] },
"foo4": { "type": "array", "items": [ { "type": "object", "properties": { "bar": { "type": "string" } }, "required": [ "bar" ] } ] }
},
"required": [
"foo1",
"foo2",
"foo3",
"foo4"
]
}
JSON
);
}
}

0 comments on commit 29171b7

Please sign in to comment.