fix: harden world travel presentation
This commit is contained in:
@@ -7,11 +7,12 @@
|
||||
<p class="context-panel__selection">Ausgewähltes Ziel: {{ selected.targetLocation.name }}</p>
|
||||
}
|
||||
|
||||
<img
|
||||
class="context-panel__artwork"
|
||||
[src]="location.artworkPath"
|
||||
[alt]="'Ortsansicht: ' + location.name"
|
||||
/>
|
||||
<picture class="context-panel__artwork">
|
||||
@if (runtimeArtworkPath(location.artworkPath); as runtimeArtwork) {
|
||||
<source [srcset]="runtimeArtwork" type="image/jpeg" />
|
||||
}
|
||||
<img [src]="location.artworkPath" [alt]="'Ortsansicht: ' + location.name" />
|
||||
</picture>
|
||||
<p class="context-panel__description">{{ location.description }}</p>
|
||||
|
||||
<dl class="context-panel__facts">
|
||||
|
||||
@@ -42,8 +42,13 @@
|
||||
.context-panel__artwork {
|
||||
display: block;
|
||||
inline-size: 100%;
|
||||
aspect-ratio: 16 / 9;
|
||||
margin-block-end: var(--ar-space-3);
|
||||
}
|
||||
|
||||
.context-panel__artwork img {
|
||||
display: block;
|
||||
inline-size: 100%;
|
||||
aspect-ratio: 16 / 9;
|
||||
border: 1px solid var(--ar-border);
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import { signal } from '@angular/core';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { WorldStore } from '../../features/world/world.store';
|
||||
import { ContextPanelComponent } from './context-panel.component';
|
||||
|
||||
describe('ContextPanelComponent', () => {
|
||||
it('uses a runtime location derivative while preserving the API artwork path as image fallback', async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [ContextPanelComponent],
|
||||
providers: [
|
||||
{
|
||||
provide: WorldStore,
|
||||
useValue: {
|
||||
currentLocation: signal({
|
||||
id: 'south-gate-id',
|
||||
key: 'south-gate',
|
||||
name: 'Südtor von Graufurt',
|
||||
description: 'Der letzte sichere Schritt vor den Aschenfeldern.',
|
||||
regionKey: 'ashen-fields',
|
||||
minRecommendedLevel: 1,
|
||||
maxRecommendedLevel: 1,
|
||||
dangerLevel: 0,
|
||||
isSafe: true,
|
||||
huntingEnabled: false,
|
||||
artworkPath: '/images/backgrounds/Suedtor.png',
|
||||
connections: [],
|
||||
}),
|
||||
selectedConnection: signal(null),
|
||||
},
|
||||
},
|
||||
],
|
||||
}).compileComponents();
|
||||
|
||||
const fixture = TestBed.createComponent(ContextPanelComponent);
|
||||
fixture.detectChanges();
|
||||
|
||||
const element = fixture.nativeElement as HTMLElement;
|
||||
expect(element.querySelector<HTMLSourceElement>('source')?.srcset).toContain(
|
||||
'/images/backgrounds/runtime/Suedtor-960.jpg',
|
||||
);
|
||||
expect(element.querySelector<HTMLImageElement>('img')?.getAttribute('src')).toBe(
|
||||
'/images/backgrounds/Suedtor.png',
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,11 @@
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { WorldStore } from '../../features/world/world.store';
|
||||
|
||||
const runtimeArtworkPaths: Readonly<Record<string, string>> = {
|
||||
'/images/backgrounds/Suedtor.png': '/images/backgrounds/runtime/Suedtor-960.jpg',
|
||||
'/images/backgrounds/Aschestrasse.png': '/images/backgrounds/runtime/Aschestrasse-960.jpg',
|
||||
};
|
||||
|
||||
@Component({
|
||||
selector: 'app-context-panel',
|
||||
templateUrl: './context-panel.component.html',
|
||||
@@ -8,4 +13,8 @@ import { WorldStore } from '../../features/world/world.store';
|
||||
})
|
||||
export class ContextPanelComponent {
|
||||
protected readonly worldStore = inject(WorldStore);
|
||||
|
||||
protected runtimeArtworkPath(artworkPath: string): string | undefined {
|
||||
return runtimeArtworkPaths[artworkPath];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user