diff --git a/app/Models/User.php b/app/Models/User.php index 2401b3a..35d6fc3 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -76,13 +76,23 @@ class User extends Authenticatable implements MustVerifyEmail public function follow(User|int $user): void { $userId = $user instanceof User ? $user->id : $user; + + if ($this->id === $userId) { + // don't allow following yourself + return; + } + $this->following()->syncWithoutDetaching($userId); } public function unfollow(User|int $user): void { $userId = $user instanceof User ? $user->id : $user; - $this->following()->detach($userId); + + // make sure the user is being followed before trying to detach + if ($this->isFollowing($userId)) { + $this->following()->detach($userId); + } } /** diff --git a/tests/Feature/User/FollowTest.php b/tests/Feature/User/FollowTest.php new file mode 100644 index 0000000..c983d00 --- /dev/null +++ b/tests/Feature/User/FollowTest.php @@ -0,0 +1,100 @@ +create(); + + $user->follow($user); + + $this->assertEmpty($user->follwers); + $this->assertEmpty($user->following); +}); + +test('confirm a user can follow and unfollow another user', function () { + $user1 = User::factory()->create(); + $user2 = User::factory()->create(); + + $user1->follow($user2); + + $this->assertTrue($user1->isFollowing($user2)); + + $user1->unfollow($user2); + + $this->assertFalse($user1->isFollowing($user2)); +}); + +test('confirm following a user cannot be done twice', function () { + $user1 = User::factory()->create(); + $user2 = User::factory()->create(); + + $user1->follow($user2); + $user1->follow($user2); + + + $this->assertCount(1, $user1->following); + $this->assertCount(1, $user2->followers); +}); + +test('confirm unfollowing a user that isnt being followed doesnt throw', function () { + $user1 = User::factory()->create(); + $user2 = User::factory()->create(); + + $user1->unfollow($user2); + + $this->assertEmpty($user1->following); + $this->assertEmpty($user2->followers); +}); + +test('confirm unfollowing random number doesnt perform detach all', function () { + $user1 = User::factory()->create(); + $user2 = User::factory()->create(); + $user3 = User::factory()->create(); + + $user1->follow($user2); + $user1->follow($user3); + + $this->assertTrue($user1->isFollowing($user2)); + $this->assertTrue($user1->isFollowing($user3)); + + $this->assertCount(2, $user1->following); + $this->assertCount(1, $user2->followers); + $this->assertCount(1, $user3->followers); + + $user1->unfollow(111112222233333); + + $this->assertTrue($user1->isFollowing($user2)); + $this->assertTrue($user1->isFollowing($user3)); +}); + +test('confirm null follow input fails', function () { + $this->expectException(TypeError::class); + + $user = User::factory()->create(); + + $user->follow(null); +}); + +test('confirm empty follow input fails', function () { + $this->expectException(ArgumentCountError::class); + + $user = User::factory()->create(); + + $user->follow(); +}); + +test('confirm null unfollow input fails', function () { + $this->expectException(TypeError::class); + + $user = User::factory()->create(); + + $user->unfollow(null); +}); + +test('confirm empty unfollow input fails', function () { + $this->expectException(ArgumentCountError::class); + + $user = User::factory()->create(); + + $user->unfollow(); +});