/*
* Copyright 2002-2007 the original author or authors.
*
* 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 org.suren.autotest.web.framework.selenium.strategy;
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.suren.autotest.web.framework.core.ElementSearchStrategy;
import org.suren.autotest.web.framework.core.ElementsSearchStrategy;
import org.suren.autotest.web.framework.core.LocatorNotFoundException;
import org.suren.autotest.web.framework.core.ui.AbstractElement;
import org.suren.autotest.web.framework.core.ui.Element;
import org.suren.autotest.web.framework.selenium.SeleniumEngine;
import org.suren.autotest.web.framework.util.StringUtils;
/**
* 查找元素策略,找不到对应的元素会抛出异常</br>
* <ul>
* <li>通过id查找</li>
* <li>通过css样式查找</li>
* <li>通过xpath查找</li>
* <li>通过超链接文本查找</li>
* <li>通过超链接部分文本查找</li>
* <li>根据标签名称来查找</li>
* </ul>
*
* @see CyleSearchStrategy
* @see ZoneSearchStrategy
* @author suren
* @date Jul 16, 2016 6:45:44 PM
*/
@Component("prioritySearchStrategy")
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class PrioritySearchStrategy implements ElementSearchStrategy<WebElement>,
ElementsSearchStrategy<WebElement>, ParentElement
{
@Autowired
private SeleniumEngine engine;
private Element element;
private WebElement targetWebElement;
private WebElement parentElement;
/**
* 根据定位元素的优先级来进行元素查找
*/
@Override
public WebElement search(Element element)
{
By by = buildBy(element);
if(targetWebElement != null)
{
return targetWebElement;
}
else
{
return findElement(by);
}
}
@Override
public List<WebElement> searchAll(Element element)
{
By by = buildBy(element);
return findElements(by);
}
/**
* 构建定位方法
* @param element
* @return
*/
private By buildBy(Element element)
{
By by = null;
this.element = element;
if (StringUtils.isNotBlank(element.getId()))
{
String orginId = element.getId();
String paramId = orginId;
if(element instanceof AbstractElement)
{
paramId = ((AbstractElement) element).paramTranslate(paramId);
}
by = By.id(paramId);
}
else if (StringUtils.isNotBlank(element.getCSS()))
{
String css = element.getCSS();
if(element instanceof AbstractElement)
{
css = ((AbstractElement) element).paramTranslate(css);
}
String[] cssArray = css.split(" ");
by = By.className(cssArray[0]);
List<WebElement> elementList = findElements(by);
for(WebElement ele : elementList)
{
new Actions(engine.getDriver()).moveToElement(ele);
if(css.equals(ele.getAttribute("class")))
{
targetWebElement = ele;
break;
}
}
return null;
}
else if(StringUtils.isNotBlank(element.getName()))
{
String orginName = element.getName();
String paramName = orginName;
if(element instanceof AbstractElement)
{
paramName = ((AbstractElement) element).paramTranslate(paramName);
}
by = By.name(paramName);
}
else if (StringUtils.isNotBlank(element.getXPath()))
{
String orginXPath = element.getXPath();
String paramXPath = orginXPath;
if(element instanceof AbstractElement)
{
paramXPath = ((AbstractElement) element).paramTranslate(paramXPath);
}
by = By.xpath(paramXPath);
}
else if (StringUtils.isNotBlank(element.getLinkText()))
{
String orginLinkText = element.getLinkText();
String paramLinkText = orginLinkText;
if(element instanceof AbstractElement)
{
paramLinkText = ((AbstractElement) element).paramTranslate(paramLinkText);
}
by = By.linkText(paramLinkText);
}
else if (StringUtils.isNotBlank(element.getPartialLinkText()))
{
String orginPartialLinkText = element.getPartialLinkText();
String paramPartialLinkText = orginPartialLinkText;
if(element instanceof AbstractElement)
{
paramPartialLinkText = ((AbstractElement) element).paramTranslate(paramPartialLinkText);
}
by = By.partialLinkText(paramPartialLinkText);
}
else if (StringUtils.isNotBlank(element.getTagName()))
{
String orginTagName = element.getTagName();
String paramTagName = orginTagName;
if(element instanceof AbstractElement)
{
paramTagName = ((AbstractElement) element).paramTranslate(paramTagName);
}
by = By.tagName(paramTagName);
}
else
{
throw new LocatorNotFoundException();
}
return by;
}
/**
* 通用的元素查找方法
* @param by 具体的查找方法
* @return
*/
private WebElement findElement(By by)
{
WebDriver driver = engine.getDriver();
driver = engine.turnToRootDriver(driver);
if(element.getTimeOut() > 0)
{
WebDriverWait wait = new WebDriverWait(driver, element.getTimeOut());
wait.until(ExpectedConditions.visibilityOfElementLocated(by));
}
if(parentElement != null)
{
return parentElement.findElement(by);
}
else
{
return driver.findElement(by);
}
}
/**
* 查找多个元素
* @param by
* @return
*/
private List<WebElement> findElements(By by)
{
WebDriver driver = engine.getDriver();
driver = engine.turnToRootDriver(driver);
if(parentElement != null)
{
return parentElement.findElements(by);
}
else
{
return driver.findElements(by);
}
}
@Override
public void setParent(WebElement parentWebElement)
{
this.parentElement = parentWebElement;
}
@Override
public String description()
{
return "根据预先给定的元素定位方法优先级进行搜索,直到找到元素或者定位方法穷举完毕。"
+ "如果元素指定了显式的查找超时时间,则采用可见性的超时等待。";
}
}