1- /**
2- * Copyright © 1998-2016, Glodon Inc. All Rights Reserved.
3- */
1+ /*
2+ * Copyright 2002-2007 the original author or authors.
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+
417package org .suren .autotest .web .framework .selenium .action ;
518
619import java .awt .AWTException ;
2235import org .slf4j .LoggerFactory ;
2336import org .springframework .beans .factory .annotation .Autowired ;
2437import org .springframework .stereotype .Component ;
38+ import org .suren .autotest .web .framework .core .ElementSearchStrategy ;
2539import org .suren .autotest .web .framework .core .action .ClickAble ;
2640import org .suren .autotest .web .framework .core .ui .Element ;
2741import org .suren .autotest .web .framework .core .ui .FileUpload ;
@@ -39,6 +53,10 @@ public class SeleniumClick implements ClickAble
3953{
4054 private static final Logger logger = LoggerFactory .getLogger (SeleniumClick .class );
4155
56+ /** 失败后重试的最大次数 */
57+ private int maxRetry = 3 ;
58+ private int errorTimes = 0 ;
59+
4260 @ Autowired
4361 private SeleniumEngine engine ;
4462 @ Autowired
@@ -47,15 +65,23 @@ public class SeleniumClick implements ClickAble
4765 @ Override
4866 public void click (Element ele )
4967 {
50- WebElement webEle = searchStrategyUtils .findStrategy (WebElement .class , ele ).search (ele );
51- if (webEle == null )
68+ if (errorTimes >= maxRetry )
5269 {
53- logger .warn ("can not found element." );
5470 return ;
5571 }
5672
73+ ElementSearchStrategy <WebElement > searchStrategy =
74+ searchStrategyUtils .findStrategy (WebElement .class , ele );
75+ WebElement webEle = searchStrategy .search (ele );
76+ if (webEle == null )
77+ {
78+ throw new RuntimeException (String .format ("Element [%s] can not found "
79+ + "by strategy [%s]!" , ele , searchStrategy ));
80+ }
81+
5782 try
5883 {
84+ //对于远程服务的文件上传,不移动鼠标
5985 if (!(ele instanceof FileUpload ) && !(engine .getDriver () instanceof RemoteWebDriver ))
6086 {
6187 Dimension size = webEle .getSize ();
@@ -67,9 +93,11 @@ public void click(Element ele)
6793 new Robot ().mouseMove (x , y );
6894 }
6995
96+ webEle .click ();
97+
98+ //如果是a标签锚点的话,根据target属性来决定是否要切换window句柄
7099 String tagName = webEle .getTagName ();
71100 String targetAttr = webEle .getAttribute ("target" );
72- webEle .click ();
73101 if ("a" .equals (tagName ) && "_blank" .equals (targetAttr ))
74102 {
75103 WebDriver driver = engine .getDriver ();
@@ -82,27 +110,26 @@ public void click(Element ele)
82110 driver .switchTo ().window (name );
83111 }
84112 }
113+
114+ errorTimes = 0 ;
85115 }
86116 catch (WebDriverException e )
87117 {
118+ logger .error ("元素点击操作发生错误。" , e );
119+ errorTimes ++;
120+
121+ //如果由于目标元素不在可见区域导致的异常,尝试滚动屏幕
88122 if (e .getMessage ().contains ("is not clickable at point" ))
89123 {
124+ logger .info ("Will retry click operation, after element move." );
125+
90126 new Actions (engine .getDriver ()).moveToElement (webEle , -50 , -50 ).perform ();
91127
92128 WebDriverWait wait = new WebDriverWait (engine .getDriver (), 30 );
93-
94129 ((JavascriptExecutor ) engine .getDriver ()).executeScript ("arguments[0].scrollIntoView();" , webEle , -50 , -50 );
95-
96130 wait .until (ExpectedConditions .visibilityOf (webEle ));
97131
98- try
99- {
100- webEle .click ();
101- }
102- catch (WebDriverException innerE )
103- {
104- click (ele );
105- }
132+ click (ele );
106133 }
107134 }
108135 catch (AWTException e )
@@ -130,4 +157,20 @@ public boolean isHidden(Element element)
130157 return !searchStrategyUtils .findStrategy (WebElement .class , element ).search (element ).isDisplayed ();
131158 }
132159
160+ /**
161+ * @return 失败后重试的最大次数
162+ */
163+ public int getMaxRetry ()
164+ {
165+ return maxRetry ;
166+ }
167+
168+ /**
169+ * @param maxRetry 失败后重试的最大次数(默认为3)
170+ */
171+ public void setMaxRetry (int maxRetry )
172+ {
173+ this .maxRetry = maxRetry ;
174+ }
175+
133176}
0 commit comments