From 991d21b4a12c64663efaa3999812913e042e4b57 Mon Sep 17 00:00:00 2001 From: Ernest Elksnis Date: Sat, 5 Jan 2019 13:38:35 +0100 Subject: [PATCH 01/18] refactoring tests --- .../CoreTest.php} | 62 +--------------- .../RelationshipTests/BelongsToManyTest.php | 12 ++++ .../RelationshipTests/BelongsToTest.php | 71 +++++++++++++++++++ .../RelationshipTests/HasManyTest.php | 12 ++++ .../RelationshipTests/HasOneTest.php | 13 ++++ .../RelationshipTests/MorphManyTest.php | 12 ++++ .../RelationshipTests/MorphOneTest.php | 12 ++++ .../RelationshipTests/MorphToTest.php | 12 ++++ 8 files changed, 146 insertions(+), 60 deletions(-) rename tests/Integration/Schema/Directives/Fields/{UpdateDirectiveTest.php => UpdateDirectiveTests/CoreTest.php} (75%) create mode 100644 tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToManyTest.php create mode 100644 tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToTest.php create mode 100644 tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/HasManyTest.php create mode 100644 tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/HasOneTest.php create mode 100644 tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/MorphManyTest.php create mode 100644 tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/MorphOneTest.php create mode 100644 tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/MorphToTest.php diff --git a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTest.php b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/CoreTest.php similarity index 75% rename from tests/Integration/Schema/Directives/Fields/UpdateDirectiveTest.php rename to tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/CoreTest.php index bea8556316..6fcb0f1213 100644 --- a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTest.php +++ b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/CoreTest.php @@ -1,6 +1,6 @@ assertSame('bar', Company::first()->name); } - /** - * @test - */ - public function itCanUpdateWithBelongsTo() - { - factory(User::class, 2)->create(); - factory(Task::class)->create([ - 'name' => 'bar', - 'user_id' => 1, - ]); - - $schema = ' - type Task { - id: ID! - name: String! - user: User @belongsTo - } - - type User { - id: ID - } - - type Mutation { - updateTask(input: UpdateTaskInput!): Task @update(flatten: true) - } - - input UpdateTaskInput { - id: ID! - name: String - user_id: ID - } - '.$this->placeholderQuery(); - $query = ' - mutation { - updateTask(input: { - id: 1 - name: "foo" - user_id: 2 - }) { - id - name - user { - id - } - } - } - '; - $result = $this->execute($schema, $query); - - $this->assertSame('1', Arr::get($result, 'data.updateTask.id')); - $this->assertSame('foo', Arr::get($result, 'data.updateTask.name')); - $this->assertSame('2', Arr::get($result, 'data.updateTask.user.id')); - - $task = Task::first(); - $this->assertSame('2', $task->user_id); - $this->assertSame('foo', $task->name); - } - /** * @test */ diff --git a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToManyTest.php b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToManyTest.php new file mode 100644 index 0000000000..2351f2d616 --- /dev/null +++ b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToManyTest.php @@ -0,0 +1,12 @@ +create(); + factory(Task::class)->create([ + 'name' => 'bar', + 'user_id' => 1, + ]); + + $schema = ' + type Task { + id: ID! + name: String! + user: User @belongsTo + } + + type User { + id: ID + } + + type Mutation { + updateTask(input: UpdateTaskInput!): Task @update(flatten: true) + } + + input UpdateTaskInput { + id: ID! + name: String + user_id: ID + } + '.$this->placeholderQuery(); + $query = ' + mutation { + updateTask(input: { + id: 1 + name: "foo" + user: { + + } + }) { + id + name + user { + id + } + } + } + '; + $result = $this->execute($schema, $query); + + $this->assertSame('1', Arr::get($result, 'data.updateTask.id')); + $this->assertSame('foo', Arr::get($result, 'data.updateTask.name')); + $this->assertSame('2', Arr::get($result, 'data.updateTask.user.id')); + + $task = Task::first(); + $this->assertSame('2', $task->user_id); + $this->assertSame('foo', $task->name); + } +} diff --git a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/HasManyTest.php b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/HasManyTest.php new file mode 100644 index 0000000000..a66c7ed9f5 --- /dev/null +++ b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/HasManyTest.php @@ -0,0 +1,12 @@ + Date: Mon, 21 Jan 2019 17:24:58 +0100 Subject: [PATCH 02/18] Fix BelongsToTest --- .../RelationshipTests/BelongsToTest.php | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToTest.php b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToTest.php index 9ae5c4141f..1bf98032b5 100644 --- a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToTest.php +++ b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToTest.php @@ -3,7 +3,6 @@ namespace Tests\Integration\Schema\Directives\Fields\UpdateDirectiveTests\RelationshipTests; use Tests\DBTestCase; -use Illuminate\Support\Arr; use Tests\Utils\Models\Task; use Tests\Utils\Models\User; @@ -20,7 +19,7 @@ public function itCanUpdateWithBelongsTo() 'user_id' => 1, ]); - $schema = ' + $this->schema = ' type Task { id: ID! name: String! @@ -41,14 +40,13 @@ public function itCanUpdateWithBelongsTo() user_id: ID } '.$this->placeholderQuery(); - $query = ' + + $this->query(' mutation { updateTask(input: { id: 1 name: "foo" - user: { - - } + user_id: 2 }) { id name @@ -57,12 +55,17 @@ public function itCanUpdateWithBelongsTo() } } } - '; - $result = $this->execute($schema, $query); - - $this->assertSame('1', Arr::get($result, 'data.updateTask.id')); - $this->assertSame('foo', Arr::get($result, 'data.updateTask.name')); - $this->assertSame('2', Arr::get($result, 'data.updateTask.user.id')); + ')->assertJson([ + 'data' => [ + 'updateTask' => [ + 'id' => '1', + 'name' => 'foo', + 'user' => [ + 'id' => '2' + ] + ] + ] + ]); $task = Task::first(); $this->assertSame('2', $task->user_id); From 723183b7bcfb86ba90c86487bd64f0d012df1f8a Mon Sep 17 00:00:00 2001 From: Ernest Elksnis Date: Sat, 9 Feb 2019 14:37:35 +0100 Subject: [PATCH 03/18] Porting functionality from create to update Pre test --- src/Execution/MutationExecutor.php | 111 +++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/src/Execution/MutationExecutor.php b/src/Execution/MutationExecutor.php index 388d1c1988..a7ba86afda 100644 --- a/src/Execution/MutationExecutor.php +++ b/src/Execution/MutationExecutor.php @@ -147,6 +147,10 @@ protected static function saveModelWithBelongsTo(Model $model, Collection $args, $belongsTo = $model->{$relationName}(); $belongsTo->associate($values); } + + if ($operationKey === 'delete') { + $relation->getModel()::destroy($values); + } }); }); @@ -212,6 +216,16 @@ public static function executeUpdate(Model $model, Collection $args, ?HasMany $p [$hasMany, $remaining] = self::partitionArgsByRelationType($reflection, $args, HasMany::class); + [$morphMany, $remaining] = self::partitionArgsByRelationType($reflection, $remaining, MorphMany::class); + + [$hasOne, $remaining] = self::partitionArgsByRelationType($reflection, $remaining, HasOne::class); + + [$belongsToMany, $remaining] = self::partitionArgsByRelationType($reflection, $remaining, BelongsToMany::class); + + [$morphOne, $remaining] = self::partitionArgsByRelationType($reflection, $remaining, MorphOne::class); + + [$morphToMany, $remaining] = self::partitionArgsByRelationType($reflection, $remaining, MorphToMany::class); + $model = self::saveModelWithBelongsTo($model, $remaining, $parentRelation); $hasMany->each(function (array $nestedOperations, string $relationName) use ($model): void { @@ -235,6 +249,103 @@ public static function executeUpdate(Model $model, Collection $args, ?HasMany $p }); }); + $hasOne->each(function (array $nestedOperations, string $relationName) use ($model): void { + /** @var \Illuminate\Database\Eloquent\Relations\HasOne $relation */ + $relation = $model->{$relationName}(); + + collect($nestedOperations)->each(function ($values, string $operationKey) use ($relation): void { + if ($operationKey === 'create') { + self::handleSingleRelationCreate(collect($values), $relation); + } + }); + }); + + $morphMany->each(function (array $nestedOperations, string $relationName) use ($model): void { + /** @var \Illuminate\Database\Eloquent\Relations\MorphMany $relation */ + $relation = $model->{$relationName}(); + + collect($nestedOperations)->each(function ($values, string $operationKey) use ($relation): void { + if ($operationKey === 'create') { + self::handleMultiRelationCreate(collect($values), $relation); + } + if ($operationKey === 'update') { + collect($values)->each(function ($singleValues) use ($relation): void { + self::executeUpdate($relation->getModel()->newInstance(), collect($singleValues), $relation); + }); + } + + if ($operationKey === 'delete') { + $relation->getModel()::destroy($values); + } + }); + }); + + $morphOne->each(function (array $nestedOperations, string $relationName) use ($model): void { + /** @var \Illuminate\Database\Eloquent\Relations\MorphOne $relation */ + $relation = $model->{$relationName}(); + + collect($nestedOperations)->each(function ($values, string $operationKey) use ($relation): void { + if ($operationKey === 'create') { + self::handleSingleRelationCreate(collect($values), $relation); + } + + if ($operationKey === 'update') { + collect($values)->each(function ($singleValues) use ($relation): void { + self::executeUpdate($relation->getModel()->newInstance(), collect($singleValues), $relation); + }); + } + + if ($operationKey === 'delete') { + $relation->getModel()::destroy($values); + } + }); + }); + + $belongsToMany->each(function (array $nestedOperations, string $relationName) use ($model): void { + /** @var \Illuminate\Database\Eloquent\Relations\BelongsToMany $relation */ + $relation = $model->{$relationName}(); + + collect($nestedOperations)->each(function ($values, string $operationKey) use ($relation): void { + if ($operationKey === 'create') { + self::handleMultiRelationCreate(collect($values), $relation); + } + + if ($operationKey === 'update') { + collect($values)->each(function ($singleValues) use ($relation): void { + self::executeUpdate($relation->getModel()->newInstance(), collect($singleValues), $relation); + }); + } + + if ($operationKey === 'delete') { + $relation->getModel()::destroy($values); + } + + if ($operationKey === 'connect') { + $relation->attach($values); + } + }); + }); + + $morphToMany->each(function (array $nestedOperations, string $relationName) use ($model): void { + /** @var \Illuminate\Database\Eloquent\Relations\HasMany $relation */ + $relation = $model->{$relationName}(); + + collect($nestedOperations)->each(function ($values, string $operationKey) use ($relation): void { + if ($operationKey === 'create') { + self::handleMultiRelationCreate(collect($values), $relation); + } + if ($operationKey === 'update') { + collect($values)->each(function ($singleValues) use ($relation): void { + self::executeUpdate($relation->getModel()->newInstance(), collect($singleValues), $relation); + }); + } + + if ($operationKey === 'delete') { + $relation->getModel()::destroy($values); + } + }); + }); + return $model; } From 5a98b9ffe5c89cab8ef977b5b898d722fd0c0487 Mon Sep 17 00:00:00 2001 From: Ernest Elksnis Date: Sat, 9 Feb 2019 14:59:40 +0100 Subject: [PATCH 04/18] HasOne --- src/Execution/MutationExecutor.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Execution/MutationExecutor.php b/src/Execution/MutationExecutor.php index a7ba86afda..7f9d180064 100644 --- a/src/Execution/MutationExecutor.php +++ b/src/Execution/MutationExecutor.php @@ -257,6 +257,16 @@ public static function executeUpdate(Model $model, Collection $args, ?HasMany $p if ($operationKey === 'create') { self::handleSingleRelationCreate(collect($values), $relation); } + + if ($operationKey === 'update') { + collect($values)->each(function ($singleValues) use ($relation): void { + self::executeUpdate($relation->getModel()->newInstance(), collect($singleValues), $relation); + }); + } + + if ($operationKey === 'delete') { + $relation->getModel()::destroy($values); + } }); }); From f8f9287c0c9af0a11fa79855fa82d01174042ebf Mon Sep 17 00:00:00 2001 From: spawnia Date: Thu, 7 Mar 2019 09:00:35 +0100 Subject: [PATCH 05/18] Fix type hints --- src/Execution/MutationExecutor.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Execution/MutationExecutor.php b/src/Execution/MutationExecutor.php index a1170d1dbc..6fdd799d6e 100644 --- a/src/Execution/MutationExecutor.php +++ b/src/Execution/MutationExecutor.php @@ -28,7 +28,7 @@ class MutationExecutor * If we are in a nested create, we can use this to associate the new model to its parent * @return \Illuminate\Database\Eloquent\Model */ - public static function executeCreate(Model $model, Collection $args, Relation $parentRelation = null): Model + public static function executeCreate(Model $model, Collection $args, ?Relation $parentRelation = null): Model { $reflection = new ReflectionClass($model); @@ -69,7 +69,7 @@ public static function executeCreate(Model $model, Collection $args, Relation $p * @param \Illuminate\Database\Eloquent\Relations\Relation|null $parentRelation * @return \Illuminate\Database\Eloquent\Model */ - protected static function saveModelWithBelongsTo(Model $model, Collection $args, Relation $parentRelation = null): Model + protected static function saveModelWithBelongsTo(Model $model, Collection $args, ?Relation $parentRelation = null): Model { $reflection = new ReflectionClass($model); [$belongsTo, $remaining] = self::partitionArgsByRelationType($reflection, $args, BelongsTo::class); @@ -147,17 +147,17 @@ protected static function handleSingleRelationCreate(Collection $singleValues, R } /** - * Execute an update. + * Execute an update mutation. * * @param \Illuminate\Database\Eloquent\Model $model * An empty instance of the model that should be updated * @param \Illuminate\Support\Collection $args * The corresponding slice of the input arguments for updating this model - * @param \Illuminate\Database\Eloquent\Relations\HasMany|null $parentRelation + * @param \Illuminate\Database\Eloquent\Relations\Relation|null $parentRelation * If we are in a nested update, we can use this to associate the new model to its parent * @return \Illuminate\Database\Eloquent\Model */ - public static function executeUpdate(Model $model, Collection $args, ?HasMany $parentRelation = null): Model + public static function executeUpdate(Model $model, Collection $args, ?Relation $parentRelation = null): Model { $id = $args->pull('id') ?? $args->pull( @@ -291,7 +291,7 @@ public static function executeUpdate(Model $model, Collection $args, ?HasMany $p }); $morphToMany->each(function (array $nestedOperations, string $relationName) use ($model): void { - /** @var \Illuminate\Database\Eloquent\Relations\HasMany $relation */ + /** @var \Illuminate\Database\Eloquent\Relations\MorphToMany $relation */ $relation = $model->{$relationName}(); collect($nestedOperations)->each(function ($values, string $operationKey) use ($relation): void { @@ -370,7 +370,7 @@ function ($value, string $key) use ($modelReflection, $relationClass): bool { * @param \Illuminate\Support\Collection $hasMany * @return void */ - protected static function executeCreateHasMany(Model $model, $hasMany): void + protected static function executeCreateHasMany(Model $model, Collection $hasMany): void { $hasMany->each(function (array $nestedOperations, string $relationName) use ($model): void { /** @var \Illuminate\Database\Eloquent\Relations\HasMany $relation */ @@ -391,7 +391,7 @@ protected static function executeCreateHasMany(Model $model, $hasMany): void * @param \Illuminate\Support\Collection $hasOne * @return void */ - protected static function executeCreateHasOne(Model $model, $hasOne): void + protected static function executeCreateHasOne(Model $model, Collection $hasOne): void { $hasOne->each(function (array $nestedOperations, string $relationName) use ($model): void { /** @var \Illuminate\Database\Eloquent\Relations\HasOne $relation */ @@ -412,7 +412,7 @@ protected static function executeCreateHasOne(Model $model, $hasOne): void * @param \Illuminate\Support\Collection $morphMany * @return void */ - protected static function executeCreateMorphMany(Model $model, $morphMany): void + protected static function executeCreateMorphMany(Model $model, Collection $morphMany): void { $morphMany->each(function (array $nestedOperations, string $relationName) use ($model): void { /** @var \Illuminate\Database\Eloquent\Relations\MorphMany $relation */ @@ -433,7 +433,7 @@ protected static function executeCreateMorphMany(Model $model, $morphMany): void * @param \Illuminate\Support\Collection $morphOne * @return void */ - protected static function executeCreateMorphOne(Model $model, $morphOne): void + protected static function executeCreateMorphOne(Model $model, Collection $morphOne): void { $morphOne->each(function (array $nestedOperations, string $relationName) use ($model): void { /** @var \Illuminate\Database\Eloquent\Relations\MorphOne $relation */ @@ -454,7 +454,7 @@ protected static function executeCreateMorphOne(Model $model, $morphOne): void * @param \Illuminate\Support\Collection $belongsToMany * @return void */ - protected static function executeCreateBelongsToMany(Model $model, $belongsToMany): void + protected static function executeCreateBelongsToMany(Model $model, Collection $belongsToMany): void { $belongsToMany->each(function (array $nestedOperations, string $relationName) use ($model): void { /** @var \Illuminate\Database\Eloquent\Relations\BelongsToMany $relation */ @@ -479,7 +479,7 @@ protected static function executeCreateBelongsToMany(Model $model, $belongsToMan * @param \Illuminate\Support\Collection $morphToMany * @return void */ - protected static function executeCreateMorphToMany(Model $model, $morphToMany): void + protected static function executeCreateMorphToMany(Model $model, Collection $morphToMany): void { $morphToMany->each(function (array $nestedOperations, string $relationName) use ($model): void { /** @var \Illuminate\Database\Eloquent\Relations\HasMany $relation */ From a6adb35b4c2b7a3ae53ff556f51f3cd709588f28 Mon Sep 17 00:00:00 2001 From: spawnia Date: Thu, 7 Mar 2019 09:01:24 +0100 Subject: [PATCH 06/18] Detach before destroying a many-to-many relationship --- src/Execution/MutationExecutor.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Execution/MutationExecutor.php b/src/Execution/MutationExecutor.php index 6fdd799d6e..1a05bb69e3 100644 --- a/src/Execution/MutationExecutor.php +++ b/src/Execution/MutationExecutor.php @@ -281,6 +281,7 @@ public static function executeUpdate(Model $model, Collection $args, ?Relation $ } if ($operationKey === 'delete') { + $relation->detach($values); $relation->getModel()::destroy($values); } @@ -305,6 +306,7 @@ public static function executeUpdate(Model $model, Collection $args, ?Relation $ } if ($operationKey === 'delete') { + $relation->detach($values); $relation->getModel()::destroy($values); } }); From 83c1a0777096d21ef5d1a105faef1bf97ff913c8 Mon Sep 17 00:00:00 2001 From: spawnia Date: Thu, 7 Mar 2019 09:01:58 +0100 Subject: [PATCH 07/18] Add connect, sync and disconnect for many-to-many relationships --- src/Execution/MutationExecutor.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/Execution/MutationExecutor.php b/src/Execution/MutationExecutor.php index 1a05bb69e3..114c77eead 100644 --- a/src/Execution/MutationExecutor.php +++ b/src/Execution/MutationExecutor.php @@ -232,6 +232,7 @@ public static function executeUpdate(Model $model, Collection $args, ?Relation $ if ($operationKey === 'create') { self::handleMultiRelationCreate(collect($values), $relation); } + if ($operationKey === 'update') { collect($values)->each(function ($singleValues) use ($relation): void { self::executeUpdate($relation->getModel()->newInstance(), collect($singleValues), $relation); @@ -288,6 +289,14 @@ public static function executeUpdate(Model $model, Collection $args, ?Relation $ if ($operationKey === 'connect') { $relation->attach($values); } + + if ($operationKey === 'sync') { + $relation->sync($values); + } + + if ($operationKey === 'disconnect') { + $relation->detach($values); + } }); }); @@ -299,6 +308,7 @@ public static function executeUpdate(Model $model, Collection $args, ?Relation $ if ($operationKey === 'create') { self::handleMultiRelationCreate(collect($values), $relation); } + if ($operationKey === 'update') { collect($values)->each(function ($singleValues) use ($relation): void { self::executeUpdate($relation->getModel()->newInstance(), collect($singleValues), $relation); @@ -309,6 +319,18 @@ public static function executeUpdate(Model $model, Collection $args, ?Relation $ $relation->detach($values); $relation->getModel()::destroy($values); } + + if ($operationKey === 'connect') { + $relation->attach($values); + } + + if ($operationKey === 'sync') { + $relation->sync($values); + } + + if ($operationKey === 'disconnect') { + $relation->detach($values); + } }); }); From 018d1c8e25f08d5bcb5e998e68cdbe10d32a1786 Mon Sep 17 00:00:00 2001 From: spawnia Date: Wed, 13 Mar 2019 08:17:22 +0100 Subject: [PATCH 08/18] Add some docs for updating nested mutations --- docs/master/guides/relationships.md | 145 ++++++++++++++++++++++------ 1 file changed, 115 insertions(+), 30 deletions(-) diff --git a/docs/master/guides/relationships.md b/docs/master/guides/relationships.md index d4576f2807..5aa47ab8e0 100644 --- a/docs/master/guides/relationships.md +++ b/docs/master/guides/relationships.md @@ -401,60 +401,110 @@ mutation { } ``` -### Belongs To Many +When updating a `User`, further nested operations become possible. +It is up to you which ones you want to expose through the schema definition. +The following example covers the full range of possible operations: +`create`, `update` and `delete`. ```graphql type Mutation { - createPost(input: CreatePostInput!): Post @create(flatten: true) + updateUser(input: UpdateUserInput!): User @update(flatten: true) } -input CreateAuthorRelation { - connect: [ID] - create: [CreateAuthorInput] +input UpdateUserInput { + id: ID! + name: String + posts: UpdatePostsRelation } -input CreateAuthorInput { - name: String! +input UpdatePostsRelation { + create: [CreatePostInput!] + update: [UpdatePostInput!] + delete: [ID!] } input CreatePostInput { title: String! - authors: CreateAuthorRelation } -``` -Just pass the ID of the models you want to associate. +input UpdatePostInput { + id: ID! + title: String +} +``` ```graphql mutation { - createPost(input: { - title: "My new Post" - authors: { - connect: [123,124] + updateUser(input: { + id: 3, + name: "Phillip" + posts: { + create: [ + { + title: "A new post" + } + ], + update: [ + { + id: 45, + title: "This post is updated" + } + ], + delete: [ + 8, + ] } }){ id - authors { - name + posts { + id } } } ``` -Or create a new ones. +### Belongs To Many + +A belongs to many relation allows you to create new related models as well +as attaching existing ones. + +```graphql +type Mutation { + createPost(input: CreatePostInput!): Post @create(flatten: true) +} + +input CreatePostInput { + title: String! + authors: CreateAuthorRelation +} + +input CreateAuthorRelation { + create: [CreateAuthorInput!] + connect: [ID!] +} + +input CreateAuthorInput { + name: String! +} +``` + +Just pass the ID of the models you want to associate or their full information +to create a new relation. ```graphql mutation { createPost(input: { title: "My new Post" - author: { - create: [{ - name: "Herbert" - }, - { - name: "Bro" - }] + authors: { + create: [ + { + name: "Herbert" + } + ] + connect: [ + 123 + ] } }){ id @@ -472,17 +522,52 @@ Lighthouse will detect the relationship and attach/create it. "data": { "createPost": { "id": 456, - "authors": [{ - "name": "Herbert" - }, - { - "name": "Bro" - }] + "authors": [ + { + "id": 165, + "name": "Herbert" + }, + { + "id": 123, + "name": "Franz" + } + ] } } } ``` +Updates on BelongsToMany relations may expose up to 6 nested operations. + +```graphql +type Mutation { + updatePost(input: UpdatePostInput!): Post @create(flatten: true) +} + +input UpdatePostInput { + id: ID! + title: String + authors: UpdateAuthorRelation +} + +input UpdateAuthorRelation { + create: [CreateAuthorInput!] + connect: [ID!] + update: [UpdateAuthorInput!] + sync: [ID!] + delete: [ID!] + disconnect: [ID!] +} + +input CreateAuthorInput { + name: String! +} + +input CreateAuthorInput { + name: String! +} +``` + ### MorphTo ```graphql From 4dce8a4b4e493a7b59e2a5b6ba2492e77822b59d Mon Sep 17 00:00:00 2001 From: spawnia Date: Thu, 14 Mar 2019 11:42:29 +0100 Subject: [PATCH 09/18] Add test for BelongsToMany and fix it --- src/Execution/MutationExecutor.php | 44 +- .../RelationshipTests/BelongsToManyTest.php | 392 +++++++++++++++++- 2 files changed, 423 insertions(+), 13 deletions(-) diff --git a/src/Execution/MutationExecutor.php b/src/Execution/MutationExecutor.php index 114c77eead..32233569e0 100644 --- a/src/Execution/MutationExecutor.php +++ b/src/Execution/MutationExecutor.php @@ -44,7 +44,7 @@ public static function executeCreate(Model $model, Collection $args, ?Relation $ [$morphToMany, $remaining] = self::partitionArgsByRelationType($reflection, $remaining, MorphToMany::class); - $model = self::saveModelWithBelongsTo($model, $remaining, $parentRelation); + $model = self::saveModelWithPotentialParent($model, $remaining, $parentRelation); self::executeCreateHasMany($model, $hasMany); @@ -62,17 +62,20 @@ public static function executeCreate(Model $model, Collection $args, ?Relation $ } /** - * Save a model with BelongsTo. + * Save a model that maybe has a parent. * * @param \Illuminate\Database\Eloquent\Model $model * @param \Illuminate\Support\Collection $args * @param \Illuminate\Database\Eloquent\Relations\Relation|null $parentRelation * @return \Illuminate\Database\Eloquent\Model */ - protected static function saveModelWithBelongsTo(Model $model, Collection $args, ?Relation $parentRelation = null): Model + protected static function saveModelWithPotentialParent(Model $model, Collection $args, ?Relation $parentRelation = null): Model { - $reflection = new ReflectionClass($model); - [$belongsTo, $remaining] = self::partitionArgsByRelationType($reflection, $args, BelongsTo::class); + [$belongsTo, $remaining] = self::partitionArgsByRelationType( + new ReflectionClass($model), + $args, + BelongsTo::class + ); // Use all the remaining attributes and fill the model $model->fill( @@ -96,18 +99,35 @@ protected static function saveModelWithBelongsTo(Model $model, Collection $args, $belongsTo->associate($values); } + if ($operationKey === 'update') { + $belongsToModel = self::executeUpdate($relation->getModel()->newInstance(), collect($values)); + $relation->associate($belongsToModel); + } + + if ($operationKey === 'disconnect') { + $relation->dissociate(); + } + if ($operationKey === 'delete') { $relation->getModel()::destroy($values); } }); }); - // If we are already resolving a nested create, we might - // already have an instance of the parent relation available. - // In that case, use it to set the current model as a child. - $parentRelation - ? $parentRelation->save($model) - : $model->save(); + if ($parentRelation && ! $parentRelation instanceof BelongsToMany){ + // If we are already resolving a nested create, we might + // already have an instance of the parent relation available. + // In that case, use it to set the current model as a child. + $parentRelation->save($model); + + return $model; + } + + $model->save(); + + if ($parentRelation instanceof BelongsToMany) { + $parentRelation->syncWithoutDetaching($model); + } return $model; } @@ -180,7 +200,7 @@ public static function executeUpdate(Model $model, Collection $args, ?Relation $ [$morphToMany, $remaining] = self::partitionArgsByRelationType($reflection, $remaining, MorphToMany::class); - $model = self::saveModelWithBelongsTo($model, $remaining, $parentRelation); + $model = self::saveModelWithPotentialParent($model, $remaining, $parentRelation); $hasMany->each(function (array $nestedOperations, string $relationName) use ($model): void { /** @var \Illuminate\Database\Eloquent\Relations\HasMany $relation */ diff --git a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToManyTest.php b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToManyTest.php index 2351f2d616..9f4a3bf86b 100644 --- a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToManyTest.php +++ b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToManyTest.php @@ -3,10 +3,400 @@ namespace Tests\Integration\Schema\Directives\Fields\UpdateDirectiveTests\RelationshipTests; use Tests\DBTestCase; -use Illuminate\Support\Arr; +use Tests\Utils\Models\Role; use Tests\Utils\Models\User; class BelongsToManyTest extends DBTestCase { + private $schemaBase = ' + type Role { + id: ID! + name: String + users: [User!] @belongsToMany + } + + type User { + id: ID! + name: String + } + + type Mutation { + updateRole(input: UpdateRoleInput!): Role @update(flatten: true) + } + + input UpdateRoleInput { + id: ID! + name: String + users: UpdateUserRelation + } + + input UpdateUserInput { + id: ID! + name: String + } + + input CreateUserInput { + name: String + } + '; + public function setUp(): void + { + parent::setUp(); + + $this->schema = $this->schemaBase . $this->placeholderQuery(); + } + + /** + * @test + */ + public function itCanCreateWithBelongsToMany(): void + { + factory(Role::class)->create([ + 'name' => 'is_admin', + ]); + + $this->schema .= ' + input UpdateUserRelation { + create: [CreateUserInput!] + } + '; + + $this->query(' + mutation { + updateRole(input: { + id: 1 + name: "is_user" + users: { + create: [{ + name: "user1" + }, + { + name: "user2" + }] + } + }) { + id + name + users { + id + name + } + } + } + ')->assertJson([ + 'data' => [ + 'updateRole' => [ + 'id' => '1', + 'name' => 'is_user', + 'users' => [ + [ + 'id' => '1', + 'name' => 'user1', + ], + [ + 'id' => '2', + 'name' => 'user2', + ], + ], + ], + ], + ]); + + /** @var \Tests\Utils\Models\Role $role */ + $role = Role::first(); + $this->assertCount(2, $role->users()->get()); + $this->assertSame('is_user', $role->name); + } + + /** + * @test + */ + public function itCanUpdateWithBelongsToMany(): void + { + factory(Role::class) + ->create([ + 'name' => 'is_admin', + ]) + ->users() + ->attach( + factory(User::class, 2)->create() + ); + + $this->schema .= ' + input UpdateUserRelation { + update: [UpdateUserInput!] + } + '; + + $this->query(' + mutation { + updateRole(input: { + id: 1 + name: "is_user" + users: { + update: [{ + id: 1 + name: "user1" + }, + { + id: 2 + name: "user2" + }] + } + }) { + id + name + users { + id + name + } + } + } + ')->assertJson([ + 'data' => [ + 'updateRole' => [ + 'id' => '1', + 'name' => 'is_user', + 'users' => [ + [ + 'id' => '1', + 'name' => 'user1', + ], + [ + 'id' => '2', + 'name' => 'user2', + ], + ], + ], + ], + ]); + + /** @var Role $role */ + $role = Role::first(); + $this->assertCount(2, $role->users()->get()); + $this->assertSame('is_user', $role->name); + } + + /** + * @test + */ + public function itCanDeleteWithBelongsToMany(): void + { + factory(Role::class) + ->create([ + 'name' => 'is_admin', + ]) + ->users() + ->attach( + factory(User::class, 2)->create() + ); + + $this->schema .= ' + input UpdateUserRelation { + delete: [ID!] + } + '; + + $this->query(' + mutation { + updateRole(input: { + id: 1 + name: "is_user" + users: { + delete: [1] + } + }) { + id + name + users { + id + } + } + } + ')->assertJson([ + 'data' => [ + 'updateRole' => [ + 'id' => '1', + 'name' => 'is_user', + 'users' => [ + [ + 'id' => '2', + ], + ], + ], + ], + ]); + + /** @var Role $role */ + $role = Role::first(); + $this->assertCount(1, $role->users()->get()); + $this->assertSame('is_user', $role->name); + + $this->assertNull(User::find(1)); + $this->assertNotNull(User::find(2)); + } + + /** + * @test + */ + public function itCanConnectWithBelongsToMany(): void + { + factory(User::class)->create(); + factory(Role::class) + ->create() + ->users() + ->attach( + factory(User::class)->create() + ); + + $this->schema .= ' + input UpdateUserRelation { + connect: [ID!] + } + '; + + $this->query(' + mutation { + updateRole(input: { + id: 1 + users: { + connect: [1] + } + }) { + id + name + users { + id + } + } + } + ')->assertJson([ + 'data' => [ + 'updateRole' => [ + 'id' => '1', + 'users' => [ + [ + 'id' => '2', + ], + [ + 'id' => '1', + ], + ], + ], + ], + ]); + + /** @var Role $role */ + $role = Role::first(); + $this->assertCount(2, $role->users()->get()); + } + + /** + * @test + */ + public function itCanSyncWithBelongsToMany(): void + { + factory(User::class)->create(); + factory(Role::class) + ->create() + ->users() + ->attach( + factory(User::class)->create() + ); + + $this->schema .= ' + input UpdateUserRelation { + sync: [ID!] + } + '; + + $this->query(' + mutation { + updateRole(input: { + id: 1 + users: { + sync: [1,2] + } + }) { + id + name + users { + id + } + } + } + ')->assertJson([ + 'data' => [ + 'updateRole' => [ + 'id' => '1', + 'users' => [ + [ + 'id' => '2', + ], + [ + 'id' => '1', + ], + ], + ], + ], + ]); + + /** @var Role $role */ + $role = Role::first(); + $this->assertCount(2, $role->users()->get()); + } + + /** + * @test + */ + public function itCanDisconnectWithBelongsToMany(): void + { + factory(Role::class) + ->create() + ->users() + ->attach( + factory(User::class, 2)->create() + ); + + $this->schema .= ' + input UpdateUserRelation { + disconnect: [ID!] + } + '; + + $this->query(' + mutation { + updateRole(input: { + id: 1 + users: { + disconnect: [1] + } + }) { + id + users { + id + } + } + } + ')->assertJson([ + 'data' => [ + 'updateRole' => [ + 'id' => '1', + 'users' => [ + [ + 'id' => '2', + ], + ], + ], + ], + ]); + + /** @var Role $role */ + $role = Role::first(); + $this->assertCount(1, $role->users()->get()); + + $this->assertNotNull(User::find(1)); + $this->assertNotNull(User::find(2)); + } } From 2c91398b29b3073d8a5732613e25aed6e456a594 Mon Sep 17 00:00:00 2001 From: spawnia Date: Thu, 14 Mar 2019 11:43:24 +0100 Subject: [PATCH 10/18] zYN7rK --- src/Execution/MutationExecutor.php | 6 +++--- .../RelationshipTests/BelongsToManyTest.php | 2 +- .../RelationshipTests/BelongsToTest.php | 8 ++++---- .../RelationshipTests/HasManyTest.php | 3 --- .../UpdateDirectiveTests/RelationshipTests/HasOneTest.php | 4 ---- .../RelationshipTests/MorphManyTest.php | 3 --- .../RelationshipTests/MorphOneTest.php | 3 --- .../RelationshipTests/MorphToTest.php | 3 --- 8 files changed, 8 insertions(+), 24 deletions(-) diff --git a/src/Execution/MutationExecutor.php b/src/Execution/MutationExecutor.php index 32233569e0..bfbcc5e4b7 100644 --- a/src/Execution/MutationExecutor.php +++ b/src/Execution/MutationExecutor.php @@ -100,8 +100,8 @@ protected static function saveModelWithPotentialParent(Model $model, Collection } if ($operationKey === 'update') { - $belongsToModel = self::executeUpdate($relation->getModel()->newInstance(), collect($values)); - $relation->associate($belongsToModel); + $belongsToModel = self::executeUpdate($relation->getModel()->newInstance(), collect($values)); + $relation->associate($belongsToModel); } if ($operationKey === 'disconnect') { @@ -114,7 +114,7 @@ protected static function saveModelWithPotentialParent(Model $model, Collection }); }); - if ($parentRelation && ! $parentRelation instanceof BelongsToMany){ + if ($parentRelation && ! $parentRelation instanceof BelongsToMany) { // If we are already resolving a nested create, we might // already have an instance of the parent relation available. // In that case, use it to set the current model as a child. diff --git a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToManyTest.php b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToManyTest.php index 9f4a3bf86b..85650bb194 100644 --- a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToManyTest.php +++ b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToManyTest.php @@ -44,7 +44,7 @@ public function setUp(): void { parent::setUp(); - $this->schema = $this->schemaBase . $this->placeholderQuery(); + $this->schema = $this->schemaBase.$this->placeholderQuery(); } /** diff --git a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToTest.php b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToTest.php index 1bf98032b5..d05817a5f1 100644 --- a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToTest.php +++ b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToTest.php @@ -61,10 +61,10 @@ public function itCanUpdateWithBelongsTo() 'id' => '1', 'name' => 'foo', 'user' => [ - 'id' => '2' - ] - ] - ] + 'id' => '2', + ], + ], + ], ]); $task = Task::first(); diff --git a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/HasManyTest.php b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/HasManyTest.php index a66c7ed9f5..bf586d1b03 100644 --- a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/HasManyTest.php +++ b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/HasManyTest.php @@ -3,10 +3,7 @@ namespace Tests\Integration\Schema\Directives\Fields\UpdateDirectiveTests\RelationshipTests; use Tests\DBTestCase; -use Illuminate\Support\Arr; -use Tests\Utils\Models\Task; class HasManyTest extends DBTestCase { - } diff --git a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/HasOneTest.php b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/HasOneTest.php index bdf00c3872..ca8a2aab15 100644 --- a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/HasOneTest.php +++ b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/HasOneTest.php @@ -3,11 +3,7 @@ namespace Tests\Integration\Schema\Directives\Fields\UpdateDirectiveTests\RelationshipTests; use Tests\DBTestCase; -use Illuminate\Support\Arr; -use Tests\Utils\Models\Post; -use Tests\Utils\Models\User; class HasOneTest extends DBTestCase { - } diff --git a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/MorphManyTest.php b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/MorphManyTest.php index 55fe3abe4d..b65e448108 100644 --- a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/MorphManyTest.php +++ b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/MorphManyTest.php @@ -3,10 +3,7 @@ namespace Tests\Integration\Schema\Directives\Fields\UpdateDirectiveTests\RelationshipTests; use Tests\DBTestCase; -use Illuminate\Support\Arr; -use Tests\Utils\Models\User; class MorphManyTest extends DBTestCase { - } diff --git a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/MorphOneTest.php b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/MorphOneTest.php index a02fe0c5c4..b9725c219b 100644 --- a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/MorphOneTest.php +++ b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/MorphOneTest.php @@ -3,10 +3,7 @@ namespace Tests\Integration\Schema\Directives\Fields\UpdateDirectiveTests\RelationshipTests; use Tests\DBTestCase; -use Illuminate\Support\Arr; -use Tests\Utils\Models\User; class MorphOneTest extends DBTestCase { - } diff --git a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/MorphToTest.php b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/MorphToTest.php index 956a5842a3..7a9d93bba9 100644 --- a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/MorphToTest.php +++ b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/MorphToTest.php @@ -3,10 +3,7 @@ namespace Tests\Integration\Schema\Directives\Fields\UpdateDirectiveTests\RelationshipTests; use Tests\DBTestCase; -use Illuminate\Support\Arr; -use Tests\Utils\Models\Task; class MorphToTest extends DBTestCase { - } From d2eb5530ffa1fc42bad048918c2f3f5b829dda01 Mon Sep 17 00:00:00 2001 From: spawnia Date: Fri, 15 Mar 2019 17:43:56 +0100 Subject: [PATCH 11/18] Add docs for updating a belongsTo relation --- docs/master/guides/relationships.md | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/docs/master/guides/relationships.md b/docs/master/guides/relationships.md index 5aa47ab8e0..ce4ce24abf 100644 --- a/docs/master/guides/relationships.md +++ b/docs/master/guides/relationships.md @@ -201,12 +201,14 @@ It has to be named just like the relationship method that is defined on the `Pos input CreateAuthorRelation { connect: ID create: CreateUserInput + update: UpdateUserInput } ``` -There are two possible operations that you can expose on a `BelongsTo` relationship: +There are 3 possible operations that you can expose on a `BelongsTo` relationship when creating: - `connect` it to an existing model -- `create` and attach a new related model +- `create` a new related model and attach it +- `update` an existing model and attach it Finally, you need to define the input that allows you to create a new `User`. @@ -284,7 +286,7 @@ mutation { } ``` -You may also allow the user to change or remove a relation. +When issuing an update, you can also allow the user to remove a relation. ```graphql type Mutation { @@ -293,17 +295,28 @@ type Mutation { input UpdatePostInput { title: String - author: ID + author: UpdateAuthorRelation +} + +input UpdateAuthorRelation { + connect: ID + create: CreateUserInput + update: UpdateUserInput + disconnect: ID + delete: ID } ``` -If you want to remove a relation, simply set it to `null`, +Both `disconnect` and `delete` remove the association to the author, +but `delete` also removes the author model itself. ```graphql mutation { updatePost(input: { title: "An updated title" - author: null + author: { + delete: 55 + } }){ title author { From 575f2c15a914d837c8bbd679dd7e3cd8d48a5086 Mon Sep 17 00:00:00 2001 From: spawnia Date: Mon, 18 Mar 2019 15:00:10 +0100 Subject: [PATCH 12/18] Clarify semantics for deleting/disconnecting BelongsTo, adding tests and docs --- docs/master/guides/relationships.md | 18 +- src/Execution/MutationExecutor.php | 16 +- .../RelationshipTests/BelongsToTest.php | 140 ++++++++----- .../RelationshipTests/BelongsToTest.php | 195 ++++++++++++++---- 4 files changed, 267 insertions(+), 102 deletions(-) diff --git a/docs/master/guides/relationships.md b/docs/master/guides/relationships.md index ce4ce24abf..4da4905bef 100644 --- a/docs/master/guides/relationships.md +++ b/docs/master/guides/relationships.md @@ -287,6 +287,8 @@ mutation { ``` When issuing an update, you can also allow the user to remove a relation. +Both `disconnect` and `delete` remove the association to the author, +but `delete` also removes the author model itself. ```graphql type Mutation { @@ -302,20 +304,21 @@ input UpdateAuthorRelation { connect: ID create: CreateUserInput update: UpdateUserInput - disconnect: ID - delete: ID + disconnect: Boolean + delete: Boolean } ``` -Both `disconnect` and `delete` remove the association to the author, -but `delete` also removes the author model itself. +You must pass a truthy value to `disconnect` and `delete` for them to actually run. +This structure was chosen as it is consistent with updating `BelongsToMany` relationships +and allows the query string to be mostly static, taking a variable value to control its behaviour. ```graphql -mutation { +mutation UpdatePost($disconnectAuthour: Boolean){ updatePost(input: { title: "An updated title" author: { - delete: 55 + disconnect: $disconnectAuthor } }){ title @@ -326,6 +329,9 @@ mutation { } ``` +The `author` relationship will only be disconnected if the value of the variable +`$disconnectAuthor` is `true`, if `false` or `null` are passed, it will not change. + ```json { "data": { diff --git a/src/Execution/MutationExecutor.php b/src/Execution/MutationExecutor.php index 7cf1550a60..bdc3b61429 100644 --- a/src/Execution/MutationExecutor.php +++ b/src/Execution/MutationExecutor.php @@ -104,12 +104,22 @@ protected static function saveModelWithPotentialParent(Model $model, Collection $relation->associate($belongsToModel); } - if ($operationKey === 'disconnect') { + // We proceed with disconnecting/deleting only if the given $values is truthy. + // There is no other information to be passed when issuing those operations, + // but GraphQL forces us to pass some value. It would be unintuitive for + // the end user if the given value had no effect on the execution. + if ( + $operationKey === 'disconnect' + && $values + ) { $relation->dissociate(); } - if ($operationKey === 'delete') { - $relation->getModel()::destroy($values); + if ( + $operationKey === 'delete' + && $values + ) { + $relation->delete(); } }); }); diff --git a/tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/BelongsToTest.php b/tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/BelongsToTest.php index 3634b854d3..c3760cfdf5 100644 --- a/tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/BelongsToTest.php +++ b/tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/BelongsToTest.php @@ -7,6 +7,50 @@ class BelongsToTest extends DBTestCase { + protected $schema = ' + type Mutation { + createTask(input: CreateTaskInput!): Task @create(flatten: true) + } + + type Task { + id: ID! + name: String! + user: User @belongsTo + } + + type User { + id: ID! + name: String! + } + + input CreateTaskInput { + name: String + user: CreateUserRelation + } + + input CreateUserRelation { + connect: ID + create: CreateUserInput + update: UpdateUserInput + } + + input CreateUserInput { + name: String! + } + + input UpdateUserInput { + id: ID! + name: String + } + '; + + public function setUp(): void + { + parent::setUp(); + + $this->schema .= $this->placeholderQuery(); + } + /** * @test */ @@ -14,31 +58,6 @@ public function itCanCreateAndConnectWithBelongsTo(): void { factory(User::class)->create(); - $this->schema = ' - type Task { - id: ID! - name: String! - user: User @belongsTo - } - - type User { - id: ID - } - - type Mutation { - createTask(input: CreateTaskInput!): Task @create(flatten: true) - } - - input CreateUserRelation { - connect: ID - } - - input CreateTaskInput { - name: String - user: CreateUserRelation - } - '.$this->placeholderQuery(); - $this->query(' mutation { createTask(input: { @@ -72,35 +91,6 @@ public function itCanCreateAndConnectWithBelongsTo(): void */ public function itCanCreateWithNewBelongsTo(): void { - $this->schema = ' - type Task { - id: ID! - name: String! - user: User @belongsTo - } - - type User { - id: ID - } - - type Mutation { - createTask(input: CreateTaskInput!): Task @create(flatten: true) - } - - input CreateUserRelation { - create: CreateUserInput! - } - - input CreateUserInput { - name: String! - } - - input CreateTaskInput { - name: String - user: CreateUserRelation - } - '.$this->placeholderQuery(); - $this->query(' mutation { createTask(input: { @@ -130,4 +120,46 @@ public function itCanCreateWithNewBelongsTo(): void ], ]); } + + /** + * @test + */ + public function itCanCreateAndUpdateBelongsTo(): void + { + factory(User::class)->create([ + 'name' => 'foo' + ]); + + $this->query(' + mutation { + createTask(input: { + name: "foo" + user: { + update: { + id: 1 + name: "bar" + } + } + }) { + id + name + user { + id + name + } + } + } + ')->assertJson([ + 'data' => [ + 'createTask' => [ + 'id' => '1', + 'name' => 'foo', + 'user' => [ + 'id' => '1', + 'name' => 'bar', + ], + ], + ], + ]); + } } diff --git a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToTest.php b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToTest.php index d05817a5f1..c8d1d0e229 100644 --- a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToTest.php +++ b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToTest.php @@ -3,72 +3,189 @@ namespace Tests\Integration\Schema\Directives\Fields\UpdateDirectiveTests\RelationshipTests; use Tests\DBTestCase; -use Tests\Utils\Models\Task; -use Tests\Utils\Models\User; +use Tests\Utils\Models\Post; class BelongsToTest extends DBTestCase { + protected $schema = ' + type Mutation { + updatePost(input: UpdatePostInput!): Post @update(flatten: true) + } + + type Post { + id: ID! + title: String! + parent: Post @belongsTo + } + + input UpdatePostInput { + id: ID! + title: String + parent: UpdatePostRelation + } + + input UpdatePostRelation { + disconnect: Boolean + delete: Boolean + } + '; + + public function setUp(): void + { + parent::setUp(); + + $this->schema .= $this->placeholderQuery(); + } + /** * @test */ - public function itCanUpdateWithBelongsTo() + public function itCanUpdateAndDisconnectBelongsTo(): void { - factory(User::class, 2)->create(); - factory(Task::class)->create([ - 'name' => 'bar', - 'user_id' => 1, - ]); + /** @var \Tests\Utils\Models\Post $post */ + $post = factory(Post::class)->create(); + $post + ->parent() + ->associate( + factory(Post::class)->create() + ) + ->save(); - $this->schema = ' - type Task { - id: ID! - name: String! - user: User @belongsTo - } - - type User { - id: ID - } - - type Mutation { - updateTask(input: UpdateTaskInput!): Task @update(flatten: true) + $this->query(' + mutation { + updatePost(input: { + id: 1 + title: "foo" + parent: { + disconnect: true + } + }) { + id + title + parent { + id + } + } } - - input UpdateTaskInput { - id: ID! - name: String - user_id: ID + ')->assertJson([ + 'data' => [ + 'updatePost' => [ + 'id' => '1', + 'title' => 'foo', + 'parent' => null, + ], + ], + ]); + + $this->assertTrue( + Post::find(2)->exists, + 'Must not delete the second model.' + ); + + $this->assertNull( + Post::find(1)->parent, + 'Must disconnect the parent relationship.' + ); + } + + /** + * @test + */ + public function itCanUpdateAndDeleteBelongsTo(): void + { + /** @var \Tests\Utils\Models\Post $post */ + $post = factory(Post::class)->create(); + $post + ->parent() + ->associate( + factory(Post::class)->create() + ) + ->save(); + + $this->query(' + mutation { + updatePost(input: { + id: 1 + title: "foo" + parent: { + delete: true + } + }) { + id + title + parent { + id + } + } } - '.$this->placeholderQuery(); + ')->assertJson([ + 'data' => [ + 'updatePost' => [ + 'id' => '1', + 'title' => 'foo', + 'parent' => null, + ], + ], + ]); + + $this->assertNull( + Post::find(2), + 'This model should be deleted.' + ); + + $this->assertNull( + Post::find(1)->parent, + 'Must disconnect the parent relationship.' + ); + } + + /** + * @test + */ + public function itDoesNotDeleteOrDisconnectOnFalsyValues(): void + { + /** @var \Tests\Utils\Models\Post $post */ + $post = factory(Post::class)->create(); + $post + ->parent() + ->associate( + factory(Post::class)->create() + ) + ->save(); $this->query(' mutation { - updateTask(input: { + updatePost(input: { id: 1 - name: "foo" - user_id: 2 + title: "foo" + parent: { + delete: null + disconnect: false + } }) { id - name - user { + title + parent { id } } } ')->assertJson([ 'data' => [ - 'updateTask' => [ + 'updatePost' => [ 'id' => '1', - 'name' => 'foo', - 'user' => [ - 'id' => '2', + 'title' => 'foo', + 'parent' => [ + 'id' => '2' ], ], ], ]); - $task = Task::first(); - $this->assertSame('2', $task->user_id); - $this->assertSame('foo', $task->name); + $this->assertSame( + 2, + Post::find(1)->parent->id, + 'The parent relationship remains untouched.' + ); } } From dd3e72b320efcb475e140e873d5a95347352721b Mon Sep 17 00:00:00 2001 From: spawnia Date: Tue, 19 Mar 2019 10:31:07 +0100 Subject: [PATCH 13/18] Use new Collection instead of collect helper --- src/Execution/MutationExecutor.php | 34 +++++++++++++++--------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/Execution/MutationExecutor.php b/src/Execution/MutationExecutor.php index bdc3b61429..39e8a421af 100644 --- a/src/Execution/MutationExecutor.php +++ b/src/Execution/MutationExecutor.php @@ -100,7 +100,7 @@ protected static function saveModelWithPotentialParent(Model $model, Collection } if ($operationKey === 'update') { - $belongsToModel = self::executeUpdate($relation->getModel()->newInstance(), collect($values)); + $belongsToModel = self::executeUpdate($relation->getModel()->newInstance(), new Collection($values)); $relation->associate($belongsToModel); } @@ -237,9 +237,9 @@ public static function executeUpdate(Model $model, Collection $args, ?Relation $ /** @var \Illuminate\Database\Eloquent\Relations\HasOne $relation */ $relation = $model->{$relationName}(); - collect($nestedOperations)->each(function ($values, string $operationKey) use ($relation): void { + (new Collection($nestedOperations))->each(function ($values, string $operationKey) use ($relation): void { if ($operationKey === 'create') { - self::handleSingleRelationCreate(collect($values), $relation); + self::handleSingleRelationCreate(new Collection($values), $relation); } if ($operationKey === 'update') { @@ -258,14 +258,14 @@ public static function executeUpdate(Model $model, Collection $args, ?Relation $ /** @var \Illuminate\Database\Eloquent\Relations\MorphMany $relation */ $relation = $model->{$relationName}(); - collect($nestedOperations)->each(function ($values, string $operationKey) use ($relation): void { + (new Collection($nestedOperations))->each(function ($values, string $operationKey) use ($relation): void { if ($operationKey === 'create') { - self::handleMultiRelationCreate(collect($values), $relation); + self::handleMultiRelationCreate(new Collection($values), $relation); } if ($operationKey === 'update') { - collect($values)->each(function ($singleValues) use ($relation): void { - self::executeUpdate($relation->getModel()->newInstance(), collect($singleValues), $relation); + (new Collection($values))->each(function ($singleValues) use ($relation): void { + self::executeUpdate($relation->getModel()->newInstance(), new Collection($singleValues), $relation); }); } @@ -279,9 +279,9 @@ public static function executeUpdate(Model $model, Collection $args, ?Relation $ /** @var \Illuminate\Database\Eloquent\Relations\MorphOne $relation */ $relation = $model->{$relationName}(); - collect($nestedOperations)->each(function ($values, string $operationKey) use ($relation): void { + (new Collection($nestedOperations))->each(function ($values, string $operationKey) use ($relation): void { if ($operationKey === 'create') { - self::handleSingleRelationCreate(collect($values), $relation); + self::handleSingleRelationCreate(new Collection($values), $relation); } if ($operationKey === 'update') { @@ -300,14 +300,14 @@ public static function executeUpdate(Model $model, Collection $args, ?Relation $ /** @var \Illuminate\Database\Eloquent\Relations\BelongsToMany $relation */ $relation = $model->{$relationName}(); - collect($nestedOperations)->each(function ($values, string $operationKey) use ($relation): void { + (new Collection($nestedOperations))->each(function ($values, string $operationKey) use ($relation): void { if ($operationKey === 'create') { - self::handleMultiRelationCreate(collect($values), $relation); + self::handleMultiRelationCreate(new Collection($values), $relation); } if ($operationKey === 'update') { - collect($values)->each(function ($singleValues) use ($relation): void { - self::executeUpdate($relation->getModel()->newInstance(), collect($singleValues), $relation); + (new Collection($values))->each(function ($singleValues) use ($relation): void { + self::executeUpdate($relation->getModel()->newInstance(), new Collection($singleValues), $relation); }); } @@ -334,14 +334,14 @@ public static function executeUpdate(Model $model, Collection $args, ?Relation $ /** @var \Illuminate\Database\Eloquent\Relations\MorphToMany $relation */ $relation = $model->{$relationName}(); - collect($nestedOperations)->each(function ($values, string $operationKey) use ($relation): void { + (new Collection($nestedOperations))->each(function ($values, string $operationKey) use ($relation): void { if ($operationKey === 'create') { - self::handleMultiRelationCreate(collect($values), $relation); + self::handleMultiRelationCreate(new Collection($values), $relation); } if ($operationKey === 'update') { - collect($values)->each(function ($singleValues) use ($relation): void { - self::executeUpdate($relation->getModel()->newInstance(), collect($singleValues), $relation); + (new Collection($values))->each(function ($singleValues) use ($relation): void { + self::executeUpdate($relation->getModel()->newInstance(), new Collection($singleValues), $relation); }); } From 035d98b4ab53a259a5b8ca1f7b374a429d2c6f96 Mon Sep 17 00:00:00 2001 From: spawnia Date: Tue, 19 Mar 2019 10:31:35 +0100 Subject: [PATCH 14/18] Make test table columns nullable for ease of use in testing --- .../2018_02_28_000003_create_testbench_tasks_table.php | 2 +- .../2018_02_28_000004_create_testbench_posts_table.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/database/migrations/2018_02_28_000003_create_testbench_tasks_table.php b/tests/database/migrations/2018_02_28_000003_create_testbench_tasks_table.php index ba6dcf05cc..8243fb0f33 100644 --- a/tests/database/migrations/2018_02_28_000003_create_testbench_tasks_table.php +++ b/tests/database/migrations/2018_02_28_000003_create_testbench_tasks_table.php @@ -13,7 +13,7 @@ public function up(): void { Schema::create('tasks', function (Blueprint $table) { $table->increments('id'); - $table->unsignedInteger('user_id'); + $table->unsignedInteger('user_id')->nullable(); $table->string('name')->unique(); // Properties which collide with native model method names $table->string('guard')->nullable(); diff --git a/tests/database/migrations/2018_02_28_000004_create_testbench_posts_table.php b/tests/database/migrations/2018_02_28_000004_create_testbench_posts_table.php index 2b381a5edf..3350b1003e 100644 --- a/tests/database/migrations/2018_02_28_000004_create_testbench_posts_table.php +++ b/tests/database/migrations/2018_02_28_000004_create_testbench_posts_table.php @@ -14,8 +14,8 @@ public function up(): void Schema::create('posts', function (Blueprint $table) { $table->increments('id'); $table->string('title'); - $table->string('body'); - $table->unsignedInteger('user_id'); + $table->string('body')->nullable(); + $table->unsignedInteger('user_id')->nullable(); $table->unsignedInteger('task_id'); $table->unsignedInteger('parent_id')->nullable(); $table->timestamps(); From 8383c7c6cfde2252ce2120bbd57e708e5054ec1e Mon Sep 17 00:00:00 2001 From: spawnia Date: Tue, 19 Mar 2019 10:31:49 +0100 Subject: [PATCH 15/18] Fix column name in HourFactory --- tests/database/factories/HourFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/database/factories/HourFactory.php b/tests/database/factories/HourFactory.php index 2cb6e673e2..f847908873 100644 --- a/tests/database/factories/HourFactory.php +++ b/tests/database/factories/HourFactory.php @@ -11,6 +11,6 @@ 'to' => $faker->time('H:i'), 'hourable_id' => Task::all()->random(1)[0]->id, 'hourable_type' => 'task', - 'workday' => $faker->randomElement([0, 1, 2, 3, 4, 5, 6]), + 'weekday' => $faker->randomElement([0, 1, 2, 3, 4, 5, 6]), ]; }); From 9f0c53a593948af2d77d998b45b357be35811597 Mon Sep 17 00:00:00 2001 From: spawnia Date: Tue, 19 Mar 2019 10:32:24 +0100 Subject: [PATCH 16/18] Fix treatment of nested relation args for HasOne and MorphOne relations --- src/Execution/MutationExecutor.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Execution/MutationExecutor.php b/src/Execution/MutationExecutor.php index 39e8a421af..282119334d 100644 --- a/src/Execution/MutationExecutor.php +++ b/src/Execution/MutationExecutor.php @@ -243,9 +243,7 @@ public static function executeUpdate(Model $model, Collection $args, ?Relation $ } if ($operationKey === 'update') { - collect($values)->each(function ($singleValues) use ($relation): void { - self::executeUpdate($relation->getModel()->newInstance(), collect($singleValues), $relation); - }); + self::executeUpdate($relation->getModel()->newInstance(), new Collection($values), $relation); } if ($operationKey === 'delete') { @@ -285,9 +283,7 @@ public static function executeUpdate(Model $model, Collection $args, ?Relation $ } if ($operationKey === 'update') { - collect($values)->each(function ($singleValues) use ($relation): void { - self::executeUpdate($relation->getModel()->newInstance(), collect($singleValues), $relation); - }); + self::executeUpdate($relation->getModel()->newInstance(), new Collection($values), $relation); } if ($operationKey === 'delete') { From 10320295d978e3b01838779b35f1bf53cbd25f91 Mon Sep 17 00:00:00 2001 From: spawnia Date: Tue, 19 Mar 2019 10:33:28 +0100 Subject: [PATCH 17/18] Combine nested relation execution tests by relation type, simplifying test setup, lift up @create und @update tests --- .../MutationExecutor}/BelongsToManyTest.php | 158 ++++++++---- .../MutationExecutor}/BelongsToTest.php | 154 +++++++++++- .../MutationExecutor/HasManyTest.php | 234 ++++++++++++++++++ .../Execution/MutationExecutor/HasOneTest.php | 230 +++++++++++++++++ .../MutationExecutor/MorphManyTest.php | 227 +++++++++++++++++ .../MutationExecutor/MorphOneTest.php | 221 +++++++++++++++++ .../MutationExecutor}/MorphToTest.php | 61 ++--- .../CoreTest.php => CreateDirectiveTest.php} | 6 +- .../RelationshipTests/BelongsToManyTest.php | 154 ------------ .../RelationshipTests/HasManyTest.php | 78 ------ .../RelationshipTests/HasOneTest.php | 89 ------- .../RelationshipTests/MorphManyTest.php | 81 ------ .../RelationshipTests/MorphOneTest.php | 79 ------ .../CoreTest.php => UpdateDirectiveTest.php} | 9 +- .../RelationshipTests/BelongsToTest.php | 191 -------------- .../RelationshipTests/HasManyTest.php | 9 - .../RelationshipTests/HasOneTest.php | 9 - .../RelationshipTests/MorphManyTest.php | 9 - .../RelationshipTests/MorphOneTest.php | 9 - .../RelationshipTests/MorphToTest.php | 9 - 20 files changed, 1216 insertions(+), 801 deletions(-) rename tests/Integration/{Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests => Execution/MutationExecutor}/BelongsToManyTest.php (75%) rename tests/Integration/{Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests => Execution/MutationExecutor}/BelongsToTest.php (50%) create mode 100644 tests/Integration/Execution/MutationExecutor/HasManyTest.php create mode 100644 tests/Integration/Execution/MutationExecutor/HasOneTest.php create mode 100644 tests/Integration/Execution/MutationExecutor/MorphManyTest.php create mode 100644 tests/Integration/Execution/MutationExecutor/MorphOneTest.php rename tests/Integration/{Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests => Execution/MutationExecutor}/MorphToTest.php (59%) rename tests/Integration/Schema/Directives/Fields/{CreateDirectiveTests/CoreTest.php => CreateDirectiveTest.php} (98%) delete mode 100644 tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/BelongsToManyTest.php delete mode 100644 tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/HasManyTest.php delete mode 100644 tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/HasOneTest.php delete mode 100644 tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/MorphManyTest.php delete mode 100644 tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/MorphOneTest.php rename tests/Integration/Schema/Directives/Fields/{UpdateDirectiveTests/CoreTest.php => UpdateDirectiveTest.php} (96%) delete mode 100644 tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToTest.php delete mode 100644 tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/HasManyTest.php delete mode 100644 tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/HasOneTest.php delete mode 100644 tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/MorphManyTest.php delete mode 100644 tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/MorphOneTest.php delete mode 100644 tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/MorphToTest.php diff --git a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToManyTest.php b/tests/Integration/Execution/MutationExecutor/BelongsToManyTest.php similarity index 75% rename from tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToManyTest.php rename to tests/Integration/Execution/MutationExecutor/BelongsToManyTest.php index 85650bb194..5c84af1b64 100644 --- a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/BelongsToManyTest.php +++ b/tests/Integration/Execution/MutationExecutor/BelongsToManyTest.php @@ -1,6 +1,6 @@ schema = $this->schemaBase.$this->placeholderQuery(); + $this->schema .= $this->placeholderQuery(); + } + + /** + * @test + */ + public function itCanCreateWithNewBelongsToMany(): void + { + $this->query(' + mutation { + createRole(input: { + name: "foobar" + users: { + create: [{ + name: "bar" + }, + { + name: "foo" + }] + } + }) { + id + name + users { + id + name + } + } + } + ')->assertJson([ + 'data' => [ + 'createRole' => [ + 'id' => '1', + 'name' => 'foobar', + 'users' => [ + [ + 'id' => '1', + 'name' => 'bar', + ], + ], + ], + ], + ]); + } + + /** + * @test + */ + public function itCanCreateAndConnectWithBelongsToMany(): void + { + factory(User::class)->create(['name' => 'user_one']); + factory(User::class)->create(['name' => 'user_two']); + + $this->query(' + mutation { + createRole(input: { + name: "foobar" + users: { + connect: [ + 1,2 + ] + } + }) { + id + name + users { + id + name + } + } + } + ')->assertJson([ + 'data' => [ + 'createRole' => [ + 'id' => '1', + 'name' => 'foobar', + 'users' => [ + [ + 'id' => '1', + 'name' => 'user_one', + ], + [ + 'id' => '2', + 'name' => 'user_two', + ], + ], + ], + ], + ]); } /** @@ -56,12 +164,6 @@ public function itCanCreateWithBelongsToMany(): void 'name' => 'is_admin', ]); - $this->schema .= ' - input UpdateUserRelation { - create: [CreateUserInput!] - } - '; - $this->query(' mutation { updateRole(input: { @@ -123,12 +225,6 @@ public function itCanUpdateWithBelongsToMany(): void factory(User::class, 2)->create() ); - $this->schema .= ' - input UpdateUserRelation { - update: [UpdateUserInput!] - } - '; - $this->query(' mutation { updateRole(input: { @@ -192,12 +288,6 @@ public function itCanDeleteWithBelongsToMany(): void factory(User::class, 2)->create() ); - $this->schema .= ' - input UpdateUserRelation { - delete: [ID!] - } - '; - $this->query(' mutation { updateRole(input: { @@ -250,12 +340,6 @@ public function itCanConnectWithBelongsToMany(): void factory(User::class)->create() ); - $this->schema .= ' - input UpdateUserRelation { - connect: [ID!] - } - '; - $this->query(' mutation { updateRole(input: { @@ -305,12 +389,6 @@ public function itCanSyncWithBelongsToMany(): void factory(User::class)->create() ); - $this->schema .= ' - input UpdateUserRelation { - sync: [ID!] - } - '; - $this->query(' mutation { updateRole(input: { @@ -359,12 +437,6 @@ public function itCanDisconnectWithBelongsToMany(): void factory(User::class, 2)->create() ); - $this->schema .= ' - input UpdateUserRelation { - disconnect: [ID!] - } - '; - $this->query(' mutation { updateRole(input: { diff --git a/tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/BelongsToTest.php b/tests/Integration/Execution/MutationExecutor/BelongsToTest.php similarity index 50% rename from tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/BelongsToTest.php rename to tests/Integration/Execution/MutationExecutor/BelongsToTest.php index c3760cfdf5..4bf9ef5cde 100644 --- a/tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/BelongsToTest.php +++ b/tests/Integration/Execution/MutationExecutor/BelongsToTest.php @@ -1,17 +1,14 @@ create(); + + $this->query(' + mutation { + updateTask(input: { + id: 1 + name: "foo" + user: { + disconnect: true + } + }) { + id + name + user { + id + } + } + } + ')->assertJson([ + 'data' => [ + 'updateTask' => [ + 'id' => '1', + 'name' => 'foo', + 'user' => null, + ], + ], + ]); + + $this->assertTrue( + User::find(1)->exists, + 'Must not delete the second model.' + ); + + $this->assertNull( + Task::find(1)->user, + 'Must disconnect the parent relationship.' + ); + } + + /** + * @test + */ + public function itCanUpdateAndDeleteBelongsTo(): void + { + factory(Task::class)->create(); + + $this->query(' + mutation { + updateTask(input: { + id: 1 + name: "foo" + user: { + delete: true + } + }) { + id + name + user { + id + } + } + } + ')->assertJson([ + 'data' => [ + 'updateTask' => [ + 'id' => '1', + 'name' => 'foo', + 'user' => null, + ], + ], + ]); + + $this->assertNull( + User::find(1), + 'This model should be deleted.' + ); + + $this->assertNull( + Task::find(1)->user, + 'Must disconnect the parent relationship.' + ); + } + + /** + * @test + */ + public function itDoesNotDeleteOrDisconnectOnFalsyValues(): void + { + factory(Task::class)->create(); + + $this->query(' + mutation { + updateTask(input: { + id: 1 + name: "foo" + user: { + delete: null + disconnect: false + } + }) { + id + name + user { + id + } + } + } + ')->assertJson([ + 'data' => [ + 'updateTask' => [ + 'id' => '1', + 'name' => 'foo', + 'user' => [ + 'id' => '1' + ], + ], + ], + ]); + + $this->assertSame( + 1, + Task::find(1)->user->id, + 'The parent relationship remains untouched.' + ); + } } diff --git a/tests/Integration/Execution/MutationExecutor/HasManyTest.php b/tests/Integration/Execution/MutationExecutor/HasManyTest.php new file mode 100644 index 0000000000..3aab87aafe --- /dev/null +++ b/tests/Integration/Execution/MutationExecutor/HasManyTest.php @@ -0,0 +1,234 @@ +schema .= $this->placeholderQuery(); + } + + /** + * @test + */ + public function itCanCreateWithNewHasMany(): void + { + $this->query(' + mutation { + createUser(input: { + name: "foo" + tasks: { + create: [{ + name: "bar" + }] + } + }) { + id + name + tasks { + id + name + } + } + } + ')->assertJson([ + 'data' => [ + 'createUser' => [ + 'id' => '1', + 'name' => 'foo', + 'tasks' => [ + [ + 'id' => '1', + 'name' => 'bar', + ], + ], + ], + ], + ]); + } + + /** + * @test + */ + public function itCanCreateHasMany(): void + { + factory(User::class)->create(); + + $this->query(' + mutation { + updateUser(input: { + id: 1 + name: "foo" + tasks: { + create: [{ + name: "bar" + }] + } + }) { + id + name + tasks { + id + name + } + } + } + ')->assertJson([ + 'data' => [ + 'updateUser' => [ + 'id' => '1', + 'name' => 'foo', + 'tasks' => [ + [ + 'id' => '1', + 'name' => 'bar', + ], + ], + ], + ], + ]); + } + + /** + * @test + */ + public function itCanUpdateHasMany(): void + { + factory(User::class) + ->create() + ->tasks() + ->save( + factory(Task::class)->create() + ); + + $this->query(' + mutation { + updateUser(input: { + id: 1 + name: "foo" + tasks: { + update: [{ + id: 1 + name: "bar" + }] + } + }) { + id + name + tasks { + id + name + } + } + } + ')->assertJson([ + 'data' => [ + 'updateUser' => [ + 'id' => '1', + 'name' => 'foo', + 'tasks' => [ + [ + 'id' => '1', + 'name' => 'bar', + ], + ], + ], + ], + ]); + } + + /** + * @test + */ + public function itCanDeleteHasMany(): void + { + factory(User::class) + ->create() + ->tasks() + ->save( + factory(Task::class)->create() + ); + + $this->query(' + mutation { + updateUser(input: { + id: 1 + name: "foo" + tasks: { + delete: [1] + } + }) { + id + name + tasks { + id + name + } + } + } + ')->assertJson([ + 'data' => [ + 'updateUser' => [ + 'id' => '1', + 'name' => 'foo', + 'tasks' => [], + ], + ], + ]); + } +} diff --git a/tests/Integration/Execution/MutationExecutor/HasOneTest.php b/tests/Integration/Execution/MutationExecutor/HasOneTest.php new file mode 100644 index 0000000000..01800d9fc6 --- /dev/null +++ b/tests/Integration/Execution/MutationExecutor/HasOneTest.php @@ -0,0 +1,230 @@ +schema .= $this->placeholderQuery(); + } + + /** + * @test + */ + public function itCanCreateWithNewHasOne(): void + { + $this->query(' + mutation { + createTask(input: { + name: "foo" + post: { + create: { + title: "bar" + } + } + }) { + id + name + post { + id + title + } + } + } + ')->assertJson([ + 'data' => [ + 'createTask' => [ + 'id' => '1', + 'name' => 'foo', + 'post' => [ + 'id' => '1', + 'title' => 'bar', + ], + ], + ], + ]); + } + + /** + * @test + */ + public function itCanUpdateWithNewHasOne(): void + { + factory(Task::class)->create(); + + $this->query(' + mutation { + updateTask(input: { + id: 1 + name: "foo" + post: { + create: { + title: "bar" + } + } + }) { + id + name + post { + id + title + } + } + } + ')->assertJson([ + 'data' => [ + 'updateTask' => [ + 'id' => '1', + 'name' => 'foo', + 'post' => [ + 'id' => '1', + 'title' => 'bar', + ], + ], + ], + ]); + } + + /** + * @test + */ + public function itCanUpdateAndUpdateHasOne(): void + { + factory(Task::class) + ->create() + ->post() + ->save( + factory(Post::class)->create() + ); + + $this->query(' + mutation { + updateTask(input: { + id: 1 + name: "foo" + post: { + update: { + id: 1 + title: "bar" + } + } + }) { + id + name + post { + id + title + } + } + } + ')->assertJson([ + 'data' => [ + 'updateTask' => [ + 'id' => '1', + 'name' => 'foo', + 'post' => [ + 'id' => '1', + 'title' => 'bar', + ], + ], + ], + ]); + } + + /** + * @test + */ + public function itCanUpdateAndDeleteHasOne(): void + { + factory(Task::class) + ->create() + ->post() + ->save( + factory(Post::class)->create() + ); + + $this->query(' + mutation { + updateTask(input: { + id: 1 + name: "foo" + post: { + delete: 1 + } + }) { + id + name + post { + id + title + } + } + } + ')->assertJson([ + 'data' => [ + 'updateTask' => [ + 'id' => '1', + 'name' => 'foo', + 'post' => null, + ], + ], + ]); + } +} diff --git a/tests/Integration/Execution/MutationExecutor/MorphManyTest.php b/tests/Integration/Execution/MutationExecutor/MorphManyTest.php new file mode 100644 index 0000000000..f227d4fbb3 --- /dev/null +++ b/tests/Integration/Execution/MutationExecutor/MorphManyTest.php @@ -0,0 +1,227 @@ +schema .= $this->placeholderQuery(); + } + + /** + * @test + */ + public function itCanCreateWithNewMorphMany(): void + { + $this->query(' + mutation { + createTask(input: { + name: "foo" + hours: { + create: [{ + weekday: 3 + }] + } + }) { + id + name + hours { + weekday + } + } + } + ')->assertJson([ + 'data' => [ + 'createTask' => [ + 'id' => '1', + 'name' => 'foo', + 'hours' => [ + [ + 'weekday' => 3, + ], + ], + ], + ], + ]); + } + + /** + * @test + */ + public function itCanUpdateWithNewMorphMany(): void + { + factory(Task::class)->create(); + + $this->query(' + mutation { + updateTask(input: { + id: 1 + name: "foo" + hours: { + create: [{ + weekday: 3 + }] + } + }) { + id + name + hours { + weekday + } + } + } + ')->assertJson([ + 'data' => [ + 'updateTask' => [ + 'id' => '1', + 'name' => 'foo', + 'hours' => [ + [ + 'weekday' => 3, + ], + ], + ], + ], + ]); + } + + /** + * @test + */ + public function itCanUpdateAndUpdateMorphMany(): void + { + factory(Task::class) + ->create() + ->hours() + ->save( + factory(Hour::class)->create() + ); + + $this->query(' + mutation { + updateTask(input: { + id: 1 + name: "foo" + hours: { + update: [{ + id: 1 + weekday: 3 + }] + } + }) { + id + name + hours { + weekday + } + } + } + ')->assertJson([ + 'data' => [ + 'updateTask' => [ + 'id' => '1', + 'name' => 'foo', + 'hours' => [ + [ + 'weekday' => 3, + ], + ], + ], + ], + ]); + } + + /** + * @test + */ + public function itCanUpdateAndDeleteMorphMany(): void + { + factory(Task::class) + ->create() + ->hours() + ->save( + factory(Hour::class)->create() + ); + + $this->query(' + mutation { + updateTask(input: { + id: 1 + name: "foo" + hours: { + delete: [1] + } + }) { + id + name + hours { + weekday + } + } + } + ')->assertJson([ + 'data' => [ + 'updateTask' => [ + 'id' => '1', + 'name' => 'foo', + 'hours' => [], + ], + ], + ]); + } +} diff --git a/tests/Integration/Execution/MutationExecutor/MorphOneTest.php b/tests/Integration/Execution/MutationExecutor/MorphOneTest.php new file mode 100644 index 0000000000..aee8feb549 --- /dev/null +++ b/tests/Integration/Execution/MutationExecutor/MorphOneTest.php @@ -0,0 +1,221 @@ +schema .= $this->placeholderQuery(); + } + + /** + * @test + */ + public function itCanCreateWithNewMorphOne(): void + { + $this->query(' + mutation { + createTask(input: { + name: "foo" + hour: { + create: { + weekday: 3 + } + } + }) { + id + name + hour { + weekday + } + } + } + ')->assertJson([ + 'data' => [ + 'createTask' => [ + 'id' => '1', + 'name' => 'foo', + 'hour' => [ + 'weekday' => 3, + ], + ], + ], + ]); + } + + /** + * @test + */ + public function itCanUpdateWithNewMorphOne(): void + { + factory(Task::class)->create(); + + $this->query(' + mutation { + updateTask(input: { + id: 1 + name: "foo" + hour: { + create: { + weekday: 3 + } + } + }) { + id + name + hour { + weekday + } + } + } + ')->assertJson([ + 'data' => [ + 'updateTask' => [ + 'id' => '1', + 'name' => 'foo', + 'hour' => [ + 'weekday' => 3, + ], + ], + ], + ]); + } + + /** + * @test + */ + public function itCanUpdateAndUpdateMorphOne(): void + { + factory(Task::class) + ->create() + ->hour() + ->save( + factory(Hour::class)->create() + ); + + $this->query(' + mutation { + updateTask(input: { + id: 1 + name: "foo" + hour: { + update: { + id: 1 + weekday: 3 + } + } + }) { + id + name + hour { + weekday + } + } + } + ')->assertJson([ + 'data' => [ + 'updateTask' => [ + 'id' => '1', + 'name' => 'foo', + 'hour' => [ + 'weekday' => 3, + ], + ], + ], + ]); + } + + /** + * @test + */ + public function itCanUpdateAndDeleteMorphOne(): void + { + factory(Task::class) + ->create() + ->hour() + ->save( + factory(Hour::class)->create() + ); + + $this->query(' + mutation { + updateTask(input: { + id: 1 + name: "foo" + hour: { + delete: 1 + } + }) { + id + name + hour { + weekday + } + } + } + ')->assertJson([ + 'data' => [ + 'updateTask' => [ + 'id' => '1', + 'name' => 'foo', + 'hour' => null, + ], + ], + ]); + } +} diff --git a/tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/MorphToTest.php b/tests/Integration/Execution/MutationExecutor/MorphToTest.php similarity index 59% rename from tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/MorphToTest.php rename to tests/Integration/Execution/MutationExecutor/MorphToTest.php index 19374add2f..90309e92b8 100644 --- a/tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/MorphToTest.php +++ b/tests/Integration/Execution/MutationExecutor/MorphToTest.php @@ -1,12 +1,44 @@ schema .= $this->placeholderQuery(); + } + /** * @test */ @@ -14,33 +46,6 @@ public function itCanCreateAndConnectWithMorphTo(): void { factory(Task::class)->create(['name' => 'first_task']); - $this->schema = ' - type Task { - id: ID - name: String - hour: Hour - } - - type Hour { - id: ID - weekday: Int - hourable: Task - } - - type Mutation { - createHour(input: CreateHourInput!): Hour @create(flatten: true) - } - - input CreateHourInput { - hourable_type: String! - hourable_id: Int! - from: String - to: String - weekday: Int - } - - '.$this->placeholderQuery(); - $this->query(' mutation { createHour(input: { diff --git a/tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/CoreTest.php b/tests/Integration/Schema/Directives/Fields/CreateDirectiveTest.php similarity index 98% rename from tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/CoreTest.php rename to tests/Integration/Schema/Directives/Fields/CreateDirectiveTest.php index 9467bfd2a0..b29046bfb0 100644 --- a/tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/CoreTest.php +++ b/tests/Integration/Schema/Directives/Fields/CreateDirectiveTest.php @@ -1,13 +1,13 @@ schema = ' - type Role { - id: ID! - name: String - users: [User] @belongsToMany - } - - type User { - id: ID - name: String - } - - type Mutation { - createRole(input: CreateRoleInput!): Role @create(flatten: true) - } - - input CreateRoleInput { - name: String - users: CreateUserRelation - } - - input CreateUserRelation { - create: [CreateUserInput!] - } - - input CreateUserInput { - name: String - } - '.$this->placeholderQuery(); - - $this->query(' - mutation { - createRole(input: { - name: "foobar" - users: { - create: [{ - name: "bar" - }, - { - name: "foo" - }] - } - }) { - id - name - users { - id - name - } - } - } - ')->assertJson([ - 'data' => [ - 'createRole' => [ - 'id' => '1', - 'name' => 'foobar', - 'users' => [ - [ - 'id' => '1', - 'name' => 'bar', - ], - ], - ], - ], - ]); - } - - /** - * @test - */ - public function itCanCreateAndConnectWithBelongsToMany(): void - { - factory(User::class)->create(['name' => 'user_one']); - factory(User::class)->create(['name' => 'user_two']); - - $this->schema = ' - type Role { - id: ID! - name: String - users: [User] @belongsToMany - } - - type User { - id: ID - name: String - } - - type Mutation { - createRole(input: CreateRoleInput!): Role @create(flatten: true) - } - - input CreateRoleInput { - name: String - users: CreateUserRelation - } - - input CreateUserRelation { - connect: [ID] - } - - '.$this->placeholderQuery(); - - $this->query(' - mutation { - createRole(input: { - name: "foobar" - users: { - connect: [ - 1,2 - ] - } - }) { - id - name - users { - id - name - } - } - } - ')->assertJson([ - 'data' => [ - 'createRole' => [ - 'id' => '1', - 'name' => 'foobar', - 'users' => [ - [ - 'id' => '1', - 'name' => 'user_one', - ], - [ - 'id' => '2', - 'name' => 'user_two', - ], - ], - ], - ], - ]); - } -} diff --git a/tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/HasManyTest.php b/tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/HasManyTest.php deleted file mode 100644 index cce24f1653..0000000000 --- a/tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/HasManyTest.php +++ /dev/null @@ -1,78 +0,0 @@ -schema = ' - type Task { - id: ID! - name: String! - } - - type User { - id: ID! - name: String - tasks: [Task!]! @hasMany - } - - type Mutation { - createUser(input: CreateUserInput!): User @create(flatten: true) - } - - input CreateUserInput { - name: String - tasks: CreateTaskRelation - } - - input CreateTaskRelation { - create: [CreateTaskInput!] - } - - input CreateTaskInput { - name: String - user: ID - } - '.$this->placeholderQuery(); - - $this->query(' - mutation { - createUser(input: { - name: "foo" - tasks: { - create: [{ - name: "bar" - }] - } - }) { - id - name - tasks { - id - name - } - } - } - ')->assertJson([ - 'data' => [ - 'createUser' => [ - 'id' => '1', - 'name' => 'foo', - 'tasks' => [ - [ - 'id' => '1', - 'name' => 'bar', - ], - ], - ], - ], - ]); - } -} diff --git a/tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/HasOneTest.php b/tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/HasOneTest.php deleted file mode 100644 index 9fb7a82b57..0000000000 --- a/tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/HasOneTest.php +++ /dev/null @@ -1,89 +0,0 @@ -create(); - - $this->schema = ' - type Task { - id: ID! - name: String! - post: Post @hasOne - } - - type Post { - id: ID! - title: String! - body: String! - } - - type Mutation { - createTask(input: CreateTaskInput!): Task @create(flatten: true) - } - - input CreatePostRelation { - create: CreatePostInput! - } - - input CreatePostRelation { - create: CreatePostInput! - } - - input CreateTaskInput { - name: String! - user_id: ID! - post: CreatePostRelation - } - - input CreatePostInput { - title: String! - user_id: ID! - body: String! - } - '.$this->placeholderQuery(); - - $this->query(' - mutation { - createTask(input: { - name: "foo" - user_id: 1 - post: { - create: { - title: "bar" - user_id: 1 - body: "foobar" - } - } - }) { - id - name - post { - id - body - } - } - } - ')->assertJson([ - 'data' => [ - 'createTask' => [ - 'id' => '1', - 'name' => 'foo', - 'post' => [ - 'id' => '1', - 'body' => 'foobar', - ], - ], - ], - ]); - } -} diff --git a/tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/MorphManyTest.php b/tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/MorphManyTest.php deleted file mode 100644 index df2c5cbbf9..0000000000 --- a/tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/MorphManyTest.php +++ /dev/null @@ -1,81 +0,0 @@ -create(); - - $this->schema = ' - type Task { - id: ID! - name: String! - hours: [Hour] - } - - type Hour { - weekday: Int - } - - type Mutation { - createTask(input: CreateTaskInput!): Task @create(flatten: true) - } - - input CreateHourRelation { - create: [CreateHourInput!]! - } - - input CreateTaskInput { - name: String! - user_id: ID! - hours: CreateHourRelation - } - - input CreateHourInput { - from: String - to: String - weekday: Int - } - '.$this->placeholderQuery(); - - $this->query(' - mutation { - createTask(input: { - name: "foo" - user_id: 1 - hours: { - create: [{ - weekday: 3 - }] - } - }) { - id - name - hours { - weekday - } - } - } - ')->assertJson([ - 'data' => [ - 'createTask' => [ - 'id' => '1', - 'name' => 'foo', - 'hours' => [ - [ - 'weekday' => 3, - ], - ], - ], - ], - ]); - } -} diff --git a/tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/MorphOneTest.php b/tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/MorphOneTest.php deleted file mode 100644 index e36deda33a..0000000000 --- a/tests/Integration/Schema/Directives/Fields/CreateDirectiveTests/RelationshipTests/MorphOneTest.php +++ /dev/null @@ -1,79 +0,0 @@ -create(); - - $this->schema = ' - type Task { - id: ID! - name: String! - hour: Hour - } - - type Hour { - weekday: Int - } - - type Mutation { - createTask(input: CreateTaskInput!): Task @create(flatten: true) - } - - input CreateHourRelation { - create: CreateHourInput! - } - - input CreateTaskInput { - name: String! - user_id: ID! - hour: CreateHourRelation - } - - input CreateHourInput { - from: String - to: String - weekday: Int - } - '.$this->placeholderQuery(); - - $this->query(' - mutation { - createTask(input: { - name: "foo" - user_id: 1 - hour: { - create: { - weekday: 3 - } - } - }) { - id - name - hour { - weekday - } - } - } - ')->assertJson([ - 'data' => [ - 'createTask' => [ - 'id' => '1', - 'name' => 'foo', - 'hour' => [ - 'weekday' => 3, - ], - ], - ], - ]); - } -} diff --git a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/CoreTest.php b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTest.php similarity index 96% rename from tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/CoreTest.php rename to tests/Integration/Schema/Directives/Fields/UpdateDirectiveTest.php index 08f587bfc4..f8d5f65077 100644 --- a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/CoreTest.php +++ b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTest.php @@ -1,14 +1,13 @@ schema .= $this->placeholderQuery(); - } - - /** - * @test - */ - public function itCanUpdateAndDisconnectBelongsTo(): void - { - /** @var \Tests\Utils\Models\Post $post */ - $post = factory(Post::class)->create(); - $post - ->parent() - ->associate( - factory(Post::class)->create() - ) - ->save(); - - $this->query(' - mutation { - updatePost(input: { - id: 1 - title: "foo" - parent: { - disconnect: true - } - }) { - id - title - parent { - id - } - } - } - ')->assertJson([ - 'data' => [ - 'updatePost' => [ - 'id' => '1', - 'title' => 'foo', - 'parent' => null, - ], - ], - ]); - - $this->assertTrue( - Post::find(2)->exists, - 'Must not delete the second model.' - ); - - $this->assertNull( - Post::find(1)->parent, - 'Must disconnect the parent relationship.' - ); - } - - /** - * @test - */ - public function itCanUpdateAndDeleteBelongsTo(): void - { - /** @var \Tests\Utils\Models\Post $post */ - $post = factory(Post::class)->create(); - $post - ->parent() - ->associate( - factory(Post::class)->create() - ) - ->save(); - - $this->query(' - mutation { - updatePost(input: { - id: 1 - title: "foo" - parent: { - delete: true - } - }) { - id - title - parent { - id - } - } - } - ')->assertJson([ - 'data' => [ - 'updatePost' => [ - 'id' => '1', - 'title' => 'foo', - 'parent' => null, - ], - ], - ]); - - $this->assertNull( - Post::find(2), - 'This model should be deleted.' - ); - - $this->assertNull( - Post::find(1)->parent, - 'Must disconnect the parent relationship.' - ); - } - - /** - * @test - */ - public function itDoesNotDeleteOrDisconnectOnFalsyValues(): void - { - /** @var \Tests\Utils\Models\Post $post */ - $post = factory(Post::class)->create(); - $post - ->parent() - ->associate( - factory(Post::class)->create() - ) - ->save(); - - $this->query(' - mutation { - updatePost(input: { - id: 1 - title: "foo" - parent: { - delete: null - disconnect: false - } - }) { - id - title - parent { - id - } - } - } - ')->assertJson([ - 'data' => [ - 'updatePost' => [ - 'id' => '1', - 'title' => 'foo', - 'parent' => [ - 'id' => '2' - ], - ], - ], - ]); - - $this->assertSame( - 2, - Post::find(1)->parent->id, - 'The parent relationship remains untouched.' - ); - } -} diff --git a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/HasManyTest.php b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/HasManyTest.php deleted file mode 100644 index bf586d1b03..0000000000 --- a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTests/RelationshipTests/HasManyTest.php +++ /dev/null @@ -1,9 +0,0 @@ - Date: Tue, 19 Mar 2019 10:37:24 +0100 Subject: [PATCH 18/18] zOGM7B --- .../Integration/Execution/MutationExecutor/BelongsToTest.php | 4 ++-- tests/Integration/Execution/MutationExecutor/HasOneTest.php | 1 - .../Integration/Execution/MutationExecutor/MorphManyTest.php | 1 - tests/Integration/Execution/MutationExecutor/MorphOneTest.php | 1 - .../Schema/Directives/Fields/CreateDirectiveTest.php | 2 +- .../Schema/Directives/Fields/UpdateDirectiveTest.php | 4 ++-- 6 files changed, 5 insertions(+), 8 deletions(-) diff --git a/tests/Integration/Execution/MutationExecutor/BelongsToTest.php b/tests/Integration/Execution/MutationExecutor/BelongsToTest.php index 4bf9ef5cde..92e5f5ea5e 100644 --- a/tests/Integration/Execution/MutationExecutor/BelongsToTest.php +++ b/tests/Integration/Execution/MutationExecutor/BelongsToTest.php @@ -140,7 +140,7 @@ public function itCanCreateWithNewBelongsTo(): void public function itCanCreateAndUpdateBelongsTo(): void { factory(User::class)->create([ - 'name' => 'foo' + 'name' => 'foo', ]); $this->query(' @@ -294,7 +294,7 @@ public function itDoesNotDeleteOrDisconnectOnFalsyValues(): void 'id' => '1', 'name' => 'foo', 'user' => [ - 'id' => '1' + 'id' => '1', ], ], ], diff --git a/tests/Integration/Execution/MutationExecutor/HasOneTest.php b/tests/Integration/Execution/MutationExecutor/HasOneTest.php index 01800d9fc6..2f81649a1f 100644 --- a/tests/Integration/Execution/MutationExecutor/HasOneTest.php +++ b/tests/Integration/Execution/MutationExecutor/HasOneTest.php @@ -5,7 +5,6 @@ use Tests\DBTestCase; use Tests\Utils\Models\Post; use Tests\Utils\Models\Task; -use Tests\Utils\Models\User; class HasOneTest extends DBTestCase { diff --git a/tests/Integration/Execution/MutationExecutor/MorphManyTest.php b/tests/Integration/Execution/MutationExecutor/MorphManyTest.php index f227d4fbb3..57db711105 100644 --- a/tests/Integration/Execution/MutationExecutor/MorphManyTest.php +++ b/tests/Integration/Execution/MutationExecutor/MorphManyTest.php @@ -5,7 +5,6 @@ use Tests\DBTestCase; use Tests\Utils\Models\Hour; use Tests\Utils\Models\Task; -use Tests\Utils\Models\User; class MorphManyTest extends DBTestCase { diff --git a/tests/Integration/Execution/MutationExecutor/MorphOneTest.php b/tests/Integration/Execution/MutationExecutor/MorphOneTest.php index aee8feb549..9e4e7873a6 100644 --- a/tests/Integration/Execution/MutationExecutor/MorphOneTest.php +++ b/tests/Integration/Execution/MutationExecutor/MorphOneTest.php @@ -5,7 +5,6 @@ use Tests\DBTestCase; use Tests\Utils\Models\Hour; use Tests\Utils\Models\Task; -use Tests\Utils\Models\User; class MorphOneTest extends DBTestCase { diff --git a/tests/Integration/Schema/Directives/Fields/CreateDirectiveTest.php b/tests/Integration/Schema/Directives/Fields/CreateDirectiveTest.php index b29046bfb0..60300af0c9 100644 --- a/tests/Integration/Schema/Directives/Fields/CreateDirectiveTest.php +++ b/tests/Integration/Schema/Directives/Fields/CreateDirectiveTest.php @@ -2,10 +2,10 @@ namespace Tests\Integration\Schema\Directives\Fields; -use CreateTestbenchTagsTable; use Tests\DBTestCase; use Tests\Utils\Models\Task; use Tests\Utils\Models\User; +use CreateTestbenchTagsTable; class CreateDirectiveTest extends DBTestCase { diff --git a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTest.php b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTest.php index f8d5f65077..98d10a8f64 100644 --- a/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTest.php +++ b/tests/Integration/Schema/Directives/Fields/UpdateDirectiveTest.php @@ -3,9 +3,9 @@ namespace Tests\Integration\Schema\Directives\Fields; use Tests\DBTestCase; -use Tests\Utils\Models\Category; -use Tests\Utils\Models\Company; use Tests\Utils\Models\User; +use Tests\Utils\Models\Company; +use Tests\Utils\Models\Category; class UpdateDirectiveTest extends DBTestCase {