diff --git a/pom.xml b/pom.xml index 195d5a8..fbdfa6f 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.vaadin.addons.flowingcode grid-helpers - 1.3.3-SNAPSHOT + 1.4.0-SNAPSHOT Grid Helpers Add-on Grid Helpers Add-on for Vaadin Flow @@ -16,6 +16,8 @@ UTF-8 ${project.basedir}/drivers 9.4.36.v20210114 + 3.8.1 + 1.0.17 @@ -158,7 +160,7 @@ io.github.bonigarcia webdrivermanager - 3.8.1 + ${webdrivermanager.version} test @@ -330,7 +332,7 @@ true none - -Xdoclint:none + -Xdoclint:none @@ -414,9 +416,8 @@ com.lazerycode.selenium - driver-binary-downloader-maven-plugin - - 1.0.17 + driver-binary-downloader-maven-plugin + ${driver-binary-downloader-maven-plugin.version} true @@ -563,7 +564,18 @@ 24.2.6 11.0.12 true + 5.6.3 + 1.0.18 + + + + org.seleniumhq.selenium + selenium-java + 4.17.0 + test + + diff --git a/src/main/java/com/flowingcode/vaadin/addons/gridhelpers/GridHelper.java b/src/main/java/com/flowingcode/vaadin/addons/gridhelpers/GridHelper.java index 48a3ee8..bd0dbc7 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/gridhelpers/GridHelper.java +++ b/src/main/java/com/flowingcode/vaadin/addons/gridhelpers/GridHelper.java @@ -555,4 +555,12 @@ public static CheckboxColumn addCheckboxColumn(Grid grid, public static void toggleSelectAllCheckbox(Grid grid, boolean visible) { getHelper(grid).lazySelectAllGridHelper.toggleSelectAllCheckbox(visible); } + + private final GridRadioSelectionColumnHelper radioButtonSelectionColumnHelper = + new GridRadioSelectionColumnHelper<>(this); + + public static GridRadioSelectionColumn showRadioSelectionColumn(Grid grid) { + return getHelper(grid).radioButtonSelectionColumnHelper.showRadioSelectionColumn(); + } + } diff --git a/src/main/java/com/flowingcode/vaadin/addons/gridhelpers/GridRadioSelectionColumn.java b/src/main/java/com/flowingcode/vaadin/addons/gridhelpers/GridRadioSelectionColumn.java new file mode 100644 index 0000000..f98feb7 --- /dev/null +++ b/src/main/java/com/flowingcode/vaadin/addons/gridhelpers/GridRadioSelectionColumn.java @@ -0,0 +1,58 @@ +/*- + * #%L + * Grid Helpers Add-on + * %% + * Copyright (C) 2022 - 2024 Flowing Code + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +package com.flowingcode.vaadin.addons.gridhelpers; + +import com.vaadin.flow.component.Component; +import com.vaadin.flow.component.HasStyle; +import com.vaadin.flow.component.Synchronize; +import com.vaadin.flow.component.Tag; +import com.vaadin.flow.component.dependency.JsModule; +import com.vaadin.flow.component.dependency.NpmPackage; + +/** + * Server side implementation for the flow specific grid radio selection column. + */ +@Tag("grid-flow-radio-selection-column") +@NpmPackage(value = "@vaadin/polymer-legacy-adapter", version = "24.3.2") +@JsModule("@vaadin/polymer-legacy-adapter/style-modules.js") +@JsModule("./fcGridHelper/grid-flow-radio-selection-column.js") +public class GridRadioSelectionColumn extends Component implements HasStyle { + + /** + * Sets this column's frozen state. + * + * @param frozen whether to freeze or unfreeze this column + */ + public void setFrozen(boolean frozen) { + getElement().setProperty("frozen", frozen); + } + + /** + * Gets the this column's frozen state. + * + * @return whether this column is frozen + */ + @Synchronize("frozen-changed") + public boolean isFrozen() { + return getElement().getProperty("frozen", false); + } + +} diff --git a/src/main/java/com/flowingcode/vaadin/addons/gridhelpers/GridRadioSelectionColumnHelper.java b/src/main/java/com/flowingcode/vaadin/addons/gridhelpers/GridRadioSelectionColumnHelper.java new file mode 100644 index 0000000..590dc74 --- /dev/null +++ b/src/main/java/com/flowingcode/vaadin/addons/gridhelpers/GridRadioSelectionColumnHelper.java @@ -0,0 +1,62 @@ +/*- + * #%L + * Grid Helpers Add-on + * %% + * Copyright (C) 2022 - 2024 Flowing Code + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +package com.flowingcode.vaadin.addons.gridhelpers; + +import com.vaadin.flow.component.grid.Grid; +import com.vaadin.flow.component.grid.Grid.SelectionMode; +import java.io.Serializable; +import lombok.RequiredArgsConstructor; + +@SuppressWarnings("serial") +@RequiredArgsConstructor +class GridRadioSelectionColumnHelper implements Serializable { + + private final GridHelper helper; + + private GridRadioSelectionColumn selectionColumn; + + public GridRadioSelectionColumn showRadioSelectionColumn() { + remove(); + + Grid grid = helper.getGrid(); + grid.setSelectionMode(SelectionMode.SINGLE); + + selectionColumn = new GridRadioSelectionColumn(); + selectionColumn.setClassName("fc-grid-radio-selection-column"); + + if (grid.getElement().getNode().isAttached()) { + grid.getElement().insertChild(0, selectionColumn.getElement()); + } else { + grid.getElement().getNode().runWhenAttached(ui -> { + grid.getElement().insertChild(0, selectionColumn.getElement()); + }); + } + + return selectionColumn; + } + + private void remove() { + if (selectionColumn != null && selectionColumn.getElement().getNode().isAttached()) { + helper.getGrid().getElement().removeChild(selectionColumn.getElement()); + } + } + +} diff --git a/src/main/resources/META-INF/frontend/fcGridHelper/grid-flow-radio-selection-column.js b/src/main/resources/META-INF/frontend/fcGridHelper/grid-flow-radio-selection-column.js new file mode 100644 index 0000000..9364114 --- /dev/null +++ b/src/main/resources/META-INF/frontend/fcGridHelper/grid-flow-radio-selection-column.js @@ -0,0 +1,131 @@ +/*- + * #%L + * Grid Helpers Add-on + * %% + * Copyright (C) 2022 - 2024 Flowing Code + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import '@vaadin/grid/vaadin-grid-column.js'; +import { GridColumn } from '@vaadin/grid/src/vaadin-grid-column.js'; +import { GridRadioSelectionColumnBaseMixin } from './grid-radio-selection-column-base-mixin.js'; + +class GridFlowRadioSelectionColumn extends GridRadioSelectionColumnBaseMixin(GridColumn) { + + static get is() { + return 'grid-flow-radio-selection-column'; + } + + static get properties() { + return { + /** + * Override property to enable auto-width + */ + autoWidth: { + type: Boolean, + value: true + }, + + /** + * Override property to set custom width + */ + width: { + type: String, + value: '56px' + }, + + /** + * The previous state of activeItem. When activeItem turns to `null`, + * previousActiveItem will have an Object with just unselected activeItem + * @private + */ + __previousActiveItem: Object, + }; + } + + + constructor() { + super(); + this.__boundOnActiveItemChanged = this.__onActiveItemChanged.bind(this); + } + + /** @protected */ + disconnectedCallback() { + this._grid.removeEventListener('active-item-changed', this.__boundOnActiveItemChanged); + super.disconnectedCallback(); + } + + /** @protected */ + connectedCallback() { + super.connectedCallback(); + if (this._grid) { + this._grid.addEventListener('active-item-changed', this.__boundOnActiveItemChanged); + } + } + + /** + * Override a method from `GridRadioSelectionColumnBaseMixin` to handle the user + * selecting an item. + * + * @param {Object} item the item to select + * @protected + * @override + */ + _selectItem(item) { + this._grid.$connector.doSelection([item], true); + } + + /** + * Override a method from `GridRadioSelectionColumnBaseMixin` to handle the user + * deselecting an item. + * + * @param {Object} item the item to deselect + * @protected + * @override + */ + _deselectItem(item) { + this._grid.$connector.doDeselection([item], true); + } + + + /** @private */ + __onActiveItemChanged(e) { + const activeItem = e.detail.value; + if (activeItem) { + if(this.__previousActiveItem !== activeItem) { + this._deselectItem(this.__previousActiveItem); + } + this._selectItem(activeItem); + this.__previousActiveItem = activeItem; + } else { + this.__previousActiveItem = undefined; + } + } + + /** + * Override a method from `GridRadioSelectionColumnBaseMixin` to handle the user clicked on an item. + * + * @param {Object} item the clicked item + * @protected + * @override + */ + _onItemClicked(item) { + super._onItemClicked(item); + this.__previousActiveItem = item; + } + +} + +customElements.define(GridFlowRadioSelectionColumn.is, GridFlowRadioSelectionColumn); diff --git a/src/main/resources/META-INF/frontend/fcGridHelper/grid-radio-selection-column-base-mixin.js b/src/main/resources/META-INF/frontend/fcGridHelper/grid-radio-selection-column-base-mixin.js new file mode 100644 index 0000000..2318520 --- /dev/null +++ b/src/main/resources/META-INF/frontend/fcGridHelper/grid-radio-selection-column-base-mixin.js @@ -0,0 +1,116 @@ +/*- + * #%L + * Grid Helpers Add-on + * %% + * Copyright (C) 2022 - 2024 Flowing Code + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import { addListener } from '@vaadin/component-base/src/gestures.js'; + +/** + * A mixin that provides basic functionality for the + * ``. This includes properties, cell rendering, + * and overridable methods for handling changes to the selection state. + * + * **NOTE**: This mixin is re-used by the Flow component, and as such must not + * implement any selection state updates for the column element or the grid. + * Web component-specific selection state updates must be implemented in the + * `` itself, by overriding the protected methods + * provided by this mixin. + * + * @polymerMixin + */ +export const GridRadioSelectionColumnBaseMixin = (superClass) => + class GriRadioSelectionColumnBaseMixin extends superClass { + static get properties() { + return { + /** + * Width of the cells for this column. + */ + width: { + type: String, + value: '58px', + }, + + /** + * Flex grow ratio for the cell widths. When set to 0, cell width is fixed. + * @attr {number} flex-grow + * @type {number} + */ + flexGrow: { + type: Number, + value: 0, + }, + + /** + * When true, the active gets automatically selected. + * @attr {boolean} auto-select + * @type {boolean} + */ + autoSelect: { + type: Boolean, + value: false, + }, + + }; + } + + static get observers() { + return [ + '_onHeaderRendererOrBindingChanged(path)', + ]; + } + + /** + * Renders the Select Row radio button to the body cell. + * + * @override + */ + _defaultRenderer(root, _column, { item, selected }) { + let radioButton = root.firstElementChild; + if (!radioButton) { + radioButton = document.createElement('vaadin-radio-button'); + radioButton.setAttribute('aria-label', 'Select Row'); + root.appendChild(radioButton); + // Add listener after appending, so we can skip the initial change event + radioButton.addEventListener('checked-changed', this.__onSelectRowCheckedChanged.bind(this)); + } + + radioButton.__item = item; + radioButton.__rendererChecked = selected; + radioButton.checked = selected; + } + + /** + * Selects the row when the Select Row radio button is clicked. + * The listener handles only user-fired events. + * + * @private + */ + __onSelectRowCheckedChanged(e) { + // Skip if the state is changed by the renderer. + if (e.target.checked === e.target.__rendererChecked) { + return; + } + + this._onItemClicked(e.target.__item); + } + + _onItemClicked(item){ + this._selectItem(item); + } + + }; diff --git a/src/main/resources/META-INF/frontend/fcGridHelper/grid-radio-selection-column-mixin.js b/src/main/resources/META-INF/frontend/fcGridHelper/grid-radio-selection-column-mixin.js new file mode 100644 index 0000000..f040074 --- /dev/null +++ b/src/main/resources/META-INF/frontend/fcGridHelper/grid-radio-selection-column-mixin.js @@ -0,0 +1,118 @@ +/*- + * #%L + * Grid Helpers Add-on + * %% + * Copyright (C) 2022 - 2024 Flowing Code + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import { GridRadioSelectionColumnBaseMixin } from './grid-radio-selection-column-base-mixin.js'; + +/** + * @polymerMixin + * @mixes GridSelectionColumnBaseMixin + */ +export const GridRadioSelectionColumnMixin = (superClass) => + class extends GridRadioSelectionColumnBaseMixin(superClass) { + static get properties() { + return { + /** + * The previous state of activeItem. When activeItem turns to `null`, + * previousActiveItem will have an Object with just unselected activeItem + * @private + */ + __previousActiveItem: Object, + }; + } + + constructor() { + super(); + + this.__boundOnActiveItemChanged = this.__onActiveItemChanged.bind(this); + this.__boundOnSelectedItemsChanged = this.__onSelectedItemsChanged.bind(this); + } + + /** @protected */ + disconnectedCallback() { + this._grid.removeEventListener('active-item-changed', this.__boundOnActiveItemChanged); + this._grid.removeEventListener('selected-items-changed', this.__boundOnSelectedItemsChanged); + super.disconnectedCallback(); + } + + /** @protected */ + connectedCallback() { + super.connectedCallback(); + if (this._grid) { + this._grid.addEventListener('active-item-changed', this.__boundOnActiveItemChanged); + this._grid.addEventListener('selected-items-changed', this.__boundOnSelectedItemsChanged); + } + } + + /** + * Override a method from `GridSelectionColumnBaseMixin` to handle the user + * selecting an item. + * + * @param {Object} item the item to select + * @protected + * @override + */ + _selectItem(item) { + this._grid.selectItem(item); + } + + /** + * Override a method from `GridSelectionColumnBaseMixin` to handle the user + * deselecting an item. + * + * @param {Object} item the item to deselect + * @protected + * @override + */ + _deselectItem(item) { + this._grid.deselectItem(item); + } + + /** @private */ + __onActiveItemChanged(e) { + const activeItem = e.detail.value; + this.__previousSelectionCleared = false; + if (this.autoSelect && activeItem) { + this._selectItem(activeItem); + this.__previousActiveItem = activeItem; + } + } + + /** @private */ + __onSelectedItemsChanged(e) { + if(!this.__previousSelectionCleared && this.__previousActiveItem){ + this.__previousSelectionCleared = true; + this._deselectItem(this.__previousActiveItem); + } + } + + /** + * Override a method from `GridRadioSelectionColumnBaseMixin` to handle the user clicked on an item. + * + * @param {Object} item the clicked item + * @protected + * @override + */ + _onItemClicked(item) { + this.__previousSelectionCleared = false; + super._onItemClicked(item); + this.__previousActiveItem = item; + } + + }; diff --git a/src/main/resources/META-INF/frontend/fcGridHelper/grid-radio-selection-column.js b/src/main/resources/META-INF/frontend/fcGridHelper/grid-radio-selection-column.js new file mode 100644 index 0000000..8c9f349 --- /dev/null +++ b/src/main/resources/META-INF/frontend/fcGridHelper/grid-radio-selection-column.js @@ -0,0 +1,56 @@ +/*- + * #%L + * Grid Helpers Add-on + * %% + * Copyright (C) 2022 - 2024 Flowing Code + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import '@vaadin/radio-group/vaadin-radio-button.js'; +import { defineCustomElement } from '@vaadin/component-base/src/define.js'; +import { GridColumn } from './vaadin-grid-column.js'; +import { GridRadioSelectionColumnMixin } from './grid-radio-selection-column-mixin.js'; + +/** + * `` is a helper element for the `` + * that provides default renderers and functionality for item selection. + * + * #### Example: + * ```html + * + * + * + * + * ... + * ``` + * + * By default the selection column displays `` elements in the + * column cells. The radio button in the body rows toggle selection of the corresponding row item. + * + * __The default content can also be overridden__ + * + * @customElement + * @extends GridColumn + * @mixes GridSelectionColumnMixin + */ +class GridRadioSelectionColumn extends GridRadioSelectionColumnMixin(GridColumn) { + static get is() { + return 'grid-radio-selection-column'; + } +} + +defineCustomElement(GridRadioSelectionColumn); + +export { GridRadioSelectionColumn }; diff --git a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/GridHelpersDemoView.java b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/GridHelpersDemoView.java index d230a1b..4eea42e 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/GridHelpersDemoView.java +++ b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/GridHelpersDemoView.java @@ -52,5 +52,6 @@ public GridHelpersDemoView() { addDemo(CheckboxColumnDemo.class); addDemo(EmptyGridLabelDemo.class); addDemo(HeightByRowsDemo.class); + addDemo(GridRadioSelectionColumnDemo.class); } } diff --git a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/GridRadioSelectionColumnDemo.java b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/GridRadioSelectionColumnDemo.java new file mode 100644 index 0000000..a4bec82 --- /dev/null +++ b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/GridRadioSelectionColumnDemo.java @@ -0,0 +1,65 @@ +/*- + * #%L + * Grid Helpers Add-on + * %% + * Copyright (C) 2022 - 2024 Flowing Code + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +package com.flowingcode.vaadin.addons.gridhelpers; + +import com.flowingcode.vaadin.addons.demo.DemoSource; +import com.vaadin.flow.component.grid.Grid; +import com.vaadin.flow.component.grid.GridSingleSelectionModel; +import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.data.provider.DataProvider; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; + +@PageTitle("Radio Selection Column") +@DemoSource +@Route(value = "grid-helpers/radio-selection-column", layout = GridHelpersDemoView.class) +public class GridRadioSelectionColumnDemo extends VerticalLayout { + + Div selection = new Div(); + + public GridRadioSelectionColumnDemo() { + setSizeFull(); + + Grid grid = new Grid<>(); + LazyTestData data = new LazyTestData(); + grid.setItems(DataProvider.fromCallbacks( + query -> data.filter(query.getOffset(), query.getPageSize()), query -> data.count())); + + grid.addColumn(Person::getFirstName).setHeader("First name"); + grid.addColumn(Person::getLastName).setHeader("Last name"); + grid.addColumn(Person::getPhoneNumber).setHeader("Phone"); + + GridHelper.showRadioSelectionColumn(grid).setFrozen(true); + + grid.setSizeFull(); + ((GridSingleSelectionModel) grid.getSelectionModel()).setDeselectAllowed(false); + grid.asSingleSelect().addValueChangeListener(e -> { + if (e.getValue() != null) { + selection.setText( + "Selected row: " + e.getValue().getFirstName() + " " + e.getValue().getLastName()); + } + }); + + add(grid, selection); + } + +} diff --git a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/GridHelperElement.java b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/GridHelperElement.java index d513be0..e29043e 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/GridHelperElement.java +++ b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/GridHelperElement.java @@ -85,6 +85,14 @@ public TestBenchElement getSelectionCheckbox(int rowIndex) { return (TestBenchElement) elements.stream().findFirst().orElse(null); } + public TestBenchElement getSelectionRadioButton(int rowIndex) { + // assumes that Grid is in single-selection mode + TestBenchElement cell = getSlottedCell(getRow(rowIndex)); + List elements = cell.findElements(By.tagName("vaadin-radio-button")); + return (TestBenchElement) elements.stream().findFirst().orElse(null); + } + + private TestBenchElement getSlottedCell(WebElement e) { String slot = e.findElement(By.tagName("slot")).getAttribute("name"); return findElement(By.cssSelector(String.format("[slot='%s']", slot))); diff --git a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/GridRadioSelectionColumnIT.java b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/GridRadioSelectionColumnIT.java new file mode 100644 index 0000000..65a8842 --- /dev/null +++ b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/GridRadioSelectionColumnIT.java @@ -0,0 +1,134 @@ +/*- + * #%L + * Grid Helpers Add-on + * %% + * Copyright (C) 2022 - 2024 Flowing Code + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +package com.flowingcode.vaadin.addons.gridhelpers.it; + +import static java.time.temporal.ChronoUnit.SECONDS; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.empty; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import com.flowingcode.vaadin.testbench.rpc.HasRpcSupport; +import com.vaadin.flow.component.grid.testbench.GridElement; +import com.vaadin.testbench.TestBenchElement; +import java.time.Duration; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.support.ui.ExpectedConditions; +import org.openqa.selenium.support.ui.WebDriverWait; + +public class GridRadioSelectionColumnIT extends AbstractViewTest implements HasRpcSupport { + + IntegrationViewCallables $server = createCallableProxy(IntegrationViewCallables.class); + GridHelperElement grid; + + public GridRadioSelectionColumnIT() { + super("it"); + } + + @Override + public void setup() throws Exception { + super.setup(); + grid = new GridHelperElement($(GridElement.class).waitForFirst()); + } + + @Test + public void testRadioSelectionColumnShown() { + // assert that the first column is not the one with radio button + assertNull("the first column has radio buttons", grid.getSelectionRadioButton(0)); + + $server.showRadioSelectionColumn(); + + waitUntil(ExpectedConditions + .presenceOfElementLocated(By.tagName("grid-flow-radio-selection-column"))); + + // assert that the first column is the one with radio buttons + assertNotNull("the first column has not any radio buttons", grid.getSelectionRadioButton(0)); + } + + @Test + public void testShouldSelectRowOnClick() { + $server.showRadioSelectionColumn(); + + waitUntil(ExpectedConditions + .presenceOfElementLocated(By.tagName("grid-flow-radio-selection-column"))); + + assertThat($server.getSelectedRows(), empty()); + + grid.getCell(0, 1).click(); + assertThat($server.getSelectedRows(), contains(0)); + + grid.getCell(4, 1).click(); + assertThat($server.getSelectedRows(), contains(4)); + } + + @Test + public void testShouldSelectRowOnRadioButtonClick() { + $server.showRadioSelectionColumn(); + + waitUntil(ExpectedConditions + .presenceOfElementLocated(By.tagName("grid-flow-radio-selection-column"))); + + + assertThat($server.getSelectedRows(), empty()); + + TestBenchElement radioButton = grid.getSelectionRadioButton(0); + radioButton.click(); + assertThat($server.getSelectedRows(), contains(0)); + + + radioButton = grid.getSelectionRadioButton(4); + radioButton.click(); + assertThat($server.getSelectedRows(), contains(4)); + } + + @Test + public void testRadioSelectionColumnFrozen() { + $server.showRadioSelectionColumn(); + + waitUntil(ExpectedConditions + .presenceOfElementLocated(By.tagName("grid-flow-radio-selection-column"))); + + TestBenchElement selectionColElement = grid.$("grid-flow-radio-selection-column").first(); + + String frozen = "return arguments[0].frozen"; + + + new WebDriverWait(getDriver(), Duration.of(2, SECONDS)) + .until(ExpectedConditions.attributeContains(selectionColElement, "frozen", "false")); + + // assert that the selection column is not frozen by default + assertFalse("Selection column is frozen", (Boolean) executeScript(frozen, selectionColElement)); + + // make selection column frozen + selectionColElement.setProperty("frozen", true); + + new WebDriverWait(getDriver(), Duration.of(2, SECONDS)) + .until(ExpectedConditions.attributeContains(selectionColElement, "frozen", "true")); + + // assert that the selection column is now frozen + assertTrue("Selection column is not frozen", + (Boolean) executeScript(frozen, selectionColElement)); + } + +} diff --git a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/IntegrationView.java b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/IntegrationView.java index 28f8b85..e677455 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/IntegrationView.java +++ b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/IntegrationView.java @@ -20,6 +20,7 @@ package com.flowingcode.vaadin.addons.gridhelpers.it; import com.flowingcode.vaadin.addons.gridhelpers.GridHelper; +import com.flowingcode.vaadin.addons.gridhelpers.GridRadioSelectionColumn; import com.flowingcode.vaadin.addons.gridhelpers.Person; import com.flowingcode.vaadin.addons.gridhelpers.TestData; import com.flowingcode.vaadin.testbench.rpc.JsonArrayList; @@ -178,4 +179,9 @@ public void setHeaderVisible(boolean visible) { public void setFooterVisible(boolean visible) { grid.setFooterVisible(visible); } + + @Override + public void showRadioSelectionColumn() { + grid.showRadioSelectionColumn(); + } } diff --git a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/IntegrationViewCallables.java b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/IntegrationViewCallables.java index 0a938b1..ee8590c 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/IntegrationViewCallables.java +++ b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/it/IntegrationViewCallables.java @@ -59,4 +59,5 @@ public interface IntegrationViewCallables extends RmiCallable { void setFooterVisible(boolean visible); + void showRadioSelectionColumn(); } diff --git a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/test/GridHelperTest.java b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/test/GridHelperTest.java index 5a617d2..9dc31cc 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/test/GridHelperTest.java +++ b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/test/GridHelperTest.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import com.flowingcode.vaadin.addons.gridhelpers.GridHelper; @@ -190,4 +191,9 @@ public void testMenuToggleColumn() { assertTrue(GridHelper.isMenuToggleColumn(toggleColumn)); } + @Test + public void testShowRadioSelectionColumn() { + assertNotNull(grid.showRadioSelectionColumn()); + } + } diff --git a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/test/SerializationTest.java b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/test/SerializationTest.java index c4f76d6..e765697 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/test/SerializationTest.java +++ b/src/test/java/com/flowingcode/vaadin/addons/gridhelpers/test/SerializationTest.java @@ -48,6 +48,7 @@ public void testSerialization() throws ClassNotFoundException, IOException { try { Grid grid = new Grid<>(); GridHelper.setColumnToggleVisible(grid, false); + GridHelper.showRadioSelectionColumn(grid); testSerializationOf(grid); } catch (Exception e) { Assert.fail("Problem while testing serialization: " + e.getMessage());