gruene-seele/tests/Feature/StorageSettingsTest.php
Kevin Adametz d05df498d3 Warenwirtschaft: AP-21 INCI-Erweiterungen
- Lagerort-Stammdaten Raum/Regal/Fach (storage_rooms/shelves/slots) mit CRUD
  auf Einstellungen -> Allgemein (SettingCrudController-Kinder, ein gemeinsamer
  StoreStorageSegmentRequest, generische Partials setting-list-card/-segment-form)
- Ingredient: alt_name (Handelsname), Lagerort-FKs + storageLabel(),
  scopeUsedInActiveRecipes()
- INCI-Formular: Lieferanten-Repeater mit Shop-URL je Lieferant (leer = Mail),
  Alternativname, drei Lagerort-Dropdowns
- INCI-Liste: Filter "nur aktive (in Rezeptur aktiver Produkte)" + Spalte
  Alternativer Name
- Rohstoffbestand-Detail: Bestellweg pro INCI-Lieferant (Pivot-URL statt
  order_method-Fallback), Kopf zeigt Alternativname + Lagerort
- Hinweise-Doku fortgeschrieben inkl. Chargen-Format-Entscheid ttmmjj (AP-24)

Tests: StorageSettingsTest, IngredientActiveRecipeFilterTest,
IngredientOrderFieldsTest (Repeater-Format), RawMaterialStockTest erweitert
(volle Suite 170 gruen, 613 Assertions)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 11:36:28 +00:00

126 lines
4.5 KiB
PHP

<?php
use App\Models\Ingredient;
use App\Models\StorageRoom;
use App\Models\StorageShelf;
use App\Models\StorageSlot;
use App\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
uses(TestCase::class, RefreshDatabase::class);
function storageSettingsUser(int $adminLevel = 8): User
{
$user = User::query()->create([
'email' => uniqid('storage_', true).'@test.example',
'password' => bcrypt('password'),
]);
$user->forceFill([
'admin' => $adminLevel,
'confirmed' => true,
'active' => true,
'wizard' => 100,
'blocked' => false,
])->save();
return $user->fresh();
}
test('allgemein-seite zeigt lagerort-karten', function () {
$this->actingAs(storageSettingsUser(8), 'user');
StorageRoom::factory()->create(['label' => 'Raum 1']);
StorageShelf::factory()->create(['label' => 'Regal 3']);
StorageSlot::factory()->create(['label' => 'A']);
$response = $this->get(route('admin.inventory.general'));
$response->assertSuccessful();
$response->assertSee('Lagerorte: Räume', false);
$response->assertSee('Lagerorte: Regale', false);
$response->assertSee('Lagerorte: Fächer / Buchstaben', false);
$response->assertSee('Raum 1', false);
$response->assertSee('Regal 3', false);
$response->assertSee(route('admin.inventory.storage-rooms.create'), false);
$response->assertSee(route('admin.inventory.storage-shelves.create'), false);
$response->assertSee(route('admin.inventory.storage-slots.create'), false);
});
test('superadmin legt raum, regal und fach an', function () {
$this->actingAs(storageSettingsUser(8), 'user');
foreach ([
['route' => 'admin.inventory.storage-rooms', 'model' => StorageRoom::class, 'label' => 'Raum 2'],
['route' => 'admin.inventory.storage-shelves', 'model' => StorageShelf::class, 'label' => 'Regal 7'],
['route' => 'admin.inventory.storage-slots', 'model' => StorageSlot::class, 'label' => 'O'],
] as $case) {
$this->get(route($case['route'].'.create'))->assertSuccessful();
$this->post(route($case['route'].'.store'), [
'label' => $case['label'],
'active' => '1',
'pos' => 0,
])->assertRedirect(route('admin.inventory.general'));
expect($case['model']::query()->where('label', $case['label'])->exists())->toBeTrue();
}
});
test('raum kann bearbeitet, deaktiviert und geloescht werden', function () {
$this->actingAs(storageSettingsUser(8), 'user');
$room = StorageRoom::factory()->create(['label' => 'Raum 5', 'active' => true, 'pos' => 1]);
$this->get(route('admin.inventory.storage-rooms.edit', $room))->assertSuccessful();
$this->put(route('admin.inventory.storage-rooms.update', $room), [
'label' => 'Raum 5 (Keller)',
'pos' => 1,
])->assertRedirect(route('admin.inventory.general'));
$room->refresh();
expect($room->label)->toBe('Raum 5 (Keller)')
->and($room->active)->toBeFalse();
$this->delete(route('admin.inventory.storage-rooms.destroy', $room))
->assertRedirect(route('admin.inventory.general'));
expect(StorageRoom::query()->whereKey($room->id)->exists())->toBeFalse();
});
test('bezeichnung ist pflicht', function () {
$this->actingAs(storageSettingsUser(8), 'user');
$this->post(route('admin.inventory.storage-rooms.store'), [
'label' => '',
])->assertSessionHasErrors('label');
});
test('nur aktive segmente ueber active-scope', function () {
StorageShelf::factory()->create(['label' => 'Aktiv', 'active' => true]);
StorageShelf::factory()->create(['label' => 'Inaktiv', 'active' => false]);
expect(StorageShelf::query()->active()->pluck('label')->all())->toBe(['Aktiv']);
});
test('geloeschter lagerort setzt ingredient-referenz auf null', function () {
$room = StorageRoom::factory()->create(['label' => 'Raum 9']);
$ingredient = Ingredient::query()->create([
'name' => 'Storage-FK-Test',
'active' => true,
'storage_room_id' => $room->id,
]);
$room->delete();
expect($ingredient->fresh()->storage_room_id)->toBeNull();
});
test('nicht-superadmin hat keinen zugriff auf lagerort-anlage', function () {
$this->actingAs(storageSettingsUser(7), 'user');
$this->get(route('admin.inventory.storage-rooms.create'))->assertRedirect('/home');
$this->get(route('admin.inventory.storage-shelves.create'))->assertRedirect('/home');
$this->get(route('admin.inventory.storage-slots.create'))->assertRedirect('/home');
});