Skip to content

Commit 0224153

Browse files
authored
Add demo app tests (#3)
1 parent 7c9f7b3 commit 0224153

File tree

25 files changed

+574
-69
lines changed

25 files changed

+574
-69
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,6 @@ vendor
22
build
33
#A library must not provide a composer.lock file
44
composer.lock
5+
6+
# Demo app excluded dirs
7+
features/demo_app/var/

behat.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ default:
22
suites:
33
default:
44
contexts:
5-
- Tests\Functional\BehatContext\FeatureContext: ~
5+
- Tests\Functional\BehatContext\SymfonyExtensionContext: ~
6+
- Tests\Functional\BehatContext\DemoAppContext: ~

composer.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
"autoload-dev": {
2424
"psr-4": {
2525
"Tests\\": "tests",
26-
"Tests\\Functional\\BehatContext\\": "features/bootstrap"
26+
"Tests\\Functional\\BehatContext\\": "features/bootstrap",
27+
"DemoApp\\": "features/demo_app/src"
2728
}
2829
},
2930
"require": {
@@ -37,6 +38,9 @@
3738
"behat/behat": "~3.0",
3839
"squizlabs/php_codesniffer": "3.*",
3940
"phpunit/phpunit": "^6.0 || ^7.0",
40-
"matthiasnoback/symfony-dependency-injection-test": "^2.0 || ^3.0"
41+
"matthiasnoback/symfony-dependency-injection-test": "^2.0 || ^3.0",
42+
"symfony/framework-bundle": "^3.4",
43+
"symfony/http-kernel": "^3.4",
44+
"symfony/routing": "^3.4"
4145
}
4246
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
namespace Tests\Functional\BehatContext;
3+
4+
use Behat\Behat\Context\Context;
5+
use Behat\Gherkin\Node\PyStringNode;
6+
use DemoApp\BaseKernel;
7+
use DemoApp\DefaultKernel;
8+
use DemoApp\KernelWithCustomResolver;
9+
use PHPUnit\Framework\Assert;
10+
use Symfony\Component\HttpFoundation\Request;
11+
use Symfony\Component\HttpFoundation\Response;
12+
13+
/**
14+
* Defines application features from the specific context.
15+
*/
16+
class DemoAppContext implements Context
17+
{
18+
/** @var Response|null */
19+
private $lastResponse;
20+
/** @var bool */
21+
private $useCustomResolver = false;
22+
23+
/**
24+
* @Given I use my DemoApp custom method resolver
25+
*/
26+
public function givenIUseMyDemoAppCustomMethodResolve()
27+
{
28+
$this->useCustomResolver = true;
29+
}
30+
31+
/**
32+
* @When I send following :httpMethod input on :uri demoApp kernel endpoint:
33+
*/
34+
public function whenISendFollowingPayloadToDemoApp($httpMethod, $uri, PyStringNode $payload)
35+
{
36+
$this->lastResponse = null;
37+
38+
$kernel = $this->getDemoAppKernel();
39+
$kernel->boot();
40+
$this->lastResponse = $kernel->handle(
41+
Request::create($uri, $httpMethod, [], [], [], [], $payload->getRaw())
42+
);
43+
}
44+
45+
/**
46+
* @Then I should have a :httpCode response from demoApp with following content:
47+
*/
48+
public function thenIShouldHaveAResponseFromDemoAppWithFollowingContent($httpCode, PyStringNode $payload)
49+
{
50+
Assert::assertInstanceOf(Response::class, $this->lastResponse);
51+
// Decode payload to get ride of indentation, spacing, etc
52+
Assert::assertEquals(
53+
json_decode($payload->getRaw(), true),
54+
json_decode($this->lastResponse->getContent(), true)
55+
);
56+
Assert::assertSame((int) $httpCode, $this->lastResponse->getStatusCode());
57+
}
58+
59+
/**
60+
* @return BaseKernel
61+
*/
62+
protected function getDemoAppKernel()
63+
{
64+
if (true === $this->useCustomResolver) {
65+
return new KernelWithCustomResolver('prod', true);
66+
}
67+
68+
return new DefaultKernel('prod', true);
69+
}
70+
}

features/bootstrap/FeatureContext.php renamed to features/bootstrap/SymfonyExtensionContext.php

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,23 @@
44
use Behat\Behat\Context\Context;
55
use Behat\Gherkin\Node\PyStringNode;
66
use Behat\Gherkin\Node\TableNode;
7+
use DemoApp\Method\MethodB;
8+
use DemoApp\Resolver\JsonRpcMethodResolver;
79
use PHPUnit\Framework\Assert;
810
use Prophecy\Argument;
911
use Prophecy\Prophet;
1012
use Symfony\Component\DependencyInjection\ContainerBuilder;
1113
use Symfony\Component\DependencyInjection\Definition;
1214
use Symfony\Component\HttpFoundation\Request;
13-
use Tests\Functional\BehatContext\App\CustomMethodResolver;
14-
use Tests\Functional\BehatContext\App\JsonRpcMethod;
15+
use Yoanm\JsonRpcServer\Domain\Model\JsonRpcMethodInterface;
1516
use Yoanm\JsonRpcServer\Infra\Endpoint\JsonRpcEndpoint;
1617
use Yoanm\SymfonyJsonRpcHttpServer\Infra\Endpoint\JsonRpcHttpEndpoint;
1718
use Yoanm\SymfonyJsonRpcHttpServer\Infra\Symfony\DependencyInjection\JsonRpcHttpServerExtension;
1819

1920
/**
2021
* Defines application features from the specific context.
2122
*/
22-
class FeatureContext implements Context
23+
class SymfonyExtensionContext implements Context
2324
{
2425
const CUSTOM_METHOD_RESOLVER_SERVICE_ID = 'custom-method-resolver-service';
2526

@@ -41,14 +42,15 @@ class FeatureContext implements Context
4142
public function __construct()
4243
{
4344
$this->prophet = new Prophet();
45+
$this->extension = new JsonRpcHttpServerExtension();
4446
}
4547

4648
/**
4749
* @Given I process the symfony extension
4850
*/
4951
public function givenIProcessTheSymfonyExtension()
5052
{
51-
(new JsonRpcHttpServerExtension())->load([], $this->getContainerBuilder());
53+
$this->extension->load([], $this->getContainerBuilder());
5254
}
5355

5456
/**
@@ -116,6 +118,7 @@ public function givenITagMyJsonRpcMethodServiceWithTagAndFollowingAttributes(
116118
*/
117119
public function whenILoadEndpointFromService($serviceId)
118120
{
121+
$this->extension->process($this->getContainerBuilder());
119122
$this->getContainerBuilder()->compile();
120123
$this->endpoint = $this->getContainerBuilder()->get($serviceId);
121124
}
@@ -152,7 +155,7 @@ private function assertEndpointRespondToCalls(JsonRpcHttpEndpoint $endpoint, arr
152155
[
153156
'jsonrpc' => '2.0',
154157
'id' => $requestId,
155-
'result' => 'OK'
158+
'result' => 'MethodB'
156159
]
157160
),
158161
$endpoint->index($request)->getContent()
@@ -161,19 +164,19 @@ private function assertEndpointRespondToCalls(JsonRpcHttpEndpoint $endpoint, arr
161164
}
162165

163166
/**
164-
* @return JsonRpcMethod
167+
* @return JsonRpcMethodInterface
165168
*/
166169
private function createJsonRpcMethod()
167170
{
168-
return new JsonRpcMethod();
171+
return new MethodB();
169172
}
170173

171174
/**
172175
* @return Definition
173176
*/
174177
private function createJsonRpcMethodDefinition()
175178
{
176-
return (new Definition(JsonRpcMethod::class))->setPrivate(false);
179+
return (new Definition(MethodB::class))->setPrivate(false);
177180
}
178181

179182
/**
@@ -196,8 +199,8 @@ private function injectJsonRpcMethodToDefaultResolverService($methodName, $metho
196199
}
197200

198201
/**
199-
* @param string $methodName
200-
* @param JsonRpcMethod|Definition $method
202+
* @param string $methodName
203+
* @param JsonRpcMethodInterface|Definition $method
201204
*/
202205
private function injectJsonRpcMethodToCustomResolverService($methodName, $method)
203206
{
@@ -221,7 +224,7 @@ private function getContainerBuilder()
221224
if (!$this->containerBuilder) {
222225
$this->containerBuilder = new ContainerBuilder();
223226
// Add definition of custom resolver (without tags)
224-
$customResolverDefinition = (new Definition(CustomMethodResolver::class))->setPrivate(false);
227+
$customResolverDefinition = (new Definition(JsonRpcMethodResolver::class))->setPublic(true);
225228
$this->containerBuilder->setDefinition(self::CUSTOM_METHOD_RESOLVER_SERVICE_ID, $customResolverDefinition);
226229
}
227230
return $this->containerBuilder;

features/demo-app.feature

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
Feature: demo symfony application
2+
3+
Scenario: Default method resolver with JSON-RPC method tags
4+
# Ensure the two methods with tag have been loaded
5+
When I send following "POST" input on "/my-json-rpc-endpoint" demoApp kernel endpoint:
6+
"""
7+
{"jsonrpc": "2.0", "method": "methodA", "id": 1}
8+
"""
9+
Then I should have a "200" response from demoApp with following content:
10+
"""
11+
{"jsonrpc":"2.0", "result":"MethodA", "id":1}
12+
"""
13+
When I send following "POST" input on "/my-json-rpc-endpoint" demoApp kernel endpoint:
14+
"""
15+
{"jsonrpc": "2.0", "method": "MethodB", "id": 2}
16+
"""
17+
Then I should have a "200" response from demoApp with following content:
18+
"""
19+
{"jsonrpc":"2.0", "result":"MethodB", "id":2}
20+
"""
21+
22+
Scenario: Default method resolver with JSON-RPC methods container injection
23+
# Ensure the two injected methods have been loaded
24+
When I send following "POST" input on "/my-json-rpc-endpoint" demoApp kernel endpoint:
25+
"""
26+
{"jsonrpc": "2.0", "method": "getDummy", "id": 3}
27+
"""
28+
Then I should have a "200" response from demoApp with following content:
29+
"""
30+
{"jsonrpc":"2.0", "result":"MethodC", "id":3}
31+
"""
32+
When I send following "POST" input on "/my-json-rpc-endpoint" demoApp kernel endpoint:
33+
"""
34+
{"jsonrpc": "2.0", "method": "getAnotherDummy", "id": 4}
35+
"""
36+
Then I should have a "200" response from demoApp with following content:
37+
"""
38+
{"jsonrpc":"2.0", "result":"MethodD", "id":4}
39+
"""
40+
41+
Scenario: custom method resolver
42+
Given I use my DemoApp custom method resolver
43+
# Ensure all methods have been loaded
44+
When I send following "POST" input on "/my-json-rpc-endpoint" demoApp kernel endpoint:
45+
"""
46+
{"jsonrpc": "2.0", "method": "custom_methodA", "id": 1}
47+
"""
48+
Then I should have a "200" response from demoApp with following content:
49+
"""
50+
{"jsonrpc":"2.0", "result":"MethodA", "id":1}
51+
"""
52+
When I send following "POST" input on "/my-json-rpc-endpoint" demoApp kernel endpoint:
53+
"""
54+
{"jsonrpc": "2.0", "method": "custom_methodB", "id": 2}
55+
"""
56+
Then I should have a "200" response from demoApp with following content:
57+
"""
58+
{"jsonrpc":"2.0", "result":"MethodB", "id":2}
59+
"""
60+
When I send following "POST" input on "/my-json-rpc-endpoint" demoApp kernel endpoint:
61+
"""
62+
{"jsonrpc": "2.0", "method": "custom_methodC", "id": 3}
63+
"""
64+
Then I should have a "200" response from demoApp with following content:
65+
"""
66+
{"jsonrpc":"2.0", "result":"MethodC", "id":3}
67+
"""
68+
When I send following "POST" input on "/my-json-rpc-endpoint" demoApp kernel endpoint:
69+
"""
70+
{"jsonrpc": "2.0", "method": "custom_methodD", "id": 4}
71+
"""
72+
Then I should have a "200" response from demoApp with following content:
73+
"""
74+
{"jsonrpc":"2.0", "result":"MethodD", "id":4}
75+
"""
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?php
2+
return [
3+
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
4+
];
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
framework:
2+
secret: '%env(APP_SECRET)%'
3+
4+
yoanm_jsonrpc_http_server: ~
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Configure your resolver and add the required tag
2+
services:
3+
jsonrpc.custom_method_resolver:
4+
class: Tests\Common\Infra\Symfony\DependencyInjection\CustomMethodResolverClass
5+
tags: ['yoanm.jsonrpc_http_server.method_resolver']
6+
7+
# Inject your JSON-RPC methods (They cannot be automatically injected as resolver implementation is on your own)
8+
calls:
9+
- method: 'addMethod'
10+
arguments:
11+
- '@jsonrpc.method.a'
12+
- 'custom_methodA'
13+
- method: 'addMethod'
14+
arguments:
15+
- '@jsonrpc.method.b'
16+
- 'custom_methodB'
17+
- method: 'addMethod'
18+
arguments:
19+
- '@jsonrpc.method.c'
20+
- 'custom_methodC'
21+
- method: 'addMethod'
22+
arguments:
23+
- '@jsonrpc.method.d'
24+
- 'custom_methodD'
25+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Configure the HTTP JSON-RPC endpoint on any path
2+
# And configure the controller
3+
homepage:
4+
path: /my-json-rpc-endpoint
5+
defaults: { _controller: 'yoanm.jsonrpc_http_server.endpoint:index' }

0 commit comments

Comments
 (0)