449 lines
13 KiB
PHP
449 lines
13 KiB
PHP
<?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);
|
|
});
|