All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.seleniumtests.uipage.aspects.SeleniumNativeActions Maven / Gradle / Ivy

/**
 * Orignal work: Copyright 2015 www.seleniumtests.com
 * Modified work: Copyright 2016 www.infotel.com
 * 				Copyright 2017-2019 B.Hecquet
 *
 * 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.seleniumtests.uipage.aspects;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchFrameException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;

import com.seleniumtests.core.SeleniumTestsContextManager;
import com.seleniumtests.uipage.htmlelements.FrameElement;
import com.seleniumtests.uipage.htmlelements.HtmlElement;

@Aspect
public class SeleniumNativeActions {

	private FrameElement currentFrame;

	private Boolean doOverride() {
		return SeleniumTestsContextManager.getThreadContext().getOverrideSeleniumNativeAction();
	}
	
	/**
	 * Intercept any call to findElement made from a PageObject subclass and returns a HtmlElement instead of a RemoteWebElement
	 * This way, every action done on this element will benefit from HtmlElement mechanism
	 * @param joinPoint
	 * @return
	 * @throws Throwable
	 */
	@Around("this(com.seleniumtests.uipage.PageObject) && " +					// caller is a PageObject
			"(call(public * org.openqa.selenium.WebDriver+.findElement (..))"
			+ ")"			
			)
	public Object interceptFindHtmlElement(ProceedingJoinPoint joinPoint) throws Throwable {
		if (doOverride()) {
			return new HtmlElement("", (By)(joinPoint.getArgs()[0]), currentFrame);
		} else {
			return joinPoint.proceed(joinPoint.getArgs());			
		}
	}
	
	@Around("this(com.seleniumtests.uipage.PageObject) && " +					// caller is a PageObject
			"(call(public * org.openqa.selenium.WebDriver+.findElements (..))"
			+ ")"			
			)
	public Object interceptFindsHtmlElement(ProceedingJoinPoint joinPoint) throws Throwable {
		if (doOverride()) {
			return new HtmlElement("", (By)(joinPoint.getArgs()[0]), currentFrame).findElements();
		} else {
			return joinPoint.proceed(joinPoint.getArgs());
		}
	}
	
	/**
	 * Method interceptFindHtmlElement creates an HtmlElement from findElement, but does not handle frames. 
	 * Here, we record all switchTo().frame(WebElement) call to create a FrameElement chain
	 * @param joinPoint
	 * @return
	 * @throws Throwable
	 */
	@Around("this(com.seleniumtests.uipage.PageObject) && " +					// caller is a PageObject
			"(call(public * org.openqa.selenium.support.ui.ExpectedConditions.frameToBeAvailableAndSwitchToIt (..))"
			+ ")"			
			)
	public Object recordFrameSwitch(ProceedingJoinPoint joinPoint) throws Throwable {
		if (doOverride()) {
			Object frameArg = joinPoint.getArgs()[0];
			FrameElement frameEl = getFrameElement(frameArg);
			
			if (frameEl == null) {
				return joinPoint.proceed(joinPoint.getArgs());
			}
			
			if (currentFrame == null) {
				currentFrame = frameEl;
			} else {
				frameEl.setFrameElement(currentFrame);
				currentFrame = frameEl;
			}

			return new ExpectedCondition() {
			      @Override
			      public WebDriver apply(WebDriver driver) {
			        try {
			          return driver;
			        } catch (NoSuchFrameException e) {
			          return null;
			        }
			      }

			      @Override
			      public String toString() {
			        return "frame to be available: " + frameArg;
			      }
			    };
			
		} else {
			return joinPoint.proceed(joinPoint.getArgs());
		}
	}
	
	/**
	 * Method interceptFindHtmlElement creates an HtmlElement from findElement, but does not handle frames. 
	 * Here, we record all switchTo().frame(WebElement) call to create a FrameElement chain
	 * @param joinPoint
	 * @return
	 * @throws Throwable
	 */
	@Around("this(com.seleniumtests.uipage.PageObject) && " +					// caller is a PageObject
			"(call(public * org.openqa.selenium.WebDriver.TargetLocator+.frame (..))"
			+ ")"			
			)
	public Object recordSwitchToFramCalls(ProceedingJoinPoint joinPoint) throws Throwable {
		if (doOverride()) {
			Object frameArg = joinPoint.getArgs()[0];
			FrameElement frameEl = getFrameElement(frameArg);
			
			if (frameEl == null) {
				return joinPoint.proceed(joinPoint.getArgs());
			}

			if (currentFrame == null) {
				currentFrame = frameEl;
			} else {
				frameEl.setFrameElement(currentFrame);
				currentFrame = frameEl;
			}
			return null;
		} else {
			return joinPoint.proceed(joinPoint.getArgs());
		}
	}
	
	/**
	 * Returns a FrameElement based on the object passed in argument
	 * @param frameArg
	 * @return
	 */
	private FrameElement getFrameElement(Object frameArg) {
		FrameElement frameEl = null;
		
		if (frameArg instanceof HtmlElement) {
			frameEl = new FrameElement("", ((HtmlElement)frameArg).getBy());
		} else if (frameArg instanceof By) {
			frameEl = new FrameElement("", (By)frameArg);
		} else if (frameArg instanceof Integer) {
			frameEl = new FrameElement("", By.tagName("iframe"), 0);
		} else if (frameArg instanceof String) {
			String name = ((String)frameArg).replaceAll("(['\"\\\\#.:;,!?+<>=~*^$|%&@`{}\\-/\\[\\]\\(\\)])", "\\\\$1");
			frameEl = new FrameElement("", By.cssSelector("frame[name='" + name + "'],iframe[name='" + name + "'],frame#" + name + ",iframe#" + name));
		}
		return frameEl;
	}
	
	@Around("this(com.seleniumtests.uipage.PageObject) && " +					// caller is a PageObject
			"(call(public * org.openqa.selenium.WebDriver.TargetLocator+.defaultContent (..))"
			+ ")"			
			)
	public Object recordSwitchDefaultContext(ProceedingJoinPoint joinPoint) throws Throwable {
		currentFrame = null;
		return joinPoint.proceed(joinPoint.getArgs());
	}
	
	
	@Around("this(com.seleniumtests.uipage.PageObject) && " +					// caller is a PageObject
			"(call(public * org.openqa.selenium.WebDriver.TargetLocator+.parentFrame (..))"
			+ ")"			
			)
	public Object recordSwitchParentFrame(ProceedingJoinPoint joinPoint) throws Throwable {
		if (currentFrame == null || !doOverride()) {
			return joinPoint.proceed(joinPoint.getArgs());
		} else {
			currentFrame = currentFrame.getFrameElement();
		}
		return null;
		
	}
	
	
	
	// TODO: handle findElementBy... (from RemoteWebDriver) => should be useless as SeleniuRobot only expose a WebDriverInstance
	// TODO: check behavior with WebDriverWait & CompositeActions
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy