com.qmetry.qaf.automation.ui.AbstractTestPage Maven / Gradle / Ivy
Show all versions of qaf Show documentation
/*******************************************************************************
* Copyright (c) 2019 Infostretch Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 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.
******************************************************************************/
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() {
}
}