Files

449 lines
13 KiB
PHP
Raw Permalink Normal View History

2026-02-06 15:13:20 +02:00
<?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);
});