engagement system
This commit is contained in:
@@ -0,0 +1,448 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Bookmark;
|
||||
use App\Models\Category;
|
||||
use App\Models\Comment;
|
||||
use App\Models\Product;
|
||||
use App\Models\Role;
|
||||
use App\Models\Upvote;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
// Create roles
|
||||
$this->userRole = Role::create([
|
||||
'name' => 'User',
|
||||
'slug' => 'user',
|
||||
'description' => 'Regular user',
|
||||
]);
|
||||
|
||||
$this->moderatorRole = Role::create([
|
||||
'name' => 'Moderator',
|
||||
'slug' => 'moderator',
|
||||
'description' => 'Moderator',
|
||||
]);
|
||||
|
||||
$this->adminRole = Role::create([
|
||||
'name' => 'Admin',
|
||||
'slug' => 'admin',
|
||||
'description' => 'Admin',
|
||||
]);
|
||||
|
||||
// Create category
|
||||
$this->category = Category::create([
|
||||
'name' => 'Test Category',
|
||||
'slug' => 'test-category',
|
||||
'description' => 'Test description',
|
||||
]);
|
||||
});
|
||||
|
||||
// ============ UPVOTE TESTS ============
|
||||
|
||||
test('authenticated users can upvote a product', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->roles()->attach($this->userRole);
|
||||
|
||||
$owner = User::factory()->create();
|
||||
$owner->roles()->attach($this->userRole);
|
||||
|
||||
$product = Product::create([
|
||||
'title' => 'Test Product',
|
||||
'slug' => 'test-product',
|
||||
'description' => 'Test description',
|
||||
'website_url' => 'https://example.com',
|
||||
'user_id' => $owner->id,
|
||||
'category_id' => $this->category->id,
|
||||
'status' => 'approved',
|
||||
]);
|
||||
|
||||
$response = $this->actingAs($user)->postJson(route('products.upvote', $product));
|
||||
|
||||
$response->assertStatus(200);
|
||||
$response->assertJson([
|
||||
'success' => true,
|
||||
'upvoted' => true,
|
||||
'upvotesCount' => 1,
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('upvotes', [
|
||||
'user_id' => $user->id,
|
||||
'product_id' => $product->id,
|
||||
]);
|
||||
});
|
||||
|
||||
test('authenticated users can remove their upvote', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->roles()->attach($this->userRole);
|
||||
|
||||
$owner = User::factory()->create();
|
||||
$owner->roles()->attach($this->userRole);
|
||||
|
||||
$product = Product::create([
|
||||
'title' => 'Test Product',
|
||||
'slug' => 'test-product',
|
||||
'description' => 'Test description',
|
||||
'website_url' => 'https://example.com',
|
||||
'user_id' => $owner->id,
|
||||
'category_id' => $this->category->id,
|
||||
'status' => 'approved',
|
||||
]);
|
||||
|
||||
// First upvote
|
||||
Upvote::create([
|
||||
'user_id' => $user->id,
|
||||
'product_id' => $product->id,
|
||||
]);
|
||||
|
||||
// Remove upvote
|
||||
$response = $this->actingAs($user)->postJson(route('products.upvote', $product));
|
||||
|
||||
$response->assertStatus(200);
|
||||
$response->assertJson([
|
||||
'success' => true,
|
||||
'upvoted' => false,
|
||||
'upvotesCount' => 0,
|
||||
]);
|
||||
|
||||
$this->assertDatabaseMissing('upvotes', [
|
||||
'user_id' => $user->id,
|
||||
'product_id' => $product->id,
|
||||
]);
|
||||
});
|
||||
|
||||
test('guests cannot upvote products', function () {
|
||||
$owner = User::factory()->create();
|
||||
$owner->roles()->attach($this->userRole);
|
||||
|
||||
$product = Product::create([
|
||||
'title' => 'Test Product',
|
||||
'slug' => 'test-product',
|
||||
'description' => 'Test description',
|
||||
'website_url' => 'https://example.com',
|
||||
'user_id' => $owner->id,
|
||||
'category_id' => $this->category->id,
|
||||
'status' => 'approved',
|
||||
]);
|
||||
|
||||
$response = $this->postJson(route('products.upvote', $product));
|
||||
|
||||
$response->assertStatus(401);
|
||||
});
|
||||
|
||||
test('users cannot upvote the same product twice', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->roles()->attach($this->userRole);
|
||||
|
||||
$owner = User::factory()->create();
|
||||
$owner->roles()->attach($this->userRole);
|
||||
|
||||
$product = Product::create([
|
||||
'title' => 'Test Product',
|
||||
'slug' => 'test-product',
|
||||
'description' => 'Test description',
|
||||
'website_url' => 'https://example.com',
|
||||
'user_id' => $owner->id,
|
||||
'category_id' => $this->category->id,
|
||||
'status' => 'approved',
|
||||
]);
|
||||
|
||||
// First upvote
|
||||
$this->actingAs($user)->postJson(route('products.upvote', $product));
|
||||
|
||||
// Second upvote should toggle (remove)
|
||||
$response = $this->actingAs($user)->postJson(route('products.upvote', $product));
|
||||
|
||||
$response->assertJson(['upvoted' => false]);
|
||||
|
||||
expect(Upvote::where('user_id', $user->id)->where('product_id', $product->id)->count())->toBe(0);
|
||||
});
|
||||
|
||||
// ============ COMMENT TESTS ============
|
||||
|
||||
test('authenticated users can comment on products', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->roles()->attach($this->userRole);
|
||||
|
||||
$owner = User::factory()->create();
|
||||
$owner->roles()->attach($this->userRole);
|
||||
|
||||
$product = Product::create([
|
||||
'title' => 'Test Product',
|
||||
'slug' => 'test-product',
|
||||
'description' => 'Test description',
|
||||
'website_url' => 'https://example.com',
|
||||
'user_id' => $owner->id,
|
||||
'category_id' => $this->category->id,
|
||||
'status' => 'approved',
|
||||
]);
|
||||
|
||||
$response = $this->actingAs($user)->post(route('products.comments.store', $product), [
|
||||
'body' => 'This is a great product!',
|
||||
]);
|
||||
|
||||
$response->assertRedirect();
|
||||
$response->assertSessionHas('success');
|
||||
|
||||
$this->assertDatabaseHas('comments', [
|
||||
'user_id' => $user->id,
|
||||
'product_id' => $product->id,
|
||||
'body' => 'This is a great product!',
|
||||
]);
|
||||
});
|
||||
|
||||
test('guests cannot comment on products', function () {
|
||||
$owner = User::factory()->create();
|
||||
$owner->roles()->attach($this->userRole);
|
||||
|
||||
$product = Product::create([
|
||||
'title' => 'Test Product',
|
||||
'slug' => 'test-product',
|
||||
'description' => 'Test description',
|
||||
'website_url' => 'https://example.com',
|
||||
'user_id' => $owner->id,
|
||||
'category_id' => $this->category->id,
|
||||
'status' => 'approved',
|
||||
]);
|
||||
|
||||
$response = $this->post(route('products.comments.store', $product), [
|
||||
'body' => 'This is a great product!',
|
||||
]);
|
||||
|
||||
$response->assertRedirect(route('login'));
|
||||
});
|
||||
|
||||
test('comment body is required', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->roles()->attach($this->userRole);
|
||||
|
||||
$owner = User::factory()->create();
|
||||
$owner->roles()->attach($this->userRole);
|
||||
|
||||
$product = Product::create([
|
||||
'title' => 'Test Product',
|
||||
'slug' => 'test-product',
|
||||
'description' => 'Test description',
|
||||
'website_url' => 'https://example.com',
|
||||
'user_id' => $owner->id,
|
||||
'category_id' => $this->category->id,
|
||||
'status' => 'approved',
|
||||
]);
|
||||
|
||||
$response = $this->actingAs($user)->post(route('products.comments.store', $product), [
|
||||
'body' => '',
|
||||
]);
|
||||
|
||||
$response->assertSessionHasErrors('body');
|
||||
});
|
||||
|
||||
test('comment body cannot exceed 1000 characters', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->roles()->attach($this->userRole);
|
||||
|
||||
$owner = User::factory()->create();
|
||||
$owner->roles()->attach($this->userRole);
|
||||
|
||||
$product = Product::create([
|
||||
'title' => 'Test Product',
|
||||
'slug' => 'test-product',
|
||||
'description' => 'Test description',
|
||||
'website_url' => 'https://example.com',
|
||||
'user_id' => $owner->id,
|
||||
'category_id' => $this->category->id,
|
||||
'status' => 'approved',
|
||||
]);
|
||||
|
||||
$response = $this->actingAs($user)->post(route('products.comments.store', $product), [
|
||||
'body' => str_repeat('a', 1001),
|
||||
]);
|
||||
|
||||
$response->assertSessionHasErrors('body');
|
||||
});
|
||||
|
||||
test('comment owners can delete their comments', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->roles()->attach($this->userRole);
|
||||
|
||||
$owner = User::factory()->create();
|
||||
$owner->roles()->attach($this->userRole);
|
||||
|
||||
$product = Product::create([
|
||||
'title' => 'Test Product',
|
||||
'slug' => 'test-product',
|
||||
'description' => 'Test description',
|
||||
'website_url' => 'https://example.com',
|
||||
'user_id' => $owner->id,
|
||||
'category_id' => $this->category->id,
|
||||
'status' => 'approved',
|
||||
]);
|
||||
|
||||
$comment = Comment::create([
|
||||
'user_id' => $user->id,
|
||||
'product_id' => $product->id,
|
||||
'body' => 'Test comment',
|
||||
]);
|
||||
|
||||
$response = $this->actingAs($user)->delete(route('comments.destroy', $comment));
|
||||
|
||||
$response->assertRedirect();
|
||||
$response->assertSessionHas('success');
|
||||
|
||||
$this->assertDatabaseMissing('comments', ['id' => $comment->id]);
|
||||
});
|
||||
|
||||
test('non-owners cannot delete comments', function () {
|
||||
$user1 = User::factory()->create();
|
||||
$user1->roles()->attach($this->userRole);
|
||||
|
||||
$user2 = User::factory()->create();
|
||||
$user2->roles()->attach($this->userRole);
|
||||
|
||||
$owner = User::factory()->create();
|
||||
$owner->roles()->attach($this->userRole);
|
||||
|
||||
$product = Product::create([
|
||||
'title' => 'Test Product',
|
||||
'slug' => 'test-product',
|
||||
'description' => 'Test description',
|
||||
'website_url' => 'https://example.com',
|
||||
'user_id' => $owner->id,
|
||||
'category_id' => $this->category->id,
|
||||
'status' => 'approved',
|
||||
]);
|
||||
|
||||
$comment = Comment::create([
|
||||
'user_id' => $user1->id,
|
||||
'product_id' => $product->id,
|
||||
'body' => 'Test comment',
|
||||
]);
|
||||
|
||||
$response = $this->actingAs($user2)->delete(route('comments.destroy', $comment));
|
||||
|
||||
$response->assertStatus(403);
|
||||
});
|
||||
|
||||
test('moderators can delete any comment', function () {
|
||||
$moderator = User::factory()->create();
|
||||
$moderator->roles()->attach($this->moderatorRole);
|
||||
|
||||
$user = User::factory()->create();
|
||||
$user->roles()->attach($this->userRole);
|
||||
|
||||
$owner = User::factory()->create();
|
||||
$owner->roles()->attach($this->userRole);
|
||||
|
||||
$product = Product::create([
|
||||
'title' => 'Test Product',
|
||||
'slug' => 'test-product',
|
||||
'description' => 'Test description',
|
||||
'website_url' => 'https://example.com',
|
||||
'user_id' => $owner->id,
|
||||
'category_id' => $this->category->id,
|
||||
'status' => 'approved',
|
||||
]);
|
||||
|
||||
$comment = Comment::create([
|
||||
'user_id' => $user->id,
|
||||
'product_id' => $product->id,
|
||||
'body' => 'Test comment',
|
||||
]);
|
||||
|
||||
$response = $this->actingAs($moderator)->delete(route('comments.destroy', $comment));
|
||||
|
||||
$response->assertRedirect();
|
||||
$response->assertSessionHas('success');
|
||||
|
||||
$this->assertDatabaseMissing('comments', ['id' => $comment->id]);
|
||||
});
|
||||
|
||||
// ============ BOOKMARK TESTS ============
|
||||
|
||||
test('authenticated users can bookmark a product', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->roles()->attach($this->userRole);
|
||||
|
||||
$owner = User::factory()->create();
|
||||
$owner->roles()->attach($this->userRole);
|
||||
|
||||
$product = Product::create([
|
||||
'title' => 'Test Product',
|
||||
'slug' => 'test-product',
|
||||
'description' => 'Test description',
|
||||
'website_url' => 'https://example.com',
|
||||
'user_id' => $owner->id,
|
||||
'category_id' => $this->category->id,
|
||||
'status' => 'approved',
|
||||
]);
|
||||
|
||||
$response = $this->actingAs($user)->postJson(route('products.bookmark', $product));
|
||||
|
||||
$response->assertStatus(200);
|
||||
$response->assertJson([
|
||||
'success' => true,
|
||||
'bookmarked' => true,
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('bookmarks', [
|
||||
'user_id' => $user->id,
|
||||
'product_id' => $product->id,
|
||||
]);
|
||||
});
|
||||
|
||||
test('authenticated users can remove their bookmark', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->roles()->attach($this->userRole);
|
||||
|
||||
$owner = User::factory()->create();
|
||||
$owner->roles()->attach($this->userRole);
|
||||
|
||||
$product = Product::create([
|
||||
'title' => 'Test Product',
|
||||
'slug' => 'test-product',
|
||||
'description' => 'Test description',
|
||||
'website_url' => 'https://example.com',
|
||||
'user_id' => $owner->id,
|
||||
'category_id' => $this->category->id,
|
||||
'status' => 'approved',
|
||||
]);
|
||||
|
||||
// First bookmark
|
||||
Bookmark::create([
|
||||
'user_id' => $user->id,
|
||||
'product_id' => $product->id,
|
||||
]);
|
||||
|
||||
// Remove bookmark
|
||||
$response = $this->actingAs($user)->postJson(route('products.bookmark', $product));
|
||||
|
||||
$response->assertStatus(200);
|
||||
$response->assertJson([
|
||||
'success' => true,
|
||||
'bookmarked' => false,
|
||||
]);
|
||||
|
||||
$this->assertDatabaseMissing('bookmarks', [
|
||||
'user_id' => $user->id,
|
||||
'product_id' => $product->id,
|
||||
]);
|
||||
});
|
||||
|
||||
test('guests cannot bookmark products', function () {
|
||||
$owner = User::factory()->create();
|
||||
$owner->roles()->attach($this->userRole);
|
||||
|
||||
$product = Product::create([
|
||||
'title' => 'Test Product',
|
||||
'slug' => 'test-product',
|
||||
'description' => 'Test description',
|
||||
'website_url' => 'https://example.com',
|
||||
'user_id' => $owner->id,
|
||||
'category_id' => $this->category->id,
|
||||
'status' => 'approved',
|
||||
]);
|
||||
|
||||
$response = $this->postJson(route('products.bookmark', $product));
|
||||
|
||||
$response->assertStatus(401);
|
||||
});
|
||||
Reference in New Issue
Block a user