-
-
Notifications
You must be signed in to change notification settings - Fork 906
Add JSON API basic support #1036
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
58bcfb4
7b8bd74
fc8d0a8
b9da3aa
ddc38d1
1b04cda
5d9846a
3bae015
7e2582a
6b21d46
e1d467b
1421971
27a133b
e2eaa3b
b1c05d8
e3e0cee
f2cc39c
ca3f390
6051c5c
d9e4f8f
42eeb19
cc12778
43754f3
0bb3b69
88d7c3a
9262a63
f894146
df5d978
8200134
3506b30
a755f72
2089a57
25445f0
7e178cf
2f530ef
042b1d0
c61fcee
545b191
5a46e42
db6da8c
ca5916c
4900b15
01dbe8e
9ad63c1
a4fd58c
77d34e6
59e0716
33b6eb0
858f4ac
39955cb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the API Platform project. | ||
* | ||
* (c) Kévin Dunglas <dunglas@gmail.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\DummyFriend; | ||
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\RelatedDummy; | ||
use Behat\Behat\Context\Context; | ||
use Behat\Behat\Context\Environment\InitializedContextEnvironment; | ||
use Behat\Behat\Hook\Scope\BeforeScenarioScope; | ||
use Behatch\Context\RestContext; | ||
use Behatch\Json\Json; | ||
use Behatch\Json\JsonInspector; | ||
use Doctrine\Common\Persistence\ManagerRegistry; | ||
|
||
final class JsonApiContext implements Context | ||
{ | ||
private $restContext; | ||
|
||
private $inspector; | ||
|
||
private $doctrine; | ||
|
||
/** | ||
* @var \Doctrine\Common\Persistence\ObjectManager | ||
*/ | ||
private $manager; | ||
|
||
public function __construct(ManagerRegistry $doctrine) | ||
{ | ||
$this->doctrine = $doctrine; | ||
$this->manager = $doctrine->getManager(); | ||
} | ||
|
||
/** | ||
* Gives access to the Behatch context. | ||
* | ||
* @param BeforeScenarioScope $scope | ||
* | ||
* @BeforeScenario | ||
*/ | ||
public function gatherContexts(BeforeScenarioScope $scope) | ||
{ | ||
/** @var InitializedContextEnvironment $environment */ | ||
$environment = $scope->getEnvironment(); | ||
|
||
$this->restContext = $environment->getContext(RestContext::class); | ||
|
||
$this->inspector = new JsonInspector('javascript'); | ||
} | ||
|
||
/** | ||
* @Then I save the response | ||
*/ | ||
public function iSaveTheResponse() | ||
{ | ||
$content = $this->getContent(); | ||
|
||
if (null === ($decoded = json_decode($content))) { | ||
throw new \RuntimeException('JSON response seems to be invalid'); | ||
} | ||
|
||
$fileName = __DIR__.'/response.json'; | ||
|
||
file_put_contents($fileName, $content); | ||
|
||
return $fileName; | ||
} | ||
|
||
/** | ||
* @Then I validate it with jsonapi-validator | ||
*/ | ||
public function iValidateItWithJsonapiValidator() | ||
{ | ||
$fileName = $this->iSaveTheResponse(); | ||
|
||
$validationResponse = exec(sprintf('cd %s && jsonapi-validator -f response.json', __DIR__)); | ||
|
||
$isValidJsonapi = 'response.json is valid JSON API.' === $validationResponse; | ||
|
||
unlink($fileName); | ||
|
||
if (!$isValidJsonapi) { | ||
throw new \RuntimeException('JSON response seems to be invalid JSON API'); | ||
} | ||
} | ||
|
||
/** | ||
* Checks that given JSON node is equal to an empty array. | ||
* | ||
* @Then the JSON node :node should be an empty array | ||
*/ | ||
public function theJsonNodeShouldBeAnEmptyArray($node) | ||
{ | ||
$actual = $this->getValueOfNode($node); | ||
|
||
if (!is_array($actual) || !empty($actual)) { | ||
throw new \Exception( | ||
sprintf("The node value is '%s'", json_encode($actual)) | ||
); | ||
} | ||
} | ||
|
||
/** | ||
* Checks that given JSON node is a number. | ||
* | ||
* @Then the JSON node :node should be a number | ||
*/ | ||
public function theJsonNodeShouldBeANumber($node) | ||
{ | ||
$actual = $this->getValueOfNode($node); | ||
|
||
if (!is_numeric($actual)) { | ||
throw new \Exception( | ||
sprintf('The node value is `%s`', json_encode($actual)) | ||
); | ||
} | ||
} | ||
|
||
/** | ||
* Checks that given JSON node is not an empty string. | ||
* | ||
* @Then the JSON node :node should not be an empty string | ||
*/ | ||
public function theJsonNodeShouldNotBeAnEmptyString($node) | ||
{ | ||
$actual = $this->getValueOfNode($node); | ||
|
||
if ($actual === '') { | ||
throw new \Exception( | ||
sprintf('The node value is `%s`', json_encode($actual)) | ||
); | ||
} | ||
} | ||
|
||
private function getValueOfNode($node) | ||
{ | ||
$json = $this->getJson(); | ||
|
||
return $this->inspector->evaluate($json, $node); | ||
} | ||
|
||
private function getJson() | ||
{ | ||
return new Json($this->getContent()); | ||
} | ||
|
||
private function getContent() | ||
{ | ||
return $this->restContext->getMink()->getSession()->getDriver()->getContent(); | ||
} | ||
|
||
/** | ||
* @Given there is a RelatedDummy | ||
*/ | ||
public function thereIsARelatedDummy() | ||
{ | ||
$relatedDummy = new RelatedDummy(); | ||
|
||
$relatedDummy->setName('RelatedDummy with no friends'); | ||
|
||
$this->manager->persist($relatedDummy); | ||
|
||
$this->manager->flush(); | ||
} | ||
|
||
/** | ||
* @Given there is a DummyFriend | ||
*/ | ||
public function thereIsADummyFriend() | ||
{ | ||
$friend = new DummyFriend(); | ||
|
||
$friend->setName('DummyFriend'); | ||
|
||
$this->manager->persist($friend); | ||
|
||
$this->manager->flush(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,11 +5,12 @@ Feature: NelmioApiDoc integration | |
|
||
Scenario: Create a user | ||
When I send a "GET" request to "/nelmioapidoc" | ||
Then the response status code should be 200 | ||
And the response status code should be 200 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why this change? |
||
And I should see text matching "AbstractDummy" | ||
And I should see text matching "Dummy" | ||
And I should see text matching "User" | ||
And I should see text matching "Retrieves the collection of Dummy resources." | ||
And I should see text matching "Creates a Dummy resource." | ||
And I should see text matching "Deletes the Dummy resource." | ||
And I should see text matching "Updates the Dummy resource." | ||
And I should see text matching "Replaces the Dummy resource." |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
Feature: JSON API collections support | ||
In order to use the JSON API hypermedia format | ||
As a client software developer | ||
I need to be able to retrieve valid JSON API responses for collection attributes on entities. | ||
|
||
@createSchema | ||
@dropSchema | ||
Scenario: Correctly serialize a collection | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Your scenario isn't correct. You have to divide it into several scenarios, with one for each operation. Each scenario consist of a list of steps: Givens, Whens, Thens. In your scenario here, there is only a list of Whens, no Thens, it's a little insane. |
||
When I add "Accept" header equal to "application/vnd.api+json" | ||
And I add "Content-Type" header equal to "application/vnd.api+json" | ||
Then I send a "POST" request to "/circular_references" with body: | ||
""" | ||
{ | ||
"data": {} | ||
} | ||
""" | ||
And I validate it with jsonapi-validator | ||
And I send a "PATCH" request to "/circular_references/1" with body: | ||
""" | ||
{ | ||
"data": { | ||
"relationships": { | ||
"parent": { | ||
"data": { | ||
"type": "CircularReference", | ||
"id": "1" | ||
} | ||
} | ||
} | ||
} | ||
} | ||
""" | ||
And I validate it with jsonapi-validator | ||
And I send a "POST" request to "/circular_references" with body: | ||
""" | ||
{ | ||
"data": { | ||
"relationships": { | ||
"parent": { | ||
"data": { | ||
"type": "CircularReference", | ||
"id": "1" | ||
} | ||
} | ||
} | ||
} | ||
} | ||
""" | ||
And I validate it with jsonapi-validator | ||
And I send a "GET" request to "/circular_references/1" | ||
And the JSON should be equal to: | ||
""" | ||
{ | ||
"data": { | ||
"id": "1", | ||
"type": "CircularReference", | ||
"relationships": { | ||
"parent": { | ||
"data": { | ||
"type": "CircularReference", | ||
"id": "1" | ||
} | ||
}, | ||
"children": { | ||
"data": [ | ||
{ | ||
"type": "CircularReference", | ||
"id": "1" | ||
}, | ||
{ | ||
"type": "CircularReference", | ||
"id": "2" | ||
} | ||
] | ||
} | ||
} | ||
} | ||
} | ||
""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I repost my comment from #785 (comment) here, I'm really not a fan of this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. It should be done in Travis directly. No need to run the command from PHP.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dunglas, my suggestion was to use
\Sanpi\Behatch\Json\JsonInspector::validate()
and not to run any command in Travis or PHP! 😛There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep I agree with @meyerbaptiste didn't had the time to do it but we should do that