From 4146aaa617fa3ac1737b6ff6de3abd03ae802097 Mon Sep 17 00:00:00 2001 From: Robert van Steen Date: Wed, 18 Jul 2018 11:10:46 +0200 Subject: [PATCH 1/5] Properly set relationships to null --- .../Concerns/InteractsWithRelations.php | 15 +++++- tests/Feature/CreateMutationTest.php | 52 +++++++++++++++++++ tests/Feature/UpdateMutationTest.php | 21 ++++++++ tests/FeatureTestCase.php | 1 + tests/Models/Article.php | 5 ++ tests/Models/Category.php | 19 +++++++ tests/Stubs/BakeryModels/ArticleBakery.php | 1 + tests/Stubs/BakeryModels/CategoryBakery.php | 27 ++++++++++ tests/Stubs/Policies/ArticlePolicy.php | 5 ++ ...0_00_00_000000_create_categories_table.php | 23 ++++++++ ...000_00_00_000001_create_articles_table.php | 5 ++ .../0000_00_00_000002_create_phones_table.php | 2 +- 12 files changed, 173 insertions(+), 3 deletions(-) create mode 100644 tests/Models/Category.php create mode 100644 tests/Stubs/BakeryModels/CategoryBakery.php create mode 100644 tests/migrations/0000_00_00_000000_create_categories_table.php diff --git a/src/Eloquent/Concerns/InteractsWithRelations.php b/src/Eloquent/Concerns/InteractsWithRelations.php index b2138132..851d0944 100644 --- a/src/Eloquent/Concerns/InteractsWithRelations.php +++ b/src/Eloquent/Concerns/InteractsWithRelations.php @@ -78,6 +78,10 @@ protected function fillConnections(array $connections) */ protected function connectBelongsToRelation(Relations\BelongsTo $relation, $id) { + if (!$id) { + return $relation->associate(null); + } + $model = $relation->getRelated()->findOrFail($id); $relation->associate($model); } @@ -104,9 +108,16 @@ protected function fillBelongsToRelation(Relations\BelongsTo $relation, $attribu */ protected function connectHasOneRelation(Relations\HasOne $relation, $id) { - $model = $relation->getRelated()->findOrFail($id); + if (!$id) { + if ($related = $relation->getResults()) { + $related->setAttribute($relation->getForeignKeyName(), null); + $related->save(); + } + return; + } - $this->transactionQueue[] = function () use ($model, $relation) { + $this->transactionQueue[] = function () use ($id, $relation) { + $model = $relation->getRelated()->findOrFail($id); $model->setAttribute($relation->getForeignKeyName(), $relation->getParentKey()); $model->save(); }; diff --git a/tests/Feature/CreateMutationTest.php b/tests/Feature/CreateMutationTest.php index abc23c40..3d449d6d 100644 --- a/tests/Feature/CreateMutationTest.php +++ b/tests/Feature/CreateMutationTest.php @@ -125,6 +125,30 @@ public function it_lets_you_save_a_has_one_relationship() $this->assertDatabaseHas('phones', ['user_id' => '2']); } + /** @test */ + public function it_lets_you_set_a_has_one_relationship_to_null() + { + $user = factory(Models\User::class)->create(); + $this->actingAs($user); + + $query = ' + mutation { + createUser(input: { + email: "jane.doe@example.com", + name: "Jane Doe", + password: "secret", + phoneId: null, + }) { + id + } + } + '; + + $response = $this->json('GET', '/graphql', ['query' => $query]); + $response->assertJsonFragment(['id']); + $this->assertDatabaseHas('users', ['email' => 'jane.doe@example.com']); + } + /** @test */ public function it_lets_you_create_a_belongs_to_relationship() { @@ -270,4 +294,32 @@ public function it_lets_you_do_deep_nested_create_mutations() $this->assertDatabaseHas('comments', ['body' => 'First!', 'article_id' => '1']); $this->assertDatabaseHas('comments', ['body' => 'Great post!', 'article_id' => '1']); } + + /** @test */ + public function it_lets_you_reset_a_belongs_to_relationship() + { + $user = factory(Models\User::class)->create(); + $this->actingAs($user); + + $query = ' + mutation { + createArticle(input: { + userId: "'.$user->id.'", + categoryId: null, + title: "Hello World!" + slug: "hello-world" + content: "Lorem ipsum" + }) { + id + } + } + '; + + $response = $this->json('GET', '/graphql', ['query' => $query]); + $response->assertJsonFragment(['id']); + // $this->assertDatabaseHas('users', ['email' => 'jane.doe@example.com', 'name' => 'Jane Doe']); + // $this->assertDatabaseHas('articles', ['title' => 'Hello World!', 'user_id' => '2']); + // $this->assertDatabaseHas('comments', ['body' => 'First!', 'article_id' => '1']); + // $this->assertDatabaseHas('comments', ['body' => 'Great post!', 'article_id' => '1']); + } } diff --git a/tests/Feature/UpdateMutationTest.php b/tests/Feature/UpdateMutationTest.php index c82eab58..9570eef6 100644 --- a/tests/Feature/UpdateMutationTest.php +++ b/tests/Feature/UpdateMutationTest.php @@ -163,4 +163,25 @@ public function it_can_set_policy_for_updating_an_attribute() $response->assertJsonFragment(['updateUser' => null]); $this->assertDatabaseMissing('users', ['type' => 'admin']); } + + /** @test */ + public function it_lets_you_reset_a_has_one_relationship() + { + $phone = factory(Models\Phone::class)->create(); + $this->actingAs($phone->user); + + $query = ' + mutation { + updateUser(id: "'.$phone->user->id.'", input: { + phoneId: null, + }) { + id + } + } + '; + + $response = $this->json('GET', '/graphql', ['query' => $query]); + $response->assertJsonFragment(['id']); + $this->assertDatabaseHas('phones', ['user_id' => null]); + } } diff --git a/tests/FeatureTestCase.php b/tests/FeatureTestCase.php index 0c4fc974..d21c5ca6 100644 --- a/tests/FeatureTestCase.php +++ b/tests/FeatureTestCase.php @@ -48,6 +48,7 @@ protected function setUp() Stubs\BakeryModels\PhoneBakery::class, Stubs\BakeryModels\CommentBakery::class, Stubs\BakeryModels\RoleBakery::class, + Stubs\BakeryModels\CategoryBakery::class, ]); } diff --git a/tests/Models/Article.php b/tests/Models/Article.php index 6caa93e3..646f68f4 100644 --- a/tests/Models/Article.php +++ b/tests/Models/Article.php @@ -30,4 +30,9 @@ public function comments() { return $this->hasMany(Comment::class); } + + public function category() + { + return $this->belongsTo(Category::class); + } } diff --git a/tests/Models/Category.php b/tests/Models/Category.php new file mode 100644 index 00000000..ac16ce29 --- /dev/null +++ b/tests/Models/Category.php @@ -0,0 +1,19 @@ + 'string', + ]; + + protected $fillable = [ + 'name', + ]; +} diff --git a/tests/Stubs/BakeryModels/ArticleBakery.php b/tests/Stubs/BakeryModels/ArticleBakery.php index 91b65bb1..708514aa 100644 --- a/tests/Stubs/BakeryModels/ArticleBakery.php +++ b/tests/Stubs/BakeryModels/ArticleBakery.php @@ -26,6 +26,7 @@ public function relations(): array { return [ 'user' => Bakery::type('User'), + 'category' => Bakery::type('Category'), 'comments' => Bakery::nonNull(Bakery::listOf(Bakery::type('Comment'))), ]; } diff --git a/tests/Stubs/BakeryModels/CategoryBakery.php b/tests/Stubs/BakeryModels/CategoryBakery.php new file mode 100644 index 00000000..b710c603 --- /dev/null +++ b/tests/Stubs/BakeryModels/CategoryBakery.php @@ -0,0 +1,27 @@ + Type::nonNull(Type::string()), + ]; + } + + public function relations(): array + { + return []; + } +} diff --git a/tests/Stubs/Policies/ArticlePolicy.php b/tests/Stubs/Policies/ArticlePolicy.php index 1f3ac715..ee85d755 100644 --- a/tests/Stubs/Policies/ArticlePolicy.php +++ b/tests/Stubs/Policies/ArticlePolicy.php @@ -29,6 +29,11 @@ public function setUser(): bool return true; } + public function setCategory(): bool + { + return true; + } + public function createComments(): bool { return true; diff --git a/tests/migrations/0000_00_00_000000_create_categories_table.php b/tests/migrations/0000_00_00_000000_create_categories_table.php new file mode 100644 index 00000000..cc82db82 --- /dev/null +++ b/tests/migrations/0000_00_00_000000_create_categories_table.php @@ -0,0 +1,23 @@ +increments('id'); + $table->string('name'); + }); + } + + public function down() + { + Schema::drop('categories'); + } +} diff --git a/tests/migrations/0000_00_00_000001_create_articles_table.php b/tests/migrations/0000_00_00_000001_create_articles_table.php index 367547f7..b8cc10ec 100644 --- a/tests/migrations/0000_00_00_000001_create_articles_table.php +++ b/tests/migrations/0000_00_00_000001_create_articles_table.php @@ -17,9 +17,14 @@ public function up() $table->string('slug'); $table->text('content'); $table->timestamp('published_at')->nullable(); + $table->unsignedInteger('category_id')->nullable(); $table->unsignedInteger('user_id'); $table->timestamps(); + $table->foreign('category_id') + ->references('id')->on('categories') + ->onDelete('set null'); + $table->foreign('user_id') ->references('id')->on('users') ->onDelete('cascade'); diff --git a/tests/migrations/0000_00_00_000002_create_phones_table.php b/tests/migrations/0000_00_00_000002_create_phones_table.php index ba949143..cd02bbfd 100644 --- a/tests/migrations/0000_00_00_000002_create_phones_table.php +++ b/tests/migrations/0000_00_00_000002_create_phones_table.php @@ -14,7 +14,7 @@ public function up() Schema::create('phones', function (Blueprint $table) { $table->increments('id'); $table->string('number')->unique(); - $table->unsignedInteger('user_id'); + $table->unsignedInteger('user_id')->nullable(); $table->timestamps(); $table->foreign('user_id') From 9c7a475c06c1a20df1f68f4e37911d82cffc7a4c Mon Sep 17 00:00:00 2001 From: Robert van Steen Date: Wed, 18 Jul 2018 09:11:03 +0000 Subject: [PATCH 2/5] Apply fixes from StyleCI --- src/Eloquent/Concerns/InteractsWithRelations.php | 5 +++-- tests/Stubs/BakeryModels/CategoryBakery.php | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Eloquent/Concerns/InteractsWithRelations.php b/src/Eloquent/Concerns/InteractsWithRelations.php index 851d0944..5eb2ffd8 100644 --- a/src/Eloquent/Concerns/InteractsWithRelations.php +++ b/src/Eloquent/Concerns/InteractsWithRelations.php @@ -78,7 +78,7 @@ protected function fillConnections(array $connections) */ protected function connectBelongsToRelation(Relations\BelongsTo $relation, $id) { - if (!$id) { + if (! $id) { return $relation->associate(null); } @@ -108,11 +108,12 @@ protected function fillBelongsToRelation(Relations\BelongsTo $relation, $attribu */ protected function connectHasOneRelation(Relations\HasOne $relation, $id) { - if (!$id) { + if (! $id) { if ($related = $relation->getResults()) { $related->setAttribute($relation->getForeignKeyName(), null); $related->save(); } + return; } diff --git a/tests/Stubs/BakeryModels/CategoryBakery.php b/tests/Stubs/BakeryModels/CategoryBakery.php index b710c603..1a95fbe3 100644 --- a/tests/Stubs/BakeryModels/CategoryBakery.php +++ b/tests/Stubs/BakeryModels/CategoryBakery.php @@ -4,7 +4,6 @@ use Bakery\Tests\Models\Category; use GraphQL\Type\Definition\Type; -use Bakery\Support\Facades\Bakery; use Bakery\Eloquent\Introspectable; class CategoryBakery From f6df4cc16d3ddc836d80a2e9e5eb2d3861e6b12f Mon Sep 17 00:00:00 2001 From: Robert van Steen Date: Wed, 18 Jul 2018 11:12:50 +0200 Subject: [PATCH 3/5] Fix assertions --- tests/Feature/CreateMutationTest.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/Feature/CreateMutationTest.php b/tests/Feature/CreateMutationTest.php index 3d449d6d..7a5a5a1a 100644 --- a/tests/Feature/CreateMutationTest.php +++ b/tests/Feature/CreateMutationTest.php @@ -317,9 +317,6 @@ public function it_lets_you_reset_a_belongs_to_relationship() $response = $this->json('GET', '/graphql', ['query' => $query]); $response->assertJsonFragment(['id']); - // $this->assertDatabaseHas('users', ['email' => 'jane.doe@example.com', 'name' => 'Jane Doe']); - // $this->assertDatabaseHas('articles', ['title' => 'Hello World!', 'user_id' => '2']); - // $this->assertDatabaseHas('comments', ['body' => 'First!', 'article_id' => '1']); - // $this->assertDatabaseHas('comments', ['body' => 'Great post!', 'article_id' => '1']); + $this->assertDatabaseHas('articles', ['title' => 'Hello World!', 'category_id' => null]); } } From aba35be6550c13d589629b9002fafc6120d72949 Mon Sep 17 00:00:00 2001 From: Robert van Steen Date: Wed, 18 Jul 2018 15:13:27 +0200 Subject: [PATCH 4/5] Update InteractsWithRelations.php --- src/Eloquent/Concerns/InteractsWithRelations.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Eloquent/Concerns/InteractsWithRelations.php b/src/Eloquent/Concerns/InteractsWithRelations.php index 5eb2ffd8..65def801 100644 --- a/src/Eloquent/Concerns/InteractsWithRelations.php +++ b/src/Eloquent/Concerns/InteractsWithRelations.php @@ -79,7 +79,8 @@ protected function fillConnections(array $connections) protected function connectBelongsToRelation(Relations\BelongsTo $relation, $id) { if (! $id) { - return $relation->associate(null); + $relation->associate(null); + return; } $model = $relation->getRelated()->findOrFail($id); From 2f9c2a273c823e881c48d3f9579dd755eedf1f63 Mon Sep 17 00:00:00 2001 From: Robert van Steen Date: Wed, 18 Jul 2018 13:13:50 +0000 Subject: [PATCH 5/5] Apply fixes from StyleCI --- src/Eloquent/Concerns/InteractsWithRelations.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Eloquent/Concerns/InteractsWithRelations.php b/src/Eloquent/Concerns/InteractsWithRelations.php index 65def801..3d8e8e43 100644 --- a/src/Eloquent/Concerns/InteractsWithRelations.php +++ b/src/Eloquent/Concerns/InteractsWithRelations.php @@ -80,6 +80,7 @@ protected function connectBelongsToRelation(Relations\BelongsTo $relation, $id) { if (! $id) { $relation->associate(null); + return; }