Skip to content

Commit 44a686c

Browse files
authored
Merge pull request #2704 from soyuka/merge-2.4
Merge 2.4
2 parents a1da24c + d442702 commit 44a686c

File tree

75 files changed

+1975
-680
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+1975
-680
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ jobs:
215215
mkdir -p build/logs/tmp build/cov
216216
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
217217
_f=${f//\//_}
218-
FEATURE="${_f}" phpdbg -qrr vendor/bin/behat --profile=coverage --suite=default --format=progress --out=std --format=junit --out=build/logs/tmp/"${_f}" "$f"
218+
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"
219219
done
220220
- run:
221221
name: Merge Behat test reports

.travis.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,13 @@ script:
6868
fi
6969
- tests/Fixtures/app/console cache:clear
7070
- if [[ $APP_ENV = 'postgres' ]]; then
71-
vendor/bin/behat --suite=postgres --format=progress;
71+
vendor/bin/behat --suite=postgres --format=progress --no-interaction;
7272
elif [[ $APP_ENV = 'mongodb' ]]; then
73-
vendor/bin/behat --suite=mongodb --format=progress;
73+
vendor/bin/behat --suite=mongodb --format=progress --no-interaction;
7474
elif [[ $APP_ENV = 'elasticsearch' ]]; then
75-
vendor/bin/behat --suite=elasticsearch --format=progress;
75+
vendor/bin/behat --suite=elasticsearch --format=progress --no-interaction;
7676
else
77-
vendor/bin/behat --suite=default --format=progress;
77+
vendor/bin/behat --suite=default --format=progress --no-interaction;
7878
fi
7979
- tests/Fixtures/app/console api:swagger:export > swagger.json && npx swagger-cli validate swagger.json && rm swagger.json
8080
- tests/Fixtures/app/console api:swagger:export --yaml > swagger.yaml && npx swagger-cli validate swagger.yaml && rm swagger.yaml

appveyor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,6 @@ services:
3333

3434
test_script:
3535
- cd %APPVEYOR_BUILD_FOLDER%
36-
- php vendor\behat\behat\bin\behat --format=progress --suite=default
36+
- php vendor\behat\behat\bin\behat --format=progress --suite=default --no-interaction
3737
- rmdir tests\Fixtures\app\var\cache /s /q
3838
- php vendor\phpunit\phpunit\phpunit

features/bootstrap/DoctrineContext.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@
1111

1212
declare(strict_types=1);
1313

14+
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Address as AddressDocument;
1415
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Answer as AnswerDocument;
1516
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\CompositeItem as CompositeItemDocument;
1617
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\CompositeLabel as CompositeLabelDocument;
1718
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\CompositePrimitiveItem as CompositePrimitiveItemDocument;
1819
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\CompositeRelation as CompositeRelationDocument;
20+
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Customer as CustomerDocument;
1921
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Dummy as DummyDocument;
2022
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\DummyAggregateOffer as DummyAggregateOfferDocument;
2123
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\DummyCar as DummyCarDocument;
@@ -39,6 +41,7 @@
3941
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\FourthLevel as FourthLevelDocument;
4042
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Greeting as GreetingDocument;
4143
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\MaxDepthDummy as MaxDepthDummyDocument;
44+
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Order as OrderDocument;
4245
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Person as PersonDocument;
4346
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\PersonToPet as PersonToPetDocument;
4447
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Pet as PetDocument;
@@ -52,12 +55,14 @@
5255
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\SoMany as SoManyDocument;
5356
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\ThirdLevel as ThirdLevelDocument;
5457
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\User as UserDocument;
58+
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Address;
5559
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Answer;
5660
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\CompositeItem;
5761
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\CompositeLabel;
5862
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\CompositePrimitiveItem;
5963
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\CompositeRelation;
6064
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Container;
65+
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Customer;
6166
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy;
6267
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\DummyAggregateOffer;
6368
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\DummyCar;
@@ -83,6 +88,7 @@
8388
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Greeting;
8489
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\MaxDepthDummy;
8590
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Node;
91+
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Order;
8692
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Person;
8793
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\PersonToPet;
8894
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Pet;
@@ -1571,4 +1577,33 @@ private function buildThirdLevel()
15711577
{
15721578
return $this->isOrm() ? new ThirdLevel() : new ThirdLevelDocument();
15731579
}
1580+
1581+
/**
1582+
* @Given there is a order with same customer and receiver
1583+
*/
1584+
public function testEagerLoadingNotDuplicateRelation()
1585+
{
1586+
$customer = $this->isOrm() ? new Customer() : new CustomerDocument();
1587+
$customer->name = 'customer_name';
1588+
1589+
$address1 = $this->isOrm() ? new Address() : new AddressDocument();
1590+
$address1->name = 'foo';
1591+
$address2 = $this->isOrm() ? new Address() : new AddressDocument();
1592+
$address2->name = 'bar';
1593+
1594+
$order = $this->isOrm() ? new Order() : new OrderDocument();
1595+
$order->recipient = $customer;
1596+
$order->customer = $customer;
1597+
1598+
$customer->addresses->add($address1);
1599+
$customer->addresses->add($address2);
1600+
1601+
$this->manager->persist($address1);
1602+
$this->manager->persist($address2);
1603+
$this->manager->persist($customer);
1604+
$this->manager->persist($order);
1605+
1606+
$this->manager->flush();
1607+
$this->manager->clear();
1608+
}
15741609
}

features/bootstrap/JsonContext.php

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,27 +24,6 @@ public function __construct(HttpCallResultPool $httpCallResultPool)
2424
parent::__construct($httpCallResultPool);
2525
}
2626

27-
private function sortArrays($obj)
28-
{
29-
$isObject = is_object($obj);
30-
31-
foreach ($obj as $key => $value) {
32-
if (null === $value || is_scalar($value)) {
33-
continue;
34-
}
35-
36-
if (is_array($value)) {
37-
sort($value);
38-
}
39-
40-
$value = $this->sortArrays($value);
41-
42-
$isObject ? $obj->{$key} = $value : $obj[$key] = $value;
43-
}
44-
45-
return $obj;
46-
}
47-
4827
/**
4928
* @Then /^the JSON should be deep equal to:$/
5029
*/
@@ -75,4 +54,25 @@ public function theJsonIsASupersetOf(PyStringNode $content)
7554
$actual = json_decode($this->httpCallResultPool->getResult()->getValue(), true);
7655
Assert::assertArraySubset(json_decode($content->getRaw(), true), $actual);
7756
}
57+
58+
private function sortArrays($obj)
59+
{
60+
$isObject = is_object($obj);
61+
62+
foreach ($obj as $key => $value) {
63+
if (null === $value || is_scalar($value)) {
64+
continue;
65+
}
66+
67+
if (is_array($value)) {
68+
sort($value);
69+
}
70+
71+
$value = $this->sortArrays($value);
72+
73+
$isObject ? $obj->{$key} = $value : $obj[$key] = $value;
74+
}
75+
76+
return $obj;
77+
}
7878
}

features/graphql/input_output.feature

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
Feature: GraphQL DTO input and output
2+
In order to use a hypermedia API
3+
As a client software developer
4+
I need to be able to use DTOs on my resources as Input or Output objects.
5+
6+
@createSchema
7+
Scenario: Retrieve an Output with GraphQl
8+
When I add "Content-Type" header equal to "application/ld+json"
9+
And I send a "POST" request to "/dummy_dto_input_outputs" with body:
10+
"""
11+
{
12+
"foo": "test",
13+
"bar": 1
14+
}
15+
"""
16+
Then the response status code should be 201
17+
And the JSON should be equal to:
18+
"""
19+
{
20+
"@context": {
21+
"@vocab": "http://example.com/docs.jsonld#",
22+
"hydra": "http://www.w3.org/ns/hydra/core#",
23+
"id": "OutputDto/id",
24+
"baz": "OutputDto/baz",
25+
"bat": "OutputDto/bat"
26+
},
27+
"@type": "DummyDtoInputOutput",
28+
"@id": "/dummy_dto_input_outputs/1",
29+
"id": 1,
30+
"baz": 1,
31+
"bat": "test"
32+
}
33+
"""
34+
When I send the following GraphQL request:
35+
"""
36+
{
37+
dummyDtoInputOutput(id: "/dummy_dto_input_outputs/1") {
38+
_id, id, baz
39+
}
40+
}
41+
"""
42+
Then the response status code should be 200
43+
And the response should be in JSON
44+
And the header "Content-Type" should be equal to "application/json"
45+
And the JSON should be equal to:
46+
"""
47+
{
48+
"data": {
49+
"dummyDtoInputOutput": {
50+
"_id": 1,
51+
"id": "/dummy_dto_input_outputs/1",
52+
"baz": 1
53+
}
54+
}
55+
}
56+
"""
57+
58+
Scenario: Create an item using custom inputClass & disabled outputClass
59+
Given there are 2 dummyDtoNoOutput objects
60+
When I send the following GraphQL request:
61+
"""
62+
mutation {
63+
createDummyDtoNoOutput(input: {foo: "A new one", bar: 3, clientMutationId: "myId"}) {
64+
dummyDtoNoOutput {
65+
id
66+
}
67+
clientMutationId
68+
}
69+
}
70+
"""
71+
Then the response status code should be 200
72+
And the response should be in JSON
73+
And the header "Content-Type" should be equal to "application/json"
74+
And the JSON should be equal to:
75+
"""
76+
{
77+
"errors": [
78+
{
79+
"message": "Cannot query field \"id\" on type \"DummyDtoNoOutput\".",
80+
"extensions": {
81+
"category": "graphql"
82+
},
83+
"locations": [
84+
{
85+
"line": 4,
86+
"column": 7
87+
}
88+
]
89+
}
90+
]
91+
}
92+
"""
93+
94+
Scenario: Cannot create an item with input fields using disabled inputClass
95+
When I send the following GraphQL request:
96+
"""
97+
mutation {
98+
createDummyDtoNoInput(input: {lorem: "A new one", ipsum: 3, clientMutationId: "myId"}) {
99+
clientMutationId
100+
}
101+
}
102+
"""
103+
Then the response status code should be 200
104+
And the response should be in JSON
105+
And the header "Content-Type" should be equal to "application/json"
106+
And the JSON should be equal to:
107+
"""
108+
{
109+
"errors": [
110+
{
111+
"message": "Field \"lorem\" is not defined by type createDummyDtoNoInputInput.",
112+
"extensions": {
113+
"category": "graphql"
114+
},
115+
"locations": [
116+
{
117+
"line": 2,
118+
"column": 33
119+
}
120+
]
121+
},
122+
{
123+
"message": "Field \"ipsum\" is not defined by type createDummyDtoNoInputInput.",
124+
"extensions": {
125+
"category": "graphql"
126+
},
127+
"locations": [
128+
{
129+
"line": 2,
130+
"column": 53
131+
}
132+
]
133+
}
134+
]
135+
}
136+
"""
137+
138+
Scenario: Create an item with empty input fields using disabled inputClass (no persist done)
139+
When I send the following GraphQL request:
140+
"""
141+
mutation {
142+
createDummyDtoNoInput(input: {clientMutationId: "myId"}) {
143+
dummyDtoNoInput {
144+
id
145+
}
146+
clientMutationId
147+
}
148+
}
149+
"""
150+
Then the response status code should be 200
151+
And the response should be in JSON
152+
And the header "Content-Type" should be equal to "application/json"
153+
And the JSON should be equal to:
154+
"""
155+
{
156+
"data": {
157+
"createDummyDtoNoInput": {
158+
"dummyDtoNoInput": null,
159+
"clientMutationId": "myId"
160+
}
161+
}
162+
}
163+
"""
164+
165+
@!mongodb
166+
Scenario: Use messenger with graphql and an input where the handler gives a synchronous result
167+
When I send the following GraphQL request:
168+
"""
169+
mutation {
170+
createMessengerWithInput(input: {var: "test"}) {
171+
messengerWithInput { id, name }
172+
}
173+
}
174+
"""
175+
Then the response status code should be 200
176+
And the response should be in JSON
177+
And the header "Content-Type" should be equal to "application/json"
178+
And the JSON should be equal to:
179+
"""
180+
{
181+
"data": {
182+
"createMessengerWithInput": {
183+
"messengerWithInput": {
184+
"id": "/messenger_with_inputs/1",
185+
"name": "test"
186+
}
187+
}
188+
}
189+
}
190+
"""

features/graphql/mutation.feature

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ Feature: GraphQL mutation support
1717
type {
1818
name
1919
kind
20+
ofType {
21+
name
22+
kind
23+
}
2024
}
2125
}
2226
}
@@ -31,8 +35,9 @@ Feature: GraphQL mutation support
3135
And the JSON node "data.__type.fields[0].type.name" should match "/^delete[A-z0-9]+Payload$/"
3236
And the JSON node "data.__type.fields[0].type.kind" should be equal to "OBJECT"
3337
And the JSON node "data.__type.fields[0].args[0].name" should be equal to "input"
34-
And the JSON node "data.__type.fields[0].args[0].type.name" should match "/^delete[A-z0-9]+Input$/"
35-
And the JSON node "data.__type.fields[0].args[0].type.kind" should be equal to "INPUT_OBJECT"
38+
And the JSON node "data.__type.fields[0].args[0].type.kind" should be equal to "NON_NULL"
39+
And the JSON node "data.__type.fields[0].args[0].type.ofType.name" should match "/^delete[A-z0-9]+Input$/"
40+
And the JSON node "data.__type.fields[0].args[0].type.ofType.kind" should be equal to "INPUT_OBJECT"
3641

3742
Scenario: Create an item
3843
When I send the following GraphQL request:

0 commit comments

Comments
 (0)