product submission
This commit is contained in:
@@ -0,0 +1,415 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Category;
|
||||
use App\Models\Product;
|
||||
use App\Models\Role;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
Storage::fake('public');
|
||||
|
||||
// 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',
|
||||
]);
|
||||
});
|
||||
|
||||
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');
|
||||
});
|
||||
Reference in New Issue
Block a user