fix: add GridStackLayout showcase view (#7)
CI / build-and-test (pull_request) Successful in 1m13s

Adds a /gridstack route demonstrating GridStackLayout: four default
widgets (line/bar/pie chart cards plus a usage hint), buttons to add and
remove widgets at runtime, a reset-layout button and a layout-change
status line. Layout is persisted per browser via the existing
localStorage support. The view gets its own SideNavItem in MainLayout
and full de/en/es translations.

Fixes an infinite recursion in GridStackLayout.add(Component): a
single-argument add(item) resolves to that overload rather than the
varargs one, so its delegation to add(item) called itself. It now
appends through the element API and passes a GridStackItem through
unwrapped.

Adds the first test sources (browserless UI tests) covering the view's
widget count and the add/remove buttons.

Closes #7

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PYAcKoXKPN3rJ7nBroKZkc
This commit is contained in:
Pit Friedrich
2026-07-25 22:12:05 +02:00
parent 12761d53ca
commit 17396466a9
9 changed files with 268 additions and 4 deletions
@@ -0,0 +1,63 @@
package com.example.views;
import com.example.Application;
import com.example.components.GridStackItem;
import com.example.components.GridStackLayout;
import com.vaadin.browserless.SpringBrowserlessTest;
import com.vaadin.browserless.ViewPackages;
import com.vaadin.flow.component.button.Button;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@SpringBootTest(classes = Application.class)
@ViewPackages(classes = GridStackView.class)
class GridStackViewTest extends SpringBrowserlessTest {
@Test
void view_rendersGridWithDefaultWidgets() {
navigate(GridStackView.class);
GridStackLayout grid = $view(GridStackLayout.class).first();
assertNotNull(grid);
List<GridStackItem.Position> layout = grid.getLayout();
assertEquals(4, layout.size(), "expected the four default widgets");
assertTrue(layout.stream().allMatch(p -> p.w() > 0 && p.h() > 0));
}
@Test
void addAndRemoveWidget_changesItemCount() {
navigate(GridStackView.class);
GridStackLayout grid = $view(GridStackLayout.class).first();
int initial = grid.getLayout().size();
button("gridstack.addWidget").click();
assertEquals(initial + 1, grid.getLayout().size());
button("gridstack.removeWidget").click();
assertEquals(initial, grid.getLayout().size());
}
@Test
void removeWidget_onDefaultLayout_keepsStaticWidgets() {
navigate(GridStackView.class);
GridStackLayout grid = $view(GridStackLayout.class).first();
button("gridstack.removeWidget").click();
assertEquals(4, grid.getLayout().size(), "static widgets must not be removable");
}
private Button button(String translationKey) {
String caption = getCurrentView().getElement().getComponent()
.orElseThrow().getTranslation(translationKey);
return $view(Button.class).withText(caption).first();
}
}