feat(web): drop the XP block from the combat victory screen

Design ruling R16: the victory screen removes the data-reward-experience
element and its "Erfahrung" line outright rather than hiding them behind
a conditional. CombatReward is now { silver, items }.

The surviving spec assertion checks that [data-reward-experience] is
absent, so it would genuinely fail if the block came back -- rather than
merely observing that some text changed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Bastian Wagner
2026-08-21 15:38:40 +02:00
parent c0401d5c60
commit 9d1c1a7706
3 changed files with 8 additions and 14 deletions

View File

@@ -140,10 +140,6 @@
<h3 class="rewards__title">Belohnungen</h3> <h3 class="rewards__title">Belohnungen</h3>
<dl class="rewards__currencies"> <dl class="rewards__currencies">
<div class="rewards__currency" data-reward-experience>
<dt>Erfahrung</dt>
<dd>+{{ rewards.experience }} XP</dd>
</div>
<div class="rewards__currency" data-reward-silver> <div class="rewards__currency" data-reward-silver>
<dt>Silber</dt> <dt>Silber</dt>
<dd>+{{ rewards.silver }}</dd> <dd>+{{ rewards.silver }}</dd>

View File

@@ -426,7 +426,7 @@ describe('CombatPageComponent', () => {
...activeCombat, ...activeCombat,
status: 'WON', status: 'WON',
monster: { ...activeCombat.monster, currentHp: 0 }, monster: { ...activeCombat.monster, currentHp: 0 },
rewards: { experience: 8, silver: 6, items: [] }, rewards: { silver: 6, items: [] },
events: [ events: [
...activeCombat.events, ...activeCombat.events,
{ round: 2, sequence: 3, type: 'DAMAGE', source: 'PLAYER', target: 'MONSTER', amount: 31 }, { round: 2, sequence: 3, type: 'DAMAGE', source: 'PLAYER', target: 'MONSTER', amount: 31 },
@@ -526,16 +526,18 @@ describe('CombatPageComponent', () => {
...activeCombat, ...activeCombat,
status: 'WON', status: 'WON',
monster: { ...activeCombat.monster, currentHp: 0 }, monster: { ...activeCombat.monster, currentHp: 0 },
rewards: { experience: 8, silver: 6, items: [] }, rewards: { silver: 6, items: [] },
}; };
it('shows the granted XP and silver on the victory screen', async () => { it('shows the granted silver on the victory screen', async () => {
const fixture = await setup(wonWithRewards); const fixture = await setup(wonWithRewards);
const element = fixture.nativeElement as HTMLElement; const element = fixture.nativeElement as HTMLElement;
expect(element.querySelector('[data-combat-rewards]')).toBeTruthy(); expect(element.querySelector('[data-combat-rewards]')).toBeTruthy();
expect(element.querySelector('[data-reward-experience]')?.textContent).toContain('8');
expect(element.querySelector('[data-reward-silver]')?.textContent).toContain('6'); expect(element.querySelector('[data-reward-silver]')?.textContent).toContain('6');
// R16: the XP block is removed entirely, not hidden -- guard against it
// reappearing in the markup.
expect(element.querySelector('[data-reward-experience]')).toBeNull();
}); });
it('renders a dropped item with its icon, name, and rarity', async () => { it('renders a dropped item with its icon, name, and rarity', async () => {
@@ -543,7 +545,6 @@ describe('CombatPageComponent', () => {
...wonWithRewards, ...wonWithRewards,
monster: { ...activeCombat.monster, key: 'road-bandit', name: 'Straßenräuber', currentHp: 0 }, monster: { ...activeCombat.monster, key: 'road-bandit', name: 'Straßenräuber', currentHp: 0 },
rewards: { rewards: {
experience: 16,
silver: 12, silver: 12,
items: [ items: [
{ {
@@ -577,8 +578,6 @@ describe('CombatPageComponent', () => {
'Keine besondere Beute gefunden.', 'Keine besondere Beute gefunden.',
); );
expect(element.querySelector('[role="alert"]')).toBeNull(); expect(element.querySelector('[role="alert"]')).toBeNull();
// XP and silver still carry the screen.
expect(element.querySelector('[data-reward-experience]')).toBeTruthy();
}); });
it('renders the persisted rewards of an already-won combat loaded from the server', async () => { it('renders the persisted rewards of an already-won combat loaded from the server', async () => {
@@ -586,12 +585,11 @@ describe('CombatPageComponent', () => {
// exactly what the server persisted, without rerolling anything. // exactly what the server persisted, without rerolling anything.
const fixture = await setup({ const fixture = await setup({
...wonWithRewards, ...wonWithRewards,
rewards: { experience: 16, silver: 12, items: [] }, rewards: { silver: 12, items: [] },
}); });
const element = fixture.nativeElement as HTMLElement; const element = fixture.nativeElement as HTMLElement;
expect(combatStore.loadCombat).toHaveBeenCalledWith('combat-1'); expect(combatStore.loadCombat).toHaveBeenCalledWith('combat-1');
expect(element.querySelector('[data-reward-experience]')?.textContent).toContain('16');
expect(element.querySelector('[data-reward-silver]')?.textContent).toContain('12'); expect(element.querySelector('[data-reward-silver]')?.textContent).toContain('12');
}); });

View File

@@ -105,7 +105,7 @@ export class CombatPageComponent implements OnInit {
} }
if (after.status === 'WON') { if (after.status === 'WON') {
// The server already granted XP and silver; pull the authoritative // The server already granted silver and renown; pull the authoritative
// character so the HUD matches (spec §35). // character so the HUD matches (spec §35).
void this.worldStore.refreshCharacter(); void this.worldStore.refreshCharacter();
} }