/*
* 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.SearchContext;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.Locator;
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.selenium.locator.AbstractLocator;
import org.suren.autotest.web.framework.util.ThreadUtil;
/**
* 区域定位元素查找策略
*
* @see PrioritySearchStrategy
* @see CyleSearchStrategy
* @author suren
* @date Jul 16, 2016 7:27:09 PM
*/
@Component("zoneSearchStrategy")
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class ZoneSearchStrategy implements ElementSearchStrategy<WebElement>, ParentElement
{
private static final Logger logger = LoggerFactory.getLogger(ZoneSearchStrategy.class);
@Autowired
private SeleniumEngine engine;
private int failedCount = 0;
private int maxFailed = 6;
private int timeout = 1500;
private WebElement parentWebElement;
@SuppressWarnings("unchecked")
@Override
public WebElement search(Element element)
{
List<Locator> locators = element.getLocatorList();
if(locators == null)
{
return null;
}
logger.info(String.format("zone search strategy, locators count[%s].", locators.size()));
AbstractElement absEle = null;
if(element instanceof AbstractElement)
{
absEle = (AbstractElement) element;
}
WebDriver driver = engine.getDriver();
for(Locator locator : locators)
{
if(!(locator instanceof AbstractLocator<?>))
{
logger.warn(String.format("Unknow locator type, not subclass of AbstractLocator, [%s].",
locator.getClass()));
continue;
}
AbstractLocator<WebElement> absLocator = ((AbstractLocator<WebElement>) locator);
if(absEle != null)
{
//动态参数转换
absLocator.setValue(absEle.paramTranslate(absLocator.getValue()));
}
if(parentWebElement != null)
{
parentWebElement = retry(absLocator, parentWebElement);
}
else
{
parentWebElement = retry(absLocator, driver);
}
}
return parentWebElement;
}
/**
* 失败重试
* @param absLocator
* @param webEle
* @return
*/
private WebElement retry(AbstractLocator<WebElement> absLocator, SearchContext webEle)
{
WebElement result = null;
if(webEle != null)
{
result = absLocator.findElement(webEle);
}
else
{
result = absLocator.findElement(webEle);
}
if(result != null || ++failedCount > maxFailed)
{
return result;
}
else
{
logger.warn("Can not found element by locator {}, "
+ "will retry locate again {} millis later, failed times {}.",
absLocator, timeout, failedCount);
ThreadUtil.silentSleep(timeout);
return retry(absLocator, webEle);
}
}
@Override
public void setParent(WebElement parentWebElement) {
this.parentWebElement = parentWebElement;
}
@Override
public String description()
{
return String.format("区域搜索策略,按照元素的区域划分,分层次地进行多次定位搜索。每次元素查找失败,"
+ "都会进行重试(%s次),每次失败后的超时时间为%s毫秒。", maxFailed, timeout);
}
}