diff --git a/src/main/java/org/vaadin/addons/dramafinder/element/ProgressBarElement.java b/src/main/java/org/vaadin/addons/dramafinder/element/ProgressBarElement.java index 6b7553e..aad5541 100644 --- a/src/main/java/org/vaadin/addons/dramafinder/element/ProgressBarElement.java +++ b/src/main/java/org/vaadin/addons/dramafinder/element/ProgressBarElement.java @@ -18,22 +18,30 @@ public class ProgressBarElement extends VaadinElement implements HasThemeElement public static final String FIELD_TAG_NAME = "vaadin-progress-bar"; public static final String INDETERMINATE_ATTRIBUTE = "indeterminate"; - /** Create a {@code ProgressBarElement} from an existing locator. */ + /** + * Create a {@code ProgressBarElement} from an existing locator. + */ public ProgressBarElement(Locator locator) { - super(locator); + super(locator.and(locator.page().locator(FIELD_TAG_NAME))); } - /** Current numeric value parsed from {@code aria-valuenow}. */ + /** + * Current numeric value parsed from {@code aria-valuenow}. + */ public double getValue() { return Double.parseDouble(getLocator().getAttribute("aria-valuenow")); } - /** Set the progress bar {@code value}. */ + /** + * Set the progress bar {@code value}. + */ public void setValue(double min) { getLocator().evaluate("(el, v) => el.value = v", min); } - /** Assert that the numeric value matches. */ + /** + * Assert that the numeric value matches. + */ public void assertValue(Double expected) { if (expected != null) { assertThat(getLocator()).hasAttribute("aria-valuenow", NumberUtils.formatDouble(expected)); @@ -42,54 +50,74 @@ public void assertValue(Double expected) { } } - /** Get the {@code min} value. */ + /** + * Get the {@code min} value. + */ public Double getMin() { String v = getLocator().getAttribute("aria-valuemin"); return v == null ? null : Double.valueOf(v); } - /** Set the {@code min} value. */ + /** + * Set the {@code min} value. + */ public void setMin(double min) { getLocator().evaluate("(el, v) => el.min = v", min); } - /** Assert that {@code min} matches the expected value. */ + /** + * Assert that {@code min} matches the expected value. + */ public void assertMin(double min) { assertThat(getLocator()).hasAttribute("aria-valuemin", NumberUtils.formatDouble(min)); } - /** Get the {@code max} value. */ + /** + * Get the {@code max} value. + */ public Double getMax() { String v = getLocator().getAttribute("aria-valuemax"); return v == null ? null : Double.valueOf(v); } - /** Set the {@code max} value. */ + /** + * Set the {@code max} value. + */ public void setMax(double max) { getLocator().evaluate("(el, v) => el.max = v", max); } - /** Assert that {@code max} matches the expected value. */ + /** + * Assert that {@code max} matches the expected value. + */ public void assertMax(double max) { assertThat(getLocator()).hasAttribute("aria-valuemax", NumberUtils.formatDouble(max)); } - /** Whether the bar is indeterminate. */ + /** + * Whether the bar is indeterminate. + */ public boolean isIndeterminate() { return getLocator().getAttribute(INDETERMINATE_ATTRIBUTE) != null; } - /** Assert indeterminate state. */ + /** + * Assert indeterminate state. + */ public void assertIndeterminate() { assertThat(getLocator()).hasAttribute(INDETERMINATE_ATTRIBUTE, ""); } - /** Assert not indeterminate. */ + /** + * Assert not indeterminate. + */ public void assertNotIndeterminate() { assertThat(getLocator()).not().hasAttribute(INDETERMINATE_ATTRIBUTE, ""); } - /** Set the indeterminate state. */ + /** + * Set the indeterminate state. + */ public void setIndeterminate(boolean indeterminate) { getLocator().evaluate("(el, val) => el.indeterminate = val", indeterminate); } diff --git a/src/main/java/org/vaadin/addons/dramafinder/element/SplitLayoutElement.java b/src/main/java/org/vaadin/addons/dramafinder/element/SplitLayoutElement.java new file mode 100644 index 0000000..ef6da49 --- /dev/null +++ b/src/main/java/org/vaadin/addons/dramafinder/element/SplitLayoutElement.java @@ -0,0 +1,90 @@ +package org.vaadin.addons.dramafinder.element; + +import com.microsoft.playwright.Locator; +import com.microsoft.playwright.Page; +import org.vaadin.addons.dramafinder.element.shared.HasStyleElement; +import org.vaadin.addons.dramafinder.element.shared.HasThemeElement; + +import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; + +/** + * PlaywrightElement for {@code vaadin-split-layout}. + *
+ * Provides helpers to read/change orientation, access primary/secondary slotted + * content and control splitter position. Primary/secondary content is exposed + * via the {@code slot} attribute, and the splitter is moved by property or drag. + */ +@PlaywrightElement(SplitLayoutElement.FIELD_TAG_NAME) +public class SplitLayoutElement extends VaadinElement implements HasStyleElement, HasThemeElement { + + public static final String FIELD_TAG_NAME = "vaadin-split-layout"; + + /** + * Create a new {@code SplitLayoutElement}. + */ + public SplitLayoutElement(Locator locator) { + super(locator); + } + + /** + * Get the first split layout on the page. + */ + public static SplitLayoutElement get(Page page) { + return new SplitLayoutElement(page.locator(FIELD_TAG_NAME).first()); + } + + /** + * Locator for the primary content (slot="primary"). + */ + public Locator getPrimaryLocator() { + return getLocator().locator("[slot='primary']"); + } + + /** + * Locator for the secondary content (slot="secondary"). + */ + public Locator getSecondaryLocator() { + return getLocator().locator("[slot='secondary']"); + } + + /** + * Locator for the splitter handle (shadow part="handle"). + */ + public Locator getHandleLocator() { + return getLocator().locator("[part='handle']"); + } + + /** + * Assert that the layout orientation is vertical. + */ + public void assertVertical() { + assertThat(getLocator()).hasAttribute("orientation", "vertical"); + } + + /** + * Assert that the layout orientation is horizontal. + */ + public void assertHorizontal() { + assertThat(getLocator()).not().hasAttribute("orientation", "vertical"); + } + + /** + * Drag the splitter by a delta offset in pixels. + * Positive X moves to the right, positive Y moves down. + */ + public void dragSplitterBy(double deltaX, double deltaY) { + Locator splitter = getHandleLocator(); + var box = splitter.boundingBox(); + if (box == null) { + return; + } + double startX = box.x; + double startY = box.y; + Page page = splitter.page(); + page.mouse().move(startX, startY); + page.mouse().down(); + page.mouse().move(box.x + (box.width / 2) + deltaX, box.y + (box.height / 2) + deltaY); + page.mouse().up(); + } + +} diff --git a/src/test/java/org/vaadin/addons/dramafinder/tests/it/SplitLayoutViewIT.java b/src/test/java/org/vaadin/addons/dramafinder/tests/it/SplitLayoutViewIT.java new file mode 100644 index 0000000..96f3ad4 --- /dev/null +++ b/src/test/java/org/vaadin/addons/dramafinder/tests/it/SplitLayoutViewIT.java @@ -0,0 +1,83 @@ +package org.vaadin.addons.dramafinder.tests.it; + +import com.microsoft.playwright.Locator; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.vaadin.addons.dramafinder.HasTestView; +import org.vaadin.addons.dramafinder.element.SplitLayoutElement; + +import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; + +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +public class SplitLayoutViewIT extends SpringPlaywrightIT implements HasTestView { + + @Override + public String getView() { + return "splitlayout"; + } + + @Test + public void testDefaultHorizontal() { + SplitLayoutElement split = SplitLayoutElement.get(page); + assertThat(split.getLocator()).isVisible(); + split.assertHorizontal(); + + assertThat(split.getPrimaryLocator().getByText("Primary 1")).isVisible(); + assertThat(split.getSecondaryLocator().getByText("Secondary 1")).isVisible(); + + } + + @Test + public void testVertical() { + Locator verticalHost = page.locator(SplitLayoutElement.FIELD_TAG_NAME + "[orientation='vertical']").first(); + SplitLayoutElement vertical = new SplitLayoutElement(verticalHost); + vertical.assertVertical(); + assertThat(vertical.getPrimaryLocator().getByText("Primary V")).isVisible(); + assertThat(vertical.getSecondaryLocator().getByText("Secondary V")).isVisible(); + } + + @Test + public void testSplitterPositionSet() { + page.setViewportSize(1600, 1400); + Locator positionedHost = page.locator(SplitLayoutElement.FIELD_TAG_NAME).nth(2); + SplitLayoutElement splitLayoutElement = new SplitLayoutElement(positionedHost); + assertThat(splitLayoutElement.getLocator()).isVisible(); + double initialWidth = splitLayoutElement.getPrimaryLocator().boundingBox().width; + assertWidth(splitLayoutElement.getPrimaryLocator(), initialWidth, 2); + splitLayoutElement.dragSplitterBy(-100, 0); + assertWidth(splitLayoutElement.getPrimaryLocator(), initialWidth - 100, 5); + splitLayoutElement.dragSplitterBy(-100, 0); + assertWidth(splitLayoutElement.getPrimaryLocator(), initialWidth - 200, 5); + } + + @Test + public void testSplitterPositionSet2() { + page.setViewportSize(1600, 1400); + Locator positionedHost = page.locator(SplitLayoutElement.FIELD_TAG_NAME).nth(2); + SplitLayoutElement splitLayoutElement = new SplitLayoutElement(positionedHost); + assertThat(splitLayoutElement.getLocator()).isVisible(); + double initialWidth = splitLayoutElement.getPrimaryLocator().boundingBox().width; + assertWidth(splitLayoutElement.getPrimaryLocator(), initialWidth, 2); + splitLayoutElement.dragSplitterBy(100, 0); + assertWidth(splitLayoutElement.getPrimaryLocator(), initialWidth + 100, 5); + splitLayoutElement.dragSplitterBy(100, 0); + assertWidth(splitLayoutElement.getPrimaryLocator(), initialWidth + 200, 5); + } + + private static void assertWidth(Locator locator, double expectedWidth, double tolerance) { + var box = locator.boundingBox(); + if (box == null) { + throw new AssertionError("Element not found or not visible — cannot read width."); + } + + double actual = box.width; + + if (Math.abs(actual - expectedWidth) > tolerance) { + throw new AssertionError( + "Expected width: " + expectedWidth + "px but was: " + actual + "px" + ); + } + } + +} diff --git a/src/test/java/org/vaadin/addons/dramafinder/tests/testuis/SplitLayoutView.java b/src/test/java/org/vaadin/addons/dramafinder/tests/testuis/SplitLayoutView.java new file mode 100644 index 0000000..00af394 --- /dev/null +++ b/src/test/java/org/vaadin/addons/dramafinder/tests/testuis/SplitLayoutView.java @@ -0,0 +1,30 @@ +package org.vaadin.addons.dramafinder.tests.testuis; + +import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.component.html.Main; +import com.vaadin.flow.component.splitlayout.SplitLayout; +import com.vaadin.flow.component.splitlayout.SplitLayout.Orientation; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; + +@PageTitle("SplitLayout Demo") +@Route(value = "splitlayout", layout = MainLayout.class) +public class SplitLayoutView extends Main { + + public SplitLayoutView() { + // Default horizontal split + SplitLayout horizontal = new SplitLayout(new Div(new Div("Primary 1")), new Div(new Div("Secondary 1"))); + add(horizontal); + + // Vertical split + SplitLayout vertical = new SplitLayout(new Div(new Div("Primary V")), new Div(new Div("Secondary V"))); + vertical.setOrientation(Orientation.VERTICAL); + add(vertical); + + // Pre-positioned splitter + SplitLayout positioned = new SplitLayout(new Div(new Div("Primary P")), new Div(new Div("Secondary P"))); + positioned.setSplitterPosition(70); + add(positioned); + } +} +