diff --git a/apps/web/src/app/features/inventory/inventory-page.component.spec.ts b/apps/web/src/app/features/inventory/inventory-page.component.spec.ts index 0ba100d..47e2a2a 100644 --- a/apps/web/src/app/features/inventory/inventory-page.component.spec.ts +++ b/apps/web/src/app/features/inventory/inventory-page.component.spec.ts @@ -1,8 +1,10 @@ import { signal } from '@angular/core'; import { TestBed } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; import { vi } from 'vitest'; -import type { CharacterResponse, EquipmentResponse, InventoryResponse } from '../../core/api/game-api.models'; +import type { CharacterResponse, EquipmentResponse, InventoryItem, InventoryResponse } from '../../core/api/game-api.models'; import { WorldStore } from '../world/world.store'; +import { InventoryDetailPanelComponent } from './inventory-detail-panel.component'; import { InventoryPageComponent } from './inventory-page.component'; import { InventoryStore } from './inventory.store'; @@ -70,17 +72,23 @@ const character: CharacterResponse = { currentLocation: { id: 'loc-1', key: 'south-gate', name: 'Südtor' }, }; -async function setup() { +interface SetupOptions { + inventoryData?: InventoryResponse; + selectedItemId?: string | null; + selectedItem?: InventoryItem | null; +} + +async function setup(options: SetupOptions = {}) { const inventoryStore = { - inventory: signal(inventory), + inventory: signal(options.inventoryData ?? inventory), equipment: signal(equipment), - selectedItemId: signal(null), + selectedItemId: signal(options.selectedItemId ?? null), loading: signal(false), equipping: signal(false), error: signal(null), load: vi.fn(() => Promise.resolve()), selectItem: vi.fn(), - selectedItem: vi.fn(() => null), + selectedItem: vi.fn(() => options.selectedItem ?? null), equip: vi.fn(() => Promise.resolve()), }; const worldStore = { character: signal(character) }; @@ -140,4 +148,44 @@ describe('InventoryPageComponent', () => { expect(text).toContain('6'); expect(text).toContain('8'); }); + + it('passes the equipped item from the SAME slot as the selection — not just any equipped item — to the detail panel', async () => { + // item-helm (HEAD, equipped) is placed before item-sword (WEAPON, equipped) so that a + // regression which drops the equipmentSlot match (i.e. "find the first equipped item") + // would surface item-helm instead of item-sword, and this test would fail. + const threeItemInventory: InventoryResponse = { + items: [ + { + id: 'item-helm', + quantity: 1, + equipped: true, + item: { + key: 'iron-helm', + name: 'Eiserner Helm', + rarity: 'COMMON', + equipmentSlot: 'HEAD', + requiredLevel: 1, + weaponDamage: 0, + bonusAttack: 0, + bonusHp: 5, + bonusArmor: 2, + iconPath: '/images/items/iron-helm.png', + }, + }, + inventory.items[0], // item-sword, WEAPON, equipped + inventory.items[1], // item-blade, WEAPON, not equipped — this is the selection + ], + }; + + const { fixture } = await setup({ + inventoryData: threeItemInventory, + selectedItemId: 'item-blade', + selectedItem: threeItemInventory.items[2], + }); + + const panel = fixture.debugElement.query(By.directive(InventoryDetailPanelComponent)) + .componentInstance as InventoryDetailPanelComponent; + + expect(panel.equippedItemInSlot()?.id).toBe('item-sword'); + }); });