001/*
002 * (C) Copyright 2012 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Anahide Tchertchian
016 */
017package org.nuxeo.functionaltests.forms;
018
019import java.lang.reflect.Constructor;
020import java.util.Map;
021
022import org.nuxeo.functionaltests.AbstractTest;
023import org.nuxeo.functionaltests.Assert;
024import org.nuxeo.functionaltests.Locator;
025import org.nuxeo.functionaltests.fragment.WebFragment;
026import org.openqa.selenium.By;
027import org.openqa.selenium.WebDriver;
028import org.openqa.selenium.WebElement;
029
030/**
031 * Represents a layout on the page, with helper methods to retrieve its widgets.
032 *
033 * @since 5.7
034 */
035public class LayoutElement implements LayoutFragment {
036
037    protected final WebDriver driver;
038
039    protected String id;
040
041    public String getId() {
042        return id;
043    }
044
045    public void setId(String id) {
046        this.id = id;
047    }
048
049    /**
050     * @param driver
051     * @param id
052     */
053    public LayoutElement(WebDriver driver, String id) {
054        this.driver = driver;
055        this.id = id;
056    }
057
058    /**
059     * Returns a sub element, concatenating the layout id with the sub element id (and using the standard character ':'
060     * as JSF UINamingContainer separator).
061     */
062    @Override
063    public String getSubElementId(String id) {
064        String finalId = id;
065        if (this.id != null) {
066            if (this.id.endsWith(":")) {
067                finalId = this.id + id;
068            } else {
069                finalId = this.id + ":" + id;
070            }
071        }
072        return finalId;
073    }
074
075    protected <T> T instantiateWidget(String id, Class<T> pageClassToProxy) {
076        try {
077            try {
078                Constructor<T> constructor = pageClassToProxy.getConstructor(WebDriver.class, String.class);
079                return constructor.newInstance(driver, getSubElementId(id));
080            } catch (NoSuchMethodException e) {
081                return pageClassToProxy.newInstance();
082            }
083        } catch (RuntimeException e) {
084            throw e;
085        } catch (Exception e) {
086            throw new RuntimeException(e);
087        }
088    }
089
090    /**
091     * Returns a {@link WidgetElement} with given id, after having injected its fields.
092     */
093    @Override
094    public WidgetElement getWidget(String id) {
095        return getWidget(id, WidgetElement.class);
096    }
097
098    /**
099     * Returns a widget with given id , after having injected its fields.
100     */
101    @Override
102    public <T> T getWidget(String id, Class<T> widgetClassToProxy) {
103        T res = instantiateWidget(id, widgetClassToProxy);
104        res = AbstractTest.fillElement(widgetClassToProxy, res);
105        return res;
106    }
107
108    /**
109     * Returns true if sub element is found in the page.
110     */
111    protected boolean hasSubElement(String id) {
112        return Assert.hasElement(By.id(getSubElementId(id)));
113    }
114
115    /**
116     * Returns the element with given id in the page.
117     */
118    public WebElement getElement(String id) {
119        return Locator.findElement(By.id(id));
120    }
121
122    /**
123     * Returns the element with given id in the page.
124     *
125     * @param wait if true, waits for a default timeout (useful when element is added to the page after an ajax call).
126     */
127    public WebElement getElement(String id, boolean wait) {
128        return Locator.findElementWithTimeout(By.id(id));
129    }
130
131    /**
132     * Returns the element with given sub id on the page.
133     * <p>
134     * The layout id is concatenated to the sub element id for retrieval.
135     */
136    @Override
137    public WebElement getSubElement(String id) {
138        return getElement(getSubElementId(id));
139    }
140
141    /**
142     * Returns the element with given sub id on the page.
143     * <p>
144     * The layout id is concatenated to the sub element id for retrieval.
145     *
146     * @param wait if true, waits for a default timeout (useful when element is added to the page after an ajax call).
147     */
148    @Override
149    public WebElement getSubElement(String id, boolean wait) {
150        return getElement(getSubElementId(id), wait);
151    }
152
153    /**
154     * Clears the given input element and sets the given value if not null.
155     */
156    public void setInput(WebElement elt, String value) {
157        elt.click();
158        elt.clear();
159        if (value != null) {
160            elt.sendKeys(value);
161        }
162    }
163
164    /**
165     * Retrieves sub input element with given id and sets the given value.
166     *
167     * @see #setInput(WebElement, String)
168     */
169    public void setInput(String id, String value) {
170        WebElement elt = getSubElement(id);
171        setInput(elt, value);
172    }
173
174    /**
175     * Retrieves sub input elements with given ids and sets corresponding values.
176     *
177     * @see #setInput(String, String)
178     */
179    public void setInput(Map<String, String> entries) {
180        if (entries == null || entries.isEmpty()) {
181            return;
182        }
183        for (Map.Entry<String, String> entry : entries.entrySet()) {
184            setInput(entry.getKey(), entry.getValue());
185        }
186    }
187
188    /**
189     * @since 5.9.2
190     */
191    public <T extends WebFragment> T getWebFragment(String id, Class<T> webFragmentClass) {
192        return AbstractTest.getWebFragment(By.id(getSubElementId(id)), webFragmentClass);
193    }
194
195}