package test_4_1.tools; import java.io.IOException; import java.io.InputStream; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.NoSuchElementException; import java.util.Scanner; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.function.Function; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import org.junit.Assert; import org.openqa.selenium.By; import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.StaleElementReferenceException; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.chrome.ChromeOptions; import org.openqa.selenium.ie.InternetExplorerDriver; import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.remote.RemoteWebDriver; import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.FluentWait; import org.openqa.selenium.support.ui.Wait; import com.fasterxml.jackson.core.JsonParser.Feature; import com.fasterxml.jackson.databind.ObjectMapper; import org.openqa.selenium.support.ui.WebDriverWait; /** * @author Terry Date : 2016-02-29 23:17 工具类 */ public class Utils { /** * 项目设置对象 */ public static JSONObject settings = null; public static WebDriver driver; /** * 全局等待的设置 */ public static WebDriverWait waitSetting; /** * extJs confirm窗口的等待时间 */ public static WebDriverWait confirmWaitSetting; // public static Wait waitSetting; public static List barcodes; public static List resendout; public static List reBarcodes = new ArrayList(); /** * 根据项目名称,初始化项目的配置对象 * * @param projectName * 项目名称的字符串 * @return 项目配置对象 */ public static JSONObject initProjectSettings(String projectName) { settings = getProjectSettings(projectName); return settings; } /** * 打印当前页面的源代码,用于分析调试 * * @param driver */ public static void printCurrentWebpageSourcecode(WebDriver driver) { Object response = ((JavascriptExecutor) driver) .executeScript("return document.documentElement.innerHTML;"); String source = (String) response; System.out.println(source); } /** * 设置等待的对象 * @param driver 对应的driver */ public static void setWaitSetting(WebDriver driver){ //最长等待15秒,每1秒轮询一次 waitSetting = new WebDriverWait(driver, 15, 800); //最长等待2秒,每0.3秒轮询一次 confirmWaitSetting = new WebDriverWait(driver, 2, 300); // waitSetting = new FluentWait<>(driver).withTimeout(5000, TimeUnit.MILLISECONDS).pollingEvery(250, TimeUnit.MILLISECONDS); } /** * 初始化chrome的driver */ private static void webDriverChromeInit(){ DesiredCapabilities chrome = DesiredCapabilities.chrome(); ChromeOptions options = new ChromeOptions(); options.addArguments("test-type"); chrome.setCapability(ChromeOptions.CAPABILITY, options); chrome.setCapability("applicationName", "terry"); chrome.setCapability("version", "11.0"); driver = new ChromeDriver(chrome); driver.get(Utils.settings.get("服务器地址").toString()); } /** 打开浏览器 */ public static void webDriverInit() { // System.setProperty("webdriver.ie.driver", // "C:\\IEDriverServer_Win32_3.3.0\\IEDriverServer.exe"); // 解决ie兼容模式设置导致无法启动问题 DesiredCapabilities ieCapabilities = DesiredCapabilities.internetExplorer(); ieCapabilities.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, true); ieCapabilities.setCapability("applicationName", "terry"); ieCapabilities.setCapability("version", "11.0"); // driver = new InternetExplorerDriver(ieCapabilities); try { // driver = new RemoteWebDriver(new URL( "http://192.168.2.18:4444/wd/hub"), ieCapabilities); driver = new InternetExplorerDriver(ieCapabilities); } catch (Exception e) { e.printStackTrace(); } driver.get(Utils.settings.get("服务器地址").toString()); } /** * 初始化设置,包括项目配置和webdriver的初始化 * */ public static void init() { //zd5y已经不使用了 initProjectSettings("all"); webDriverInit(); // webDriverChromeInit(); // driver初始化完设置全局等待的对象 setWaitSetting(driver); } /** 定位到弹出对话框的按钮 */ public static void LocaAndWait() { // Wait wait = new FluentWait(Utils.driver) // .withTimeout(5000, TimeUnit.MILLISECONDS) // .pollingEvery(250, TimeUnit.MILLISECONDS) // .ignoring(NoSuchElementException.class); // WebElement yesbutton = wait // .until(new Function() { // public WebElement apply(WebDriver driver) { // return driver.findElement(By.linkText("是")); // } // }); // yesbutton.click(); retryingFindAndClick(By.linkText("是")); } /** 获取当前日期 */ public static void DateTime() { Date now = new Date(); SimpleDateFormat dateFormater = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss"); System.out.print(dateFormater.format(now) + " "); } /** * 获取装配时创建的器械包的条码,为集合对象 * */ public static List getToussesBarcodes() { JavascriptExecutor js = (JavascriptExecutor) driver; Object toussesStr = js .executeScript("return JSON.stringify(packingToussesArray)"); List barcodes = new ArrayList(); JSONArray array = JSONArray.fromObject(toussesStr); if (array != null) { for (int i = 0; i < array.size(); i++) { JSONObject tousse = array.getJSONObject(i); JSONArray b = tousse.getJSONArray("barcodes"); for (int j = 0; j < b.size(); j++) { barcodes.add((String) b.get(j)); } } } Utils.reBarcodes.addAll(barcodes); return barcodes; } /** * 重复查找,当出现引用的element过时后,重新查找该element * * @param by * @return */ public static WebElement retryingFind(By by) { WebElement element = null; int attempts = 0; while (attempts < 3) { try { Thread.sleep(1000); element = fluentWaitUntilFind(by); break; } catch (Exception e) { } attempts++; } return element; } /** * 重复查找和click,当出现引用的element过时后,重新查找该element * * @param by * @return */ public static WebElement retryingFindAndClick(By by) { WebElement element = null; int attempts = 0; while (attempts < 3) { try { element = fluentWaitUntilFind(by); element.click(); break; } catch (Exception e) { } attempts++; } return element; } public static WebElement retryingFindAndSendKeys(By by, java.lang.CharSequence... keys) { WebElement element = null; int attempts = 0; while (attempts < 3) { try { element = fluentWaitUntilFind(by); element.sendKeys(keys); break; } catch (Exception e) { // System.out.println("hkkkkkk"); // e.printStackTrace(); } attempts++; } return element; } /** * 查找组合框,输入按键。输入按键后休眠1.5秒,等待下拉框的内容出现,保证可靠的输入值。 * TODO:如果找到更可靠输入组合框内容的方法,可以取消休眠。如果需要更可靠的输入,可以延长休眠时间 * @param by * @param keys * @return */ public static WebElement retryingFindComboBoxAndSendKeys(By by, java.lang.CharSequence... keys) { WebElement element = null; int attempts = 0; while (attempts < 3) { try { element = fluentWaitUntilFind(by); element.sendKeys(keys); Thread.sleep(1500); break; } catch (Exception e) { // System.out.println("hkkkkkk"); // e.printStackTrace(); } attempts++; } return element; } /** * 查找并切换到IFrame * @param by * @return */ public static WebElement retryingFindAndSwitchToFrame(By by) { WebElement element = null; int attempts = 0; while (attempts < 3) { try { // 跳出所有的frame。调用后:you are now outside both frames // Utils.driver.switchTo().defaultContent(); element = fluentWaitUntilFind(by); Utils.driver.switchTo().frame(element); break; } catch (Exception e) { } attempts++; } return element; } /** * 流畅等待,查找页面元素 * * @param by * @return */ public static WebElement fluentWaitUntilFind(By by) { WebElement element; Wait wait = new FluentWait(Utils.driver) .withTimeout(5000, TimeUnit.MILLISECONDS) .pollingEvery(250, TimeUnit.MILLISECONDS) .ignoring(NoSuchElementException.class) .ignoring(StaleElementReferenceException.class) .ignoring(NullPointerException.class); element = wait .until(new Function() { public WebElement apply(WebDriver driver) { //等待页面状态加载完成 JavascriptExecutor js=(JavascriptExecutor)driver; js.executeScript("return document.readyState").equals("complete"); return driver.findElement(by); } }); return element; } /** * 等待对象使用waitSetting * @see Utils#findByAwait(By, WebDriverWait) */ public static WebElement findByAwait(By by) { return findByAwait(by, waitSetting); } /** * 查找页面的节点,使用轮询方式,会一直阻塞,如果超过指定的时间仍然找不到则会抛出异常 * @param wait 等待的对象 * @return 查找到的节点,如果在指定的时间找不到则不会返回,直接抛出异常 */ public static WebElement findByAwait(By by, WebDriverWait wait) { final WebElement[] webElement = {null}; try { //这里找不到会抛出异常 if (wait.until((ExpectedCondition) driver -> { webElement[0] = driver.findElement(by); return webElement[0] != null && webElement[0].isDisplayed(); })) { // webElement[0] = driver.findElement(by); } } catch (Exception e) { throw new NoSuchElementException(String.format("找不到对应的元素:%s,原因如下:\n%s", by, e)); } return webElement[0]; } /** * 先用confirmWaitSetting去找ExtJs的confirm框,如果找得到则点击确认,抛出异常则不点击(用于判断是否需要点击确认框) */ public static WebElement findConfirmAndClick(By by) { WebElement webElement = null; try { webElement = findByAwait(by, confirmWaitSetting); webElement.click(); } catch (Exception ignored) { } return webElement; } /** * 尝试寻找某个节点 * @return 返回空则表示找不到 */ public static WebElement tryFind(By by) { try { return findByAwait(by, confirmWaitSetting); } catch (Exception ignored) { } return null; } /** * 判断某个节点是否被找到 * @param webElement 对应的节点 * @return */ public static boolean isFind(WebElement webElement) { return webElement != null && webElement.isDisplayed(); } /** * 在对应的文本框输入想要的内容 * @param keys 要输入的内容 */ public static WebElement findByAwaitAndSend(By by, java.lang.CharSequence... keys) { //先清空文本框上面的然后再输入 WebElement webElement = findByAwaitAndClear(by); webElement.sendKeys(keys); return webElement; } /** * 点击页面元素 */ public static WebElement findByAwaitAndClick(By by) { WebElement webElement = findByAwait(by); // String javascript = "var evt = document.createEvent('MouseEvents');" + "evt.initMouseEvent('click',true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0,null);" + "arguments[0].dispatchEvent(evt);"; // runJavaScript(javascript, webElement); webElement.click(); return webElement; } /** * 清除页面的元素,例如文本框 */ public static WebElement findByAwaitAndClear(By by) { WebElement webElement = findByAwait(by); webElement.clear(); return webElement; } /** * 切换到对应的frame */ public static WebElement findByAwaitAndSwitchToFrame(By by) { Utils.driver.switchTo().defaultContent(); WebElement webElement = findByAwait(by); Utils.driver.switchTo().frame(webElement); return webElement; } /** * 运行js脚本 * @param script 要运行的js脚本 */ public static Object runJavaScript(String script){ return ((JavascriptExecutor) Utils.driver).executeScript(script); } public static Object runJavaScript(String script, Object... args){ return ((JavascriptExecutor) Utils.driver).executeScript(script, args); } /** * 等待页面加载完成 */ public static void waitPageLoaded() { waitSetting.until((ExpectedCondition) driver -> Utils.runJavaScript("return document.readyState").equals("complete")); } /** * 重复查找和click,html表格的第一个单元格对象 * * @param by * html table的查找条件 * @return 单元格对象 */ public static boolean retryingFindClickFirstCellOfTable(By by) { boolean result = false; int attempts = 0; while (attempts < 3) { try { WebElement table = retryingFind(by); if (table != null) { WebElement cell = getFirstCellOfTable(table); cell.click(); result = true; break; } } catch (StaleElementReferenceException e) { System.out.println("发生了异常:StaleElementReferenceException"); e.printStackTrace(); } catch (NoSuchElementException e) { System.out.println("发生了异常:NoSuchElementException"); e.printStackTrace(); } attempts++; } return result; } /** * 重复查找,html表格的第四个单元格对象 * * @param by * html table的查找条件 * @return 单元格对象 */ public static WebElement retryingFindForthCellOfTable(By by) { WebElement result = null; int attempts = 0; while (attempts < 3) { try { WebElement table = retryingFind(by); if (table != null) { WebElement cell = getforthCellOfTable(table); if (cell != null) { String text = cell.getText(); if (text != null) { if (text.equals("自定义器械包申请单") || text.equals("消毒物品申请单")) { result = cell; break; } else { result = null; break; } } } else { result = null; break; } } } catch (StaleElementReferenceException e) { System.out.println("发生了异常:StaleElementReferenceException"); e.printStackTrace(); } catch (NoSuchElementException e) { System.out.println("发生了异常:NoSuchElementException"); e.printStackTrace(); } attempts++; } return result; } /** * 获取Html Table的第一个单元格,即第一行第一列的单元格 * * @param table * 表格对象 * @return 单元格对象 */ private static WebElement getFirstCellOfTable(WebElement table) { WebElement cell = null; // Now get all the TR elements from the table List allRows = table.findElements(By.tagName("tr")); System.out.println("rows size = " + allRows.size()); if (allRows != null && allRows.size() > 0) { WebElement row = allRows.get(0); // return row; List cells = row.findElements(By.tagName("td")); if (cells != null && cells.size() > 0) { cell = cells.get(0); } } return cell; } /** * 获取Html Table的第四个单元格,即第一行第四列的单元格 * * @param table * 表格对象 * @return 单元格对象 */ private static WebElement getforthCellOfTable(WebElement table) { WebElement cell = null; // Now get all the TR elements from the table List allRows = table.findElements(By.tagName("tr")); System.out.println("rows size = " + allRows.size()); if (allRows != null && allRows.size() > 0) { WebElement row = allRows.get(0); // return row; List cells = row.findElements(By.tagName("td")); if (cells != null && cells.size() > 0) { cell = cells.get(3); } } return cell; } /** * 等待直到新窗口被打开 * * @param noOfWindows * 期望的窗口数量 * @param timeOut * 超时时间,单位为毫秒 */ public static void waitForWindowToOpen(int noOfWindows, int timeOut) { int initCount = driver.getWindowHandles().size(); if (initCount == noOfWindows) { return; } else { boolean foundWindow = false; long duration; long startTime = System.currentTimeMillis(); duration = (System.currentTimeMillis() - startTime); while (timeOut > duration && !foundWindow) { try { Thread.sleep(500); } catch (InterruptedException e) { } foundWindow = driver.getWindowHandles().size() >= noOfWindows; duration = (System.currentTimeMillis() - startTime); } if (timeOut <= duration && !foundWindow) { // Throw Error } } } /** * 尝试关闭警告对话框,如果弹出了警告对话框,则关闭该对话框 警告框可能有多个,如:器械包过期告警、满意度调查 */ public static void tryToCloseWarningWindow() { try { Wait wait = new FluentWait(Utils.driver) .withTimeout(5000, TimeUnit.MILLISECONDS) .pollingEvery(250, TimeUnit.MILLISECONDS) .ignoring(NoSuchElementException.class); // 等待对话框弹出 // wait.until(ExpectedConditions // .visibilityOfElementLocated(By // .xpath("//div/span[contains(text(),'满意度调查表')]"))); // 获取警告信息对话框的集合 List closeBtns = wait .until(new Function>() { public List apply(WebDriver driver) { return driver.findElements(By .cssSelector("div[class='x-tool x-tool-close']")); } }); if (closeBtns.size() == 0) { return; } // List closeBtns = Utils.driver.findElements(By // .cssSelector("div[class='x-tool x-tool-close']")); System.out.println("closeBtns.size() = " + closeBtns.size()); // 逐个关闭对话框,先关闭最外层的。如果没关闭最外层的,里面的对话框无法关闭 for (int i = closeBtns.size() - 1; i >= 0; i--) { closeBtns.get(i).click(); } } catch (Exception e) { e.printStackTrace(); Assert.fail(e.getMessage()); } } /** * 回收自定义入筐窗口的切换 */ public static void changeCustomWindow() { try { // 回收窗口 String mainWindow = Utils.driver.getWindowHandle(); Utils.retryingFindAndClick(By.cssSelector("div[class='add2']")); Utils.waitForWindowToOpen(3, 5000); // 遍历所有窗口,切换至新窗口(自定义入筐窗口) Set handles = Utils.driver.getWindowHandles(); for (String windowHandle : handles) { if (!windowHandle.equalsIgnoreCase(mainWindow)) { Utils.driver.switchTo().window(windowHandle); System.out.println("切换到新窗口:" + windowHandle); } } Thread.sleep(5000); // 确认已经切换至自定义入筐窗口 String currentUrl = Utils.driver.getCurrentUrl(); System.out.println("currentUrl = " + currentUrl); boolean isLoginOk = currentUrl .indexOf("disinfectsystem/touchScreen/recycle/customIntoBasket.jsp?data") > 0; if (!isLoginOk) { } Assert.assertTrue(isLoginOk); } catch (Exception e) { e.printStackTrace(); Assert.fail(e.getMessage()); } } /** * 等待一段时间,直到页面的URL地址变为期望值 * * @param newUrl * 期望的url * @param seconds * 等待的超时时间 */ public static void waitUntilUrlChange(final String newUrl, int seconds) { Wait wait = new FluentWait(Utils.driver) .withTimeout(5000, TimeUnit.MILLISECONDS) .pollingEvery(250, TimeUnit.MILLISECONDS) .ignoring(NoSuchElementException.class); wait.until(new Function() { public Boolean apply(WebDriver d) { return d.getCurrentUrl().startsWith(newUrl); } }); } /** * 获取项目的配置信息,该配置信息合并了web项目的config.js与seleniumTest的settings.json配置信息 * * @param projectName * 项目名称 * @return 项目配置的json对象 */ public static JSONObject getProjectSettings(String projectName) { JSONObject jsonObj = null; ObjectMapper mapper = new ObjectMapper().configure( Feature.ALLOW_COMMENTS, true); mapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); mapper.configure(Feature.ALLOW_SINGLE_QUOTES, true); try { // 获取Selenium自动化测试的配置信息 InputStream instream1 = Utils.class.getClassLoader() .getResourceAsStream( "test_4_1/config/" + projectName + "/config.js"); Scanner scanner1 = new Scanner(instream1); String content = scanner1.useDelimiter("\\Z").next(); content = content.replaceAll("var sstsConfig = ", ""); jsonObj = mapper.readValue(content, JSONObject.class); // String testConfigFilename = seleniumTestConfigPath + "/" // + projectName + "/settings.json"; InputStream instream2 = Utils.class .getClassLoader() .getResourceAsStream( "test_4_1/config/" + projectName + "/settings.json"); Scanner scanner2 = new Scanner(instream2); String testConfigFileContent = scanner2.useDelimiter("\\Z").next(); JSONObject jsonObjTestSettings = mapper.readValue( testConfigFileContent, JSONObject.class); // 合并到jsonObj jsonObj.putAll(jsonObjTestSettings); instream1.close(); scanner1.close(); instream2.close(); scanner2.close(); } catch (IOException e) { e.printStackTrace(); } return jsonObj; } }