Index: ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/tools/TestUtils.java =================================================================== diff -u --- ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/tools/TestUtils.java (revision 0) +++ ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/tools/TestUtils.java (revision 27142) @@ -0,0 +1,86 @@ +/** + * + */ +package test.forgon.disinfectsystem.selenium3.tools; + +import java.util.Set; +import net.sf.json.JSONArray; +import net.sf.json.JSONObject; +import org.apache.commons.lang3.StringUtils; +import org.testng.Assert; +import org.junit.Test; +import com.forgon.disinfectsystem.entity.basedatamanager.toussedefinition.TousseDefinition; + +/** + * @author jeffli 2017年5月2日 下午2:51:52 + * + */ +public class TestUtils { + + /** + * 测试添加装配返回的器械包信息 + * */ + @Test + public void test_SeleniumRuntimeData_addPackingTousseInfo() { + JSONArray tousseArray = new JSONArray(); + { + JSONObject tousse = new JSONObject(); + tousse.put("tousseName", "器械包1"); + tousse.put("barcode", "010000001"); + tousse.put("tousseType", TousseDefinition.PACKAGE_TYPE_INSIDE); + tousseArray.add(tousse); + } + { + JSONObject tousse = new JSONObject(); + tousse.put("tousseName", "器械包2"); + tousse.put("barcode", "010000002"); + tousse.put("tousseType", TousseDefinition.PACKAGE_TYPE_INSIDE); + tousseArray.add(tousse); + } + { + JSONObject tousse = new JSONObject(); + tousse.put("tousseName", "敷料包1"); + tousse.put("barcode", "010100001"); + tousse.put("tousseType", TousseDefinition.PACKAGE_TYPE_DRESSING); + tousseArray.add(tousse); + } + { + JSONObject tousse = new JSONObject(); + tousse.put("tousseName", "敷料包2"); + tousse.put("barcode", "010100002"); + tousse.put("tousseType", TousseDefinition.PACKAGE_TYPE_DRESSING); + tousseArray.add(tousse); + } + { + JSONObject tousse = new JSONObject(); + tousse.put("tousseName", "外来器械包1"); + tousse.put("barcode", "010200001"); + tousse.put("tousseType", TousseDefinition.PACKAGE_TYPE_FOREIGN); + tousseArray.add(tousse); + } + { + JSONObject tousse = new JSONObject(); + tousse.put("tousseName", "外来器械包2"); + tousse.put("barcode", "010200002"); + tousse.put("tousseType", TousseDefinition.PACKAGE_TYPE_FOREIGN); + tousseArray.add(tousse); + } + Utils.getSeleniumRuntimeData().addPackingTousseInfo(tousseArray); + { + String barcode = Utils.getSeleniumRuntimeData().getInsideTousseBarcode(); + Assert.assertTrue(StringUtils.equals(barcode, "010000001") || StringUtils.equals(barcode, "010000002")); + Set barcodes = Utils.getSeleniumRuntimeData().getInsideTousseBarcodes(); + Assert.assertEquals(barcodes.size(), 2); + Assert.assertTrue(barcodes.contains("010000001")); + Assert.assertTrue(barcodes.contains("010000002")); + } + { + String barcode = Utils.getSeleniumRuntimeData().getDressingTousseBarcode(); + Assert.assertTrue(StringUtils.equals(barcode, "010100001") || StringUtils.equals(barcode, "010100002")); + Set barcodes = Utils.getSeleniumRuntimeData().getDressingTousseBarcodes(); + Assert.assertEquals(barcodes.size(), 2); + Assert.assertTrue(barcodes.contains("010100001")); + Assert.assertTrue(barcodes.contains("010100002")); + } + } +} Index: ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/recycle/TestForeignTousseApplicationRecycled.java =================================================================== diff -u --- ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/recycle/TestForeignTousseApplicationRecycled.java (revision 0) +++ ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/recycle/TestForeignTousseApplicationRecycled.java (revision 27142) @@ -0,0 +1,181 @@ +package test.forgon.disinfectsystem.selenium3.recycle; + +import static org.junit.Assert.fail; + +import java.util.List; +import net.sf.json.JSONArray; +import net.sf.json.JSONObject; +import org.apache.log4j.Logger; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.openqa.selenium.Alert; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.ExpectedConditions; +import org.openqa.selenium.support.ui.Wait; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; +import com.forgon.disinfectsystem.entity.basedatamanager.toussedefinition.TousseDefinition; +import com.forgon.disinfectsystem.entity.foreigntousseapplication.ForeignTousseApplication; +import test.forgon.constant.Constants; +import test.forgon.disinfectsystem.constants.ForeignTousseConstant; +import test.forgon.disinfectsystem.dataProvider.application.ForeignTousseAppDataProvider; +import test.forgon.disinfectsystem.dataProvider.tousseDefinition.MaterialDataProvider; +import test.forgon.disinfectsystem.selenium3.factory.WaitFactory; +import test.forgon.disinfectsystem.selenium3.login.Login; +import test.forgon.disinfectsystem.selenium3.tools.JSWaiter; +import test.forgon.disinfectsystem.selenium3.tools.Utils; + +/** + * 自动化测试用例:回收外来器械申请单 + * @author yuandongxiao + * + */ +@Transactional(propagation = Propagation.NEVER) +public class TestForeignTousseApplicationRecycled extends TestRecycled { + + protected Logger logger = Logger.getLogger(this.getClass());//日志记录 + private Login login = new Login();//登录 + private String SERVER_URL;//访问地址 + + /*********************************************************************************************** + * * + * 测试数据准备 * + * * + * *********************************************************************************************/ + + /** + * 基础数据准备 + */ + private void prepareData() { + initCSSDData(); + makeActiveUser("admin"); + } + + /** + * 构建外来器械申请单,物品如下: + * 测试外来器械包材料,数量5 + * 鼻窥,数量2 + * + * @return + */ + public JSONArray getForeignTousseTreeData() { + JSONObject material1 = MaterialDataProvider.createForeignMaterial(ForeignTousseConstant.测试外来器械包材料, 5); + JSONObject material2 = MaterialDataProvider.createForeignMaterial(ForeignTousseConstant.鼻窥, 2); + JSONArray materials = MaterialDataProvider.createMaterials(new JSONObject[]{material1, material2}); + TousseDefinition tousseDefinition_Test骨钩 = tousseDefinitionManager.getTousseDefinitionByName(Constants.TousseDefinitionName.Test骨钩); + JSONArray foreignTousseTreeDatas = ForeignTousseAppDataProvider.createForeignTousseTreeDatas(ForeignTousseAppDataProvider.createForeignTousseItem(tousseDefinition_Test骨钩), materials); + return foreignTousseTreeDatas; + } + + /** + * 创建外来器械申请单 + */ + public void createForeignTousseGoodRecyclingApplication() { + JSONArray foreignTousseTreeDatas = getForeignTousseTreeData(); + prepareData(); + ForeignTousseApplication foreignTousseApplication = ForeignTousseAppDataProvider.createForeignTousseApplication(); + //创建一张外来器械申请单 + foreignTousseApplicationManager.saveOrUpdate(foreignTousseApplication, foreignTousseTreeDatas.toString(), ForeignTousseApplication.ACTION_TYPE_ADD); + } + + /** + * 生成测试数据 + */ + public void initData() { + this.prepareData(); + this.createForeignTousseGoodRecyclingApplication(); + } + + /*********************************************************************************************** + * * + * 外来器械申请单自动化测试用例 * + * * + * *********************************************************************************************/ + + /** + * 1.准备回收模块的自动化测试数据 + * 2.初始化自动化设置 + */ + @Before + public void init(){ + this.initData(); + Utils.init(); + SERVER_URL = Utils.settings.get("服务器地址").toString(); + } + + /** + * 外来器械回收编辑材料数量 + * */ + @Test + public void recyle_Foreign_edit() { + logger.info("外来器械回收编辑材料数量开始"); + Utils.driver.get(SERVER_URL + "/?logonType=1080p"); + login.loginAction(); + Utils.waitUntilUrlContains("awaitForRecycleList.jsp", 15); + Utils.retryingFindAndClick(By.id("appTypeSelect")); + Utils.retryingFindAndClick(By.cssSelector("option[value='(待接收)外来器械包申请单']")); + WebElement element = Utils.retryingFind(By.id("awaitForRecycleTable")); + if (Utils.isFind(element)) { + Utils.driver.getWindowHandle(); + try { + //点击待回收表格第一行第一列 + Utils.retryingFindClickFirstCellOfTable(By.id("awaitForRecycleTable")); + waitUrlChange(); + //扫描清点人、回收人 + WebElement tousseItemTable = scanRecycleUserBarcode(); + Utils.retryingFindAndSendKeys(By.id("tousseItemTable"), + Utils.settings.getJSONObject("一级供应室清洗篮筐4").getString("条码")+ "\n"); + + dialogWindowClose(); + //点击器械包名称 + Utils.retryingFindAndClick(By.id("showTousseName0")); + Utils.driver.switchTo().defaultContent(); + Utils.retryingFindAndSwitchToFrame(By.tagName("iframe")); + Utils.retryingFindAndClick(By.id("amount1")); + + Utils.retryingFindAndSwitchToFrame(By.tagName("iframe")); + String a = (int) (Math.random() * 8 + 1) + ""; + Utils.retryingFindAndClick(By.id("button" + a)); + Utils.retryingFindAndClick(By.id("button5")); + Utils.retryingFindAndClick(By.id("okButton")); + + Utils.driver.switchTo().defaultContent(); + Utils.retryingFindAndSwitchToFrame(By.tagName("iframe")); + + Utils.retryingFindAndClick(By.id("ftDefinitionSubmitButton")); + Wait wait = WaitFactory.createDefaultWait(); + wait.until(ExpectedConditions.alertIsPresent()); + Alert alertBox = Utils.driver.switchTo().alert(); + alertBox.accept(); + + String recyclingFormWindowhandle = Utils.driver.getWindowHandle(); + Utils.driver.switchTo().window(recyclingFormWindowhandle); + tousseItemTable = Utils.retryingFind(By.id("tousseItemTable")); + List addButtons = tousseItemTable.findElements(By.cssSelector(".btn-a")); + for (WebElement addButton : addButtons) { + addButton.click(); + } + Utils.retryingFindAndClick(By.id("saveBtn")); + JSWaiter.waitUntilJQueryReady(); + Utils.waitUntilUrlContains( + SERVER_URL + "/disinfectsystem/touchScreen/recycle/awaitForRecycleList.jsp?resolution=1980",8); + logger.info("外来器械回收编辑材料数量完成"); + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + } + + /** + * 测试用例运行完毕之后 + */ + @After + public void after(){ + Utils.end(); + } + +} Index: ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/factory/WaitFactory.java =================================================================== diff -u --- ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/factory/WaitFactory.java (revision 0) +++ ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/factory/WaitFactory.java (revision 27142) @@ -0,0 +1,44 @@ +package test.forgon.disinfectsystem.selenium3.factory; + +import org.openqa.selenium.StaleElementReferenceException; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.support.ui.FluentWait; +import org.openqa.selenium.support.ui.Wait; +import test.forgon.disinfectsystem.selenium3.tools.Utils; +import java.util.NoSuchElementException; +import java.util.concurrent.TimeUnit; + +/** + * @author zhonghaowen + * @apiNote wait工厂 + * @since 2017-05-19 + */ +public class WaitFactory { + + /** + * 默认的wait对象 + * + * @return {@link Wait} + */ + public static Wait createDefaultWait() { + return createWait(15000, 600); + } + + /** + * 创建wai对象 + * + * @param withTimeout + * 超时的时间 + * @param pollingEvery + * 轮询的间隔 + * @return {@link Wait} + */ + public static Wait createWait(int withTimeout, int pollingEvery) { + return new FluentWait<>(Utils.driver) + .withTimeout(withTimeout, TimeUnit.MILLISECONDS) + .pollingEvery(pollingEvery, TimeUnit.MILLISECONDS) + .ignoring(NoSuchElementException.class) + .ignoring(StaleElementReferenceException.class) + .ignoring(NullPointerException.class); + } +} Index: ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/tools/Path.java =================================================================== diff -u --- ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/tools/Path.java (revision 0) +++ ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/tools/Path.java (revision 27142) @@ -0,0 +1,258 @@ +package test.forgon.disinfectsystem.selenium3.tools; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.CodeSource; +import java.security.ProtectionDomain; + +public class Path { + /** + * 获取一个类的class文件所在的绝对路径。 这个类可以是JDK自身的类,也可以是用户自定义的类,或者是第三方开发包里的类。 + * 只要是在本程序中可以被加载的类,都可以定位到它的class文件的绝对路径。 + * + * @param cls + * 一个对象的Class属性 + * @return 这个类的class文件位置的绝对路径。 如果没有这个类的定义,则返回null。 + */ + /** + * + * @param cls + * @return 某个类所在的文件夹的绝对路径 + * @throws IOException + */ + public static String getAbsoluteDirectoryPathOfClass(Class cls) + throws IOException { + String directoryPath = null; + String classPath = getPathFromClass(cls); + if (classPath.endsWith(".class")) { + int lastIndex = classPath.lastIndexOf('\\'); + if (lastIndex > 0) { + directoryPath = classPath.substring(0, lastIndex); + } + } + + return directoryPath; + } + + public static String getPathFromClass(Class cls) throws IOException { + String path = null; + if (cls == null) { + throw new NullPointerException(); + } + URL url = getClassLocationURL(cls); + if (url != null) { + path = getPath(url); + if ("jar".equalsIgnoreCase(url.getProtocol())) { + try { + path = getPath(new URL(path)); + } catch (MalformedURLException e) { + } + int location = path.indexOf("!/"); + if (location != -1) { + path = path.substring(0, location); + } + } + File file = new File(path); + path = file.getCanonicalPath(); + } + return path; + } + + /** + * 这个方法可以通过与某个类的class文件的相对路径来获取文件或目录的绝对路径。 通常在程序中很难定位某个相对路径,特别是在B/S应用中。 + * 通过这个方法,我们可以根据我们程序自身的类文件的位置来定位某个相对路径。 + * 比如:某个txt文件相对于程序的Test类文件的路径是../../resource/test.txt, + * 那么使用本方法Path.getFullPathRelateClass("../../resource/test.txt",Test.class) + * 得到的结果是txt文件的在系统中的绝对路径。 + * + * @param relatedPath + * 相对路径 + * @param cls + * 用来定位的类 + * @return 相对路径所对应的绝对路径 + * @throws IOException + * 因为本方法将查询文件系统,所以可能抛出IO异常 + */ + public static String getFullPathRelateClass(String relatedPath, Class cls) + throws IOException { + String path = null; + if (relatedPath == null) { + throw new NullPointerException(); + } + String clsPath = getPathFromClass(cls); + File clsFile = new File(clsPath); + String tempPath = clsFile.getParent() + File.separator + relatedPath; + File file = new File(tempPath); + path = file.getCanonicalPath(); + return path; + } + + /** + * 获取类的class文件位置的URL。这个方法是本类最基础的方法,供其它方法调用。 + */ + private static URL getClassLocationURL(final Class cls) { + if (cls == null) + throw new IllegalArgumentException("null input: cls"); + URL result = null; + final String clsAsResource = cls.getName().replace('.', '/').concat( + ".class"); + final ProtectionDomain pd = cls.getProtectionDomain(); + // java.lang.Class contract does not specify + // if 'pd' can ever be null; + // it is not the case for Sun's implementations, + // but guard against null + // just in case: + if (pd != null) { + final CodeSource cs = pd.getCodeSource(); + // 'cs' can be null depending on + // the classloader behavior: + if (cs != null) + result = cs.getLocation(); + if (result != null) { + // Convert a code source location into + // a full class file location + // for some common cases: + + if ("file".equals(result.getProtocol())) { + + try { + if (result.toExternalForm().endsWith(".jar") + || result.toExternalForm().endsWith(".zip")) + result = new URL("jar:".concat( + result.toExternalForm()).concat("!/") + .concat(clsAsResource)); + else if (new File(getFile(result)).isDirectory()) { + result = new URL(result, clsAsResource); + + } + } catch (MalformedURLException ignore) { + } + } + } + } + + if (result == null) { + // Try to find 'cls' definition as a resource; + // this is not + // document.d to be legal, but Sun's + // implementations seem to //allow this: + final ClassLoader clsLoader = cls.getClassLoader(); + result = clsLoader != null ? clsLoader.getResource(clsAsResource) + : ClassLoader.getSystemResource(clsAsResource); + } + return result; + } + + private static String getFile(URL url) { + if (url != null) { + return url.getFile().replaceAll("%20", " "); + } else { + return null; + } + } + + private static String getPath(URL url) { + if (url != null) { + return url.getPath().replaceAll("%20", " "); + } else { + return null; + } + } + +// public static String getContextPath(HttpServletRequest request) { +// String realContextPath = request.getSession().getServletContext() +// .getRealPath(""); +// try { +// realContextPath = java.net.URLDecoder.decode(realContextPath, +// "utf-8"); +// } catch (UnsupportedEncodingException e) { +// +// e.printStackTrace(); +// } +// return realContextPath; +// } + + // 得到JavaEE Web应用部署的根路径,即Tomcat的ROOT文件夹路径,不是WEB-INF文件夹 +// public static String getWebAppRoot() { +// String webAppRoot = ""; +// +// if (StringUtils.isBlank(webAppRoot)) { +// ClassLoader loader = Thread.currentThread().getContextClassLoader(); +// +// if (loader == null) { +// loader = Path.class.getClassLoader(); +// } +// String path = Path.class.getName().replace('.', '/') + ".class"; +// +// try { +// Enumeration e = loader.getResources(path); +// +// if (!e.hasMoreElements()) { +// try { +// throw new UnavailableException(path + " file not found"); +// } catch (UnavailableException e1) { +// e1.printStackTrace(); +// } +// } else { +// if (e.hasMoreElements()) { +// URL myClassURL = (URL) e.nextElement(); +// String myClassPath = URLDecoder.decode(myClassURL +// .getPath(), "UTF-8"); +// +// int webInfPosistion = myClassPath +// .lastIndexOf("/WEB-INF"); +// +// if (webInfPosistion > 0){ +// webAppRoot = myClassPath.substring(0, webInfPosistion); +// } +// else{ +//// webAppRoot = "C:/WorkspaceLunaSR2/forgon-ssts/ssts-web/src/main/webapp"; +// webAppRoot = "C:/WorkspaceLunaSR2/forgon-ssts-V4.1.0/ssts-web/src/main/webapp"; +// } +// } +// } +// +// } catch (IOException e2) { +// e2.printStackTrace(); +// } +// } +// if (webAppRoot.startsWith("file:/")){ +// webAppRoot = webAppRoot.substring("file:/".length()); +// } +// +// return webAppRoot; +// } + + public static void createDirectoryIfNeeded(String directoryName) + { + File theDir = new File(directoryName); + + // if the directory does not exist, create it + if (!theDir.exists()) + { + theDir.mkdir(); + } + } + /** + * 根据类型获取pda客户端的信息json文件路径 + * @param type clientForAndroid或者clientForWindowsMobile + * @return pda客户端的信息json文件路径 + */ +// public static String getMobileClientInfoFilePath(String type) { +// if(StringUtils.isBlank(type)){ +// type="clientForAndroid"; +// } +// String webInfoPath = getWebAppRoot(); +// String path = webInfoPath; +// if(webInfoPath != null){ +// int end = webInfoPath.indexOf("WEB-INF"); +// if( end != -1){ +// path = webInfoPath.substring(0,end - 1); +// } +// } +// return path + "/mobileClient/" + type + ".json"; +// } + +} Index: ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/recycle/TestComboApplicationRecycled.java =================================================================== diff -u --- ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/recycle/TestComboApplicationRecycled.java (revision 0) +++ ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/recycle/TestComboApplicationRecycled.java (revision 27142) @@ -0,0 +1,667 @@ +package test.forgon.disinfectsystem.selenium3.recycle; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.log4j.Logger; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.JavascriptExecutor; +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.Wait; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import com.forgon.disinfectsystem.entity.basedatamanager.toussedefinition.TousseDefinition; +import com.forgon.disinfectsystem.entity.invoicemanager.InvoicePlan; +import com.forgon.disinfectsystem.entity.recyclingapplication.RecyclingApplication; +import com.forgon.disinfectsystem.vo.TousseItemVo; + +import test.forgon.disinfectsystem.application.assertThat.RecyclingApplicationAssert; +import test.forgon.disinfectsystem.dataProvider.application.ApplicationDataProvider; +import test.forgon.disinfectsystem.selenium3.factory.WaitFactory; +import test.forgon.disinfectsystem.selenium3.login.Login; +import test.forgon.disinfectsystem.selenium3.tools.JSWaiter; +import test.forgon.disinfectsystem.selenium3.tools.Utils; + +/** + * 自动化测试用例:回收通用申请单 + * @author yuandongxiao + * + */ +@Transactional(propagation = Propagation.NEVER) +public class TestComboApplicationRecycled extends TestRecycled{ + + protected Logger logger = Logger.getLogger(this.getClass());//日志记录 + private Login login = new Login();//登录 + private String SERVER_URL;//访问地址 + + /*********************************************************************************************** + * * + * 测试数据准备 * + * * + * *********************************************************************************************/ + + /** + * 基础数据准备 + */ + private void prepareData() { + initCSSDData(); + initGoods(); + makeActiveUser("admin"); + } + + /** + * 申请物品的map(以名字-数量的形式) + */ + private final Map applyGoodsMap = Collections.unmodifiableMap(new LinkedHashMap() { + private static final long serialVersionUID = 8517084509264930675L; + + { + put("Test穿刺包", 2); + put("Test开口包", 2); + put("Test雾化器", 2); + } + }); + + /** + * 初始化需要的物品 + */ + private void initGoods() { + //修改"Test雾化器"的包定义:整包清洗->否 快速回收->是 + TousseDefinition tousseDefinition = tousseDefinitionManager.getTousseDefinitionByName("Test雾化器"); + tousseDefinition.setIsCleanedEntirely(TousseDefinition.STR_NO);//是否整包清洗 + tousseDefinition.setExpressRecycling(TousseDefinition.STR_YES);//是否快速回收 + tousseDefinitionManager.update(tousseDefinition); + + } + + + /** + * 把物品的map的名字和数量放到applyItemVos中 + * + * @param maps 物品的map + */ + private Collection appendGoodsMapToCollection(Map maps) { + Collection applyItemVos = new ArrayList<>(); + for (Map.Entry map : maps.entrySet()) { + appendToCollection(applyItemVos, map.getKey(), map.getValue(), TousseDefinition.PACKAGE_TYPE_INSIDE, "是", 0); + } + return applyItemVos; + } + + /** + * 创建通用申请单 + * + * @return + */ + public RecyclingApplication createComboTousseRecyclingApplication() { + Collection applyItemVos = this.appendGoodsMapToCollection(this.applyGoodsMap); + //通用申请单 + RecyclingApplication comboApplication = ApplicationDataProvider.createApplicationByParam(InvoicePlan.TYPE_COMBO_FORM); + recyclingApplicationManager.saveRecyclingApplication(comboApplication, applyItemVos, true); + return comboApplication; + } + + /** + * 申请Test雾化器,Test穿刺包,Test开口包,呼吸机,然后部分终止Test开口包 + */ + public void terminateTousseItemByIds() { + this.prepareData(); + RecyclingApplication recyclingApplication = this.createComboTousseRecyclingApplication(); + Long id = recyclingApplication.getId(); + assertNotNull(id); + RecyclingApplication result = this.getRecyclingApplicationById(id); + String assertGoodName = "Test开口包"; + Collection collect = RecyclingApplicationAssert.beforeTerminateTousseItemByIds(result, assertGoodName); + //终止Test开口包 + invoicePlanManager.checkTousseItemCanCancel(collect); + invoicePlanManager.terminateTousseItemByIds(collect, "测试部分终止"); + } + + /** + * 生成测试数据 + */ + public void initData() { + this.prepareData(); + this.createComboTousseRecyclingApplication(); + } + + + /*********************************************************************************************** + * * + * 通用申请单自动化测试用例 * + * * + * *********************************************************************************************/ + + /** + * 1.准备回收模块的自动化测试数据 + * 2.初始化自动化设置 + */ + @Before + public void init(){ + this.initData(); + Utils.init(); + Utils.setAndWriteConfigByNameAndValueForAutoTest("enbaleCheckToConfirm", true);//开启清点确认配置项 + SERVER_URL = Utils.settings.get("服务器地址").toString(); + } + + /** + * 部分回收 + */ + @Test + public void testPartialRecycling() { + logger.info("部分回收开始"); + Utils.driver.get(SERVER_URL + "/?logonType=1080p"); + login.loginAction(); + Utils.waitUntilUrlContains("awaitForRecycleList.jsp", 15); + Utils.retryingFindAndClick(By.id("appTypeSelect")); + Utils.retryingFindAndClick(By.cssSelector("option[value='通用申请单']")); + WebElement element = Utils.retryingFind(By.id("awaitForRecycleTable")); + if (Utils.isFind(element)) { + try { + // 输入临床科室条码,只显示临床科室的申请单 + Utils.retryingFindAndSendKeys(By.tagName("body"), Utils.settings + .getJSONObject("临床科室").getString("条码") + "\n"); + element = Utils.retryingFind(By.id("tousseItemTable")); + if (element == null) { + //点击待回收表格第一行第一列 + Utils.retryingFindClickFirstCellOfTable(By.id("awaitForRecycleTable")); + waitUrlChange(); + } else { + Utils.retryingFind(By.id("tousseItemTable")); + } + String recyclingFormWindowhandle = Utils.driver.getWindowHandle(); + Utils.driver.switchTo().window(recyclingFormWindowhandle); + + WebElement tousseItemTable = this.scanRecycleUserBarcode(); + tousseItemTable.sendKeys(Utils.settings.getJSONObject("一级供应室清洗篮筐5") + .getString("条码") + "\n"); + + dialogWindowClose(); + tousseItemTable = Utils.retryingFind(By.id("tousseItemTable")); + List addButtons = tousseItemTable.findElements(By + .cssSelector(".btn-a")); + //部分回收,只回收一个包 + addButtons.get(0).click(); + dialogClose(); + + Utils.retryingFindAndClick(By.id("saveBtn")); + dialogWindowClose(); + + //保存后,断言待回收列表、回收记录列表同时存在回收记录 + Utils.retryingFindAndClick(By.id("appTypeSelect")); + Utils.retryingFindAndClick(By + .cssSelector("option[value='通用申请单']")); + element = Utils.retryingFindForthCellOfTable(By + .id("awaitForRecycleTable")); + //待回收记录 + WebElement await = Utils.retryingFind(By.xpath("//*[@id='awaitForRecycleTable']//tr[1]/td[2]")); + String applyTime1 = await.getText(); + String style1 = await.getAttribute("style"); + //已回收记录 + WebElement record = Utils.retryingFind(By.xpath("//*[@id='recyclingRecordTable']//tr[1]/td[6]")); + WebElement _record = Utils.retryingFind(By.xpath("//*[@id='recyclingRecordTable']//tr[1]")); + String applyTime2 = record.getText(); + String style2 = _record.getAttribute("bgcolor"); + //通过申请时间断言这两条记录为同一申请单 + assertTrue("待回收列表第一条申请单不是部分回收申请单!","background-color: yellow;".equals(style1)); + assertTrue("回收记录列表第一条申请单不是部分回收申请单!","yellow".equals(style2)); + assertTrue("申请时间不一致,不是同一张申请单!",applyTime1.equals(applyTime2)); + logger.info("部分回收完成"); + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + }else { + JSWaiter.waitUntilJQueryReady(); + Utils.waitUntilUrlContains( + SERVER_URL + "/disinfectsystem/touchScreen/recycle/awaitForRecycleList.jsp?resolution=1980",8); + } + } + + /** + * 回收终止 + */ + @Test + public void testRecycleTermination(){ + logger.info("回收终止开始"); + Utils.driver.get(SERVER_URL + "/?logonType=1080p"); + login.loginAction(); + Utils.waitUntilUrlContains("awaitForRecycleList.jsp", 15); + Utils.retryingFindAndClick(By.id("appTypeSelect")); + Utils.retryingFindAndClick(By.cssSelector("option[value='通用申请单']")); + WebElement element = Utils.retryingFind(By.id("awaitForRecycleTable")); + if (Utils.isFind(element)) { + String recyleWin = Utils.driver.getWindowHandle(); + try { + // 输入临床科室条码,只显示临床科室的申请单 + Utils.retryingFindAndSendKeys(By.tagName("body"), Utils.settings.getJSONObject("临床科室").getString("条码") + "\n"); + element = Utils.retryingFind(By.id("tousseItemTable")); + if (element == null) { + Utils.retryingFindClickFirstCellOfTable(By.id("awaitForRecycleTable")); + waitUrlChange(); + } else { + Utils.retryingFind(By.id("tousseItemTable")); + } + //跳转到回收页面 + String recyclingFormWindowhandle = Utils.driver.getWindowHandle(); + Utils.driver.switchTo().window(recyclingFormWindowhandle); + //查找终止按钮 + WebElement webElement = Utils.retryingFind(By.id("btn-terminate")); + //若终止确认按钮存在则执行清点确认场景,否则断言终止测试用例 + assertNotNull(webElement); + //点击终止按钮 + webElement.click(); + //等待终止页面出现 + Utils.waitForWindowAmountEquals(2, 8000); + //获取所有窗口句柄 + Set windowHandles = Utils.driver.getWindowHandles(); + windowHandles.remove(recyclingFormWindowhandle); + //终止窗口 + String terminateWin = new ArrayList(windowHandles).get(0); + //跳转到终止窗口 + Utils.driver.switchTo().window(terminateWin); + logger.info("切换到模态窗口:{"+terminateWin+"}成功"); + //点击“其他”按钮 + Utils.retryingFindAndClick(By.id("other")); + //终止原因 + Utils.retryingFindAndSendKeys(By.id("tem"), "*****自动化测试回收终止*****"); + //确定 + Utils.retryingFindAndClick(By.id("confirm")); + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + Utils.driver.switchTo().window(recyleWin); + JSWaiter.waitUntilJQueryReady(); + Utils.waitUntilUrlContains( + SERVER_URL + "/disinfectsystem/touchScreen/recycle/awaitForRecycleList.jsp?resolution=1980",8); + logger.info("回收终止完成"); + } else { + JSWaiter.waitUntilJQueryReady(); + Utils.waitUntilUrlContains( + SERVER_URL + "/disinfectsystem/touchScreen/recycle/awaitForRecycleList.jsp?resolution=1980",8); + } + } + + /** + * 一级供应室回收部分终止的单 + * */ + @Test + public void testRecylePartiallyTerminatedApplication() { + //准备部分终止的申请单 + this.terminateTousseItemByIds(); + try { + logger.info(" 一级供应室回收部分终止的单开始"); + Utils.driver.get(SERVER_URL + "/?logonType=1080p"); + login.loginAction(); + Utils.waitUntilUrlContains("awaitForRecycleList.jsp", 15); + Utils.retryingFindAndClick(By.id("appTypeSelect")); + Utils.retryingFindAndClick(By.cssSelector("option[value='通用申请单']")); + String barcode = Utils.settings.getJSONObject("临床科室").getString("条码"); + // 输入临床科室条码,只显示临床科室的申请单 + Utils.retryingFindAndSendKeys(By.tagName("body"), barcode + "\n"); + Utils.retryingFindClickFirstCellOfTable(By.id("awaitForRecycleTable")); + Utils.waitForWindowAmountEquals(1, 8000); + Utils.switchToDefaultContent(); +// JSWaiter.waitUntilJQueryReady(); + Utils.jsClick(Utils.retryingFindAssure(By.xpath("html/body/div[2]/div[1]/form/div[1]/input"))); + Utils.isFind(Utils.retryingFindAssure(By.id("tousseItemTable"))); + + // 获取器械包的器械(材料)清单表格 + WebElement tousseItemTable = this.scanRecycleUserBarcode(); + tousseItemTable.sendKeys(Utils.settings.getJSONObject("一级供应室清洗篮筐4") + .getString("条码") + "\n"); + + dialogWindowClose(); + List Buttons = tousseItemTable.findElements(By + .xpath("//tbody/tr/td/a[contains(text(), '-')]")); + List Amounts = tousseItemTable.findElements(By + .cssSelector("input[name^='recycleAmount']")); + for (WebElement Amount : Amounts) { + int i = Integer.valueOf(Amount.getText()).intValue(); + if (i > 1) { + for (WebElement Button : Buttons) { + Button.click(); + WebElement element = Utils.retryingFind(By + .id("idBoxClose")); + if (Utils.isFind(element)) { + Utils.retryingFindAndClick(By.id("idBoxClose")); + } + continue; + } + } + continue; + } + tousseItemTable = Utils.retryingFind(By.id("tousseItemTable")); + List addButtons = tousseItemTable.findElements(By + .cssSelector(".btn-a")); + for (WebElement addButton : addButtons) { + addButton.click(); + } + Utils.retryingFindAndClick(By.cssSelector("input[value='保存']")); + Utils.waitUntilUrlContains(SERVER_URL+ "/disinfectsystem/touchScreen/recycle/awaitForRecycleList.jsp?resolution=1980",8); + logger.info("一级供应室回收部分终止的单完成"); + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + /** + * 一级供应室自定义入筐回收 + * */ + @Test + public void testRecyleCustom() { + logger.info("一级供应室自定义入筐回收开始:"); + Utils.driver.get(SERVER_URL + "/?logonType=1080p"); + login.loginAction(); + Utils.waitUntilUrlContains("awaitForRecycleList.jsp", 15); + Utils.retryingFindAndClick(By.id("appTypeSelect")); + Utils.retryingFindAndClick(By.cssSelector("option[value='通用申请单']")); + String basket = Utils.settings.getJSONObject("一级供应室清洗篮筐1").getString("条码"); + try { + Actions actions = new Actions(Utils.driver); + actions.moveToElement( + Utils.retryingFindAssure(By.id("awaitForRecycleTable"))) + .sendKeys(Utils.settings.getJSONObject("临床科室").getString("条码") + "\n").perform(); + WebElement element = Utils.tryFind(By.id("tousseItemTable")); + if (element == null) { + Utils.retryingFindClickFirstCellOfTable(By + .id("awaitForRecycleTable")); + waitUrlChange(); + } + this.scanRecycleUserBarcode(); + Utils.switchToDefaultContent(); + // 获得当前窗口 + String mainWindow = Utils.driver.getWindowHandle(); + // 直接调用webElement的click,避免js打开模态窗口后代码阻塞的问题 + if (Utils.isFind(Utils.retryingFind(By.id("customIntoBasketDiv")))) { + WebElement customIntoBasketDiv = Utils.driver.findElement(By.id("customIntoBasketDiv")) ; + String onclickScript = customIntoBasketDiv.getAttribute("onclick"); + JavascriptExecutor js = (JavascriptExecutor) Utils.driver; + js.executeScript(onclickScript); + Utils.waitForWindowAmountEquals(2, 8000); + // 获取所有窗口 + Set handles = Utils.driver.getWindowHandles(); + // 删除当前窗口 + handles.remove(mainWindow); + for (String windowHandle : handles) { + Utils.driver.switchTo().window(windowHandle); + } + } + WebElement recycleForm = Utils.retryingFind(By.id("tousseItemTable")); + + // 如果自定义入筐的页面打开不成功,跳转到了登录页面,则recycleForm取到的值为空,导致测试失败 + assertNotNull(recycleForm); + + if (Utils.isFind(recycleForm)) { + } else { + Utils.switchToDefaultContent(); + Utils.driver.navigate().back(); + } + actions.moveToElement(recycleForm).sendKeys(basket + "\n") + .perform(); + dialogWindowClose(); + // 判断自定义入筐扫完篮筐直到回调成功后才执行后面的入筐 + Wait wait = WaitFactory.createDefaultWait(); + wait.until(ExpectedConditions.attributeToBe( + By.id("seleniumResult"), "value", "1")); + Utils.retryingFindAndClick(By.className("btn-a")); + + basket = Utils.settings.getJSONObject("一级供应室清洗篮筐2").getString("条码"); + actions.moveToElement(recycleForm).sendKeys(basket + "\n") + .perform(); + dialogWindowClose(); + List addButtons = recycleForm.findElements(By + .className("btn-a")); + for (WebElement addButton : addButtons) { + Utils.jsClick(addButton); + dialogWindowClose(); + } + + Utils.retryingFindAndClickBySeleniumAPI(By.className("btn-e")); + Utils.waitForWindowAmountEquals(1, 20000); + // 从自定义入筐的窗口切换回主窗口 + for (String winHandle : Utils.driver.getWindowHandles()) { + Utils.driver.switchTo().window(winHandle); + } + JSWaiter.waitUntilJQueryReady(); + recycleForm = Utils.retryingFind(By.id("tousseItemTable")); + addButtons = recycleForm.findElements(By.className("btn-a")); + for (WebElement addButton : addButtons) { + Utils.jsClick(addButton); + element = Utils.retryingFind(By.id("idBoxClose")); + if (Utils.isFind(element)) { + Utils.jsClick(element); + } + } + JSWaiter.waitUntilJQueryReady(); + Utils.retryingFindAndClick(By.id("saveBtn")); + logger.info("一级供应室自定义入筐回收完成"); + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + + /** + * 快速回收 + * */ + @Test + public void testFastRecycling() { + logger.info("快速回收开始:"); + Utils.driver.get(SERVER_URL + "/?logonType=1080p"); + login.loginAction(); + Utils.waitUntilUrlContains("awaitForRecycleList.jsp", 15); + try { + Utils.retryingFindAndClick(By.id("quickRecycleImg")); + Utils.waitUntilUrlContains( + Utils.settings.get("服务器地址").toString() + + "/disinfectsystem/touchScreen/recycle/expressRecycleForTouchScreen.jsp?resolution=1980", + 15); + WebElement element = Utils.tryFind(By.id("tousseItemTable")); + if (Utils.isFind(element)) { + element.sendKeys(Utils.settings.getJSONObject("一级供应室清洗篮筐1") + .getString("条码") + "\n"); + dialogWindowClose(); + if (Utils.isFind(Utils.retryingFind(By.id("allIntoBasket")))) { + Utils.retryingFindAndClick(By.id("allIntoBasket")); + } else { + List addButtons = element.findElements(By + .className("btn-a")); + for (WebElement addButton : addButtons) { + Utils.jsClick(addButton); + } + } + Utils.retryingFindAndClick(By.className("btn-e")); + JSWaiter.waitUntilJQueryReady(); + } + Utils.driver.navigate().back(); + Utils.waitUntilUrlContains( + SERVER_URL+ "/disinfectsystem/touchScreen/recycle/awaitForRecycleList.jsp?resolution=1980",8); + logger.info("快速回收完成"); + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + /** + * 切换篮筐并丢失材料 + **/ + @Test + public void testRecyleChangeBasket() { + logger.info("切换篮筐并丢失材料开始:"); + Utils.driver.get(SERVER_URL + "/?logonType=1080p"); + login.loginAction(); + Utils.waitUntilUrlContains("awaitForRecycleList.jsp", 15); + Utils.retryingFindAndClick(By.id("addRecycleRecordBtn")); + try { + WebElement recycleForm = this.scanRecycleUserBarcode(); + // 扫描科室条码 + Utils.retryingFindAndSendKeys(By.id("depart"), Utils.settings + .getJSONObject("临床科室").getString("条码") + "\n"); + dialogWindowClose(); + Utils.retryingFindAndClick(By.id("add-bao")); + Utils.driver.switchTo().defaultContent(); + Utils.retryingFindAndSwitchToFrame(By.tagName("iframe")); + + Utils.retryingFindAndClick(By.id(Utils.settings.getJSONObject( + "回收查询").getString("按钮2"))); + + Utils.retryingFindAndClick(By.id(Utils.settings.getJSONObject( + "回收查询").getString("按钮2"))); + + Utils.retryingFindAndClick(By.linkText(Utils.settings + .getJSONObject("一级供应室器械包2").getString("名称"))); + + String recyclingFormWindowhandle = Utils.driver.getWindowHandle(); + Utils.driver.switchTo().window(recyclingFormWindowhandle); + + Utils.retryingFindAndSendKeys(By.id("tousseItemTable"), + Utils.settings.getJSONObject("一级供应室清洗篮筐1").getString("条码") + + "\n"); + + dialogWindowClose(); + recycleForm = Utils.retryingFind(By.id("tousseItemTable")); + List addButtons = recycleForm.findElements(By + .cssSelector(".btn-a")); + Utils.retryingFindAndClick(By + .xpath("//tbody/tr/td/a[contains(text(), '+')]")); + for (WebElement addButton : addButtons) { + addButton.click(); + + } + dialogWindowClose(); + Utils.retryingFindAndClick(By.id("saveBtn")); + Utils.retryingFind(By.id("recyclingRecordTable")); + Utils.retryingFindAndClick(By.id("tr0")); + Utils.retryingFindClickFirstCellOfTable(By.id("recyclingRecordTable")); + waitUrlChange(); + Utils.retryingFindAndClick(By.id("B"+ Utils.settings.getJSONObject("一级供应室清洗篮筐1").getString("条码"))); + dialogWindowClose(); + recycleForm = this.scanRecycleUserBarcode(); + dialogClose(); + recycleForm.sendKeys(Utils.settings.getJSONObject("一级供应室清洗篮筐4").getString("条码") + "\n"); + dialogWindowClose(); + recycleForm = Utils.retryingFind(By.id("tousseItemTable")); + List addButtons2 = recycleForm.findElements(By + .cssSelector(".btn-a")); + for (WebElement addButton : addButtons2) { + addButton.click(); + } + // 增加材料丢失 + Utils.retryingFindAndClick(By.id("recyclingErrorButton0")); + Utils.retryingFindAndSwitchToFrame(By.tagName("iframe")); + Utils.retryingFindAndClick(By.id("recyclingErrorTable")); + // 点击第1行的+号按钮 + Utils.retryingFindAndClick(By.id("addButton0")); + if (Utils.isFind(Utils.retryingFind(By.id("errorRemark")))) { + Utils.retryingFindAndSendKeys(By.id("errorRemark"), "丢失材料"); + } + Utils.retryingFindAndClick(By.id("errorSubmitButton")); + Utils.driver.switchTo().defaultContent(); + Utils.retryingFindAndClick(By.id("saveBtn")); + logger.info("切换篮筐并丢失材料完成"); + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + /** + * 清点确认 + * */ + @Test + public void testRecyleCheckAndConfirm() { + logger.info("清点确认开始:"); + Utils.driver.get(SERVER_URL + "/?logonType=1080p"); + login.loginAction(); + Utils.waitUntilUrlContains("awaitForRecycleList.jsp", 15); + try { + WebElement element = Utils.retryingFind(By.id("tousseItemTable")); + if (element == null) { + //点击待回收表格第一行第一列 + Utils.retryingFindClickFirstCellOfTable(By.id("awaitForRecycleTable")); + waitUrlChange(); + } else { + Utils.retryingFind(By.id("tousseItemTable")); + } + String recyclingFormWindowhandle = Utils.driver.getWindowHandle(); + Utils.driver.switchTo().window(recyclingFormWindowhandle); + + //查找清点确认按钮 + WebElement webElement = Utils.retryingFind(By.id("isCheckIntoTheBox")); + //若清点确认按钮存在则执行清点确认场景,否则点击返回按钮 + if(Utils.isFind(webElement)){ + //先将整包清洗的物品入筐后再做清点确认 + WebElement tousseItemTable = this.scanRecycleUserBarcode(); + tousseItemTable.sendKeys(Utils.settings.getJSONObject("一级供应室清洗篮筐1") + .getString("条码") + "\n"); + List addButtons = Utils.driver.findElements(By.cssSelector(".btn-a")); + for(int i=0;i wait = WaitFactory.createDefaultWait(); + * + * @author cherry 2016-07-18 + */ + +public class Login { + protected Logger logger = Logger.getLogger(this.getClass()); + + /** + * 初始化WebDriver对象 + */ + @Before + public void init() { + Utils.init(); + } + + /** + * 输入错误的用户名密码 + * */ + @Test + public void login_fail1() { + Utils.retryingFind(By.id("j_username_display")).clear(); + Utils.retryingFindAndSendKeys(By.id("j_username_display"), + Utils.settings.getJSONObject("一级供应室用户").getString("工号")); + Utils.retryingFind(By.id("j_password")).clear(); + Utils.retryingFindAndSendKeys(By.id("j_password"), "error"); + Utils.retryingFindAndClick(By.id("btn1")); + + Utils.waitUntilUrlChange(Utils.settings.get("服务器地址") + + "/logon.jsp?login_error=1", 5); + + assertEquals(Utils.settings.get("服务器地址") + "/logon.jsp?login_error=1", + Utils.driver.getCurrentUrl()); + } + + public boolean isAlertPresent() { + try { + Utils.driver.switchTo().alert(); + return true; + } + catch (NoAlertPresentException Ex) { + return false; + } + } + + /** + * 输入用户名不输入密码 + * */ + @Test + public void login_fail2() { + Utils.retryingFind(By.id("j_username_display")).clear(); + Utils.retryingFindAndSendKeys(By.id("j_username_display"), + Utils.settings.getJSONObject("一级供应室用户").getString("工号")); + + // 清空密码输入框,避免IE记住密码后自动填写密码 + Utils.retryingFind(By.id("j_password")).clear(); + + Utils.retryingFindAndClick(By.id("btn1")); + assertTrue(isAlertPresent()); + Alert alertBox = Utils.driver.switchTo().alert(); + assertEquals("请输入密码!", alertBox.getText()); + alertBox.accept(); + } + + /** + * 登陆成功 + * */ + @Test + public void login_success() { + try { + if (Utils.isFind(Utils.retryingFind(By.id("j_username_display")))) { + Utils.retryingFind(By.id("j_username_display")).clear(); + Utils.retryingFindAndClick(By.id("j_username_display")); + Utils.retryingFindAndSendKeys(By.id("j_username_display"), + Utils.settings.getJSONObject("一级供应室用户").getString("工号")); + Utils.retryingFind(By.id("j_password")).clear(); + Utils.retryingFindAndSendKeys(By.id("j_password"), + Utils.settings.getJSONObject("一级供应室用户").getString("密码")); + Utils.retryingFindAndClick(By.id("btn1")); + isLoginSuccess(); + } + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + /** + * 供应室用户登陆成功 + * */ + @Test + public void login_oneSupplyRoom() { + try { + loginAction(); + isLoginSuccess(); + + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + /** + * 登陆后退出 + * */ + @Test + public void login_Out() { + try { + JSWaiter.waitUntilJQueryReady(); + Utils.driver.switchTo().defaultContent(); + String currentwindowhandle = Utils.driver.getWindowHandle(); + Utils.driver.switchTo().window(currentwindowhandle); + if (Utils.isFind(Utils.retryingFind(By + .cssSelector("a[title='退出系统']")))) { + Utils.retryingFindAndClick(By.cssSelector("a[title='退出系统']")); + Utils.waitUntilUrlChange(Utils.settings.get("服务器地址").toString() + + "/logon.jsp", 15); + } else { + logger.info("找不到退出系统按钮"); + } + Utils.switchToDefaultContent(); + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + public void loginAction() { + JSWaiter.waitUntilJQueryReady(); + WebElement usernameElement = Utils.retryingFind(By + .id("j_username_display")); + + assertNotNull(usernameElement); + + if (Utils.isFind(usernameElement)) { + usernameElement.clear(); + Utils.retryingFindAndClick(By.id("j_username_display")); + Utils.retryingFindAndSendKeys(By.id("j_username_display"), + Utils.settings.getJSONObject("一级供应室用户").get("工号") + .toString()); + Utils.retryingFind(By.id("j_password")).clear(); + Utils.retryingFindAndSendKeys(By.id("j_password"), Utils.settings + .getJSONObject("一级供应室用户").get("密码").toString()); + Utils.retryingFindAndClick(By.id("btn1")); + } + } + + /** + * 判断登录是否成功 + */ + private void isLoginSuccess() { + + JSWaiter.waitUntilJQueryReady(); + logger.info("Page title is: " + Utils.driver.getTitle()); + if (Utils.isFind(Utils.retryingFind(By + .cssSelector("div[class='x-tool x-tool-close']")))) { + Utils.tryToCloseWarningWindow(); + } + JSWaiter.waitUntilJQueryReady(); + assertEquals(Utils.settings.get("服务器地址") + "/homepage/portalPage.jsp", + Utils.driver.getCurrentUrl()); + } + + /** + * 供应室用户登陆触摸屏清洗 + * */ + @Test + public void login_touch() { + try { + if (Utils.isFind(Utils.retryingFind(By.id("j_username_display")))) { + Utils.retryingFind(By.id("j_username_display")).clear(); + Utils.retryingFindAndClick(By.id("j_username_display")); + Utils.retryingFindAndSendKeys(By.id("j_username_display"), + Utils.settings.getJSONObject("一级供应室用户").get("工号") + .toString()); + Utils.retryingFind(By.id("j_password")).clear(); + Utils.retryingFindAndSendKeys(By.id("j_password"), + Utils.settings.getJSONObject("一级供应室用户").get("密码") + .toString()); + Utils.retryingFindAndClick(By.id("btn1")); + logger.info("Page title is: " + Utils.driver.getTitle()); + Utils.waitUntilUrlChange( + Utils.settings.get("服务器地址") + + "/disinfectsystem/washanddisinfectmanager/washanddisinfectrecord/washForTouchScreen.jsp?resolution=1980", + 10); + assertEquals( + Utils.settings.get("服务器地址") + + "/disinfectsystem/washanddisinfectmanager/washanddisinfectrecord/washForTouchScreen.jsp?resolution=1980", + Utils.driver.getCurrentUrl()); + } + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + + } + + /** + * 二级供应室用户登陆成功 + * */ + @Test + public void login_secondSupplyRoom() { + this.login_secondSupplyRoom(true); + } + + /** + * 二级供应室用户登录 + * + * @param isLoginToHomepage + * 是否登录到首页,如果为否,则登陆到触摸屏回收界面 + * + */ + public void login_secondSupplyRoom(boolean isLoginToHomepage) { + try { + if (Utils.isFind(Utils.retryingFind(By.id("j_username_display")))) { + Utils.retryingFind(By.id("j_username_display")).clear(); + Utils.retryingFindAndClick(By.id("j_username_display")); + Utils.retryingFindAndSendKeys(By.id("j_username_display"), + Utils.settings.getJSONObject("二级供应室用户").getString("工号")); + Utils.retryingFind(By.id("j_password")).clear(); + Utils.retryingFindAndSendKeys(By.id("j_password"), + Utils.settings.getJSONObject("二级供应室用户").getString("密码")); + Utils.retryingFindAndClick(By.id("btn1")); + + if (isLoginToHomepage) { + isLoginSuccess(); + Utils.tryToCloseWarningWindow(); + } else { + Utils.waitUntilUrlContains("awaitForRecycleList.jsp", 15); + } + JSWaiter.waitUntilJQueryReady(); + } + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + /** + * 临床用户登陆成功 + * */ + @Test + public void login_clinic() { + if (Utils.isFind(Utils.retryingFind(By.id("j_username_display")))) { + Utils.retryingFind(By.id("j_username_display")).clear(); + Utils.retryingFindAndClick(By.id("j_username_display")); + Utils.retryingFindAndSendKeys(By.id("j_username_display"), + Utils.settings.getJSONObject("临床科室用户").get("工号").toString()); + Utils.retryingFind(By.id("j_password")).clear(); + Utils.retryingFindAndSendKeys(By.id("j_password"), Utils.settings + .getJSONObject("临床科室用户").get("密码").toString()); + Utils.retryingFindAndClick(By.id("btn1")); + + isLoginSuccess(); + } + } + + /** + * 临床用户登陆无提示框 + * */ + @Test + public void login_clinicNoWarnig() { + try { + if (Utils.isFind(Utils.retryingFind(By.id("j_username_display")))) { + Utils.retryingFind(By.id("j_username_display")).clear(); + Utils.retryingFindAndClick(By.id("j_username_display")); + Utils.retryingFindAndSendKeys(By.id("j_username_display"), + Utils.settings.getJSONObject("临床科室用户").get("工号") + .toString()); + Utils.retryingFind(By.id("j_password")).clear(); + Utils.retryingFindAndSendKeys(By.id("j_password"), + Utils.settings.getJSONObject("临床科室用户").get("密码") + .toString()); + Utils.retryingFindAndClick(By.id("btn1")); + isLoginSuccess(); + + logger.info("Page title is: " + Utils.driver.getTitle()); + + JSWaiter.waitUntilJQueryReady(); + + assertEquals(Utils.settings.get("服务器地址") + + "/homepage/portalPage.jsp", + Utils.driver.getCurrentUrl()); + } + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + @After + public void after() { + Utils.driver.quit(); + try { + Runtime.getRuntime().exec("Taskkill /F /IM IEDriverServer.exe"); + Runtime.getRuntime().exec("Taskkill /F /IM iexplore.exe"); + Runtime.getRuntime().exec("Taskkill /F /IM iexplore.exe *32"); + } catch (IOException e1) { + e1.printStackTrace(); + } + } +} Index: ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/tools/LoginUtil.java =================================================================== diff -u --- ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/tools/LoginUtil.java (revision 0) +++ ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/tools/LoginUtil.java (revision 27142) @@ -0,0 +1,39 @@ +package test.forgon.disinfectsystem.selenium3.tools; + +import test.forgon.disinfectsystem.selenium3.login.Login; + +/** + * @author zhonghaowen + * @apiNote 登录工具类 + * @since 2017-05-05 + */ +public class LoginUtil { + public static Login login = new Login(); + + /** + * 先关闭当前浏览器,然后重新初始化 + */ + private static Login prepareInit() { + if (Utils.driver != null) { + Utils.driver.quit(); + } + login.init(); + return login; + } + + /** + * 用一级供应室登录,如果之前有登录,则会退出当前用户重新登录 + */ + public static void loginWithOneSupplyRoom() { + login.login_Out(); + login.login_oneSupplyRoom(); + } + + /** + * 用临床用户来登录,如果之前有登录,则会退出当前用户重新登录 + */ + public static void loginWithClinical() { + login.login_Out(); + login.login_clinicNoWarnig(); + } +} Index: ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/wash/AllTests.java =================================================================== diff -u --- ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/wash/AllTests.java (revision 0) +++ ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/wash/AllTests.java (revision 27142) @@ -0,0 +1,17 @@ +package test.forgon.disinfectsystem.selenium3.wash; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + + +/** + * 清洗消毒模块自动化测试用例 + * @author yuandongxiao + * + */ +@RunWith(Suite.class) +@SuiteClasses({ TestWashAndDisinfect.class}) +public class AllTests { + +} Index: ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/recycle/TestRecycled.java =================================================================== diff -u --- ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/recycle/TestRecycled.java (revision 0) +++ ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/recycle/TestRecycled.java (revision 27142) @@ -0,0 +1,98 @@ +package test.forgon.disinfectsystem.selenium3.recycle; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import net.sf.json.JSONObject; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.ExpectedConditions; +import org.openqa.selenium.support.ui.Wait; +import test.forgon.disinfectsystem.AbstractCSSDTest; +import test.forgon.disinfectsystem.selenium3.factory.WaitFactory; +import test.forgon.disinfectsystem.selenium3.tools.Utils; + +/** + * 自动化测试用例:回收模块父类 + * @author yuandongxiao + * + */ +public class TestRecycled extends AbstractCSSDTest{ + + /*********************************************************************************************** + * * + * 回收模块公共方法 * + * * + * *********************************************************************************************/ + + /** + * 跳转页面断言 + */ + public void waitUrlChange() { + Utils.waitUntilUrlContains( + Utils.settings.get("服务器地址").toString() + "/disinfectsystem/touchScreen/recycle/recycleForTouchScreen.jsp?resolution=1980",10); + String currentUrl = Utils.driver.getCurrentUrl(); + logger.info("currentUrl = " + currentUrl); + boolean isLoginOk = currentUrl.indexOf("disinfectsystem/touchScreen/recycle/recycleForTouchScreen.jsp?resolution=1980") > 0; + assertTrue(isLoginOk); + } + + /** + * 回收扫描回收人和清点人 + */ + public WebElement scanRecycleUserBarcode() { + WebElement table = null; + try { + // 扫描回收人条码 + if (Utils.isFind(Utils.retryingFindAssure(By.id("recyclingUser")))) { + table = this.scanBarcode(By.id("recyclingUser"), "回收人"); + this.logger.info("扫描回收人条码成功"); + } + // 扫描清点人条码 + if (Utils.isFind(Utils.retryingFindAssure(By.id("operator")))) { + table = this.scanBarcode(By.id("operator"), "清点人"); + this.logger.info("扫描清点人条码成功"); + } + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + return table; + } + + /** + * 扫描条码并断言扫描后的结果 + */ + private WebElement scanBarcode(By by, String user) { + JSONObject jsonObject = Utils.settings.getJSONObject(user); + WebElement webElement = Utils.retryingFindAndSendKeys(by, + jsonObject.getString("条码") + "\n"); + Wait wait = WaitFactory.createDefaultWait(); + // 断言回收人或者清洗人的姓名填写成功 + wait.until(ExpectedConditions.attributeContains(by, "value", + jsonObject.getString("姓名"))); + return webElement; + } + + /** + * 关闭弹窗 + */ + public void dialogWindowClose() { + WebElement button = Utils.tryFind(By.xpath("//button/span[contains(text(), '是')]")); + if (Utils.isFind(button)) { + button.click(); + } + } + + /** + * 关闭弹窗 + */ + public void dialogClose() { + WebElement button = Utils.tryFind(By.id("idBoxClose")); + if (Utils.isFind(button)) { + button.click(); + } + + } + +} Index: ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/recycle/TestDisinfectGoodApplicationRecycled.java =================================================================== diff -u --- ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/recycle/TestDisinfectGoodApplicationRecycled.java (revision 0) +++ ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/recycle/TestDisinfectGoodApplicationRecycled.java (revision 27142) @@ -0,0 +1,166 @@ +package test.forgon.disinfectsystem.selenium3.recycle; + +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import test.forgon.disinfectsystem.dataProvider.application.ApplicationDataProvider; +import test.forgon.disinfectsystem.selenium3.login.Login; +import test.forgon.disinfectsystem.selenium3.tools.Utils; + +import com.forgon.disinfectsystem.entity.basedatamanager.toussedefinition.TousseDefinition; +import com.forgon.disinfectsystem.entity.invoicemanager.InvoicePlan; +import com.forgon.disinfectsystem.entity.recyclingapplication.RecyclingApplication; +import com.forgon.disinfectsystem.vo.TousseItemVo; + +/** + * 自动化测试用例:回收消毒物品申请单 + * @author yuandongxiao + * + */ +@Transactional(propagation = Propagation.NEVER) +public class TestDisinfectGoodApplicationRecycled extends TestRecycled{ + protected Logger logger = LoggerFactory.getLogger(this.getClass());//日志记录 + private Login login = new Login();//登录 + private String SERVER_URL;//访问地址 + + /*********************************************************************************************** + * * + * 测试数据准备 * + * * + * *********************************************************************************************/ + + /** + * 要申请的物品 + */ + private final String[] applyGoodsNames = new String[]{"Test雾化器", "呼吸机"}; + + /** + * 基础数据准备 + */ + private void prepareData() { + initCSSDData(); + makeActiveUser("admin"); + } + + /** + * 创建消毒物品申请单 + * + */ + private RecyclingApplication createDisinfectGoodRecyclingApplication() { + Collection applyItemVos = new ArrayList<>(); + RecyclingApplication disinfectGoodApplication = ApplicationDataProvider.createApplicationByParam(InvoicePlan.TYPE_DISINFECT_GOODS_APPLICATION_FORM); + + for (int i = 0; i < applyGoodsNames.length; i++) { + appendToCollection2(applyItemVos, applyGoodsNames[i], 4, TousseDefinition.PACKAGE_TYPE_DISINFECTION, "是", 0, tousseDefinitionManager.getTousseDefinitionByName(applyGoodsNames[i]).getId()); + } + recyclingApplicationManager.saveRecyclingApplication(disinfectGoodApplication, applyItemVos, true); + return disinfectGoodApplication; + } + + /** + * 生成测试数据 + */ + public void initData() { + this.prepareData(); + this.createDisinfectGoodRecyclingApplication(); + } + + /*********************************************************************************************** + * * + * 消毒物品申请单自动化测试用例 * + * * + * *********************************************************************************************/ + + /** + * 1.准备回收模块的自动化测试数据 + * 2.初始化自动化设置 + */ + @Before + public void init(){ + this.initData(); + Utils.init(); + SERVER_URL = Utils.settings.get("服务器地址").toString(); + } + + + /** + * 修改消毒物品材料数量 + * */ + @Test + public void testRecycleChangeMaterialAmount() { + logger.info("修改消毒物品材料数量开始:"); + Utils.driver.get(SERVER_URL + "/?logonType=1080p"); + login.loginAction(); + Utils.waitUntilUrlContains("awaitForRecycleList.jsp", 15); + try { + // 输入临床科室条码,只显示临床科室的申请单 + Utils.retryingFindAndSendKeys(By.tagName("body"), Utils.settings + .getJSONObject("临床科室").getString("条码") + "\n"); + + Utils.retryingFindClickFirstCellOfTable(By.id("awaitForRecycleTable")); + + /** + * 修改材料数量 + */ + //点击呼吸机 + Utils.retryingFindAndClick(By.id("showTousseName0")); + Utils.driver.switchTo().defaultContent(); + Utils.retryingFindAndSwitchToFrame(By.tagName("iframe")); + WebElement materialItemsTable = Utils.retryingFind(By.id("materialItemsTable")); + List addButtonList = materialItemsTable.findElements(By.className("add")); + //点击增加材料按钮:“+” + for(int i=0;i addButtons = tousseItemTable.findElements(By + .cssSelector(".btn-a")); + //点击入筐按钮 + for(int i=0;i createInvoiceItems(RecyclingApplication recyclingApplication, TousseDefinition tousseDefinition, int applyAmount) { + List items = new ArrayList<>(); + TousseItem tousseItem = ApplicationDataProvider.createInvoiceItem(recyclingApplication, tousseDefinition, applyAmount); + //这个setEditAmount要加上,不然saveOrUpdateRecyclingApplication的时候,tousseItem不会有数据 + tousseItem.setEditAmount(applyAmount); + items.add(tousseItem); + return items; + } + + /** + * 创建自定义器械包申请单 + * + * @return {@link RecyclingApplication} + */ + private RecyclingApplication createCustomRecyclingApplication(String customTousseName, JSONArray materials) { + RecyclingApplication customRecyclingApplication = ApplicationDataProvider.createApplicationByParam(InvoicePlan.TYPE_CUSTOM_TOUSSE_APPLIACTION_FORM); + TousseDefinition tousseDefinition = TousseDefinitionDataProvider.createCustomGood(customTousseName, false); + // String materialDefinitionConfigResult = "[{\"name\":\"Test镊子\",\"tousseType\":\"器械\",\"count\":6},{\"name\":\"Test钳子\",\"tousseType\":\"器械\",\"count\":4}]"; + tousseDefinitionManager.saveTousseDefinition(tousseDefinition, materials.toString(), null); + List items = this.createInvoiceItems(customRecyclingApplication, tousseDefinition, 2); + customRecyclingApplication.setApplicationItems(items); + recyclingApplicationManager.saveOrUpdateRecyclingApplication(customRecyclingApplication, true); + //新建一张器械包申请单 + return customRecyclingApplication; + } + + /** + * 生成测试数据 + */ + public void initData() { + JSONArray materials = customTousseTreeDataProvider(); + this.prepareData(); + //创建自定义器械包申请单 + this.createCustomRecyclingApplication(this.customGoodName, materials); + } + + /*********************************************************************************************** + * * + * 自定义器械包申请单自动化测试用例 * + * * + * *********************************************************************************************/ + + /** + * 1.准备回收模块的自动化测试数据 + * 2.初始化自动化设置 + */ + @Before + public void init(){ + this.initData(); + Utils.init(); + SERVER_URL = Utils.settings.get("服务器地址").toString(); + } + + /** + * 回收自定义器械包申请单 + */ + @Test + public void testCustomApplicationRecycling(){ + logger.info("回收自定义器械包申请单开始:"); + Utils.driver.get(SERVER_URL + "/?logonType=1080p"); + login.loginAction(); + Utils.waitUntilUrlContains("awaitForRecycleList.jsp", 15); + try { + WebElement element = Utils.retryingFind(By.id("tousseItemTable")); + if (element == null) { + //点击待回收表格第一行第一列 + Utils.retryingFindClickFirstCellOfTable(By.id("awaitForRecycleTable")); + waitUrlChange(); + } else { + Utils.retryingFind(By.id("tousseItemTable")); + } + String recyclingFormWindowhandle = Utils.driver.getWindowHandle(); + Utils.driver.switchTo().window(recyclingFormWindowhandle); + WebElement tousseItemTable = this.scanRecycleUserBarcode(); + tousseItemTable.sendKeys(Utils.settings.getJSONObject("一级供应室清洗篮筐4").getString("条码") + "\n"); + dialogWindowClose(); + tousseItemTable = Utils.retryingFind(By.id("tousseItemTable")); + List addButtons = tousseItemTable.findElements(By.cssSelector(".btn-a")); + for (WebElement addButton : addButtons) { + addButton.click(); + } + Utils.retryingFindAndClick(By.id("saveBtn")); + logger.info("回收自定义器械包申请单完成"); + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + /** + * 测试用例运行完毕之后 + */ + @After + public void after(){ + Utils.end(); + } +} Index: ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/tools/SeleniumRuntimeData.java =================================================================== diff -u --- ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/tools/SeleniumRuntimeData.java (revision 0) +++ ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/tools/SeleniumRuntimeData.java (revision 27142) @@ -0,0 +1,185 @@ +/** + * + */ +package test.forgon.disinfectsystem.selenium3.tools; + +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import net.sf.json.JSONArray; +import net.sf.json.JSONObject; +import org.apache.commons.lang3.StringUtils; +import com.forgon.disinfectsystem.entity.basedatamanager.toussedefinition.TousseDefinition; + +/** + * @author jeffli 2017年5月2日 下午2:01:36 + * + */ +public class SeleniumRuntimeData { + + private List tousseInfo = new LinkedList(); + + public void addPackingTousseInfo(JSONArray tousseArray) { + if (tousseArray == null) { + return; + } + for (int i = 0; i < tousseArray.size(); i++) { + JSONObject tousse = tousseArray.getJSONObject(i); + tousseInfo.add(tousse); + } + } + + /** + * 获取普通器械包条码 + * + */ + public String getInsideTousseBarcode() { + Set barcodeSet = getInsideTousseBarcodes(); + if (barcodeSet.isEmpty()) { + return null; + } + return barcodeSet.iterator().next(); + } + + /** + * 获取普通器械包条码 + * + */ + public Set getInsideTousseBarcodes() { + return getTousseBarcodesByTousseType(TousseDefinition.PACKAGE_TYPE_INSIDE); + } + + /** + * 获取敷料包条码 + * + */ + public String getDressingTousseBarcode() { + Set barcodeSet = getDressingTousseBarcodes(); + if (barcodeSet.isEmpty()) { + return null; + } + return barcodeSet.iterator().next(); + } + + /** + * 获取敷料包条码 + * + */ + public Set getDressingTousseBarcodes() { + return getTousseBarcodesByTousseType(TousseDefinition.PACKAGE_TYPE_DRESSING); + } + + /** + * 获取消毒物品条码 + * + */ + public String getDisinfectionTousseBarcode() { + Set barcodeSet = getDisinfectionTousseBarcodes(); + if (barcodeSet.isEmpty()) { + return null; + } + return barcodeSet.iterator().next(); + } + + /** + * 获取消毒物品条码 + * + */ + public Set getDisinfectionTousseBarcodes() { + return getTousseBarcodesByTousseType(TousseDefinition.PACKAGE_TYPE_DISINFECTION); + } + /** + * 获取消毒物品固定条码 + * + */ + public String getDisinfectionTousseFixedBarcode() { + for (JSONObject jsonObject : tousseInfo) { + String tousseType = jsonObject.optString("tousseType"); + String isTraceable = jsonObject.optString("isTraceable"); + if (StringUtils.equals(tousseType, TousseDefinition.PACKAGE_TYPE_DISINFECTION) && StringUtils.equals(isTraceable, TousseDefinition.STR_NO)) { + String barcode = jsonObject.optString("barcode"); + return barcode; + } + } + return null; + } + + /** + * 获取外来器械条码 + * + */ + public String getForeignTousseBarcode() { + Set barcodeSet = getForeignTousseBarcodes(); + if (barcodeSet.isEmpty()) { + return null; + } + return barcodeSet.iterator().next(); + } + + /** + * 获取外来器械条码 + * + */ + public Set getForeignTousseBarcodes() { + Set pTousseTypes = new HashSet(); + pTousseTypes.add(TousseDefinition.PACKAGE_TYPE_FOREIGN); + pTousseTypes.add(TousseDefinition.PACKAGE_TYPE_SPLIT); + return getTousseBarcodesByTousseType(pTousseTypes); + } + + /** + * 获取外部代理灭菌条码 + * + */ + public String getForeignproxyTousseBarcode() { + Set barcodeSet = getForeignproxyTousseBarcodes(); + if (barcodeSet.isEmpty()) { + return null; + } + return barcodeSet.iterator().next(); + } + + /** + * 获取外部代理灭菌条码 + * + */ + public Set getForeignproxyTousseBarcodes() { + return getTousseBarcodesByTousseType(TousseDefinition.PACKAGE_TYPE_FOREIGNPROXY); + } + + /** + * 获取器械包条码 + * + */ + public Set getTousseBarcodesByTousseType(String pTousseType) { + Set barcodeSet = new HashSet(); + for (JSONObject jsonObject : tousseInfo) { + String tousseType = jsonObject.optString("tousseType"); + if (StringUtils.equals(tousseType, pTousseType)) { + String barcode = jsonObject.optString("barcode"); + if (StringUtils.isNotBlank(barcode)) { + barcodeSet.add(barcode); + } + } + } + return barcodeSet; + } + /** + * 获取器械包条码 + * + */ + public Set getTousseBarcodesByTousseType(Set pTousseTypes) { + Set barcodeSet = new HashSet(); + for (JSONObject jsonObject : tousseInfo) { + String tousseType = jsonObject.optString("tousseType"); + if (pTousseTypes.contains(tousseType)) { + String barcode = jsonObject.optString("barcode"); + if (StringUtils.isNotBlank(barcode)) { + barcodeSet.add(barcode); + } + } + } + return barcodeSet; + } +} Index: ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/AllTests.java =================================================================== diff -u --- ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/AllTests.java (revision 0) +++ ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/AllTests.java (revision 27142) @@ -0,0 +1,17 @@ +package test.forgon.disinfectsystem.selenium3; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +/** + * 所有自动化测试用例 + * @author yuandongxiao + * + */ +@RunWith(Suite.class) +@SuiteClasses({ test.forgon.disinfectsystem.selenium3.recycle.AllTests.class, + test.forgon.disinfectsystem.selenium3.wash.AllTests.class}) +public class AllTests { + +} Index: ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/wash/TestWashAndDisinfect.java =================================================================== diff -u --- ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/wash/TestWashAndDisinfect.java (revision 0) +++ ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/wash/TestWashAndDisinfect.java (revision 27142) @@ -0,0 +1,651 @@ +package test.forgon.disinfectsystem.selenium3.wash; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.Map; + +import net.sf.json.JSONArray; +import net.sf.json.JSONObject; + +import org.apache.log4j.Logger; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.Keys; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.ExpectedConditions; +import org.openqa.selenium.support.ui.Wait; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; +import org.testng.AssertJUnit; + +import com.forgon.disinfectsystem.entity.basedatamanager.toussedefinition.TousseDefinition; +import com.forgon.disinfectsystem.entity.invoicemanager.InvoicePlan; +import com.forgon.disinfectsystem.entity.recyclingapplication.RecyclingApplication; +import com.forgon.disinfectsystem.entity.recyclingrecord.RecyclingRecord; +import com.forgon.disinfectsystem.vo.TousseItemVo; + +import test.forgon.disinfectsystem.AbstractCSSDTest; +import test.forgon.disinfectsystem.dataProvider.application.ApplicationDataProvider; +import test.forgon.disinfectsystem.selenium3.factory.WaitFactory; +import test.forgon.disinfectsystem.selenium3.tools.JSWaiter; +import test.forgon.disinfectsystem.selenium3.login.Login; +import test.forgon.disinfectsystem.selenium3.tools.Utils; + +/** + * 自动化测试用例:清洗消毒模块 + * @author yuandongxiao + * + */ +@Transactional(propagation = Propagation.NEVER) +public class TestWashAndDisinfect extends AbstractCSSDTest{ + protected Logger logger = Logger.getLogger(this.getClass());//日志记录 + private Login login = new Login();//登录 + private String SERVER_URL;//访问地址 + + /*********************************************************************************************** + * * + * 测试数据准备 * + * * + ***********************************************************************************************/ + + /** + * 基础数据准备 + */ + private void prepareData() { + initCSSDData(); + makeActiveUser("admin"); + } + + /** + * 申请物品的map(以名字-数量的形式) + */ + private final Map applyGoodsMap = Collections.unmodifiableMap(new LinkedHashMap() { + private static final long serialVersionUID = 8517084509264930675L; + + { + put("Test穿刺包", 2); + put("Test开口包", 2); + put("Test雾化器", 2); + } + }); + + /** + * 把物品的map的名字和数量放到applyItemVos中 + * + * @param maps 物品的map + */ + private Collection appendGoodsMapToCollection(Map maps) { + Collection applyItemVos = new ArrayList<>(); + for (Map.Entry map : maps.entrySet()) { + appendToCollection(applyItemVos, map.getKey(), map.getValue(), TousseDefinition.PACKAGE_TYPE_INSIDE, "是", 0); + } + return applyItemVos; + } + + /** + * 创建通用申请单 + * @return + */ + public RecyclingApplication createComboTousseRecyclingApplication() { + Collection applyItemVos = this.appendGoodsMapToCollection(this.applyGoodsMap); + //通用申请单 + RecyclingApplication comboApplication = ApplicationDataProvider.createApplicationByParam(InvoicePlan.TYPE_COMBO_FORM); + recyclingApplicationManager.saveRecyclingApplication(comboApplication, applyItemVos, true); + return comboApplication; + } + + /** + * 调用回收 + * @param application + */ + public void recycledComboTousseRecyclingApplication(RecyclingApplication application){ + + //调用回收 + RecyclingRecord recyclingRecord = new RecyclingRecord(); + recyclingRecord.setRecyclingApplication(application); + recyclingRecord.setDepart(application.getDepart()); + recyclingRecord.setDepartCode(application.getDepartCoding()); + recyclingRecord.setOrgUnitCoding(application.getDepartCoding()); + recyclingRecord.setOperator(application.getApplicant()); + recyclingRecord.setRecyclingTime(new Date()); + recyclingRecord.setRecyclingUser(application.getApplicant()); + recyclingRecord.setStatus(RecyclingRecord.STATUS_SAVED); + + /** + TousseDefinition Test穿刺包 = tousseDefinitionManager.getTousseDefinitionByNameTypeAndAPPID("Test穿刺包", TousseDefinition.PACKAGE_TYPE_INSIDE, application.getId().toString()); + TousseDefinition Test开口包 = tousseDefinitionManager.getTousseDefinitionByNameTypeAndAPPID("Test开口包", TousseDefinition.PACKAGE_TYPE_INSIDE, application.getId().toString()); + TousseDefinition Test雾化器 = tousseDefinitionManager.getTousseDefinitionByNameTypeAndAPPID("Test雾化器", TousseDefinition.PACKAGE_TYPE_DISINFECTION, application.getId().toString()); + */ + + TousseDefinition Test穿刺包 = tousseDefinitionManager.getTousseDefinitionByName("Test穿刺包"); + TousseDefinition Test开口包 = tousseDefinitionManager.getTousseDefinitionByName("Test开口包"); + TousseDefinition Test雾化器 = tousseDefinitionManager.getTousseDefinitionByName("Test雾化器"); + + JSONArray jarr = new JSONArray(); + JSONObject jobj1 = new JSONObject(); + JSONObject jobj2 = new JSONObject(); + JSONObject jobj3 = new JSONObject(); + JSONObject jsonParam2 = new JSONObject(); + + jobj1.put("basketBarcode", "019000001"); + jobj1.put("basketId", 0); + jobj1.put("tousseName", "Test穿刺包"); + jobj1.put("tousseDefinitionID", Test穿刺包.getId()); + jobj1.put("amount", 2); + jobj1.put("itemType", "器械包"); + jobj1.put("tousseNameForMaterial", ""); + jobj1.put("idCardBarcode", ""); + jobj1.put("tousseAmountForMaterial", 1); + jarr.add(jobj1); + + jobj2.put("basketBarcode", "019000001"); + jobj2.put("basketId", 0); + jobj2.put("tousseName", "Test开口包"); + jobj2.put("tousseDefinitionID", Test开口包.getId()); + jobj2.put("amount", 2); + jobj2.put("itemType", "器械包"); + jobj2.put("tousseNameForMaterial", ""); + jobj2.put("idCardBarcode", ""); + jobj2.put("tousseAmountForMaterial", 1); + jarr.add(jobj2); + + jobj3.put("basketBarcode", "019000001"); + jobj3.put("basketId", 0); + jobj3.put("tousseName", "Test雾化器"); + jobj3.put("tousseDefinitionID", Test雾化器.getId()); + jobj3.put("amount", 2); + jobj3.put("itemType", "器械包"); + jobj3.put("tousseNameForMaterial", ""); + jobj3.put("idCardBarcode", ""); + jobj3.put("tousseAmountForMaterial", 1); + jarr.add(jobj3); + + jsonParam2.put("tousseJson", jarr); + jsonParam2.put("errors", ""); + jsonParam2.put("damages", ""); + jsonParam2.put("confirmation", false); + String jsonParam = jsonParam2.toString(); + + //保存回收申请单 + recyclingRecordManager.save(recyclingRecord,JSONObject.fromObject(jsonParam)); + //更新申请单记录(此处不完善,没有生成已回收记录,但不影响清洗模块自动化测试用例运行) + application.setRecyclingStatus("已回收"); + objectDao.saveOrUpdate(application); + + } + + /** + * 生成测试数据 + */ + public void initData() { + this.prepareData(); + RecyclingApplication application = this.createComboTousseRecyclingApplication(); + this.recycledComboTousseRecyclingApplication(application); + } + + + /*********************************************************************************************** + * * + * 清洗模块自动化测试用例 * + * * + * *********************************************************************************************/ + + /** + * 1.准备清洗模块的自动化测试数据 + * 2.初始化自动化设置 + */ + @Before + public void init(){ + this.initData(); + Utils.init(); + SERVER_URL = Utils.settings.get("服务器地址").toString(); + } + + /** + * PC端添加清洗消毒记录 + */ + @Test + public void washAndDisinfectForPC() { + try { + login.loginAction(); + Utils.retryingFindAndClick(By.id("washAndDisinfect")); + for (String winHandle : Utils.driver.getWindowHandles()) { + Utils.driver.switchTo().window(winHandle); + } + Wait wait = WaitFactory.createDefaultWait(); + Utils.retryingFindAndSwitchToFrame(By.id("iframe_washAndDisinfect")); + Utils.retryingFindAndClick(By + .xpath("//button[contains(text(), '添加')]")); + + Utils.driver.switchTo().defaultContent(); + String currentwindowhandle = Utils.driver.getWindowHandle(); + Utils.driver.switchTo().window(currentwindowhandle); + + wait.until(ExpectedConditions.attributeToBe( + Utils.driver.findElement(By.id("washLoadResult")), "value", + "1")); + + Utils.retryingFindAndSendKeys(By.id("inputText"), Utils.settings + .getJSONObject("一级供应室清洗机").getString("清洗机条码") + "\n"); + wait.until(ExpectedConditions.attributeToBeNotEmpty( + Utils.driver.findElement(By.id("disinfectIdentification")), + "value")); + Utils.retryingFindAndSendKeys(By.id("inputText"), Utils.settings + .getJSONObject("一级供应室清洗机").getString("清洗程序条码") + "\n"); + wait.until(ExpectedConditions.attributeToBeNotEmpty( + Utils.driver.findElement(By.id("disinfectProgram")), + "value")); + Utils.retryingFindAndSendKeys(By.id("inputText"), Utils.settings + .getJSONObject("一级供应室审核人").getString("条码") + "\n"); + wait.until(ExpectedConditions.attributeToBeNotEmpty( + Utils.driver.findElement(By.id("personInCharge")), "value")); + Utils.retryingFindAndSendKeys(By.id("inputText"), Utils.settings + .getJSONObject("一级供应室清洗篮筐1").getString("条码") + "\n"); + Utils.retryingFindAndClick(By.id("saveBtn")); + JSWaiter.waitUntilJQueryReady(); + // 定位回来 + Utils.retryingFindAndSwitchToFrame(By.id("iframe_washAndDisinfect")); + // 需要判断表单提交成功且返回正常后才能结束,否则就将不会提交到后台 + if (Utils.isFind(Utils.retryingFind(By.id("washSaveSubmitResult")))) { + wait.until(ExpectedConditions.attributeToBe( + Utils.driver.findElement(By.id("washSaveSubmitResult")), + "value", "1")); + } + + } catch (Exception e) { + e.printStackTrace(); + AssertJUnit.fail(e.getMessage()); + } + } + + /** + * 触摸屏清洗,清洗前,清洗机需要设置为不需要清洗确认 + */ + @Test + public void washAndDisinfectForTouchScreen() { + try { + // 触摸屏清洗服务的地址为相对地址,访问时必须加上服务器地址 + String touchScreenURL = Utils.settings.get("触摸屏清洗服务地址").toString(); + if (!touchScreenURL.startsWith("/")) { + touchScreenURL = "/" + touchScreenURL; + } + Utils.driver.get(SERVER_URL + touchScreenURL); + login.login_touch(); + Utils.retryingFindAndSendKeys(By.id("personInCharge"), + Utils.settings.getJSONObject("一级供应室用户").getString("条码") + + "\n"); + + Utils.retryingFindAndSendKeys(By.id("disinfectIdentification"), + Utils.settings.getJSONObject("一级供应室清洗机").getString("清洗机条码") + + "\n"); + + Utils.retryingFindAndSendKeys(By.id("disinfectProgram"), + Utils.settings.getJSONObject("一级供应室清洗机") + .getString("清洗程序条码") + "\n"); + + Utils.retryingFindAndSendKeys(By.className("add-form"), + "888888888" + "\n"); + + Utils.retryingFindAndSendKeys(By.id("personInCharge"), + Utils.settings.getJSONObject("一级供应室用户").getString("条码") + + "\n"); + + Utils.retryingFindAndSendKeys(By.id("disinfectIdentification"), + Utils.settings.getJSONObject("一级供应室清洗机").getString("清洗机条码") + + "\n"); + + Utils.retryingFindAndSendKeys(By.id("disinfectProgram"), + Utils.settings.getJSONObject("一级供应室清洗机") + .getString("清洗程序条码") + "\n"); + + Utils.retryingFindAndSendKeys(By.className("add-form"), + Utils.settings.getJSONObject("一级供应室清洗篮筐1").getString("条码") + + "\n"); + dialogWindowClose(); + Utils.retryingFindAndSendKeys(By.className("add-form"), + "999999999" + "\n"); + + } catch (Exception e) { + e.printStackTrace(); + AssertJUnit.fail(e.getMessage()); + } + } + + /** + * 清洗并添加材料 + */ + @Test + public void washAddMaterial() { + try { + login.loginAction(); + Utils.retryingFindAndClick(By.id("washAndDisinfect")); + for (String winHandle : Utils.driver.getWindowHandles()) { + Utils.driver.switchTo().window(winHandle); + } + Wait wait = WaitFactory.createDefaultWait(); + Utils.retryingFindAndSwitchToFrame(By.id("iframe_washAndDisinfect")); + Utils.retryingFindAndClick(By + .xpath("//button[contains(text(), '添加')]")); + + Utils.driver.switchTo().defaultContent(); + String currentwindowhandle = Utils.driver.getWindowHandle(); + Utils.driver.switchTo().window(currentwindowhandle); + + wait.until(ExpectedConditions.attributeToBe( + Utils.driver.findElement(By.id("washLoadResult")), "value","1")); + + Utils.retryingFindAndSendKeys(By.id("inputText"), Utils.settings + .getJSONObject("一级供应室清洗机").getString("清洗机条码") + "\n"); + wait.until(ExpectedConditions.attributeToBeNotEmpty( + Utils.driver.findElement(By.id("disinfectIdentification")), + "value")); + Utils.retryingFindAndSendKeys(By.id("inputText"), Utils.settings + .getJSONObject("一级供应室清洗机").getString("清洗程序条码") + "\n"); + wait.until(ExpectedConditions.attributeToBeNotEmpty( + Utils.driver.findElement(By.id("disinfectProgram")), + "value")); + Utils.retryingFindAndSendKeys(By.id("inputText"), Utils.settings + .getJSONObject("一级供应室审核人").getString("条码") + "\n"); + wait.until(ExpectedConditions.attributeToBeNotEmpty( + Utils.driver.findElement(By.id("personInCharge")), "value")); + Utils.retryingFindAndSendKeys(By.id("inputText"), Utils.settings + .getJSONObject("一级供应室清洗篮筐1").getString("条码") + "\n"); + addMaterial(); + } catch (Exception e) { + e.printStackTrace(); + AssertJUnit.fail(e.getMessage()); + } + } + + /** + * 清洗添加材料 + */ + public void addMaterial() { + try { + Utils.retryingFindAndSendKeys(By.id("materialName"), Keys.DOWN); + Utils.retryingFindAndClick(By.xpath("//div[contains(text(),'" + + Utils.settings.getJSONObject("一级供应室材料").getString("名称") + + "')]")); + Utils.retryingFindAndSendKeys(By.id("materialAmount"), "2" + "\n"); + Utils.retryingFindAndClick(By.id("saveBtn")); + // 定位回来 + Utils.retryingFindAndSwitchToFrame(By.id("iframe_washAndDisinfect")); + // 需要判断表单提交成功且返回正常后才能结束,否则就将不会提交到后台 + Wait wait = WaitFactory.createDefaultWait(); + wait.until(ExpectedConditions.attributeToBe( + Utils.driver.findElement(By.id("washSaveSubmitResult")), + "value", "1")); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + /** + * 清洗删除篮筐再添加篮筐,扫描不同的责任人 + */ + @Test + public void washChangeBasket() { + login.loginAction(); + Utils.retryingFindAndClick(By.id("washAndDisinfect")); + for (String winHandle : Utils.driver.getWindowHandles()) { + Utils.driver.switchTo().window(winHandle); + } + Wait wait = WaitFactory.createDefaultWait(); + Utils.retryingFindAndSwitchToFrame(By.id("iframe_washAndDisinfect")); + Utils.retryingFindAndClick(By + .xpath("//button[contains(text(), '添加')]")); + + Utils.driver.switchTo().defaultContent(); + String currentwindowhandle = Utils.driver.getWindowHandle(); + Utils.driver.switchTo().window(currentwindowhandle); + Utils.retryingFindAndSendKeys(By.id("inputText"), Utils.settings + .getJSONObject("一级供应室清洗机").getString("清洗机条码") + "\n"); + wait.until(ExpectedConditions.attributeToBeNotEmpty( + Utils.driver.findElement(By.id("disinfectIdentification")), + "value")); + Utils.retryingFindAndSendKeys(By.id("inputText"), Utils.settings + .getJSONObject("一级供应室清洗机").getString("清洗程序条码") + "\n"); + wait.until(ExpectedConditions.attributeToBeNotEmpty( + Utils.driver.findElement(By.id("disinfectProgram")), "value")); + Utils.retryingFindAndSendKeys(By.id("inputText"), Utils.settings + .getJSONObject("一级供应室清洗篮筐1").getString("条码") + "\n"); + // 扫描责任人 + Utils.retryingFindAndSendKeys(By.id("inputText"), Utils.settings + .getJSONObject("一级供应室审核人").getString("条码") + "\n"); + wait.until(ExpectedConditions.attributeToBeNotEmpty( + Utils.driver.findElement(By.id("personInCharge")), "value")); + String basketName = Utils.settings.getJSONObject("一级供应室清洗篮筐1") + .getString("名称"); + Utils.retryingFindAndClick(By.xpath("//span[contains(text(), '" + + basketName + "')]")); + // 删除篮筐 + Utils.retryingFindAndClick(By + .cssSelector("img[src='" + SERVER_URL+ "/images/web/stop.png" + "']")); + + // 重新扫描篮筐 + JSWaiter.waitUntilJQueryReady(); + if (Utils.isFind(Utils.retryingFind(By.id("inputText")))) { + Utils.retryingFindAndSendKeys(By.id("inputText"), Utils.settings + .getJSONObject("一级供应室清洗篮筐1").getString("条码") + "\n"); + if (Utils.isFind(Utils.retryingFind(By + .xpath("//a/span[contains(text(), '" + basketName+ "')]")))) { + } else { + Utils.retryingFindAndSendKeys( + By.id("inputText"), + Utils.settings.getJSONObject("一级供应室清洗篮筐1").getString("条码")+ "\n"); + } + Utils.retryingFindAndClick(By.xpath("//a/span[contains(text(), '"+ basketName + "')]")); + // 一级供应室配包人 + Utils.retryingFindAndSendKeys(By.id("inputText"), Utils.settings + .getJSONObject("一级供应室配包人").getString("条码") + "\n"); + wait.until(ExpectedConditions.attributeToBeNotEmpty( + Utils.driver.findElement(By.id("personInCharge")), "value")); + Utils.retryingFindAndClick(By.id("saveBtn")); + // 定位回来 + Utils.retryingFindAndSwitchToFrame(By.id("iframe_washAndDisinfect")); + // 需要判断表单提交成功且返回正常后才能结束,否则就将不会提交到后台 + if (Utils.isFind(Utils.retryingFind(By.id("washSaveSubmitResult")))) { + wait.until(ExpectedConditions.attributeToBe( + Utils.driver.findElement(By.id("washSaveSubmitResult")), + "value", "1")); + } + } + } + + /** + * 清洗失败,重新清洗,清洗完成,清洗机需要设置为清洗确认 + */ + @Test + public void washFailRewashAndFinish() { + try { + login.loginAction(); + Utils.retryingFindAndClick(By.id("washAndDisinfect")); + for (String winHandle : Utils.driver.getWindowHandles()) { + Utils.driver.switchTo().window(winHandle); + } + Wait wait = WaitFactory.createDefaultWait(); + Utils.retryingFindAndSwitchToFrame(By.id("iframe_washAndDisinfect")); + Utils.retryingFindAndClick(By + .xpath("//button[contains(text(), '添加')]")); + + Utils.driver.switchTo().defaultContent(); + String currentwindowhandle = Utils.driver.getWindowHandle(); + Utils.driver.switchTo().window(currentwindowhandle); + + wait.until(ExpectedConditions.attributeToBe( + Utils.driver.findElement(By.id("washLoadResult")), "value", + "1")); + + Utils.retryingFindAndSendKeys(By.id("inputText"), Utils.settings + .getJSONObject("一级供应室清洗机1").getString("清洗机条码") + "\n"); + wait.until(ExpectedConditions.attributeToBeNotEmpty( + Utils.retryingFind(By.id("disinfectIdentification")), + "value")); + Utils.retryingFindAndSendKeys(By.id("inputText"), Utils.settings + .getJSONObject("一级供应室清洗机1").getString("清洗程序条码") + "\n"); + wait.until(ExpectedConditions.attributeToBeNotEmpty( + Utils.driver.findElement(By.id("disinfectIdentification")), + "value")); + Utils.retryingFindAndSendKeys(By.id("inputText"), Utils.settings + .getJSONObject("一级供应室审核人").getString("条码") + "\n"); + wait.until(ExpectedConditions.attributeToBeNotEmpty( + Utils.driver.findElement(By.id("personInCharge")), "value")); + Utils.retryingFindAndSendKeys(By.id("inputText"), Utils.settings + .getJSONObject("一级供应室清洗篮筐1").getString("条码") + "\n"); + Utils.retryingFindAndClick(By.id("saveBtn")); + // 定位回来 + Utils.retryingFindAndSwitchToFrame(By.id("iframe_washAndDisinfect")); + // 需要判断表单提交成功且返回正常后才能结束,否则就将不会提交到后台 + wait.until(ExpectedConditions.attributeToBe( + Utils.driver.findElement(By.id("washSaveSubmitResult")), + "value", "1")); + + Utils.retryingFindAndClick(By.xpath("//p[contains(text(), '清洗中')]")); + JSWaiter.waitUntilJQueryReady(); + Utils.retryingFindAndClick(By + .xpath("//button[contains(text(), '清洗失败')]")); + JSWaiter.waitUntilJQueryReady(); + currentwindowhandle = Utils.driver.getWindowHandle(); + Utils.driver.switchTo().window(currentwindowhandle); + Utils.retryingFindAndClick(By + .xpath("//button[contains(text(), '是')]")); + // 定位回来 + Utils.retryingFindAndSwitchToFrame(By.id("iframe_washAndDisinfect")); + // 需要判断表单提交成功且返回正常后才能结束,否则就将不会提交到后台 + if (Utils.isFind(Utils.retryingFind(By.id("washSaveConfirm")))) { + wait.until(ExpectedConditions.attributeToBe( + Utils.driver.findElement(By.id("washSaveConfirm")), + "value", "1")); + } + // 扫描篮筐条码,录质量监测记录 + Utils.retryingFind(By.id("qualityMonitoringWin")); + Utils.retryingFindAndSendKeys(By.id("formName"), Keys.DOWN); + Utils.retryingFindAndClick(By.xpath("//div[contains(text(), '无')]")); + WebElement element = Utils.retryingFind(By.id("scanBarcode")); + + if (Utils.isFind(element)) { + Utils.retryingFindAndSendKeys(By.id("scanBarcode"), + Utils.settings.getJSONObject("一级供应室清洗篮筐1").getString( + "条码")+ "\n"); + } + + // 质量监测保存 + Utils.retryingFindAndClick(By + .xpath("//button[contains(text(), '保存')]")); + // 重新清洗 + Utils.retryingFindAndClick(By + .xpath("//p[contains(text(), '清洗失败')]")); + Utils.retryingFindAndClick(By + .xpath("//button[contains(text(), '修改')]")); + Utils.driver.switchTo().defaultContent(); + currentwindowhandle = Utils.driver.getWindowHandle(); + Utils.driver.switchTo().window(currentwindowhandle); + + Utils.retryingFindAndClick(By + .xpath("//button[contains(text(), '重新清洗')]")); + Utils.retryingFindAndSwitchToFrame(By.id("iframe_washAndDisinfect")); + wait.until(ExpectedConditions.attributeToBe( + Utils.driver.findElement(By.id("washSaveConfirm")), + "value", "1")); + wait.until(ExpectedConditions.attributeToBe( + Utils.driver.findElement(By.id("washSaveSubmitResult")), + "value", "1")); + WebElement element1 = Utils.retryingFind(By + .cssSelector("div[class='x-grid3-row-checker']")); + if (Utils.isFind(element1)) { + if (element1.isSelected()) { + } else { + element1.click(); + } + } + // 重新清洗后完成 + Utils.retryingFindAndClick(By + .xpath("//button[contains(text(), '清洗完成')]")); + Utils.driver.switchTo().defaultContent(); + currentwindowhandle = Utils.driver.getWindowHandle(); + Utils.driver.switchTo().window(currentwindowhandle); + Utils.retryingFindAndClick(By + .xpath("//button[contains(text(), '是')]")); + // 定位回来 + Utils.retryingFindAndSwitchToFrame(By.id("iframe_washAndDisinfect")); + // 需要判断表单提交成功且返回正常后才能结束,否则就将不会提交到后台 + Wait wait2 = WaitFactory.createDefaultWait(); + wait2.until(ExpectedConditions.attributeToBe( + Utils.driver.findElement(By.id("washSaveConfirm")), + "value", "1")); + if (Utils.isFind(Utils.retryingFind(By + .xpath("//p[contains(text(), '清洗中')]")))) { + element1 = Utils.retryingFind(By + .cssSelector("div[class='x-grid3-row-checker']")); + if (Utils.isFind(element1)) { + if (element1.isSelected()) { + // 重新清洗后完成 + Utils.retryingFindAndClick(By + .xpath("//button[contains(text(), '清洗完成')]")); + Utils.driver.switchTo().defaultContent(); + currentwindowhandle = Utils.driver.getWindowHandle(); + Utils.driver.switchTo().window(currentwindowhandle); + Utils.retryingFindAndClick(By + .xpath("//button[contains(text(), '是')]")); + // 定位回来 + Utils.retryingFindAndSwitchToFrame(By + .id("iframe_washAndDisinfect")); + // 需要判断表单提交成功且返回正常后才能结束,否则就将不会提交到后台 + wait2 = WaitFactory.createDefaultWait(); + wait2.until(ExpectedConditions.attributeToBe( + Utils.driver.findElement(By + .id("washSaveConfirm")), "value", "1")); + } else { + element1.click(); + // 重新清洗后完成 + Utils.retryingFindAndClick(By + .xpath("//button[contains(text(), '清洗完成')]")); + Utils.driver.switchTo().defaultContent(); + currentwindowhandle = Utils.driver.getWindowHandle(); + Utils.driver.switchTo().window(currentwindowhandle); + Utils.retryingFindAndClick(By + .xpath("//button[contains(text(), '是')]")); + // 定位回来 + Utils.retryingFindAndSwitchToFrame(By + .id("iframe_washAndDisinfect")); + // 需要判断表单提交成功且返回正常后才能结束,否则就将不会提交到后台 + wait2 = WaitFactory.createDefaultWait(); + wait2.until(ExpectedConditions.attributeToBe( + Utils.driver.findElement(By + .id("washSaveConfirm")), "value", "1")); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + AssertJUnit.fail(e.getMessage()); + } + } + + /** + * 关闭弹窗 + */ + private void dialogWindowClose() { + WebElement button = Utils.tryFind(By.id("idBox")); + if (Utils.isFind(button)) { + button.sendKeys("888888888"); + } + } + + /** + * 测试用例运行完毕之后 + */ + @After + public void after(){ + Utils.end(); + } + + +} Index: ssts-web/build.gradle =================================================================== diff -u -r27135 -r27142 --- ssts-web/build.gradle (.../build.gradle) (revision 27135) +++ ssts-web/build.gradle (.../build.gradle) (revision 27142) @@ -55,8 +55,9 @@ filter { if (project.hasProperty("seleniumTests")){ includeTestsMatching "test.forgon.disinfectsystem.selenium.ALL" - } - else{ + }else if(project.hasProperty("seleniumTestsForDivideTestCases")){ + includeTestsMatching "test.forgon.disinfectsystem.selenium3.AllTests" + }else{ includeTestsMatching "test.forgon.AllTests" } } Index: build.gradle =================================================================== diff -u -r27135 -r27142 --- build.gradle (.../build.gradle) (revision 27135) +++ build.gradle (.../build.gradle) (revision 27142) @@ -107,7 +107,7 @@ if (seleniumParameters.length != 5){ // 抛出异常,终止编译 - throw new GradleException("selenium参数错误,参数个数应该为4个,并且用逗号分隔") + throw new GradleException("selenium参数错误,参数个数应该为5个,并且用逗号分隔") } else{ Index: ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/tools/JSWaiter.java =================================================================== diff -u --- ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/tools/JSWaiter.java (revision 0) +++ ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/tools/JSWaiter.java (revision 27142) @@ -0,0 +1,221 @@ +package test.forgon.disinfectsystem.selenium3.tools; + +import java.util.concurrent.TimeUnit; + +import org.apache.log4j.Logger; +import org.openqa.selenium.JavascriptException; +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.NoSuchWindowException; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.support.ui.ExpectedCondition; +import org.openqa.selenium.support.ui.FluentWait; +import org.openqa.selenium.support.ui.Wait; +import org.openqa.selenium.support.ui.WebDriverWait; + +/** + * + * @author : Terry Kwan + * @date 创建时间:2017年7月15日 下午11:19:17 + * + * 代码来源及使用说明: + * http://www.swtestacademy.com/selenium-wait-javascript-angular-ajax/ + * + */ +public class JSWaiter { + + private final static Logger logger = Logger.getLogger(JSWaiter.class); + + private static WebDriver jsWaitDriver; + private static Wait jsWait; + private static JavascriptExecutor jsExec; + + // Get the driver from relevant test + public static void setDriver(WebDriver driver) { + jsWaitDriver = driver; + jsWait = new FluentWait(jsWaitDriver) + .withTimeout(20000, TimeUnit.MILLISECONDS) + .pollingEvery(250, TimeUnit.MILLISECONDS) + .ignoring(JavascriptException.class) + .ignoring(NoSuchWindowException.class) + .ignoring(ClassCastException.class); + + jsExec = (JavascriptExecutor) jsWaitDriver; + } + + // Wait for JQuery Load + private static void waitForJQueryLoad() { + // Wait for jQuery to load + ExpectedCondition jQueryLoad = driver -> ((Long) ((JavascriptExecutor) jsWaitDriver) + .executeScript("return jQuery.active") == 0); + + // Get JQuery is Ready + boolean jqueryReady = false; + // 捕获Exception异常 + try { + jqueryReady = (Boolean) jsExec + .executeScript("return jQuery.active==0"); + } catch (Exception e) { + e.printStackTrace(); + logger.debug(e.getMessage()); + } + // Wait JQuery until it is Ready! + if (!jqueryReady) { + logger.debug("JQuery is NOT Ready!"); + // Wait for jQuery to load + jsWait.until(jQueryLoad); + } else { + // logger.debug("JQuery is Ready!"); + } + } + + // Wait for Angular Load + private static void waitForAngularLoad() { + WebDriverWait wait = new WebDriverWait(jsWaitDriver, 15); + JavascriptExecutor jsExec = (JavascriptExecutor) jsWaitDriver; + + String angularReadyScript = "return angular.element(document).injector().get('$http').pendingRequests.length === 0"; + + // Wait for ANGULAR to load + ExpectedCondition angularLoad = driver -> Boolean + .valueOf(((JavascriptExecutor) driver).executeScript( + angularReadyScript).toString()); + + // Get Angular is Ready + boolean angularReady = Boolean.valueOf(jsExec.executeScript( + angularReadyScript).toString()); + + // Wait ANGULAR until it is Ready! + if (!angularReady) { + logger.debug("ANGULAR is NOT Ready!"); + // Wait for Angular to load + wait.until(angularLoad); + } else { + logger.debug("ANGULAR is Ready!"); + } + } + + // Wait Until JS Ready + public static void waitUntilJSReady() { + + Wait wait = new FluentWait(jsWaitDriver) + .withTimeout(25000, TimeUnit.MILLISECONDS) + .pollingEvery(250, TimeUnit.MILLISECONDS) + .ignoring(JavascriptException.class) + .ignoring(NoSuchWindowException.class) + .ignoring(ClassCastException.class); + + JavascriptExecutor jsExec = (JavascriptExecutor) jsWaitDriver; + + // Get JS is Ready + boolean jsReady = false; + + // 禁用jQuery的动画效果,一方面可以加快测试的速度,另一方面可以加强测试的稳定性(如果启用了Animation,使用WebDriver驱动浏览器时可能会出现一些无法预料的异常) + String disableJQueryAnimation = "try{ jQuery.fx.off = true;}catch(e){}"; + String waitPageReadyJS = disableJQueryAnimation + "if (typeof window != 'undefined'){return window.document.readyState;} else {return 'uninitialized';}"; + + // Wait for Javascript to load + ExpectedCondition jsLoad = driver -> "complete" + .equals(((JavascriptExecutor) jsWaitDriver) + .executeScript(waitPageReadyJS)); + try { + + jsReady = (Boolean) "complete".equals(jsExec.executeScript( + waitPageReadyJS)); + } + // 捕获Exception,忽略该异常 + catch (Exception e) { + logger.debug("错误信息:" + e.getMessage()); + e.printStackTrace(); + } + // Wait Javascript until it is Ready! + if (!jsReady) { + logger.debug("JS is NOT Ready!"); + // Wait for Javascript to load + wait.until(jsLoad); + } else { + // logger.debug("JS is Ready!"); + } + } + + // Wait Until JQuery and JS Ready + public static void waitUntilJQueryReady() { + + // 先等待JS加载完成 + waitUntilJSReady(); + + JavascriptExecutor jsExec = (JavascriptExecutor) jsWaitDriver; + + // First check that JQuery is defined on the page. If it is, then wait + // AJAX + Boolean jQueryDefined = false; + try { + jQueryDefined = (Boolean) jsExec + .executeScript("return typeof jQuery != 'undefined'"); + } catch (Exception e) { + logger.debug("错误信息:" + e.getMessage()); + e.printStackTrace(); + } + for (int i = 0; i < 3; i++) { + if (jQueryDefined == true) { + // Pre Wait for stability (Optional) + sleep(50); + + // Wait JQuery Load + waitForJQueryLoad(); + + // Post Wait for stability (Optional) + sleep(50); + break; + } else { + // logger.debug("jQuery is not defined on this site!"); + sleep(50); + continue; + } + } + } + + // Wait Until Angular and JS Ready + public static void waitUntilAngularReady() { + JavascriptExecutor jsExec = (JavascriptExecutor) jsWaitDriver; + + // First check that ANGULAR is defined on the page. If it is, then wait + // ANGULAR + Boolean angularUnDefined = (Boolean) jsExec + .executeScript("return window.angular === undefined"); + if (!angularUnDefined) { + Boolean angularInjectorUnDefined = (Boolean) jsExec + .executeScript("return angular.element(document).injector() === undefined"); + if (!angularInjectorUnDefined) { + // Pre Wait for stability (Optional) + sleep(100); + + // Wait Angular Load + waitForAngularLoad(); + + // Wait JS Load + waitUntilJSReady(); + + // Post Wait for stability (Optional) + sleep(100); + } else { + logger.debug("Angular injector is not defined on this site!"); + } + } else { + logger.debug("Angular is not defined on this site!"); + } + } + + // Wait Until JQuery Angular and JS is ready + public static void waitJQueryAngular() { + waitUntilJQueryReady(); + waitUntilAngularReady(); + } + + public static void sleep(long milis) { + try { + Thread.sleep(milis); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +} Index: ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/tools/Utils.java =================================================================== diff -u --- ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/tools/Utils.java (revision 0) +++ ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/tools/Utils.java (revision 27142) @@ -0,0 +1,1740 @@ +package test.forgon.disinfectsystem.selenium3.tools; + +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsEnvironment; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileWriter; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +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.function.Function; + +import net.sf.json.JSONArray; +import net.sf.json.JSONObject; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.log4j.Logger; +import org.monte.media.Format; +import org.monte.media.FormatKeys.MediaType; +import org.monte.media.math.Rational; +import org.monte.screenrecorder.ScreenRecorder; +import org.openqa.selenium.By; +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.OutputType; +import org.openqa.selenium.StaleElementReferenceException; +import org.openqa.selenium.TakesScreenshot; +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.ie.InternetExplorerOptions; +import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.remote.CapabilityType; +import org.openqa.selenium.remote.DesiredCapabilities; +import org.openqa.selenium.remote.RemoteWebDriver; +import org.openqa.selenium.remote.SessionId; +import org.openqa.selenium.support.ui.ExpectedCondition; +import org.openqa.selenium.support.ui.ExpectedConditions; +import org.openqa.selenium.support.ui.Wait; +import org.openqa.selenium.support.ui.WebDriverWait; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import test.forgon.disinfectsystem.selenium3.factory.WaitFactory; + +import com.fasterxml.jackson.core.JsonParser.Feature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.forgon.tools.util.PathUtils; + +import static org.monte.media.FormatKeys.EncodingKey; +import static org.monte.media.FormatKeys.FrameRateKey; +import static org.monte.media.FormatKeys.KeyFrameIntervalKey; +import static org.monte.media.FormatKeys.MIME_AVI; +import static org.monte.media.FormatKeys.MediaTypeKey; +import static org.monte.media.FormatKeys.MimeTypeKey; +import static org.monte.media.VideoFormatKeys.CompressorNameKey; +import static org.monte.media.VideoFormatKeys.DepthKey; +import static org.monte.media.VideoFormatKeys.ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE; +import static org.monte.media.VideoFormatKeys.QualityKey; + +/** + * @author Terry Date : 2016-02-29 23:17 工具类 + */ +public class Utils { + + private final static Logger logger = Logger.getLogger(Utils.class); + public static final String ACTION_CLICK = "click"; + public static final String ACTION_SENDKEYS = "sendKeys"; + public static final String ACTION_CLEAR_AND_SENDKEYS = "clear_and_sendKeys"; + public static final String ACTION_SWITCH_TO_FRAME = "switchToFrame"; + public static final String ACTION_CLEAR = "clear"; + + /** + * 屏幕录制 + */ + public static ScreenRecorder screenRecorder; + + /* + * 鼠标停留在控件上 + */ + public static final String ACTION_HOVER = "hover"; + public static final String ACTION_NOP = "nop"; + + /* + * 运行测试用例的模式 + */ + public enum RunMode { + + LOCAL, REMOTE + + } + + /* + * 测试用例的运行模式 + */ +// private static RunMode testRunMode = RunMode.REMOTE; + + private static RunMode testRunMode = RunMode.LOCAL; + + /* + * 执行动作的方式,调用JS或者Selenium API + * + * JavaScript:通过js方式调用 API:通过API方式调用 ByTagType:根据标签类型决定 + */ + public enum ActionExecuteMethod { + + JavaScript, API, ByTagType + + } + + // public static Wait wait; + + /** + * 项目设置对象 + */ + public static JSONObject settings = null; + public static WebDriver driver; + public static int cleanTime = 0; + + /** + * 全局等待的设置 WebDriverWait不能用全局变量,Terry Kwan,2017-5-1 + */ + // public static WebDriverWait waitSetting; + + /** + * extJs confirm窗口的等待时间 WebDriverWait不能用全局变量,Terry Kwan,2017-5-1 + */ + // public static WebDriverWait confirmWaitSetting; + // public static Wait waitSetting; + /** + * 单次装配后产生的条码 + */ + public static List barcodes; + /** + * 用于代理灭菌二次发货的条码 + */ + public static List resendout; + /** + * 一级供应室所有装配产生的条码 + */ + public static List oneSupplyReBarcodes = new ArrayList(); + /** + * 二级供应室所有装配产生的条码 + */ + public static List secondSupplyReBarcodes = new ArrayList(); + /** + * 一级供应室成功灭菌的条码 + */ +// public static List sterilizedBarcodes = new ArrayList(); + /** + * 一级供应室发货条码 + */ +// public static List sendGoodsBarcodes = new ArrayList(); + /** + * 外来器械包装配条码 + */ + public static List foreignToussesPackingBarcodes = new ArrayList(); + /** + * 代理灭菌器械包条码 + */ + public static List agentDisinfectionBarcodes = new ArrayList(); + /** + * 动态产生的数据 + */ + private static SeleniumRuntimeData seleniumRuntimeData = new SeleniumRuntimeData(); + /** + * 单次一次性物品入库后产生的条码 + */ + public static List disposableGoodsBatchBarcodesAfterEntry = new ArrayList(); + /** + * 一次性物品高值耗材条码 + */ + public static List high_Value_Consumables = new ArrayList(); + + /** + * 发货的一次性物品条码 + */ + public static List disposableGoodsBatchBarcodesForInvoice = new ArrayList(); + + public static SeleniumRuntimeData getSeleniumRuntimeData() { + return seleniumRuntimeData; + } + + /** + * 根据项目名称,初始化项目的配置对象 + * + * @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); + } + + /** + * 初始化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", "cherry"); + // chrome.setCapability("version", "8.0"); + driver = new ChromeDriver(chrome); + String serverAddress = Utils.settings.get("服务器地址").toString(); + driver.get(serverAddress); + } + + /** 启动前,先杀掉进程,再打开浏览器 */ + public static void webDriverInit() { + try { +// Runtime.getRuntime().exec("Taskkill /F /IM IEDriverServer.exe *32"); +// Runtime.getRuntime().exec("Taskkill /F /IM IEDriverServer.exe"); + Runtime.getRuntime().exec("Taskkill /F /IM iexplore.exe"); +// Runtime.getRuntime().exec("Taskkill /F /IM Command line server for the IE Driver.exe"); + Runtime.getRuntime().exec("Taskkill /F /IM iexplore.exe *32"); + } catch (Exception e1) { + e1.printStackTrace(); + } + // 解决ie兼容模式设置导致无法启动问题 + DesiredCapabilities ieCapabilities = DesiredCapabilities + .internetExplorer(); + ieCapabilities.setCapability(CapabilityType.BROWSER_NAME, + "internet explorer"); + // 禁用持续悬停特性,避免web页面的控件闪烁 + ieCapabilities.setCapability( + InternetExplorerDriver.ENABLE_PERSISTENT_HOVERING, false); + + ieCapabilities + .setCapability( + InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, + true); + String applicationName = Utils.settings.get( + "seleniumBrowserApplicationName").toString(); + ieCapabilities.setCapability("applicationName", applicationName); + + String browserVersion = Utils.settings.get("seleniumBrowserVersion") + .toString(); + ieCapabilities.setCapability("version", browserVersion); + + try { + String seleniumHubURL = Utils.settings.get("seleniumHubURL") + .toString(); + + // 远程运行 + if (testRunMode == RunMode.REMOTE) { + + logger.debug("selenium 运行模式:REMOTE,通过Selenium Hub分发测试任务"); + + driver = new RemoteWebDriver(new URL(seleniumHubURL), + ieCapabilities); + } else { + + logger.debug("selenium 运行模式:LOCAL"); + + /** + * 视频录制 + */ + GraphicsConfiguration gconfig = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); + screenRecorder = new ScreenRecorder(gconfig, new Format(MediaTypeKey, + MediaType.FILE, MimeTypeKey, MIME_AVI), new Format( + MediaTypeKey, MediaType.VIDEO, EncodingKey, + ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE, CompressorNameKey, + ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE, DepthKey, (int) 24, + FrameRateKey, Rational.valueOf(15), QualityKey, 1.0f, + KeyFrameIntervalKey, (int) (15 * 60)), new Format(MediaTypeKey, + MediaType.VIDEO, EncodingKey, "black", FrameRateKey, + Rational.valueOf(30)), null); + /** + * 初始化driver + */ + InternetExplorerOptions s = new InternetExplorerOptions(ieCapabilities); + driver = new InternetExplorerDriver(s); + String cap = ((InternetExplorerDriver) driver) + .getCapabilities().toString(); + + // 开始捕获视频 + screenRecorder.start(); + + logger.debug("my cap = " + cap); + + } + + JSWaiter.setDriver(driver); + + if (cleanTime == 0) { + Utils.driver.manage().deleteAllCookies(); + + // Utils.waitPageLoaded(); + JSWaiter.waitUntilJQueryReady(); + + cleanTime++; + } + } catch (Exception e) { + e.printStackTrace(); + } + + String serverAddress = Utils.settings.get("服务器地址").toString(); + driver.get(serverAddress); + } + + /** + * 初始化设置,包括项目配置和webdriver的初始化 + * + */ + public static void init() { + initProjectSettings("all"); + webDriverInit(); + + } + + /** + * 根据key与value对config.js的进行设值 + * @param key + * @return + */ + public static String setAndWriteConfigByNameAndValueForAutoTest(String key , Object value){ +// String configFilePath = ConfigUtils.getProjectName() + "/config.js"; + //自动化测试运行电脑项目名是“祈福医院”,而实际运行的项目为“广州市十二人民医院”,为了不修改到“祈福医院”的文件,因此将configFilePath写为固定值 + String configFilePath = "gzs12rmyy/config.js"; + writeWebConfigInfoForAutoTest(configFilePath , key , value); + return null; + } + + /** + * 将配置项写进config.js文件 + * @param configFilePath + * @param key + * @param value + * @return + */ + private static JSONObject writeWebConfigInfoForAutoTest(String configFilePath , String key , Object value){ + 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); + Scanner scan = null; + try { + String rootPath = Utils.settings.get("configJSPath").toString() + "/disinfectsystem/config/"; + String content = readFullFile(rootPath + configFilePath); + int startIndex = content.indexOf("{"); + //json变量定义的头(即左花括号之前的部分) + String jsonHeadContent = content.substring(0,startIndex); + int endIndex = (content.lastIndexOf("}") + 1); + if (startIndex != -1 && endIndex != -1 && startIndex < endIndex) { + content = content.substring(startIndex, endIndex); + } + + jsonObj = mapper.readValue(content,JSONObject.class); + + jsonObj.put(key, value); + String writeContent = jsonHeadContent; + writeContent += jsonObj; + + FileWriter writer = new FileWriter(new File(rootPath + configFilePath)); + writer.write(writeContent); + writer.flush(); + writer.close(); + } catch (IOException e) { + e.printStackTrace(); + }finally{ + if(scan != null){ + scan.close(); + } + } + return jsonObj; + } + + // 读取完整的文件 + private static String readFullFile(String Path) { + BufferedReader reader = null; + String laststr = ""; + try { + FileInputStream fileInputStream = new FileInputStream(Path); + InputStreamReader inputStreamReader = new InputStreamReader( + fileInputStream, "UTF-8"); + reader = new BufferedReader(inputStreamReader); + String tempString = null; + while ((tempString = reader.readLine()) != null) { + laststr += tempString + "\r\n"; + } + reader.close(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return laststr; + } + + /** 定位到弹出对话框的按钮 */ + public static void LocaAndWait() { + 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(String supply) { + 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)); + } + } + seleniumRuntimeData.addPackingTousseInfo(array); + } + + /** + * 若是一级供应室产生的装配条码则往oneSupplyReBarcodes添加 + * 二级供应室的则往secondSupplyReBarcodes添加 + * 代理灭菌器械包条码则往agentDisinfectionBarcodes添加 + */ + if("one".equals(supply)){ + Utils.oneSupplyReBarcodes.addAll(barcodes); + }else if("second".equals(supply)){ + Utils.secondSupplyReBarcodes.addAll(barcodes); + }else if("agent".equals(supply)){ + Utils.agentDisinfectionBarcodes.addAll(barcodes); + } + return barcodes; + } + + /** + * 获取一次性物品入库后的条码集合对象 + * + */ + public static List getDisposableGoodsBatchBarcodesAfterEntry() { + int count = 0; + List barcodes = new ArrayList(); + while (count <= 10) { + try { + JavascriptExecutor js = (JavascriptExecutor) driver; + Object entryItemStr = js + .executeScript("return JSON.stringify(entryItemJsonArray)"); + JSONArray array = JSONArray.fromObject(entryItemStr); + if (array != null) { + for (int i = 0; i < array.size(); i++) { + JSONObject entryItem = array.optJSONObject(i); + barcodes.add(entryItem.optString("barcode")); + } + break; + } + } catch (Exception e) { + e.printStackTrace(); + } + try { + doWait(1000); + } catch (Exception e) { + e.printStackTrace(); + } + count++; + } + return barcodes; + } + + /** + * 重复查找,当出现引用的element过时后,重新查找该element 如果找不到元素,不会抛出异常 + * + * @param by + * @return + */ + public static WebElement retryingFind(By by) { + WebElement element = null; + int attempts = 0; + // TODO:下面的循环重试应该可以去掉,直接用fluentWaitUntilFind即可 + while (attempts < 1) { + try { + + element = fluentWaitUntilFind(by); + + break; + } catch (Exception e) { + } + attempts++; + } + return element; + } + + /** + * 重复查找,当出现引用的element过时后,重新查找该element 如果找不到元素,会抛出异常 + * + * @param by + * @return + */ + public static WebElement retryingFindAssure(By by) { + WebElement element = null; + try { + element = fluentWaitUntilFind(by); + + } catch (Exception e) { + throw new NoSuchElementException(String.format( + "找不到对应的元素:%s,原因如下:\n%s", by, e)); + } + return element; + } + + /** + * 重复查找和执行动作(click或sendKeys等),当出现引用的element过时后,重新查找该element + * + * @param by + * @param actionType + * 动作类型 + * @param forceRunSeleniumAPI + * 是否强制用selniumAPI执行动作 + * @return + */ + private static WebElement retryingFindAndDoAction(By by, + ActionExecuteMethod actionExecuteMethod, String actionType, + CharSequence... keys) { + + JSWaiter.waitUntilJQueryReady(); + + WebElement element = null; + int attempts = 0; + int attemptsTime = 5; + while (attempts++ < attemptsTime) { + try { + + // element = findByAwait(by); + + element = fluentWaitUntilFind(by); + if (element == null){ + logger.debug("元素未找到,By = " + by); + continue; + } + + if (ACTION_CLICK.equalsIgnoreCase(actionType)) { + JavascriptExecutor executor = (JavascriptExecutor) driver; + Object aa = executor + .executeScript( + "var items = {}; for (index = 0; index < arguments[0].attributes.length; ++index) { items[arguments[0].attributes[index].name] = arguments[0].attributes[index].value }; return items;", + element); + System.out.println("click element attributes:\n" + aa); + String attribute = element.getAttribute("disabled"); + System.out.println("disabled = " + attribute); + if (!"true".equalsIgnoreCase(attribute) + && element.isEnabled()) { + if (Utils.isFind(element)) { + clickWebElement(actionExecuteMethod, element); + logger.info("点击元素[" + by + "]成功"); + } + } else { + logger.info("元素[" + by + "]不是Enable状态,不能点击"); + continue; + } + // 用按回车键模拟click,当element在屏幕上不可见时,也能达到click的效果 + // element.sendKeys(Keys.ENTER); + + } else if (ACTION_SENDKEYS.equalsIgnoreCase(actionType)) { + if (Utils.isFind(element)) { + element.sendKeys(keys); + } + } else if (ACTION_CLEAR.equalsIgnoreCase(actionType)) { + if (Utils.isFind(element)) { + element.clear(); + } + } else if (ACTION_CLEAR_AND_SENDKEYS + .equalsIgnoreCase(actionType)) { + if (Utils.isFind(element)) { + element.clear(); + element.sendKeys(keys); + } + } else if (ACTION_SWITCH_TO_FRAME.equalsIgnoreCase(actionType)) { + // 跳出所有的frame。调用后:you are now outside both frames + // Utils.driver.switchTo().defaultContent(); + if (Utils.isFind(element)) { + Wait wait = WaitFactory.createDefaultWait(); + // Utils.driver.switchTo().frame(element); + // switchToFrame(element); + wait.until(ExpectedConditions + .frameToBeAvailableAndSwitchToIt(element)); + logger.info("切换[" + by + "],frame成功"); + } + } else if (ACTION_HOVER.equalsIgnoreCase(actionType)) { + if (Utils.isFind(element)) { + Actions moveover = new Actions(Utils.driver); + moveover.moveToElement(element).perform(); + moveover.moveToElement(element, 1, 1).perform(); + } + } + break; + + } catch (Exception e) { + if (attempts == attemptsTime) { + String message = e.getMessage(); + logger.error(String.format("执行%s时尝试%s次仍然发生错误:%s", by, + attemptsTime, message)); + e.printStackTrace(); + throw new RuntimeException(message); + } + logger.warn(String.format("执行动作:%s操作节点%s时,发生错误,重试第%s次,异常如下:%s", + actionType, by, attempts, e)); + e.printStackTrace(); + } + } + return element; + } + + /** + * 重复查找获取控件的文本 + * + * @param by + * @return + */ + public static String retryingFindAndGetText(By by) { + String text = ""; + int attempts = 0; + while (attempts < 3) { + try { + + WebElement element = fluentWaitUntilFind(by); + if (element != null) { + text = element.getText(); + } else { + continue; + } + break; + } catch (Exception e) { + } + attempts++; + } + return text; + } + + /** + * 重复查找和click,当出现引用的element过时后,重新查找该element + * + * @param by + * @return + */ + public static WebElement retryingFindAndClick(By by) { + + return retryingFindAndDoAction(by, ActionExecuteMethod.ByTagType, + ACTION_CLICK); + } + + /** + * 通过Selenium API进行点击,避免JS点击不成功或者弹出对话框阻塞的问题 + * + * @param by + * @return + */ + public static WebElement retryingFindAndClickBySeleniumAPI(By by) { + + return retryingFindAndDoAction(by, ActionExecuteMethod.API, + ACTION_CLICK); + } + + /** + * 通过Javascript进行点击,避免Selenium API点击不成功 + * + * @param by + * @return + */ + public static WebElement retryingFindAndClickByJavaScript(By by) { + + return retryingFindAndDoAction(by, ActionExecuteMethod.JavaScript, + ACTION_CLICK); + } + + /* + * 鼠标停留在控件上 + */ + public static WebElement retryingFindAndHover(By by) { + + return retryingFindAndDoAction(by, ActionExecuteMethod.ByTagType, + ACTION_HOVER); + } + + /** + * 重复查找和清空内容,当出现引用的element过时后,重新查找该element + * + * @param by + * @return + */ + public static WebElement retryingFindAndClear(By by) { + return retryingFindAndDoAction(by, ActionExecuteMethod.ByTagType, + ACTION_CLEAR); + } + + public static WebElement retryingFindAndSendKeys(By by, + java.lang.CharSequence... keys) { + return retryingFindAndDoAction(by, ActionExecuteMethod.ByTagType, + ACTION_SENDKEYS, keys); + } + + public static WebElement retryingFindAndClearAndSendKeys(By by, + java.lang.CharSequence... keys) { + return retryingFindAndDoAction(by, ActionExecuteMethod.ByTagType, + ACTION_CLEAR_AND_SENDKEYS, keys); + } + + /** + * 查找组合框,输入按键。 说明:之前输入按键后,会休眠1.5秒,等待下拉框的内容出现,保证可靠的输入值。 + * 后面采用了JSWaiter的waitUntilJQueryReady方法,取消了休眠。 + * + * @param by + * @param keys + * @return + */ + public static WebElement retryingFindComboBoxAndSendKeys(By by, + java.lang.CharSequence... keys) { + WebElement element = null; + int attempts = 0; + while (attempts < 5) { + try { + + element = fluentWaitUntilFind(by); + element.sendKeys(keys); + JSWaiter.waitUntilJQueryReady(); + break; + + } catch (Exception e) { + // System.out.println("hkkkkkk"); + // e.printStackTrace(); + } + attempts++; + } + return element; + } + + /** + * 查找并切换到IFrame + * + * @param by + * @return + */ + public static WebElement retryingFindAndSwitchToFrame(By by) { + return retryingFindAndDoAction(by, ActionExecuteMethod.ByTagType, + ACTION_SWITCH_TO_FRAME); + } + + /** + * 流畅等待,查找页面元素 + * + * @param by + * @return + */ + public static WebElement fluentWaitUntilFind(By by) { + + // Wait wait = new FluentWait(driver) + // .withTimeout(5000, TimeUnit.MILLISECONDS) + // .pollingEvery(250, TimeUnit.MILLISECONDS) + // .ignoring(NoSuchElementException.class) + // .ignoring(StaleElementReferenceException.class) + // .ignoring(NullPointerException.class); + + // element = wait + // 暂时改成waitSetting,如果有必要,可以每次new一个新的. + // waitPageLoaded(); + + JSWaiter.waitUntilJQueryReady(); + WebElement element = null; + try { + WebDriverWait waitSetting = new WebDriverWait(driver, 15, 600); + element = waitSetting.until(new Function() { + public WebElement apply(WebDriver driver) { + // 等待页面状态加载完成 + // waitPageLoaded(); + return driver.findElement(by); + } + }); + } catch (Exception e) { + } + if (isFind(element) == true) { + logger.info("元素" + element + "存在,By = " + by.toString()); + } else { + logger.info("元素" + element + "不存在,By = " + by.toString()); + } + return element; + } + + /** + * 查找页面的节点,使用轮询方式,会一直阻塞,如果超过指定的时间仍然找不到则会抛出异常 + * + * @param wait + * 等待的对象 + * @return 查找到的节点,如果在指定的时间找不到则不会返回,直接抛出异常 + */ + public static WebElement findByAwait(By by, WebDriverWait wait) { + JSWaiter.waitUntilJQueryReady(); + try { + // 这里找不到会抛出异常 + return wait.until((ExpectedCondition) driver -> driver + .findElement(by)); + } catch (Exception e) { + throw new NoSuchElementException(String.format( + "找不到对应的元素:%s,原因如下:\n%s", by, e)); + } + } + + /** + * 先用confirmWaitSetting去找ExtJs的confirm框,如果找得到则点击确认,抛出异常则不点击(用于判断是否需要点击确认框) + */ + public static WebElement findConfirmAndClick(By by) { + WebElement webElement = null; + try { + webElement = tryFind(by); + if (isFind(webElement)) { + clickWebElement(ActionExecuteMethod.ByTagType, webElement); + } + // webElement = findByAwait(by, confirmWaitSetting); + } catch (Exception ignored) { + } + return webElement; + } + + /** + * 尝试寻找某个节点 + * + * Terry Kwan:本方法目前不能直接改为调用retryingFind方法,修改后的运行会出问题。 + * 找到原因后,可以统一为retryingFind方法 + * + * @return 返回空则表示找不到 + */ + public static WebElement tryFind(By by) { + try { + WebDriverWait confirmWaitSetting = new WebDriverWait(driver, 2, 300); + return findByAwait(by, confirmWaitSetting); + } catch (Exception ignored) { + logger.warn(String.format("尝试查找%s失败", by)); + } + return null; + } + + /** + * 判断某个节点是否被找到,如果抛出StaleElementReferenceException等异常,则认为没找到 + * + * @param webElement + * 对应的节点 + * @return + */ + public static boolean isFind(WebElement webElement) { + boolean isFind = false; + try { + isFind = webElement != null && webElement.isDisplayed() + && webElement.isEnabled(); + } catch (Exception e) { + e.printStackTrace(); + } + return isFind; + } + + /** + * 运行js脚本 + * + * @param script + * 要运行的js脚本 + */ + public static Object runJavaScript(String script) { + JSWaiter.waitUntilJQueryReady(); + Object response = null; + int attempts = 0; + while (attempts < 5) { + // 通过Try Catch执行js语句,发生JavaScriptException等异常后重试 + try { + response = ((JavascriptExecutor) Utils.driver) + .executeScript(script); + logger.info("执行脚本:" + script + " 返回值:" + response); + break; + } catch (Exception e) { + logger.info("第" + (attempts + 1) + "次出现异常:" + e.getMessage()); + e.printStackTrace(); + // 休眠1000ms后重试 + doWait(1000); + } + attempts++; + } + return response; + } + + public static Object runJavaScript(String script, Object... args) { + return ((JavascriptExecutor) Utils.driver).executeScript(script, args); + } + + /** + * 等待页面加载完成 + * + * @deprecated 改为调用JSWaiter的waitUntilJQueryReady()方法 + */ + public static void waitPageLoaded() { + // 这里加长到20秒,有时多次退出登录会卡住,所以这里要设置长一点的等待时间 + WebDriverWait waitSetting = new WebDriverWait(driver, 20, 400); + waitSetting.until((ExpectedCondition) driver -> "complete" + .equals(Utils.runJavaScript("return document.readyState"))); + } + + /** + * 默认每次轮询间隔的时间为0.5秒,最长等待时间为10秒 + * + * @see Utils#waitPageLoaded + */ + public static void waitPageLoaded(String script) { + waitPageLoaded(script, 15000, 500); + } + + /** + * 等待页面的某些元素或者某些东西加载完成(通过使用脚本来判断这些是否加载完成) + * + * @param script + * 要执行判断的脚本 + * @param maxWaitTime + * 最长等待时间 + * @param interval + * 每次轮询间隔的时间 + */ + public static void waitPageLoaded(String script, long maxWaitTime, + Integer interval) { + long start = System.currentTimeMillis(); + logger.info("执行等待脚本:" + script); + while (BooleanUtils.isTrue((Boolean) Utils.runJavaScript(script))) { + if (System.currentTimeMillis() - start > maxWaitTime) { + logger.warn("超出最长等待时间" + maxWaitTime + ",跳出循环"); + throw new RuntimeException("超出最长等待时间:" + maxWaitTime); + } + doWait(interval); + } + ; + } + + /** + * 切换到主窗口的main document,这样才能找到iframe之上的控件,例如各个模块的选项卡 + */ + public static void switchToDefaultContent() { + + driver.switchTo().defaultContent(); + String currentwindowhandle = Utils.driver.getWindowHandle(); + driver.switchTo().window(currentwindowhandle); + // 由于切换frame有点不太稳定,切换完立刻点击可能会出现永远找不到元素,所以这里暂时用要休眠一下来解决 + doWait(null); + } + + /** + * 切换到指定的frame + * + * @param frame + */ + public static void switchToFrame(WebElement frame) { + if (isFind(frame)) { + Utils.driver.switchTo().frame(frame); + // 由于切换frame有点不太稳定,切换完立刻点击可能会出现永远找不到元素,所以这里暂时用要休眠一下来解决 + doWait(500); + } + } + + /** + * 切换到指定的frame + * + * @param frame + * frame的名字 + */ + public static void switchToFrame(String frame) { + + Utils.driver.switchTo().frame(frame); + // 由于切换frame有点不太稳定,切换完立刻点击可能会出现永远找不到元素,所以这里暂时用要休眠一下来解决 + doWait(null); + } + + /** + * 休眠等待一下 + * + * @param time + * 要等待的时间 + */ + public static void doWait(Integer time) { + time = time == null ? 300 : time; + // 休眠等待一下 + try { + Thread.sleep(time); + } catch (InterruptedException e) { + logger.error(e.getMessage()); + } + } + + /** + * 重复查找和click,html表格的第一个单元格对象 + * + * @param by + * html table的查找条件 + * @return 点击结果。 true:点击成功, false:点击失败 + */ + 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); + if (cell != null) { + // cell.click(); + clickWebElement(ActionExecuteMethod.ByTagType, cell); + } + result = true; + break; + } + } catch (Exception e) { + // 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("消毒物品申请单") + || 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) { + return getIndexCellOfTable(table, 0); + } + + /** + * 获取Html Table的第四个单元格,即第一行第四列的单元格 + * + * @param table + * 表格对象 + * @return 单元格对象 + */ + public static WebElement getforthCellOfTable(WebElement table) { + return getIndexCellOfTable(table, 3); + } + + /** + * 获取表格的第一行的第index个单元格,只获取显示的单元格,会过滤掉不显示的单元格 + * + * @param table + * HTML的表格 + * @param index + * 第一行的第index个单元格,index从0开始计数 + * @return + */ + private static WebElement getIndexCellOfTable(WebElement table, int index) { + WebElement cell = null; + // Now get all the TR elements from the table + List allRows = table.findElements(By.tagName("tr")); + logger.debug("rows size = " + allRows.size()); + if (allRows != null && allRows.size() > 0) { + WebElement row = allRows.get(0); + // return row; + List cells = row.findElements(By.tagName("td")); + + List cellsNotHidden = new ArrayList(); + // 去掉隐藏的cell + for (WebElement myCell : cells) { + String style = myCell.getAttribute("style"); + if (style == null || style.indexOf("none") == -1) { + cellsNotHidden.add(myCell); + } + } + + if (cellsNotHidden.size() >= index + 1) { + cell = cellsNotHidden.get(index); + } + } + logger.debug("cell = " + cell); + return cell; + } + + /** + * 等待直到窗口数量变为期望值,新打开了窗口或者关闭了窗口 + * + * @param expectedNumberOfWindows + * 期望的窗口数量 + * @param timeOut + * 超时时间,单位为毫秒 + */ + public static void waitForWindowAmountEquals(int expectedNumberOfWindows, + int timeOut) { + + boolean isEquals = isWindowAmountEquals(expectedNumberOfWindows, + timeOut); + + if (!isEquals) { + int actualSize = driver.getWindowHandles().size(); + throw new RuntimeException("没有达到期望的窗口数量,实际窗口数量 = " + actualSize + + ",期望数量 = " + expectedNumberOfWindows); + } + } + + /** + * 是否浏览器窗口的数量达到了期望值 + * + * @param expectedNumberOfWindows + * 期望的窗口数量 + * @param timeOut + * 等待的超时时间 + */ + public static boolean isWindowAmountEquals(int expectedNumberOfWindows, + int timeOut) { + int initCount = driver.getWindowHandles().size(); + int actualSize = initCount; + if (initCount == expectedNumberOfWindows) { + return true; + } else { + // 达到了期望的窗口数量 + boolean reachExpectedWindowAmount = false; + long duration; + long startTime = System.currentTimeMillis(); + duration = (System.currentTimeMillis() - startTime); + while (timeOut > duration && !reachExpectedWindowAmount) { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + } + actualSize = driver.getWindowHandles().size(); + if (actualSize == expectedNumberOfWindows) { + reachExpectedWindowAmount = true; + } + duration = (System.currentTimeMillis() - startTime); + } + if (timeOut <= duration && !reachExpectedWindowAmount) { + return false; + } else { + return true; + } + } + } + + /** + * 尝试关闭警告对话框,如果弹出了警告对话框,则关闭该对话框 警告框可能有多个,如:器械包过期告警、满意度调查 + */ + public static void tryToCloseWarningWindow() { + try { + // 先等待页面加载完成,然后再等待Ext4.onReady执行完 + // waitPageLoaded(); + JSWaiter.waitUntilJQueryReady(); + + // TODO:以下Ext4的onReady,是否也可以用JS ready替代?这样就不需要调用了。 terry + // kwan,2017-07-16 + // 先等待portalPage.js的Ext4.onReady执行完 + // windowOnLoaded是自定义的JS变量 + // waitPageLoaded("return windowOnLoaded == false ? true : false;", + // 15000, 350); + waitPageLoaded( + "if(typeof(windowOnLoaded) != 'undefined' && windowOnLoaded == true){return false;} else {return true;}", + 15000, 350); + Wait wait = WaitFactory.createDefaultWait(); + // 等待对话框弹出 + // wait.until(ExpectedConditions + // .visibilityOfElementLocated(By + // .xpath("//div/span[contains(text(),'满意度调查表')]"))); + // 获取警告信息对话框的集合 + + By warningWindowsBy = By + .cssSelector("div[class='x-tool x-tool-close']"); + + List warningWindows = Utils.driver + .findElements(warningWindowsBy); + + if (warningWindows != null && warningWindows.size() > 0) { + int size = warningWindows.size(); + logger.debug("closeBtns.size() = " + size); + // 逐个关闭对话框,先关闭最外层的。如果没关闭最外层的,里面的对话框无法关闭 + + for (int i = size - 1; i >= 0; i--) { + + // 尝试关闭对话框,关闭后判断是否真正关闭,如果没有关闭,则再次循环点击关闭按钮 + try { + int count = 5; + for (int j = count; j > 0; j--) { + // closeBtns.get(i).click(); + // 通过运行JS关闭警告框,似乎更加可靠 + jsClick(warningWindows.get(i)); + + Thread.sleep(200); + List btns = driver + .findElements(warningWindowsBy); + if (btns != null && (btns.size() - i) >= 1) { + continue; + } else { + j = 0; + break; + } + } + } catch (Exception e) { + e.printStackTrace(); + } + + } + List btns = driver.findElements(warningWindowsBy); + if (btns != null) { + logger.debug("after click close button, closeBtns.size() = " + + btns.size()); + } + } else { + logger.debug("没有找到要关闭的按钮"); + } + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(e.getMessage()); + } + } + + /** + * 回收自定义入筐窗口的切换 + */ + public static void changeCustomWindow() { + try { + // 回收窗口 + boolean isNewWindowOpened = false; + String mainWindow = Utils.driver.getWindowHandle(); + + // 通过JS方式点击自定义入筐的div按钮(适用于Win7 IE11环境) + Utils.retryingFindAndHover(By.id("customIntoBasketDiv")); + Utils.retryingFindAndClickByJavaScript(By.id("customIntoBasketDiv")); + isNewWindowOpened = Utils.isWindowAmountEquals(2, 8000); + // 尝试用API的方式点击自定义入筐按钮 + if (!isNewWindowOpened) { + logger.info("通过JS点击,没有打开自定义入筐的窗口,尝试用API调用方式打开..."); + Utils.retryingFindAndClickBySeleniumAPI(By + .id("customIntoBasketDiv")); + isNewWindowOpened = Utils.isWindowAmountEquals(2, 8000); + } else { + logger.info("通过JS点击,打开了自定义入筐的窗口"); + } + + if (isNewWindowOpened) { + logger.info("最终打开了自定义入筐的窗口!"); + } else { + logger.info("没有打开自定义入筐的窗口,再次尝试打开!"); + Utils.retryingFindAndClick(By.id("customIntoBasketDiv")); + isNewWindowOpened = Utils.isWindowAmountEquals(2, 8000); + if (isNewWindowOpened) { + logger.info("最终打开了自定义入筐的窗口!"); + + } else { + logger.info("最终没有打开自定义入筐的窗口,测试失败!"); + + } + } + + AssertJUnit.assertTrue(isNewWindowOpened); + + // 遍历所有窗口,切换至新窗口(自定义入筐窗口) + Set handles = Utils.driver.getWindowHandles(); + for (String windowHandle : handles) { + if (!windowHandle.equalsIgnoreCase(mainWindow)) { + Utils.driver.switchTo().window(windowHandle); + System.out.println("切换到新窗口:" + windowHandle); + // 确认已经切换至自定义入筐窗口 + 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); + break; + } else { + logger.info("自定义入筐打开的窗口路径不一致!"); + } + } + + } + + } catch (Exception e) { + e.printStackTrace(); + Assert.fail(e.getMessage()); + } + } + + /** + * 刷新页面 + */ + public static void refresh() { + + JSWaiter.waitUntilJQueryReady(); + Utils.switchToDefaultContent(); + Utils.driver.navigate().refresh(); + String currentwindowhandle = Utils.driver.getWindowHandle(); + Utils.driver.switchTo().window(currentwindowhandle); + if (Utils.isFind(Utils.retryingFind(By + .cssSelector("div[class='x-tool x-tool-close']")))) { + Utils.tryToCloseWarningWindow(); + } + // Utils.waitPageLoaded(); + JSWaiter.waitUntilJQueryReady(); + } + + /** + * 等待一段时间,直到页面的URL地址变为期望值。如果没有跳转到期望值,则抛出运行时异常 + * + * @param newUrl + * 期望的url + * @param seconds + * 等待的超时时间 + */ + public static void waitUntilUrlChange(final String newUrl, int seconds) { + boolean isURLOk = false; + JSWaiter.waitUntilJQueryReady(); + + try{ + Wait wait = WaitFactory.createWait(seconds * 1000, 500); + isURLOk = wait.until(new Function() { + public Boolean apply(WebDriver d) { + return d.getCurrentUrl().startsWith(newUrl); + } + }); + } + catch (Exception e){ + e.printStackTrace(); + } + if (!isURLOk) { + String currentURL = Utils.driver.getCurrentUrl(); + throw new RuntimeException("URL地址没有跳转到期望地址,期望地址 = " + newUrl + + ",当前地址 = " + currentURL); + } + + } + + /** + * 等待一段时间,直到页面的URL地址包含了期望值。如果没有包含期望值,则抛出运行时异常 + * + * @param urlContaints + * 期望的新URL中被包含的值 + * @param seconds + * 等待的超时时间 + */ + public static void waitUntilUrlContains(final String urlContaints, + int seconds) { + boolean isURLOk = false; + + JSWaiter.waitUntilJQueryReady(); + try { + Wait wait = WaitFactory.createWait(seconds * 1000, 500); + isURLOk = wait.until(new Function() { + public Boolean apply(WebDriver d) { + return d.getCurrentUrl().toLowerCase() + .contains(urlContaints.toLowerCase()); + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + + if (!isURLOk) { + String currentURL = Utils.driver.getCurrentUrl(); + throw new RuntimeException("URL地址包含期望值,期望包含值 = " + urlContaints + + ",当前地址 = " + currentURL); + } + + } + + /** + * 获取项目的配置信息,该配置信息合并了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 { + + // config.js配置文件的路径。相对于类路径 + String configFilePath = "test/forgon/disinfectsystem/selenium/config/"; + + // 获取Selenium自动化测试的配置信息 + InputStream instream1 = Utils.class.getClassLoader() + .getResourceAsStream( + configFilePath + 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( + configFilePath + 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; + } + + /** + * 为ExtJS4的组合框输入文字 + * + * @param comboBoxName + * ExtJS4的组合框名字 + * @param text + * 要输入的文字 + */ + public static void extJS4comboBoxInput(String comboBoxName, String text) { + String script = "return Ext4.getCmp('" + comboBoxName + + "').getStore().isLoading();"; + // 输入前先等待,看看是否已经加载完,因为处理科室改变物品会重新加载 + Utils.waitPageLoaded(script); + Utils.retryingFindAndClearAndSendKeys( + By.cssSelector("input[name='" + comboBoxName + "']"), text); + // 输入完等待加载完毕,加载完毕后才能点 + Utils.waitPageLoaded(script); + Utils.retryingFindAndClick(By.xpath("//div/ul/li[contains(text(), '" + + text + "')]")); + } + + /** + * 根据自定义属性获取第一个dom,使用方法可以参考: + * + * @see Utils#getCustomAttributeDom(String, boolean) + * @param fnName + * 添加的方法名字 + * @return 返回在页面生成js脚本的字符串 + */ + public static String getFirstCustomAttributeDom(String fnName) { + return getCustomAttributeDom(fnName, true); + } + + /** + * 根据自定义属性获取对应的dom,使用方法如下: + *

+ * String script = getCustomAttributeDom("functionName", true); + *

+ *

+ * script += + * " var typeDom = functionName('自定义属性所在的tag', '自定义属性的名字');return typeDom;" + *

+ *

+ * Object dom = Utils.runJavaScript(script);" + *

+ * + * @param fnName + * 添加的方法名字 + * @param getFirst + * 是否取第一个节点 + * @return 返回添加好的脚本 + */ + public static String getCustomAttributeDom(String fnName, boolean getFirst) { + StringBuilder customAttributeFn = new StringBuilder() + .append(String.format("function %s (tagName, attr){", fnName)) + .append("var tagNames = document.getElementsByTagName(tagName);") + .append("var ar = [];") + .append("for(var i = 0,len = tagNames.length;i < len;i++){") + .append("var node = tagNames[i];") + .append("if (node.getAttributeNode(attr)){"); + customAttributeFn.append(getFirst ? "return node;}}}" + : "ar.push(node);}}return ar;}"); + return customAttributeFn.toString(); + } + + /** + * 向页面添加JQuery + */ + public static void addJQuery() { + StringBuilder script = new StringBuilder().append("(function() {") + .append(" if (!window.jQuery) {") + .append(" var s = document.createElement('script');") + .append(" s.type = 'text/javascript';") + .append(" s.src = '/jquery/jquery-1.11.2.js';") + .append(" document.body.appendChild(s);") + .append(" }").append("})();"); + // String script = + // "(function(){if(!window.jQuery){var s = document.createElement('script'); s.type = 'text/javascript'; s.src = '/jquery/jquery-1.11.2.js'; document.body.appendChild(s);}})();"; + Utils.runJavaScript(script.toString()); + } + + /** + * 使用js来点击 + * + * @param webElement + * 要点击的元素 + */ + public static void jsClick(WebElement webElement) { + try { + if (isFind(webElement)) { + Utils.runJavaScript("arguments[0].click();", webElement); + // 用以下方式可以解决模态窗点击不到,但会申请单提交可能会有问题, + // Utils.runJavaScript("var elem=arguments[0]; setTimeout(function() {elem.click();}, 100)", + // webElement); + } else { + logger.warn("页面上的元素无法进行单击操作,请检查是否由于屏幕分辨率太低,导致页面控件显示不出来。"); + } + } catch (StaleElementReferenceException e) { + logger.warn("页面元素没有附加在网页中" + e.getStackTrace()); + } catch (NoSuchElementException e) { + logger.warn("页面元素没有找到要操作的页面元素" + e.getStackTrace()); + } catch (Exception e) { + logger.warn("无法完成单击操作" + e.getStackTrace()); + } + } + + /** + * 点击WebElement的通用方法,建议都通过此方法调用,以便统一更换最可靠的方法 + * + * @param ActionExecuteMethod + * 是否强制用selenium的API调用,因为JS调用弹出Alert或模态窗口可能导致阻塞 + * @param webElement + * + */ + public static void clickWebElement(ActionExecuteMethod actionExecuteMethod, + WebElement webElement) { + + logger.debug("调用clickWebElement方法: actionExecuteMethod = " + + actionExecuteMethod + ", webElement = " + webElement); + + if (actionExecuteMethod.equals(ActionExecuteMethod.API)) { + if (isFind(webElement)) { + webElement.click(); + } + } else if (actionExecuteMethod.equals(ActionExecuteMethod.JavaScript)) { + if (isFind(webElement)) { + jsClick(webElement); + } + } else if (actionExecuteMethod.equals(ActionExecuteMethod.ByTagType)) { + // jsClick(webElement); + String tagName = webElement.getTagName(); + + // span标签:导航菜单 + // a标签:很多ExtJS的按钮,例如申请单的终止按钮 + // img标签:登录按钮为img标签 + // li标签:桌面的图标按钮 + + // table标签:灭菌记录表单的保存按钮,不能整个改,否则似乎其他地方不稳定了 + + // P标签用js无法选中 + // p标签:视图列表中的清洗失败记录的选择 + + String[] tagNamesClickByJS = new String[] { "button", "a", "span", + "img", "li", "input" }; + + // 如果不强制调用selenium API,并且是需要采用JavaScript点击的标签类型,则用JS进行点击 + if (ArrayUtils.contains(tagNamesClickByJS, tagName)) { + if (isFind(webElement)) { + jsClick(webElement); + } + } else { + if (isFind(webElement)) { + webElement.click(); + } + } + } + } + + + /** + * 结束测试 + */ + public static void end(){ + try { + SessionId session = null; + + if (Utils.driver instanceof RemoteWebDriver) { + session = ((RemoteWebDriver) Utils.driver).getSessionId(); + } else if (Utils.driver instanceof InternetExplorerDriver) { + session = ((InternetExplorerDriver) Utils.driver).getSessionId(); + } + + //停止视频录制 + Thread.sleep(5000); + Utils.screenRecorder.stop(); + + if (session != null) { + String webAppRootPath = PathUtils.getWebAppRootPath(); + String buildTempPath = webAppRootPath.replaceAll("/src/main/webapp", "/build/tmp"); + + // 删除之前产生的截图文件 + final File folder = new File(buildTempPath); + + final File[] files = folder.listFiles(new FilenameFilter() { + public boolean accept(final File dir, final String name) { + return name.endsWith(".png")&& name.startsWith("screenshot"); + } + }); + for (final File file : files) { + if (!file.delete()) { + System.err.println("无法删除文件:" + file.getAbsolutePath()); + } + } + + // 截图 + File scrFile = ((TakesScreenshot) Utils.driver).getScreenshotAs(OutputType.FILE); + String timeStamp = new SimpleDateFormat("yyyy-MM-dd HH.mm.ss").format(new java.util.Date()); + FileUtils.copyFile(scrFile, new File(buildTempPath+ "/screenshot-" + timeStamp + ".png")); + + if (Utils.driver.getWindowHandles().isEmpty()) { + logger.info("Session ID is null"); + } else { + Set allWindowsId = Utils.driver.getWindowHandles(); + for (String windowID : allWindowsId) { + if (windowID != null) { + String title = Utils.driver.switchTo().window(windowID).getTitle(); + logger.debug("windowID = " + windowID + ", title = " + title); + if (title.contains("消毒") || title.contains("回收")|| title.contains("WebDriver")) { + Utils.driver.switchTo().window(windowID); + logger.info(windowID); + JSWaiter.waitUntilJQueryReady(); +// Utils.driver.quit(); + Runtime.getRuntime().exec("Taskkill /F /IM conhost.exe"); + Runtime.getRuntime().exec("Taskkill /F /IM IEDriverServer.exe *32"); + Runtime.getRuntime().exec("Taskkill /F /IM IEDriverServer.exe"); + Runtime.getRuntime().exec("Taskkill /F /IM iexplore.exe"); + Runtime.getRuntime().exec("Taskkill /F /IM Command line server for the IE Driver.exe"); + Runtime.getRuntime().exec("Taskkill /F /IM iexplore.exe *32"); + continue; + } + } else { + break; + } + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + +} Index: ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/recycle/TestSignboardRecyledAndDropAndScrap.java =================================================================== diff -u --- ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/recycle/TestSignboardRecyledAndDropAndScrap.java (revision 0) +++ ssts-web/src/test/java/test/forgon/disinfectsystem/selenium3/recycle/TestSignboardRecyledAndDropAndScrap.java (revision 27142) @@ -0,0 +1,179 @@ +package test.forgon.disinfectsystem.selenium3.recycle; + +import static org.junit.Assert.fail; + +import org.apache.log4j.Logger; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.ExpectedConditions; +import org.openqa.selenium.support.ui.Wait; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import test.forgon.disinfectsystem.selenium3.factory.WaitFactory; +import test.forgon.disinfectsystem.selenium3.login.Login; +import test.forgon.disinfectsystem.selenium3.tools.JSWaiter; +import test.forgon.disinfectsystem.selenium3.tools.Utils; + +/** + * 自动化测试用例:回收带标识牌器械包 + * @author yuandongxiao + * + */ +@Transactional(propagation = Propagation.NEVER) +public class TestSignboardRecyledAndDropAndScrap extends TestRecycled{ + protected Logger logger = Logger.getLogger(this.getClass());//日志记录 + private Login login = new Login();//登录 + private String SERVER_URL;//访问地址 + + /*********************************************************************************************** + * * + * 测试数据准备 * + * * + * *********************************************************************************************/ + + /** + * 基础数据准备 + */ + private void prepareData() { + initCSSDData(); + makeActiveUser("admin"); + } + + + /*********************************************************************************************** + * * + * 标识牌器械包回收自动化测试用例 * + * * + * *********************************************************************************************/ + + /** + * 1.准备回收模块的自动化测试数据 + * 2.初始化自动化设置 + */ + @Before + public void init(){ + this.prepareData(); + Utils.init(); + SERVER_URL = Utils.settings.get("服务器地址").toString(); + } + + + /** + * 一级供应室回收带标识牌的回收单并确认 + */ + @Test + public void recyleSignboardAndDropAndScrap(){ + try { + logger.info("一级供应室回收带标识牌的回收单开始"); + Utils.driver.get(SERVER_URL + "/?logonType=1080p"); + login.loginAction(); + Utils.waitUntilUrlContains("awaitForRecycleList.jsp", 15); + // 点击添加按钮 + Utils.retryingFindAndClick(By.id("addRecycleRecordBtn")); + + // 等待页面跳转 + waitUrlChange(); + + WebElement recycleForm = this.scanRecycleUserBarcode(); + // 扫描科室条码 + + Utils.retryingFindAndSendKeys(By.id("depart"), Utils.settings + .getJSONObject("临床科室").getString("条码") + "\n"); + + Wait wait = WaitFactory.createDefaultWait(); + + // 断言临床科室的填写成功 + wait.until(ExpectedConditions.attributeContains(By.id("depart"), + "value", + Utils.settings.getJSONObject("临床科室").getString("名称"))); + + Utils.retryingFindAndSendKeys(By.id("operator"), Utils.settings + .getJSONObject("一级供应室清洗篮筐2").getString("条码") + "\n"); + + dialogWindowClose(); + Utils.retryingFindAndSendKeys(By.id("depart"), Utils.settings + .getJSONObject("一级供应室器械包1").getString("标识牌条码2") + "\n"); + + // 增加丢失、报损 + Utils.retryingFindAndClick(By + .cssSelector("a[id^='recyclingErrorButton']")); + Utils.retryingFindAndSwitchToFrame(By.tagName("iframe")); + + Utils.retryingFindAndClick(By.id("recyclingErrorTable")); + // 点击第1行的+号按钮 + Utils.retryingFindAndClick(By.id("addButton0")); + if (Utils.isFind(Utils.retryingFind(By.id("errorRemark")))) { + Utils.retryingFindAndSendKeys(By.id("errorRemark"), "丢失标识牌"); + } + Utils.retryingFindAndClick(By.id("errorSubmitButton")); + Utils.driver.switchTo().defaultContent(); + Utils.retryingFindAndClick(By + .cssSelector("a[id^='recyclingDamageButton']")); + Utils.retryingFindAndSwitchToFrame(By.tagName("iframe")); + + Utils.retryingFindAndClick(By.id("recyclingDamageForm")); + Utils.retryingFindAndClick(By.id("addButton0")); + + if (Utils.isFind(Utils.retryingFind(By.id("damageRemark")))) { + Utils.retryingFindAndSendKeys(By.id("damageRemark"), "报损材料"); + } + Utils.retryingFindAndClick(By.id("damageSubmitButton")); + // 加急 + Utils.driver.switchTo().defaultContent(); + Utils.retryingFindAndClick(By + .cssSelector("div[id^='urgentAmountDiv']")); + Utils.retryingFindAndSwitchToFrame(By.tagName("iframe")); + Utils.retryingFindAndClick(By.id("recyclingErrorTable")); + Utils.retryingFindAndClick(By.id("addButton0")); + JSWaiter.waitUntilJQueryReady(); + if (Utils.isFind(Utils.retryingFind(By.id("urgentLevelTd")))) { + Utils.retryingFindAndClick(By.id("urgentLevelTd")); + Utils.retryingFindAndClick(By.cssSelector("option[value='加急']")); + } + Utils.retryingFindAndClick(By.id("urgentSubmitButton")); + Utils.driver.switchTo().defaultContent(); + // 扫描篮筐条码 + recycleForm.sendKeys(Utils.settings.getJSONObject("一级供应室清洗篮筐3") + .getString("条码") + "\n"); + dialogWindowClose(); + Utils.retryingFindAndClick(By.cssSelector(".btn-a")); + Utils.retryingFindAndClick(By.id("saveBtn")); + Utils.waitUntilUrlContains( + SERVER_URL + + "/disinfectsystem/touchScreen/recycle/awaitForRecycleList.jsp?resolution=1980", + 8); + logger.info("一级供应室回收带标识牌的回收单完成"); + logger.info("一级供应室确认回收申请单开始"); + Utils.retryingFind(By.id("recyclingRecordTable")); + WebElement element = Utils.retryingFind(By + .cssSelector("tr[bgcolor='#FF8C69']")); + if (Utils.isFind(element)) { + + Utils.retryingFindClickFirstCellOfTable(By + .id("recyclingRecordTable")); + + waitUrlChange(); + + Utils.retryingFindAndClick(By.id("confirmBtnTd")); + logger.info("一级供应室确认回收申请单完成"); + } + }catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + + /** + * 测试用例运行完毕之后 + */ + @After + public void after(){ + Utils.end(); + } +}