From e8adf6bd556d6e43b33ae815bad2574bc6ef72d5 Mon Sep 17 00:00:00 2001 From: spawnia Date: Fri, 14 Dec 2018 16:28:12 +0100 Subject: [PATCH 1/2] Add a test for the create directive nested has many --- .../Directives/Fields/CreateDirectiveTest.php | 62 +++++++++++++++++++ ...28_000002_create_testbench_users_table.php | 8 +-- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/tests/Integration/Schema/Directives/Fields/CreateDirectiveTest.php b/tests/Integration/Schema/Directives/Fields/CreateDirectiveTest.php index 1f83a5efd9..4adc05be86 100644 --- a/tests/Integration/Schema/Directives/Fields/CreateDirectiveTest.php +++ b/tests/Integration/Schema/Directives/Fields/CreateDirectiveTest.php @@ -119,4 +119,66 @@ public function itCanCreateWithBelongsTo() $this->assertSame('foo', Arr::get($result, 'data.createTask.name')); $this->assertSame('1', Arr::get($result, 'data.createTask.user.id')); } + + /** + * @test + */ + public function itCanCreateWithHasMany() + { + $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(); + $query = ' + mutation { + createUser(input: { + name: "foo" + tasks: { + create: [{ + name: "bar" + }] + } + }) { + id + name + tasks { + id + name + } + } + } + '; + $result = $this->execute($schema, $query); + + $this->assertSame('1', Arr::get($result, 'data.createUser.id')); + $this->assertSame('foo', Arr::get($result, 'data.createUser.name')); + $this->assertSame('1', Arr::get($result, 'data.createUser.tasks.0.id')); + $this->assertSame('bar', Arr::get($result, 'data.createUser.tasks.0.name')); + } } diff --git a/tests/database/migrations/2018_02_28_000002_create_testbench_users_table.php b/tests/database/migrations/2018_02_28_000002_create_testbench_users_table.php index fae93e1ebf..c9f545772c 100644 --- a/tests/database/migrations/2018_02_28_000002_create_testbench_users_table.php +++ b/tests/database/migrations/2018_02_28_000002_create_testbench_users_table.php @@ -13,11 +13,11 @@ public function up() { Schema::create('users', function (Blueprint $table) { $table->increments('id'); - $table->unsignedInteger('company_id'); + $table->unsignedInteger('company_id')->nullable(); $table->unsignedInteger('team_id')->nullable(); - $table->string('name'); - $table->string('email'); - $table->string('password'); + $table->string('name')->nullable(); + $table->string('email')->nullable(); + $table->string('password')->nullable(); $table->timestamps(); }); } From 68cf80c29e69754b9cdb0e143e35e29bcf218871 Mon Sep 17 00:00:00 2001 From: spawnia Date: Fri, 14 Dec 2018 16:29:09 +0100 Subject: [PATCH 2/2] Refresh newly created models before returning them Resolves #501 --- src/Execution/MutationExecutor.php | 30 +++++++++++++----- .../Directives/Fields/CreateDirectiveTest.php | 31 +++++++++++++++++++ ..._30_000006_create_testbench_tags_table.php | 3 ++ 3 files changed, 56 insertions(+), 8 deletions(-) diff --git a/src/Execution/MutationExecutor.php b/src/Execution/MutationExecutor.php index b26dfd53a7..928a7780da 100644 --- a/src/Execution/MutationExecutor.php +++ b/src/Execution/MutationExecutor.php @@ -34,6 +34,10 @@ public static function executeCreate(Model $model, Collection $args, HasMany $pa }); }); + // Make sure that values that are set through the database insert + // are immediately available for return, e.g. default values + $model->refresh(); + return $model; } @@ -73,7 +77,11 @@ protected static function saveModelWithBelongsTo(Model $model, Collection $remai protected static function handleHasManyCreate(Collection $multiValues, HasMany $relation) { $multiValues->each(function ($singleValues) use ($relation) { - self::executeCreate($relation->getModel()->newInstance(), collect($singleValues), $relation); + self::executeCreate( + $relation->getModel()->newInstance(), + collect($singleValues), + $relation + ); }); } @@ -99,18 +107,22 @@ public static function executeUpdate(Model $model, Collection $args, HasMany $pa $model = self::saveModelWithBelongsTo($model, $remaining, $parentRelation); - $hasMany->each(function ($nestedOperations, $relationName) use ($model) { + $hasMany->each(function ($nestedOperations, string $relationName) use ($model) { /** @var HasMany $relation */ $relation = $model->{$relationName}(); - collect($nestedOperations)->each(function ($values, $operationKey) use ($relation) { + collect($nestedOperations)->each(function ($values, string $operationKey) use ($relation) { if ($operationKey === 'create') { self::handleHasManyCreate(collect($values), $relation); } if ($operationKey === 'update') { collect($values)->each(function ($singleValues) use ($relation) { - self::executeUpdate($relation->getModel()->newInstance(), collect($singleValues), $relation); + self::executeUpdate( + $relation->getModel()->newInstance(), + collect($singleValues), + $relation + ); }); } @@ -144,8 +156,9 @@ public static function executeUpdate(Model $model, Collection $args, HasMany $pa */ protected static function extractBelongsToArgs(Model $model, Collection $args): Collection { - return $args->partition(function ($value, $key) use ($model) { - return method_exists($model, $key) && ($model->{$key}() instanceof BelongsTo); + return $args->partition(function ($value, string $key) use ($model) { + return method_exists($model, $key) + && ($model->{$key}() instanceof BelongsTo); }); } @@ -179,8 +192,9 @@ protected static function extractBelongsToArgs(Model $model, Collection $args): */ protected static function extractHasManyArgs(Model $model, Collection $args): Collection { - return $args->partition(function ($value, $key) use ($model) { - return method_exists($model, $key) && ($model->{$key}() instanceof HasMany); + return $args->partition(function ($value, string $key) use ($model) { + return method_exists($model, $key) + && ($model->{$key}() instanceof HasMany); }); } } diff --git a/tests/Integration/Schema/Directives/Fields/CreateDirectiveTest.php b/tests/Integration/Schema/Directives/Fields/CreateDirectiveTest.php index 4adc05be86..1a0d15e0da 100644 --- a/tests/Integration/Schema/Directives/Fields/CreateDirectiveTest.php +++ b/tests/Integration/Schema/Directives/Fields/CreateDirectiveTest.php @@ -181,4 +181,35 @@ public function itCanCreateWithHasMany() $this->assertSame('1', Arr::get($result, 'data.createUser.tasks.0.id')); $this->assertSame('bar', Arr::get($result, 'data.createUser.tasks.0.name')); } + + /** + * @test + */ + public function itCreatesAnEntryWithDatabaseDefaultsAndReturnsItImmediately() + { + $schema = ' + type Mutation { + createTag(name: String): Tag @create + } + + type Tag { + name: String! + default_string: String! + } + ' . $this->placeholderQuery(); + $query = ' + mutation { + createTag(name: "foobar"){ + name + default_string + } + } + '; + $result = $this->execute($schema, $query); + + $this->assertSame([ + 'name' => 'foobar', + 'default_string' => \CreateTestbenchTagsTable::DEFAULT_STRING, + ], Arr::get($result, 'data.createTag')); + } } diff --git a/tests/database/migrations/2018_09_30_000006_create_testbench_tags_table.php b/tests/database/migrations/2018_09_30_000006_create_testbench_tags_table.php index cb2b44b91b..69b6e5dd1f 100644 --- a/tests/database/migrations/2018_09_30_000006_create_testbench_tags_table.php +++ b/tests/database/migrations/2018_09_30_000006_create_testbench_tags_table.php @@ -6,6 +6,8 @@ class CreateTestbenchTagsTable extends Migration { + const DEFAULT_STRING = 'this is the default string'; + /** * Run the migrations. */ @@ -14,6 +16,7 @@ public function up() Schema::create('tags', function (Blueprint $table) { $table->increments('id'); $table->string('name'); + $table->string('default_string')->default(self::DEFAULT_STRING); $table->timestamps(); }); }