From 37e488d86b0bc59bf085a64eda3e258a01c496f0 Mon Sep 17 00:00:00 2001 From: elmot Date: Mon, 12 Sep 2016 17:58:38 +0300 Subject: [PATCH] Create a CheckBoxGroup that replaces the multi select case of OptionGroup Change-Id: I250c60741bc65443b66498a8d0b17541edb77bf1 --- .../com/vaadin/client/ui/VCheckBoxGroup.java | 223 +++++++++++++++ .../client/ui/checkbox/CheckBoxConnector.java | 6 + .../optiongroup/CheckBoxGroupConnector.java | 83 ++++++ .../java/com/vaadin/ui/CheckBoxGroup.java | 262 ++++++++++++++++++ .../com/vaadin/ui/CheckBoxGroupBoVTest.java | 46 +++ .../optiongroup/CheckBoxGroupConstants.java | 28 ++ .../ui/optiongroup/CheckBoxGroupState.java | 35 +++ .../customelements/CheckBoxGroupElement.java | 98 +++++++ .../checkbox/CheckBoxGroupTestUI.java | 32 +++ .../checkboxgroup/CheckBoxGroupTest.java | 73 +++++ 10 files changed, 886 insertions(+) create mode 100644 client/src/main/java/com/vaadin/client/ui/VCheckBoxGroup.java create mode 100644 client/src/main/java/com/vaadin/client/ui/optiongroup/CheckBoxGroupConnector.java create mode 100644 server/src/main/java/com/vaadin/ui/CheckBoxGroup.java create mode 100644 server/src/test/java/com/vaadin/ui/CheckBoxGroupBoVTest.java create mode 100644 shared/src/main/java/com/vaadin/shared/ui/optiongroup/CheckBoxGroupConstants.java create mode 100644 shared/src/main/java/com/vaadin/shared/ui/optiongroup/CheckBoxGroupState.java create mode 100644 uitest-common/src/main/java/com/vaadin/testbench/customelements/CheckBoxGroupElement.java create mode 100644 uitest/src/main/java/com/vaadin/tests/components/checkbox/CheckBoxGroupTestUI.java create mode 100644 uitest/src/test/java/com/vaadin/tests/components/checkboxgroup/CheckBoxGroupTest.java diff --git a/client/src/main/java/com/vaadin/client/ui/VCheckBoxGroup.java b/client/src/main/java/com/vaadin/client/ui/VCheckBoxGroup.java new file mode 100644 index 0000000000..3b6c73950c --- /dev/null +++ b/client/src/main/java/com/vaadin/client/ui/VCheckBoxGroup.java @@ -0,0 +1,223 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * 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. + */ + +package com.vaadin.client.ui; + +import com.google.gwt.aria.client.Roles; +import com.google.gwt.event.dom.client.ChangeEvent; +import com.google.gwt.event.dom.client.ChangeHandler; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.FocusWidget; +import com.google.gwt.user.client.ui.Focusable; +import com.google.gwt.user.client.ui.HasEnabled; +import com.google.gwt.user.client.ui.Panel; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.client.ApplicationConnection; +import com.vaadin.client.WidgetUtil; +import com.vaadin.shared.Registration; +import com.vaadin.shared.ui.optiongroup.CheckBoxGroupConstants; +import elemental.json.JsonObject; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +import static com.vaadin.shared.ui.optiongroup.CheckBoxGroupConstants.JSONKEY_ITEM_DISABLED; + +/** + * The client-side widget for the {@code CheckBoxGroup} component. + * + * @author Vaadin Ltd. + * @since 8.0 + */ +public class VCheckBoxGroup extends Composite + implements Field, ClickHandler, ChangeHandler, + com.vaadin.client.Focusable, HasEnabled { + + public static final String CLASSNAME = "v-select-optiongroup"; + public static final String CLASSNAME_OPTION = "v-select-option"; + + private final Map optionsToItems; + + /** + * For internal use only. May be removed or replaced in the future. + */ + public ApplicationConnection client; + /** + * For internal use only. May be removed or replaced in the future. + */ + public JsonObject selected; //TODO replace with SelectionModel + /** + * Widget holding the different options (e.g. ListBox or Panel for radio + * buttons) (optional, fallbacks to container Panel) + *

+ * For internal use only. May be removed or replaced in the future. + */ + public Panel optionsContainer; + + private boolean htmlContentAllowed = false; + + private boolean enabled; + private boolean readonly; + private List> selectionChangeListeners; + + public VCheckBoxGroup() { + optionsContainer = new FlowPanel(); + initWidget(this.optionsContainer); + optionsContainer.setStyleName(CLASSNAME); + optionsToItems = new HashMap<>(); + selectionChangeListeners = new ArrayList<>(); + } + + /* + * Build all the options + */ + public void buildOptions(List items) { + /* + * In order to retain focus, we need to update values rather than + * recreate panel from scratch (#10451). However, the panel will be + * rebuilt (losing focus) if number of elements or their order is + * changed. + */ + + Roles.getRadiogroupRole().set(getElement()); + optionsContainer.clear(); + for (JsonObject item : items) { + String itemHtml = + item.getString(CheckBoxGroupConstants.JSONKEY_ITEM_VALUE); + if (!isHtmlContentAllowed()) { + itemHtml = WidgetUtil.escapeHTML(itemHtml); + } + VCheckBox checkBox = new VCheckBox(); + + String iconUrl = + item.getString(CheckBoxGroupConstants.JSONKEY_ITEM_ICON); + if (iconUrl != null && iconUrl.length() != 0) { + checkBox.icon = client.getIcon(iconUrl); + } + + checkBox.addStyleName(CLASSNAME_OPTION); + checkBox.addClickHandler(this); + checkBox.setHTML(itemHtml); + checkBox.setValue(true);//TODO selection model here + boolean optionEnabled = !item.getBoolean(JSONKEY_ITEM_DISABLED); + boolean enabled = optionEnabled && !isReadonly() && isEnabled(); + checkBox.setEnabled(enabled); + + optionsContainer.add(checkBox); + optionsToItems.put(checkBox, item); + } + } + + @Override + public void onClick(ClickEvent event) { + if (event.getSource() instanceof VCheckBox) { + VCheckBox source = (VCheckBox) event.getSource(); + if (!source.isEnabled()) { + // Click events on the text are received even though the + // checkbox is disabled + return; + } + + final boolean selected = source.getValue(); + JsonObject item = optionsToItems.get(source); //TODO SelectionModel + if (selected) { + this.selected = item; + } else { + this.selected = null; + } + } + } + + public void setTabIndex(int tabIndex) { + for (Widget anOptionsContainer : optionsContainer) { + FocusWidget widget = (FocusWidget) anOptionsContainer; + widget.setTabIndex(tabIndex); + } + } + + protected void updateEnabledState() { + boolean optionGroupEnabled = isEnabled() && !isReadonly(); + // sets options enabled according to the widget's enabled, + // readonly and each options own enabled + for (Map.Entry entry : optionsToItems + .entrySet()) { + VCheckBox checkBox = entry.getKey(); + JsonObject value = entry.getValue(); + Boolean isOptionEnabled = !value.getBoolean( + CheckBoxGroupConstants.JSONKEY_ITEM_DISABLED); + checkBox.setEnabled(optionGroupEnabled && isOptionEnabled); + } + } + + @Override + public void focus() { + Iterator iterator = optionsContainer.iterator(); + if (iterator.hasNext()) { + ((Focusable) iterator.next()).setFocus(true); + } + } + + public boolean isHtmlContentAllowed() { + return htmlContentAllowed; + } + + public void setHtmlContentAllowed(boolean htmlContentAllowed) { + this.htmlContentAllowed = htmlContentAllowed; + } + + @Override + public boolean isEnabled() { + return enabled; + } + + public boolean isReadonly() { + return readonly; + } + + @Override + public void onChange(ChangeEvent event) { + //TODO selectionModel + } + + public void setReadonly(boolean readonly) { + if (this.readonly != readonly) { + this.readonly = readonly; + updateEnabledState(); + } + } + + @Override + public void setEnabled(boolean enabled) { + if (this.enabled != enabled) { + this.enabled = enabled; + updateEnabledState(); + } + } + + public Registration addNotifyHandler( + Consumer selectionChanged) { + selectionChangeListeners.add(selectionChanged); + return (Registration) () -> selectionChangeListeners + .remove(selectionChanged); + } +} diff --git a/client/src/main/java/com/vaadin/client/ui/checkbox/CheckBoxConnector.java b/client/src/main/java/com/vaadin/client/ui/checkbox/CheckBoxConnector.java index 598280cf5c..3c36ffd4fe 100644 --- a/client/src/main/java/com/vaadin/client/ui/checkbox/CheckBoxConnector.java +++ b/client/src/main/java/com/vaadin/client/ui/checkbox/CheckBoxConnector.java @@ -36,6 +36,12 @@ import com.vaadin.shared.ui.checkbox.CheckBoxServerRpc; import com.vaadin.shared.ui.checkbox.CheckBoxState; import com.vaadin.ui.CheckBox; +/** + * The client-side connector for the {@code CheckBoxGroup} component. + * + * @author Vaadin Ltd. + * @since 8.0 + */ @Connect(CheckBox.class) public class CheckBoxConnector extends AbstractFieldConnector implements ClickHandler { diff --git a/client/src/main/java/com/vaadin/client/ui/optiongroup/CheckBoxGroupConnector.java b/client/src/main/java/com/vaadin/client/ui/optiongroup/CheckBoxGroupConnector.java new file mode 100644 index 0000000000..dbd531382d --- /dev/null +++ b/client/src/main/java/com/vaadin/client/ui/optiongroup/CheckBoxGroupConnector.java @@ -0,0 +1,83 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * 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. + */ + +package com.vaadin.client.ui.optiongroup; + +import java.util.ArrayList; +import java.util.List; + +import com.vaadin.client.communication.StateChangeEvent; +import com.vaadin.client.connectors.AbstractListingConnector; +import com.vaadin.client.data.DataSource; +import com.vaadin.client.ui.VCheckBoxGroup; +import com.vaadin.shared.Registration; +import com.vaadin.shared.data.selection.SelectionModel; +import com.vaadin.shared.ui.Connect; +import com.vaadin.shared.ui.optiongroup.CheckBoxGroupState; +import com.vaadin.ui.CheckBoxGroup; + +import elemental.json.JsonObject; + +@Connect(CheckBoxGroup.class) +public class CheckBoxGroupConnector + extends AbstractListingConnector> { + + private Registration selectionChangeRegistration; + + @Override + protected void init() { + super.init(); + selectionChangeRegistration = + getWidget().addNotifyHandler(this::selectionChanged); + } + + private void selectionChanged(JsonObject newSelection) { + getSelectionModel().select(newSelection); + } + + @Override + public void onStateChanged(StateChangeEvent stateChangeEvent) { + super.onStateChanged(stateChangeEvent); + getWidget().setTabIndex(getState().tabIndex); + getWidget().setReadonly(isReadOnly()); + getWidget().client = getConnection(); + } + + @Override + public void setDataSource(DataSource dataSource) { + dataSource.addDataChangeHandler(range -> updateOptionGroup()); + super.setDataSource(dataSource); + } + + private void updateOptionGroup() { + List items = new ArrayList<>(getDataSource().size()); + for (int i = 0; i < getDataSource().size(); ++i) { + JsonObject item = getDataSource().getRow(i); + items.add(item); + } + getWidget().buildOptions(items); + } + + @Override + public VCheckBoxGroup getWidget() { + return (VCheckBoxGroup) super.getWidget(); + } + + @Override + public CheckBoxGroupState getState() { + return (CheckBoxGroupState) super.getState(); + } +} diff --git a/server/src/main/java/com/vaadin/ui/CheckBoxGroup.java b/server/src/main/java/com/vaadin/ui/CheckBoxGroup.java new file mode 100644 index 0000000000..2ad72c5e2c --- /dev/null +++ b/server/src/main/java/com/vaadin/ui/CheckBoxGroup.java @@ -0,0 +1,262 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * 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. + */ + +package com.vaadin.ui; + +import com.vaadin.data.Listing; +import com.vaadin.server.Resource; +import com.vaadin.server.ResourceReference; +import com.vaadin.server.data.DataGenerator; +import com.vaadin.server.data.DataSource; +import com.vaadin.shared.data.selection.SelectionModel; +import com.vaadin.shared.ui.optiongroup.CheckBoxGroupConstants; +import com.vaadin.shared.ui.optiongroup.CheckBoxGroupState; +import elemental.json.JsonObject; + +import java.util.Collection; +import java.util.Collections; +import java.util.Objects; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Predicate; + +/** + * A group of Checkboxes. Individual checkboxes are made from items given to + * supplied by {@code Datasource}. Checkboxes my have captions and icons. + * + * @param + * item type + * @author Vaadin Ltd + * @since 8.0 + */ +public class CheckBoxGroup extends AbstractListing> { + + private Function itemIconProvider = item -> null; + + private Function itemCaptionProvider = String::valueOf; + + private Predicate itemEnabledProvider = item -> true; + + /** + * Constructs a new CheckBoxGroup with caption. + * + * @param caption + * caption text + * @see Listing#setDataSource(DataSource) + */ + public CheckBoxGroup(String caption) { + this(); + setCaption(caption); + } + + /** + * Constructs a new CheckBoxGroup with caption and DataSource. + * + * @param caption + * the caption text + * @param dataSource + * the data source, not null + * @see Listing#setDataSource(DataSource) + */ + public CheckBoxGroup(String caption, DataSource dataSource) { + this(caption); + setDataSource(dataSource); + } + + /** + * Constructs a new CheckBoxGroup with caption and DataSource containing + * given items. + * + * @param caption + * the caption text + * @param items + * the data items to use, not null + * @see Listing#setDataSource(DataSource) + */ + public CheckBoxGroup(String caption, Collection items) { + this(caption, DataSource.create(items)); + } + + /** + * Constructs a new CheckBoxGroup. + * + * @see Listing#setDataSource(DataSource) + */ + public CheckBoxGroup() { + //TODO Fix when MultiSelection is ready + // SingleSelection model = new SingleSelection<>(this); + // setSelectionModel(model); + // model.addSelectionListener(event -> beforeClientResponse(false)); + setSelectionModel(new SelectionModel.Multi() { + @Override + public void select(T item) { + + } + + @Override + public Set getSelectedItems() { + return Collections.emptySet(); + } + + @Override + public void deselect(T item) { + + } + + @Override + public void deselectAll() { + + } + + @Override + public boolean isSelected(T item) { + return false; + } + }); + addDataGenerator(new DataGenerator() { + @Override + public void generateData(T data, JsonObject jsonObject) { + jsonObject.put(CheckBoxGroupConstants.JSONKEY_ITEM_VALUE, + itemCaptionProvider.apply(data)); + Resource icon = itemIconProvider.apply(data); + if (icon != null) { + String iconUrl = ResourceReference + .create(icon, CheckBoxGroup.this, null).getURL(); + jsonObject.put(CheckBoxGroupConstants.JSONKEY_ITEM_ICON, + iconUrl); + } + if (!itemEnabledProvider.test(data)) { + jsonObject.put(CheckBoxGroupConstants.JSONKEY_ITEM_DISABLED, + true); + } + } + + @Override + public void destroyData(T data) { + } + }); + + } + + /** + * Sets whether html is allowed in the item captions. If set to true, the + * captions are passed to the browser as html and the developer is + * responsible for ensuring no harmful html is used. If set to false, the + * content is passed to the browser as plain text. + * + * @param htmlContentAllowed + * true if the captions are used as html, false if used as plain + * text + */ + public void setHtmlContentAllowed(boolean htmlContentAllowed) { + getState().htmlContentAllowed = htmlContentAllowed; + } + + /** + * Checks whether captions are interpreted as html or plain text. + * + * @return true if the captions are used as html, false if used as plain + * text + * @see #setHtmlContentAllowed(boolean) + */ + public boolean isHtmlContentAllowed() { + return getState(false).htmlContentAllowed; + } + + @Override + protected CheckBoxGroupState getState() { + return (CheckBoxGroupState) super.getState(); + } + + @Override + protected CheckBoxGroupState getState(boolean markAsDirty) { + return (CheckBoxGroupState) super.getState(markAsDirty); + } + + /** + * Returns the item icons provider. + * + * @return the icons provider for items + * @see #setItemIconProvider + */ + public Function getItemIconProvider() { + return itemIconProvider; + } + + /** + * Sets the item icon provider for this checkbox group. The icon provider + * is queried for each item to optionally display an icon next to + * the item caption. If the provider returns null for an item, no icon is + * displayed. The default provider always returns null (no icons). + * + * @param itemIconProvider + * icons provider, not null + */ + public void setItemIconProvider(Function itemIconProvider) { + Objects.nonNull(itemIconProvider); + this.itemIconProvider = itemIconProvider; + } + + /** + * Returns the item caption provider. + * + * @return the captions provider + * @see #setItemCaptionProvider + */ + public Function getItemCaptionProvider() { + return itemCaptionProvider; + } + + /** + * Sets the item caption provider for this checkbox group. The caption + * provider is queried for each item to optionally display an item + * textual representation. The default provider returns + * {@code String.valueOf(item)}. + * + * @param itemCaptionProvider + * the item caption provider, not null + */ + public void setItemCaptionProvider( + Function itemCaptionProvider) { + Objects.nonNull(itemCaptionProvider); + this.itemCaptionProvider = itemCaptionProvider; + } + + /** + * Returns the item enabled predicate. + * + * @return the item enabled predicate + * @see #setItemEnabledProvider + */ + public Predicate getItemEnabledProvider() { + return itemEnabledProvider; + } + + /** + * Sets the item enabled predicate for this checkbox group. The predicate + * is applied to each item to determine whether the item should be + * enabled (true) or disabled (false). Disabled items are displayed as + * grayed out and the user cannot select them. The default predicate + * always returns true (all the items are enabled). + * + * @param itemEnabledProvider + * the item enable predicate, not null + */ + public void setItemEnabledProvider(Predicate itemEnabledProvider) { + Objects.nonNull(itemEnabledProvider); + this.itemEnabledProvider = itemEnabledProvider; + } +} diff --git a/server/src/test/java/com/vaadin/ui/CheckBoxGroupBoVTest.java b/server/src/test/java/com/vaadin/ui/CheckBoxGroupBoVTest.java new file mode 100644 index 0000000000..e8594757d0 --- /dev/null +++ b/server/src/test/java/com/vaadin/ui/CheckBoxGroupBoVTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * 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. + */ +package com.vaadin.ui; + +import java.util.EnumSet; + +/** + * Option group test from Book of Vaadin + * + * @author Vaadin Ltd + * @since 8.0 + */ +public class CheckBoxGroupBoVTest +{ + public enum Status { + STATE_A, + STATE_B, + STATE_C, + STATE_D; + + public String getCaption() { + return "** " + toString(); + } + } + + + public void createOptionGroup() { + CheckBoxGroup s = new CheckBoxGroup<>(); + s.setItems(EnumSet.allOf(Status.class)); + s.setItemCaptionProvider(Status::getCaption); + } + +} diff --git a/shared/src/main/java/com/vaadin/shared/ui/optiongroup/CheckBoxGroupConstants.java b/shared/src/main/java/com/vaadin/shared/ui/optiongroup/CheckBoxGroupConstants.java new file mode 100644 index 0000000000..2747dd4c99 --- /dev/null +++ b/shared/src/main/java/com/vaadin/shared/ui/optiongroup/CheckBoxGroupConstants.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * 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. + */ +package com.vaadin.shared.ui.optiongroup; + +import java.io.Serializable; + +public class CheckBoxGroupConstants implements Serializable { + public static final String JSONKEY_ITEM_DISABLED = "d"; + + public static final String JSONKEY_ITEM_ICON = "i"; + + public static final String JSONKEY_ITEM_VALUE = "v"; + + public static final String JSONKEY_ITEM_KEY = "k"; +} diff --git a/shared/src/main/java/com/vaadin/shared/ui/optiongroup/CheckBoxGroupState.java b/shared/src/main/java/com/vaadin/shared/ui/optiongroup/CheckBoxGroupState.java new file mode 100644 index 0000000000..2decfdd49c --- /dev/null +++ b/shared/src/main/java/com/vaadin/shared/ui/optiongroup/CheckBoxGroupState.java @@ -0,0 +1,35 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * 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. + */ +package com.vaadin.shared.ui.optiongroup; + +import com.vaadin.shared.annotations.DelegateToWidget; +import com.vaadin.shared.AbstractFieldState; + +/** + * Shared state for the CheckBoxGroup component. + * + * @author Vaadin Ltd. + * @since 8.0 + */ +public class CheckBoxGroupState extends AbstractFieldState { + + { + primaryStyleName = "v-select-optiongroup"; + } + + @DelegateToWidget + public boolean htmlContentAllowed = false; +} diff --git a/uitest-common/src/main/java/com/vaadin/testbench/customelements/CheckBoxGroupElement.java b/uitest-common/src/main/java/com/vaadin/testbench/customelements/CheckBoxGroupElement.java new file mode 100644 index 0000000000..b070ece852 --- /dev/null +++ b/uitest-common/src/main/java/com/vaadin/testbench/customelements/CheckBoxGroupElement.java @@ -0,0 +1,98 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * 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. + */ +package com.vaadin.testbench.customelements; + +import java.util.ArrayList; +import java.util.List; + +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.By; +import com.vaadin.testbench.elements.AbstractSelectElement; +import com.vaadin.testbench.elementsbase.ServerClass; + +/** + * TestBench element supporting CheckBoxGroup + * + * @author Vaadin Ltd + */ + +@ServerClass("com.vaadin.ui.CheckBoxGroup") +public class CheckBoxGroupElement extends AbstractSelectElement { + private static org.openqa.selenium.By byButtonSpan = + By.className("v-select-option"); + private static org.openqa.selenium.By byLabel = By.tagName("label"); + private static org.openqa.selenium.By byInput = By.tagName("input"); + + public List getOptions() { + List optionTexts = new ArrayList(); + List options = findElements(byButtonSpan); + for (WebElement option : options) { + optionTexts.add(option.findElement(byLabel).getText()); + } + return optionTexts; + } + + public void selectByText(String text) throws ReadOnlyException { + if (isReadOnly()) { + throw new ReadOnlyException(); + } + List options = findElements(byButtonSpan); + for (WebElement option : options) { + if (text.equals(option.findElement(byLabel).getText())) { + option.findElement(byInput).click(); + } + } + } + + /** + * Return list of the selected options in the checkbox group + * + * @return list of the selected options in the checkbox group + */ + public List getSelection() { + List values = new ArrayList<>(); + List options = findElements(byButtonSpan); + for (WebElement option : options) { + WebElement checkedItem; + checkedItem = option.findElement(By.tagName("input")); + String checked = checkedItem.getAttribute("checked"); + if (checked != null && + checkedItem.getAttribute("checked").equals("true")) { + values.add(option.findElement(By.tagName("label")).getText()); + } + } + return values; + } + + /** + * Select option in the checkbox group with the specified value + * + * @param chars + * value of the option in the checkbox group which will be selected + */ + public void selectOption(CharSequence chars) throws ReadOnlyException { + selectByText((String) chars); + } + + @Override + public void clear() { + throw new UnsupportedOperationException( + "Clear operation is not supported for CheckBoxGroup." + + " This operation has no effect on the element."); + } +} + diff --git a/uitest/src/main/java/com/vaadin/tests/components/checkbox/CheckBoxGroupTestUI.java b/uitest/src/main/java/com/vaadin/tests/components/checkbox/CheckBoxGroupTestUI.java new file mode 100644 index 0000000000..343faf3930 --- /dev/null +++ b/uitest/src/main/java/com/vaadin/tests/components/checkbox/CheckBoxGroupTestUI.java @@ -0,0 +1,32 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * 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. + */ +package com.vaadin.tests.components.checkbox; + +import com.vaadin.tests.components.abstractlisting.AbstractListingTestUI; +import com.vaadin.ui.CheckBoxGroup; + +/** + * Test UI for CheckBoxGroup component + * + * @author Vaadin Ltd + */ +public class CheckBoxGroupTestUI + extends AbstractListingTestUI> { + @Override + protected Class> getTestClass() { + return (Class) CheckBoxGroup.class; + } +} diff --git a/uitest/src/test/java/com/vaadin/tests/components/checkboxgroup/CheckBoxGroupTest.java b/uitest/src/test/java/com/vaadin/tests/components/checkboxgroup/CheckBoxGroupTest.java new file mode 100644 index 0000000000..9a3c2a656c --- /dev/null +++ b/uitest/src/test/java/com/vaadin/tests/components/checkboxgroup/CheckBoxGroupTest.java @@ -0,0 +1,73 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * 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. + */ +package com.vaadin.tests.components.checkboxgroup; + +import com.vaadin.testbench.customelements.CheckBoxGroupElement; +import com.vaadin.tests.components.checkbox.CheckBoxGroupTestUI; +import com.vaadin.tests.tb3.MultiBrowserTest; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Test for CheckBoxGroup + * + * @author Vaadin Ltd + * @since 8.0 + */ +public class CheckBoxGroupTest extends MultiBrowserTest { + + @Before + public void setUp() throws Exception { + openTestURL(); + } + + @Test + public void initialLoad_containsCorrectItems() { + assertItems(20); + } + + @Test + public void initialItems_reduceItemCount_containsCorrectItems() { + selectMenuPath("Component", "Data source", "Items", "5"); + assertItems(5); + } + + @Test + public void initialItems_increaseItemCount_containsCorrectItems() { + selectMenuPath("Component", "Data source", "Items", "100"); + assertItems(100); + } + + @Override + protected Class getUIClass() { + return CheckBoxGroupTestUI.class; + } + + protected CheckBoxGroupElement getSelect() { + return $(CheckBoxGroupElement.class).first(); + } + + protected void assertItems(int count) { + int i = 0; + for (String text : getSelect().getOptions()) { + assertEquals("Item " + i, text); + i++; + } + assertEquals("Number of items", count, i); + } +} -- 2.39.5