20-02-2026

This commit is contained in:
Kevin Adametz 2026-02-20 17:57:50 +01:00
parent 854ce02bf6
commit 4d6b4930b2
128 changed files with 18247 additions and 2093 deletions

View file

@ -0,0 +1,280 @@
<?php
declare(strict_types=1);
use App\Enums\ProductStatus;
use App\Enums\ProductType;
use App\Models\Category;
use App\Models\Hub;
use App\Models\Partner;
use App\Models\Product;
use App\Models\User;
use Livewire\Volt\Volt;
use Spatie\Permission\Models\Role;
beforeEach(function () {
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
Role::create(['name' => 'Admin']);
Role::create(['name' => 'Retailer']);
Role::create(['name' => 'Customer']);
});
test('customer only sees curated active available products from own hub', function () {
$hub = Hub::factory()->create();
$otherHub = Hub::factory()->create();
$partner = Partner::factory()->setupCompleted()->create(['hub_id' => $hub->id]);
$customer = User::factory()->create(['hub_id' => $hub->id]);
$customer->assignRole('Customer');
// Sichtbares Produkt: aktiv + kuratiert + verfügbar + gleicher Hub
$visibleProduct = Product::factory()->create([
'partner_id' => $partner->id,
'hub_id' => $hub->id,
'status' => ProductStatus::Active,
'is_curated' => true,
'is_available' => true,
]);
// Nicht sichtbar: nicht kuratiert
$notCurated = Product::factory()->create([
'partner_id' => $partner->id,
'hub_id' => $hub->id,
'status' => ProductStatus::Active,
'is_curated' => false,
'is_available' => true,
]);
// Nicht sichtbar: anderen Hub
$otherHubProduct = Product::factory()->create([
'partner_id' => $partner->id,
'hub_id' => $otherHub->id,
'status' => ProductStatus::Active,
'is_curated' => true,
'is_available' => true,
]);
// Nicht sichtbar: Draft-Status
$draftProduct = Product::factory()->create([
'partner_id' => $partner->id,
'hub_id' => $hub->id,
'status' => ProductStatus::Draft,
'is_curated' => true,
'is_available' => true,
]);
$this->actingAs($customer);
Volt::test('products.index')
->assertSee($visibleProduct->name)
->assertDontSee($notCurated->name)
->assertDontSee($otherHubProduct->name)
->assertDontSee($draftProduct->name);
});
test('admin sees all products regardless of curation or status', function () {
$hub = Hub::factory()->create();
$partner = Partner::factory()->setupCompleted()->create(['hub_id' => $hub->id]);
$admin = User::factory()->create();
$admin->assignRole('Admin');
$activeProduct = Product::factory()->create([
'partner_id' => $partner->id,
'hub_id' => $hub->id,
'status' => ProductStatus::Active,
'is_curated' => true,
'is_available' => true,
]);
$draftProduct = Product::factory()->create([
'partner_id' => $partner->id,
'hub_id' => $hub->id,
'status' => ProductStatus::Draft,
'is_curated' => false,
'is_available' => false,
]);
$this->actingAs($admin);
Volt::test('products.index')
->assertSee($activeProduct->name)
->assertSee($draftProduct->name);
});
test('retailer only sees own products', function () {
$hub = Hub::factory()->create();
$partner = Partner::factory()->setupCompleted()->create(['hub_id' => $hub->id]);
$otherPartner = Partner::factory()->setupCompleted()->create(['hub_id' => $hub->id]);
$retailer = User::factory()->create(['partner_id' => $partner->id]);
$retailer->assignRole('Retailer');
$ownProduct = Product::factory()->create([
'partner_id' => $partner->id,
'hub_id' => $hub->id,
'status' => ProductStatus::Active,
]);
$otherProduct = Product::factory()->create([
'partner_id' => $otherPartner->id,
'hub_id' => $hub->id,
'status' => ProductStatus::Active,
]);
$this->actingAs($retailer);
Volt::test('products.index')
->assertSee($ownProduct->name)
->assertDontSee($otherProduct->name);
});
test('customer can search products by name', function () {
$hub = Hub::factory()->create();
$partner = Partner::factory()->setupCompleted()->create(['hub_id' => $hub->id]);
$customer = User::factory()->create(['hub_id' => $hub->id]);
$customer->assignRole('Customer');
$matchingProduct = Product::factory()->create([
'name' => 'Eiche Sideboard',
'partner_id' => $partner->id,
'hub_id' => $hub->id,
'status' => ProductStatus::Active,
'is_curated' => true,
'is_available' => true,
]);
$otherProduct = Product::factory()->create([
'name' => 'Massivholztisch',
'partner_id' => $partner->id,
'hub_id' => $hub->id,
'status' => ProductStatus::Active,
'is_curated' => true,
'is_available' => true,
]);
$this->actingAs($customer);
Volt::test('products.index')
->set('search', 'Eiche')
->assertSee($matchingProduct->name)
->assertDontSee($otherProduct->name);
});
test('customer can filter products by category', function () {
$hub = Hub::factory()->create();
$partner = Partner::factory()->setupCompleted()->create(['hub_id' => $hub->id]);
$category = Category::factory()->create();
$customer = User::factory()->create(['hub_id' => $hub->id]);
$customer->assignRole('Customer');
$categoryProduct = Product::factory()->create([
'partner_id' => $partner->id,
'hub_id' => $hub->id,
'status' => ProductStatus::Active,
'is_curated' => true,
'is_available' => true,
]);
$categoryProduct->categories()->attach($category);
$noCategory = Product::factory()->create([
'partner_id' => $partner->id,
'hub_id' => $hub->id,
'status' => ProductStatus::Active,
'is_curated' => true,
'is_available' => true,
]);
$this->actingAs($customer);
Volt::test('products.index')
->set('categoryFilter', (string) $category->id)
->assertSee($categoryProduct->name)
->assertDontSee($noCategory->name);
});
test('retailer can filter products by product type', function () {
$hub = Hub::factory()->create();
$partner = Partner::factory()->setupCompleted()->create(['hub_id' => $hub->id]);
$retailer = User::factory()->create(['partner_id' => $partner->id]);
$retailer->assignRole('Retailer');
$teaserProduct = Product::factory()->create([
'name' => 'Teaser Sideboard',
'partner_id' => $partner->id,
'hub_id' => $hub->id,
'product_type' => ProductType::LocalStock,
'status' => ProductStatus::Active,
]);
$standardProduct = Product::factory()->create([
'name' => 'Standard Sofa',
'partner_id' => $partner->id,
'hub_id' => $hub->id,
'product_type' => ProductType::SmartOrder,
'status' => ProductStatus::Active,
]);
$this->actingAs($retailer);
// Filter auf Teaser (LocalStock)
Volt::test('products.index')
->set('productTypeFilter', 'local_stock')
->assertSee($teaserProduct->name)
->assertDontSee($standardProduct->name);
// Filter auf Standard (SmartOrder)
Volt::test('products.index')
->set('productTypeFilter', 'smart_order')
->assertSee($standardProduct->name)
->assertDontSee($teaserProduct->name);
// Kein Filter beide sichtbar
Volt::test('products.index')
->set('productTypeFilter', '')
->assertSee($teaserProduct->name)
->assertSee($standardProduct->name);
});
test('product list shows both create buttons for retailer', function () {
$hub = Hub::factory()->create();
$partner = Partner::factory()->setupCompleted()->create(['hub_id' => $hub->id]);
$retailer = User::factory()->create(['partner_id' => $partner->id]);
$retailer->assignRole('Retailer');
$this->actingAs($retailer);
Volt::test('products.index')
->assertSee(__('Neues Teaser-Produkt'))
->assertSee(__('Neues Standard-Produkt'));
});
test('product list shows both create buttons for manufacturer', function () {
$hub = Hub::factory()->create();
$partner = Partner::factory()->setupCompleted()->create(['hub_id' => $hub->id]);
$manufacturer = User::factory()->create(['partner_id' => $partner->id]);
$manufacturer->assignRole('Retailer'); // Need Manufacturer role
Role::create(['name' => 'Manufacturer']);
$manufacturer->syncRoles(['Manufacturer']);
$this->actingAs($manufacturer);
Volt::test('products.index')
->assertSee(__('Neues Teaser-Produkt'))
->assertSee(__('Neues Standard-Produkt'));
});
test('product list does not show create buttons for customer', function () {
$hub = Hub::factory()->create();
$customer = User::factory()->create(['hub_id' => $hub->id]);
$customer->assignRole('Customer');
$this->actingAs($customer);
Volt::test('products.index')
->assertDontSee(__('Neues Teaser-Produkt'))
->assertDontSee(__('Neues Standard-Produkt'));
});