Skip to content

Merge 2.4 #2704

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

Merged
merged 22 commits into from
Apr 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
e74ce08
Metadata: Attributes default value should be null not an empty array
soyuka Apr 3, 2019
a20bb89
Merge pull request #2685 from soyuka/fix-attributes-override-2
soyuka Apr 5, 2019
70a43a8
ApiResource attributes default value to null
soyuka Apr 5, 2019
5272e3d
Merge pull request #2695 from soyuka/fix-attributes-override
teohhanhui Apr 5, 2019
2bb4db1
Normalize non-resource objects in a standalone normalizer
teohhanhui Apr 2, 2019
521fa98
Add a regression test for api-platform/api-platform#1085
soyuka Apr 4, 2019
b7afbf8
Merge pull request #2679 from teohhanhui/fix/normalize-non-resource
soyuka Apr 6, 2019
ec376e2
Add a nonNull wrapper around input objets (#2696)
alanpoulain Apr 6, 2019
8029b86
Add Behat test for PR #2183
ilicmsreten Sep 4, 2018
9eafd71
Merge pull request #2188 from ilicmsreten/add-behat-test-for-PR-2183
soyuka Apr 6, 2019
e4d701e
Add support for ignore property exist test for interface
Nek- Jul 10, 2018
e05809e
Removing id/context keys from interfaces resources
Nek- Apr 6, 2019
e84373d
fix (cache): prevent avoidable purge
GregoireHebert Apr 6, 2019
a228079
fix (cache): cs
GregoireHebert Apr 6, 2019
0aead14
Check that strict types work as expected
teohhanhui Jun 28, 2018
a183b9f
Fixed test
Toflar Apr 6, 2019
5ef88f8
Merge pull request #2086 from Nek-/feature/ignore-property-exist-test…
soyuka Apr 6, 2019
0569e10
Merge pull request #2697 from GregoireHebert/fix-cache-purge
soyuka Apr 6, 2019
6826437
Merge pull request #2699 from Toflar/strict-types
soyuka Apr 6, 2019
d77d61c
Merge branch '2.4' into merge-2.4
soyuka Apr 6, 2019
d5dc43f
MongoDb: as its experimental do not invalid constructor args
soyuka Apr 6, 2019
d442702
fix tests readableLink and graphql
soyuka Apr 7, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ jobs:
mkdir -p build/logs/tmp build/cov
for f in $(find features -name '*.feature' -not -path 'features/main/exposed_state.feature' -not -path 'features/elasticsearch/*' -not -path 'features/mongodb/*' | circleci tests split --split-by=timings); do
_f=${f//\//_}
FEATURE="${_f}" phpdbg -qrr vendor/bin/behat --profile=coverage --suite=default --format=progress --out=std --format=junit --out=build/logs/tmp/"${_f}" "$f"
FEATURE="${_f}" phpdbg -qrr vendor/bin/behat --profile=coverage --suite=default --format=progress --out=std --format=junit --out=build/logs/tmp/"${_f}" --no-interaction "$f"
done
- run:
name: Merge Behat test reports
Expand Down
8 changes: 4 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,13 @@ script:
fi
- tests/Fixtures/app/console cache:clear
- if [[ $APP_ENV = 'postgres' ]]; then
vendor/bin/behat --suite=postgres --format=progress;
vendor/bin/behat --suite=postgres --format=progress --no-interaction;
elif [[ $APP_ENV = 'mongodb' ]]; then
vendor/bin/behat --suite=mongodb --format=progress;
vendor/bin/behat --suite=mongodb --format=progress --no-interaction;
elif [[ $APP_ENV = 'elasticsearch' ]]; then
vendor/bin/behat --suite=elasticsearch --format=progress;
vendor/bin/behat --suite=elasticsearch --format=progress --no-interaction;
else
vendor/bin/behat --suite=default --format=progress;
vendor/bin/behat --suite=default --format=progress --no-interaction;
fi
- tests/Fixtures/app/console api:swagger:export > swagger.json && npx swagger-cli validate swagger.json && rm swagger.json
- tests/Fixtures/app/console api:swagger:export --yaml > swagger.yaml && npx swagger-cli validate swagger.yaml && rm swagger.yaml
Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ services:

test_script:
- cd %APPVEYOR_BUILD_FOLDER%
- php vendor\behat\behat\bin\behat --format=progress --suite=default
- php vendor\behat\behat\bin\behat --format=progress --suite=default --no-interaction
- rmdir tests\Fixtures\app\var\cache /s /q
- php vendor\phpunit\phpunit\phpunit
35 changes: 35 additions & 0 deletions features/bootstrap/DoctrineContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@

declare(strict_types=1);

use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Address as AddressDocument;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Answer as AnswerDocument;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\CompositeItem as CompositeItemDocument;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\CompositeLabel as CompositeLabelDocument;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\CompositePrimitiveItem as CompositePrimitiveItemDocument;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\CompositeRelation as CompositeRelationDocument;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Customer as CustomerDocument;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Dummy as DummyDocument;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\DummyAggregateOffer as DummyAggregateOfferDocument;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\DummyCar as DummyCarDocument;
Expand All @@ -39,6 +41,7 @@
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\FourthLevel as FourthLevelDocument;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Greeting as GreetingDocument;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\MaxDepthDummy as MaxDepthDummyDocument;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Order as OrderDocument;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Person as PersonDocument;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\PersonToPet as PersonToPetDocument;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Pet as PetDocument;
Expand All @@ -52,12 +55,14 @@
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\SoMany as SoManyDocument;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\ThirdLevel as ThirdLevelDocument;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\User as UserDocument;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Address;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Answer;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\CompositeItem;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\CompositeLabel;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\CompositePrimitiveItem;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\CompositeRelation;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Container;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Customer;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\DummyAggregateOffer;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\DummyCar;
Expand All @@ -83,6 +88,7 @@
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Greeting;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\MaxDepthDummy;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Node;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Order;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Person;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\PersonToPet;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Pet;
Expand Down Expand Up @@ -1571,4 +1577,33 @@ private function buildThirdLevel()
{
return $this->isOrm() ? new ThirdLevel() : new ThirdLevelDocument();
}

/**
* @Given there is a order with same customer and receiver
*/
public function testEagerLoadingNotDuplicateRelation()
{
$customer = $this->isOrm() ? new Customer() : new CustomerDocument();
$customer->name = 'customer_name';

$address1 = $this->isOrm() ? new Address() : new AddressDocument();
$address1->name = 'foo';
$address2 = $this->isOrm() ? new Address() : new AddressDocument();
$address2->name = 'bar';

$order = $this->isOrm() ? new Order() : new OrderDocument();
$order->recipient = $customer;
$order->customer = $customer;

$customer->addresses->add($address1);
$customer->addresses->add($address2);

$this->manager->persist($address1);
$this->manager->persist($address2);
$this->manager->persist($customer);
$this->manager->persist($order);

$this->manager->flush();
$this->manager->clear();
}
}
42 changes: 21 additions & 21 deletions features/bootstrap/JsonContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,6 @@ public function __construct(HttpCallResultPool $httpCallResultPool)
parent::__construct($httpCallResultPool);
}

private function sortArrays($obj)
{
$isObject = is_object($obj);

foreach ($obj as $key => $value) {
if (null === $value || is_scalar($value)) {
continue;
}

if (is_array($value)) {
sort($value);
}

$value = $this->sortArrays($value);

$isObject ? $obj->{$key} = $value : $obj[$key] = $value;
}

return $obj;
}

/**
* @Then /^the JSON should be deep equal to:$/
*/
Expand Down Expand Up @@ -75,4 +54,25 @@ public function theJsonIsASupersetOf(PyStringNode $content)
$actual = json_decode($this->httpCallResultPool->getResult()->getValue(), true);
Assert::assertArraySubset(json_decode($content->getRaw(), true), $actual);
}

private function sortArrays($obj)
{
$isObject = is_object($obj);

foreach ($obj as $key => $value) {
if (null === $value || is_scalar($value)) {
continue;
}

if (is_array($value)) {
sort($value);
}

$value = $this->sortArrays($value);

$isObject ? $obj->{$key} = $value : $obj[$key] = $value;
}

return $obj;
}
}
190 changes: 190 additions & 0 deletions features/graphql/input_output.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
Feature: GraphQL DTO input and output
In order to use a hypermedia API
As a client software developer
I need to be able to use DTOs on my resources as Input or Output objects.

@createSchema
Scenario: Retrieve an Output with GraphQl
When I add "Content-Type" header equal to "application/ld+json"
And I send a "POST" request to "/dummy_dto_input_outputs" with body:
"""
{
"foo": "test",
"bar": 1
}
"""
Then the response status code should be 201
And the JSON should be equal to:
"""
{
"@context": {
"@vocab": "http://example.com/docs.jsonld#",
"hydra": "http://www.w3.org/ns/hydra/core#",
"id": "OutputDto/id",
"baz": "OutputDto/baz",
"bat": "OutputDto/bat"
},
"@type": "DummyDtoInputOutput",
"@id": "/dummy_dto_input_outputs/1",
"id": 1,
"baz": 1,
"bat": "test"
}
"""
When I send the following GraphQL request:
"""
{
dummyDtoInputOutput(id: "/dummy_dto_input_outputs/1") {
_id, id, baz
}
}
"""
Then the response status code should be 200
And the response should be in JSON
And the header "Content-Type" should be equal to "application/json"
And the JSON should be equal to:
"""
{
"data": {
"dummyDtoInputOutput": {
"_id": 1,
"id": "/dummy_dto_input_outputs/1",
"baz": 1
}
}
}
"""

Scenario: Create an item using custom inputClass & disabled outputClass
Given there are 2 dummyDtoNoOutput objects
When I send the following GraphQL request:
"""
mutation {
createDummyDtoNoOutput(input: {foo: "A new one", bar: 3, clientMutationId: "myId"}) {
dummyDtoNoOutput {
id
}
clientMutationId
}
}
"""
Then the response status code should be 200
And the response should be in JSON
And the header "Content-Type" should be equal to "application/json"
And the JSON should be equal to:
"""
{
"errors": [
{
"message": "Cannot query field \"id\" on type \"DummyDtoNoOutput\".",
"extensions": {
"category": "graphql"
},
"locations": [
{
"line": 4,
"column": 7
}
]
}
]
}
"""

Scenario: Cannot create an item with input fields using disabled inputClass
When I send the following GraphQL request:
"""
mutation {
createDummyDtoNoInput(input: {lorem: "A new one", ipsum: 3, clientMutationId: "myId"}) {
clientMutationId
}
}
"""
Then the response status code should be 200
And the response should be in JSON
And the header "Content-Type" should be equal to "application/json"
And the JSON should be equal to:
"""
{
"errors": [
{
"message": "Field \"lorem\" is not defined by type createDummyDtoNoInputInput.",
"extensions": {
"category": "graphql"
},
"locations": [
{
"line": 2,
"column": 33
}
]
},
{
"message": "Field \"ipsum\" is not defined by type createDummyDtoNoInputInput.",
"extensions": {
"category": "graphql"
},
"locations": [
{
"line": 2,
"column": 53
}
]
}
]
}
"""

Scenario: Create an item with empty input fields using disabled inputClass (no persist done)
When I send the following GraphQL request:
"""
mutation {
createDummyDtoNoInput(input: {clientMutationId: "myId"}) {
dummyDtoNoInput {
id
}
clientMutationId
}
}
"""
Then the response status code should be 200
And the response should be in JSON
And the header "Content-Type" should be equal to "application/json"
And the JSON should be equal to:
"""
{
"data": {
"createDummyDtoNoInput": {
"dummyDtoNoInput": null,
"clientMutationId": "myId"
}
}
}
"""

@!mongodb
Scenario: Use messenger with graphql and an input where the handler gives a synchronous result
When I send the following GraphQL request:
"""
mutation {
createMessengerWithInput(input: {var: "test"}) {
messengerWithInput { id, name }
}
}
"""
Then the response status code should be 200
And the response should be in JSON
And the header "Content-Type" should be equal to "application/json"
And the JSON should be equal to:
"""
{
"data": {
"createMessengerWithInput": {
"messengerWithInput": {
"id": "/messenger_with_inputs/1",
"name": "test"
}
}
}
}
"""
9 changes: 7 additions & 2 deletions features/graphql/mutation.feature
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ Feature: GraphQL mutation support
type {
name
kind
ofType {
name
kind
}
}
}
}
Expand All @@ -31,8 +35,9 @@ Feature: GraphQL mutation support
And the JSON node "data.__type.fields[0].type.name" should match "/^delete[A-z0-9]+Payload$/"
And the JSON node "data.__type.fields[0].type.kind" should be equal to "OBJECT"
And the JSON node "data.__type.fields[0].args[0].name" should be equal to "input"
And the JSON node "data.__type.fields[0].args[0].type.name" should match "/^delete[A-z0-9]+Input$/"
And the JSON node "data.__type.fields[0].args[0].type.kind" should be equal to "INPUT_OBJECT"
And the JSON node "data.__type.fields[0].args[0].type.kind" should be equal to "NON_NULL"
And the JSON node "data.__type.fields[0].args[0].type.ofType.name" should match "/^delete[A-z0-9]+Input$/"
And the JSON node "data.__type.fields[0].args[0].type.ofType.kind" should be equal to "INPUT_OBJECT"

Scenario: Create an item
When I send the following GraphQL request:
Expand Down
Loading