fix: add a widget registry and "add widget" picker (#21)
CI / build-and-test (pull_request) Successful in 2m25s
CI / build-and-test (pull_request) Successful in 2m25s
"Widget hinzufügen" appended an empty placeholder card, so a widget closed via its X was gone until a page reload. Widget types now live in a WidgetRegistry (WidgetDefinition: type id, title key, default size, content factory); the toolbar button opens a picker dialog over the registry, and the dashboard builds its initial widgets from it too. Chart construction moves from DashboardView into the registry factories, which resolve translation keys through the chart component so they follow the UI locale. Added widgets get an id of "<type>-<n>" from a monotonically growing counter, so a closed widget's id is never handed to a new one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0124BiJikbhbiEsNfJxdWM69
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
package com.example.widgets;
|
||||
|
||||
import com.example.data.InMemoryChartDataService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* The definitions themselves — the factories need a Vaadin UI to resolve
|
||||
* translations, so they are exercised from {@code DashboardViewTest} instead.
|
||||
*/
|
||||
class WidgetRegistryTest {
|
||||
|
||||
private final WidgetRegistry registry = new WidgetRegistry(new InMemoryChartDataService());
|
||||
|
||||
@Test
|
||||
void definitions_areListedInRegistrationOrder() {
|
||||
List<String> types = registry.definitions().stream()
|
||||
.map(WidgetDefinition::type).toList();
|
||||
|
||||
assertEquals(List.of(WidgetRegistry.REVENUE_TREND, WidgetRegistry.REVENUE_MONTH,
|
||||
WidgetRegistry.REVENUE_REGION), types);
|
||||
assertTrue(registry.definitions().stream()
|
||||
.allMatch(d -> d.width() > 0 && d.height() > 0),
|
||||
"every definition carries a usable default size");
|
||||
}
|
||||
|
||||
@Test
|
||||
void require_rejectsAnUnknownType() {
|
||||
assertThrows(IllegalArgumentException.class, () -> registry.require("nope"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void register_replacesTheDefinitionOfTheSameType() {
|
||||
int before = registry.definitions().size();
|
||||
WidgetDefinition replacement = new WidgetDefinition(WidgetRegistry.REVENUE_TREND,
|
||||
"card.revenueTrend", 2, 2, () -> null);
|
||||
|
||||
registry.register(replacement);
|
||||
|
||||
assertEquals(before, registry.definitions().size());
|
||||
assertEquals(replacement, registry.require(WidgetRegistry.REVENUE_TREND));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user