├── .gitignore ├── src └── main │ ├── resources │ ├── images │ │ ├── cancel.png │ │ ├── inspect.png │ │ ├── refresh.png │ │ └── wisard.png │ └── license │ │ └── license.txt │ └── java │ └── objectivetester │ ├── RichElement.java │ ├── UserInterface.java │ ├── Const.java │ ├── Theme.java │ ├── DefaultWriter.java │ ├── TestWriter.java │ ├── Test5Writer.java │ ├── ScriptWriter.java │ ├── JsWriter.java │ ├── EventListener.java │ ├── BrowserDriver.java │ ├── Wisard.form │ └── Wisard.java ├── LICENSE ├── nb-configuration.xml ├── README.md ├── nbactions.xml └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /nbproject/ -------------------------------------------------------------------------------- /src/main/resources/images/cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ObjectiveTester/wisard/HEAD/src/main/resources/images/cancel.png -------------------------------------------------------------------------------- /src/main/resources/images/inspect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ObjectiveTester/wisard/HEAD/src/main/resources/images/inspect.png -------------------------------------------------------------------------------- /src/main/resources/images/refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ObjectiveTester/wisard/HEAD/src/main/resources/images/refresh.png -------------------------------------------------------------------------------- /src/main/resources/images/wisard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ObjectiveTester/wisard/HEAD/src/main/resources/images/wisard.png -------------------------------------------------------------------------------- /src/main/java/objectivetester/RichElement.java: -------------------------------------------------------------------------------- 1 | package objectivetester; 2 | 3 | /** 4 | * 5 | * @author steve 6 | */ 7 | public class RichElement { 8 | 9 | protected String method; 10 | protected String attribute; 11 | 12 | RichElement(String method, String attribute) { 13 | this.method = method; 14 | this.attribute = attribute; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/objectivetester/UserInterface.java: -------------------------------------------------------------------------------- 1 | package objectivetester; 2 | 3 | /** 4 | * 5 | * @author Steve 6 | */ 7 | interface UserInterface { 8 | 9 | void addItem(String type, Object stack, String name, String id, String value, Object element, Boolean displayed); 10 | 11 | void rescan(); 12 | 13 | void abort(); 14 | 15 | void finished(); 16 | 17 | void addCode(String fragment); 18 | 19 | void insertCode(String fragment, int above); 20 | 21 | boolean alertResponse(String title); 22 | 23 | String enterValue(String title); 24 | 25 | String enterSelection(String title, String choices[]); 26 | 27 | void elementIdent(String message); 28 | 29 | void errorMessage(String message); 30 | 31 | String getCSSselectors(); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 - 2018 Steve Mellor 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /src/main/resources/license/license.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 - 2018 Steve Mellor 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /nb-configuration.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 16 | ${project.basedir}/license 17 | true 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/main/java/objectivetester/Const.java: -------------------------------------------------------------------------------- 1 | package objectivetester; 2 | 3 | /** 4 | * 5 | * @author Steve 6 | */ 7 | interface Const { 8 | 9 | //these are used internally to denote action and element type 10 | static final String CLICK = "click"; 11 | 12 | static final String FIND = "find"; 13 | 14 | static final String ASSERT = "assert"; 15 | 16 | static final String IDENTIFY = "identify"; 17 | 18 | static final String INVISIBLE = "(invisible) "; 19 | 20 | static final String PAGE = "page"; 21 | 22 | static final String TITLE = "title"; 23 | 24 | static final String BROWSER = "browser"; 25 | 26 | static final String WINDOW = "other window"; 27 | 28 | static final String CURRENT = "current focus"; 29 | 30 | static final String COOKIE = "cookie"; 31 | 32 | //the style to 'highlight' an element 33 | static final String HIGHLIGHT = "'color: yellow; font-weight: bold; border: 2px dotted red;'"; 34 | 35 | //max text to put in a dialog box 36 | static final int MAX_SIZ = 2048; 37 | 38 | static final int POP_CLICK = 0; 39 | 40 | static final int POP_FIND = 1; 41 | 42 | static final int POP_ASSERT = 2; 43 | 44 | static final int POP_ID = 3; 45 | 46 | static final int TAB_ELEMENT = 0; 47 | 48 | static final int TAB_LOCATION = 1; 49 | 50 | static final int TAB_NAME = 2; 51 | 52 | static final int TAB_ID = 3; 53 | 54 | static final int TAB_VALUE = 4; 55 | 56 | static final int TAB_WEBELEMENT = 5; 57 | 58 | } 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Wisard 2 | ====== 3 | 4 | Web Internal Structure Action RecorDer - a webdriver based tool for creating Selenium tests 5 | 6 | Building Wisard 7 | =============== 8 | 9 | Clone or download the source code and either: 10 | 11 | Open the 'wisard' folder in NetBeans or your favourite IDE, and build it. 12 | 13 | Build a package from the command line with: 14 | 15 | mvn package 16 | 17 | 18 | Running Wisard 19 | ============== 20 | 21 | Once built, either double-click 'Wisard-1.6.jar' or start from the command line with: 22 | 23 | java -jar target/Wisard-1.6.jar 24 | 25 | 26 | Then enter a web URL and click the find icon 27 | 28 | Using Wisard 29 | ============ 30 | Once a browser has opened and displayed your web page, all the useful elements of the page are displayed in left hand pane of the Wisard window. Wisard will try to momentarily highlight any element you click on. Right clicking an element allows you to interact with it by clicking it or verifying it's value, etc. 31 | 32 | As you set and verify element values, the right hand pane is updated with jUnit test cases. Alternately, Java statements can be generated to automate a web task. These can be copied and pasted into a file/your favourite IDE and then compiled and executed. 33 | 34 | Wisard can set and verify input elements, verify and click links and anchors, and verify image elements. 35 | 36 | Wisard can open and record scripts in 'Firefox', 'Chrome', 'Internet Explorer', 'Edge' and 'Safari', drivers are auto-downloaded by Selenium Manager, or can be manually overridden by setting the 'driver' path setting in the 'Settings' window, and downloading the correct drivers for your OS. 37 | 38 | 39 | Screenshots and more can be found here : http://objectivetester.github.io/wisard 40 | -------------------------------------------------------------------------------- /src/main/java/objectivetester/Theme.java: -------------------------------------------------------------------------------- 1 | package objectivetester; 2 | import java.io.BufferedReader; 3 | import java.io.InputStreamReader; 4 | import com.sun.jna.platform.win32.Advapi32Util; 5 | import com.sun.jna.platform.win32.WinReg; 6 | 7 | public final class Theme 8 | { 9 | public static boolean light() { 10 | Boolean light = false; 11 | String os = System.getProperty("os.name").toLowerCase(); 12 | 13 | if (os.contains("windows")) { 14 | if (Advapi32Util.registryGetValue(WinReg.HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\personalize", "AppsUseLightTheme").toString().contentEquals("1")) { 15 | light = true; 16 | } 17 | } else if (os.contains("mac")) { 18 | try { 19 | Runtime rt = Runtime.getRuntime(); 20 | String[] commands = {"/usr/bin/defaults", "read", "-g", "AppleInterfaceStyle"}; 21 | Process proc = rt.exec(commands); 22 | BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream())); 23 | BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream())); 24 | String s = null; 25 | while ((s = stdError.readLine()) != null) { 26 | light = true; 27 | } 28 | 29 | s = null; 30 | while ((s = stdInput.readLine()) != null) { 31 | if (s.equalsIgnoreCase("dark")) { 32 | light = false; 33 | } 34 | 35 | } 36 | } catch (Exception e) { 37 | //System.out.println(e); 38 | } 39 | } 40 | 41 | return light; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /nbactions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | run 5 | 6 | jar 7 | 8 | 9 | process-classes 10 | org.codehaus.mojo:exec-maven-plugin:1.2.1:exec 11 | 12 | 13 | -classpath %classpath objectivetester.Wisard 14 | java 15 | 16 | 17 | 18 | debug 19 | 20 | jar 21 | 22 | 23 | process-classes 24 | org.codehaus.mojo:exec-maven-plugin:1.2.1:exec 25 | 26 | 27 | -Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -classpath %classpath objectivetester.Wisard 28 | java 29 | true 30 | 31 | 32 | 33 | profile 34 | 35 | jar 36 | 37 | 38 | process-classes 39 | org.codehaus.mojo:exec-maven-plugin:1.2.1:exec 40 | 41 | 42 | -classpath %classpath objectivetester.Wisard 43 | java 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | Wisard 5 | objectivetester 6 | Wisard 7 | 1.6 8 | jar 9 | 10 | 11 | org.seleniumhq.selenium 12 | selenium-java 13 | 4.10.0 14 | 15 | 16 | com.formdev 17 | flatlaf 18 | 2.6 19 | 20 | 21 | net.java.dev.jna 22 | jna-platform 23 | 5.13.0 24 | 25 | 26 | 27 | UTF-8 28 | 1.8 29 | 1.8 30 | -Xlint:unchecked 31 | 32 | 33 | 34 | 35 | org.apache.maven.plugins 36 | maven-compiler-plugin 37 | 3.11.0 38 | 39 | 1.8 40 | 1.8 41 | 42 | 43 | 44 | org.apache.maven.plugins 45 | maven-jar-plugin 46 | 3.3.0 47 | 48 | 49 | org.apache.maven.plugins 50 | maven-assembly-plugin 51 | 3.6.0 52 | 53 | 54 | jar-with-dependencies 55 | 56 | 57 | 58 | objectivetester.Wisard 59 | 60 | 61 | false 62 | 63 | 64 | 65 | package 66 | 67 | single 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /src/main/java/objectivetester/DefaultWriter.java: -------------------------------------------------------------------------------- 1 | package objectivetester; 2 | 3 | /** 4 | * 5 | * @author steve 6 | */ 7 | public class DefaultWriter { 8 | //browsermodel calls this and it updates the generated code 9 | 10 | UserInterface ui; 11 | int footer = 0; 12 | 13 | void writeHeader(String url, String browser) { 14 | } 15 | 16 | void writeFindEvent(String method, String attribute) { 17 | ui.insertCode("\n //find:" + attribute + "\n" 18 | + " element = driver.findElement(By." + method + "(\"" + attribute + "\"));" 19 | + "", footer); 20 | } 21 | 22 | void writeClickEvent(String method, String attribute) { 23 | ui.insertCode("\n //click:" + attribute + "\n" 24 | + " driver.findElement(By." + method + "(\"" + attribute + "\")).click();" 25 | + "", footer); 26 | } 27 | 28 | void writeInputEvent(String data) { 29 | ui.insertCode("\n element.clear();\n" 30 | + " element.sendKeys(\"" + data + "\");" 31 | + "", footer); 32 | } 33 | 34 | void writeSelectEvent(String data) { 35 | ui.insertCode("\n selector = new Select(element);\n" 36 | + " selector.selectByVisibleText(\"" + data + "\");" 37 | + "", footer); 38 | } 39 | 40 | void writeInputjsEvent(String jsInput) { 41 | ui.insertCode("\n js.executeScript(\"" + jsInput + "\");" 42 | + "", footer); 43 | } 44 | 45 | void writeAlertClick(String question, boolean choice) { 46 | String action; 47 | if (choice) { 48 | action = " alert.accept();\n"; 49 | } else { 50 | action = " alert.dismiss();\n"; 51 | } 52 | ui.insertCode("\n //alert:" + question + "\n" 53 | + " alert = driver.switchTo().alert();\n" 54 | + action 55 | + "", footer); 56 | } 57 | 58 | void writeSwitchByIndex(int frame) { 59 | ui.insertCode("\n //switch to:" + frame + "\n" 60 | + " driver.switchTo().frame(" + frame + ");" 61 | + "", footer); 62 | } 63 | 64 | void writeSwitchBack() { 65 | ui.insertCode("\n //switch back\n" 66 | + " driver.switchTo().defaultContent();" 67 | + "", footer); 68 | } 69 | 70 | void writeSwitchWin(String title) { 71 | ui.insertCode("\n //switch to:" + title + "\n" 72 | + " switchWin(driver, \"" + title + "\");" 73 | + "", footer); 74 | } 75 | 76 | void writeVerifyElement(String value, String method) { 77 | if (value != null) { 78 | value = "\"" + value + "\""; 79 | } 80 | 81 | String line; 82 | switch (method) { 83 | case "gettext": 84 | line = " assertEquals(" + value + ",element.getText());"; 85 | break; 86 | default: 87 | line = " assertEquals(" + value + ",element.getAttribute(\"" + method + "\"));"; 88 | } 89 | ui.insertCode("\n //assert:" + value + "\n" 90 | + line 91 | + "", footer); 92 | } 93 | 94 | void writeVerifyPage(String value) { 95 | if (value != null) { 96 | value = "\"" + value + "\""; 97 | } 98 | ui.insertCode("\n //assert:" + value + "\n" 99 | + " assertEquals(" + value + ", driver.getTitle());" 100 | + "", footer); 101 | } 102 | 103 | void writeVerifyCookie(String name, String value) { 104 | ui.insertCode("\n //assert:" + value + "\n" 105 | + " assertEquals(\"" + value + "\", driver.manage().getCookieNamed(\"" + name + "\").getValue().toString());" 106 | + "", footer); 107 | } 108 | 109 | void comment(String text) { 110 | ui.insertCode("\n //" + text + "\n", footer); 111 | } 112 | 113 | void writeStart() { 114 | } 115 | 116 | void writeEnd() { 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/main/java/objectivetester/TestWriter.java: -------------------------------------------------------------------------------- 1 | package objectivetester; 2 | 3 | /** 4 | * 5 | * @author Steve 6 | */ 7 | class TestWriter extends DefaultWriter { 8 | //browsermodel calls this and it updates the generated code 9 | //creates numbered junit test cases 10 | 11 | private int n; 12 | 13 | TestWriter(UserInterface ui) { 14 | this.n = 0; 15 | this.ui = ui; 16 | } 17 | 18 | @Override 19 | void writeHeader(String url, String browser) { 20 | String driverImport = ""; 21 | String sysProp = ""; 22 | String driverInit = ""; 23 | 24 | switch (browser) { 25 | 26 | case "FF": 27 | driverImport = "import org.openqa.selenium.firefox.FirefoxDriver;\n"; 28 | if (System.getProperty("webdriver.gecko.driver") != null) { 29 | sysProp = " System.setProperty(\"webdriver.gecko.driver\", \""+System.getProperty("webdriver.gecko.driver")+"\");\n"; 30 | } 31 | driverInit = " driver = new FirefoxDriver();\n"; 32 | break; 33 | 34 | case "CR": 35 | driverImport = "import org.openqa.selenium.chrome.ChromeDriver;\n"; 36 | if (System.getProperty("webdriver.chrome.driver") != null) { 37 | sysProp = " System.setProperty(\"webdriver.chrome.driver\", \""+System.getProperty("webdriver.chrome.driver")+"\");\n"; 38 | } 39 | driverInit = " driver = new ChromeDriver();\n"; 40 | break; 41 | 42 | case "ED": 43 | driverImport = "import org.openqa.selenium.edge.EdgeDriver;\n"; 44 | if (System.getProperty("webdriver.edge.driver") != null) { 45 | sysProp = " System.setProperty(\"webdriver.edge.driver\", \""+System.getProperty("webdriver.edge.driver")+"\");\n"; 46 | } 47 | driverInit = " WebDriver driver = new EdgeDriver();\n"; 48 | break; 49 | 50 | case "SA": 51 | driverImport = "import org.openqa.selenium.safari.SafariDriver;\n"; 52 | driverInit = " driver = new SafariDriver();\n"; 53 | break; 54 | } 55 | 56 | ui.addCode("import java.time.Duration;\n" 57 | + driverImport 58 | + "import org.openqa.selenium.JavascriptExecutor;\n" 59 | + "import org.openqa.selenium.WebDriver;\n" 60 | + "import org.openqa.selenium.WebElement;\n" 61 | + "import org.openqa.selenium.By;\n" 62 | + "import org.openqa.selenium.Alert;\n" 63 | + "import org.openqa.selenium.support.ui.Select;\n" 64 | + "import org.junit.After;\n" 65 | + "import org.junit.AfterClass;\n" 66 | + "import org.junit.Before;\n" 67 | + "import org.junit.BeforeClass;\n" 68 | + "import org.junit.Test;\n" 69 | + "import static org.junit.Assert.*;\n" 70 | + "import org.junit.FixMethodOrder;\n" 71 | + "import org.junit.runners.MethodSorters;\n\n" 72 | + "@FixMethodOrder(MethodSorters.NAME_ASCENDING)\n" 73 | + "public class RecordedTest {\n\n" 74 | + " public RecordedTest() {\n" 75 | + " }\n" 76 | + " WebElement element;\n" 77 | + " Alert alert;\n" 78 | + " Select selector;\n" 79 | + " static WebDriver driver;\n" 80 | + " static JavascriptExecutor js;\n\n" 81 | + " @BeforeClass\n" 82 | + " public static void setUpClass() {\n" 83 | + sysProp 84 | + driverInit 85 | + " js = (JavascriptExecutor) driver;\n" 86 | + " driver.manage().timeouts().pageLoadTimeout(Duration.ofSeconds(10));\n" 87 | + " driver.manage().timeouts().scriptTimeout(Duration.ofSeconds(10));\n" 88 | + " driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));\n" 89 | + " driver.get(\"" + url + "\");\n" 90 | + " }\n\n" 91 | + " @AfterClass\n" 92 | + " public static void tearDownClass() {\n" 93 | + " driver.quit();\n" 94 | + " }\n\n" 95 | + " public static void switchWin(WebDriver driver, String title) {\n" 96 | + " String target = driver.getWindowHandle();\n" 97 | + " for (String handle : driver.getWindowHandles()) {\n" 98 | + " driver.switchTo().window(handle);\n" 99 | + " if (driver.getTitle().equals(title)) {\n" 100 | + " target = handle;\n" 101 | + " }\n" 102 | + " }\n" 103 | + " driver.switchTo().window(target);\n" 104 | + " }\n" 105 | + "}\n"); 106 | footer = 18; //lines from the insert point to the bottom 107 | } 108 | 109 | @Override 110 | void writeStart() { 111 | n++; 112 | ui.insertCode("\n @Test\n" 113 | + " public void test" + n + "() {", footer); 114 | } 115 | 116 | @Override 117 | void writeEnd() { 118 | ui.insertCode("\n }\n", footer); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/main/java/objectivetester/Test5Writer.java: -------------------------------------------------------------------------------- 1 | package objectivetester; 2 | 3 | /** 4 | * 5 | * @author Steve 6 | */ 7 | class Test5Writer extends DefaultWriter { 8 | //browsermodel calls this and it updates the generated code 9 | //creates numbered junit5 test cases 10 | 11 | private int n; 12 | 13 | Test5Writer(UserInterface ui) { 14 | this.n = 0; 15 | this.ui = ui; 16 | } 17 | 18 | @Override 19 | void writeHeader(String url, String browser) { 20 | String driverImport = ""; 21 | String sysProp = ""; 22 | String driverInit = ""; 23 | 24 | switch (browser) { 25 | 26 | case "FF": 27 | driverImport = "import org.openqa.selenium.firefox.FirefoxDriver;\n"; 28 | if (System.getProperty("webdriver.gecko.driver") != null) { 29 | sysProp = " System.setProperty(\"webdriver.gecko.driver\", \"" + System.getProperty("webdriver.gecko.driver") + "\");\n"; 30 | } 31 | driverInit = " driver = new FirefoxDriver();\n"; 32 | break; 33 | 34 | case "CR": 35 | driverImport = "import org.openqa.selenium.chrome.ChromeDriver;\n"; 36 | if (System.getProperty("webdriver.chrome.driver") != null) { 37 | sysProp = " System.setProperty(\"webdriver.chrome.driver\", \"" + System.getProperty("webdriver.chrome.driver") + "\");\n"; 38 | } 39 | driverInit = " driver = new ChromeDriver();\n"; 40 | break; 41 | 42 | case "ED": 43 | driverImport = "import org.openqa.selenium.edge.EdgeDriver;\n"; 44 | if (System.getProperty("webdriver.edge.driver") != null) { 45 | sysProp = " System.setProperty(\"webdriver.edge.driver\", \"" + System.getProperty("webdriver.edge.driver") + "\");\n"; 46 | } 47 | driverInit = " WebDriver driver = new EdgeDriver();\n"; 48 | break; 49 | 50 | case "SA": 51 | driverImport = "import org.openqa.selenium.safari.SafariDriver;\n"; 52 | driverInit = " driver = new SafariDriver();\n"; 53 | break; 54 | } 55 | 56 | ui.addCode("import java.time.Duration;\n" 57 | + driverImport 58 | + "import org.openqa.selenium.JavascriptExecutor;\n" 59 | + "import org.openqa.selenium.WebDriver;\n" 60 | + "import org.openqa.selenium.WebElement;\n" 61 | + "import org.openqa.selenium.By;\n" 62 | + "import org.openqa.selenium.Alert;\n" 63 | + "import org.openqa.selenium.support.ui.Select;\n" 64 | + "import org.junit.jupiter.api.AfterAll;\n" 65 | + "import org.junit.jupiter.api.AfterEach;\n" 66 | + "import org.junit.jupiter.api.BeforeAll;\n" 67 | + "import org.junit.jupiter.api.BeforeEach;\n" 68 | + "import org.junit.jupiter.api.Test;\n" 69 | + "import static org.junit.jupiter.api.Assertions.*;\n" 70 | + "import org.junit.jupiter.api.TestMethodOrder;\n" 71 | + "import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;\n" 72 | + "import org.junit.jupiter.api.Order;\n\n" 73 | + "@TestMethodOrder(OrderAnnotation.class)\n" 74 | + "public class RecordedTest {\n\n" 75 | + " public RecordedTest() {\n" 76 | + " }\n" 77 | + " WebElement element;\n" 78 | + " Alert alert;\n" 79 | + " Select selector;\n" 80 | + " static WebDriver driver;\n" 81 | + " static JavascriptExecutor js;\n\n" 82 | + " @BeforeAll\n" 83 | + " public static void setUp() {\n" 84 | + sysProp 85 | + driverInit 86 | + " js = (JavascriptExecutor) driver;\n" 87 | + " driver.manage().timeouts().pageLoadTimeout(Duration.ofSeconds(10));\n" 88 | + " driver.manage().timeouts().scriptTimeout(Duration.ofSeconds(10));\n" 89 | + " driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));\n" 90 | + " driver.get(\"" + url + "\");\n" 91 | + " }\n\n" 92 | + " @AfterAll\n" 93 | + " public static void tearDown() {\n" 94 | + " driver.quit();\n" 95 | + " }\n\n" 96 | + " public static void switchWin(WebDriver driver, String title) {\n" 97 | + " String target = driver.getWindowHandle();\n" 98 | + " for (String handle : driver.getWindowHandles()) {\n" 99 | + " driver.switchTo().window(handle);\n" 100 | + " if (driver.getTitle().equals(title)) {\n" 101 | + " target = handle;\n" 102 | + " }\n" 103 | + " }\n" 104 | + " driver.switchTo().window(target);\n" 105 | + " }\n" 106 | + "}\n"); 107 | footer = 18; //lines from the insert point to the bottom 108 | } 109 | 110 | @Override 111 | void writeStart() { 112 | n++; 113 | ui.insertCode("\n @Test\n" 114 | + " @Order(" + n + ")\n" 115 | + " public void test" + n + "() {", footer); 116 | } 117 | 118 | @Override 119 | void writeEnd() { 120 | ui.insertCode("\n }\n", footer); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/main/java/objectivetester/ScriptWriter.java: -------------------------------------------------------------------------------- 1 | package objectivetester; 2 | 3 | /** 4 | * 5 | * @author Steve 6 | */ 7 | class ScriptWriter extends DefaultWriter { 8 | //browsermodel calls this and it updates the generated code 9 | //creates a java program - e.g. for task automation 10 | 11 | ScriptWriter(UserInterface ui) { 12 | this.ui = ui; 13 | } 14 | 15 | @Override 16 | void writeHeader(String url, String browser) { 17 | String driverImport = ""; 18 | String sysProp = ""; 19 | String driverInit = ""; 20 | 21 | switch (browser) { 22 | 23 | case "FF": 24 | driverImport = "import org.openqa.selenium.firefox.FirefoxDriver;\n"; 25 | if (System.getProperty("webdriver.gecko.driver") != null) { 26 | sysProp = " System.setProperty(\"webdriver.gecko.driver\", \""+System.getProperty("webdriver.gecko.driver")+"\");\n"; 27 | } 28 | driverInit = " WebDriver driver = new FirefoxDriver();\n"; 29 | break; 30 | 31 | case "CR": 32 | driverImport = "import org.openqa.selenium.chrome.ChromeDriver;\n"; 33 | if (System.getProperty("webdriver.chrome.driver") != null) { 34 | sysProp = " System.setProperty(\"webdriver.chrome.driver\", \""+System.getProperty("webdriver.chrome.driver")+"\");\n"; 35 | } 36 | driverInit = " WebDriver driver = new ChromeDriver();\n"; 37 | break; 38 | 39 | case "ED": 40 | driverImport = "import org.openqa.selenium.edge.EdgeDriver;\n"; 41 | if (System.getProperty("webdriver.edge.driver") != null) { 42 | sysProp = " System.setProperty(\"webdriver.edge.driver\", \""+System.getProperty("webdriver.edge.driver")+"\");\n"; 43 | } 44 | driverInit = " WebDriver driver = new EdgeDriver();\n"; 45 | break; 46 | 47 | case "SA": 48 | driverImport = "import org.openqa.selenium.safari.SafariDriver;\n"; 49 | driverInit = " WebDriver driver = new SafariDriver();\n"; 50 | break; 51 | } 52 | 53 | ui.addCode("import java.time.Duration;\n" 54 | + driverImport 55 | + "import org.openqa.selenium.JavascriptExecutor;\n" 56 | + "import org.openqa.selenium.WebDriver;\n" 57 | + "import org.openqa.selenium.WebElement;\n" 58 | + "import org.openqa.selenium.By;\n" 59 | + "import org.openqa.selenium.Alert;\n" 60 | + "import org.openqa.selenium.support.ui.Select;\n\n" 61 | + "public class RecordedScript {\n\n" 62 | + " public static void main(String[] args) {\n" 63 | + " WebElement element;\n" 64 | + " Alert alert;\n" 65 | + " Select selector;\n" 66 | + sysProp 67 | + driverInit 68 | + " JavascriptExecutor js = (JavascriptExecutor) driver;\n" 69 | + " driver.manage().timeouts().pageLoadTimeout(Duration.ofSeconds(10));\n" 70 | + " driver.manage().timeouts().scriptTimeout(Duration.ofSeconds(10));\n" 71 | + " driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));\n" 72 | + " driver.get(\"" + url + "\");\n\n\n" 73 | + " driver.quit();\n" 74 | + " }\n" 75 | + " public static void switchWin(WebDriver driver, String title) {\n" 76 | + " String target = driver.getWindowHandle();\n" 77 | + " for (String handle : driver.getWindowHandles()) {\n" 78 | + " driver.switchTo().window(handle);\n" 79 | + " if (driver.getTitle().equals(title)) {\n" 80 | + " target = handle;\n" 81 | + " }\n" 82 | + " }\n" 83 | + " driver.switchTo().window(target);\n" 84 | + " }\n" 85 | + "}\n"); 86 | footer = 16; //lines from the insert point to the bottom 87 | } 88 | 89 | @Override 90 | void writeVerifyElement(String value, String method) { 91 | String check = ".contentEquals(\"" + value + "\")"; 92 | if (value == null) { 93 | check = " == null"; 94 | } else { 95 | 96 | } 97 | ui.insertCode("\n //verify:" + value + "\n" 98 | + " if (element.getAttribute(\"" + method + "\")" + check + ") {\n" 99 | + " System.out.println(\"" + method + " = " + value + "\");\n" 100 | + " }" 101 | + "", footer); 102 | } 103 | 104 | @Override 105 | void writeVerifyPage(String value) { 106 | if (value != null) { 107 | value = "\"" + value + "\""; 108 | } 109 | ui.insertCode("\n //verify:" + value + "\n" 110 | + " if (driver.getTitle().contentEquals(" + value + ")) {\n" 111 | + " System.out.println(\"title= \" +" + value + ");\n" 112 | + " }" 113 | + "", footer); 114 | } 115 | 116 | @Override 117 | void writeVerifyCookie(String name, String value) { 118 | ui.insertCode("\n //verify:" + value + "\n" 119 | + " if (driver.manage().getCookieNamed(\"" + name + "\").getValue().contentEquals(\"" + value + "\")) {\n" 120 | + " System.out.println(\"" + name + " = " + value + "\");\n" 121 | + " }" 122 | + "", footer); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/objectivetester/JsWriter.java: -------------------------------------------------------------------------------- 1 | package objectivetester; 2 | 3 | /** 4 | * 5 | * @author Steve 6 | */ 7 | class JsWriter extends DefaultWriter { 8 | //browsermodel calls this and it updates the generated code 9 | //Webdriver.io v7 10 | 11 | private int n = 0; 12 | 13 | JsWriter(UserInterface ui) { 14 | this.n = 0; 15 | this.ui = ui; 16 | } 17 | 18 | @Override 19 | void writeHeader(String url, String browser) { 20 | ui.addCode("describe('webdriver.io v7 test suite', () => {\n\n" 21 | + " before(async () => {\n" 22 | + " browser.setTimeout(\n" 23 | + " { 'implicit': 60000 },\n" 24 | + " { 'pageLoad': 60000 },\n" 25 | + " { 'script': 60000 })\n" 26 | + " await browser.url('" + url + "')\n" 27 | + " })\n\n" 28 | + " after(async () => {\n" 29 | + " })\n\n" 30 | + "})\n"); 31 | footer = 3; //lines from the insert point to the bottom 32 | 33 | } 34 | 35 | @Override 36 | void writeFindEvent(String method, String attribute) { 37 | ui.insertCode("\n //find:" + attribute + "\n" 38 | + " const element = await $('" + wdioMethod(method, attribute) + "')" 39 | + "", footer); 40 | } 41 | 42 | @Override 43 | void writeClickEvent(String method, String attribute) { 44 | ui.insertCode("\n //click:" + attribute + "\n" 45 | + " await (await $('" + wdioMethod(method, attribute) + "')).click()" 46 | + "", footer); 47 | } 48 | 49 | @Override 50 | void writeInputEvent(String data) { 51 | ui.insertCode("\n element.setValue('" + data + "')" 52 | + "", footer); 53 | } 54 | 55 | @Override 56 | void writeSelectEvent(String data) { 57 | ui.insertCode("\n element.selectByVisibleText(\"" + data + "\")" 58 | + "", footer); 59 | } 60 | 61 | @Override 62 | void writeInputjsEvent(String jsInput) { 63 | ui.insertCode("\n browser.execute(\"" + jsInput + "\")" 64 | + "", footer); 65 | } 66 | 67 | @Override 68 | void writeAlertClick(String question, boolean choice) { 69 | String action; 70 | if (choice) { 71 | action = " browser.acceptAlert()\n"; 72 | } else { 73 | action = " browser.dismissAlert()\n"; 74 | } 75 | ui.insertCode("\n //alert:" + question + "\n" 76 | + action 77 | + "", footer); 78 | } 79 | 80 | @Override 81 | void writeSwitchByIndex(int frame) { 82 | ui.insertCode("\n //switch to:" + frame + "\n" 83 | + " await browser.switchToFrame(" + frame + ")" 84 | + "", footer); 85 | } 86 | 87 | @Override 88 | void writeSwitchBack() { 89 | ui.insertCode("\n //switch back\n" 90 | + " await browser.switchToParentFrame()" 91 | + "", footer); 92 | } 93 | 94 | @Override 95 | void writeSwitchWin(String title) { 96 | ui.insertCode("\n //switch to:" + title + "\n" 97 | + " await browser.switchWindow('" + title + "')" 98 | + "", footer); 99 | } 100 | 101 | @Override 102 | void writeVerifyElement(String value, String method) { 103 | if (value != null) { 104 | value = "'" + value + "'"; 105 | } 106 | String line; 107 | switch (method) { 108 | case "checked": 109 | if (value == null) { 110 | line = " await expect(element).not.toBeChecked()"; 111 | } else { 112 | line = " await expect(element).toBeChecked()"; 113 | } 114 | break; 115 | case "value": 116 | line = " await expect(element).toHaveValue(" + value + ")"; 117 | break; 118 | case "href": 119 | line = " await expect(element).toHaveHref(" + value + ")"; 120 | break; 121 | case "gettext": 122 | line = " await expect(element).toHaveText([" + value + "])"; 123 | break; 124 | default: 125 | line = " await expect(element).toHaveAttr('" + method + "', " + value + ")"; 126 | } 127 | ui.insertCode("\n //assert:" + value + "\n" 128 | + line 129 | + "", footer); 130 | } 131 | 132 | @Override 133 | void writeVerifyPage(String value) { 134 | if (value != null) { 135 | value = "'" + value + "'"; 136 | } 137 | ui.insertCode("\n //assert:" + value + "\n" 138 | + " await expect(browser).toHaveTitle(" + value + ")" 139 | + "", footer); 140 | } 141 | 142 | @Override 143 | void writeVerifyCookie(String name, String value) { 144 | ui.insertCode("\n //assert:" + value + "\n" 145 | + " expect(browser.getCookies(['" + name + "'])).toHaveValue('" + value.replaceAll("\"", "'") + "')" 146 | + "", footer); 147 | } 148 | 149 | @Override 150 | void comment(String text) { 151 | ui.insertCode("\n //" + text + "\n", footer); 152 | } 153 | 154 | @Override 155 | void writeStart() { 156 | n++; 157 | ui.insertCode("\n it('test " + n + "', async () => {", footer); 158 | } 159 | 160 | @Override 161 | void writeEnd() { 162 | ui.insertCode("\n })\n", footer); 163 | } 164 | 165 | String wdioMethod(String method, String attribute) { 166 | switch (method) { 167 | case "linkText": 168 | return "=" + attribute; 169 | case "name": 170 | return "[name=\"" + attribute + "\"]"; 171 | case "id": 172 | return "#" + attribute; 173 | case "cssSelector": 174 | return attribute.replaceAll("'", "\""); 175 | case "className": 176 | return "." + attribute; 177 | default: 178 | return attribute; 179 | } 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /src/main/java/objectivetester/EventListener.java: -------------------------------------------------------------------------------- 1 | package objectivetester; 2 | 3 | import java.awt.event.ActionEvent; 4 | import java.awt.event.MouseAdapter; 5 | import java.awt.event.MouseEvent; 6 | import java.util.ArrayList; 7 | import javax.swing.JPopupMenu; 8 | import javax.swing.JTable; 9 | import org.openqa.selenium.WebElement; 10 | 11 | /** 12 | * 13 | * @author Steve 14 | */ 15 | class EventListener extends MouseAdapter implements java.awt.event.ActionListener { 16 | 17 | JPopupMenu popup; 18 | JTable table; 19 | BrowserDriver bd; 20 | int current; 21 | 22 | EventListener(JPopupMenu popup, JTable table, BrowserDriver bd) { 23 | this.popup = popup; 24 | this.table = table; 25 | this.bd = bd; 26 | } 27 | 28 | @Override 29 | public void mouseClicked(MouseEvent e) { 30 | } 31 | 32 | @Override 33 | public void mousePressed(MouseEvent e) { 34 | if (bd.safe) { 35 | //dont allow unsafe interactions until the examiner has finished 36 | clickEvent(e); 37 | popupEvent(e); 38 | } 39 | } 40 | 41 | @Override 42 | public void mouseReleased(MouseEvent e) { 43 | if (bd.safe) { 44 | //dont allow unsafe interactions until the examiner has finished 45 | popupEvent(e); 46 | } 47 | } 48 | 49 | private void popupEvent(MouseEvent e) { 50 | if (e.isPopupTrigger()) { 51 | //reenable all choices 52 | popup.getComponent(Const.POP_CLICK).setEnabled(true); //click 53 | popup.getComponent(Const.POP_FIND).setEnabled(true); //find 54 | popup.getComponent(Const.POP_ASSERT).setEnabled(true); //assert 55 | popup.getComponent(Const.POP_ID).setEnabled(true); //identify 56 | 57 | int idx = table.rowAtPoint(e.getPoint()); 58 | table.getSelectionModel().setSelectionInterval(idx, idx); 59 | current = table.getSelectedRow(); 60 | 61 | //disable the invalid choices 62 | if ((table.getValueAt(current, Const.TAB_ELEMENT).toString().contentEquals(Const.TITLE))) { 63 | //cant elementFind or ident a page, so grey it out 64 | popup.getComponent(Const.POP_FIND).setEnabled(false); 65 | popup.getComponent(Const.POP_ID).setEnabled(false); 66 | if (!(table.getValueAt(current, Const.TAB_LOCATION).toString().contentEquals(Const.CURRENT))) { 67 | //cant assert other pages 68 | popup.getComponent(Const.POP_ASSERT).setEnabled(false); 69 | } else { 70 | //cant click on current page 71 | popup.getComponent(Const.POP_CLICK).setEnabled(false); 72 | } 73 | } 74 | if (table.getValueAt(current, Const.TAB_ELEMENT).toString().contentEquals(Const.COOKIE)) { 75 | //can only assert and change a cookie 76 | popup.getComponent(Const.POP_CLICK).setEnabled(false); 77 | popup.getComponent(Const.POP_ID).setEnabled(false); 78 | popup.getComponent(Const.POP_FIND).setEnabled(false); 79 | } 80 | if (table.getValueAt(current, Const.TAB_ELEMENT).toString().contentEquals("form") && !table.getValueAt(current, Const.TAB_ELEMENT).toString().contains(":")) { 81 | //can only assert form elements, not forms 82 | popup.getComponent(Const.POP_CLICK).setEnabled(false); 83 | popup.getComponent(Const.POP_ASSERT).setEnabled(false); 84 | } 85 | if (table.getValueAt(current, Const.TAB_ELEMENT).toString().endsWith(":hidden")) { 86 | //cant click or id hidden form fields 87 | popup.getComponent(Const.POP_CLICK).setEnabled(false); 88 | popup.getComponent(Const.POP_ID).setEnabled(false); 89 | } 90 | if (table.getValueAt(current, Const.TAB_ELEMENT).toString().startsWith(Const.INVISIBLE)) { 91 | //cant click or id invisible objects 92 | popup.getComponent(Const.POP_CLICK).setEnabled(false); 93 | popup.getComponent(Const.POP_ID).setEnabled(false); 94 | } 95 | //show the popup menu 96 | popup.show(e.getComponent(), e.getX(), e.getY()); 97 | } 98 | } 99 | 100 | private void clickEvent(MouseEvent e) { 101 | int idx = table.rowAtPoint(e.getPoint()); 102 | table.getSelectionModel().setSelectionInterval(idx, idx); 103 | current = table.getSelectedRow(); 104 | Object stack; 105 | String element = table.getModel().getValueAt(current, Const.TAB_ELEMENT).toString(); 106 | if (table.getModel().getValueAt(current, Const.TAB_LOCATION).getClass().equals(String.class)) { 107 | stack = (String) table.getModel().getValueAt(current, Const.TAB_LOCATION); 108 | } else { 109 | stack = (ArrayList) table.getModel().getValueAt(current, Const.TAB_LOCATION); 110 | } 111 | Object webElement = table.getModel().getValueAt(current, Const.TAB_WEBELEMENT); 112 | //if it's an element, highlight it 113 | //the element column is only in the model, so use the model to retreive it 114 | if (!element.contentEquals(Const.TITLE) && !element.startsWith(Const.INVISIBLE) && !element.contentEquals(Const.COOKIE)) { 115 | bd.highlight((WebElement) webElement, stack); 116 | } 117 | } 118 | 119 | @Override 120 | public void actionPerformed(ActionEvent e) { 121 | String element = table.getModel().getValueAt(current, Const.TAB_ELEMENT).toString(); 122 | Object stack; 123 | if (table.getModel().getValueAt(current, Const.TAB_LOCATION).getClass().equals(String.class)) { 124 | stack = (String) table.getModel().getValueAt(current, Const.TAB_LOCATION); 125 | } else { 126 | stack = (ArrayList) table.getModel().getValueAt(current, Const.TAB_LOCATION); 127 | } 128 | String name = table.getModel().getValueAt(current, Const.TAB_NAME).toString(); 129 | String id = table.getModel().getValueAt(current, Const.TAB_ID).toString(); 130 | Object value = table.getModel().getValueAt(current, Const.TAB_VALUE); 131 | Object webElement = table.getModel().getValueAt(current, Const.TAB_WEBELEMENT); 132 | //clicking on an element 133 | if (e.getActionCommand().contentEquals(Const.CLICK)) { 134 | if (element.contains("date") || element.contains("datetime-local") || element.contains("email") || element.contains("file") || element.contains("month") || element.contains("number") || element.contains("password") || element.contains("search") || element.contains("tel") || element.contains("text") || element.contains("time") || element.contains("url") || element.contains("week")) { 135 | //input element 136 | bd.input((WebElement) webElement, stack); 137 | } else if (element.endsWith(":select-one")) { 138 | //selection 139 | bd.select((WebElement) webElement, stack); 140 | } else if (element.contentEquals(Const.TITLE)) { 141 | //page title 142 | bd.switchWin((String) webElement, (String) value); 143 | } else if (element.endsWith(":range") || element.endsWith(":color")) { 144 | //special input 145 | bd.inputjs((WebElement) webElement, stack); 146 | } else { 147 | //clickable 148 | bd.click((WebElement) webElement, stack); 149 | } 150 | } 151 | 152 | //finding an element 153 | if (e.getActionCommand() 154 | .contentEquals(Const.FIND)) { 155 | if (element.contentEquals(Const.TITLE)) { 156 | //page title 157 | } else { 158 | //page element 159 | bd.find((WebElement) webElement, stack, Const.FIND); 160 | } 161 | } 162 | 163 | //asserting the value of an element 164 | if (e.getActionCommand() 165 | .contentEquals(Const.ASSERT)) { 166 | if (element.contentEquals(Const.TITLE)) { 167 | //page title 168 | bd.verifyPage((String) value); 169 | } else if (element.contentEquals(Const.COOKIE)) { 170 | bd.verifyCookie((String) name, (String) value); 171 | } else { 172 | //page element 173 | bd.verify((WebElement) webElement, stack, element, (String) value); 174 | } 175 | } 176 | 177 | //identifying an element 178 | if (e.getActionCommand() 179 | .contentEquals(Const.IDENTIFY)) { 180 | if (element.contentEquals(Const.TITLE)) { 181 | //page title 182 | } else { 183 | //page element 184 | bd.ident((WebElement) webElement, stack, (String) element, name, id, (String) value); 185 | 186 | } 187 | } 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /src/main/java/objectivetester/BrowserDriver.java: -------------------------------------------------------------------------------- 1 | package objectivetester; 2 | 3 | /** 4 | * 5 | * @author Steve 6 | */ 7 | import java.time.Duration; 8 | import java.util.ArrayList; 9 | import java.util.Arrays; 10 | import java.util.List; 11 | import java.util.Set; 12 | import org.openqa.selenium.Alert; 13 | import org.openqa.selenium.By; 14 | import org.openqa.selenium.Cookie; 15 | import org.openqa.selenium.ElementNotInteractableException; 16 | import org.openqa.selenium.InvalidArgumentException; 17 | import org.openqa.selenium.InvalidSelectorException; 18 | import org.openqa.selenium.JavascriptExecutor; 19 | import org.openqa.selenium.NoAlertPresentException; 20 | import org.openqa.selenium.NoSuchFrameException; 21 | import org.openqa.selenium.SessionNotCreatedException; 22 | import org.openqa.selenium.StaleElementReferenceException; 23 | import org.openqa.selenium.TimeoutException; 24 | import org.openqa.selenium.WebDriver; 25 | import org.openqa.selenium.WebDriverException; 26 | import org.openqa.selenium.WebElement; 27 | import org.openqa.selenium.chrome.ChromeDriver; 28 | import org.openqa.selenium.edge.EdgeDriver; 29 | import org.openqa.selenium.firefox.FirefoxDriver; 30 | import org.openqa.selenium.remote.NoSuchDriverException; 31 | import org.openqa.selenium.safari.SafariDriver; 32 | import org.openqa.selenium.support.ui.*; 33 | 34 | class BrowserDriver implements Runnable { 35 | 36 | WebDriver driver; 37 | JavascriptExecutor js; 38 | UserInterface ui; 39 | DefaultWriter writer; 40 | boolean safe = false; 41 | ArrayList CSSselectors; 42 | ArrayList allElements; 43 | 44 | BrowserDriver(UserInterface ui) { 45 | this.ui = ui; 46 | } 47 | 48 | void initWriter(String selected) { 49 | switch (selected) { 50 | case "junit": 51 | writer = new TestWriter(ui); 52 | break; 53 | case "junit5": 54 | writer = new Test5Writer(ui); 55 | break; 56 | case "js": 57 | writer = new JsWriter(ui); 58 | break; 59 | default: 60 | writer = new ScriptWriter(ui); 61 | break; 62 | } 63 | } 64 | 65 | boolean initFF(String url, String path) { 66 | //FF 67 | try { 68 | if (!path.isEmpty()) { 69 | System.setProperty("webdriver.gecko.driver", path); 70 | } 71 | driver = new FirefoxDriver(); 72 | js = (JavascriptExecutor) driver; 73 | writer.writeHeader(url, "FF"); 74 | driver.get(url); 75 | } catch (NoSuchDriverException nde) { 76 | System.err.println(nde); 77 | ui.errorMessage("Path to Gecko driver is invalid, check settings."); 78 | return false; 79 | } catch (InvalidArgumentException iae) { 80 | System.err.println(iae); 81 | ui.errorMessage("Invalid URL?"); 82 | return false; 83 | } catch (Exception e) { 84 | System.err.println(e); 85 | return false; 86 | } 87 | return true; 88 | } 89 | 90 | boolean initCR(String url, String path) { 91 | //Chrome 92 | try { 93 | if (!path.isEmpty()) { 94 | System.setProperty("webdriver.chrome.driver", path); 95 | } 96 | driver = new ChromeDriver(); 97 | js = (JavascriptExecutor) driver; 98 | writer.writeHeader(url, "CR"); 99 | driver.get(url); 100 | } catch (NoSuchDriverException nde) { 101 | System.err.println(nde); 102 | ui.errorMessage("Path to Chrome driver is invalid, check settings."); 103 | return false; 104 | } catch (InvalidArgumentException iae) { 105 | System.err.println(iae); 106 | ui.errorMessage("Invalid URL?"); 107 | return false; 108 | } catch (Exception e) { 109 | System.err.println(e); 110 | return false; 111 | } 112 | return true; 113 | } 114 | 115 | boolean initED(String url, String path) { 116 | //Edge 117 | try { 118 | if (!path.isEmpty()) { 119 | System.setProperty("webdriver.edge.driver", path); 120 | } 121 | driver = new EdgeDriver(); 122 | js = (JavascriptExecutor) driver; 123 | writer.writeHeader(url, "ED"); 124 | driver.get(url); 125 | } catch (NoSuchDriverException nde) { 126 | System.err.println(nde); 127 | ui.errorMessage("Path to Edge driver is invalid, check settings."); 128 | return false; 129 | } catch (InvalidArgumentException iae) { 130 | ui.errorMessage("Invalid URL?"); 131 | return false; 132 | } catch (Exception e) { 133 | System.err.println(e); 134 | return false; 135 | } 136 | return true; 137 | } 138 | 139 | boolean initSA(String url) { 140 | //Safari 141 | try { 142 | driver = new SafariDriver(); 143 | js = (JavascriptExecutor) driver; 144 | writer.writeHeader(url, "SA"); 145 | driver.get(url); 146 | } catch (SessionNotCreatedException e) { 147 | ui.errorMessage(e.getMessage().substring(0, e.getMessage().indexOf(10))); 148 | return false; 149 | } catch (Exception e) { 150 | System.err.println(e); 151 | return false; 152 | } 153 | return true; 154 | } 155 | 156 | @Override 157 | public void run() { 158 | if (driver != null) { 159 | safe = false; 160 | 161 | //get list of CSS selectors to search for 162 | String[] selectors = ui.getCSSselectors().split("\\s*,\\s*"); 163 | CSSselectors = new ArrayList<>(Arrays.asList(selectors)); 164 | 165 | //reset element list 166 | allElements = new ArrayList<>(); 167 | 168 | driver.manage().timeouts().implicitlyWait(Duration.ofMillis(10)); 169 | //examine the root contents 170 | examine(Const.PAGE); 171 | ui.finished(); 172 | safe = true; 173 | } 174 | } 175 | 176 | void examine(Object stack) { 177 | try { 178 | String value; 179 | driver.switchTo().defaultContent(); 180 | 181 | if ((stack.getClass().equals(String.class)) && ((String) stack).equals(Const.PAGE)) { 182 | String current = driver.getWindowHandle(); 183 | //indicate current window 184 | ui.addItem(Const.TITLE, (Object) Const.CURRENT, "", "", driver.getTitle(), current, true); 185 | //show all available windows 186 | List winList = new ArrayList<>(driver.getWindowHandles()); 187 | for (String handle : winList) { 188 | driver.switchTo().window(handle); 189 | if (!handle.contentEquals(current)) { 190 | ui.addItem(Const.TITLE, Const.WINDOW, "", "", driver.getTitle(), handle, true); 191 | } 192 | } 193 | driver.switchTo().window(current); 194 | 195 | //get cookies 196 | Set cookies = driver.manage().getCookies(); 197 | for (Cookie c : cookies) { 198 | ui.addItem(Const.COOKIE, Const.BROWSER, c.getName(), c.getDomain() + c.getPath(), c.getValue(), null, true); 199 | } 200 | 201 | } else { 202 | //drill down the frames stack 203 | traverse((ArrayList) stack, false); 204 | } 205 | 206 | try { 207 | //links 208 | //System.out.println("links:" + Integer.parseInt((js.executeScript("return document.links.length;")).toString())); 209 | List links = (List) (js.executeScript("return document.links;")); 210 | for (WebElement element : links) { 211 | ui.addItem("link", stack, element.getAttribute("text").trim(), element.getAttribute("id"), element.getAttribute("href"), element, element.isDisplayed()); 212 | allElements.add(element); 213 | } 214 | } catch (Exception e) { 215 | //ui.errorMessage("Failed to find links"); 216 | } 217 | 218 | try { 219 | //forms 220 | //System.out.println("forms:" + Integer.parseInt((js.executeScript("return document.forms.length;")).toString())); 221 | //you can't return all the forms, so do each individually 222 | int i = 0; 223 | WebElement form = (WebElement) ((js.executeScript("return document.forms[" + i + "];"))); 224 | while (form != null) { 225 | ui.addItem("form" + i, stack, form.getAttribute("name"), form.getAttribute("id"), "", form, form.isDisplayed()); 226 | allElements.add(form); 227 | //System.out.println("form " + i + ", " + Integer.parseInt((js.executeScript("return document.forms[" + i + "].length;")).toString()) + " elements"); 228 | 229 | List formElement = (List) (js.executeScript("return document.forms[" + i + "].elements;")); 230 | for (WebElement element : formElement) { 231 | if ((element.getAttribute("type").contentEquals("radio")) || (element.getAttribute("type").contentEquals("checkbox"))) { 232 | value = element.getAttribute("checked"); 233 | } else { 234 | value = element.getAttribute("value"); 235 | } 236 | 237 | ui.addItem("form" + i + ":" + element.getAttribute("type"), stack, element.getAttribute("name"), element.getAttribute("id"), value, element, element.isDisplayed()); 238 | allElements.add(element); 239 | } 240 | i++; 241 | form = (WebElement) ((js.executeScript("return document.forms[" + i + "];"))); 242 | } 243 | } catch (Exception e) { 244 | //ui.errorMessage("Failed to find form content"); 245 | } 246 | 247 | try { 248 | //non-form input elements 249 | List inputs = driver.findElements(By.tagName("input")); 250 | inputs.addAll(driver.findElements(By.tagName("select"))); 251 | inputs.addAll(driver.findElements(By.tagName("button"))); 252 | 253 | for (WebElement element : inputs) { 254 | //see if we've added this webElement already 255 | Boolean present = false; 256 | for (WebElement in : allElements) { 257 | if (in.equals(element)) { 258 | present = true; 259 | } 260 | } 261 | if (!present) { 262 | if ((element.getAttribute("type").contentEquals("radio")) || (element.getAttribute("type").contentEquals("checkbox"))) { 263 | value = element.getAttribute("checked"); 264 | } else { 265 | value = element.getAttribute("value"); 266 | } 267 | ui.addItem("input:" + element.getAttribute("type"), stack, element.getAttribute("name"), element.getAttribute("id"), value, element, element.isDisplayed()); 268 | allElements.add(element); 269 | } 270 | 271 | } 272 | } catch (Exception e) { 273 | //ui.errorMessage("Failed to find input elements"); 274 | } 275 | 276 | try { 277 | //images 278 | //System.out.println("images:" + Integer.parseInt((js.executeScript("return document.images.length;")).toString())); 279 | List images = (List) (js.executeScript("return document.images;")); 280 | for (WebElement element : images) { 281 | ui.addItem("image", stack, element.getAttribute("alt"), element.getAttribute("id"), element.getAttribute("src"), element, element.isDisplayed()); 282 | allElements.add(element); 283 | } 284 | } catch (Exception e) { 285 | //ui.errorMessage("Failed to find images"); 286 | } 287 | 288 | try { 289 | //anchors 290 | //System.out.println("anchors:" + Integer.parseInt((js.executeScript("return document.anchors.length;")).toString())); 291 | List anchors = (List) (js.executeScript("return document.anchors;")); 292 | for (WebElement element : anchors) { 293 | ui.addItem("anchor", stack, element.getAttribute("text"), element.getAttribute("id"), element.getAttribute("name"), element, element.isDisplayed()); 294 | allElements.add(element); 295 | } 296 | } catch (Exception e) { 297 | //ui.errorMessage("Failed to find anchors"); 298 | } 299 | 300 | //custom CSS selectors 301 | if (CSSselectors.get(0).length() != 0) { 302 | for (String item : CSSselectors) { 303 | try { 304 | List custom = (List) driver.findElements(By.cssSelector(item)); 305 | for (WebElement element : custom) { 306 | String elementVal = element.getAttribute("value"); 307 | if (elementVal == null) { 308 | elementVal = element.getText(); 309 | } 310 | ui.addItem(element.getTagName().toLowerCase(), stack, element.getAttribute("id"), item, elementVal, element, element.isDisplayed()); 311 | allElements.add(element); 312 | } 313 | } catch (Exception e) { 314 | //ui.errorMessage("Failed to find custom"); 315 | } 316 | } 317 | } 318 | 319 | boolean validFrame = true; 320 | int frame = 0; 321 | while (validFrame) { 322 | try { 323 | driver.switchTo().frame(frame); 324 | } catch (NoSuchFrameException nse) { 325 | validFrame = false; 326 | } 327 | 328 | if (validFrame) { 329 | if (stack.getClass().equals(String.class)) { 330 | stack = new ArrayList<>(); 331 | } 332 | driver.switchTo().parentFrame(); 333 | ArrayList newstack = new ArrayList<>((ArrayList) stack); 334 | newstack.add(frame); 335 | 336 | //down the rabbit hole.... 337 | examine(newstack); 338 | 339 | //restore original position 340 | driver.switchTo().parentFrame(); 341 | 342 | frame++; 343 | } 344 | } 345 | 346 | } catch (TimeoutException | StaleElementReferenceException | ElementNotInteractableException e) { 347 | ui.rescan(); 348 | } catch (WebDriverException e) { 349 | ui.abort(); 350 | } 351 | } 352 | 353 | void close() { 354 | if (driver != null) { 355 | try { 356 | driver.quit(); 357 | driver = null; 358 | } catch (WebDriverException e) { 359 | driver = null; 360 | } 361 | } 362 | } 363 | 364 | private void traverse(ArrayList stack, Boolean write) { 365 | for (int item = 0; item < stack.size(); item++) { 366 | int nextFrame = (int) stack.get(item); 367 | if (write) { 368 | writer.writeSwitchByIndex(nextFrame); 369 | } 370 | driver.switchTo().frame(nextFrame); 371 | } 372 | } 373 | 374 | void highlight(WebElement webElement, Object stack) { 375 | try { 376 | driver.switchTo().defaultContent(); 377 | //drill down the frames 378 | if (stack.getClass().equals(ArrayList.class)) { 379 | traverse((ArrayList) stack, false); 380 | } 381 | js.executeScript("arguments[0].scrollIntoView(true);", webElement); 382 | String style = webElement.getAttribute("style"); 383 | //System.out.println(webElement + style); 384 | js.executeScript("arguments[0].setAttribute('style', " + Const.HIGHLIGHT + ");", webElement); 385 | Thread.sleep(500); 386 | js.executeScript("arguments[0].setAttribute('style', 'arguments[1]');", webElement, style); 387 | } catch (TimeoutException | StaleElementReferenceException e) { 388 | ui.rescan(); 389 | } catch (ElementNotInteractableException | InterruptedException e) { 390 | } catch (WebDriverException e) { 391 | ui.abort(); 392 | } 393 | } 394 | 395 | RichElement elementFind(WebElement webElement, Object stack, String action) { 396 | driver.switchTo().defaultContent(); 397 | //see if we can elementFind it first 398 | if (stack.getClass().equals(ArrayList.class)) { 399 | traverse((ArrayList) stack, false); 400 | } 401 | js.executeScript("arguments[0].scrollIntoView(true);", webElement); 402 | String name = webElement.getText(); 403 | RichElement ele = elementFinder(webElement); 404 | driver.switchTo().defaultContent(); 405 | if (ele.method != null) { 406 | //we can elementFind it, so write code to navigate 407 | if (stack.getClass().equals(ArrayList.class)) { 408 | //navigate to the webElement 409 | traverse((ArrayList) stack, true); 410 | } 411 | if (!action.equals(Const.CLICK)) { 412 | //write code to get the element 413 | writer.writeFindEvent(ele.method, ele.attribute); 414 | } 415 | 416 | //if we're just doing a elementFind, tidy up 417 | if (action.equals(Const.FIND)) { 418 | if (stack.getClass().equals(ArrayList.class)) { 419 | //if we had to navigate here, switch back 420 | writer.writeSwitchBack(); 421 | } 422 | 423 | } 424 | 425 | } else { 426 | //failed to elementFind the webElement 427 | 428 | ui.errorMessage("Unable to uniquely identify " + name); 429 | writer.comment("Unable to uniquely identify " + name); 430 | } 431 | return ele; 432 | } 433 | 434 | void find(WebElement webElement, Object stack, String action) { 435 | writer.writeStart(); 436 | elementFind(webElement, stack, action); 437 | writer.writeEnd(); 438 | } 439 | 440 | void click(WebElement webElement, Object stack) { 441 | writer.writeStart(); 442 | RichElement ele = elementFind(webElement, stack, Const.CLICK); 443 | if (ele.method != null) { 444 | writer.writeClickEvent(ele.method, ele.attribute); 445 | if (driver.getClass().getName().contains("SafariDriver")) { 446 | //workaround for a click problem with Safari that only happens in Wisard 447 | js.executeScript("arguments[0].click();", webElement); 448 | } else { 449 | webElement.click(); 450 | } 451 | 452 | //if that caused an alert to popup, deal with it 453 | //prompting alerts are not dealt with yet, but are supported in webdriver 454 | //does anyone really use them? 455 | try { 456 | Alert alert = driver.switchTo().alert(); 457 | if (alert != null) { 458 | String title = alert.getText(); 459 | Boolean action = ui.alertResponse(title); 460 | if (action == false) { 461 | alert.dismiss(); 462 | } else { 463 | alert.accept(); 464 | } 465 | writer.writeAlertClick(title, action); 466 | ui.rescan(); 467 | } 468 | } catch (NoAlertPresentException na) { 469 | //System.out.println("no alert"); 470 | } 471 | 472 | if (stack.getClass().equals(ArrayList.class)) { 473 | //if we had to navigate here, switch back 474 | writer.writeSwitchBack(); 475 | } 476 | driver.switchTo().defaultContent(); 477 | } 478 | writer.writeEnd(); 479 | } 480 | 481 | void input(WebElement webElement, Object stack) { 482 | String data = ui.enterValue(webElement.getAttribute("name")); 483 | if (data != null) { 484 | writer.writeStart(); 485 | RichElement ele = elementFind(webElement, stack, ""); 486 | if (ele.method != null) { 487 | writer.writeInputEvent(data); 488 | if (stack.getClass().equals(ArrayList.class)) { 489 | //if we had to navigate here, switch back 490 | writer.writeSwitchBack(); 491 | } 492 | webElement.clear(); 493 | webElement.sendKeys(data); 494 | driver.switchTo().defaultContent(); 495 | } 496 | writer.writeEnd(); 497 | } 498 | } 499 | 500 | void inputjs(WebElement webElement, Object stack) { 501 | String data = ui.enterValue(webElement.getAttribute("name")); 502 | if (data != null) { 503 | writer.writeStart(); 504 | RichElement ele = elementFind(webElement, stack, "click"); 505 | if (ele.method != null) { 506 | 507 | //this only works if the first match is the right element 508 | String jsInput = "javascript:var e=document.getElementsByName(\"" + ele.attribute + "\");e[0].value=\"" + data + "\";"; 509 | 510 | if (ele.method.contentEquals("id")) { 511 | jsInput = "javascript:document.getElementById(\"" + ele.attribute + "\").value=\"" + data + "\";"; 512 | } 513 | if (ele.method.contentEquals("cssSelector")) { 514 | jsInput = jsInput.replace("getElementsByName", "querySelectorAll"); 515 | } 516 | if (ele.method.contentEquals("className")) { 517 | jsInput = jsInput.replace("getElementsByName", "getElementsByClassName"); 518 | } 519 | writer.writeInputjsEvent(jsInput.replace("\"", "\\\"")); 520 | if (stack.getClass().equals(ArrayList.class)) { 521 | //if we had to navigate here, switch back 522 | writer.writeSwitchBack(); 523 | } 524 | js.executeScript(jsInput); 525 | driver.switchTo().defaultContent(); 526 | } 527 | writer.writeEnd(); 528 | } 529 | } 530 | 531 | void select(WebElement webElement, Object stack) { 532 | //extract the choices 533 | Select selector = new Select(webElement); 534 | List selectOptions = selector.getOptions(); 535 | List items = new ArrayList<>(); 536 | for (WebElement option : selectOptions) { 537 | items.add(option.getText()); 538 | } 539 | String[] choices = items.toArray(new String[0]); 540 | //make a choice 541 | String data = ui.enterSelection(webElement.getAttribute("name"), choices); 542 | if (data != null) { 543 | writer.writeStart(); 544 | RichElement ele = elementFind(webElement, stack, ""); 545 | if (ele.method != null) { 546 | writer.writeSelectEvent(data); 547 | if (stack.getClass().equals(ArrayList.class)) { 548 | //if we had to navigate here, switch back 549 | writer.writeSwitchBack(); 550 | } 551 | selector.selectByVisibleText(data); 552 | driver.switchTo().defaultContent(); 553 | writer.writeEnd(); 554 | } 555 | } 556 | 557 | } 558 | 559 | void verify(WebElement webElement, Object stack, String element, String expected) { 560 | writer.writeStart(); 561 | RichElement ele = elementFind(webElement, stack, ""); 562 | if (ele.method != null) { 563 | String verifymethod; 564 | if (element.contains("link")) { 565 | verifymethod = "href"; 566 | } else if (element.contains("image")) { 567 | verifymethod = "src"; 568 | } else if (element.contains("anchor")) { 569 | verifymethod = "name"; 570 | } else if (element.contains("radio") || element.contains("checkbox")) { 571 | verifymethod = "checked"; 572 | } else if (webElement.getAttribute("value") == null) { 573 | verifymethod = "gettext"; 574 | } else { 575 | verifymethod = "value"; 576 | } 577 | 578 | //System.out.println("expected:" + expected); 579 | //System.out.println("actual:" + webElement.getAttribute(verifymethod)); 580 | //System.out.println("using:" + verifymethod); 581 | writer.writeVerifyElement(expected, verifymethod); 582 | 583 | if (stack.getClass().equals(ArrayList.class)) { 584 | //if we had to navigate here, switch back 585 | writer.writeSwitchBack(); 586 | } 587 | } 588 | writer.writeEnd(); 589 | } 590 | 591 | void verifyPage(String expected) { 592 | writer.writeStart(); 593 | writer.writeVerifyPage(expected); 594 | writer.writeEnd(); 595 | } 596 | 597 | void verifyCookie(String name, String expected) { 598 | writer.writeStart(); 599 | writer.writeVerifyCookie(name, expected); 600 | writer.writeEnd(); 601 | } 602 | 603 | void ident(WebElement webElement, Object stack, String element, String name, String id, String value) { 604 | driver.switchTo().defaultContent(); 605 | if (stack.getClass().equals(ArrayList.class)) { 606 | traverse((ArrayList) stack, false); 607 | } 608 | 609 | RichElement ele = elementFinder(webElement); 610 | String method = "not found!"; 611 | if (ele.method != null) { 612 | method = "By." + ele.method + "(\"" + ele.attribute + "\")"; 613 | } 614 | 615 | String message = "Element: " + element 616 | + "
Name: " + name 617 | + "
ID: " + id 618 | + "
Value: " + value 619 | + "
Location: " + stack.toString() 620 | + "
Find Method: " + method 621 | + "
Outer HTML:" 622 | + "
" + webElement.getAttribute("outerHTML"); 623 | 624 | try { 625 | String style = webElement.getAttribute("style"); 626 | //System.out.println(webElement + style); 627 | js.executeScript("arguments[0].setAttribute('style', " + Const.HIGHLIGHT + ");", webElement); 628 | //highlight until the message box is cleared 629 | ui.elementIdent(message); 630 | 631 | js.executeScript("arguments[0].setAttribute('style', 'arguments[1]');", webElement, style); 632 | driver.switchTo().defaultContent(); 633 | } catch (TimeoutException | StaleElementReferenceException e) { 634 | ui.rescan(); 635 | } catch (ElementNotInteractableException e) { 636 | } catch (WebDriverException e) { 637 | ui.abort(); 638 | } 639 | 640 | } 641 | 642 | void switchWin(String handle, String title) { 643 | try { 644 | writer.writeStart(); 645 | writer.writeSwitchWin(title); 646 | writer.writeEnd(); 647 | driver.switchTo().window(handle); 648 | } catch (TimeoutException | StaleElementReferenceException | ElementNotInteractableException e) { 649 | //do nothing, we're rescanning anyway 650 | } catch (WebDriverException e) { 651 | ui.abort(); 652 | } 653 | ui.rescan(); 654 | } 655 | 656 | private RichElement elementFinder(WebElement webElement) { 657 | //uniquely elementFind the webElement by the most descriptive attribute 658 | // 659 | //By.id 660 | //By.name 661 | //By.linkText 662 | //By.cssSelector - alt 663 | //By.cssSelector - href 664 | //By.cssSelector - src 665 | //By.cssSelector - title 666 | //By.className 667 | //By.cssSelector - class 668 | //By.cssSelector - type 669 | //By.cssSelector - value 670 | //By.cssSelector - custom 671 | List elements; 672 | String selector; 673 | 674 | //id 675 | if (!webElement.getAttribute("id").isEmpty()) { //prevent FF crash 676 | elements = driver.findElements(By.id(webElement.getAttribute("id"))); 677 | if ((elements.size() == 1) && elements.contains(webElement)) { 678 | //System.out.println("found id:" + elements.get(0).getAttribute("id")); 679 | return new RichElement("id", elements.get(0).getAttribute("id")); 680 | } 681 | } 682 | 683 | //name 684 | if (webElement.getAttribute("name") != null) { 685 | elements = driver.findElements(By.name(webElement.getAttribute("name"))); 686 | if ((elements.size() == 1) && elements.contains(webElement)) { 687 | //System.out.println("found frames:" + elements.get(0).getAttribute("frames")); 688 | return new RichElement("name", elements.get(0).getAttribute("name")); 689 | } 690 | } 691 | 692 | //linktext 693 | if (webElement.getText() != null) { 694 | elements = driver.findElements(By.linkText(webElement.getText())); 695 | if ((elements.size() == 1) && elements.contains(webElement)) { 696 | //System.out.println("found linktext:" + elements.get(0).getText()); 697 | return new RichElement("linkText", elements.get(0).getText()); 698 | } 699 | } 700 | 701 | //alt 702 | try { 703 | selector = "[alt='" + webElement.getAttribute("alt") + "']"; 704 | elements = driver.findElements(By.cssSelector(selector)); 705 | if ((elements.size() == 1) && elements.contains(webElement)) { 706 | //System.out.println("found cssSelector:" + selector); 707 | return new RichElement("cssSelector", "[alt='" + elements.get(0).getAttribute("alt") + "']"); 708 | } 709 | } catch (InvalidSelectorException | NullPointerException e) { 710 | } 711 | 712 | String root = js.executeScript("return document.domain;").toString(); 713 | 714 | //href 715 | try { 716 | selector = "[href='" + webElement.getAttribute("href") + "']"; 717 | elements = driver.findElements(By.cssSelector(selector)); 718 | if ((elements.size() == 1) && elements.contains(webElement)) { 719 | //System.out.println("found cssSelector:" + selector); 720 | return new RichElement("cssSelector", "[href='" + elements.get(0).getAttribute("href") + "']"); 721 | } 722 | } catch (InvalidSelectorException | NullPointerException e) { 723 | } 724 | 725 | //href, no path 726 | try { 727 | selector = "[href='" + webElement.getAttribute("href").replaceAll("http.*" + root + "/", "") + "']"; 728 | elements = driver.findElements(By.cssSelector(selector)); 729 | if ((elements.size() == 1) && elements.contains(webElement)) { 730 | //System.out.println("found cssSelector:" + selector); 731 | return new RichElement("cssSelector", "[href='" + elements.get(0).getAttribute("href").replaceAll("http.*" + root + "/", "") + "']"); 732 | } 733 | } catch (InvalidSelectorException | NullPointerException e) { 734 | } 735 | 736 | //href, relative path 737 | try { 738 | selector = "[href='" + webElement.getAttribute("href").replaceAll("http.*" + root, "") + "']"; 739 | elements = driver.findElements(By.cssSelector(selector)); 740 | if ((elements.size() == 1) && elements.contains(webElement)) { 741 | //System.out.println("found cssSelector:" + selector); 742 | return new RichElement("cssSelector", "[href='" + elements.get(0).getAttribute("href").replaceAll("http.*" + root, "") + "']"); 743 | } 744 | } catch (InvalidSelectorException | NullPointerException e) { 745 | } 746 | 747 | //src 748 | try { 749 | selector = "[src='" + webElement.getAttribute("src") + "']"; 750 | elements = driver.findElements(By.cssSelector(selector)); 751 | if ((elements.size() == 1) && elements.contains(webElement)) { 752 | //System.out.println("found cssSelector:" + selector); 753 | return new RichElement("cssSelector", "[src='" + elements.get(0).getAttribute("src") + "']"); 754 | } 755 | } catch (InvalidSelectorException | NullPointerException e) { 756 | } 757 | 758 | //src, no path 759 | try { 760 | selector = "[src='" + webElement.getAttribute("src").replaceAll("http.*" + root + "/", "") + "']"; 761 | elements = driver.findElements(By.cssSelector(selector)); 762 | if ((elements.size() == 1) && elements.contains(webElement)) { 763 | //System.out.println("found cssSelector:" + selector); 764 | return new RichElement("cssSelector", "[src='" + elements.get(0).getAttribute("src").replaceAll("http.*" + root + "/", "") + "']"); 765 | } 766 | } catch (InvalidSelectorException | NullPointerException e) { 767 | } 768 | 769 | //src, relative path 770 | try { 771 | selector = "[src='" + webElement.getAttribute("src").replaceAll("http.*" + root, "") + "']"; 772 | elements = driver.findElements(By.cssSelector(selector)); 773 | if ((elements.size() == 1) && elements.contains(webElement)) { 774 | //System.out.println("found cssSelector:" + selector); 775 | return new RichElement("cssSelector", "[src='" + elements.get(0).getAttribute("src").replaceAll("http.*" + root, "") + "']"); 776 | } 777 | } catch (InvalidSelectorException | NullPointerException e) { 778 | } 779 | 780 | //title 781 | try { 782 | selector = "[title='" + webElement.getAttribute("title") + "']"; 783 | elements = driver.findElements(By.cssSelector(selector)); 784 | if ((elements.size() == 1) && elements.contains(webElement)) { 785 | //System.out.println("found cssSelector:" + selector); 786 | return new RichElement("cssSelector", "[title='" + elements.get(0).getAttribute("title") + "']"); 787 | } 788 | } catch (InvalidSelectorException | NullPointerException e) { 789 | } 790 | 791 | //classname 792 | try { 793 | elements = driver.findElements(By.className(webElement.getAttribute("className"))); 794 | if ((elements.size() == 1) && elements.contains(webElement)) { 795 | //System.out.println("found className:" + elements.get(0).getAttribute("className")); 796 | return new RichElement("className", elements.get(0).getAttribute("className")); 797 | } 798 | } catch (InvalidSelectorException | NullPointerException e) { 799 | } 800 | 801 | try { 802 | selector = "." + webElement.getAttribute("className").replace(" ", "."); 803 | elements = driver.findElements(By.cssSelector(selector)); 804 | if ((elements.size() == 1) && elements.contains(webElement)) { 805 | //System.out.println("found cssSelector:" + selector); 806 | return new RichElement("className", "." + elements.get(0).getAttribute("className").replace(" ", ".")); 807 | } 808 | } catch (InvalidSelectorException | NullPointerException e) { 809 | } 810 | 811 | //class 812 | try { 813 | selector = "[class='" + webElement.getAttribute("class") + "']"; 814 | elements = driver.findElements(By.cssSelector(selector)); 815 | if ((elements.size() == 1) && elements.contains(webElement)) { 816 | //System.out.println("found cssSelector:" + selector); 817 | return new RichElement("cssSelector", "[class='" + elements.get(0).getAttribute("class") + "']"); 818 | } 819 | } catch (InvalidSelectorException | NullPointerException e) { 820 | } 821 | 822 | //type 823 | try { 824 | selector = "[type='" + webElement.getAttribute("type") + "']"; 825 | elements = driver.findElements(By.cssSelector(selector)); 826 | if ((elements.size() == 1) && elements.contains(webElement)) { 827 | //System.out.println("found cssSelector:" + selector); 828 | return new RichElement("cssSelector", "[type='" + elements.get(0).getAttribute("type") + "']"); 829 | } 830 | } catch (InvalidSelectorException | NullPointerException e) { 831 | } 832 | 833 | //value 834 | try { 835 | selector = "[value='" + webElement.getAttribute("value") + "']"; 836 | elements = driver.findElements(By.cssSelector(selector)); 837 | if ((elements.size() == 1) && elements.contains(webElement)) { 838 | //System.out.println("found cssSelector:" + selector); 839 | return new RichElement("cssSelector", "[value='" + elements.get(0).getAttribute("value") + "']"); 840 | } 841 | } catch (InvalidSelectorException | NullPointerException e) { 842 | } 843 | 844 | //custom CSS selectors 845 | for (String item : CSSselectors) { 846 | try { 847 | elements = driver.findElements(By.cssSelector(item)); 848 | //System.out.println("len:" + elements.size()); 849 | if ((elements.size() == 1) && elements.contains(webElement)) { 850 | return new RichElement("cssSelector", item.replace("\"", "\\\"")); 851 | } 852 | } catch (InvalidSelectorException | NullPointerException e) { 853 | } 854 | } 855 | 856 | //implement other methods? 857 | return new RichElement(null, null); 858 | } 859 | 860 | } 861 | -------------------------------------------------------------------------------- /src/main/java/objectivetester/Wisard.form: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | -------------------------------------------------------------------------------- /src/main/java/objectivetester/Wisard.java: -------------------------------------------------------------------------------- 1 | package objectivetester; 2 | 3 | import java.awt.Color; 4 | import java.awt.Cursor; 5 | import java.awt.Desktop; 6 | import java.awt.event.ActionListener; 7 | import java.awt.event.MouseListener; 8 | import java.awt.event.WindowAdapter; 9 | import java.awt.event.WindowEvent; 10 | import java.io.IOException; 11 | import java.io.OutputStream; 12 | import java.io.PrintStream; 13 | import java.net.URI; 14 | import java.net.URISyntaxException; 15 | import java.util.prefs.Preferences; 16 | import javax.swing.ImageIcon; 17 | import javax.swing.JFrame; 18 | import javax.swing.JMenuItem; 19 | import javax.swing.JOptionPane; 20 | import javax.swing.JPopupMenu; 21 | import javax.swing.text.BadLocationException; 22 | import com.formdev.flatlaf.FlatLightLaf; 23 | import com.formdev.flatlaf.FlatDarkLaf; 24 | 25 | /** 26 | * 27 | * @author Steve 28 | */ 29 | public class Wisard extends javax.swing.JFrame implements UserInterface { 30 | //Web Internal Structure Action RecorDer 31 | 32 | private ImageIcon icon; 33 | private final javax.swing.table.DefaultTableModel jTable1Model; 34 | private final JPopupMenu popup; 35 | private final BrowserDriver bd = new BrowserDriver(this); 36 | private final Preferences prefs; 37 | 38 | /** 39 | * Creates new form Wisard 40 | */ 41 | public Wisard() { 42 | icon = new ImageIcon(getClass().getResource("/images/wisard.png")); 43 | //create the tablemodel for the element table 44 | jTable1Model = new javax.swing.table.DefaultTableModel( 45 | new Object[][]{}, 46 | new String[]{ 47 | "Element", "Location", "Name", "id", "Value", "webElement" 48 | }) { 49 | boolean[] canEdit = new boolean[]{ 50 | false, false, false, false, false, false 51 | }; 52 | 53 | @Override 54 | public boolean isCellEditable(int rowIndex, int columnIndex) { 55 | return canEdit[columnIndex]; 56 | } 57 | }; 58 | 59 | initComponents(); 60 | 61 | //redirect output to text area 62 | PrintStream printStream = new PrintStream(new OutputStream() { 63 | @Override 64 | public void write(int b) throws IOException { 65 | textConsole.append(String.valueOf((char) b)); 66 | textConsole.setCaretPosition(textConsole.getDocument().getLength()); 67 | } 68 | }); 69 | System.setOut(printStream); 70 | System.setErr(printStream); 71 | 72 | //create the popup menu for the element table 73 | popup = new JPopupMenu(); 74 | MouseListener popupListener = new EventListener(popup, tableElements, bd); 75 | 76 | JMenuItem menuItem = new JMenuItem(Const.CLICK); 77 | menuItem.addActionListener((ActionListener) popupListener); 78 | popup.add(menuItem); 79 | menuItem = new JMenuItem(Const.FIND); 80 | menuItem.addActionListener((ActionListener) popupListener); 81 | popup.add(menuItem); 82 | menuItem = new JMenuItem(Const.ASSERT); 83 | menuItem.addActionListener((ActionListener) popupListener); 84 | popup.add(menuItem); 85 | menuItem = new JMenuItem(Const.IDENTIFY); 86 | menuItem.addActionListener((ActionListener) popupListener); 87 | popup.add(menuItem); 88 | tableElements.addMouseListener(popupListener); 89 | //hide the webElements 90 | tableElements.removeColumn(tableElements.getColumn("webElement")); 91 | 92 | this.addWindowListener(new WindowAdapter() { 93 | @Override 94 | public void windowClosing(WindowEvent event) { 95 | exitProcedure(); 96 | } 97 | }); 98 | 99 | //get prefs 100 | prefs = Preferences.userRoot().node("wisard"); 101 | if (prefs.get("browser", "").contentEquals("")) { 102 | //System.out.println("no prefs, writing defaults"); 103 | prefs.put("browser", "FF"); 104 | prefs.put("output", "junit"); 105 | prefs.put("driverFF", ""); 106 | prefs.put("driverCR", ""); 107 | prefs.put("driverED", ""); 108 | prefs.putBoolean("showId", false); 109 | prefs.putBoolean("showInvis", false); 110 | prefs.put("defaultURL", "http://www.saucedemo.com"); 111 | } 112 | pathFF.setText(prefs.get("driverFF", "")); 113 | pathCR.setText(prefs.get("driverCR", "")); 114 | pathED.setText(prefs.get("driverED", "")); 115 | defaultURL.setText(prefs.get("defaultURL", "")); 116 | currentUrl.setText(prefs.get("defaultURL", "")); 117 | CSSselectors.setText(prefs.get("cssselectors", "div[id=shopping_cart_container], div[class=cart_quantity]")); 118 | if (prefs.get("browser", "").contentEquals("FF")) { 119 | buttonFF.setSelected(true); 120 | } 121 | if (prefs.get("browser", "").contentEquals("CR")) { 122 | buttonCR.setSelected(true); 123 | } 124 | if (prefs.get("browser", "").contentEquals("ED")) { 125 | buttonED.setSelected(true); 126 | } 127 | if (prefs.get("browser", "").contentEquals("SA")) { 128 | buttonSA.setSelected(true); 129 | } 130 | if (prefs.getBoolean("showId", false)) { 131 | checkBoxId.setSelected(true); 132 | } else { 133 | //hide id column 134 | tableElements.removeColumn(tableElements.getColumn("id")); 135 | } 136 | if (prefs.get("output", "").contentEquals("java")) { 137 | buttonJava.setSelected(true); 138 | } 139 | if (prefs.get("output", "").contentEquals("junit")) { 140 | buttonJunit.setSelected(true); 141 | } 142 | if (prefs.get("output", "").contentEquals("junit5")) { 143 | buttonJunit5.setSelected(true); 144 | } 145 | if (prefs.get("output", "").contentEquals("js")) { 146 | buttonJs.setSelected(true); 147 | } 148 | } 149 | 150 | /** 151 | * This method is called from within the constructor to initialise the form. 152 | * WARNING: Do NOT modify this code. The content of this method is always 153 | * regenerated by the Form Editor. 154 | */ 155 | // //GEN-BEGIN:initComponents 156 | private void initComponents() { 157 | java.awt.GridBagConstraints gridBagConstraints; 158 | 159 | buttonsBrowser = new javax.swing.ButtonGroup(); 160 | buttonsOutput = new javax.swing.ButtonGroup(); 161 | dialogAbout = new javax.swing.JDialog(); 162 | panelAbout = new javax.swing.JPanel(); 163 | labelName = new javax.swing.JLabel(); 164 | labelDesc = new javax.swing.JLabel(); 165 | labelCopyright = new javax.swing.JLabel(); 166 | labelLink = new javax.swing.JLabel(); 167 | buttonCool = new javax.swing.JButton(); 168 | dialogSettings = new javax.swing.JDialog(); 169 | panelSettings = new javax.swing.JPanel(); 170 | labelDefurl = new javax.swing.JLabel(); 171 | defaultURL = new javax.swing.JTextField(); 172 | labelDispopts = new javax.swing.JLabel(); 173 | checkBoxId = new javax.swing.JCheckBox(); 174 | checkBoxInvis = new javax.swing.JCheckBox(); 175 | labelOutput = new javax.swing.JLabel(); 176 | buttonJunit = new javax.swing.JRadioButton(); 177 | buttonJunit5 = new javax.swing.JRadioButton(); 178 | buttonJava = new javax.swing.JRadioButton(); 179 | buttonJs = new javax.swing.JRadioButton(); 180 | labelDriver = new javax.swing.JLabel(); 181 | buttonFF = new javax.swing.JRadioButton(); 182 | buttonCR = new javax.swing.JRadioButton(); 183 | buttonED = new javax.swing.JRadioButton(); 184 | buttonSA = new javax.swing.JRadioButton(); 185 | pathFF = new javax.swing.JTextField(); 186 | pathCR = new javax.swing.JTextField(); 187 | labelPlugin = new javax.swing.JLabel(); 188 | buttonSave = new javax.swing.JButton(); 189 | buttonCancel = new javax.swing.JButton(); 190 | pathED = new javax.swing.JTextField(); 191 | labelCSS = new javax.swing.JLabel(); 192 | CSSselectors = new javax.swing.JTextField(); 193 | jToolBar1 = new javax.swing.JToolBar(); 194 | labelUrl = new javax.swing.JLabel(); 195 | currentUrl = new javax.swing.JTextField(); 196 | buttonInspect = new javax.swing.JToggleButton(); 197 | buttonRefresh = new javax.swing.JButton(); 198 | jSplitPane1 = new javax.swing.JSplitPane(); 199 | panelElements = new javax.swing.JPanel(); 200 | paneElements = new javax.swing.JScrollPane(); 201 | tableElements = new javax.swing.JTable(); 202 | tableElements.getTableHeader().setReorderingAllowed(false); 203 | paneCode = new javax.swing.JScrollPane(); 204 | code = new javax.swing.JTextArea(); 205 | paneConsole = new javax.swing.JScrollPane(); 206 | textConsole = new javax.swing.JTextArea(); 207 | menuBar = new javax.swing.JMenuBar(); 208 | menuFile = new javax.swing.JMenu(); 209 | menuExit = new javax.swing.JMenuItem(); 210 | menuEdit = new javax.swing.JMenu(); 211 | menuSettings = new javax.swing.JMenuItem(); 212 | menuHelp = new javax.swing.JMenu(); 213 | menuAbout = new javax.swing.JMenuItem(); 214 | 215 | dialogAbout.setTitle("About"); 216 | dialogAbout.setIconImage(icon.getImage()); 217 | dialogAbout.setMinimumSize(new java.awt.Dimension(400, 400)); 218 | dialogAbout.setModal(true); 219 | 220 | panelAbout.setLayout(new java.awt.GridBagLayout()); 221 | 222 | labelName.setFont(new java.awt.Font("Tahoma", 0, 72)); // NOI18N 223 | labelName.setText("Wisard"); 224 | gridBagConstraints = new java.awt.GridBagConstraints(); 225 | gridBagConstraints.gridx = 0; 226 | gridBagConstraints.gridy = 0; 227 | panelAbout.add(labelName, gridBagConstraints); 228 | 229 | labelDesc.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N 230 | labelDesc.setText("Web Internal Structure Action RecorDer"); 231 | gridBagConstraints = new java.awt.GridBagConstraints(); 232 | gridBagConstraints.gridx = 0; 233 | gridBagConstraints.gridy = 1; 234 | panelAbout.add(labelDesc, gridBagConstraints); 235 | 236 | labelCopyright.setText("© Steve Mellor 2014-2023"); 237 | gridBagConstraints = new java.awt.GridBagConstraints(); 238 | gridBagConstraints.gridx = 0; 239 | gridBagConstraints.gridy = 2; 240 | panelAbout.add(labelCopyright, gridBagConstraints); 241 | 242 | labelLink.setText(" Wisard on github"); 243 | labelLink.setToolTipText(""); 244 | labelLink.addMouseListener(new java.awt.event.MouseAdapter() { 245 | public void mouseClicked(java.awt.event.MouseEvent evt) { 246 | labelLinkMouseClicked(evt); 247 | } 248 | public void mouseEntered(java.awt.event.MouseEvent evt) { 249 | labelLinkMouseEntered(evt); 250 | } 251 | }); 252 | gridBagConstraints = new java.awt.GridBagConstraints(); 253 | gridBagConstraints.gridx = 0; 254 | gridBagConstraints.gridy = 3; 255 | panelAbout.add(labelLink, gridBagConstraints); 256 | 257 | buttonCool.setText("Cool"); 258 | buttonCool.addActionListener(new java.awt.event.ActionListener() { 259 | public void actionPerformed(java.awt.event.ActionEvent evt) { 260 | buttonCoolActionPerformed(evt); 261 | } 262 | }); 263 | gridBagConstraints = new java.awt.GridBagConstraints(); 264 | gridBagConstraints.gridx = 0; 265 | gridBagConstraints.gridy = 4; 266 | gridBagConstraints.insets = new java.awt.Insets(14, 0, 0, 0); 267 | panelAbout.add(buttonCool, gridBagConstraints); 268 | 269 | javax.swing.GroupLayout dialogAboutLayout = new javax.swing.GroupLayout(dialogAbout.getContentPane()); 270 | dialogAbout.getContentPane().setLayout(dialogAboutLayout); 271 | dialogAboutLayout.setHorizontalGroup( 272 | dialogAboutLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 273 | .addGroup(dialogAboutLayout.createSequentialGroup() 274 | .addGap(0, 0, Short.MAX_VALUE) 275 | .addComponent(panelAbout, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) 276 | .addGap(0, 0, Short.MAX_VALUE)) 277 | ); 278 | dialogAboutLayout.setVerticalGroup( 279 | dialogAboutLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 280 | .addGroup(dialogAboutLayout.createSequentialGroup() 281 | .addGap(0, 0, Short.MAX_VALUE) 282 | .addComponent(panelAbout, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) 283 | .addGap(0, 0, Short.MAX_VALUE)) 284 | ); 285 | 286 | dialogSettings.setTitle("Settings"); 287 | dialogSettings.setIconImage(icon.getImage()); 288 | dialogSettings.setMinimumSize(new java.awt.Dimension(500, 500)); 289 | dialogSettings.setModal(true); 290 | 291 | panelSettings.setLayout(new java.awt.GridBagLayout()); 292 | 293 | labelDefurl.setText("Default URL"); 294 | gridBagConstraints = new java.awt.GridBagConstraints(); 295 | gridBagConstraints.gridx = 0; 296 | gridBagConstraints.gridy = 1; 297 | gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START; 298 | panelSettings.add(labelDefurl, gridBagConstraints); 299 | 300 | defaultURL.setColumns(20); 301 | defaultURL.setText("defaultURL"); 302 | defaultURL.setToolTipText("Default URL"); 303 | defaultURL.setMinimumSize(new java.awt.Dimension(166, 20)); 304 | defaultURL.setName(""); // NOI18N 305 | gridBagConstraints = new java.awt.GridBagConstraints(); 306 | gridBagConstraints.gridx = 1; 307 | gridBagConstraints.gridy = 1; 308 | gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; 309 | gridBagConstraints.ipadx = 100; 310 | gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; 311 | panelSettings.add(defaultURL, gridBagConstraints); 312 | defaultURL.getAccessibleContext().setAccessibleName("Default URL"); 313 | 314 | labelDispopts.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N 315 | labelDispopts.setText("Display Options"); 316 | gridBagConstraints = new java.awt.GridBagConstraints(); 317 | gridBagConstraints.gridx = 0; 318 | gridBagConstraints.gridy = 3; 319 | gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START; 320 | gridBagConstraints.insets = new java.awt.Insets(20, 0, 0, 0); 321 | panelSettings.add(labelDispopts, gridBagConstraints); 322 | 323 | checkBoxId.setText("Show Element 'id'"); 324 | checkBoxId.setToolTipText("Show Element 'id'"); 325 | gridBagConstraints = new java.awt.GridBagConstraints(); 326 | gridBagConstraints.gridx = 0; 327 | gridBagConstraints.gridy = 4; 328 | gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START; 329 | panelSettings.add(checkBoxId, gridBagConstraints); 330 | checkBoxId.getAccessibleContext().setAccessibleDescription("Show id"); 331 | 332 | checkBoxInvis.setText("List invisible Elements"); 333 | checkBoxInvis.setToolTipText("List invisible Elements"); 334 | gridBagConstraints = new java.awt.GridBagConstraints(); 335 | gridBagConstraints.gridx = 0; 336 | gridBagConstraints.gridy = 5; 337 | gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START; 338 | panelSettings.add(checkBoxInvis, gridBagConstraints); 339 | checkBoxInvis.getAccessibleContext().setAccessibleDescription("List Invisible"); 340 | 341 | labelOutput.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N 342 | labelOutput.setText("Generated Output"); 343 | gridBagConstraints = new java.awt.GridBagConstraints(); 344 | gridBagConstraints.gridx = 0; 345 | gridBagConstraints.gridy = 6; 346 | gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START; 347 | gridBagConstraints.insets = new java.awt.Insets(20, 0, 0, 0); 348 | panelSettings.add(labelOutput, gridBagConstraints); 349 | 350 | buttonsOutput.add(buttonJunit); 351 | buttonJunit.setText("JUnit"); 352 | gridBagConstraints = new java.awt.GridBagConstraints(); 353 | gridBagConstraints.gridx = 0; 354 | gridBagConstraints.gridy = 7; 355 | gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START; 356 | panelSettings.add(buttonJunit, gridBagConstraints); 357 | 358 | buttonsOutput.add(buttonJunit5); 359 | buttonJunit5.setText("JUnit5"); 360 | gridBagConstraints = new java.awt.GridBagConstraints(); 361 | gridBagConstraints.gridx = 0; 362 | gridBagConstraints.gridy = 8; 363 | gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START; 364 | panelSettings.add(buttonJunit5, gridBagConstraints); 365 | 366 | buttonsOutput.add(buttonJava); 367 | buttonJava.setText("Java"); 368 | gridBagConstraints = new java.awt.GridBagConstraints(); 369 | gridBagConstraints.gridx = 0; 370 | gridBagConstraints.gridy = 9; 371 | gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START; 372 | panelSettings.add(buttonJava, gridBagConstraints); 373 | 374 | buttonsOutput.add(buttonJs); 375 | buttonJs.setText("JavaScript"); 376 | gridBagConstraints = new java.awt.GridBagConstraints(); 377 | gridBagConstraints.gridx = 0; 378 | gridBagConstraints.gridy = 10; 379 | gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START; 380 | panelSettings.add(buttonJs, gridBagConstraints); 381 | 382 | labelDriver.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N 383 | labelDriver.setText("Target Browser and driver"); 384 | gridBagConstraints = new java.awt.GridBagConstraints(); 385 | gridBagConstraints.gridx = 0; 386 | gridBagConstraints.gridy = 11; 387 | gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START; 388 | gridBagConstraints.insets = new java.awt.Insets(20, 0, 0, 20); 389 | panelSettings.add(labelDriver, gridBagConstraints); 390 | 391 | buttonsBrowser.add(buttonFF); 392 | buttonFF.setText("Firefox"); 393 | gridBagConstraints = new java.awt.GridBagConstraints(); 394 | gridBagConstraints.gridx = 0; 395 | gridBagConstraints.gridy = 12; 396 | gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START; 397 | panelSettings.add(buttonFF, gridBagConstraints); 398 | 399 | buttonsBrowser.add(buttonCR); 400 | buttonCR.setText("Chrome"); 401 | gridBagConstraints = new java.awt.GridBagConstraints(); 402 | gridBagConstraints.gridx = 0; 403 | gridBagConstraints.gridy = 14; 404 | gridBagConstraints.gridheight = 2; 405 | gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; 406 | panelSettings.add(buttonCR, gridBagConstraints); 407 | 408 | buttonsBrowser.add(buttonED); 409 | buttonED.setText("Edge"); 410 | gridBagConstraints = new java.awt.GridBagConstraints(); 411 | gridBagConstraints.gridx = 0; 412 | gridBagConstraints.gridy = 18; 413 | gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; 414 | panelSettings.add(buttonED, gridBagConstraints); 415 | 416 | buttonsBrowser.add(buttonSA); 417 | buttonSA.setText("Safari"); 418 | gridBagConstraints = new java.awt.GridBagConstraints(); 419 | gridBagConstraints.gridx = 0; 420 | gridBagConstraints.gridy = 20; 421 | gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; 422 | panelSettings.add(buttonSA, gridBagConstraints); 423 | 424 | pathFF.setColumns(20); 425 | pathFF.setText("pathFF"); 426 | pathFF.setToolTipText("Path to Gecko driver"); 427 | pathFF.setName(""); // NOI18N 428 | gridBagConstraints = new java.awt.GridBagConstraints(); 429 | gridBagConstraints.gridx = 1; 430 | gridBagConstraints.gridy = 12; 431 | gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; 432 | gridBagConstraints.ipadx = 100; 433 | gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; 434 | panelSettings.add(pathFF, gridBagConstraints); 435 | 436 | pathCR.setColumns(20); 437 | pathCR.setText("pathCR"); 438 | pathCR.setToolTipText("Path to Chrome driver"); 439 | gridBagConstraints = new java.awt.GridBagConstraints(); 440 | gridBagConstraints.gridx = 1; 441 | gridBagConstraints.gridy = 14; 442 | gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; 443 | gridBagConstraints.ipadx = 100; 444 | gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; 445 | panelSettings.add(pathCR, gridBagConstraints); 446 | pathCR.getAccessibleContext().setAccessibleName("Chrome driver"); 447 | 448 | labelPlugin.setFont(new java.awt.Font("Tahoma", 2, 11)); // NOI18N 449 | labelPlugin.setText("/usr/bin/safaridriver"); 450 | gridBagConstraints = new java.awt.GridBagConstraints(); 451 | gridBagConstraints.gridx = 1; 452 | gridBagConstraints.gridy = 20; 453 | panelSettings.add(labelPlugin, gridBagConstraints); 454 | 455 | buttonSave.setText("Save"); 456 | buttonSave.addActionListener(new java.awt.event.ActionListener() { 457 | public void actionPerformed(java.awt.event.ActionEvent evt) { 458 | buttonSaveActionPerformed(evt); 459 | } 460 | }); 461 | gridBagConstraints = new java.awt.GridBagConstraints(); 462 | gridBagConstraints.gridx = 0; 463 | gridBagConstraints.gridy = 22; 464 | gridBagConstraints.insets = new java.awt.Insets(20, 0, 0, 0); 465 | panelSettings.add(buttonSave, gridBagConstraints); 466 | 467 | buttonCancel.setText("Cancel"); 468 | buttonCancel.addActionListener(new java.awt.event.ActionListener() { 469 | public void actionPerformed(java.awt.event.ActionEvent evt) { 470 | buttonCancelActionPerformed(evt); 471 | } 472 | }); 473 | gridBagConstraints = new java.awt.GridBagConstraints(); 474 | gridBagConstraints.gridx = 1; 475 | gridBagConstraints.gridy = 22; 476 | gridBagConstraints.insets = new java.awt.Insets(20, 0, 0, 0); 477 | panelSettings.add(buttonCancel, gridBagConstraints); 478 | 479 | pathED.setColumns(20); 480 | pathED.setText("pathED"); 481 | pathED.setToolTipText("Path to Edge driver"); 482 | gridBagConstraints = new java.awt.GridBagConstraints(); 483 | gridBagConstraints.gridx = 1; 484 | gridBagConstraints.gridy = 18; 485 | gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; 486 | gridBagConstraints.ipadx = 100; 487 | gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; 488 | panelSettings.add(pathED, gridBagConstraints); 489 | 490 | labelCSS.setText("CSS selectors"); 491 | gridBagConstraints = new java.awt.GridBagConstraints(); 492 | gridBagConstraints.gridx = 0; 493 | gridBagConstraints.gridy = 2; 494 | gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START; 495 | gridBagConstraints.insets = new java.awt.Insets(20, 0, 0, 20); 496 | panelSettings.add(labelCSS, gridBagConstraints); 497 | 498 | CSSselectors.setColumns(20); 499 | CSSselectors.setText("CSSselectors"); 500 | CSSselectors.setToolTipText("comma seperated list of selectors"); 501 | CSSselectors.setMinimumSize(new java.awt.Dimension(166, 24)); 502 | gridBagConstraints = new java.awt.GridBagConstraints(); 503 | gridBagConstraints.gridx = 1; 504 | gridBagConstraints.gridy = 2; 505 | gridBagConstraints.ipadx = 100; 506 | gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; 507 | gridBagConstraints.insets = new java.awt.Insets(20, 0, 0, 0); 508 | panelSettings.add(CSSselectors, gridBagConstraints); 509 | 510 | javax.swing.GroupLayout dialogSettingsLayout = new javax.swing.GroupLayout(dialogSettings.getContentPane()); 511 | dialogSettings.getContentPane().setLayout(dialogSettingsLayout); 512 | dialogSettingsLayout.setHorizontalGroup( 513 | dialogSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 514 | .addGap(0, 400, Short.MAX_VALUE) 515 | .addGroup(dialogSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 516 | .addComponent(panelSettings, javax.swing.GroupLayout.PREFERRED_SIZE, 400, Short.MAX_VALUE)) 517 | ); 518 | dialogSettingsLayout.setVerticalGroup( 519 | dialogSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 520 | .addGap(0, 450, Short.MAX_VALUE) 521 | .addGroup(dialogSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 522 | .addComponent(panelSettings, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) 523 | ); 524 | 525 | setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE); 526 | setTitle("Wisard"); 527 | setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); 528 | setIconImage(icon.getImage()); 529 | 530 | jToolBar1.setRollover(true); 531 | 532 | labelUrl.setText("URL"); 533 | jToolBar1.add(labelUrl); 534 | 535 | currentUrl.setColumns(15); 536 | currentUrl.setText("URL"); 537 | currentUrl.setToolTipText("Website URL"); 538 | currentUrl.setCursor(new java.awt.Cursor(java.awt.Cursor.TEXT_CURSOR)); 539 | currentUrl.setMinimumSize(new java.awt.Dimension(6, 15)); 540 | currentUrl.setPreferredSize(new java.awt.Dimension(12, 20)); 541 | currentUrl.addActionListener(new java.awt.event.ActionListener() { 542 | public void actionPerformed(java.awt.event.ActionEvent evt) { 543 | currentUrlActionPerformed(evt); 544 | } 545 | }); 546 | jToolBar1.add(currentUrl); 547 | currentUrl.getAccessibleContext().setAccessibleName("URL"); 548 | 549 | buttonInspect.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/inspect.png"))); // NOI18N 550 | buttonInspect.setToolTipText("Open the URL"); 551 | buttonInspect.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED)); 552 | buttonInspect.setFocusable(false); 553 | buttonInspect.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); 554 | buttonInspect.setSelectedIcon(new javax.swing.ImageIcon(getClass().getResource("/images/cancel.png"))); // NOI18N 555 | buttonInspect.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); 556 | buttonInspect.addActionListener(new java.awt.event.ActionListener() { 557 | public void actionPerformed(java.awt.event.ActionEvent evt) { 558 | buttonInspectActionPerformed(evt); 559 | } 560 | }); 561 | jToolBar1.add(buttonInspect); 562 | 563 | buttonRefresh.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/refresh.png"))); // NOI18N 564 | buttonRefresh.setToolTipText("Refresh the page elements list"); 565 | buttonRefresh.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED)); 566 | buttonRefresh.setFocusable(false); 567 | buttonRefresh.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); 568 | buttonRefresh.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); 569 | buttonRefresh.addActionListener(new java.awt.event.ActionListener() { 570 | public void actionPerformed(java.awt.event.ActionEvent evt) { 571 | buttonRefreshActionPerformed(evt); 572 | } 573 | }); 574 | jToolBar1.add(buttonRefresh); 575 | 576 | getContentPane().add(jToolBar1, java.awt.BorderLayout.PAGE_START); 577 | 578 | panelElements.setPreferredSize(new java.awt.Dimension(300, 300)); 579 | panelElements.setLayout(new java.awt.BorderLayout()); 580 | 581 | paneElements.setPreferredSize(new java.awt.Dimension(300, 300)); 582 | 583 | tableElements.setModel(jTable1Model); 584 | tableElements.setColumnSelectionAllowed(true); 585 | tableElements.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); 586 | paneElements.setViewportView(tableElements); 587 | tableElements.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); 588 | 589 | panelElements.add(paneElements, java.awt.BorderLayout.CENTER); 590 | 591 | jSplitPane1.setLeftComponent(panelElements); 592 | 593 | code.setEditable(false); 594 | code.setColumns(20); 595 | code.setFont(new java.awt.Font("Courier New", 0, 12)); // NOI18N 596 | code.setRows(5); 597 | code.setTabSize(4); 598 | paneCode.setViewportView(code); 599 | 600 | jSplitPane1.setRightComponent(paneCode); 601 | 602 | getContentPane().add(jSplitPane1, java.awt.BorderLayout.CENTER); 603 | 604 | textConsole.setEditable(false); 605 | textConsole.setColumns(20); 606 | textConsole.setFont(new java.awt.Font("Courier New", 0, 12)); // NOI18N 607 | textConsole.setRows(5); 608 | paneConsole.setViewportView(textConsole); 609 | 610 | getContentPane().add(paneConsole, java.awt.BorderLayout.PAGE_END); 611 | 612 | menuFile.setText("File"); 613 | 614 | menuExit.setText("Exit"); 615 | menuExit.addActionListener(new java.awt.event.ActionListener() { 616 | public void actionPerformed(java.awt.event.ActionEvent evt) { 617 | menuExitActionPerformed(evt); 618 | } 619 | }); 620 | menuFile.add(menuExit); 621 | 622 | menuBar.add(menuFile); 623 | 624 | menuEdit.setText("Edit"); 625 | 626 | menuSettings.setText("Settings"); 627 | menuSettings.addActionListener(new java.awt.event.ActionListener() { 628 | public void actionPerformed(java.awt.event.ActionEvent evt) { 629 | menuSettingsActionPerformed(evt); 630 | } 631 | }); 632 | menuEdit.add(menuSettings); 633 | 634 | menuBar.add(menuEdit); 635 | 636 | menuHelp.setText("Help"); 637 | 638 | menuAbout.setText("About"); 639 | menuAbout.addActionListener(new java.awt.event.ActionListener() { 640 | public void actionPerformed(java.awt.event.ActionEvent evt) { 641 | menuAboutActionPerformed(evt); 642 | } 643 | }); 644 | menuHelp.add(menuAbout); 645 | 646 | menuBar.add(menuHelp); 647 | 648 | setJMenuBar(menuBar); 649 | 650 | pack(); 651 | }// //GEN-END:initComponents 652 | 653 | private void currentUrlActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_currentUrlActionPerformed 654 | buttonInspect.doClick(); 655 | }//GEN-LAST:event_currentUrlActionPerformed 656 | 657 | private void buttonSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonSaveActionPerformed 658 | 659 | //update UI 660 | if (!buttonInspect.isSelected()) { 661 | currentUrl.setText(defaultURL.getText()); 662 | } 663 | if (!prefs.getBoolean("showId", false) && checkBoxId.isSelected()) { 664 | //reset table to show id 665 | jTable1Model.fireTableStructureChanged(); 666 | //re-hide webElements 667 | tableElements.removeColumn(tableElements.getColumn("webElement")); 668 | } 669 | if (prefs.getBoolean("showId", false) && !checkBoxId.isSelected()) { 670 | //hide id column 671 | tableElements.removeColumn(tableElements.getColumn("id")); 672 | } 673 | 674 | //save new settings 675 | prefs.put("defaultURL", defaultURL.getText()); 676 | prefs.put("cssselectors", CSSselectors.getText()); 677 | 678 | prefs.putBoolean("showId", checkBoxId.isSelected()); 679 | prefs.putBoolean("showInvis", checkBoxInvis.isSelected()); 680 | 681 | if (buttonFF.isSelected()) { 682 | prefs.put("browser", "FF"); 683 | } 684 | if (buttonED.isSelected()) { 685 | prefs.put("browser", "ED"); 686 | } 687 | if (buttonCR.isSelected()) { 688 | prefs.put("browser", "CR"); 689 | } 690 | if (buttonSA.isSelected()) { 691 | prefs.put("browser", "SA"); 692 | } 693 | if (buttonJunit.isSelected()) { 694 | prefs.put("output", "junit"); 695 | } 696 | if (buttonJunit5.isSelected()) { 697 | prefs.put("output", "junit5"); 698 | } 699 | if (buttonJava.isSelected()) { 700 | prefs.put("output", "java"); 701 | } 702 | if (buttonJs.isSelected()) { 703 | prefs.put("output", "js"); 704 | } 705 | 706 | prefs.put("driverFF", pathFF.getText()); 707 | prefs.put("driverCR", pathCR.getText()); 708 | prefs.put("driverED", pathED.getText()); 709 | 710 | dialogSettings.setVisible(false); 711 | }//GEN-LAST:event_buttonSaveActionPerformed 712 | 713 | private void buttonInspectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonInspectActionPerformed 714 | // TODO add your handling code here: 715 | //System.out.println(evt.getActionCommand()); 716 | if (buttonInspect.isSelected()) { 717 | currentUrl.setEnabled(false); 718 | Boolean success = false; 719 | bd.initWriter(prefs.get("output", "junit")); 720 | if (prefs.get("browser", "").contentEquals("FF")) { 721 | success = bd.initFF(currentUrl.getText(), prefs.get("driverFF", "")); 722 | } 723 | if (prefs.get("browser", "").contentEquals("CR")) { 724 | success = bd.initCR(currentUrl.getText(), prefs.get("driverCR", "")); 725 | } 726 | if (prefs.get("browser", "").contentEquals("ED")) { 727 | success = bd.initED(currentUrl.getText(), prefs.get("driverED", "")); 728 | } 729 | if (prefs.get("browser", "").contentEquals("SA")) { 730 | success = bd.initSA(currentUrl.getText()); 731 | } 732 | 733 | if (success) { 734 | Thread t = new Thread(bd, "Page Examiner"); 735 | t.start(); 736 | } else { 737 | currentUrl.setEnabled(true); 738 | buttonInspect.doClick(); 739 | bd.close(); 740 | } 741 | 742 | } else { 743 | currentUrl.setEnabled(true); 744 | //tidy up 745 | popup.setVisible(false); 746 | for (int i = jTable1Model.getRowCount(); i > 0; i--) { 747 | jTable1Model.removeRow(i - 1); 748 | } 749 | bd.close(); 750 | } 751 | }//GEN-LAST:event_buttonInspectActionPerformed 752 | 753 | private void buttonRefreshActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonRefreshActionPerformed 754 | rescan(); 755 | }//GEN-LAST:event_buttonRefreshActionPerformed 756 | 757 | private void labelLinkMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_labelLinkMouseClicked 758 | // TODO add your handling code here: 759 | if (Desktop.isDesktopSupported()) { 760 | try { 761 | Desktop.getDesktop().browse(new URI("https://github.com/objectivetester/wisard")); 762 | } catch (URISyntaxException | IOException | UnsupportedOperationException ex) { 763 | this.errorMessage("Unable to open browser, please visit:\n https://github.com/objectivetester/wisard"); 764 | } 765 | } else { 766 | this.errorMessage("Unable to open browser, please visit:\n https://github.com/objectivetester/wisard"); 767 | } 768 | }//GEN-LAST:event_labelLinkMouseClicked 769 | 770 | private void labelLinkMouseEntered(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_labelLinkMouseEntered 771 | // TODO add your handling code here: 772 | labelLink.setCursor(new Cursor(Cursor.HAND_CURSOR)); 773 | }//GEN-LAST:event_labelLinkMouseEntered 774 | 775 | private void menuExitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuExitActionPerformed 776 | // TODO add your handling code here: 777 | dispose(); 778 | }//GEN-LAST:event_menuExitActionPerformed 779 | 780 | private void menuSettingsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuSettingsActionPerformed 781 | // TODO add your handling code here: 782 | dialogSettings.setVisible(true); 783 | }//GEN-LAST:event_menuSettingsActionPerformed 784 | 785 | private void menuAboutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuAboutActionPerformed 786 | // TODO add your handling code here: 787 | dialogAbout.setVisible(true); 788 | }//GEN-LAST:event_menuAboutActionPerformed 789 | 790 | private void buttonCoolActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonCoolActionPerformed 791 | // TODO add your handling code here: 792 | dialogAbout.setVisible(false); 793 | }//GEN-LAST:event_buttonCoolActionPerformed 794 | 795 | private void buttonCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonCancelActionPerformed 796 | // TODO add your handling code here: 797 | //restore original settings 798 | defaultURL.setText((prefs.get("defaultURL", ""))); 799 | checkBoxId.setSelected(prefs.getBoolean("showId", true)); 800 | checkBoxInvis.setSelected(prefs.getBoolean("showInvis", true)); 801 | 802 | if (prefs.get("browser", "").contentEquals("FF")) { 803 | buttonFF.setSelected(true); 804 | } 805 | if (prefs.get("browser", "").contentEquals("CR")) { 806 | buttonCR.setSelected(true); 807 | } 808 | if (prefs.get("browser", "").contentEquals("ED")) { 809 | buttonED.setSelected(true); 810 | } 811 | if (prefs.get("browser", "").contentEquals("SA")) { 812 | buttonSA.setSelected(true); 813 | } 814 | 815 | pathFF.setText(prefs.get("driverFF", "")); 816 | pathCR.setText(prefs.get("driverCR", "")); 817 | pathED.setText(prefs.get("driverED", "")); 818 | 819 | dialogSettings.setVisible(false); 820 | }//GEN-LAST:event_buttonCancelActionPerformed 821 | 822 | /** 823 | * @param args the command line arguments 824 | */ 825 | public static void main(String args[]) { 826 | /* Set the look and feel */ 827 | // 828 | 829 | try { 830 | //javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager.getSystemLookAndFeelClassName()); 831 | if (Theme.light()) { 832 | javax.swing.UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf"); 833 | } else { 834 | javax.swing.UIManager.setLookAndFeel("com.formdev.flatlaf.FlatDarkLaf"); 835 | } 836 | 837 | // for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { 838 | // if ("Nimbus".equals(info.getName())) { 839 | // javax.swing.UIManager.setLookAndFeel(info.getClassName()); 840 | // break; 841 | // } 842 | // } 843 | } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) { 844 | } 845 | // 846 | 847 | /* Create and display the form */ 848 | java.awt.EventQueue.invokeLater(new Runnable() { 849 | @Override 850 | public void run() { 851 | new Wisard().setVisible(true); 852 | } 853 | }); 854 | } 855 | // Variables declaration - do not modify//GEN-BEGIN:variables 856 | private javax.swing.JTextField CSSselectors; 857 | private javax.swing.JRadioButton buttonCR; 858 | private javax.swing.JButton buttonCancel; 859 | private javax.swing.JButton buttonCool; 860 | private javax.swing.JRadioButton buttonED; 861 | private javax.swing.JRadioButton buttonFF; 862 | private javax.swing.JToggleButton buttonInspect; 863 | private javax.swing.JRadioButton buttonJava; 864 | private javax.swing.JRadioButton buttonJs; 865 | private javax.swing.JRadioButton buttonJunit; 866 | private javax.swing.JRadioButton buttonJunit5; 867 | private javax.swing.JButton buttonRefresh; 868 | private javax.swing.JRadioButton buttonSA; 869 | private javax.swing.JButton buttonSave; 870 | private javax.swing.ButtonGroup buttonsBrowser; 871 | private javax.swing.ButtonGroup buttonsOutput; 872 | private javax.swing.JCheckBox checkBoxId; 873 | private javax.swing.JCheckBox checkBoxInvis; 874 | private javax.swing.JTextArea code; 875 | private javax.swing.JTextField currentUrl; 876 | private javax.swing.JTextField defaultURL; 877 | private javax.swing.JDialog dialogAbout; 878 | private javax.swing.JDialog dialogSettings; 879 | private javax.swing.JSplitPane jSplitPane1; 880 | private javax.swing.JToolBar jToolBar1; 881 | private javax.swing.JLabel labelCSS; 882 | private javax.swing.JLabel labelCopyright; 883 | private javax.swing.JLabel labelDefurl; 884 | private javax.swing.JLabel labelDesc; 885 | private javax.swing.JLabel labelDispopts; 886 | private javax.swing.JLabel labelDriver; 887 | private javax.swing.JLabel labelLink; 888 | private javax.swing.JLabel labelName; 889 | private javax.swing.JLabel labelOutput; 890 | private javax.swing.JLabel labelPlugin; 891 | private javax.swing.JLabel labelUrl; 892 | private javax.swing.JMenuItem menuAbout; 893 | private javax.swing.JMenuBar menuBar; 894 | private javax.swing.JMenu menuEdit; 895 | private javax.swing.JMenuItem menuExit; 896 | private javax.swing.JMenu menuFile; 897 | private javax.swing.JMenu menuHelp; 898 | private javax.swing.JMenuItem menuSettings; 899 | private javax.swing.JScrollPane paneCode; 900 | private javax.swing.JScrollPane paneConsole; 901 | private javax.swing.JScrollPane paneElements; 902 | private javax.swing.JPanel panelAbout; 903 | private javax.swing.JPanel panelElements; 904 | private javax.swing.JPanel panelSettings; 905 | private javax.swing.JTextField pathCR; 906 | private javax.swing.JTextField pathED; 907 | private javax.swing.JTextField pathFF; 908 | private javax.swing.JTable tableElements; 909 | private javax.swing.JTextArea textConsole; 910 | // End of variables declaration//GEN-END:variables 911 | 912 | private void exitProcedure() { 913 | bd.close(); 914 | this.dispose(); 915 | System.exit(0); 916 | } 917 | 918 | @Override 919 | public void addItem(String element, Object stack, String name, String id, String value, Object webElement, Boolean displayed) { 920 | //adds content to the elements table 921 | if (Theme.light()) { 922 | tableElements.setForeground(Color.LIGHT_GRAY); 923 | } else { 924 | tableElements.setForeground(Color.GRAY); 925 | } 926 | if ((!displayed) && (prefs.getBoolean("showInvis", false))) { 927 | element = Const.INVISIBLE + element; 928 | Object item = new Object[]{element, stack, name, id, value, webElement}; 929 | jTable1Model.addRow((Object[]) item); 930 | } else if (displayed) { 931 | Object item = new Object[]{element, stack, name, id, value, webElement}; 932 | jTable1Model.addRow((Object[]) item); 933 | } 934 | } 935 | 936 | @Override 937 | public void rescan() { 938 | //triggers rescan of the page 939 | 940 | //tidy up first 941 | popup.setVisible(false); 942 | for (int i = jTable1Model.getRowCount(); i > 0; i--) { 943 | jTable1Model.removeRow(i - 1); 944 | } 945 | 946 | //off we go 947 | Thread t = new Thread(bd, "Page Examiner"); 948 | t.start(); 949 | } 950 | 951 | @Override 952 | public void abort() { 953 | //triggers a UI cleanup 954 | this.errorMessage("Unexpected error!"); 955 | buttonInspect.doClick(); 956 | } 957 | 958 | @Override 959 | public void addCode(String fragment) { 960 | //adds content to the generated code 961 | code.setText(fragment); 962 | } 963 | 964 | @Override 965 | public void insertCode(String fragment, int above) { 966 | //inserts content to the generated code 967 | int point; 968 | try { 969 | point = code.getLineEndOffset(code.getLineCount() - above); 970 | } catch (BadLocationException e) { 971 | point = 1; 972 | //it'll be messy 973 | } 974 | code.insert(fragment, point - 1); 975 | 976 | } 977 | 978 | @Override 979 | public boolean alertResponse(String title) { 980 | int ok = JOptionPane.showConfirmDialog(new JFrame(), title, "Alert box opened by browser", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); 981 | if (ok == 0) { 982 | return true; 983 | } else { 984 | return false; 985 | } 986 | } 987 | 988 | @Override 989 | public String enterValue(String title) { 990 | return (String) JOptionPane.showInputDialog(new JFrame(), title, "Enter Value", JOptionPane.QUESTION_MESSAGE); 991 | } 992 | 993 | @Override 994 | public String enterSelection(String title, String choices[]) { 995 | return (String) JOptionPane.showInputDialog(new JFrame(), title, "Make Selection", JOptionPane.QUESTION_MESSAGE, null, choices, choices[0]); 996 | } 997 | 998 | @Override 999 | public void elementIdent(String text) { 1000 | if (text.length() > Const.MAX_SIZ) { 1001 | //crop the text 1002 | text = text.substring(0, Const.MAX_SIZ); 1003 | } 1004 | JOptionPane.showMessageDialog(new JFrame(), text, "Element Highlighted in Browser", JOptionPane.PLAIN_MESSAGE); 1005 | } 1006 | 1007 | @Override 1008 | public void errorMessage(String message) { 1009 | if (message.length() > Const.MAX_SIZ) { 1010 | //crop the text 1011 | message = message.substring(0, Const.MAX_SIZ); 1012 | } 1013 | JOptionPane.showMessageDialog(new JFrame(), message.replace(". ", ". \n"), "Error", JOptionPane.INFORMATION_MESSAGE); 1014 | } 1015 | 1016 | @Override 1017 | public void finished() { 1018 | if (Theme.light()) { 1019 | tableElements.setForeground(Color.BLACK); 1020 | } else { 1021 | tableElements.setForeground(Color.LIGHT_GRAY); 1022 | } 1023 | 1024 | } 1025 | 1026 | @Override 1027 | public String getCSSselectors() { 1028 | return prefs.get("cssselectors", ""); 1029 | } 1030 | 1031 | } 1032 | --------------------------------------------------------------------------------