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', ]); }); test('guests can view approved products', function () { $user = User::factory()->create(); $user->roles()->attach($this->userRole); $product = Product::create([ 'title' => 'Test Product', 'slug' => 'test-product', 'description' => 'Test description', 'website_url' => 'https://example.com', 'user_id' => $user->id, 'category_id' => $this->category->id, 'status' => 'approved', ]); $response = $this->get(route('products.index')); $response->assertStatus(200); $response->assertSee('Test Product'); }); test('guests cannot view pending products', function () { $user = User::factory()->create(); $user->roles()->attach($this->userRole); $product = Product::create([ 'title' => 'Pending Product', 'slug' => 'pending-product', 'description' => 'Test description', 'website_url' => 'https://example.com', 'user_id' => $user->id, 'category_id' => $this->category->id, 'status' => 'pending', ]); $response = $this->get(route('products.show', $product)); $response->assertStatus(404); }); test('authenticated users can submit products', function () { $user = User::factory()->create(); $user->roles()->attach($this->userRole); $response = $this->actingAs($user)->post(route('products.store'), [ 'title' => 'New Product', 'description' => 'This is a new product', 'website_url' => 'https://newproduct.com', 'category_id' => $this->category->id, ]); $response->assertRedirect(); $this->assertDatabaseHas('products', [ 'title' => 'New Product', 'user_id' => $user->id, 'status' => 'pending', ]); }); test('guests cannot submit products', function () { $response = $this->get(route('products.create')); $response->assertRedirect(route('login')); }); test('product submission requires title', function () { $user = User::factory()->create(); $user->roles()->attach($this->userRole); $response = $this->actingAs($user)->post(route('products.store'), [ 'description' => 'Test description', 'website_url' => 'https://example.com', 'category_id' => $this->category->id, ]); $response->assertSessionHasErrors('title'); }); test('product submission requires description', function () { $user = User::factory()->create(); $user->roles()->attach($this->userRole); $response = $this->actingAs($user)->post(route('products.store'), [ 'title' => 'Test Product', 'website_url' => 'https://example.com', 'category_id' => $this->category->id, ]); $response->assertSessionHasErrors('description'); }); test('product submission requires valid url', function () { $user = User::factory()->create(); $user->roles()->attach($this->userRole); $response = $this->actingAs($user)->post(route('products.store'), [ 'title' => 'Test Product', 'description' => 'Test description', 'website_url' => 'not-a-valid-url', 'category_id' => $this->category->id, ]); $response->assertSessionHasErrors('website_url'); }); test('product submission requires valid category', function () { $user = User::factory()->create(); $user->roles()->attach($this->userRole); $response = $this->actingAs($user)->post(route('products.store'), [ 'title' => 'Test Product', 'description' => 'Test description', 'website_url' => 'https://example.com', 'category_id' => 999, ]); $response->assertSessionHasErrors('category_id'); }); test('users can upload thumbnail when submitting product', function () { $user = User::factory()->create(); $user->roles()->attach($this->userRole); $file = UploadedFile::fake()->image('thumbnail.jpg'); $response = $this->actingAs($user)->post(route('products.store'), [ 'title' => 'Test Product', 'description' => 'Test description', 'website_url' => 'https://example.com', 'category_id' => $this->category->id, 'thumbnail' => $file, ]); $product = Product::where('title', 'Test Product')->first(); expect($product->thumbnail)->not->toBeNull(); Storage::disk('public')->assertExists($product->thumbnail); }); test('thumbnail must be an image', function () { $user = User::factory()->create(); $user->roles()->attach($this->userRole); $file = UploadedFile::fake()->create('document.pdf'); $response = $this->actingAs($user)->post(route('products.store'), [ 'title' => 'Test Product', 'description' => 'Test description', 'website_url' => 'https://example.com', 'category_id' => $this->category->id, 'thumbnail' => $file, ]); $response->assertSessionHasErrors('thumbnail'); }); test('product owner can edit their product', function () { $user = User::factory()->create(); $user->roles()->attach($this->userRole); $product = Product::create([ 'title' => 'Test Product', 'slug' => 'test-product', 'description' => 'Test description', 'website_url' => 'https://example.com', 'user_id' => $user->id, 'category_id' => $this->category->id, 'status' => 'pending', ]); $response = $this->actingAs($user)->put(route('products.update', $product), [ 'title' => 'Updated Product', 'description' => 'Updated description', 'website_url' => 'https://updated.com', 'category_id' => $this->category->id, ]); $response->assertRedirect(); $this->assertDatabaseHas('products', [ 'id' => $product->id, 'title' => 'Updated Product', ]); }); test('non-owner cannot edit product', function () { $owner = User::factory()->create(); $owner->roles()->attach($this->userRole); $other = User::factory()->create(); $other->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' => 'pending', ]); $response = $this->actingAs($other)->put(route('products.update', $product), [ 'title' => 'Updated Product', 'description' => 'Updated description', 'website_url' => 'https://updated.com', 'category_id' => $this->category->id, ]); $response->assertStatus(403); }); test('product owner can delete their product', function () { $user = User::factory()->create(); $user->roles()->attach($this->userRole); $product = Product::create([ 'title' => 'Test Product', 'slug' => 'test-product', 'description' => 'Test description', 'website_url' => 'https://example.com', 'user_id' => $user->id, 'category_id' => $this->category->id, 'status' => 'pending', ]); $response = $this->actingAs($user)->delete(route('products.destroy', $product)); $response->assertRedirect(); $this->assertDatabaseMissing('products', ['id' => $product->id]); }); test('moderators can approve products', function () { $moderator = User::factory()->create(); $moderator->roles()->attach($this->moderatorRole); $user = User::factory()->create(); $user->roles()->attach($this->userRole); $product = Product::create([ 'title' => 'Test Product', 'slug' => 'test-product', 'description' => 'Test description', 'website_url' => 'https://example.com', 'user_id' => $user->id, 'category_id' => $this->category->id, 'status' => 'pending', ]); $response = $this->actingAs($moderator)->post(route('products.approve', $product)); $response->assertRedirect(); $this->assertDatabaseHas('products', [ 'id' => $product->id, 'status' => 'approved', ]); expect($product->fresh()->approved_at)->not->toBeNull(); }); test('moderators can reject products', function () { $moderator = User::factory()->create(); $moderator->roles()->attach($this->moderatorRole); $user = User::factory()->create(); $user->roles()->attach($this->userRole); $product = Product::create([ 'title' => 'Test Product', 'slug' => 'test-product', 'description' => 'Test description', 'website_url' => 'https://example.com', 'user_id' => $user->id, 'category_id' => $this->category->id, 'status' => 'pending', ]); $response = $this->actingAs($moderator)->post(route('products.reject', $product)); $response->assertRedirect(); $this->assertDatabaseHas('products', [ 'id' => $product->id, 'status' => 'rejected', ]); expect($product->fresh()->rejected_at)->not->toBeNull(); }); test('regular users cannot approve products', function () { $user = User::factory()->create(); $user->roles()->attach($this->userRole); $product = Product::create([ 'title' => 'Test Product', 'slug' => 'test-product', 'description' => 'Test description', 'website_url' => 'https://example.com', 'user_id' => $user->id, 'category_id' => $this->category->id, 'status' => 'pending', ]); $response = $this->actingAs($user)->post(route('products.approve', $product)); $response->assertStatus(403); }); test('regular users cannot access product management page', function () { $user = User::factory()->create(); $user->roles()->attach($this->userRole); $response = $this->actingAs($user)->get(route('products.manage')); $response->assertStatus(403); }); test('moderators can access product management page', function () { $moderator = User::factory()->create(); $moderator->roles()->attach($this->moderatorRole); $response = $this->actingAs($moderator)->get(route('products.manage')); $response->assertStatus(200); }); test('admins can access product management page', function () { $admin = User::factory()->create(); $admin->roles()->attach($this->adminRole); $response = $this->actingAs($admin)->get(route('products.manage')); $response->assertStatus(200); }); test('slug is auto-generated from title', function () { $user = User::factory()->create(); $user->roles()->attach($this->userRole); $product = Product::create([ 'title' => 'My Awesome Product', 'description' => 'Test description', 'website_url' => 'https://example.com', 'user_id' => $user->id, 'category_id' => $this->category->id, 'status' => 'pending', ]); expect($product->slug)->toBe('my-awesome-product'); }); test('duplicate slugs are handled correctly', function () { $user = User::factory()->create(); $user->roles()->attach($this->userRole); $product1 = Product::create([ 'title' => 'Test Product', 'description' => 'Test description', 'website_url' => 'https://example.com', 'user_id' => $user->id, 'category_id' => $this->category->id, 'status' => 'pending', ]); $product2 = Product::create([ 'title' => 'Test Product', 'description' => 'Test description', 'website_url' => 'https://example2.com', 'user_id' => $user->id, 'category_id' => $this->category->id, 'status' => 'pending', ]); expect($product1->slug)->toBe('test-product'); expect($product2->slug)->toBe('test-product-1'); });