Skip to content

Commit

Permalink
Merge 33b6eb0 into f73309c
Browse files Browse the repository at this point in the history
  • Loading branch information
hectorh30 committed Apr 25, 2017
2 parents f73309c + 33b6eb0 commit 952f6c9
Show file tree
Hide file tree
Showing 47 changed files with 2,729 additions and 31 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Expand Up @@ -18,7 +18,9 @@ matrix:
before_install:
- phpenv config-rm xdebug.ini || echo "xdebug not available"
- echo "memory_limit=-1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
- rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install 6.10.2
- npm install -g swagger-cli
- npm install -g jsonapi-validator
- if [[ $coverage = 1 ]]; then mkdir -p build/logs build/cov; fi
- if [[ $coverage = 1 ]]; then wget https://phar.phpunit.de/phpcov.phar; fi
- if [[ $coverage = 1 ]]; then wget https://github.com/satooshi/php-coveralls/releases/download/v1.0.1/coveralls.phar; fi
Expand Down
5 changes: 5 additions & 0 deletions appveyor.yml
Expand Up @@ -2,13 +2,18 @@ build: false
platform: x86
clone_folder: c:\projects\api-platform\core

environment:
nodejs_version: "6"

cache:
- '%LOCALAPPDATA%\Composer\files'

init:
- SET PATH=c:\tools\php71;%PATH%

install:
- ps: Install-Product node $env:nodejs_version
- npm install -g jsonapi-validator
- ps: Set-Service wuauserv -StartupType Manual
- cinst -y php
- cd c:\tools\php71
Expand Down
1 change: 1 addition & 0 deletions behat.yml.dist
Expand Up @@ -5,6 +5,7 @@ default:
- 'FeatureContext': { doctrine: '@doctrine' }
- 'HydraContext'
- 'SwaggerContext'
- 'JsonApiContext': { doctrine: '@doctrine' }
- 'Behat\MinkExtension\Context\MinkContext'
- 'Behatch\Context\RestContext'
- 'Behatch\Context\JsonContext'
Expand Down
188 changes: 188 additions & 0 deletions features/bootstrap/JsonApiContext.php
@@ -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 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();
}
}
8 changes: 7 additions & 1 deletion features/doctrine/date_filter.feature
Expand Up @@ -407,7 +407,7 @@ Feature: Date filter on collections
},
"hydra:search": {
"@type": "hydra:IriTemplate",
"hydra:template": "\/dummies{?id,id[],name,alias,description,relatedDummy.name,relatedDummy.name[],relatedDummies,relatedDummies[],dummy,relatedDummies.name,order[id],order[name],order[relatedDummy.symfony],dummyDate[before],dummyDate[after],relatedDummy.dummyDate[before],relatedDummy.dummyDate[after],dummyFloat[between],dummyFloat[gt],dummyFloat[gte],dummyFloat[lt],dummyFloat[lte],dummyPrice[between],dummyPrice[gt],dummyPrice[gte],dummyPrice[lt],dummyPrice[lte],dummyBoolean,dummyFloat,dummyPrice,description[exists],relatedDummy.name[exists],dummyBoolean[exists]}",
"hydra:template": "\/dummies{?id,id[],name,alias,description,relatedDummy.name,relatedDummy.name[],relatedDummies,relatedDummies[],dummy,relatedDummies.name,order[id],order[name],order[description],order[relatedDummy.symfony],dummyDate[before],dummyDate[after],relatedDummy.dummyDate[before],relatedDummy.dummyDate[after],dummyFloat[between],dummyFloat[gt],dummyFloat[gte],dummyFloat[lt],dummyFloat[lte],dummyPrice[between],dummyPrice[gt],dummyPrice[gte],dummyPrice[lt],dummyPrice[lte],dummyBoolean,dummyFloat,dummyPrice,description[exists],relatedDummy.name[exists],dummyBoolean[exists]}",
"hydra:variableRepresentation": "BasicRepresentation",
"hydra:mapping": [
{
Expand Down Expand Up @@ -488,6 +488,12 @@ Feature: Date filter on collections
"property": "name",
"required": false
},
{
"@type": "IriTemplateMapping",
"variable": "order[description]",
"property": "description",
"required": false
},
{
"@type": "IriTemplateMapping",
"variable": "order[relatedDummy.symfony]",
Expand Down
3 changes: 2 additions & 1 deletion features/integration/nelmio_api_doc.feature
Expand Up @@ -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
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."
79 changes: 79 additions & 0 deletions features/jsonapi/collections.feature
@@ -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
When I add "Accept" header equal to "application/vnd.api+json"
And I add "Content-Type" header equal to "application/vnd.api+json"
And 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"
}
]
}
}
}
}
"""

0 comments on commit 952f6c9

Please sign in to comment.