Skip to content

Commit 0676174

Browse files
authored
Add JsonRpcParamsValidator (#4)
1 parent 56e5529 commit 0676174

File tree

5 files changed

+192
-13
lines changed

5 files changed

+192
-13
lines changed

composer.json

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,13 @@
3030
"symfony/validator": "^3.0 || ^4.0"
3131
},
3232
"suggest": {
33-
"yoanm/jsonrpc-server-doc-sdk": "To generate payload documentation from validation constraints",
33+
"yoanm/jsonrpc-params-symfony-constraint-doc-sdk": "To generate payload documentation from validation constraints",
3434
"yoanm/symfony-jsonrpc-server-doc": "For automatic payload documentation"
3535
},
3636
"require-dev": {
3737
"behat/behat": "~3.0",
3838
"squizlabs/php_codesniffer": "3.*",
3939
"phpunit/phpunit": "^6.0 || ^7.0",
40-
"matthiasnoback/symfony-dependency-injection-test": "^2.0 || ^3.0",
41-
"matthiasnoback/symfony-config-test": "^3.0 || ^4.0",
42-
"symfony/framework-bundle": "^3.4",
43-
"symfony/http-kernel": "^3.4",
44-
"symfony/routing": "^3.4",
45-
"yoanm/php-unit-extended": "~1.0",
46-
"yoanm/jsonrpc-server-doc-sdk": "dev-release/1.0.0"
47-
},
48-
"minimum-stability": "dev"
40+
"yoanm/php-unit-extended": "^1.0"
41+
}
4942
}

phpunit.xml.dist

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,17 @@
2727
forceCoversAnnotation="true"
2828

2929
bootstrap="vendor/autoload.php"
30-
>
30+
>
3131
<listeners>
3232
<listener class="Yoanm\PhpUnitExtended\Listener\YoanmTestsStrategyListener"/>
3333
</listeners>
3434

3535
<testsuites>
3636
<testsuite name="functional">
37-
<directory>tests/Functional</directory>
37+
<directory>tests/Functional/*</directory>
3838
</testsuite>
3939
<testsuite name="technical">
40-
<directory>tests/Technical</directory>
40+
<directory>tests/Technical/*</directory>
4141
</testsuite>
4242
</testsuites>
4343

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
namespace Yoanm\JsonRpcParamsSymfonyValidator\Domain\Model;
3+
4+
use Symfony\Component\Validator\Constraint;
5+
6+
/**
7+
* Interface MethodWithValidatedParams
8+
*/
9+
interface MethodWithValidatedParams
10+
{
11+
/**
12+
* @return Constraint Usually a Collection constraint
13+
*/
14+
public function getParamsConstraint() : Constraint;
15+
}

src/Infra/JsonRpcParamsValidator.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
namespace Yoanm\JsonRpcParamsSymfonyValidator\Infra;
3+
4+
use Symfony\Component\Validator\ConstraintViolationInterface;
5+
use Symfony\Component\Validator\Validator\ValidatorInterface;
6+
use Yoanm\JsonRpcParamsSymfonyValidator\Domain\Model\MethodWithValidatedParams;
7+
use Yoanm\JsonRpcServer\Domain\Event\Action\ValidateParamsEvent;
8+
9+
/**
10+
* Class JsonRpcParamsValidator
11+
*/
12+
class JsonRpcParamsValidator
13+
{
14+
/** @var ValidatorInterface */
15+
private $validator;
16+
17+
/**
18+
* @param ValidatorInterface $validator
19+
*/
20+
public function __construct(ValidatorInterface $validator)
21+
{
22+
$this->validator = $validator;
23+
}
24+
25+
/**
26+
* @param ValidateParamsEvent $event
27+
*/
28+
public function validate(ValidateParamsEvent $event)
29+
{
30+
$method = $event->getMethod();
31+
if (!$method instanceof MethodWithValidatedParams) {
32+
return;
33+
}
34+
foreach ($this->validator->validate($event->getParamList(), $method->getParamsConstraint()) as $violation) {
35+
/** @var ConstraintViolationInterface $violation */
36+
$event->addViolation([
37+
'path' => $violation->getPropertyPath(),
38+
'message' => $violation->getMessage(),
39+
'code' => $violation->getCode(),
40+
]);
41+
}
42+
}
43+
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<?php
2+
namespace Tests\Functional\Infra;
3+
4+
use PHPUnit\Framework\TestCase;
5+
use Prophecy\Prophecy\ObjectProphecy;
6+
use Symfony\Component\Validator\Constraints\Collection;
7+
use Symfony\Component\Validator\ConstraintViolationInterface;
8+
use Symfony\Component\Validator\Validator\ValidatorInterface;
9+
use Yoanm\JsonRpcParamsSymfonyValidator\Domain\Model\MethodWithValidatedParams;
10+
use Yoanm\JsonRpcParamsSymfonyValidator\Infra\JsonRpcParamsValidator;
11+
use Yoanm\JsonRpcServer\Domain\Event\Action\ValidateParamsEvent;
12+
use Yoanm\JsonRpcServer\Domain\JsonRpcMethodInterface;
13+
14+
/**
15+
* @covers \Yoanm\JsonRpcParamsSymfonyValidator\Infra\JsonRpcParamsValidator
16+
*
17+
* @group Validator
18+
*/
19+
class JsonRpcParamsValidatorTest extends TestCase
20+
{
21+
/** @var JsonRpcParamsValidator */
22+
private $validator;
23+
/** @var ValidatorInterface|ObjectProphecy */
24+
private $sfValidator;
25+
26+
public function setUp()
27+
{
28+
$this->sfValidator = $this->prophesize(ValidatorInterface::class);
29+
30+
$this->validator = new JsonRpcParamsValidator(
31+
$this->sfValidator->reveal()
32+
);
33+
}
34+
35+
public function testShouldDoNothingIfMethodDoesNotImplementSpecificInterface()
36+
{
37+
$paramList = ['paramList'];
38+
/** @var JsonRpcMethodInterface|ObjectProphecy $method */
39+
$method = $this->prophesize(JsonRpcMethodInterface::class);
40+
$event = new ValidateParamsEvent($method->reveal(), $paramList);
41+
42+
$this->validator->validate($event);
43+
$this->assertCount(0, $event->getViolationList());
44+
}
45+
46+
public function testSshouldCallSfValidator()
47+
{
48+
$paramList = ['paramList'];
49+
/** @var MethodWithValidatedParams|JsonRpcMethodInterface|ObjectProphecy $method */
50+
$method = $this->prophesize(MethodWithValidatedParams::class);
51+
$method->willImplement(JsonRpcMethodInterface::class);
52+
/** @var Collection|ObjectProphecy $paramConstraint */
53+
$paramConstraint = $this->prophesize(Collection::class);
54+
$event = new ValidateParamsEvent($method->reveal(), $paramList);
55+
56+
$method->getParamsConstraint()
57+
->willReturn($paramConstraint->reveal())
58+
->shouldBeCalled()
59+
;
60+
61+
$this->sfValidator->validate($paramList, $paramConstraint->reveal())
62+
->willReturn([])
63+
->shouldBeCalled()
64+
;
65+
66+
$this->validator->validate($event);
67+
$this->assertCount(0, $event->getViolationList());
68+
}
69+
70+
public function testShouldNormalizeViolations()
71+
{
72+
$paramList = ['paramList'];
73+
/** @var MethodWithValidatedParams|JsonRpcMethodInterface|ObjectProphecy $method */
74+
$method = $this->prophesize(MethodWithValidatedParams::class);
75+
$method->willImplement(JsonRpcMethodInterface::class);
76+
/** @var Collection|ObjectProphecy $paramConstraint */
77+
$paramConstraint = $this->prophesize(Collection::class);
78+
/** @var ConstraintViolationInterface|ObjectProphecy $violation1 */
79+
$violation1 = $this->prophesize(ConstraintViolationInterface::class);
80+
/** @var ConstraintViolationInterface|ObjectProphecy $violation2 */
81+
$violation2 = $this->prophesize(ConstraintViolationInterface::class);
82+
/** @var ConstraintViolationInterface|ObjectProphecy $violation3 */
83+
$violation3 = $this->prophesize(ConstraintViolationInterface::class);
84+
$violationList = [$violation1->reveal(), $violation2->reveal(), $violation3->reveal()];
85+
$expectedNormalizedErrorList = [
86+
[
87+
'path' => 'path1',
88+
'message' => 'message1',
89+
'code' => 'code1',
90+
],
91+
[
92+
'path' => 'path2',
93+
'message' => 'message2',
94+
'code' => 'code2',
95+
],
96+
[
97+
'path' => 'path3',
98+
'message' => 'message3',
99+
'code' => 'code3',
100+
]
101+
];
102+
$violation1->getPropertyPath()->willReturn($expectedNormalizedErrorList[0]['path'])->shouldBeCalled();
103+
$violation1->getMessage()->willReturn($expectedNormalizedErrorList[0]['message'])->shouldBeCalled();
104+
$violation1->getCode()->willReturn($expectedNormalizedErrorList[0]['code'])->shouldBeCalled();
105+
$violation2->getPropertyPath()->willReturn($expectedNormalizedErrorList[1]['path'])->shouldBeCalled();
106+
$violation2->getMessage()->willReturn($expectedNormalizedErrorList[1]['message'])->shouldBeCalled();
107+
$violation2->getCode()->willReturn($expectedNormalizedErrorList[1]['code'])->shouldBeCalled();
108+
$violation3->getPropertyPath()->willReturn($expectedNormalizedErrorList[2]['path'])->shouldBeCalled();
109+
$violation3->getMessage()->willReturn($expectedNormalizedErrorList[2]['message'])->shouldBeCalled();
110+
$violation3->getCode()->willReturn($expectedNormalizedErrorList[2]['code'])->shouldBeCalled();
111+
112+
$event = new ValidateParamsEvent($method->reveal(), $paramList);
113+
114+
$method->getParamsConstraint()
115+
->willReturn($paramConstraint->reveal())
116+
->shouldBeCalled()
117+
;
118+
119+
$this->sfValidator->validate($paramList, $paramConstraint->reveal())
120+
->willReturn($violationList)
121+
->shouldBeCalled()
122+
;
123+
124+
$this->validator->validate($event);
125+
126+
$this->assertSame($expectedNormalizedErrorList, $event->getViolationList());
127+
}
128+
}

0 commit comments

Comments
 (0)