com.qmetry.qaf.automation.ui.AbstractTestPage Maven / Gradle / Ivy
Show all versions of qaf Show documentation
/*******************************************************************************
* QMetry Automation Framework provides a powerful and versatile platform to author
* Automated Test Cases in Behavior Driven, Keyword Driven or Code Driven approach
*
* Copyright 2016 Infostretch Corporation
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
* OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
*
* You should have received a copy of the GNU General Public License along with this program in the name of LICENSE.txt in the root folder of the distribution. If not, see https://opensource.org/licenses/gpl-3.0.html
*
* See the NOTICE.TXT file in root folder of this source files distribution
* for additional information regarding copyright ownership and licenses
* of other open source software / files used by QMetry Automation Framework.
*
* For any inquiry or need additional information, please contact [email protected]
*******************************************************************************/
package com.qmetry.qaf.automation.ui;
import java.lang.reflect.ParameterizedType;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.impl.LogFactoryImpl;
import com.qmetry.qaf.automation.core.ConfigurationManager;
import com.qmetry.qaf.automation.ui.api.PageLocator;
import com.qmetry.qaf.automation.ui.api.TestPage;
import com.qmetry.qaf.automation.ui.api.UiTestBase;
import com.qmetry.qaf.automation.ui.webdriver.ElementFactory;
import com.qmetry.qaf.automation.util.PropertyUtil;
/**
* High level page class for different UI driver implementation.
*
* This class provides you a way to define static or dynamic page hierarchy. In
* the case of page hierarchy, you just need to call launch page method of the
* object. it takes care of not only launching that page but also the entire
* page hierarchy to reach that specific page. Furthermore it also checks that
* is page already active in browser? If so then it will continue from there,
* results in reduced execution time. It also allows you to set one of the
* {@link #setLaunchStrategy(com.qmetry.qaf.automation.ui.api.TestPage.LaunchStrategy)
* launch strategy} so that you can specify launch behavior before launching the
* page. The default launch strategy is {@link LaunchStrategy#onlyIfRequired
* launch only if required}.
*
* When functionality changes only the specific test page file needs to be
* updated: if there is any change in page/ui of web/native AUT you need to
* update just in particular page rather than each and every test case, thus
* result in less maintenance.
*
* By implementation of test page concept in a best efficient way, you can
* manipulate page navigation same as on actual web application under test. Once
* page get created page object's functionalities can be used in any test case,
* makes code more reusable.
*
* @author Chirag Jayswal
* @param
* parent page in hierarchy
* @param
* Driver implementation - e.g. selenium or webdriver
*/
public abstract class AbstractTestPage, D> implements TestPage {
protected P parent;
protected UiTestBase testbase;
protected D driver;
protected PropertyUtil pageProps;
protected PageLocator pageLocator;
protected Object[] launchArguments;
protected final Log logger;
protected LaunchStrategy launchStrategy = LaunchStrategy.onlyIfRequired;
public AbstractTestPage(UiTestBase testBase) {
this.testbase = testBase;
logger = LogFactoryImpl.getLog(this.getClass());
driver = testbase.getDriver();
this.pageProps = ConfigurationManager.getBundle();
initWebElements();
}
public AbstractTestPage(UiTestBase testBase, P parent2) {
this(testBase);
this.parent = parent2;
}
@Override
public UiTestBase getTestBase() {
return testbase;
}
@Override
public PageLocator getPageLocator() {
return this.pageLocator;
}
@Override
public void setLaunchStrategy(LaunchStrategy strategy) {
launchStrategy = strategy;
}
@Override
public void launchPage(PageLocator locator, Object... args) {
this.pageLocator = locator;
this.launchArguments = args;
boolean reqToLaunch = false;
parent = getParent();
try {
reqToLaunch = !launchStrategy.equals(LaunchStrategy.onlyIfRequired) || !this.isPageActive(locator, args);
} catch (Exception e) {
e.printStackTrace();
}
if (reqToLaunch) {
logger.debug("Launching page: " + this.getClass().getCanonicalName());
if (parent != null) {
if (launchStrategy.equals(LaunchStrategy.alwaysRelaunchFromRoot)) {
parent.setLaunchStrategy(launchStrategy);
} else {
parent.setLaunchStrategy(LaunchStrategy.onlyIfRequired);
}
parent.launchPage(locator != null ? locator.getParentLocator() : null, args);
}
beforeLaunch(args);
openPage(locator, args);
waitForPageToLoad();
afterLaunch();
}
}
public void waitForPageToLoad() {
}
@Override
public boolean isPageActive(PageLocator loc, Object... args) {
return false;
}
/**
* this method can be override to provide tasks to be done immediate after
* page launch. It will ensure that page is launched. It is
*/
protected void afterLaunch() {
}
/**
* you can override this method to fech any information/data from parent
* page before launching the page. FW will ensure that when this method get
* executed parent page is open.
*
* Note: If launch method found this page is not opened and going to
* open the page then only this method will get executed.
*
* @param args
* passed in {@link #launchPage(PageLocator, Object...)}
*/
protected void beforeLaunch(Object... args) {
}
@SuppressWarnings("unchecked")
protected void initParent() {
try {
Class
class1 = (Class
) ((ParameterizedType) this.getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
if (!class1.isInterface()) {
parent = class1.newInstance();
}
} catch (Exception e) {
logger.warn("Unable to init parent class" + e.getMessage());
}
}
/**
* Do not provide steps to load this page in this method, Instead provide
* steps in method of parent and call that method over here.
* In case of multiple parent or referrer page, provide code to get parent
* by casting. For instance:
*
*
*
* if(parent instanceof UploadStatus ){
* UploadStatus parent = (UploadStatus) getParent();
* parent.methodToLoadThisPage(args_if_any);
* }
*
*
*
* @param locator
* @param args
*/
abstract protected void openPage(PageLocator locator, Object... args);
@Override
public final P getParent() {
if (this.parent == null) {
initParent();
}
return this.parent;
}
private void initWebElements() {
ElementFactory elementFactory = new ElementFactory();
elementFactory.initFields(this);
}
public void assertActive() {
String msg = String.format("Expected %s is active.", this.getClass().getSimpleName());
AbstractTestCase.assertTrue(isPageActive(pageLocator, launchArguments), msg, msg);
}
@Deprecated
public void waitForImageToLoad(final String imgLoc) {
}
/**
* for any kit
*/
public void waitForAjaxToComplete() {
}
}