8545b06f41
CI / build-and-test (pull_request) Successful in 2m25s
A GridStackItem now carries an overflow menu next to the grip and the close button: refresh, maximize, duplicate, remove. Maximize and remove are handled by the item itself; refresh and duplicate are only reported, since what they mean depends on the widget. Maximizing only sets a class — the item's gs-* attributes and its gridstack node are untouched, so restoring is by definition the position it had. The menu sits outside the drag-handle selector, like the close button, so opening it never starts a drag; a Playwright test drags it to prove it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0124BiJikbhbiEsNfJxdWM69
59 lines
2.1 KiB
Java
59 lines
2.1 KiB
Java
package com.example.widgets;
|
|
|
|
import com.example.data.InMemoryChartDataService;
|
|
import com.vaadin.flow.component.html.Div;
|
|
import org.junit.jupiter.api.Test;
|
|
|
|
import java.util.List;
|
|
|
|
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
|
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");
|
|
}
|
|
|
|
/** A widget with no refresher must not blow up when one is asked for: the
|
|
* dashboard offers the action per widget, the registry only carries it
|
|
* out. */
|
|
@Test
|
|
void refresh_ignoresAWidgetThatCarriesNoRefresher() {
|
|
assertDoesNotThrow(() -> WidgetRegistry.refresh(new Div()));
|
|
}
|
|
|
|
@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, context -> null);
|
|
|
|
registry.register(replacement);
|
|
|
|
assertEquals(before, registry.definitions().size());
|
|
assertEquals(replacement, registry.require(WidgetRegistry.REVENUE_TREND));
|
|
}
|
|
}
|