feat(theme): enhance theme management with storage capabilities and add unit tests

This commit is contained in:
extio-de
2025-12-28 13:24:02 +01:00
parent 99eb8bc46f
commit b0b9d9b4f5
7 changed files with 398 additions and 35 deletions

View File

@@ -26,7 +26,6 @@ import de.extio.game_engine.renderer.model.event.UiControlEvent;
import de.extio.game_engine.renderer.work.RenderingBoPool;
import de.extio.game_engine.resource.StaticResource;
import de.extio.game_engine.spatial2.model.ImmutableCoordI2;
import de.extio.game_engine.storage.StorageService;
public class DemoModule extends AbstractClientModule {
@@ -48,9 +47,6 @@ public class DemoModule extends AbstractClientModule {
@Autowired
private ThemeManager themeManager;
@Autowired
private StorageService storageService;
private Window mainWindow;
private Window secondaryWindow;
@@ -93,12 +89,6 @@ public class DemoModule extends AbstractClientModule {
@Override
public void onActivate() {
this.storageService.loadByPath(String.class, List.of("gameEngine"), "theme").ifPresent(themeName -> {
if (themeName != null && !themeName.isBlank()) {
this.themeManager.setCurrentTheme(themeName);
}
});
final var audioOptions = this.audioController.getAudioOptions();
this.audioMuted = isAudioMuted(audioOptions);
@@ -158,7 +148,6 @@ public class DemoModule extends AbstractClientModule {
if (themeName != null) {
this.audioController.play(new StaticResource(List.of("audio"), "alert0.ogg"));
this.themeManager.setCurrentTheme(themeName);
this.storageService.store(List.of("gameEngine"), "theme", themeName);
}
}
}

View File

@@ -0,0 +1,222 @@
package de.extio.game_engine.renderer.g2d.theme;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import de.extio.game_engine.resource.StaticResource;
import de.extio.game_engine.resource.StaticResourceService;
import de.extio.game_engine.storage.StorageService;
public class G2DThemeManagerTest {
private static Theme theme(final String name) {
return Theme.builder()
.name(name)
.patternRendererName("testPatternRenderer")
.borderOuter(new HSBColor(0.1f, 0.2f, 0.3f))
.borderInner(new HSBColor(0.1f, 0.2f, 0.3f))
.borderInnerDisabled(new HSBColor(0.1f, 0.2f, 0.3f))
.backgroundNormal(new HSBColor(0.1f, 0.2f, 0.3f))
.backgroundSelected(new HSBColor(0.1f, 0.2f, 0.3f))
.textNormal(new HSBColor(0.1f, 0.2f, 0.3f))
.textDisabled(new HSBColor(0.1f, 0.2f, 0.3f))
.selectionPrimary(new HSBColor(0.1f, 0.2f, 0.3f))
.selectionSecondary(new HSBColor(0.1f, 0.2f, 0.3f))
.windowBackground(new HSBColor(0.1f, 0.2f, 0.3f))
.hoverBrightnessAdjustment(0.25f)
.pressedBrightnessAdjustment(0.40f)
.build();
}
@Test
void loadsLastUsedThemeFromStorageOnConstruction() {
final StaticResourceService staticResourceService = org.mockito.Mockito.mock(StaticResourceService.class);
final StorageService storageService = org.mockito.Mockito.mock(StorageService.class);
final PatternRenderer patternRenderer = org.mockito.Mockito.mock(PatternRenderer.class);
final Theme defaultTheme = theme("Default");
final Theme persistedTheme = theme("Persisted");
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine", "themes")), eq("lastTheme")))
.thenReturn(Optional.of(persistedTheme));
final var manager = new G2DThemeManager(
staticResourceService,
storageService,
List.of(patternRenderer),
Map.of("defaultKey", defaultTheme),
"defaultKey");
assertEquals("Persisted", manager.getCurrentTheme().getName());
assertTrue(manager.getAvailableThemeNames().contains("Persisted"));
}
@Test
void setCurrentThemePersistsLastThemeObject() {
final StaticResourceService staticResourceService = org.mockito.Mockito.mock(StaticResourceService.class);
final StorageService storageService = org.mockito.Mockito.mock(StorageService.class);
final PatternRenderer patternRenderer = org.mockito.Mockito.mock(PatternRenderer.class);
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine", "themes")), eq("lastTheme")))
.thenReturn(Optional.empty());
final Theme defaultTheme = theme("Default");
final var manager = new G2DThemeManager(
staticResourceService,
storageService,
List.of(patternRenderer),
Map.of("defaultKey", defaultTheme),
"defaultKey");
final Theme selected = theme("Selected");
manager.setCurrentTheme(selected);
verify(storageService).store(eq(List.of("gameEngine", "themes")), eq("lastTheme"), eq(selected));
assertTrue(manager.getAvailableThemeNames().contains("Selected"));
}
@Test
void loadThemeFromStorageRegistersTheme() {
final StaticResourceService staticResourceService = org.mockito.Mockito.mock(StaticResourceService.class);
final StorageService storageService = org.mockito.Mockito.mock(StorageService.class);
final PatternRenderer patternRenderer = org.mockito.Mockito.mock(PatternRenderer.class);
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine", "themes")), eq("lastTheme")))
.thenReturn(Optional.empty());
final Theme defaultTheme = theme("Default");
final var manager = new G2DThemeManager(
staticResourceService,
storageService,
List.of(patternRenderer),
Map.of("defaultKey", defaultTheme),
"defaultKey");
final Theme loaded = theme("FromStorage");
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine", "themes")), eq("FromStorage")))
.thenReturn(Optional.of(loaded));
final Optional<Theme> result = manager.loadThemeFromStorage("FromStorage");
assertTrue(result.isPresent());
assertEquals("FromStorage", result.get().getName());
assertTrue(manager.getAvailableThemeNames().contains("FromStorage"));
}
@Test
void loadThemeFromStaticResourceRegistersTheme() {
final StaticResourceService staticResourceService = org.mockito.Mockito.mock(StaticResourceService.class);
final StorageService storageService = org.mockito.Mockito.mock(StorageService.class);
final PatternRenderer patternRenderer = org.mockito.Mockito.mock(PatternRenderer.class);
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine", "themes")), eq("lastTheme")))
.thenReturn(Optional.empty());
final Theme defaultTheme = theme("Default");
final var manager = new G2DThemeManager(
staticResourceService,
storageService,
List.of(patternRenderer),
Map.of("defaultKey", defaultTheme),
"defaultKey");
final Theme loaded = theme("FromStaticResource");
final StaticResource resource = new StaticResource(List.of("themes"), "fromStatic.theme");
when(staticResourceService.loadByPath(eq(Theme.class), eq(resource)))
.thenReturn(Optional.of(loaded));
final Optional<Theme> result = manager.loadThemeFromStaticResource(resource);
assertTrue(result.isPresent());
assertEquals("FromStaticResource", result.get().getName());
assertTrue(manager.getAvailableThemeNames().contains("FromStaticResource"));
}
@Test
void saveThemeToStorageUsesThemeNameAsStorageName() {
final StaticResourceService staticResourceService = org.mockito.Mockito.mock(StaticResourceService.class);
final StorageService storageService = org.mockito.Mockito.mock(StorageService.class);
final PatternRenderer patternRenderer = org.mockito.Mockito.mock(PatternRenderer.class);
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine", "themes")), eq("lastTheme")))
.thenReturn(Optional.empty());
final Theme defaultTheme = theme("Default");
final var manager = new G2DThemeManager(
staticResourceService,
storageService,
List.of(patternRenderer),
Map.of("defaultKey", defaultTheme),
"defaultKey");
final Theme themeToSave = theme("UserTheme");
manager.saveThemeToStorage(themeToSave);
verify(storageService).store(eq(List.of("gameEngine", "themes")), eq("UserTheme"), eq(themeToSave));
}
@Test
void saveThemeToStorageThrowsIfNoStorageService() {
final StaticResourceService staticResourceService = org.mockito.Mockito.mock(StaticResourceService.class);
final PatternRenderer patternRenderer = org.mockito.Mockito.mock(PatternRenderer.class);
final Theme defaultTheme = theme("Default");
final var manager = new G2DThemeManager(
staticResourceService,
null,
List.of(patternRenderer),
Map.of("defaultKey", defaultTheme),
"defaultKey");
assertThrows(IllegalStateException.class, () -> manager.saveThemeToStorage(theme("SomeTheme")));
}
@Test
void loadThemeFromStorageReturnsEmptyWhenStorageNotAvailable() {
final StaticResourceService staticResourceService = org.mockito.Mockito.mock(StaticResourceService.class);
final PatternRenderer patternRenderer = org.mockito.Mockito.mock(PatternRenderer.class);
final Theme defaultTheme = theme("Default");
final var manager = new G2DThemeManager(
staticResourceService,
null,
List.of(patternRenderer),
Map.of("defaultKey", defaultTheme),
"defaultKey");
final Optional<Theme> loaded = manager.loadThemeFromStorage("Anything");
assertFalse(loaded.isPresent());
}
@Test
void loadThemeFromStaticResourceReturnsEmptyWhenStaticResourceServiceNotAvailable() {
final StorageService storageService = org.mockito.Mockito.mock(StorageService.class);
final PatternRenderer patternRenderer = org.mockito.Mockito.mock(PatternRenderer.class);
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine", "themes")), eq("lastTheme")))
.thenReturn(Optional.empty());
final Theme defaultTheme = theme("Default");
final var manager = new G2DThemeManager(
null,
storageService,
List.of(patternRenderer),
Map.of("defaultKey", defaultTheme),
"defaultKey");
final Optional<Theme> loaded = manager.loadThemeFromStaticResource(new StaticResource(List.of("themes"), "x"));
assertFalse(loaded.isPresent());
verify(storageService, never()).store(any(), any(), any());
}
}