diff options
author | Knoobie <Knoobie@gmx.de> | 2018-12-18 14:29:59 +0100 |
---|---|---|
committer | Sun Zhe <31067185+ZheSun88@users.noreply.github.com> | 2018-12-18 15:29:59 +0200 |
commit | 353ba29cfdefddb032122cbeae5f02f6d9de76ba (patch) | |
tree | 05ee1da595faaab05976e9ab339472799648135b | |
parent | 9c9c962549eb04adac87b0cfe26d24b17843fb6a (diff) | |
download | vaadin-framework-353ba29cfdefddb032122cbeae5f02f6d9de76ba.tar.gz vaadin-framework-353ba29cfdefddb032122cbeae5f02f6d9de76ba.zip |
Checkbox allow customizing of input and label classNames. (#11372)
* add client side integration for custom styles for checkbox.label and checkbox.input
* add server side integration for checkbox element styling
* add server side tests
* add client side test
9 files changed, 636 insertions, 4 deletions
diff --git a/client/src/main/java/com/vaadin/client/ui/VCheckBox.java b/client/src/main/java/com/vaadin/client/ui/VCheckBox.java index 2c2df0a27e..f535086d94 100644 --- a/client/src/main/java/com/vaadin/client/ui/VCheckBox.java +++ b/client/src/main/java/com/vaadin/client/ui/VCheckBox.java @@ -84,19 +84,32 @@ public class VCheckBox extends com.google.gwt.user.client.ui.CheckBox * * @return Element of the CheckBox itself */ - private Element getCheckBoxElement() { + public Element getInputElement() { + // public to allow CheckBoxState to access it. // FIXME: Would love to use a better way to access the checkbox element return getElement().getFirstChildElement(); } + /** + * Gives access to the label element. + * + * @return Element of the Label itself + * @since + */ + public Element getLabelElement() { + // public to allow CheckBoxState to access it. + // FIXME: Would love to use a better way to access the label element + return getInputElement().getNextSiblingElement(); + } + @Override public void setAriaRequired(boolean required) { - AriaHelper.handleInputRequired(getCheckBoxElement(), required); + AriaHelper.handleInputRequired(getInputElement(), required); } @Override public void setAriaInvalid(boolean invalid) { - AriaHelper.handleInputInvalid(getCheckBoxElement(), invalid); + AriaHelper.handleInputInvalid(getInputElement(), invalid); } @Override 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 e9582d1755..df9b9b11cf 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 @@ -15,6 +15,8 @@ */ package com.vaadin.client.ui.checkbox; +import com.google.gwt.core.client.JsArrayString; +import com.google.gwt.dom.client.Element; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.DOM; @@ -30,11 +32,14 @@ import com.vaadin.client.ui.Icon; import com.vaadin.client.ui.VCheckBox; import com.vaadin.shared.EventId; import com.vaadin.shared.MouseEventDetails; +import com.vaadin.shared.ui.ComponentStateUtil; import com.vaadin.shared.ui.Connect; import com.vaadin.shared.ui.checkbox.CheckBoxServerRpc; import com.vaadin.shared.ui.checkbox.CheckBoxState; import com.vaadin.ui.CheckBox; +import java.util.List; + /** * The client-side connector for the {@code CheckBoxGroup} component. * @@ -45,6 +50,22 @@ import com.vaadin.ui.CheckBox; public class CheckBoxConnector extends AbstractFieldConnector implements ClickHandler { + /** + * The style names from getState().inputStyles which are currently applied + * to the checkbox. + * + * @since + */ + private JsArrayString inputStyleNames = JsArrayString.createArray().cast(); + + /** + * The style names from getState().labelStyles which are currently applied + * to the checkbox. + * + * @since + */ + private JsArrayString labelStyleNames = JsArrayString.createArray().cast(); + @Override public boolean delegateCaptionHandling() { return false; @@ -88,6 +109,10 @@ public class CheckBoxConnector extends AbstractFieldConnector VCaption.setCaptionText(getWidget(), getState()); getWidget().setValue(getState().checked); + + // Set styles for input and label + updateStyles(getWidget().getInputElement(), inputStyleNames, getState().inputStyles); + updateStyles(getWidget().getLabelElement(), labelStyleNames, getState().labelStyles); } @Override @@ -134,4 +159,21 @@ public class CheckBoxConnector extends AbstractFieldConnector contextEventSunk = true; } } + + private void updateStyles(Element clientElement, JsArrayString clientSideStyles, List<String> serverSideStyes) { + // Remove all old stylenames + for (int i = 0; i < clientSideStyles.length(); i++) { + clientElement.removeClassName(clientSideStyles.get(i)); + } + clientSideStyles.setLength(0); + + if (ComponentStateUtil.hasStyles(serverSideStyes)) { + // add new style names + for (String newStyle : serverSideStyes) { + clientElement.addClassName(newStyle); + clientSideStyles.push(newStyle); + } + + } + } } diff --git a/server/src/main/java/com/vaadin/ui/CheckBox.java b/server/src/main/java/com/vaadin/ui/CheckBox.java index 30ec0487b2..c0e259f330 100644 --- a/server/src/main/java/com/vaadin/ui/CheckBox.java +++ b/server/src/main/java/com/vaadin/ui/CheckBox.java @@ -16,8 +16,12 @@ package com.vaadin.ui; +import java.util.ArrayList; import java.util.Collection; +import java.util.Iterator; +import java.util.List; import java.util.Objects; +import java.util.StringTokenizer; import org.jsoup.nodes.Attributes; import org.jsoup.nodes.Element; @@ -30,6 +34,7 @@ import com.vaadin.event.FieldEvents.FocusEvent; import com.vaadin.event.FieldEvents.FocusListener; import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.Registration; +import com.vaadin.shared.ui.ComponentStateUtil; import com.vaadin.shared.ui.checkbox.CheckBoxServerRpc; import com.vaadin.shared.ui.checkbox.CheckBoxState; import com.vaadin.ui.declarative.DesignAttributeHandler; @@ -64,6 +69,175 @@ public class CheckBox extends AbstractField<Boolean> } }; + private CheckBoxInputElement checkBoxInputElement = null; + private CheckBoxLabelElement checkBoxLabelElement = null; + + /** + * The inner input element of the CheckBox. + */ + public static class CheckBoxInputElement implements HasStyleNames { + + private final CheckBox checkBox; + + private CheckBoxInputElement(CheckBox checkBox){ + this.checkBox = checkBox; + } + + @Override + // Implementation copied from AbstractComponent + public String getStyleName() { + // replaced String with StringBuilder + StringBuilder s = new StringBuilder(); + if (ComponentStateUtil.hasStyles(checkBox.getState(false).inputStyles)) { + for (final Iterator<String> it = checkBox.getState(false).inputStyles + .iterator(); it.hasNext();) { + s.append(it.next()); + if (it.hasNext()) { + s.append(" "); + } + } + } + return s.toString(); + } + + @Override + // Implementation copied from AbstractComponent + public void setStyleName(String style) { + if (style == null || style.isEmpty()) { + checkBox.getState().inputStyles = null; + return; + } + if (checkBox.getState().inputStyles == null) { + checkBox.getState().inputStyles = new ArrayList<>(); + } + List<String> styles = checkBox.getState().inputStyles; + styles.clear(); + StringTokenizer tokenizer = new StringTokenizer(style, " "); + while (tokenizer.hasMoreTokens()) { + styles.add(tokenizer.nextToken()); + } + } + + @Override + // Implementation copied from AbstractComponent + public void addStyleName(String style) { + if (style == null || style.isEmpty()) { + return; + } + if (checkBox.getState().inputStyles != null && checkBox.getState().inputStyles.contains(style)) { + return; + } + if (style.contains(" ")) { + // Split space separated style names and add them one by one. + StringTokenizer tokenizer = new StringTokenizer(style, " "); + while (tokenizer.hasMoreTokens()) { + addStyleName(tokenizer.nextToken()); + } + return; + } + + if (checkBox.getState().inputStyles == null) { + checkBox.getState().inputStyles = new ArrayList<>(); + } + List<String> styles = checkBox.getState().inputStyles; + styles.add(style); + } + + @Override + // Implementation copied from AbstractComponent + public void removeStyleName(String style) { + if (ComponentStateUtil.hasStyles(checkBox.getState().inputStyles)) { + StringTokenizer tokenizer = new StringTokenizer(style, " "); + while (tokenizer.hasMoreTokens()) { + checkBox.getState().inputStyles.remove(tokenizer.nextToken()); + } + } + } + } + + /** + * The inner label element of the CheckBox. + */ + public static class CheckBoxLabelElement implements HasStyleNames { + + private final CheckBox checkBox; + + private CheckBoxLabelElement(CheckBox checkBox){ + this.checkBox = checkBox; + } + + @Override + // Implementation copied from AbstractComponent + public String getStyleName() { + // replaced String with StringBuilder + StringBuilder s = new StringBuilder(); + if (ComponentStateUtil.hasStyles(checkBox.getState(false).labelStyles)) { + for (final Iterator<String> it = checkBox.getState(false).labelStyles + .iterator(); it.hasNext();) { + s.append(it.next()); + if (it.hasNext()) { + s.append(" "); + } + } + } + return s.toString(); + } + + @Override + // Implementation copied from AbstractComponent + public void setStyleName(String style) { + if (style == null || style.isEmpty()) { + checkBox.getState().labelStyles = null; + return; + } + if (checkBox.getState().labelStyles == null) { + checkBox.getState().labelStyles = new ArrayList<>(); + } + List<String> styles = checkBox.getState().labelStyles; + styles.clear(); + StringTokenizer tokenizer = new StringTokenizer(style, " "); + while (tokenizer.hasMoreTokens()) { + styles.add(tokenizer.nextToken()); + } + } + + @Override + // Implementation copied from AbstractComponent + public void addStyleName(String style) { + if (style == null || style.isEmpty()) { + return; + } + if (checkBox.getState().labelStyles != null && checkBox.getState().labelStyles.contains(style)) { + return; + } + if (style.contains(" ")) { + // Split space separated style names and add them one by one. + StringTokenizer tokenizer = new StringTokenizer(style, " "); + while (tokenizer.hasMoreTokens()) { + addStyleName(tokenizer.nextToken()); + } + return; + } + + if (checkBox.getState().labelStyles == null) { + checkBox.getState().labelStyles = new ArrayList<>(); + } + List<String> styles = checkBox.getState().labelStyles; + styles.add(style); + } + + @Override + // Implementation copied from AbstractComponent + public void removeStyleName(String style) { + if (ComponentStateUtil.hasStyles(checkBox.getState().labelStyles)) { + StringTokenizer tokenizer = new StringTokenizer(style, " "); + while (tokenizer.hasMoreTokens()) { + checkBox.getState().labelStyles.remove(tokenizer.nextToken()); + } + } + } + } + /** * Creates a new checkbox. */ @@ -211,4 +385,31 @@ public class CheckBox extends AbstractField<Boolean> def.getValue(), Boolean.class, designContext); } + /** + * Returns the {@link CheckBoxInputElement} element to manipulate + * the style name of the {@code input} element of the {@link CheckBox}. + * + * @since + * @return the current {@link CheckBoxInputElement}, not {@code null}. + */ + public CheckBoxInputElement getInputElement() { + if(checkBoxInputElement == null) { + checkBoxInputElement = new CheckBoxInputElement(this); + } + return checkBoxInputElement; + } + + /** + * Returns the {@link CheckBoxLabelElement} element to manipulate + * the style name of the {@code label} element of the {@link CheckBox}. + * + * @since + * @return the current {@link CheckBoxLabelElement}, not {@code null}. + */ + public CheckBoxLabelElement getLabelElement() { + if(checkBoxLabelElement == null) { + checkBoxLabelElement = new CheckBoxLabelElement(this); + } + return checkBoxLabelElement; + } } diff --git a/server/src/main/java/com/vaadin/ui/HasStyleNames.java b/server/src/main/java/com/vaadin/ui/HasStyleNames.java new file mode 100644 index 0000000000..953711b1e6 --- /dev/null +++ b/server/src/main/java/com/vaadin/ui/HasStyleNames.java @@ -0,0 +1,179 @@ +/* + * Copyright 2000-2018 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.io.Serializable; + +/** + * Implemented by components which support style names. + * + * <p> + * Each style name will occur only once as specified and it is not + * prefixed with the style name of the component. + * </p> + * + * @since + */ +public interface HasStyleNames extends Serializable { + + /** + * Gets all user-defined CSS style names of a component. If the component + * has multiple style names defined, the return string is a space-separated + * list of style names. Built-in style names defined in Vaadin or GWT are + * not returned. + * + * <p> + * The style names are returned only in the basic form in which they were + * added. + * </p> + * + * @since + * @return the style name or a space-separated list of user-defined style + * names of the component + * @see #setStyleName(String) + * @see #addStyleName(String) + * @see #removeStyleName(String) + */ + String getStyleName(); + + /** + * Sets one or more user-defined style names of the component, replacing any + * previous user-defined styles. Multiple styles can be specified as a + * space-separated list of style names. The style names must be valid CSS + * class names. + * + * <p> + * It is normally a good practice to use {@link #addStyleName(String) + * addStyleName()} rather than this setter, as different software + * abstraction layers can then add their own styles without accidentally + * removing those defined in other layers. + * </p> + * + * @since + * @param style + * the new style or styles of the component as a space-separated + * list + * @see #getStyleName() + * @see #addStyleName(String) + * @see #removeStyleName(String) + */ + void setStyleName(String style); + + /** + * Adds or removes a style name. Multiple styles can be specified as a + * space-separated list of style names. + * + * If the {@code add} parameter is true, the style name is added to the + * component. If the {@code add} parameter is false, the style name is + * removed from the component. + * <p> + * Functionally this is equivalent to using {@link #addStyleName(String)} or + * {@link #removeStyleName(String)} + * + * @since + * @param style + * the style name to be added or removed + * @param add + * <code>true</code> to add the given style, <code>false</code> + * to remove it + * @see #addStyleName(String) + * @see #removeStyleName(String) + */ + default void setStyleName(String style, boolean add) { + if (add) { + addStyleName(style); + } else { + removeStyleName(style); + } + } + + /** + * Adds one or more style names to this component. Multiple styles can be + * specified as a space-separated list of style names. The style name will + * be rendered as a HTML class name, which can be used in a CSS definition. + * + * + * @since + * @param style + * the new style to be added to the component + * @see #getStyleName() + * @see #setStyleName(String) + * @see #removeStyleName(String) + */ + void addStyleName(String style); + + /** + * Adds one or more style names to this component by using one or multiple + * parameters. + * + * @since + * @param styles + * the style name or style names to be added to the component + * @see #addStyleName(String) + * @see #setStyleName(String) + * @see #removeStyleName(String) + */ + default void addStyleNames(String... styles) { + for (String style : styles) { + addStyleName(style); + } + } + + /** + * Removes one or more style names from component. Multiple styles can be + * specified as a space-separated list of style names. + * + * <p> + * The parameter must be a valid CSS style name. Only user-defined style + * names added with {@link #addStyleName(String) addStyleName()} or + * {@link #setStyleName(String) setStyleName()} can be removed; built-in + * style names defined in Vaadin or GWT can not be removed. + * </p> + * + * @since + * @param style + * the style name or style names to be removed + * @see #getStyleName() + * @see #setStyleName(String) + * @see #addStyleName(String) + */ + void removeStyleName(String style); + + /** + * Removes one or more style names from component. Multiple styles can be + * specified by using multiple parameters. + * + * <p> + * The parameter must be a valid CSS style name. Only user-defined style + * names added with {@link #addStyleName(String) addStyleName()} or + * {@link #setStyleName(String) setStyleName()} can be removed; built-in + * style names defined in Vaadin or GWT can not be removed. + * </p> + * + * @since + * @param styles + * the style name or style names to be removed + * @see #removeStyleName(String) + * @see #setStyleName(String) + * @see #addStyleName(String) + */ + default void removeStyleNames(String... styles) { + for (String style : styles) { + removeStyleName(style); + } + } + +} diff --git a/server/src/test/java/com/vaadin/ui/CheckBoxTest.java b/server/src/test/java/com/vaadin/ui/CheckBoxTest.java index 042bc07482..0fbd6fa694 100644 --- a/server/src/test/java/com/vaadin/ui/CheckBoxTest.java +++ b/server/src/test/java/com/vaadin/ui/CheckBoxTest.java @@ -1,10 +1,13 @@ package com.vaadin.ui; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.util.concurrent.atomic.AtomicBoolean; +import org.junit.Ignore; import org.junit.Test; import com.vaadin.server.ServerRpcManager; @@ -68,4 +71,108 @@ public class CheckBoxTest { cb.setValue(null); } + @Test + public void getComboBoxInput() { + CheckBox cb = new CheckBox(); + assertNotNull("getInputElement should always return a element", cb.getInputElement()); + assertHasStyleNames(cb.getInputElement()); + } + + @Test + public void getCheckBoxLabel() { + CheckBox cb = new CheckBox(); + assertNotNull("getLabelElement should always return a element", cb.getLabelElement()); + assertHasStyleNames(cb.getLabelElement()); + } + + @Test + @Ignore("Component#setStyleName(null, false) should not throw a NPE") + public void setStyleName_null_false_throws_NPE() { + // FIXME? - Currently it throws a NPE like the implementation in Component.java + // waiting for other ticket that fixes the behaviour in Component.java before + CheckBox cb = new CheckBox(); + cb.getLabelElement().addStyleName("first"); + cb.getLabelElement().setStyleName(null, false); + assertEquals("Removing a null style should be ignored", + "first", cb.getLabelElement().getStyleName()); + } + + private void assertHasStyleNames(HasStyleNames hasStyleNames) { + assertEquals("Given element should not have a default style name", + "", hasStyleNames.getStyleName()); + + hasStyleNames.addStyleName("first"); + assertEquals("first", hasStyleNames.getStyleName()); + + hasStyleNames.addStyleName("first"); + assertEquals("Adding two times the same style should be ignored", + "first", hasStyleNames.getStyleName()); + + hasStyleNames.addStyleName(null); + assertEquals("Adding null as style should be ignored", + "first", hasStyleNames.getStyleName()); + + hasStyleNames.addStyleName(""); + assertEquals("Adding an empty string as style should be ignored", + "first", hasStyleNames.getStyleName()); + + hasStyleNames.addStyleName("second"); + assertEquals("first second", hasStyleNames.getStyleName()); + + hasStyleNames.removeStyleName("second"); + assertEquals("first", hasStyleNames.getStyleName()); + + hasStyleNames.addStyleName("second third fourth"); + assertEquals("first second third fourth", hasStyleNames.getStyleName()); + + hasStyleNames.removeStyleName("third fourth"); + assertEquals("first second", hasStyleNames.getStyleName()); + + hasStyleNames.addStyleNames("third", "fourth"); + assertEquals("first second third fourth", hasStyleNames.getStyleName()); + + hasStyleNames.removeStyleNames("second", "fourth"); + assertEquals("first third", hasStyleNames.getStyleName()); + + hasStyleNames.setStyleName(null); + assertEquals("Setting null as style should reset them", + "", hasStyleNames.getStyleName()); + + hasStyleNames.setStyleName("set-style"); + assertEquals("set-style", hasStyleNames.getStyleName()); + + hasStyleNames.setStyleName(""); + assertEquals("Setting an empty string as style should reset them", + "", hasStyleNames.getStyleName()); + + hasStyleNames.setStyleName("set-style multiple values"); + assertEquals("set-style multiple values", hasStyleNames.getStyleName()); + + hasStyleNames.setStyleName("set-style", false); + assertEquals("multiple values", hasStyleNames.getStyleName()); + + hasStyleNames.setStyleName("", false); + assertEquals("Removing an empty style should be ignored", + "multiple values", hasStyleNames.getStyleName()); + + hasStyleNames.setStyleName("", true); + assertEquals("Adding an empty style should be ignored", + "multiple values", hasStyleNames.getStyleName()); + + hasStyleNames.setStyleName(null, true); + assertEquals("Adding a null style should be ignored", + "multiple values", hasStyleNames.getStyleName()); + + hasStyleNames.setStyleName("multiple values", false); + assertEquals("Removing all set style names should result in an empty style name", + "", hasStyleNames.getStyleName()); + + hasStyleNames.setStyleName("set-style", true); + assertEquals("set-style", hasStyleNames.getStyleName()); + + hasStyleNames.setStyleName("multiple values", true); + assertEquals("set-style multiple values", hasStyleNames.getStyleName()); + + } + } diff --git a/shared/src/main/java/com/vaadin/shared/ui/ComponentStateUtil.java b/shared/src/main/java/com/vaadin/shared/ui/ComponentStateUtil.java index 494af9151d..3daa91d436 100644 --- a/shared/src/main/java/com/vaadin/shared/ui/ComponentStateUtil.java +++ b/shared/src/main/java/com/vaadin/shared/ui/ComponentStateUtil.java @@ -17,6 +17,7 @@ package com.vaadin.shared.ui; import java.io.Serializable; import java.util.HashSet; +import java.util.List; import com.vaadin.shared.AbstractComponentState; import com.vaadin.shared.Registration; @@ -42,7 +43,11 @@ public final class ComponentStateUtil implements Serializable { } public static final boolean hasStyles(AbstractComponentState state) { - return state.styles != null && !state.styles.isEmpty(); + return hasStyles(state.styles); + } + + public static final boolean hasStyles(List<String> styles) { + return styles != null && !styles.isEmpty(); } public static final boolean isRelativeWidth(AbstractComponentState state) { diff --git a/shared/src/main/java/com/vaadin/shared/ui/checkbox/CheckBoxState.java b/shared/src/main/java/com/vaadin/shared/ui/checkbox/CheckBoxState.java index c3e4c29c83..2a35a23726 100644 --- a/shared/src/main/java/com/vaadin/shared/ui/checkbox/CheckBoxState.java +++ b/shared/src/main/java/com/vaadin/shared/ui/checkbox/CheckBoxState.java @@ -17,10 +17,14 @@ package com.vaadin.shared.ui.checkbox; import com.vaadin.shared.AbstractFieldState; +import java.util.List; + public class CheckBoxState extends AbstractFieldState { { primaryStyleName = "v-checkbox"; } public boolean checked = false; + public List<String> inputStyles = null; + public List<String> labelStyles = null; } diff --git a/uitest/src/main/java/com/vaadin/tests/components/checkbox/CheckboxLabelInputElement.java b/uitest/src/main/java/com/vaadin/tests/components/checkbox/CheckboxLabelInputElement.java new file mode 100644 index 0000000000..248f214d1b --- /dev/null +++ b/uitest/src/main/java/com/vaadin/tests/components/checkbox/CheckboxLabelInputElement.java @@ -0,0 +1,33 @@ +package com.vaadin.tests.components.checkbox; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUIWithLog; +import com.vaadin.ui.CheckBox; + +public class CheckboxLabelInputElement extends AbstractTestUIWithLog { + + @Override + protected void setup(VaadinRequest request) { + final CheckBox cb = new CheckBox("Test custom style names for inner elements", true); + cb.getInputElement().addStyleName("my-input-class"); + cb.getLabelElement().addStyleName("my-label-class"); + + addComponent(cb); + + addButton("add-style", e -> { + cb.getInputElement().addStyleName("later-applied-input-class"); + cb.getLabelElement().addStyleName("later-applied-label-class"); + }); + + addButton("remove-style", e -> { + cb.getInputElement().removeStyleName("my-input-class"); + cb.getLabelElement().removeStyleName("my-label-class"); + }); + + addButton("remove-style-2", e -> { + cb.getInputElement().removeStyleName("later-applied-input-class"); + cb.getLabelElement().removeStyleName("later-applied-label-class"); + }); + } + +} diff --git a/uitest/src/test/java/com/vaadin/tests/components/checkbox/CheckboxLabelInputElementTest.java b/uitest/src/test/java/com/vaadin/tests/components/checkbox/CheckboxLabelInputElementTest.java new file mode 100644 index 0000000000..16ac7ee1fc --- /dev/null +++ b/uitest/src/test/java/com/vaadin/tests/components/checkbox/CheckboxLabelInputElementTest.java @@ -0,0 +1,48 @@ +package com.vaadin.tests.components.checkbox; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.elements.CheckBoxElement; +import com.vaadin.tests.tb3.MultiBrowserTest; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +public class CheckboxLabelInputElementTest extends MultiBrowserTest { + + @Test + public void contextClickCheckboxAndText() { + openTestURL(); + CheckBoxElement checkBoxElement = $(CheckBoxElement.class).first(); + WebElement labelElem = checkBoxElement.findElement(By.tagName("label")); + WebElement inputElem = checkBoxElement.findElement(By.tagName("input")); + + assertEquals("my-label-class", labelElem.getAttribute("class")); + assertEquals("my-input-class", inputElem.getAttribute("class")); + assertTrue("The Checkbox Widget should not contain the classes that are " + + "defined as style names for the input or label.", + !checkBoxElement.getAttribute("class").contains("my-label-class") && + !checkBoxElement.getAttribute("class").contains("my-input-class")); + + $(ButtonElement.class).caption("add-style").first().click(); + + assertEquals("my-label-class later-applied-label-class", labelElem.getAttribute("class")); + assertEquals("my-input-class later-applied-input-class", inputElem.getAttribute("class")); + assertTrue("The Checkbox Widget should not contain the classes that are " + + "defined as style names for the input or label.", + !checkBoxElement.getAttribute("class").contains("later-applied-label-class") && + !checkBoxElement.getAttribute("class").contains("later-applied-input-class")); + + $(ButtonElement.class).caption("remove-style").first().click(); + + assertEquals("later-applied-label-class", labelElem.getAttribute("class")); + assertEquals("later-applied-input-class", inputElem.getAttribute("class")); + + $(ButtonElement.class).caption("remove-style-2").first().click(); + + assertTrue(labelElem.getAttribute("class").isEmpty()); + assertTrue(inputElem.getAttribute("class").isEmpty()); + } +} |