250 lines
7.5 KiB
PHP
250 lines
7.5 KiB
PHP
<?php
|
|
|
|
use App\Models\MealPosts;
|
|
use App\Models\PostReviews;
|
|
use App\Models\User;
|
|
use App\Notifications\MealPostCommentedNotification;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Notification;
|
|
use Laravel\Sanctum\Sanctum;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
it('creates one review per user for a meal post', function () {
|
|
$user = User::factory()->create();
|
|
$mealPost = MealPosts::factory()->create();
|
|
|
|
Sanctum::actingAs($user);
|
|
|
|
$this->postJson("/api/meal-posts/{$mealPost->id}/reviews", [
|
|
'rating' => 5,
|
|
'comment' => 'Très bon repas.',
|
|
])
|
|
->assertCreated()
|
|
->assertJsonPath('data.rating', 5)
|
|
->assertJsonPath('data.comment', 'Très bon repas.')
|
|
->assertJsonPath('data.meal_post_id', $mealPost->id)
|
|
->assertJsonPath('data.user_id', $user->id);
|
|
|
|
$this->assertDatabaseHas('post_reviews', [
|
|
'meal_post_id' => $mealPost->id,
|
|
'user_id' => $user->id,
|
|
'rating' => 5,
|
|
'comment' => 'Très bon repas.',
|
|
]);
|
|
|
|
$this->postJson("/api/meal-posts/{$mealPost->id}/reviews", [
|
|
'rating' => 4,
|
|
])
|
|
->assertConflict()
|
|
->assertJsonPath('message', __('api.post_reviews.already_exists'));
|
|
|
|
expect(PostReviews::query()->count())->toBe(1);
|
|
});
|
|
|
|
it('sends a push notification to the meal owner when another user comments on their meal', function () {
|
|
Notification::fake();
|
|
|
|
$owner = User::factory()->create();
|
|
$owner->deviceTokens()->create([
|
|
'expo_push_token' => 'ExponentPushToken[owner]',
|
|
'platform' => 'ios',
|
|
]);
|
|
$reviewer = User::factory()->create(['name' => 'Alex']);
|
|
$mealPost = MealPosts::factory()
|
|
->for($owner, 'user')
|
|
->create(['title' => 'Recovery bowl']);
|
|
|
|
Sanctum::actingAs($reviewer);
|
|
|
|
$this->postJson("/api/meal-posts/{$mealPost->id}/reviews", [
|
|
'rating' => 5,
|
|
'comment' => 'Très bon repas.',
|
|
])->assertCreated();
|
|
|
|
Notification::assertSentTo(
|
|
$owner,
|
|
MealPostCommentedNotification::class,
|
|
function (MealPostCommentedNotification $notification) use ($mealPost, $owner): bool {
|
|
$payload = $notification->toExpoPush($owner);
|
|
|
|
return $payload['title'] === 'New comment'
|
|
&& $payload['body'] === 'Alex commented on your meal "Recovery bowl".'
|
|
&& $payload['data']['type'] === 'meal_commented'
|
|
&& $payload['data']['url'] === "bowli://meals/{$mealPost->id}";
|
|
},
|
|
);
|
|
});
|
|
|
|
it('does not send a push notification for rating-only reviews', function () {
|
|
Notification::fake();
|
|
|
|
$owner = User::factory()->create();
|
|
$owner->deviceTokens()->create([
|
|
'expo_push_token' => 'ExponentPushToken[owner]',
|
|
'platform' => 'ios',
|
|
]);
|
|
$reviewer = User::factory()->create();
|
|
$mealPost = MealPosts::factory()->for($owner, 'user')->create();
|
|
|
|
Sanctum::actingAs($reviewer);
|
|
|
|
$this->postJson("/api/meal-posts/{$mealPost->id}/reviews", [
|
|
'rating' => 5,
|
|
])->assertCreated();
|
|
|
|
Notification::assertNothingSent();
|
|
});
|
|
|
|
it('does not notify the owner when they comment on their own meal', function () {
|
|
Notification::fake();
|
|
|
|
$owner = User::factory()->create();
|
|
$owner->deviceTokens()->create([
|
|
'expo_push_token' => 'ExponentPushToken[owner]',
|
|
'platform' => 'ios',
|
|
]);
|
|
$mealPost = MealPosts::factory()->for($owner, 'user')->create();
|
|
|
|
Sanctum::actingAs($owner);
|
|
|
|
$this->postJson("/api/meal-posts/{$mealPost->id}/reviews", [
|
|
'rating' => 5,
|
|
'comment' => 'Note personnelle.',
|
|
])->assertCreated();
|
|
|
|
Notification::assertNothingSent();
|
|
});
|
|
|
|
it('lists reviews for a single meal post', function () {
|
|
$user = User::factory()->create();
|
|
$mealPost = MealPosts::factory()->create();
|
|
$otherMealPost = MealPosts::factory()->create();
|
|
$firstReview = PostReviews::query()->create([
|
|
'meal_post_id' => $mealPost->id,
|
|
'user_id' => User::factory()->create()->id,
|
|
'rating' => 4,
|
|
'comment' => 'Solide.',
|
|
]);
|
|
$secondReview = PostReviews::query()->create([
|
|
'meal_post_id' => $mealPost->id,
|
|
'user_id' => User::factory()->create()->id,
|
|
'rating' => 5,
|
|
'comment' => null,
|
|
]);
|
|
$otherReview = PostReviews::query()->create([
|
|
'meal_post_id' => $otherMealPost->id,
|
|
'user_id' => User::factory()->create()->id,
|
|
'rating' => 1,
|
|
'comment' => 'Pas celui-ci.',
|
|
]);
|
|
|
|
Sanctum::actingAs($user);
|
|
|
|
$this->getJson("/api/meal-posts/{$mealPost->id}/reviews")
|
|
->assertOk()
|
|
->assertJsonCount(2, 'data')
|
|
->assertJsonFragment(['id' => $firstReview->id])
|
|
->assertJsonFragment(['id' => $secondReview->id])
|
|
->assertJsonMissing(['id' => $otherReview->id]);
|
|
});
|
|
|
|
it('shows the authenticated users review for a meal post', function () {
|
|
$user = User::factory()->create();
|
|
$mealPost = MealPosts::factory()->create();
|
|
$review = PostReviews::query()->create([
|
|
'meal_post_id' => $mealPost->id,
|
|
'user_id' => $user->id,
|
|
'rating' => 4,
|
|
'comment' => 'Mon avis.',
|
|
]);
|
|
PostReviews::query()->create([
|
|
'meal_post_id' => $mealPost->id,
|
|
'user_id' => User::factory()->create()->id,
|
|
'rating' => 5,
|
|
'comment' => 'Un autre avis.',
|
|
]);
|
|
|
|
Sanctum::actingAs($user);
|
|
|
|
$this->getJson("/api/meal-posts/{$mealPost->id}/my-review")
|
|
->assertOk()
|
|
->assertJsonPath('data.id', $review->id)
|
|
->assertJsonPath('data.user_id', $user->id);
|
|
});
|
|
|
|
it('returns null when the authenticated user has not reviewed a meal post', function () {
|
|
$user = User::factory()->create();
|
|
$mealPost = MealPosts::factory()->create();
|
|
|
|
Sanctum::actingAs($user);
|
|
|
|
$this->getJson("/api/meal-posts/{$mealPost->id}/my-review")
|
|
->assertOk()
|
|
->assertJsonPath('data', null);
|
|
});
|
|
|
|
it('lets the review author update and delete their review', function () {
|
|
$user = User::factory()->create();
|
|
$review = PostReviews::query()->create([
|
|
'meal_post_id' => MealPosts::factory()->create()->id,
|
|
'user_id' => $user->id,
|
|
'rating' => 3,
|
|
'comment' => 'Initial.',
|
|
]);
|
|
|
|
Sanctum::actingAs($user);
|
|
|
|
$this->patchJson("/api/post-reviews/{$review->id}", [
|
|
'rating' => 4,
|
|
'comment' => null,
|
|
])
|
|
->assertOk()
|
|
->assertJsonPath('data.rating', 4)
|
|
->assertJsonPath('data.comment', null);
|
|
|
|
$this->assertDatabaseHas('post_reviews', [
|
|
'id' => $review->id,
|
|
'rating' => 4,
|
|
'comment' => null,
|
|
]);
|
|
|
|
$this->deleteJson("/api/post-reviews/{$review->id}")
|
|
->assertNoContent();
|
|
|
|
$this->assertDatabaseMissing('post_reviews', [
|
|
'id' => $review->id,
|
|
]);
|
|
});
|
|
|
|
it('does not let another user mutate a review', function () {
|
|
$review = PostReviews::query()->create([
|
|
'meal_post_id' => MealPosts::factory()->create()->id,
|
|
'user_id' => User::factory()->create()->id,
|
|
'rating' => 3,
|
|
'comment' => 'Initial.',
|
|
]);
|
|
|
|
Sanctum::actingAs(User::factory()->create());
|
|
|
|
$this->patchJson("/api/post-reviews/{$review->id}", [
|
|
'rating' => 4,
|
|
])->assertNotFound();
|
|
|
|
$this->deleteJson("/api/post-reviews/{$review->id}")
|
|
->assertNotFound();
|
|
|
|
$this->assertDatabaseHas('post_reviews', [
|
|
'id' => $review->id,
|
|
'rating' => 3,
|
|
]);
|
|
});
|
|
|
|
it('requires authentication to create a review', function () {
|
|
$mealPost = MealPosts::factory()->create();
|
|
|
|
$this->postJson("/api/meal-posts/{$mealPost->id}/reviews", [
|
|
'rating' => 5,
|
|
])->assertUnauthorized();
|
|
});
|