├── repo
└── .project.local
├── .gitattributes
├── launch.sh
├── launch.cmd
├── screenshots
├── config.png
├── form.png
├── capture1.png
├── capture2.png
├── capture3.png
├── capture4.png
├── codegen.png
├── breadcumps.png
├── exception.png
├── swd_table.png
├── swet_javafx.png
├── config_browse.png
├── confirm_close.png
├── exported_flow.png
├── open_sesssion.png
├── firefox_vesion.png
├── tip_of_the_day.png
├── exit_confirmation.png
├── table_editor_view.png
├── config_browse_result.png
├── exception_app_cersion.png
├── ctrl_right_button_bw_32.png
├── ctrl_right_button_bw_36.png
├── ctrl_right_button_bw_48.png
├── capture_run_complexformex.png
├── init_with_custom_arguments.png
└── error_invalid_template_format.png
├── src
├── test
│ ├── resources
│ │ ├── question.png
│ │ ├── ElementSearch.html
│ │ └── log4j_test.xml
│ └── java
│ │ └── com
│ │ └── github
│ │ └── sergueik
│ │ └── swet
│ │ ├── RenderTemplateTest.java
│ │ ├── Log4j2Test.java
│ │ ├── InstalledBrowsersTest.java
│ │ ├── Log4jTest.java
│ │ ├── SwetImmutableListCopyOfExcerptionTest.java
│ │ ├── PropertiesTest.java
│ │ ├── EscapeUtilTest.java
│ │ ├── WriteScriptFileTest.java
│ │ ├── BrowserDiscoveryTest.java
│ │ ├── TestConfigurationParserTest.java
│ │ ├── AWTTest.java
│ │ ├── OSUtilsAndWinRegistryTest.java
│ │ └── ExcelWriterTest.java
└── main
│ ├── resources
│ ├── images
│ │ ├── demo.png
│ │ ├── find.png
│ │ ├── open.png
│ │ ├── page.png
│ │ ├── quit.png
│ │ ├── save.png
│ │ ├── stop.gif
│ │ ├── arrow.png
│ │ ├── demo_36.png
│ │ ├── down_sm.png
│ │ ├── find_32.png
│ │ ├── find_36.png
│ │ ├── gear_36.png
│ │ ├── help_32.png
│ │ ├── launch.png
│ │ ├── light1.png
│ │ ├── open_32.png
│ │ ├── open_36.png
│ │ ├── quit_32.png
│ │ ├── save_32.png
│ │ ├── save_36.png
│ │ ├── start.gif
│ │ ├── browsers.png
│ │ ├── code_128.png
│ │ ├── facepalm.png
│ │ ├── find2_36.png
│ │ ├── find_2_32.png
│ │ ├── flowchart.png
│ │ ├── launch_32.png
│ │ ├── launch_36.png
│ │ ├── right_sm.png
│ │ ├── wrench_36.png
│ │ ├── browsers_32.png
│ │ ├── codegen_32.png
│ │ ├── codegen_36.png
│ │ ├── excel_gen_32.png
│ │ ├── flowchart_32.png
│ │ ├── preferences.png
│ │ ├── arrow_expanded.png
│ │ ├── o3_calc_app_32.png
│ │ ├── preferences_32.png
│ │ ├── document_wrench_bw.png
│ │ ├── document_wrench_color.ico
│ │ ├── document_wrench_color.png
│ │ └── document_wrench_color_36.png
│ ├── templates
│ │ ├── aftertest.twig
│ │ ├── initObjects.twig
│ │ ├── example1.twig
│ │ ├── example_broken.twig
│ │ ├── beforeTest.twig
│ │ ├── importList.twig
│ │ ├── core_selenium_csharp.twig
│ │ ├── core_selenium_java.twig
│ │ ├── core_selenium_linq_csharp.twig
│ │ ├── basic_page_objects_java.twig
│ │ ├── core_selenium_java8_streams.twig
│ │ ├── core_selenium_python.twig
│ │ ├── core_selenium_ruby.twig
│ │ └── core_selenium_with_wait_java.twig
│ ├── test.configuration
│ ├── blankpage.html
│ ├── config.properties
│ ├── application.properties
│ ├── internalConfiguration.yaml
│ ├── help.yaml
│ ├── log4j.xml
│ ├── sample.yaml
│ ├── sampleTest.json
│ └── log4j2.xml
│ └── java
│ ├── org
│ ├── mihalis
│ │ └── opal
│ │ │ └── multi
│ │ │ ├── MultiChoiceLabelProvider.java
│ │ │ ├── MultiChoiceDefaultLabelProvider.java
│ │ │ ├── SimpleSelectionAdapter.java
│ │ │ └── MultiChoiceSelectionListener.java
│ └── passer
│ │ └── ChoiceItem.java
│ ├── custom
│ └── swt
│ │ └── widgets
│ │ ├── SimpleFuture.java
│ │ ├── Container.java
│ │ ├── InfoPopup.java
│ │ ├── ImageLabel.java
│ │ ├── MultilineButton.java
│ │ ├── MultiSelectCombo.java
│ │ └── SWTUtil.java
│ └── com
│ └── github
│ └── sergueik
│ └── swet
│ ├── ConfigDataSerializer.java
│ ├── BrowserConfiguration.java
│ ├── ChoiceDialogEx.java
│ ├── BusyIndicatorEx.java
│ ├── PropertiesParser.java
│ ├── ConfigData.java
│ ├── ListJavaFonts.java
│ ├── JavaHotkeyManager.java
│ ├── Configuration.java
│ ├── TestConfigurationParser.java
│ ├── BatchPipeRun.java
│ ├── SystemTrayEx.java
│ ├── JavaScanner.java
│ ├── UtilExtensions.java
│ ├── MouseEventDemo.java
│ ├── ExceptionDialogEx.java
│ ├── ButtonSizeEx.java
│ ├── YamlHelper.java
│ ├── RenderTemplate.java
│ ├── User32WakeupTest.java
│ └── TemplateCache.java
├── get.ps1
├── .gitignore
├── LICENSE
├── launch.ps1
├── run2.sh
├── run.sh
├── MouseEventDemo.java
├── run.cmd
└── run2.cmd
/repo/.project.local:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.cmd eol=crlf
2 | *.ps1 eol=crlf
3 | *.sh eol=lf
4 |
--------------------------------------------------------------------------------
/launch.sh:
--------------------------------------------------------------------------------
1 | export SKIP_BUILD=true
2 | $(dirname $0)/run.sh $*
3 |
--------------------------------------------------------------------------------
/launch.cmd:
--------------------------------------------------------------------------------
1 | @echo OFF
2 | set SKIP_BUILD=true
3 | call run %*
4 | set SKIP_BUILD=
--------------------------------------------------------------------------------
/screenshots/config.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/config.png
--------------------------------------------------------------------------------
/screenshots/form.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/form.png
--------------------------------------------------------------------------------
/screenshots/capture1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/capture1.png
--------------------------------------------------------------------------------
/screenshots/capture2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/capture2.png
--------------------------------------------------------------------------------
/screenshots/capture3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/capture3.png
--------------------------------------------------------------------------------
/screenshots/capture4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/capture4.png
--------------------------------------------------------------------------------
/screenshots/codegen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/codegen.png
--------------------------------------------------------------------------------
/screenshots/breadcumps.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/breadcumps.png
--------------------------------------------------------------------------------
/screenshots/exception.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/exception.png
--------------------------------------------------------------------------------
/screenshots/swd_table.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/swd_table.png
--------------------------------------------------------------------------------
/screenshots/swet_javafx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/swet_javafx.png
--------------------------------------------------------------------------------
/screenshots/config_browse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/config_browse.png
--------------------------------------------------------------------------------
/screenshots/confirm_close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/confirm_close.png
--------------------------------------------------------------------------------
/screenshots/exported_flow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/exported_flow.png
--------------------------------------------------------------------------------
/screenshots/open_sesssion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/open_sesssion.png
--------------------------------------------------------------------------------
/screenshots/firefox_vesion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/firefox_vesion.png
--------------------------------------------------------------------------------
/screenshots/tip_of_the_day.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/tip_of_the_day.png
--------------------------------------------------------------------------------
/src/test/resources/question.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/test/resources/question.png
--------------------------------------------------------------------------------
/screenshots/exit_confirmation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/exit_confirmation.png
--------------------------------------------------------------------------------
/screenshots/table_editor_view.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/table_editor_view.png
--------------------------------------------------------------------------------
/src/main/resources/images/demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/demo.png
--------------------------------------------------------------------------------
/src/main/resources/images/find.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/find.png
--------------------------------------------------------------------------------
/src/main/resources/images/open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/open.png
--------------------------------------------------------------------------------
/src/main/resources/images/page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/page.png
--------------------------------------------------------------------------------
/src/main/resources/images/quit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/quit.png
--------------------------------------------------------------------------------
/src/main/resources/images/save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/save.png
--------------------------------------------------------------------------------
/src/main/resources/images/stop.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/stop.gif
--------------------------------------------------------------------------------
/screenshots/config_browse_result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/config_browse_result.png
--------------------------------------------------------------------------------
/screenshots/exception_app_cersion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/exception_app_cersion.png
--------------------------------------------------------------------------------
/src/main/resources/images/arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/arrow.png
--------------------------------------------------------------------------------
/src/main/resources/images/demo_36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/demo_36.png
--------------------------------------------------------------------------------
/src/main/resources/images/down_sm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/down_sm.png
--------------------------------------------------------------------------------
/src/main/resources/images/find_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/find_32.png
--------------------------------------------------------------------------------
/src/main/resources/images/find_36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/find_36.png
--------------------------------------------------------------------------------
/src/main/resources/images/gear_36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/gear_36.png
--------------------------------------------------------------------------------
/src/main/resources/images/help_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/help_32.png
--------------------------------------------------------------------------------
/src/main/resources/images/launch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/launch.png
--------------------------------------------------------------------------------
/src/main/resources/images/light1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/light1.png
--------------------------------------------------------------------------------
/src/main/resources/images/open_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/open_32.png
--------------------------------------------------------------------------------
/src/main/resources/images/open_36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/open_36.png
--------------------------------------------------------------------------------
/src/main/resources/images/quit_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/quit_32.png
--------------------------------------------------------------------------------
/src/main/resources/images/save_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/save_32.png
--------------------------------------------------------------------------------
/src/main/resources/images/save_36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/save_36.png
--------------------------------------------------------------------------------
/src/main/resources/images/start.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/start.gif
--------------------------------------------------------------------------------
/src/main/resources/templates/aftertest.twig:
--------------------------------------------------------------------------------
1 | @AfterTest
2 | public void tearDown() {
3 | driver.quit();
4 | }
5 |
--------------------------------------------------------------------------------
/screenshots/ctrl_right_button_bw_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/ctrl_right_button_bw_32.png
--------------------------------------------------------------------------------
/screenshots/ctrl_right_button_bw_36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/ctrl_right_button_bw_36.png
--------------------------------------------------------------------------------
/screenshots/ctrl_right_button_bw_48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/ctrl_right_button_bw_48.png
--------------------------------------------------------------------------------
/src/main/resources/images/browsers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/browsers.png
--------------------------------------------------------------------------------
/src/main/resources/images/code_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/code_128.png
--------------------------------------------------------------------------------
/src/main/resources/images/facepalm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/facepalm.png
--------------------------------------------------------------------------------
/src/main/resources/images/find2_36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/find2_36.png
--------------------------------------------------------------------------------
/src/main/resources/images/find_2_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/find_2_32.png
--------------------------------------------------------------------------------
/src/main/resources/images/flowchart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/flowchart.png
--------------------------------------------------------------------------------
/src/main/resources/images/launch_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/launch_32.png
--------------------------------------------------------------------------------
/src/main/resources/images/launch_36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/launch_36.png
--------------------------------------------------------------------------------
/src/main/resources/images/right_sm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/right_sm.png
--------------------------------------------------------------------------------
/src/main/resources/images/wrench_36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/wrench_36.png
--------------------------------------------------------------------------------
/screenshots/capture_run_complexformex.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/capture_run_complexformex.png
--------------------------------------------------------------------------------
/screenshots/init_with_custom_arguments.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/init_with_custom_arguments.png
--------------------------------------------------------------------------------
/src/main/resources/images/browsers_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/browsers_32.png
--------------------------------------------------------------------------------
/src/main/resources/images/codegen_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/codegen_32.png
--------------------------------------------------------------------------------
/src/main/resources/images/codegen_36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/codegen_36.png
--------------------------------------------------------------------------------
/src/main/resources/images/excel_gen_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/excel_gen_32.png
--------------------------------------------------------------------------------
/src/main/resources/images/flowchart_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/flowchart_32.png
--------------------------------------------------------------------------------
/src/main/resources/images/preferences.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/preferences.png
--------------------------------------------------------------------------------
/src/main/resources/images/arrow_expanded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/arrow_expanded.png
--------------------------------------------------------------------------------
/src/main/resources/images/o3_calc_app_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/o3_calc_app_32.png
--------------------------------------------------------------------------------
/src/main/resources/images/preferences_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/preferences_32.png
--------------------------------------------------------------------------------
/screenshots/error_invalid_template_format.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/screenshots/error_invalid_template_format.png
--------------------------------------------------------------------------------
/src/main/resources/templates/initObjects.twig:
--------------------------------------------------------------------------------
1 | private Log log;
2 | private WebDriver driver;
3 | private SeleniumKeywords seleniumKeywords;
4 |
--------------------------------------------------------------------------------
/src/main/resources/images/document_wrench_bw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/document_wrench_bw.png
--------------------------------------------------------------------------------
/src/main/resources/images/document_wrench_color.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/document_wrench_color.ico
--------------------------------------------------------------------------------
/src/main/resources/images/document_wrench_color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/document_wrench_color.png
--------------------------------------------------------------------------------
/src/main/resources/images/document_wrench_color_36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergueik/SWET/HEAD/src/main/resources/images/document_wrench_color_36.png
--------------------------------------------------------------------------------
/src/main/resources/test.configuration:
--------------------------------------------------------------------------------
1 | # examples of configurations
2 | column1|column2|column3
3 | A1|A2|A3
4 | B1 B2 B3
5 | C1,C2,C3
6 | D1;D2;D3
7 |
8 |
--------------------------------------------------------------------------------
/src/main/java/org/mihalis/opal/multi/MultiChoiceLabelProvider.java:
--------------------------------------------------------------------------------
1 | package org.mihalis.opal.multi;
2 |
3 | public interface MultiChoiceLabelProvider {
4 | String getText(Object element);
5 | }
--------------------------------------------------------------------------------
/get.ps1:
--------------------------------------------------------------------------------
1 | $s1 = [xml]$raw_data
2 | $s1.'rawdata'.'div'.'div'.'ul'.'li'.'div'.'h3'.'a' | ForEach-Object {
3 | Write-Output ($_.GetAttribute('title'))
4 | Write-Output ($_.GetAttribute('href'))
5 | $_ | Get-Member | Out-Null
6 | }
7 |
--------------------------------------------------------------------------------
/src/main/resources/blankpage.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Blank page
4 |
5 |
6 |
7 |
8 | Blank Page
9 |
10 | Keymaster is being injected by WebDriver
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | **/bin/**
2 | **/.settings
3 | **/.classpath
4 | **/.project
5 | **/.gitignore
6 | **/work/**
7 | **/target/**
8 | **/*.log
9 | **/src/**/*.jar
10 | **/build/**
11 | **/test-output/**
12 | /pom.xml.releaseBackup
13 | /release.properties
14 | /settings.xml
15 | *.unc-backup~
16 | *.uncrustify
17 | *~
18 |
--------------------------------------------------------------------------------
/src/main/resources/templates/example1.twig:
--------------------------------------------------------------------------------
1 | {% if (useCss) %}
2 | driver.findElement(By.cssSelector("{{ ElementCssSelector }}");
3 | {% elseif (useXPath) %}
4 | driver.findElement(By.cssSelector("{{ ElementXPath }}");
5 | {% elseif (useId)%}
6 | driver.findElement(By.Id("{{ ElementId }}");
7 | {% else %}
8 | {% endif %}
--------------------------------------------------------------------------------
/src/main/java/org/mihalis/opal/multi/MultiChoiceDefaultLabelProvider.java:
--------------------------------------------------------------------------------
1 | package org.mihalis.opal.multi;
2 |
3 | public class MultiChoiceDefaultLabelProvider
4 | implements MultiChoiceLabelProvider {
5 |
6 | @Override
7 | public String getText(final Object element) {
8 | return element == null ? "" : element.toString();
9 | }
10 |
11 | }
--------------------------------------------------------------------------------
/src/main/resources/templates/example_broken.twig:
--------------------------------------------------------------------------------
1 | {% if (ElementSelectedBy == 'ElementCssSelector') -%}
2 | driver.findElement(By.cssSelector("{{ ElementCssSelector }}");
3 | {% elseif (ElementSelectedBy == 'ElementXPath') -%}
4 | driver.findElement(By.Xpath("{{ ElementXPath }}");
5 | {% else= 'ElementId') -%}
6 | driver.findElement(By.Id("{{ ElementId }}");
7 | {% else -%}
8 | {% endif -%}
9 |
--------------------------------------------------------------------------------
/src/main/resources/templates/beforeTest.twig:
--------------------------------------------------------------------------------
1 | @Parameters({"browser", "URL"})
2 | @BeforeTest
3 | public void setUp(String browser, String URL) throws Exception {
4 | log = Utils.createLog(this.getClass().getSimpleName());
5 | driver = WebDriverManager.createWebDriver(browser, log);
6 | seleniumKeywords = new SeleniumKeywords(driver, log);
7 | seleniumKeywords.open_Url(URL);
8 | }
--------------------------------------------------------------------------------
/src/test/resources/ElementSearch.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Element Search
4 |
5 |
6 |
7 |
8 | Element Search
9 |
10 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/main/resources/templates/importList.twig:
--------------------------------------------------------------------------------
1 | import libs.WebDriverUtils.SeleniumKeywords;
2 | import libs.WebDriverUtils.WebDriverManager;
3 |
4 | import org.openqa.selenium.WebDriver;
5 |
6 | import org.testng.annotations.AfterTest;
7 | import org.testng.annotations.BeforeTest;
8 | import org.testng.annotations.Parameters;
9 | import org.testng.annotations.Test;
10 |
11 | import utils.Logs.Log;
12 | import utils.Utility;
13 |
--------------------------------------------------------------------------------
/src/main/resources/config.properties:
--------------------------------------------------------------------------------
1 | chromeDriverPath=D:\\Books\\SourceCode\\seleniumDriver\\chromedriver.exe
2 | firefoxDriverPath=D:\\Books\\SourceCode\\seleniumDriver\\geckodriver.exe
3 | ieDriverPath=D:\\Books\\SourceCode\\seleniumDriver\\IEDriverServer.exe
4 | selenium.getLink=Go to URL
5 | selenium.click=Click
6 | selenium.type_Text=Write Text
7 | selenium.selectDropDownListOptionByLabel=Select Option
8 | selenium.verifyElementTextEqual=checkValue
9 | selenium.verifyElementTextContains=CheckContainsValue
--------------------------------------------------------------------------------
/src/main/java/custom/swt/widgets/SimpleFuture.java:
--------------------------------------------------------------------------------
1 | package custom.swt.widgets;
2 |
3 | public class SimpleFuture {
4 |
5 | I value;
6 | boolean aborted;
7 |
8 | public synchronized void abort() {
9 | aborted = true;
10 | notifyAll();
11 | }
12 |
13 | public synchronized void put(I value) {
14 | this.value = value;
15 | notifyAll();
16 | }
17 |
18 | public synchronized I get() throws InterruptedException {
19 | while (value == null && !aborted)
20 | wait();
21 | return value;
22 | }
23 |
24 | public synchronized I peek() {
25 | return value;
26 | }
27 | }
--------------------------------------------------------------------------------
/src/main/resources/templates/core_selenium_csharp.twig:
--------------------------------------------------------------------------------
1 | {#
2 | template: Core Selenium C#
3 | #}
4 |
5 | // {{ ElementCodeName }}
6 | {% if (ElementText != '') -%}
7 | // {{ ElementText }}
8 | {% endif -%}
9 | IWebElement button = driver.FindElement(
10 | {% if (ElementSelectedBy == 'ElementCssSelector') -%}
11 | By.CssSelector("{{ ElementCssSelector }}")
12 | {% elseif (ElementSelectedBy == 'ElementXPath') -%}
13 | By.XPath("{{ ElementXPath }}")
14 | {% elseif (ElementSelectedBy == 'ElementId') -%}
15 | By.Id("{{ ElementId }}")
16 | {% elseif (ElementSelectedBy == 'ElementText') -%}
17 | By.XPath("//{{ ElementTagName }}[contains(normalize-space(text()), '{{ ElementText }}')]")
18 | {% endif -%}
19 | )
20 |
--------------------------------------------------------------------------------
/src/main/resources/templates/core_selenium_java.twig:
--------------------------------------------------------------------------------
1 | {#
2 | template: Core Selenium Java
3 | #}
4 |
5 | // {{ ElementCodeName }}
6 | {% if (ElementText != '') -%}
7 | // {{ ElementText }}
8 | {% endif -%}
9 | WebElement element = driver.findElement(
10 | {% if (ElementSelectedBy == 'ElementCssSelector') -%}
11 | By.cssSelector("{{ ElementCssSelector }}")
12 | {% elseif (ElementSelectedBy == 'ElementXPath') -%}
13 | By.xpath("{{ ElementXPath }}")
14 | {% elseif (ElementSelectedBy == 'ElementId') -%}
15 | By.id("{{ ElementId }}")
16 | {% elseif (ElementSelectedBy == 'ElementText') -%}
17 | By.xpath("//{{ ElementTagName }}[contains(normalize-space(text()), '{{ ElementText }}')]")
18 | {% endif -%}
19 | )
20 |
--------------------------------------------------------------------------------
/src/main/java/org/mihalis/opal/multi/SimpleSelectionAdapter.java:
--------------------------------------------------------------------------------
1 | package org.mihalis.opal.multi;
2 |
3 | import org.eclipse.swt.events.SelectionEvent;
4 | import org.eclipse.swt.events.SelectionListener;
5 |
6 | public abstract class SimpleSelectionAdapter implements SelectionListener {
7 |
8 | // see
9 | // org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
10 |
11 | @Override
12 | public void widgetDefaultSelected(final SelectionEvent e) {
13 | this.handle(e);
14 |
15 | }
16 |
17 | @Override
18 | public void widgetSelected(final SelectionEvent e) {
19 | this.handle(e);
20 |
21 | }
22 |
23 | public abstract void handle(SelectionEvent e);
24 |
25 | }
--------------------------------------------------------------------------------
/src/main/resources/templates/core_selenium_linq_csharp.twig:
--------------------------------------------------------------------------------
1 | {#
2 | template: Selenium with LINQ C#
3 | #}
4 |
5 | // {{ ElementCodeName }}
6 | {% if (ElementText != '') -%}
7 | // {{ ElementText }}
8 | {% endif -%}
9 | IWebElement element =
10 | {% if (ElementSelectedBy == 'ElementText') -%}
11 | driver.FindElements(By.TagName("{{ ElementTagName }}"))
12 | .First(o => String.Compare("{{ElementText}}", o.Text, StringComparison.InvariantCulture) == 0);
13 | {% else -%}
14 | driver.FindElement(
15 | {% if (ElementSelectedBy == 'ElementCssSelector') -%}
16 | By.CssSelector("{{ ElementCssSelector }}")
17 | {% elseif (ElementSelectedBy == 'ElementXPath') -%}
18 | By.XPath("{{ ElementXPath }}")
19 | {% elseif (ElementSelectedBy == 'ElementId') -%}
20 | By.Id("{{ ElementId }}")
21 | {% endif -%}
22 | )
23 | {% endif -%}
24 | )
25 |
--------------------------------------------------------------------------------
/src/main/resources/templates/basic_page_objects_java.twig:
--------------------------------------------------------------------------------
1 | {#
2 | template: Basic Page Objects Java
3 | }
4 | class TestPage (Page) {
5 | // {{ ElementText }}
6 | {% if (ElementSelectedBy == 'ElementCssSelector') -%}
7 | @FindBy( how = How.CSS, using = "{{ ElementCssSelector }}" )
8 | {% elseif (ElementSelectedBy == 'ElementXPath') -%}
9 | @FindBy( how = How.XPATH, using = "{{ ElementXPath }}" )
10 | {% elseif (ElementSelectedBy == 'ElementId') -%}
11 | @FindBy( how = How.ID, using = "{{ ElementId }}" )
12 | {% elseif (ElementSelectedBy == 'ElementText') -%}
13 | @FindBy( how = How.XPATH, using = "//{{ ElementTagName }}[contains(normalize-space(text()), '{{ ElementText }}')]" ) #}
14 | {% endif -%}
15 | {% if (ElementVariable != '') -%}
16 | private WebElement {{ ElementVariable }};
17 | {% else -%}
18 | private WebElement element;
19 | {% endif -%}
--------------------------------------------------------------------------------
/src/main/resources/templates/core_selenium_java8_streams.twig:
--------------------------------------------------------------------------------
1 | {#
2 | template: Core Selenium Java8 / Streams
3 | #}
4 | // {{ ElementCodeName }}
5 | {% if (ElementText != '') -%}
6 | // Text: {{ ElementText }}
7 | {% endif -%}
8 | {% if (ElementSelectedBy == 'ElementText') -%}
9 | WebElement element = driver.findElements( By.tagName("{{ ElementTagName }}"
10 | .stream().filter(o -> {
11 | return (Boolean) (o.getText().contains("{{ ElementText }}"));
12 | }).findFirst();
13 | {% else -%}
14 | WebElement element = driver.findElement(
15 | {% if (ElementSelectedBy == 'ElementCssSelector') -%}
16 | By.cssSelector("{{ ElementCssSelector }}")
17 | {% elseif (ElementSelectedBy == 'ElementXPath') -%}
18 | By.xpath("{{ ElementXPath }}")
19 | {% elseif (ElementSelectedBy == 'ElementId') -%}
20 | By.id("{{ ElementId }}")
21 | {% endif -%}
22 | )
23 | {% endif -%}
24 |
--------------------------------------------------------------------------------
/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | # username / password not currently used - reserved for Sauce Labs or browserStack
2 | username: username
3 | password: password
4 | # no quotes should be put around paths. Trailing whitespace is ok
5 | # use the following syntax for environment variables: ${USERPROFILE}\\desktop\\chromedriver.exe
6 | chromeDriverPath: ${USERPROFILE}\\Downloads\\chromedriver.exe
7 | # chromeDriverPath: ${HOME}/Downloads/chromedriver
8 | geckoDriverPath: c:/java/selenium/geckodriver.exe
9 | firefoxBrowserPath: C:/Program Files (x86)/Mozilla Firefox/firefox.exe
10 | # firefoxBrowserPath: /Applications/Firefox.app/Contents/MacOS/firefox
11 | geckoDriverPath: c:/java/selenium/geckodriver.exe
12 | # geckoDriverPath: ${HOME}/Downloads/geckodriver
13 | ieDriverPath: c:/java/selenium/IEDriverServer.exe
14 | edgeDriverPath: C:/Program Files (x86)/Microsoft Web Driver/MicrosoftWebDriver.exe
15 |
16 |
--------------------------------------------------------------------------------
/src/main/resources/templates/core_selenium_python.twig:
--------------------------------------------------------------------------------
1 | {#
2 | template: Core Selenium Python
3 | #}
4 |
5 | from selenium import webdriver
6 | driver = webdriver.Chrome()
7 |
8 | def locate_{{ ElementCodeName }}():
9 | {% if (ElementText != '') -%}
10 | # {{ ElementText }}
11 | {% endif -%}
12 | {% if (ElementSelectedBy == 'ElementCssSelector') -%}
13 | return driver.find_element_by_css('{{ ElementCssSelector }}');
14 |
15 | {% elseif (ElementSelectedBy == 'ElementXPath') -%}
16 | return driver.find_element_by_xpath('{{ ElementXPath }}');
17 |
18 | {% elseif (ElementSelectedBy == 'ElementId') -%}
19 | return driver.find_element_by_id('{{ ElementId }}');
20 |
21 | {% elseif (ElementSelectedBy == 'ElementText') -%}
22 | return driver.find_element_by_xpath("//{{ ElementTagName }}[contains(normalize-space(text()), '{{ ElementText }}')]")
23 |
24 | {% endif -%}
25 |
26 | # TODO: preserve whitespace
27 |
--------------------------------------------------------------------------------
/src/main/resources/templates/core_selenium_ruby.twig:
--------------------------------------------------------------------------------
1 | {#
2 | template: Core Selenium Ruby
3 | #}
4 |
5 | require 'selenium-webdriver'
6 |
7 | class PageElement
8 |
9 | def initialize(url)
10 | @driver=Selenium::WebDriver.for :chrome
11 | @driver.manage.window.maximize
12 | @driver.navigate.to url
13 | end
14 | def close_browser()
15 | @driver.quit
16 | end
17 | def locate_{{ ElementCodeName }}()
18 | {% if (ElementText != '') -%}
19 | # {{ ElementText }}
20 | {% endif -%}
21 | @driver.find_element(
22 | {% if (ElementSelectedBy == 'ElementCssSelector') -%}
23 | :css, '{{ ElementCssSelector }}'
24 | {% elseif (ElementSelectedBy == 'ElementXPath') -%}
25 | :xpath,'{{ ElementXPath }}'
26 | {% elseif (ElementSelectedBy == 'ElementId') -%}
27 | :id,'{{ ElementId }}'
28 | {% elseif (ElementSelectedBy == 'ElementText') -%}
29 | :xpath, "//{{ ElementTagName }}[contains(normalize-space(text()), '{{ ElementText }}')]"
30 | {% endif -%}
31 | )
32 | end
33 | end
--------------------------------------------------------------------------------
/src/test/java/com/github/sergueik/swet/RenderTemplateTest.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 | /**
3 | * Copyright 2014 - 2019 Serguei Kouzmine
4 | */
5 |
6 | import java.io.File;
7 | import java.util.HashMap;
8 |
9 | import org.junit.Test;
10 |
11 | import com.github.sergueik.swet.Utils;
12 | import com.github.sergueik.swet.RenderTemplate;
13 |
14 | public class RenderTemplateTest {
15 |
16 | private String templateAbsolutePath = System.getProperty("user.dir")
17 | + File.separator + "src\\main\\resources\\templates" ;
18 |
19 | @Test
20 | public void renderTest() {
21 | String templatePath = System.getProperty("user.dir") + File.separator
22 | + "src\\main\\resources\\templates\\core_selenium_csharp.twig";
23 | RenderTemplate renderTemplate = new RenderTemplate();
24 | System.err
25 | .println(String.format("Reading template from %s ...", templatePath));
26 | renderTemplate.setTemplateAbsolutePath(
27 | templatePath.replace("\\\\", "\\").replace("\\", "/"));
28 | String output = renderTemplate.renderTest();
29 | System.err.println("Rendered: " + output);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014,2017 Serguei Kouzmine
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 |
--------------------------------------------------------------------------------
/src/main/java/org/passer/ChoiceItem.java:
--------------------------------------------------------------------------------
1 | package org.passer;
2 |
3 | /*******************************************************************************
4 | * Copyright (c) 2015 Fabian Prasser
5 | *******************************************************************************/
6 |
7 | /**
8 | * Item for the choices dialog
9 | * @author Fabian Prasser
10 | */
11 | public class ChoiceItem {
12 |
13 | private String text;
14 | private String tooltipText;
15 |
16 | public ChoiceItem(String text, String tooltipText) {
17 | checkNull(text);
18 | checkNull(tooltipText);
19 | this.text = text;
20 | this.tooltipText = tooltipText;
21 | }
22 |
23 | public String getText() {
24 | return text;
25 | }
26 |
27 | public String getTooltipText() {
28 | return tooltipText;
29 | }
30 |
31 | public void setText(String data) {
32 | checkNull(data);
33 | this.text = data;
34 | }
35 |
36 | public void setTooltipText(String data) {
37 | checkNull(tooltipText);
38 | this.tooltipText = data;
39 | }
40 |
41 | private void checkNull(Object object) {
42 | if (object == null) {
43 | throw new IllegalArgumentException("Null is not a valid argument");
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/src/main/resources/internalConfiguration.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | Keywords:
3 | CLEAR_TEXT: clearText
4 | SWITCH_FRAME: switchFrame
5 | SET_TEXT: enterText
6 | CLICK_CHECKBOX: clickCheckBox
7 | SEND_KEYS: enterText
8 | VERIFY_TEXT: verifyText
9 | CLICK_RADIO: clickRadioButton
10 | GET_ATTR: getElementAttribute
11 | CLICK_LINK: clickLink
12 | GET_TEXT: getElementText
13 | ELEMENT_PRESENT: elementPresent
14 | GOTO_URL: navigateTo
15 | CLICK_BUTTON: clickButton
16 | CLOSE_BROWSER: closeBrowser
17 | CREATE_BROWSER: openBrowser
18 | VERIFY_ATTR: verifyAttribute
19 | CLICK: clickButton
20 | WAIT: wait
21 | SELECT_OPTION: selectDropDown
22 | SWDSelectors:
23 | ElementCssSelector: cssSelector
24 | ElementTagName: tagName
25 | ElementText: text
26 | ElementId: id
27 | ElementLinkText: linkText
28 | ElementXPath: xpath
29 | 'Column Headers':
30 | - 'Element'
31 | - 'Action Keyword'
32 | - 'Selector Choice'
33 | - 'Selector Value'
34 | - 'Param 1'
35 | - 'Param 2'
36 | - 'Param 3'
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 |
--------------------------------------------------------------------------------
/src/main/resources/help.yaml:
--------------------------------------------------------------------------------
1 | 'Testsuite Program creation': "You can generate a program in Java , C# , Ruby or other language. Few templates are embedded.
2 | You can provide your own using http://jtwig.org/ syntax:
3 | {% if (ElementText != '') -%}
4 | // Text: {{ ElementText }}
5 | {% endif -%} "
6 |
7 | 'Keyword-driven Framework flow creation': 'You can generate and export it as an Excel file
8 | a Keyword-driven Framework http://toolsqa.com/selenium-webdriver/keyword-driven-framework
9 | test flow'
10 |
11 | 'Saving and restoring sessions': "You can save the recording session to continue later..
12 | Recording will be written in YAML format and will contain all element attributes
13 | (including the deselected ones) of all recorder elements:
14 | ElementCssSelector: img.site-header-logo
15 | ElementSelectedBy: ElementCssSelector
16 | ElementCodeName: logo
17 | ElementPageURL: https://coderanch.com/c/java
18 | ElementTagName: IMG
19 | ElementStepNumber: 1
20 | ElementText: ''
21 | ElementId: ''
22 | ElementXPath: /html/body/header[1]/div[2]/div[1]/span[1]/img
23 | "
--------------------------------------------------------------------------------
/src/main/java/org/mihalis/opal/multi/MultiChoiceSelectionListener.java:
--------------------------------------------------------------------------------
1 | package org.mihalis.opal.multi;
2 |
3 | import org.eclipse.swt.events.SelectionEvent;
4 | import org.eclipse.swt.events.SelectionListener;
5 | import org.eclipse.swt.widgets.Button;
6 | import org.eclipse.swt.widgets.Shell;
7 |
8 | public abstract class MultiChoiceSelectionListener
9 | implements SelectionListener {
10 | private final MultiChoiceEx parent;
11 |
12 | public MultiChoiceSelectionListener(final MultiChoiceEx parent) {
13 | this.parent = parent;
14 | }
15 |
16 | // see
17 | // org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
18 | @Override
19 | public final void widgetSelected(final SelectionEvent e) {
20 | final Button button = (Button) e.widget;
21 | handle(parent, parent.getLastModified(), button.getSelection(),
22 | parent.getPopup());
23 | }
24 |
25 | // see
26 | // org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
27 | @Override
28 | public final void widgetDefaultSelected(final SelectionEvent inutile) {
29 | }
30 |
31 | public abstract void handle(MultiChoiceEx parent, T receiver,
32 | boolean selected /* was the check box checked */, Shell popup);
33 | }
--------------------------------------------------------------------------------
/launch.ps1:
--------------------------------------------------------------------------------
1 | [System.Environment]::SetEnvironmentVariable('SKIP_BUILD', 'true', [System.EnvironmentVariableTarget]::User)
2 | ./run.ps1 $args
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 |
--------------------------------------------------------------------------------
/src/main/resources/log4j.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/test/resources/log4j_test.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/main/resources/templates/core_selenium_with_wait_java.twig:
--------------------------------------------------------------------------------
1 | {#
2 | template: Core Selenium with wait / Java
3 | #}
4 | // {{ ElementCodeName }}
5 | {% if (ElementText != '') -%}
6 | // {{ ElementText }}
7 | WebElement element =
8 | {% endif -%}
9 | {% if (ElementSelectedBy == 'ElementText') -%}
10 | wait.until( new ExpectedCondition(){
11 | @Override
12 | public WebElement apply(WebDriver _driver) {
13 | Iterator _elements = _driver
14 | .findElements(
15 | By.XPath("//{{ ElementTagName }}[contains(normalize-space(text()), '{{ ElementText }}')]"))
16 | .iterator();
17 | WebElement result = null;
18 | Pattern pattern = Pattern.compile("^ *" + Pattern.quote("{{ ElementText }}"),
19 | Pattern.CASE_INSENSITIVE);
20 | while (_elements.hasNext()) {
21 | WebElement _element = (WebElement) _elements.next();
22 | Matcher matcher = pattern.matcher(_element.getText);
23 | if (matcher.find()) {
24 | result = _element;
25 | break;
26 | }
27 | }
28 | return result;
29 | }
30 | });
31 | {% else -%}
32 | WebElement element = wait.until(ExpectedConditions.visibilityOf(driver.findElement(
33 | {% if (ElementSelectedBy == 'ElementCssSelector') -%}
34 | By.cssSelector("{{ ElementCssSelector }}")
35 | {% elseif (ElementSelectedBy == 'ElementXPath') -%}
36 | By.Xpath("{{ ElementXPath }}")
37 | {% elseif (ElementSelectedBy == 'ElementId') -%}
38 | By.Id("{{ ElementId }}")
39 | {% endif -%}
40 | )));
41 | {% endif -%}
42 |
--------------------------------------------------------------------------------
/src/main/java/com/github/sergueik/swet/ConfigDataSerializer.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 |
3 | import java.lang.reflect.Type;
4 |
5 | import com.google.gson.JsonElement;
6 | import com.google.gson.JsonObject;
7 | import com.google.gson.JsonPrimitive;
8 | import com.google.gson.JsonSerializationContext;
9 | import com.google.gson.JsonSerializer;
10 |
11 | // https://stackoverflow.com/questions/11038553/serialize-java-object-with-gson
12 | public class ConfigDataSerializer implements JsonSerializer {
13 | @Override
14 | public JsonElement serialize(final ConfigData configData, final Type type,
15 | final JsonSerializationContext context) {
16 | JsonObject result = new JsonObject();
17 | String id = configData.getId();
18 | if (id != null && !id.isEmpty()) {
19 | result.add("id", new JsonPrimitive(id));
20 | }
21 | result.add("browser", new JsonPrimitive(configData.getBrowser()));
22 | result.add("templateName", new JsonPrimitive(configData.getTemplateName()));
23 | String templateDirectory = configData.getTemplateDirectory();
24 | if (templateDirectory != null && !templateDirectory.isEmpty()) {
25 | result.add("templateDirectory", new JsonPrimitive(templateDirectory));
26 | }
27 | String templatePath = configData.getTemplatePath();
28 | if (templatePath != null && !templatePath.isEmpty()) {
29 | result.add("templatePath", new JsonPrimitive(templatePath));
30 | }
31 | /*
32 | Template template = configData.getTemplate();
33 | if (template != null) {
34 | result.add("template", new JsonPrimitive(template.getId()));
35 | }
36 | */
37 | return result;
38 | }
39 | }
--------------------------------------------------------------------------------
/src/main/java/custom/swt/widgets/Container.java:
--------------------------------------------------------------------------------
1 | package custom.swt.widgets;
2 |
3 | import org.eclipse.swt.SWT;
4 | import org.eclipse.swt.SWTException;
5 | import org.eclipse.swt.graphics.Image;
6 | import org.eclipse.swt.graphics.Point;
7 | import org.eclipse.swt.layout.GridData;
8 | import org.eclipse.swt.layout.GridLayout;
9 | import org.eclipse.swt.widgets.Button;
10 | import org.eclipse.swt.widgets.Composite;
11 | import org.eclipse.swt.widgets.Control;
12 | import org.eclipse.swt.widgets.Dialog;
13 | import org.eclipse.swt.widgets.Display;
14 | import org.eclipse.swt.widgets.Event;
15 | import org.eclipse.swt.widgets.Label;
16 | import org.eclipse.swt.widgets.Listener;
17 | import org.eclipse.swt.widgets.ProgressBar;
18 | import org.eclipse.swt.widgets.ScrollBar;
19 | import org.eclipse.swt.widgets.Shell;
20 | import org.eclipse.swt.widgets.Text;
21 | import org.eclipse.swt.graphics.Rectangle;
22 |
23 | import org.eclipse.swt.graphics.Point;
24 | import org.eclipse.swt.widgets.Composite;
25 |
26 | public class Container extends Composite {
27 |
28 | public Container(Composite parent, int style) {
29 | super(parent, style);
30 | /*
31 | setLayout(new LayoutDelegate().layout(this::onLayout)
32 | .computeSize(this::onComputeSize));
33 | */
34 | }
35 |
36 | protected void onLayout(Composite composite, boolean flushCache) {
37 |
38 | }
39 |
40 | protected Point onComputeSize(Composite composite, int wHint, int hHint,
41 | boolean flushCache) {
42 | return new Point(0, 0);
43 | }
44 |
45 | public void dispose() {
46 | if (isDisposed())
47 | return;
48 |
49 | super.dispose();
50 | onDisposed();
51 | }
52 |
53 | protected void onDisposed() {
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/test/java/com/github/sergueik/swet/Log4j2Test.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 | /**
3 | * Copyright 2014 - 2019 Serguei Kouzmine
4 | */
5 |
6 | // for jvm arguments. Must have "-DAPP_LOG_ROOT=c:/temp"
7 | // can also assert if the -Dfile.encoding=UTF-8 argument is passed into surefile plugin properly
8 | import java.lang.management.ManagementFactory;
9 | import java.lang.management.RuntimeMXBean;
10 |
11 | import java.util.List;
12 |
13 | import org.apache.logging.log4j.LogManager;
14 | import org.apache.logging.log4j.Logger;
15 |
16 | import org.junit.After;
17 | import org.junit.AfterClass;
18 | import org.junit.Before;
19 | import org.junit.BeforeClass;
20 | import org.junit.Ignore;
21 | import org.junit.Test;
22 |
23 | /**
24 | * Common utilities for separate patterns, files for Logging info, error and debug to console and file logging for Selenium WebDriver Elementor Tool (SWET)
25 | * @author: Serguei Kouzmine (kouzmine_serguei@yahoo.com)
26 | */
27 |
28 | // based on: https://github.com/hmeclazcke/log4j2-example
29 | public class Log4j2Test {
30 | // This example must run with -DAPP_LOG_ROOT=c:/temp
31 | private static final Logger LOGGER = LogManager
32 | .getLogger(Log4j2Test.class.getName());
33 |
34 | @Test
35 | public void sampleLog4Jtest() {
36 |
37 | // Prints the jvm arguments. Must have "-DAPP_LOG_ROOT=c:/temp" --> location
38 | // of the logs.-
39 | RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
40 | List jvmArgs = runtimeMXBean.getInputArguments();
41 | System.out.println("jvm arguments: " + jvmArgs);
42 |
43 | LOGGER.debug("Debug debugging message");
44 | LOGGER.info("Info information message");
45 | LOGGER.error("Error Message Logged !!!", new Exception("excepition"));
46 |
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/test/java/com/github/sergueik/swet/InstalledBrowsersTest.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 |
3 | import static java.lang.System.err;
4 | import static java.lang.System.out;
5 |
6 | import java.util.HashMap;
7 | import java.util.List;
8 | import java.util.Map;
9 |
10 | import static org.junit.Assert.*;
11 | // [WARNING] No processor claimed any of these annotations: org.junit.AfterClass,org.junit.BeforeClass,org.junit.Ignore,org.junit.After,org.junit.Test,org.junit.Before
12 |
13 | import org.junit.Test;
14 |
15 | import com.github.sergueik.swet.Utils;
16 | import com.github.sergueik.swet.OSUtils;
17 |
18 | public class InstalledBrowsersTest {
19 |
20 | private static Map browserNames = new HashMap<>();
21 | static {
22 | browserNames.put("chrome.exe", "Google Chrome");
23 | browserNames.put("iexplore.exe", "Internet Explorer");
24 | browserNames.put("firefox.exe", "Mozilla Firefox");
25 | }
26 | private static Utils utils = Utils.getInstance();
27 | private static String result = null;
28 | private static final boolean debug = true;
29 |
30 | @Test
31 | public void test() {
32 | utils.setDebug(debug);
33 | List browsers = OSUtils.getInstalledBrowsers();
34 | assertTrue(browsers.size() > 0);
35 | out.println("Your browsers: " + browsers);
36 |
37 | for (String browserName : browserNames.keySet()) {
38 | if (browsers.contains(browserName)) {
39 | assertTrue(OSUtils.isInstalled(browserName));
40 | assertTrue(OSUtils.getMajorVersion(browserName) > 0);
41 | out.println(String.format("%s version: %s",
42 | browserNames.get(browserName), OSUtils.getVersion(browserName)));
43 | } else {
44 | assertFalse(OSUtils.isInstalled(browserName));
45 | assertTrue(OSUtils.getMajorVersion(browserName) == 0);
46 | }
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/src/main/java/com/github/sergueik/swet/BrowserConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 | /**
3 | * Copyright 2014 - 2019 Serguei Kouzmine
4 | */
5 |
6 | import static java.lang.String.format;
7 |
8 | /**
9 | * Browser Configuration Serializer class for Selenium WebDriver Elementor Tool (SWET)
10 | * @author: Serguei Kouzmine (kouzmine_serguei@yahoo.com)
11 | */
12 |
13 | public final class BrowserConfiguration {
14 | public String name;
15 | public String platform;
16 | public String driverPath;
17 | public String driverVersion;
18 | public String version;
19 |
20 | public String getName() {
21 | return name;
22 | }
23 |
24 | public void setName(String data) {
25 | this.name = data;
26 | }
27 |
28 | public String getDriverVersion() {
29 | return driverVersion;
30 | }
31 |
32 | public void setDriverVersion(String data) {
33 | this.driverVersion = data;
34 | }
35 |
36 | public String getVersion() {
37 | return version;
38 | }
39 |
40 | public void setVersion(String data) {
41 | this.version = data;
42 | }
43 |
44 | public String getPlatform() {
45 | return platform;
46 | }
47 |
48 | public void setPlatform(String data) {
49 | this.platform = data;
50 | }
51 |
52 | public String getDriverPath() {
53 | return driverPath;
54 | }
55 |
56 | public void setDriverPath(String data) {
57 | this.driverPath = data;
58 | }
59 |
60 | @Override
61 | public String toString() {
62 | return String.format("Browser '%s' version '%s'%s on '%s'%s", getName(),
63 | getVersion(),
64 | (getDriverVersion() == null) ? ""
65 | : String.format(", driver version '%s'", getDriverVersion()),
66 | getPlatform(),
67 | (getDriverPath() == null) ? ""
68 | : String.format(", with path to driver set to '%s'",
69 | getDriverPath()));
70 | }
71 | }
--------------------------------------------------------------------------------
/src/main/resources/sample.yaml:
--------------------------------------------------------------------------------
1 | !!com.github.sergueik.swet.Configuration
2 | browserConfiguration: null
3 | browsers: null
4 | created: null
5 | elements:
6 | 0b55bdd1-b5df-4558-9bcf-94ef9f216395:
7 | ElementCssSelector: div#hplogo > canvas
8 | ElementSelectedBy: ElementCssSelector
9 | ElementCodeName: logo
10 | Command: AddElement
11 | Caller: addElement
12 | ElementPageURL: https://www.google.com/
13 | ElementTagName: CANVAS
14 | CommandId: 0b55bdd1-b5df-4558-9bcf-94ef9f216395
15 | ElementStepNumber: '0'
16 | ElementText: ''
17 | ElementId: ''
18 | ElementXPath: id("hplogo")/canvas[1]
19 | e0b7030a-0030-4136-a81a-8070a48fa585:
20 | ElementCssSelector: form#tsf > div.tsf-p > div.jsb > center > input
21 | ElementSelectedBy: ElementCssSelector
22 | ElementCodeName: search button
23 | Command: AddElement
24 | Caller: addElement
25 | ElementPageURL: https://www.google.com/
26 | ElementTagName: INPUT
27 | CommandId: e0b7030a-0030-4136-a81a-8070a48fa585
28 | ElementStepNumber: '2'
29 | ElementText: ''
30 | ElementId: ''
31 | ElementXPath: //input[@name="btnK"]
32 | a6d566be-a0fd-4b31-929a-52b370746680:
33 | ElementCssSelector: div#gbw > div > div.gb_kb.gb_Dg.gb_R.gb_Cg.gb_Hg.gb_T > div.gb_je.gb_R.gb_Dg.gb_ug
34 | > div.gb_Q.gb_R > a.gb_P[ href = "https://mail.google.com/mail/?tab=wm" ]
35 | ElementSelectedBy: ElementCssSelector
36 | ElementCodeName: gmail link
37 | Command: AddElement
38 | Caller: addElement
39 | ElementPageURL: https://www.google.com/
40 | ElementTagName: A
41 | CommandId: a6d566be-a0fd-4b31-929a-52b370746680
42 | ElementStepNumber: '1'
43 | ElementText: Gmail
44 | ElementId: ''
45 | ElementXPath: id("gbw")/div[1]/div[1]/div[1]/div[1]/a[ @href = "https://mail.google.com/mail/?tab=wm"
46 | ]
47 | plugins: null
48 | seleniumVersion: null
49 | updated: 2017-12-31T05:00:00Z
50 | version: null
51 |
--------------------------------------------------------------------------------
/run2.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # based on:
4 | # https://www.cyberforum.ru/shell/thread2822786.html
5 |
6 | get_text() {
7 |
8 | TAG=${1:-version}
9 | PROJECT_FILE=${2:-pom.xml}
10 |
11 | if [[ "$DEBUG" = 'true' ]]; then
12 | 1>&2 printf "started get_text() with TAG=%s PROJECT_FILE=%s\n" $TAG $PROJECT_FILE
13 | fi
14 | RESULT=''
15 | PRINTED='false'
16 | IN_PROJECT='false'
17 | IN_DEPENDENCIES='false'
18 | while read LINE;
19 | do
20 | if [[ "$LINE" =~ '' ]]; then
21 | IN_PROJECT='true'
22 | RESULT=''
23 | PRINTED='false'
24 | fi
25 | if [ $(expr match "$LINE" '' ]]; then
29 | IN_PROJECT='false'
30 | fi
31 | # TODO: exclude scanning etc.
32 | if [ $(expr match "$LINE" ' ") != '0' ]; then
39 |
40 | RESULT=$(echo $LINE | sed "s/<\\/\\{0,1\\}${TAG}>//g")
41 | if [[ "$DEBUG" = 'true' ]]; then
42 | 1>&2 printf "Found result:%s\n" $RESULT
43 | fi
44 | # return result immediately
45 | echo $RESULT
46 | return
47 | fi
48 | fi
49 | done <$PROJECT_FILE
50 | }
51 |
52 | PROJECT_FILE=${1:-pom.xml}
53 | if [[ "$DEBUG" = 'true' ]]; then
54 | 1>&2 echo 'Started.'
55 | fi
56 | TAG='version'
57 | APP_VERSION=$(get_text $TAG $PROJECT_FILE)
58 | echo "APP_VERSION=${APP_VERSION}"
59 |
60 | TAG='groupId'
61 | PACKAGE=$(get_text $TAG $PROJECT_FILE)
62 | echo "PACKAGE=${PACKAGE}"
63 |
64 | TAG='artifactId'
65 | APP_NAME=$(get_text $TAG $PROJECT_FILE)
66 | echo "APP_NAME=${APP_NAME}"
67 |
68 | TAG='mainClass'
69 | DEFAULT_MAIN_CLASS=$(get_text $TAG $PROJECT_FILE)
70 | echo "DEFAULT_MAIN_CLASS=${DEFAULT_MAIN_CLASS}"
71 |
72 | if [[ "$DEBUG" = 'true' ]]; then
73 | 1>&2 echo 'Done.'
74 | fi
75 |
--------------------------------------------------------------------------------
/src/main/java/com/github/sergueik/swet/ChoiceDialogEx.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 | /**
3 | * Copyright 2014 - 2019,2021 Serguei Kouzmine
4 | */
5 |
6 | import org.eclipse.swt.SWT;
7 | import org.eclipse.swt.widgets.Display;
8 | import org.eclipse.swt.widgets.Shell;
9 |
10 | import org.passer.ChoiceItem;
11 | import org.passer.ChoicesDialog;
12 |
13 | import org.slf4j.Logger;
14 | import org.slf4j.LoggerFactory;
15 |
16 | import java.io.FileInputStream;
17 | import java.io.IOException;
18 | import java.util.Formatter;
19 | import java.util.Locale;
20 | import java.util.Properties;
21 |
22 | public class ChoiceDialogEx {
23 |
24 | private static Display display;
25 | private static Shell shell;
26 | private static StringBuilder loggingSb = new StringBuilder();
27 | private static Formatter formatter = new Formatter(loggingSb, Locale.US);
28 | private static Utils utils = Utils.getInstance();
29 |
30 | private static final Logger logger = LoggerFactory
31 | .getLogger(ChoiceDialogEx.class);
32 |
33 | @SuppressWarnings("unused")
34 | public static void main(String[] args) {
35 | // Create choices
36 | utils.initializeLogger();
37 | logger.info("Initialized logger.");
38 | display = new Display();
39 | shell = new Shell(display);
40 | ChoiceItem[] items = new ChoiceItem[] {
41 | new ChoiceItem("Exit and save my project",
42 | "Save your work in progress and exit the program"),
43 | new ChoiceItem("Exit and don't save",
44 | "Exit the program without saving your project"),
45 | new ChoiceItem("Don't exit", "Return to the program"), };
46 |
47 | ChoicesDialog dialog = new ChoicesDialog(shell, SWT.APPLICATION_MODAL);
48 |
49 | dialog.setTitle("Exit");
50 | dialog.setMessage("Do you really want to exit?");
51 | dialog.setImage(Display.getCurrent().getSystemImage(SWT.ICON_QUESTION));
52 | dialog.setChoices(items);
53 | dialog.setDefaultChoice(items[2]);
54 | dialog.setShowArrows(false);
55 |
56 | int choice = dialog.open();
57 | logger.info("Choice: " + choice);
58 | if (choice == -1) {
59 | // Choice selected, will be one of {0,1,2}
60 | } else {
61 |
62 | }
63 | }
64 |
65 | }
--------------------------------------------------------------------------------
/src/main/java/com/github/sergueik/swet/BusyIndicatorEx.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 |
3 | /**
4 | * Copyright 2018 Serguei Kouzmine
5 | */
6 |
7 | import static java.lang.String.format;
8 |
9 | import java.util.Date;
10 | import java.util.List;
11 | import java.util.Map;
12 | import org.eclipse.swt.*;
13 | import org.eclipse.swt.custom.*;
14 | import org.eclipse.swt.events.*;
15 | import org.eclipse.swt.layout.*;
16 | import org.eclipse.swt.widgets.*;
17 |
18 | /**
19 | * @author: Serguei Kouzmine (kouzmine_serguei@yahoo.com)
20 | *
21 | */
22 | // Demo of toggle to a Busy Cursor
23 | // during a long running process
24 | // using org.eclipse.swt.custom.BusyIndicator .
25 |
26 | // based on:
27 | // http://www.java2s.com/Code/Java/SWT-JFace-Eclipse/DemonstratesBusyIndicator.htm
28 |
29 | final class BusyIndicatorEx {
30 | private static final int SLEEP_TIME = 3000;
31 |
32 | private void run() {
33 |
34 | Display display = new Display();
35 | Shell shell = new Shell(display);
36 | shell.setText("Busy Indicator Test");
37 | createContents(shell);
38 | shell.pack();
39 | shell.open();
40 | while (!shell.isDisposed()) {
41 | if (!display.readAndDispatch()) {
42 | display.sleep();
43 | }
44 | }
45 | display.dispose();
46 | }
47 |
48 | private void createContents(Shell shell) {
49 | shell.setLayout(new FillLayout());
50 | final Button button = new Button(shell, SWT.PUSH);
51 | button.setText("Press to Start");
52 | button.addSelectionListener(new SelectionAdapter() {
53 | public void widgetSelected(SelectionEvent event) {
54 | button.setText("Running...");
55 | BusyIndicator.showWhile(button.getDisplay(),
56 | new SleepThread(SLEEP_TIME));
57 | button.setText("Press to Start");
58 | }
59 | });
60 | }
61 |
62 | // dummy worker
63 | static private class SleepThread extends Thread {
64 | private long ms;
65 |
66 | public SleepThread(long ms) {
67 | this.ms = ms;
68 | }
69 |
70 | public void run() {
71 | try {
72 | sleep(ms);
73 | } catch (InterruptedException e) {
74 | }
75 | }
76 | }
77 |
78 | public static void main(String[] args) {
79 | new BusyIndicatorEx().run();
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/main/java/com/github/sergueik/swet/PropertiesParser.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 | /**
3 | * Copyright 2014 - 2019 Serguei Kouzmine
4 | */
5 |
6 | import java.io.FileInputStream;
7 | import java.io.FileNotFoundException;
8 | import java.io.IOException;
9 | import java.util.Enumeration;
10 | import java.util.HashMap;
11 | import java.util.Map;
12 | import java.util.Properties;
13 |
14 | /**
15 | * Common configuration / properties file parsers for Selenium WebDriver Elementor Tool (SWET)
16 | * @author: Serguei Kouzmine (kouzmine_serguei@yahoo.com)
17 | */
18 |
19 | public class PropertiesParser {
20 |
21 | /*
22 |
23 | private static String propertiesFileName = "test.properties";
24 | Map propertiesMap = PropertiesParser
25 | .getProperties(String.format("%s/src/main/resources/%s",
26 | System.getProperty("user.dir"), propertiesFileName));
27 | String username = propertiesMap.get("username");
28 | String password = propertiesMap.get("password");
29 | StringBuilder loggingSb = new StringBuilder();
30 | Formatter formatter = new Formatter(loggingSb, Locale.US);
31 | */
32 |
33 | public static Map getProperties(final String fileName) {
34 | Properties p = new Properties();
35 | Map propertiesMap = new HashMap<>();
36 | // System.err.println(String.format("Reading properties file: '%s'",
37 | // fileName));
38 | try {
39 | p.load(new FileInputStream(fileName));
40 | @SuppressWarnings("unchecked")
41 | Enumeration e = (Enumeration) p.propertyNames();
42 | for (; e.hasMoreElements();) {
43 | String key = e.nextElement();
44 | String val = p.get(key).toString();
45 | System.out.println(String.format("Reading: '%s' = '%s'", key, val));
46 | propertiesMap.put(key, Utils.resolveEnvVars(val));
47 | }
48 |
49 | } catch (FileNotFoundException e) {
50 | System.err.println(
51 | String.format("Properties file was not found: '%s'", fileName));
52 | e.printStackTrace();
53 | } catch (IOException e) {
54 | System.err.println(
55 | String.format("Properties file is not readable: '%s'", fileName));
56 | e.printStackTrace();
57 | }
58 | return (propertiesMap);
59 | }
60 | }
--------------------------------------------------------------------------------
/src/main/java/custom/swt/widgets/InfoPopup.java:
--------------------------------------------------------------------------------
1 | package custom.swt.widgets;
2 |
3 | import org.eclipse.swt.SWT;
4 | import org.eclipse.swt.graphics.Color;
5 | import org.eclipse.swt.graphics.Point;
6 | import org.eclipse.swt.layout.GridLayout;
7 | import org.eclipse.swt.widgets.Composite;
8 | import org.eclipse.swt.widgets.Control;
9 | import org.eclipse.swt.widgets.Display;
10 | import org.eclipse.swt.widgets.Label;
11 | import org.eclipse.swt.widgets.Shell;
12 | import custom.swt.widgets.PopupDialog;
13 |
14 |
15 | // origin: https://github.com/cosbi-research/SWTCustomComponents/blob/master/src/custom/swt/widgets/InfoPopup.java
16 | public class InfoPopup extends PopupDialog {
17 |
18 | private static Display display;
19 | private static Shell shell;
20 |
21 | private Composite popupContent;
22 | private Composite parent;
23 | private String content;
24 |
25 | public InfoPopup(Composite parent, String textToBeDisplayed) {
26 | super(parent.getShell(), SWT.ON_TOP, true, false, false, false, false, null,
27 | null);
28 | content = textToBeDisplayed;
29 | }
30 |
31 | @Override
32 | protected Control createDialogArea(Composite parent) {
33 | this.parent = parent;
34 | // parent.setBackground(white);
35 | popupContent = new Composite(parent, SWT.NONE);
36 | // popupContent.setBackground(white);
37 | disposeContent();
38 | updateContent();
39 | return popupContent;
40 | }
41 |
42 | private void disposeContent() {
43 | for (Control child : popupContent.getChildren())
44 | child.dispose();
45 | }
46 |
47 | private void updateContent() {
48 |
49 | GridLayout gridLayout = new GridLayout(1, false);
50 | popupContent.setLayout(gridLayout);
51 |
52 | Label label = new Label(popupContent, SWT.NONE);
53 | label.setText(content);
54 | }
55 |
56 | @Override
57 | protected Color getBackground() {
58 | return parent.getBackground();
59 | }
60 |
61 | @Override
62 | protected void adjustBounds() {
63 | getShell().setBounds(x, y, getShell().getSize().x, getShell().getSize().y);
64 | }
65 |
66 | private int x;
67 | private int y;
68 |
69 | public void setPosition(Point point) {
70 | this.x = point.x;
71 | this.y = point.y;
72 | }
73 |
74 | @Override
75 | public boolean close() {
76 | boolean ret = super.close();
77 | return ret;
78 | }
79 |
80 | }
--------------------------------------------------------------------------------
/src/test/java/com/github/sergueik/swet/Log4jTest.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 | /**
3 | * Copyright 2014 - 2019 Serguei Kouzmine
4 | */
5 |
6 | // NOTE: the org.apache.log4j.Category
7 | // has been deprecated and needs to be replaced by the org.apache.log4jLogger
8 | // NOTE: the latter does not appear to allow different ConversionPattern for STDERR and FILE
9 |
10 | import org.apache.log4j.Logger;
11 |
12 | import org.apache.log4j.PropertyConfigurator;
13 |
14 | import java.util.Formatter;
15 | import java.util.Locale;
16 | import java.util.Properties;
17 | import java.io.FileInputStream;
18 |
19 | import java.io.IOException;
20 |
21 | import org.junit.After;
22 | import org.junit.AfterClass;
23 | import org.junit.Before;
24 | import org.junit.BeforeClass;
25 | import org.junit.Ignore;
26 | import org.junit.Test;
27 |
28 | import com.github.sergueik.swet.Utils;
29 |
30 | // based on: https://alvinalexander.com/blog/post/java/sample-how-format-log4j-logging-logfile-output
31 | public class Log4jTest {
32 | private static StringBuilder loggingSb = new StringBuilder();
33 | private static Formatter formatter = new Formatter(loggingSb, Locale.US);
34 |
35 | @SuppressWarnings("deprecation")
36 | static final Logger logger = (Logger) Logger.getInstance(Log4jTest.class);
37 | private static Utils utils = Utils.getInstance();
38 |
39 | // @Before
40 |
41 | @Test
42 | public void sampleLog4jtest() {
43 | Sample sample = new Sample();
44 | logger.debug("sampleLog4jtest (debug) done.");
45 | logger.info("sampleLog4jtest (info) done.");
46 | }
47 |
48 | private static class Sample {
49 |
50 | private static StringBuilder loggingSb = new StringBuilder();
51 | private static Formatter formatter = new Formatter(loggingSb, Locale.US);
52 |
53 | @SuppressWarnings("deprecation")
54 | static final Logger logger = (Logger) Logger.getInstance(Sample.class);
55 | private static Utils utils = Utils.getInstance();
56 |
57 | public Sample() {
58 | utils.setDebug(true);
59 | // utils.initializeLogger();
60 | utils.initializeLogger(
61 | String.format("%s/%s/%s", System.getProperty("user.dir"),
62 | "src/test/resources", "log4j_test.xml"));
63 | logger.info("Sample constructor (info) done.");
64 | logger.debug("Sample constructor (debug) done.");
65 | }
66 |
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/java/com/github/sergueik/swet/ConfigData.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 |
3 | /**
4 | * Copyright 2018 Serguei Kouzmine
5 | */
6 |
7 | import static java.lang.String.format;
8 |
9 | import java.util.Date;
10 | import java.util.List;
11 | import java.util.Map;
12 |
13 | /**
14 | * @author: Serguei Kouzmine (kouzmine_serguei@yahoo.com)
15 | */
16 |
17 | final class ConfigData {
18 |
19 | private String browser;
20 | private String baseURL;
21 | private String templateName;
22 | private String templateDirectory;
23 | private String templatePath;
24 | private String id;
25 |
26 | private List tests;
27 |
28 | public String getBrowser() {
29 | return browser;
30 | }
31 |
32 | public void setBrowser(String data) {
33 | this.browser = data;
34 | }
35 |
36 | public String getBaseURL() {
37 | return baseURL;
38 | }
39 |
40 | public void setBaseURL(String data) {
41 | this.baseURL = data;
42 | }
43 |
44 | public String getTemplateName() {
45 | return templateName;
46 | }
47 |
48 | public void setTemplateName(String data) {
49 | this.templateName = data;
50 | }
51 |
52 | public String getTemplatePath() {
53 | return templatePath;
54 | }
55 |
56 | public void setTemplatePath(String data) {
57 | this.templatePath = data;
58 | }
59 |
60 | public void setTemplateDirectory(String data) {
61 | this.templateDirectory = data;
62 | }
63 |
64 | public String getTemplateDirectory() {
65 | return templateDirectory;
66 | }
67 |
68 | public String getId() {
69 | return id;
70 | }
71 |
72 | public void setId(String data) {
73 | this.id = data;
74 | }
75 |
76 | public void setTests(List data) {
77 | this.tests = data;
78 | }
79 |
80 | public List getTests() {
81 | return tests;
82 | }
83 |
84 | // https://stackoverflow.com/questions/11038553/serialize-java-object-with-gson
85 | // https://dzone.com/articles/automate-the-planet-10
86 | @Override
87 | public String toString() {
88 | return new StringBuilder().append(format("\"id\": \"%s\"\n", id))
89 | .append(format("\"browser\": \"%s\"\n", browser))
90 | .append(format("\"Template Name\": \"%s\"\n", templateName))
91 | .append(format("\"Template Directory\": \"%s\"\n", templateDirectory))
92 | .append(format("\"Template Path\": \"%s\"\n", templatePath))
93 | .append(format("\"tests\": %s\n", tests.toString())).toString();
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/src/main/java/com/github/sergueik/swet/ListJavaFonts.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 |
3 | import java.awt.Font;
4 | import java.awt.FontMetrics;
5 | import java.awt.Graphics;
6 | import java.awt.GraphicsEnvironment;
7 | import java.awt.image.BufferedImage;
8 | import java.util.ArrayList;
9 | import java.util.Arrays;
10 | import java.util.List;
11 |
12 | /**
13 | * Utilities for Selenium WebDriver Elementor Tool (SWET)
14 | * @author: Serguei Kouzmine (kouzmine_serguei@yahoo.com)
15 | */
16 |
17 | public class ListJavaFonts {
18 |
19 | public static void main(String[] args) {
20 |
21 | List monospaceFontFamilyNames = new ArrayList<>();
22 | GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment
23 | .getLocalGraphicsEnvironment();
24 | String[] fontFamilyNames = graphicsEnvironment
25 | .getAvailableFontFamilyNames();
26 |
27 | BufferedImage bufferedImage = new BufferedImage(1, 1,
28 | BufferedImage.TYPE_INT_ARGB);
29 | Graphics graphics = bufferedImage.createGraphics();
30 |
31 | for (String fontFamilyName : fontFamilyNames) {
32 | boolean isMonospaced = true;
33 | //
34 | int fontStyle = Font.PLAIN;
35 | int fontSize = 12;
36 | Font font = new Font(fontFamilyName, fontStyle, fontSize);
37 | @SuppressWarnings("serial")
38 | List codePoints = new ArrayList() {
39 | {
40 | add(108); /* l */
41 | add(109); /* m */
42 | add(119); /* w */
43 | add(49); /* 1 */
44 | add(52); /* 4 */
45 | }
46 | };
47 | FontMetrics fontMetrics = graphics.getFontMetrics(font);
48 |
49 | int firstCharacterWidth = 0;
50 | boolean hasFirstCharacterWidth = false;
51 | for (int codePoint : codePoints) {
52 | if (Character.isValidCodePoint(codePoint)
53 | && (Character.isLetter(codePoint)
54 | || Character.isDigit(codePoint))) {
55 | char character = (char) codePoint;
56 | int characterWidth = fontMetrics.charWidth(character);
57 | if (hasFirstCharacterWidth) {
58 | if (characterWidth != firstCharacterWidth) {
59 | isMonospaced = false;
60 | break;
61 | }
62 | } else {
63 | firstCharacterWidth = characterWidth;
64 | hasFirstCharacterWidth = true;
65 | }
66 | }
67 | }
68 |
69 | if (isMonospaced) {
70 | monospaceFontFamilyNames.add(fontFamilyName);
71 | }
72 | }
73 |
74 | graphics.dispose();
75 | for (String fontFamily : monospaceFontFamilyNames) {
76 | System.out.println(fontFamily);
77 | }
78 | }
79 | }
--------------------------------------------------------------------------------
/src/main/resources/sampleTest.json:
--------------------------------------------------------------------------------
1 | {
2 | "browser": "Firefox",
3 | "URL": "https://www.amazon.com/",
4 | "testsuite": {
5 | "name": "BuyTheItem",
6 | "testcase": [
7 | {
8 | "name": "OutofStock",
9 | "step": [
10 | {
11 | "name": "selectAttributes",
12 | "action": "Click",
13 | "locateElement": {
14 | "by": "Xpath",
15 | "value": ".//a[@title=\"Echo Dot (2nd Generation) - Black\"]"
16 | },
17 | "thirdPara": "Step comment."
18 | },
19 | {
20 | "name": "addAssertion",
21 | "action": "CheckValue",
22 | "locateElement": {
23 | "by": "id",
24 | "value": "availability"
25 | },
26 | "thirdPara": "In Stock."
27 | }
28 | ]
29 | },
30 | {
31 | "name": "AddtoCart",
32 | "step": [
33 | {
34 | "name": "itemName",
35 | "action": "WriteText",
36 | "locateElement": {
37 | "by": "id",
38 | "value": "twotabsearchtextbox"
39 | },
40 | "thirdPara": "echo dot"
41 | },
42 | {
43 | "name": "searchItem",
44 | "action": "Click",
45 | "locateElement": {
46 | "by": "className",
47 | "value": "nav-input"
48 | }
49 | },
50 | {
51 | "name": "selectAttributes",
52 | "action": "Click",
53 | "locateElement": {
54 | "by": "Xpath",
55 | "value": ".//a[@title=\"Echo Dot (2nd Generation) - White\"]"
56 | }
57 | },
58 | {
59 | "name": "selectQty",
60 | "action": "SelectOption",
61 | "locateElement": {
62 | "by": "Xpath",
63 | "value": ".//select[@id=\"quantity\"]"
64 | },
65 | "thirdPara": "3"
66 | },
67 | {
68 | "name": "buy",
69 | "action": "Click",
70 | "locateElement": {
71 | "by": "Xpath",
72 | "value": ".//*[@title=\"Add to Shopping Cart\"]"
73 | }
74 | },
75 | {
76 | "name": "addAssertion",
77 | "action": "CheckContainsValue",
78 | "locateElement": {
79 | "by": "id",
80 | "value": "availability"
81 | },
82 | "thirdPara": "In Stock."
83 | }
84 | ]
85 | }
86 | ]
87 | }
88 | }
--------------------------------------------------------------------------------
/src/main/java/com/github/sergueik/swet/JavaHotkeyManager.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 |
3 | import java.awt.event.KeyEvent;
4 | import com.sun.jna.Native;
5 | import com.sun.jna.NativeLibrary;
6 | import com.sun.jna.Pointer;
7 | import com.sun.jna.win32.W32APIOptions;
8 |
9 | import java.util.Arrays;
10 | import java.util.List;
11 |
12 | import com.sun.jna.Pointer;
13 | import com.sun.jna.Structure;
14 |
15 | // based on: https://toster.ru/q/636535
16 | public class JavaHotkeyManager extends Thread {
17 | public static void register() {
18 | User32.RegisterHotKey(null, 1, 0x000, KeyEvent.VK_F);
19 | new JavaHotkeyManager().start();
20 | }
21 |
22 | public JavaHotkeyManager() {
23 |
24 | }
25 |
26 | public static void main(String[] args) {
27 | register();
28 | // run();
29 | }
30 |
31 | @Override
32 | public void run() {
33 | JavaHotkeyManager.MSG msg = new JavaHotkeyManager.MSG();
34 | System.err.println("Running " + this.toString());
35 | while (true) {
36 | // register the key on the same thread as listening
37 | User32.RegisterHotKey(null, 1, 0x000, KeyEvent.VK_F);
38 | while (User32.PeekMessage(msg, null, 0, 0, User32.PM_REMOVE)) {
39 | if (msg.message == User32.WM_HOTKEY) {
40 | System.out.println("Hotkey pressed with id: " + msg.wParam);
41 | }
42 | }
43 |
44 | try {
45 | Thread.sleep(300);
46 | } catch (InterruptedException e) {
47 | // TODO Auto-generated catch block
48 | e.printStackTrace();
49 | }
50 | }
51 | }
52 |
53 | private static class User32 {
54 | static {
55 | Native.register(
56 | NativeLibrary.getInstance("user32", W32APIOptions.DEFAULT_OPTIONS));
57 | }
58 |
59 | public static final int MOD_ALT = 0x0001;
60 | public static final int MOD_CONTROL = 0x0002;
61 | public static final int MOD_SHIFT = 0x0004;
62 | public static final int MOD_WIN = 0x0008;
63 | public static final int WM_HOTKEY = 0x0312;
64 | public static final int PM_REMOVE = 0x0001;
65 |
66 | public static native boolean RegisterHotKey(Pointer hWnd, int id,
67 | int fsModifiers, int vk);
68 |
69 | public static native boolean UnregisterHotKey(Pointer hWnd, int id);
70 |
71 | public static native boolean PeekMessage(JavaHotkeyManager.MSG lpMsg,
72 | Pointer hWnd, int wMsgFilterMin, int wMsgFilterMax, int wRemoveMsg);
73 |
74 | }
75 |
76 | public static class MSG extends Structure {
77 | public Pointer hWnd;
78 | public int lParam;
79 | public int message;
80 | public int time;
81 | public int wParam;
82 | public int x;
83 | public int y;
84 |
85 | @Override
86 | protected List getFieldOrder() {
87 | return Arrays.asList(new String[] { "hWnd", "lParam", "message", "time",
88 | "wParam", "x", "y" });
89 | }
90 | }
91 |
92 | }
--------------------------------------------------------------------------------
/src/test/java/com/github/sergueik/swet/SwetImmutableListCopyOfExcerptionTest.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 | /**
3 | * Copyright 2014 - 2019 Serguei Kouzmine
4 | */
5 |
6 | import java.util.concurrent.TimeUnit;
7 |
8 | import org.junit.After;
9 | import org.junit.AfterClass;
10 | import org.junit.Before;
11 | import org.junit.BeforeClass;
12 | import org.junit.Test;
13 | import org.openqa.selenium.Alert;
14 | import org.openqa.selenium.WebDriver;
15 | import org.openqa.selenium.interactions.Actions;
16 | import org.openqa.selenium.support.ui.WebDriverWait;
17 |
18 | // reproduced launch button action
19 | @SuppressWarnings("deprecation")
20 | public class SwetImmutableListCopyOfExcerptionTest {
21 |
22 | private static WebDriver driver;
23 | private static WebDriverWait wait;
24 | private static Actions actions;
25 | private static Alert alert; // unused
26 |
27 | private static String browser = "chrome";
28 | private static final String baseURL = "about:blank";
29 | private static String osName = OSUtils.getOsName();
30 | private Utils utils = Utils.getInstance();
31 |
32 | private static final int flexibleWait = 30;
33 | private static final int implicitWait = 1;
34 | private static final long pollingInterval = 500;
35 |
36 | @BeforeClass
37 | public static void beforeClassMethod() {
38 | // for exception test the browser selection is hard-coded
39 | System.err.println("os: " + osName);
40 | if (osName.equals("windows")) {
41 | browser = "Chrome";
42 | } else if (osName.startsWith("mac")) {
43 | browser = "safari";
44 | } else {
45 | browser = "firefox";
46 | }
47 | System.err.println("browser: " + browser);
48 | driver = BrowserDriver.initialize(browser);
49 | }
50 |
51 | @Before
52 | public void loadBaseURL() {
53 | utils.setDriver(driver);
54 | driver.manage().timeouts().pageLoadTimeout(50, TimeUnit.SECONDS)
55 | .implicitlyWait(implicitWait, TimeUnit.SECONDS)
56 | .setScriptTimeout(30, TimeUnit.SECONDS);
57 | utils.setFlexibleWait(flexibleWait);
58 | wait = new WebDriverWait(driver, flexibleWait);
59 | wait.pollingEvery(pollingInterval, TimeUnit.MILLISECONDS);
60 | actions = new Actions(driver);
61 | utils.setActions(actions);
62 | driver.get(baseURL);
63 | }
64 |
65 | // @Ignore
66 | @Test
67 | public void testWebPageElementSearch() {
68 | driver.get("https://www.codeproject.com/");
69 | }
70 |
71 | @After
72 | public void resetBrowser() {
73 | driver.get("about:blank");
74 | }
75 |
76 | @AfterClass
77 | public static void afterSuiteMethod() {
78 | if (driver != null) {
79 | try {
80 | BrowserDriver.close();
81 | } catch (Exception e) {
82 | // System.err.println("Ignored exception (after suite): " +
83 | // e.toString());
84 | }
85 | }
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/src/main/java/com/github/sergueik/swet/Configuration.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 | /**
3 | * Copyright 2014 - 2018 Serguei Kouzmine
4 | */
5 |
6 | import static java.lang.String.format;
7 |
8 | import java.util.Date;
9 | import java.util.List;
10 | import java.util.Map;
11 |
12 | /**
13 | * Test configuration serializer class for Selenium WebDriver Elementor Tool (SWET)
14 | * @author: Serguei Kouzmine (kouzmine_serguei@yahoo.com)
15 | */
16 |
17 | final class Configuration {
18 | public Date created;
19 | public Date updated;
20 | public String version;
21 | public String seleniumVersion;
22 | public BrowserConfiguration browserConfiguration;
23 | public List browsers;
24 | public Map> elements;
25 | public Map plugins;
26 |
27 | public Date getCreated() {
28 | return created;
29 | }
30 |
31 | public void setCreated(Date data) {
32 | this.created = data;
33 | }
34 |
35 | public Date getUpdated() {
36 | return updated;
37 | }
38 |
39 | public void setUpdated(Date data) {
40 | this.updated = data;
41 | }
42 |
43 | public String getVersion() {
44 | return version;
45 | }
46 |
47 | public void setVersion(String data) {
48 | this.version = data;
49 | }
50 |
51 | public String getSeleniumVersion() {
52 | return seleniumVersion;
53 | }
54 |
55 | public void setSeleniumVersion(String data) {
56 | this.seleniumVersion = data;
57 | }
58 |
59 | public BrowserConfiguration getBrowserConfiguration() {
60 | return browserConfiguration;
61 | }
62 |
63 | public void setBrowserConfiguration(BrowserConfiguration data) {
64 | this.browserConfiguration = data;
65 | }
66 |
67 | public List getBrowsers() {
68 | return browsers;
69 | }
70 |
71 | public void setBrowsers(List data) {
72 | this.browsers = data;
73 | }
74 |
75 | public Map getPlugins() {
76 | return plugins;
77 | }
78 |
79 | public void setPlugins(Map data) {
80 | this.plugins = data;
81 | }
82 |
83 | public Map> getElements() {
84 | return elements;
85 | }
86 |
87 | public void setElements(Map> data) {
88 | this.elements = data;
89 | }
90 |
91 | @Override
92 | public String toString() {
93 | return new StringBuilder().append(format("Version: %s\n", version))
94 | .append(format("Created: %s\n", created))
95 | .append(format("Selenium version: %s\n", seleniumVersion))
96 | .append(format("Supported browsers: %s\n", browsers))
97 | .append(format("Using: %s\n", browserConfiguration))
98 | .append(format("Plugins: %s\n", plugins))
99 | .append(format("Elements: %s\n", elements)).toString();
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/main/java/com/github/sergueik/swet/TestConfigurationParser.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 | /**
3 | * Copyright 2014 - 2019 Serguei Kouzmine
4 | */
5 |
6 | import java.io.File;
7 | import java.io.FileNotFoundException;
8 | import java.util.ArrayList;
9 | import java.util.Arrays;
10 | import java.util.LinkedList;
11 | import java.util.List;
12 | import java.util.Scanner;
13 | import java.util.regex.Pattern;
14 | import java.util.stream.Collectors;
15 |
16 | /**
17 | * Configuration table helper for Selenium WebDriver Elementor Tool (SWET)
18 | * @author: Serguei Kouzmine (kouzmine_serguei@yahoo.com)
19 | */
20 |
21 | public class TestConfigurationParser {
22 |
23 | private static boolean skipHeaders = true;
24 | private static String defaultConfig = "test.configuration";
25 | private static Scanner scanner;
26 |
27 | public static void main(String[] args) {
28 | String configuPath = (args.length == 0)
29 | ? String.format("%s/src/main/resources/%s",
30 | System.getProperty("user.dir"), defaultConfig)
31 | : String.format("%s/%s", System.getProperty("user.dir"), args[0]);
32 | TestConfigurationParser.getConfiguration(configuPath);
33 |
34 | }
35 |
36 | @SuppressWarnings("resource")
37 | public static Scanner loadTestData(final String filename) {
38 | Scanner scanner = null;
39 | System.err
40 | .println(String.format("Reading configuration file: '%s'", filename));
41 | try {
42 | scanner = new Scanner(new File(filename)).useDelimiter("(?:\\r?\\n)+");
43 | } catch (FileNotFoundException e) {
44 | System.err.println(
45 | String.format("Configuration file was not found: '%s'", filename));
46 | e.printStackTrace();
47 | }
48 | return scanner;
49 | }
50 |
51 | public static List getConfiguration(final String filename) {
52 | List result = new LinkedList<>();
53 | scanner = loadTestData(filename);
54 | List separators = new ArrayList(
55 | Arrays.asList(new String[] { "|", "\t", ";", "," }));
56 | String separator = String
57 | .format("(?:%s)",
58 | String.join("|",
59 | separators.stream().map(o -> Pattern.compile("(\\||/)")
60 | .matcher(o).replaceAll("\\\\$1"))
61 | .collect(Collectors.toList())));
62 | int lineNum = 0;
63 | // System.err.println("separator:" + separator);
64 | while (scanner.hasNext()) {
65 | String line = scanner.next();
66 | // System.err.println("line: " + line);
67 | // skip comments
68 | if (line.matches("^#.*$")) {
69 | continue;
70 | }
71 | lineNum++;
72 | // skip headers
73 | if (skipHeaders) {
74 | if (lineNum == 1) {
75 | continue;
76 | }
77 | }
78 |
79 | String[] columns = line.split(separator);
80 | /*
81 | for (String column : columns) {
82 | System.err.println("data column: " + column);
83 | }
84 | */
85 | result.add(columns);
86 | }
87 | scanner.close();
88 | return result;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/main/resources/log4j2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | %d{yyyy-MM-dd'T'HH:mm:ss.SSSZ} %p %m%n
6 | %-5p - %m%n
7 | %-5p %d{yyyy-MM-dd HH:mm:ss} **** %F [%c{1}] - [%M] - %m%n
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 |
--------------------------------------------------------------------------------
/src/test/java/com/github/sergueik/swet/PropertiesTest.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 | /**
3 | * Copyright 2014 - 2019 Serguei Kouzmine
4 | */
5 |
6 | import static org.hamcrest.CoreMatchers.is;
7 | import static org.hamcrest.CoreMatchers.nullValue;
8 | import static org.hamcrest.Matchers.containsInAnyOrder;
9 | // NOTE: need to provide all entries
10 | import static org.hamcrest.Matchers.hasItems;
11 | import static org.hamcrest.CoreMatchers.notNullValue;
12 | import static org.hamcrest.CoreMatchers.containsString;
13 | import static org.hamcrest.Matchers.greaterThan;
14 | import static org.hamcrest.core.AnyOf.anyOf;
15 |
16 | import static org.junit.Assert.assertThat;
17 |
18 | import java.io.InputStream;
19 | import java.util.HashMap;
20 | import java.util.HashSet;
21 | import java.util.Map;
22 | import java.util.regex.Matcher;
23 | import java.util.regex.Pattern;
24 |
25 | import org.apache.commons.io.IOUtils;
26 | import org.junit.Ignore;
27 | import org.junit.Test;
28 |
29 | public class PropertiesTest {
30 |
31 | private static final Utils utils = Utils.getInstance();
32 | private final static String propertiesFileName = "application.properties";
33 | private static String result = null;
34 | private static Map properties = new HashMap<>();
35 | private static Object[] definedProperties = new Object[] { "chromeDriverPath",
36 | "firefoxBrowserPath" };
37 |
38 | @SuppressWarnings("static-access")
39 | @Test
40 | public void readPropertyTest() {
41 | result = utils.readProperty("chromeDriverPath");
42 | // result will be empty:
43 | // `Utils.readProperty` will scan properties file in application
44 | // resource path build relative to target/test-classes
45 | assertThat(result, is(nullValue()));
46 | }
47 |
48 | @Test
49 | public void getResourcePathTest() {
50 | String resourcePath = utils.getResourcePath(propertiesFileName);
51 | properties = PropertiesParser.getProperties(resourcePath);
52 | assertThat(properties, notNullValue());
53 | assertThat(properties.keySet().size(), greaterThan(1));
54 |
55 | assertThat(new HashSet(properties.keySet()),
56 | hasItems(definedProperties));
57 | /*
58 | Expected: (a collection containing "missing property")
59 | but: a collection containing "missing property"
60 | was "password",
61 | was "edgeDriverPath",
62 | was "ieDriverPath",
63 | was "firefoxBrowserPath",
64 | was "chromeDriverPath", was "geckoDriverPath",
65 | was "username"
66 | */
67 | }
68 |
69 | @Test
70 | public void getResourceStreamTest() {
71 | utils.setDebug(true);
72 | result = utils.getScriptContent(propertiesFileName);
73 | assertThat(result, containsString("chromeDriverPath"));
74 | }
75 |
76 | // @Ignore
77 | // https://www.baeldung.com/junit-assert-exception
78 | @Test(expected = NullPointerException.class)
79 | public void failingResourceStreamTest() {
80 | utils.setDebug(true);
81 | result = utils.getScriptContent(
82 | String.format("src/main/resources/%s", propertiesFileName));
83 | assertThat(result, is(nullValue()));
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/test/java/com/github/sergueik/swet/EscapeUtilTest.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 | /**
3 | * Copyright 2014 - 2019 Serguei Kouzmine
4 | */
5 |
6 | import static org.hamcrest.CoreMatchers.equalTo;
7 | import static org.hamcrest.CoreMatchers.is;
8 | import static org.hamcrest.CoreMatchers.notNullValue;
9 | import static org.hamcrest.Matchers.hasEntry;
10 | import static org.hamcrest.Matchers.hasItems;
11 | import static org.junit.Assert.assertFalse;
12 | import static org.junit.Assert.assertThat;
13 | import static org.junit.Assert.assertTrue;
14 |
15 | import java.lang.reflect.InvocationTargetException;
16 | import java.lang.reflect.Method;
17 | import java.util.ArrayList;
18 | import java.util.Arrays;
19 | import java.util.Collections;
20 | import java.util.Date;
21 | import java.util.HashMap;
22 | import java.util.List;
23 | import java.util.Map;
24 | import java.util.Optional;
25 | import java.util.concurrent.TimeUnit;
26 | import java.util.stream.Collectors;
27 |
28 | import org.hamcrest.Matchers;
29 | import org.junit.After;
30 | import org.junit.AfterClass;
31 | import org.junit.Before;
32 | import org.junit.BeforeClass;
33 | import org.junit.Ignore;
34 | import org.junit.Test;
35 | import org.openqa.selenium.Alert;
36 | import org.openqa.selenium.By;
37 | import org.openqa.selenium.WebDriver;
38 | import org.openqa.selenium.WebElement;
39 | import org.openqa.selenium.interactions.Actions;
40 | import org.openqa.selenium.support.ui.ExpectedConditions;
41 | import org.openqa.selenium.support.ui.WebDriverWait;
42 | import org.openqa.selenium.NoSuchElementException;
43 |
44 | import com.github.sergueik.swet.Utils;
45 |
46 | @SuppressWarnings("deprecation")
47 | public class EscapeUtilTest {
48 |
49 | private static String osName = OSUtils.getOsName();
50 | private Utils utils = Utils.getInstance();
51 |
52 | @BeforeClass
53 | public static void beforeClassMethod() {
54 | }
55 |
56 | @Before
57 | public void loadBaseURL() {
58 | utils.setDebug(true);
59 | }
60 |
61 | // @Ignore
62 | @Test
63 | public void testBasicXMLEscape() {
64 | String data = " ";
65 | String escapedData = utils.escape(data);
66 | assertFalse(escapedData.isEmpty());
67 | assertFalse(escapedData.matches("&(?:<|>|\"|');"));
68 | // NOTE: negative lookahead
69 | assertFalse(escapedData.matches("&(?!lt|gt|amp|quot|apos|#x);"));
70 | System.err.println("Validated : " + escapedData);
71 | }
72 |
73 | @Test
74 | public void testCodePointEscape() {
75 | // Create 2 char primitives
76 | char ch1 = '\ud800';
77 | char ch2 = '\udc00';
78 | String data = "" + Character.toString(ch1) + Character.toString(ch2)
79 | + " ";
80 |
81 | // assign code point value of surrogate pair ch1, ch2 to cp
82 | int codePoint = Character.toCodePoint(ch1, ch2);
83 | // Print code point value of surrogate pair ch1, ch2
84 | System.err.println(
85 | String.format("Supplementary code point value is 0x%08X", codePoint));
86 | String escapedData = utils.escape(data);
87 | // NOTE: pad the same way, usual format is the "0x%08X"
88 | assertTrue(escapedData.matches(
89 | String.format("^.*(?:%s).*$", String.format("%05X", codePoint))));
90 | System.err.println("Validated : " + escapedData);
91 | }
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/src/main/java/com/github/sergueik/swet/BatchPipeRun.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.IOException;
5 | import java.io.InputStream;
6 | import java.io.InputStreamReader;
7 | import java.io.OutputStream;
8 | import java.io.PrintWriter;
9 | import java.time.LocalDate;
10 | import java.time.format.DateTimeFormatter;
11 |
12 | /**
13 | * Selected test scenarios for Selenium WebDriver
14 | * @author: Serguei Kouzmine (kouzmine_serguei@yahoo.com)
15 | */
16 |
17 | // based on:
18 | // https://qna.habr.com/q/704745
19 |
20 | public class BatchPipeRun {
21 |
22 | public static void main(String[] args)
23 | throws IOException, InterruptedException {
24 | LocalDate futureDate = LocalDate.now().plusMonths(12);
25 | String formattedDate = futureDate
26 | .format(DateTimeFormatter.ofPattern("yyyyMMdd"));
27 | String serialNumber = "foo";
28 | String keyName = "bar";
29 | String command = "c:\\Users\\Serguei\\echoargs.cmd " + serialNumber + " "
30 | + keyName + " " + formattedDate + " 2>&1";
31 | System.err.println("Exit code:" + runWithPipes(command));
32 | }
33 |
34 | public static String runWithPipes(String command)
35 | throws IOException, InterruptedException {
36 | String[] shell = { "cmd.exe", };
37 | Process process = Runtime.getRuntime().exec(shell);
38 | // this code allows seeing the child process on the console
39 | new Thread(new SyncPipe(process.getErrorStream(), System.err)).start();
40 | new Thread(new SyncPipe(process.getInputStream(), System.out)).start();
41 |
42 | PrintWriter stdinPrintWriter = new PrintWriter(process.getOutputStream());
43 | stdinPrintWriter.println(command);
44 | stdinPrintWriter.close();
45 |
46 | BufferedReader stdoutBufferedReader = new BufferedReader(
47 | new InputStreamReader(process.getInputStream()));
48 |
49 | BufferedReader stderrBufferedReader = new BufferedReader(
50 | new InputStreamReader(process.getErrorStream()));
51 | String line = null;
52 |
53 | StringBuffer processOutput = new StringBuffer();
54 | while ((line = stdoutBufferedReader.readLine()) != null) {
55 | processOutput.append(line);
56 | // add a platform-independent newline
57 | processOutput.append(System.getProperty("line.separator"));
58 | }
59 | StringBuffer processError = new StringBuffer();
60 | while ((line = stderrBufferedReader.readLine()) != null) {
61 | processError.append(line);
62 | processError.append(String.format("%n"));
63 | }
64 | System.err.println("OUTPUT:" + processOutput.toString());
65 | System.err.println("ERROR :" + processError.toString());
66 | String exitCode = Integer.toString(process.waitFor());
67 | return exitCode;
68 | }
69 |
70 | private static class SyncPipe implements Runnable {
71 | private final OutputStream outputStream;
72 | private final InputStream intputStream;
73 |
74 | public SyncPipe(InputStream intputStream, OutputStream outputStream) {
75 | this.intputStream = intputStream;
76 | this.outputStream = outputStream;
77 |
78 | }
79 |
80 | public void run() {
81 | try {
82 | final byte[] buffer = new byte[1024];
83 | for (int length = 0; (length = this.intputStream.read(buffer)) != -1;) {
84 | this.outputStream.write(buffer, 0, length);
85 | }
86 | } catch (IOException e) {
87 | e.printStackTrace();
88 | }
89 | }
90 | }
91 | }
--------------------------------------------------------------------------------
/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # set -x
3 |
4 | which xmllint > /dev/null
5 |
6 | if [ $? -ne 0 ] ; then
7 | echo 'Missing xmllint'
8 | # use bash scripting to extract project attributes
9 | # see run2.sh for the implemtnation.
10 | # NOTE: very slow
11 | exit 1
12 | fi
13 |
14 | echo 'Loading parameters from the project "pom.xml"'
15 |
16 | if [ -z "${APP_VERSION}" ]
17 | then
18 | APP_VERSION=$(xmllint -xpath "/*[local-name() = 'project' ]/*[local-name() = 'version' ]/text()" pom.xml)
19 | else
20 | echo "Using provided APP_VERSION=${APP_VERSION}"
21 | fi
22 | if [ -z "${PACKAGE}" ]
23 | then
24 | PACKAGE=$(xmllint -xpath "/*[local-name() = 'project' ]/*[local-name() = 'groupId' ]/text()" pom.xml)
25 | fi
26 | if [ -z "${APP_NAME}" ]
27 | then
28 | APP_NAME=$(xmllint -xpath "/*[local-name() = 'project' ]/*[local-name() = 'artifactId' ]/text()" pom.xml)
29 | fi
30 | if [ -z "${DEFAULT_MAIN_CLASS}" ]
31 | then
32 | DEFAULT_MAIN_CLASS=$(xmllint -xpath "/*[local-name() = 'project' ]/*[local-name() = 'properties' ]/*[local-name() = 'mainClass']/text()" pom.xml)
33 | fi
34 | MAIN_CLASS=${1:-$DEFAULT_MAIN_CLASS}
35 |
36 | if [ -z "${SCM_CONNECTION}" ]
37 | then
38 | SCM_CONNECTION=$(xmllint -xpath "/*[local-name() = 'project' ]/*[local-name()='scm']/*[local-name() = 'connection']/text()" pom.xml | sed 's|scm:git://||')
39 | fi
40 |
41 | DOWNLOAD_EXTERNAL_JAR=false
42 |
43 | if [[ $DOWNLOAD_EXTERNAL_JAR ]]
44 | then
45 | ALIAS='opal'
46 | JARFILE_VERSION='1.0.4'
47 | JARFILE="$ALIAS-$JARFILE_VERSION.jar"
48 | URL="https://github.com/lcaron/${ALIAS}/blob/releases/V$JARFILE_VERSION/${ALIAS}-$JARFILE_VERSION.jar?raw=true"
49 | if [[ ! -f "src/main/resources/$JARFILE" ]]
50 | then
51 | pushd 'src/main/resources/'
52 | wget -O $JARFILE -nv $URL
53 | popd
54 | # https://ftp.mozilla.org/pub/firefox/releases/40.0.3/mac/en-US/
55 | fi
56 | fi
57 |
58 | if $(uname -s | grep -qi 'Darwin')
59 | then
60 |
61 | # OSX-specific
62 | # https://www.java.com/en/download/help/version_manual.xml
63 | JAVA_VERSION=$('/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java' -version 2>& 1| sed -n 's|^.*"\(.*\)\".*$|\1|p')
64 | if [ -z $JAVA_VERSION} ]; then
65 | JAVA_VERSION='1.8.0_121'
66 | fi
67 | export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk$JAVA_VERSION.jdk/Contents/Home
68 |
69 | # NOTE: No uniform way to query OSX for the installed maven version
70 | # If Maven is installed to 'Applications' need to adjust the command line to: "mdfind -onlyin '/Applications' -name mvn"
71 | M2=$(mdfind -onlyin "${HOME}/Downloads" -name mvn | sed -n 's|^\(.*\)/mvn$|\1|p'|head -1)
72 |
73 | if [ -z $M2 ] ; then
74 | MAVEN_VERSION='3.6.1'
75 | export M2_HOME="$HOME/Downloads/apache-maven-$MAVEN_VERSION"
76 | export M2="$M2_HOME/bin"
77 | else
78 | export M2
79 | export M2_HOME=$(echo $M2| sed 's|/bin||')
80 | fi
81 | export MAVEN_OPTS='-Xms256m -Xmx512m'
82 | export PATH=$M2_HOME/bin:$PATH
83 | # http://stackoverflow.com/questions/3976342/running-swt-based-cross-platform-jar-properly-on-a-mac
84 | LAUNCH_OPTS='-XstartOnFirstThread'
85 | fi
86 | if [[ $SKIP_BUILD != 'true' ]] ; then
87 | mvn -Dmaven.test.skip=true package install
88 | fi
89 | echo "java $LAUNCH_OPTS -cp target/$APP_NAME-$APP_VERSION.jar:target/lib/* $PACKAGE.$MAIN_CLASS" $*
90 | java $LAUNCH_OPTS -cp target/$APP_NAME-$APP_VERSION.jar:target/lib/* $PACKAGE.$MAIN_CLASS $*
91 |
--------------------------------------------------------------------------------
/src/test/java/com/github/sergueik/swet/WriteScriptFileTest.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 | /**
3 | * Copyright 2014 - 2019 Serguei Kouzmine
4 | */
5 |
6 | import java.io.File;
7 | import java.io.FileNotFoundException;
8 | import java.io.FileReader;
9 |
10 | import org.junit.AfterClass;
11 | import org.junit.BeforeClass;
12 | import org.junit.Test;
13 |
14 | import com.google.gson.Gson;
15 |
16 | import com.github.sergueik.swet.WriteScriptFile;
17 | import com.github.sergueik.swet.Utils;
18 | import com.github.sergueik.swet.OSUtils;
19 |
20 | public class WriteScriptFileTest {
21 |
22 | private static String scriptsPath;
23 | private static Gson gson;
24 | private static String resourcePath;
25 | private static Utils utils = Utils.getInstance();
26 |
27 | @BeforeClass
28 | public static void Setup() {
29 | resourcePath = utils.getResourcePath("sampleTest.json");
30 | gson = new Gson();
31 | scriptsPath = System.getProperty("user.dir") + File.separator + "scripts";
32 | File scriptsDirectory = new File(scriptsPath);
33 | if (!scriptsDirectory.exists()) {
34 | if (scriptsDirectory.mkdir()) {
35 | } else {
36 | System.out.println("Failed to create directory: " + scriptsPath);
37 | }
38 | }
39 | }
40 |
41 | // cleanup generated test sources
42 | // TODO: error detection
43 | @AfterClass
44 | public static void Cleanup() {
45 | /*
46 | try {
47 | FileUtils.deleteDirectory(new File(scriptsPath));
48 | } catch (IOException e) {
49 | }
50 | */
51 | }
52 |
53 | @Test
54 | public void writeTestScript() throws FileNotFoundException {
55 | // Warning: places generated sources into the working girectory
56 | WriteScriptFile writeScriptFile = new WriteScriptFile(resourcePath);
57 | writeScriptFile.generateTestScripts(scriptsPath);
58 | }
59 |
60 | @Test
61 | public void dumplJSon() throws FileNotFoundException {
62 | WriteScriptFile.AI_Parser parser = new WriteScriptFile.AI_Parser(
63 | resourcePath);
64 | parser.printTestSuiteDetails();
65 | }
66 |
67 | @Test
68 | public void dumpRawJSon() throws FileNotFoundException {
69 |
70 | WriteScriptFile.TestParamsDTO params = gson.fromJson(
71 | new FileReader(resourcePath), WriteScriptFile.TestParamsDTO.class);
72 |
73 | System.out.println(params.getBrowser());
74 | System.out.println(params.getURL());
75 | System.out.println(params.getTestsuite().getName());
76 | System.out.println(
77 | "Number of testcases: " + params.getTestsuite().getTestcase().length);
78 | System.out.println(params.getTestsuite().getTestcase()[0].getName());
79 | System.out.println("Number of test steps of testcase 1: "
80 | + params.getTestsuite().getTestcase()[0].getStep().length);
81 | System.out.println(String.format("Step 1 name: \"%s\"",
82 | params.getTestsuite().getTestcase()[0].getStep()[0].getName()));
83 | System.out.println(String.format("Step 1 action: \"%s\"",
84 | params.getTestsuite().getTestcase()[0].getStep()[0].getAction()));
85 | System.out
86 | .println(String.format("Step 1 locateElement selector type : \"%s\"",
87 | params.getTestsuite().getTestcase()[0].getStep()[0]
88 | .getLocateElement().getBy()));
89 | System.out
90 | .println(String.format("Step 1 locateElement selector value: \"%s\"",
91 | params.getTestsuite().getTestcase()[0].getStep()[0]
92 | .getLocateElement().getValue()));
93 | System.out.println(String.format("Step 1 extra param: \"%s\"",
94 | params.getTestsuite().getTestcase()[0].getStep()[0].getThirdPara()));
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/main/java/custom/swt/widgets/ImageLabel.java:
--------------------------------------------------------------------------------
1 | package custom.swt.widgets;
2 |
3 | import org.eclipse.swt.SWT;
4 | import org.eclipse.swt.graphics.Image;
5 | import org.eclipse.swt.graphics.Point;
6 | import org.eclipse.swt.graphics.Rectangle;
7 | import org.eclipse.swt.widgets.Composite;
8 | import org.eclipse.swt.widgets.Label;
9 |
10 | public class ImageLabel extends Container {
11 |
12 | static final int hgap = 16;
13 |
14 | // no need since the label's.getImage() retrieves the image
15 | // private Image image;
16 | public final Label image;
17 | public final Label text;
18 | private int alignment = SWT.TOP;
19 |
20 | // ==[ Constructor
21 | // ]=================================================================================
22 |
23 | public ImageLabel(Composite parent, int style) {
24 | super(parent, style);
25 |
26 | // Children
27 | image = new Label(this, SWT.NONE);
28 | text = new Label(this, SWT.WRAP);
29 |
30 | }
31 |
32 | // ==[ Layout
33 | // ]======================================================================================
34 |
35 | @Override
36 | protected Point onComputeSize(Composite composite, int wHint, int hHint,
37 | boolean flushCache) {
38 | // System.out.println("imageLabel.computeSize(" + wHint + "," + hHint +
39 | // ")");
40 | Point imgPrefSize = image.computeSize(SWT.DEFAULT, SWT.DEFAULT);
41 | // System.out.println("\tImage Width: " + imgPrefSize.x);
42 |
43 | if (wHint != SWT.DEFAULT)
44 | wHint = Math.max(0, wHint - imgPrefSize.x - hgap);
45 |
46 | // System.out.println("\tReduced wHint: " + wHint);
47 |
48 | Point textPrefSize = text.computeSize(wHint, hHint);
49 |
50 | // System.out.println("\tImage Height: " + imgPrefSize.y);
51 | // System.out.println("\tText Height: " + textPrefSize.y);
52 |
53 | int height = Math.max(imgPrefSize.y, textPrefSize.y);
54 | int width = imgPrefSize.x + hgap + textPrefSize.x;
55 |
56 | // System.out.println("\t-> Result: " + width + "," + height);
57 |
58 | return new Point(width, height);
59 | }
60 |
61 | @Override
62 | protected void onLayout(Composite composite, boolean flushCache) {
63 |
64 | Rectangle bounds = composite.getBounds();
65 |
66 | Point imgPrefSize = image.computeSize(SWT.DEFAULT, bounds.height);
67 | Point textPrefSize = text.computeSize(bounds.width - imgPrefSize.x,
68 | SWT.DEFAULT);
69 |
70 | int y = 0;
71 | if (alignment == SWT.CENTER)
72 | y = (bounds.height - textPrefSize.y) / 2;
73 | else if (alignment == SWT.BOTTOM)
74 | y = bounds.height - textPrefSize.y;
75 |
76 | image.setBounds(0, 0, imgPrefSize.x, imgPrefSize.y);
77 | text.setBounds(imgPrefSize.x + hgap, y, textPrefSize.x, textPrefSize.y);
78 |
79 | }
80 |
81 | // ==[ Getter & Setter
82 | // ]=============================================================================
83 |
84 | // public Label getImageLabel() {
85 | // return image;
86 | // }
87 | //
88 | // public Label getTextLabel() {
89 | // return text;
90 | // }
91 |
92 | public void setImage(Image newImage) {
93 | checkWidget();
94 | // image = newImage;
95 | image.setImage(newImage);
96 | }
97 |
98 | public void setText(String content) {
99 | checkWidget();
100 | text.setText(content);
101 | }
102 |
103 | public void setVerticalAlignment(int alignment) {
104 | checkWidget();
105 | if (alignment != SWT.TOP && alignment != SWT.CENTER
106 | && alignment != SWT.BOTTOM)
107 | SWT.error(SWT.ERROR_INVALID_ARGUMENT);
108 | this.alignment = alignment;
109 | // TODO: locate and clone implementing class
110 | // requestLayout();
111 | }
112 |
113 | }
--------------------------------------------------------------------------------
/src/test/java/com/github/sergueik/swet/BrowserDiscoveryTest.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 | /**
3 | * Copyright 2014 - 2018 Serguei Kouzmine
4 | */
5 |
6 | import static org.junit.Assert.assertFalse;
7 | import static org.junit.Assert.assertTrue;
8 |
9 | import java.io.IOException;
10 | import java.util.ArrayList;
11 | import java.util.Arrays;
12 | import java.util.HashMap;
13 | import java.util.List;
14 | import java.util.Map;
15 |
16 | import org.junit.Test;
17 |
18 | import com.github.sergueik.swet.OSUtils;
19 | import com.google.common.collect.Lists;
20 |
21 | public class BrowserDiscoveryTest {
22 |
23 | private static String osName = OSUtils.getOsName();
24 | private static Map browserNames = new HashMap<>();
25 | static {
26 | switch (osName) {
27 | case "windows":
28 | browserNames.put("chrome.exe", "Google Chrome");
29 | browserNames.put("edge.exe", "Edge");
30 | browserNames.put("iexplore.exe", "Internet Explorer");
31 | browserNames.put("firefox.exe", "Mozilla Firefox");
32 | browserNames.put("safari", "Safari");
33 | break;
34 | case "linux":
35 | browserNames.put("google-chrome", "Google Chrome");
36 | browserNames.put("firefox", "Mozilla Firefox");
37 | // browserNames.put("chrome", "Google Chrome (wrong proces name)");
38 | break;
39 | case "mac os x":
40 | browserNames.put("Google Chrome", "Google Chrome");
41 | browserNames.put("Mozilla Firefox", "Mozilla Firefox");
42 | browserNames.put("Safari", "Safari");
43 | break;
44 | }
45 | }
46 |
47 | @Test
48 | public void testInstalledBrowserInformaation() {
49 | if (osName.equals("windows")) {
50 | List browsers = OSUtils.getInstalledBrowsers();
51 | assertTrue(browsers.size() > 0);
52 | // System.err.println("Installed browsers: " + browsers);
53 |
54 | for (String browserName : browserNames.keySet()) {
55 | if (browsers.contains(browserName)) {
56 | assertTrue(OSUtils.isInstalled(browserName));
57 | assertTrue(OSUtils.getMajorVersion(browserName) > 0);
58 | System.err.println(String.format("%s version: %s", browserNames.get(browserName),
59 | OSUtils.getVersion(browserName)));
60 | } else {
61 | assertFalse(OSUtils.isInstalled(browserName));
62 | assertTrue(OSUtils.getMajorVersion(browserName) == 0);
63 | }
64 | }
65 | }
66 | if (osName.equals("mac os x")) {
67 | List browsers = new ArrayList(browserNames.keySet());
68 | for (String browserName : browsers) {
69 | if ( !OSUtils.findAppInPath(browserName) ) {
70 | System.err.println(
71 | String.format("Broser not installed: %s", browserName));
72 | } else {
73 | System.err.println("Found browser: " + browserNames.get(browserName));
74 |
75 | }
76 | }
77 | }
78 | if (osName.equals("linux")) {
79 | List browsers = new ArrayList(browserNames.keySet());
80 | for (String browserName : browsers) {
81 | String command = "/usr/bin/which " + browserName;
82 | Runtime runtime = Runtime.getRuntime();
83 | Process process;
84 | try {
85 | process = runtime.exec(command);
86 | int exitCode = process.waitFor();
87 | if (exitCode != 0) {
88 | System.err.println(
89 | String.format("Process exit code: %d for browser process %s", exitCode, browserName));
90 | } else {
91 | System.err.println("Found browser: " + browserNames.get(browserName));
92 |
93 | }
94 | } catch (IOException | InterruptedException e) {
95 | System.err.println("Exception (ignnord): " + e.getMessage());
96 | }
97 | }
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/main/java/custom/swt/widgets/MultilineButton.java:
--------------------------------------------------------------------------------
1 | package custom.swt.widgets;
2 |
3 | import org.eclipse.jface.resource.FontDescriptor;
4 | import org.eclipse.jface.resource.ResourceManager;
5 | import org.eclipse.swt.SWT;
6 | import org.eclipse.swt.events.SelectionEvent;
7 | import org.eclipse.swt.events.SelectionListener;
8 | import org.eclipse.swt.graphics.GC;
9 | import org.eclipse.swt.graphics.Point;
10 | import org.eclipse.swt.layout.FillLayout;
11 | import org.eclipse.swt.layout.GridData;
12 | import org.eclipse.swt.widgets.Button;
13 | import org.eclipse.swt.widgets.Composite;
14 | import org.eclipse.swt.widgets.Display;
15 | import org.eclipse.swt.widgets.Shell;
16 | import org.eclipse.swt.graphics.Color;
17 | import org.eclipse.swt.graphics.Font;
18 | import org.eclipse.swt.graphics.FontData;
19 | import org.eclipse.swt.graphics.TextLayout;
20 | import org.eclipse.swt.graphics.TextStyle;
21 |
22 | // origin: https://raw.githubusercontent.com/dfuchss/swt-utils/master/src/main/java/org/fuchss/swt/widgets/MultilineButton.java
23 | public class MultilineButton extends Button {
24 |
25 | public MultilineButton(Composite parent, int style) {
26 | super(parent, style | SWT.WRAP | SWT.PUSH | SWT.LEFT);
27 | // wrong layout class
28 | // this.setLayoutData(
29 | // new GridData(SWT.WRAP | SWT.PUSH | SWT.LEFT, SWT.LEFT, true, false));
30 | }
31 |
32 | // Disable the check that prevents subclassing of SWT components
33 | @Override
34 | protected final void checkSubclass() {
35 | }
36 |
37 | @Override
38 | public Point computeSize(int wHint, int hHint, boolean changed) {
39 | Point size = super.computeSize(wHint, hHint, changed);
40 | GC gc = new GC(this);
41 |
42 | String text = this.getText();
43 | Point mlSize = gc.textExtent(text, SWT.DRAW_DELIMITER | SWT.LEFT);
44 | Point simpleSize = gc.textExtent(text.replace('\n', ' '));
45 |
46 | gc.dispose();
47 |
48 | size.x -= simpleSize.x - mlSize.x;
49 | size.y += mlSize.y - simpleSize.y;
50 |
51 | return size;
52 | }
53 |
54 | // origin:
55 | // https://www.programcreek.com/java-api-examples/org.eclipse.swt.graphics.Font
56 | private Font createFont(final ResourceManager resourceManager) {
57 | final Font defaultFont = resourceManager.getDevice().getSystemFont();
58 |
59 | if (defaultFont == null) {
60 | return null;
61 | }
62 |
63 | final FontData fd[] = FontDescriptor.copy(defaultFont.getFontData());
64 | if (fd == null) {
65 | return null;
66 | }
67 |
68 | for (final FontData f : fd) {
69 | if (this.fontSize > 0) {
70 | f.setHeight(this.fontSize);
71 | }
72 | }
73 | return resourceManager.createFont(FontDescriptor.createFrom(fd));
74 | }
75 |
76 | private final static int fontSize = 9;
77 |
78 | // testing the widget
79 |
80 | private static Shell shell;
81 | static Display display = new Display();
82 |
83 | private final static int formWidth = 250;
84 | private final static int formHeight = 120;
85 |
86 | public static void main(String[] args) {
87 | shell = new Shell(display);
88 | shell.setLayout(new FillLayout());
89 |
90 | final MultilineButton button = new MultilineButton(shell, SWT.PUSH); // NONE?
91 | // TODO: display.getSystemFont()
92 | Font font = new Font(display, "Helvetica", 9, SWT.NORMAL);
93 | // https://www.programcreek.com/java-api-examples/?class=org.eclipse.swt.SWT&method=LEFT
94 | button.setFont(font);
95 | button.addSelectionListener(new SelectionListener() {
96 | // required
97 | public void widgetDefaultSelected(SelectionEvent e) {
98 | }
99 |
100 | // required
101 | public void widgetSelected(SelectionEvent e) {
102 | // TODO: close Shell
103 | shell.dispose();
104 | }
105 | });
106 | button.setText("start\ncontinue\nmore action\nfinishing\nfinished");
107 | shell.pack();
108 | shell.setSize(formWidth, formHeight);
109 |
110 | shell.open();
111 | while (!shell.isDisposed()) { // Event loop.
112 | if (!display.readAndDispatch())
113 | display.sleep();
114 | }
115 | display.dispose();
116 | }
117 | }
--------------------------------------------------------------------------------
/src/test/java/com/github/sergueik/swet/TestConfigurationParserTest.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 | /**
3 | * Copyright 2014 - 2019 Serguei Kouzmine
4 | */
5 |
6 | import java.lang.reflect.Array;
7 | import java.util.ArrayList;
8 | import java.util.Arrays;
9 | import java.util.HashSet;
10 | import java.util.List;
11 | import java.util.Set;
12 |
13 | import static org.junit.Assert.*;
14 | // import static org.hamcrest.CoreMatchers.*;
15 | // NOTE: a need to switch to hamcrest-all.jar and Matchers
16 | // just for resolving method 'containsInAnyOrder'
17 | import static org.hamcrest.Matchers.*;
18 |
19 | import static org.junit.Assert.assertThat;
20 | import static org.hamcrest.core.AnyOf.anyOf;
21 | import static org.hamcrest.CoreMatchers.is;
22 | import static org.hamcrest.CoreMatchers.containsString;
23 |
24 | import org.junit.After;
25 | import org.junit.AfterClass;
26 | import org.junit.Before;
27 | import org.junit.BeforeClass;
28 | import org.junit.Ignore;
29 | import org.junit.Test;
30 |
31 | import com.github.sergueik.swet.TestConfigurationParser;
32 |
33 | public class TestConfigurationParserTest {
34 | /**
35 | * Testing of the Selenium WebDriver Elementor Tool (SWET) Configuration table helper
36 | * @author: Serguei Kouzmine (kouzmine_serguei@yahoo.com)
37 | */
38 |
39 | private static boolean skipHeaders = true;
40 | private static String defaultConfig = "test.configuration";
41 | private static String configuPath = String.format("%s/src/main/resources/%s",
42 | System.getProperty("user.dir"), defaultConfig);
43 | private static List result = new ArrayList<>();
44 | private static Object[] expected = new Object[] { "A1", "A2", "A3", "B1",
45 | "B2", "B3", "C1", "C2", "C3", "D1", "D2", "D3" /* , "E1" */ };
46 |
47 | @BeforeClass
48 | public static void beforeSuiteMethod() throws Exception {
49 | result = flatten(TestConfigurationParser.getConfiguration(configuPath));
50 | }
51 |
52 | // @Ignore
53 | @Test
54 | public void junitBuiltIArrayTest() {
55 | assertArrayEquals(expected, result.toArray());
56 | }
57 |
58 | // @Ignore
59 | @Test
60 | public void orderInsensitiveTest() {
61 | // NOTE: would fail
62 | Set dataSet = new HashSet(Arrays.asList(expected));
63 | assertTrue(new HashSet(result).containsAll(dataSet));
64 | }
65 |
66 | // @Ignore
67 | @Test
68 | public void orderSensitiveTest() {
69 | // order-sensitive
70 | assertThat(result.toArray(), is(expected));
71 | }
72 |
73 | @Test
74 | public void iterateAnyOfTest() {
75 | // origin: https://github.com/junit-team/junit4/blob/master/src/test/java/org/junit/experimental/categories/CategoryTest.java
76 | // see also: https://www.programcreek.com/java-api-examples/index.php?api=org.hamcrest.core.AnyOf
77 | for (Object resultItem : result) {
78 | // this expectation tailored to small sets
79 | // http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/core/AnyOf.html
80 | // will be failing with
81 | // Expected: (is "A1" or is "A2" or is "A3" or is "B1" or is "B2" or is
82 | // "B3")
83 | // but: was "C1"
84 | assertThat(resultItem, anyOf(is(expected[0]), is(expected[1]),
85 | is(expected[2]), is(expected[3]), is(expected[4]), is(expected[5])));
86 | }
87 | }
88 |
89 | // https://www.javaworld.com/article/2074689/core-java/hamcrest-containing-matchers.html
90 | // @Ignore
91 | @Test
92 | public void hasItemsTest() {
93 | assertThat(new HashSet(result), hasItems(expected));
94 | }
95 |
96 | // @Ignore
97 | // https://www.javaworld.com/article/2074689/core-java/hamcrest-containing-matchers.html
98 | @Test
99 | public void containsInAnyOrderTest() {
100 | assertThat(new HashSet(result), containsInAnyOrder(expected));
101 | }
102 |
103 | // https://stackoverflow.com/questions/40186270/java-flatten-an-array-using-recursion
104 | private static List flatten(Object input) {
105 | List result = new ArrayList();
106 | if (input.getClass().isArray()) {
107 | for (int pos = 0; pos < Array.getLength(input); pos++) {
108 | result.addAll(flatten(Array.get(input, pos)));
109 | }
110 | } else if (input instanceof List) {
111 | for (Object element : (List>) input) {
112 | result.addAll(flatten(element));
113 | }
114 | } else {
115 | result.add(input);
116 | }
117 | return result;
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/src/test/java/com/github/sergueik/swet/AWTTest.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 |
3 | import java.awt.AWTException;
4 | import java.awt.Robot;
5 | import java.awt.event.KeyEvent;
6 | import java.io.*;
7 | import java.util.ArrayList;
8 | import java.util.Arrays;
9 | import java.util.HashMap;
10 | import java.util.List;
11 |
12 | import org.junit.After;
13 | import org.junit.BeforeClass;
14 | import org.junit.Ignore;
15 | import org.junit.Test;
16 |
17 | public class AWTTest {
18 |
19 | private final static String command = "notepad.exe";
20 | // Create an instance of Robot class
21 | private final static Runtime runtime = Runtime.getRuntime();
22 | private static Robot robot = null;
23 | private static final int delay2 = 30;
24 | private static final int delay = 100;
25 | private static final int launchDelay = 5000;
26 | // low-level event is generated by a component object (
27 | private static int[] rawKeys = { KeyEvent.VK_H, KeyEvent.VK_E, KeyEvent.VK_L,
28 | KeyEvent.VK_L, KeyEvent.VK_O, KeyEvent.VK_SPACE, };
29 |
30 | @BeforeClass
31 | public static void load() throws IOException {
32 | runtime.exec(command);
33 | sleep(launchDelay);
34 | try {
35 | robot = new Robot();
36 | } catch (AWTException e) {
37 | // TODO Auto-generated catch block
38 | e.printStackTrace();
39 | }
40 | }
41 |
42 | @After
43 | public void writeNewLine() {
44 | robot.keyPress(KeyEvent.VK_ENTER);
45 | }
46 |
47 | @Ignore
48 | @Test
49 | public void basicTest() throws AWTException, InterruptedException {
50 |
51 | for (int cnt = 0; cnt != rawKeys.length; cnt++) {
52 | robot.keyPress(rawKeys[cnt]);
53 | Thread.sleep(delay);
54 | }
55 | writeString("Hello AWT!");
56 | }
57 |
58 | // @Ignore
59 | @Test
60 | public void writeStringTest() {
61 | writeString("Hello AWT!");
62 | robot.keyPress(KeyEvent.VK_ENTER);
63 | writeString("Hello again AWT!");
64 | robot.keyPress(KeyEvent.VK_ENTER);
65 | writeString(",-./0123456789;=ABCDEFGHIJKLMNOPQRSTUVWXYZ");
66 | // prints
67 | // -.0123456789=ФИСВУАПРШОЛДЬТЩЗЙКЫЕГМЦЧНЯфисвуапршолдьтщзйкыегмцчня\0123456789-.
68 | robot.keyPress(KeyEvent.VK_ENTER);
69 | writeString("abcdefghijklmnopqrstuvwxyz[\\]0123456789*+-./");
70 | // prints
71 | // -.0123456789=ФИСВУАПРШОЛДЬТЩЗЙКЫЕГМЦЧНЯфисвуапршолдьтщзйкыегмцчня\0123456789-.
72 | robot.keyPress(KeyEvent.VK_ENTER);
73 | writeString(
74 | ",-./0123456789;=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz[\\]0123456789*+-./");
75 | // prints
76 | // -.0123456789=ФИСВУАПРШОЛДЬТЩЗЙКЫЕГМЦЧНЯфисвуапршолдьтщзйкыегмцчня\0123456789-.
77 | }
78 |
79 | @Ignore
80 | @Test
81 | public void printAllCharactersTest() {
82 |
83 | // print range of character codes brute force
84 | for (int code = 17; code < 128; code++) {
85 | try {
86 | robot.keyPress(code);
87 | robot.delay(delay);
88 | robot.keyRelease(code);
89 | } catch (IllegalArgumentException e) {
90 | System.err.println(
91 | "Failed to press " + code + " " + KeyEvent.getKeyText(code));
92 | // Failed to press 91 Open Bracket
93 | // Failed to press 93 Close Bracket
94 | // Failed to press 44 Comma
95 | // Failed to press 47 Slash
96 | }
97 | }
98 | }
99 |
100 | public static void sleep(Integer milliSeconds) {
101 | try {
102 | Thread.sleep((long) milliSeconds);
103 | } catch (InterruptedException e) {
104 | e.printStackTrace();
105 | }
106 | }
107 |
108 | private void writeString(String s) {
109 | for (int code = 0; code < s.length(); code++) {
110 | char character = s.charAt(code);
111 | if (Character.isUpperCase(character)) {
112 | robot.keyPress(KeyEvent.VK_SHIFT);
113 | }
114 | try {
115 | System.err.println("Pressing " + character);
116 | robot.keyPress(character);
117 | sleep(delay2);
118 | System.err.println("Releasing " + character);
119 | robot.keyRelease(character);
120 | // https://stackoverflow.com/questions/29665534/type-a-string-using-java-awt-robots
121 | // robot.keyPress(KeyEvent.getExtendedKeyCodeForChar((int) character));
122 | //
123 | } catch (IllegalArgumentException e) {
124 | System.err.println(
125 | "Failed to press " + code + " " + KeyEvent.getKeyText(code));
126 | //
127 | }
128 | if (Character.isUpperCase(character)) {
129 | robot.keyRelease(KeyEvent.VK_SHIFT);
130 | }
131 | }
132 | robot.delay(delay);
133 | }
134 |
135 | }
136 |
--------------------------------------------------------------------------------
/src/test/java/com/github/sergueik/swet/OSUtilsAndWinRegistryTest.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 | /**
3 | * Copyright 2014 - 2019 Serguei Kouzmine
4 | */
5 |
6 | import static org.junit.Assert.assertArrayEquals;
7 | import static org.junit.Assert.assertTrue;
8 | import static org.junit.Assert.assertThat;
9 |
10 | import static org.hamcrest.CoreMatchers.containsString;
11 | import static org.hamcrest.Matchers.greaterThan;
12 | import static org.hamcrest.Matchers.equalTo;
13 |
14 | import java.lang.reflect.InvocationTargetException;
15 | import java.util.ArrayList;
16 | import java.util.Arrays;
17 | import java.util.HashMap;
18 | import java.util.HashSet;
19 | import java.util.List;
20 | import java.util.Map;
21 | import java.util.Optional;
22 | import java.util.Set;
23 |
24 | import org.junit.Before;
25 | import org.junit.BeforeClass;
26 | import org.junit.Ignore;
27 | import org.junit.Test;
28 |
29 | import org.json.JSONArray;
30 | import org.json.JSONException;
31 | import org.json.JSONObject;
32 |
33 | import java.util.UUID;
34 |
35 | import static org.hamcrest.CoreMatchers.notNullValue;
36 | import static org.hamcrest.core.AnyOf.anyOf;
37 |
38 | import com.google.gson.Gson;
39 | import com.google.gson.GsonBuilder;
40 |
41 | import com.github.sergueik.swet.Utils;
42 | import com.github.sergueik.swet.OSUtils;
43 |
44 | @SuppressWarnings("deprecation")
45 | public class OSUtilsAndWinRegistryTest {
46 |
47 | private static Utils utils = Utils.getInstance();
48 | private static String result = null;
49 | private static final boolean debug = true;
50 |
51 | @BeforeClass
52 | public static void beforeSuiteMethod() throws Exception {
53 |
54 | }
55 |
56 | @Before
57 | public void before() {
58 | }
59 |
60 | @Test
61 | public void registryReadBrowsersTest() {
62 | List browsers = OSUtils.getInstalledBrowsers();
63 | assertThat(browsers, notNullValue());
64 | assertThat(browsers.size(), greaterThan(2));
65 | if (debug) {
66 | System.err.println("Installed browsers: " + browsers.toString());
67 | }
68 | }
69 |
70 | @Test
71 | public void registryReadZoomTest() {
72 | int zoom = OSUtils.getZoom();
73 | assertThat(zoom, notNullValue());
74 | assertThat(zoom, anyOf(equalTo(100000), equalTo(80000), equalTo(-1)));
75 | // NOTE: possibly after a cold reboot:
76 | // Expected: <100000>
77 | // but: was <-1>
78 | // TODO:
79 | // "ResetZoomOnStartup2"
80 | // assertThat(zoom, anyOf(equalTo(1), equalTo(-1)));
81 |
82 | if (debug) {
83 | System.err.println("Zoom: " + zoom);
84 | }
85 | }
86 |
87 | // based on:
88 | // https://answers.microsoft.com/en-us/ie/forum/all/ie-11-how-do-i-get-a-default-zoom-to-stick/19510f5a-c339-45d1-b74e-edc885ef5517
89 | @Test
90 | public void registryReadAdvancedOptionsZoomTest() {
91 | int zoom = OSUtils.getAdvancedOptionsZoom();
92 | assertThat(zoom, notNullValue());
93 | assertThat(zoom, equalTo(1));
94 | if (debug) {
95 | System.err.println("Accesibility Zoom: " + zoom);
96 | }
97 | }
98 |
99 | @Ignore
100 | @Test
101 | public void registryWinRegistryReadAdvancedOptionsTest1() {
102 | String value = null;
103 | try {
104 | value = OSUtils.WinRegistry.readString(
105 | OSUtils.WinRegistry.HKEY_LOCAL_MACHINE,
106 | "SOFTWARE\\Microsoft\\Internet Explorer\\AdvancedOptions\\ACCESSIBILITY\\ZOOMLEVEL",
107 | "CheckedValue");
108 | } catch (IllegalArgumentException | IllegalAccessException
109 | | InvocationTargetException e) {
110 | System.err.println("Exceptiion (ignored): " + e.toString());
111 | }
112 | // assertThat(value, notNullValue());
113 | // java.lang.NumberFormatException: null
114 | assertThat(Integer.parseInt(value), equalTo(1));
115 | if (debug) {
116 | System.err.println("Accesibility Zoom CheckedValue: " + value);
117 | }
118 |
119 | }
120 |
121 | @Test
122 | public void registryWinRegistryReadAdvancedOptionsTest2() {
123 | String value = null;
124 | try {
125 | value = OSUtils.WinRegistry.readString(
126 | OSUtils.WinRegistry.HKEY_LOCAL_MACHINE,
127 | "SOFTWARE\\Microsoft\\Internet Explorer\\AdvancedOptions\\ACCESSIBILITY\\ZOOMLEVEL",
128 | "ValueName");
129 | } catch (IllegalArgumentException | IllegalAccessException
130 | | InvocationTargetException e) {
131 | System.err.println("Exceptiion (ignored): " + e.toString());
132 | }
133 | assertThat(value, notNullValue());
134 | // assertThat(Integer.parseInt(value), equalTo(1));
135 | if (debug) {
136 | System.err.println("Accesibility Zoom ValueName: " + value);
137 | }
138 |
139 | }
140 |
141 | }
142 |
--------------------------------------------------------------------------------
/src/main/java/com/github/sergueik/swet/SystemTrayEx.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 | /**
3 | * Copyright 2014 - 2019 Serguei Kouzmine
4 | */
5 |
6 | import javax.swing.ImageIcon;
7 |
8 | import org.eclipse.swt.SWT;
9 | import org.eclipse.swt.events.SelectionAdapter;
10 | import org.eclipse.swt.events.SelectionEvent;
11 | import org.eclipse.swt.graphics.Image;
12 | import org.eclipse.swt.layout.RowLayout;
13 | import org.eclipse.swt.widgets.Display;
14 | import org.eclipse.swt.widgets.Event;
15 | import org.eclipse.swt.widgets.Listener;
16 | import org.eclipse.swt.widgets.Menu;
17 | import org.eclipse.swt.widgets.MenuItem;
18 | import org.eclipse.swt.widgets.Shell;
19 | import org.eclipse.swt.widgets.ToolTip;
20 | import org.eclipse.swt.widgets.Tray;
21 | import org.eclipse.swt.widgets.TrayItem;
22 |
23 | // origin: https://github.com/Vladimir-Novick/System-Tray
24 | ////////////////////////////////////////////////////////////////////////////
25 | // Copyright 2006, 2017 : Vladimir Novick https://www.linkedin.com/in/vladimirnovick/
26 | //
27 | // https://github.com/Vladimir-Novick/System-Tray
28 | //
29 | // NO WARRANTIES ARE EXTENDED. USE AT YOUR OWN RISK.
30 | //
31 | // To contact the author with suggestions or comments, use :vlad.novick@gmail.com
32 | //
33 | ////////////////////////////////////////////////////////////////////////////
34 |
35 | public class SystemTrayEx {
36 |
37 | public SystemTrayEx() {
38 | super();
39 | }
40 |
41 | private static TrayItem trayItem = null;
42 |
43 | private static Image imageStarted = null;
44 | private static Image imageStopped = null;
45 |
46 | /** Returns an ImageIcon, or null if the path was invalid. */
47 | protected ImageIcon createImage(String path, String description) {
48 | java.net.URL imgURL = SystemTrayEx.class.getResource(path);
49 | if (imgURL != null) {
50 | return new ImageIcon(imgURL, description);
51 | } else {
52 | System.err.println("Couldn't find file: " + path);
53 | return null;
54 | }
55 | }
56 |
57 | /**
58 | * @param args
59 | */
60 | public static void main(String[] args) {
61 |
62 | // -------------
63 | Display display = new Display();
64 | final Shell shell = new Shell(display);
65 | shell.setLayout(new RowLayout());
66 |
67 | // -------------
68 |
69 | final ToolTip tip = new ToolTip(shell, SWT.BALLOON | SWT.ICON_INFORMATION);
70 | tip.setMessage("SGcombo System Agent Goes Here!");
71 |
72 | Tray tray = display.getSystemTray();
73 |
74 | if (tray != null) {
75 | trayItem = new TrayItem(tray, SWT.NONE);
76 | trayItem.setImage(imageStarted);
77 | final Menu menu = new Menu(shell, SWT.POP_UP);
78 |
79 | MenuItem menuItem = new MenuItem(menu, SWT.PUSH);
80 | menuItem.setText("Stop Agent");
81 |
82 | Image imagemenu = new Image(display, "./src/main/resources/images/stop.gif");
83 | menuItem.setImage(imagemenu);
84 |
85 | menuItem.addSelectionListener(new SelectionAdapter() {
86 | public void widgetSelected(SelectionEvent event) {
87 | stopAgent();
88 | }
89 | });
90 |
91 | menuItem = new MenuItem(menu, SWT.PUSH);
92 | menuItem.setText("Start Agent");
93 | imagemenu = new Image(display, "./src/main/resources/images/start.gif");
94 | menuItem.setImage(imagemenu);
95 |
96 | menuItem.addSelectionListener(new SelectionAdapter() {
97 | public void widgetSelected(SelectionEvent event) {
98 | startAgent();
99 | trayItem.setImage(imageStarted);
100 | }
101 | });
102 |
103 | menuItem = new MenuItem(menu, SWT.PUSH);
104 | menuItem.setText("Show Status");
105 |
106 | menuItem = new MenuItem(menu, SWT.PUSH);
107 | menuItem.setText("Shutdown");
108 |
109 | menuItem.addSelectionListener(new SelectionAdapter() {
110 |
111 | public void widgetSelected(SelectionEvent event) {
112 |
113 | shell.close(); // calls dispose() - see note below
114 |
115 | }
116 |
117 | });
118 |
119 | trayItem.addListener(SWT.MouseEnter, new Listener() {
120 | public void handleEvent(Event e) {
121 | tip.setVisible(true);
122 | }
123 | });
124 |
125 | trayItem.addListener(SWT.MenuDetect, new Listener() {
126 | public void handleEvent(Event event) {
127 | menu.setVisible(true);
128 | }
129 | });
130 | }
131 |
132 | shell.pack();
133 | shell.open();
134 |
135 | shell.setVisible(false);
136 |
137 | while (!shell.isDisposed()) {
138 | if (!display.readAndDispatch())
139 | display.sleep();
140 | }
141 | trayItem.dispose();
142 | display.dispose();
143 |
144 | }
145 |
146 | protected static void startAgent() {
147 | trayItem.setImage(imageStarted);
148 | }
149 |
150 | protected static void stopAgent() {
151 | trayItem.setImage(imageStopped);
152 | }
153 |
154 | }
155 |
--------------------------------------------------------------------------------
/src/main/java/com/github/sergueik/swet/JavaScanner.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 |
3 | import java.util.Hashtable;
4 |
5 | /**
6 | * Token scanner for Selenium WebDriver Elementor Tool(SWET)
7 | * @author: Serguei Kouzmine (kouzmine_serguei@yahoo.cm)
8 | */
9 |
10 | public class JavaScanner {
11 |
12 | public static final int EOF = -1;
13 | public static final int EOL = 10;
14 | public static final int WORD = 0;
15 | public static final int WHITE = 1;
16 | public static final int KEY = 2;
17 | public static final int COMMENT = 3;
18 | public static final int STRING = 5;
19 | public static final int OTHER = 6;
20 | public static final int NUMBER = 7;
21 | public static final int MAXIMUM_TOKEN = 8;
22 |
23 | @SuppressWarnings("rawtypes")
24 | protected Hashtable fgKeys = null;
25 | protected StringBuffer fBuffer = new StringBuffer();
26 | protected String fDoc;
27 | protected int fPos;
28 | protected int fEnd;
29 | protected int fStartToken;
30 | protected boolean fEofSeen = false;
31 |
32 | private String[] fgKeywords = { "abstract", "boolean", "break", "byte",
33 | "case", "catch", "char", "class", "continue", "default", "do", "double",
34 | "else", "extends", "false", "final", "finally", "float", "for", "if",
35 | "implements", "import", "instanceof", "int", "interface", "long",
36 | "native", "new", "null", "package", "private", "protected", "public",
37 | "return", "short", "static", "super", "switch", "synchronized", "this",
38 | "throw", "throws", "transient", "true", "try", "void", "volatile",
39 | "while" };
40 |
41 | public JavaScanner() {
42 | initialize();
43 | }
44 |
45 | /**
46 | * Returns the ending location of the current token in the document.
47 | */
48 | public final int getLength() {
49 | return fPos - fStartToken;
50 | }
51 |
52 | /**
53 | * Initialize the lookup table.
54 | */
55 | @SuppressWarnings({ "rawtypes", "unchecked" })
56 | void initialize() {
57 | fgKeys = new Hashtable();
58 | Integer k = new Integer(KEY);
59 | for (int i = 0; i < fgKeywords.length; i++)
60 | fgKeys.put(fgKeywords[i], k);
61 | }
62 |
63 | /**
64 | * Returns the starting location of the current token in the document.
65 | */
66 | public final int getStartOffset() {
67 | return fStartToken;
68 | }
69 |
70 | /**
71 | * Returns the next lexical token in the document.
72 | */
73 | public int nextToken() {
74 | int c;
75 | fStartToken = fPos;
76 | while (true) {
77 | switch (c = read()) {
78 | case EOF:
79 | return EOF;
80 | case '/': // comment
81 | c = read();
82 | if (c == '/') {
83 | while (true) {
84 | c = read();
85 | if ((c == EOF) || (c == EOL)) {
86 | unread(c);
87 | return COMMENT;
88 | }
89 | }
90 | } else {
91 | unread(c);
92 | }
93 | return OTHER;
94 | case '\'': // char const
95 | character: for (;;) {
96 | c = read();
97 | switch (c) {
98 | case '\'':
99 | return STRING;
100 | case EOF:
101 | unread(c);
102 | return STRING;
103 | case '\\':
104 | c = read();
105 | break;
106 | }
107 | }
108 |
109 | case '"': // string
110 | string: for (;;) {
111 | c = read();
112 | switch (c) {
113 | case '"':
114 | return STRING;
115 | case EOF:
116 | unread(c);
117 | return STRING;
118 | case '\\':
119 | c = read();
120 | break;
121 | }
122 | }
123 |
124 | case '0':
125 | case '1':
126 | case '2':
127 | case '3':
128 | case '4':
129 | case '5':
130 | case '6':
131 | case '7':
132 | case '8':
133 | case '9':
134 | do {
135 | c = read();
136 | } while (Character.isDigit((char) c));
137 | unread(c);
138 | return NUMBER;
139 | default:
140 | if (Character.isWhitespace((char) c)) {
141 | do {
142 | c = read();
143 | } while (Character.isWhitespace((char) c));
144 | unread(c);
145 | return WHITE;
146 | }
147 | if (Character.isJavaIdentifierStart((char) c)) {
148 | fBuffer.setLength(0);
149 | do {
150 | fBuffer.append((char) c);
151 | c = read();
152 | } while (Character.isJavaIdentifierPart((char) c));
153 | unread(c);
154 | Integer i = (Integer) fgKeys.get(fBuffer.toString());
155 | if (i != null)
156 | return i.intValue();
157 | return WORD;
158 | }
159 | return OTHER;
160 | }
161 | }
162 | }
163 |
164 | /**
165 | * Returns next character.
166 | */
167 | protected int read() {
168 | if (fPos <= fEnd) {
169 | return fDoc.charAt(fPos++);
170 | }
171 | return EOF;
172 | }
173 |
174 | public void setRange(String text) {
175 | fDoc = text;
176 | fPos = 0;
177 | fEnd = fDoc.length() - 1;
178 | }
179 |
180 | protected void unread(int c) {
181 | if (c != EOF)
182 | fPos--;
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/src/main/java/com/github/sergueik/swet/UtilExtensions.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 | /**
3 | * Copyright 2014 - 2019 Serguei Kouzmine
4 | */
5 |
6 | import java.lang.reflect.Field;
7 | import java.lang.reflect.InvocationTargetException;
8 |
9 | import java.util.ArrayList;
10 | import java.util.HashMap;
11 | import java.util.List;
12 | import java.util.Map;
13 | import java.util.Map.Entry;
14 | import java.util.Set;
15 |
16 | import org.json.JSONArray;
17 | import org.json.JSONException;
18 | import org.json.JSONObject;
19 |
20 | // generic JSONobject (de-)serializer
21 | // origin: https://www.codeproject.com/Tips/709552/Google-App-Engine-JAVA
22 |
23 | public class UtilExtensions {
24 | public static JSONObject getJsonObject(String payload) throws JSONException {
25 | JSONObject jsonObject = new JSONObject(payload);
26 | return jsonObject;
27 | }
28 |
29 | public static JSONArray getJsonArray(String payload) throws JSONException {
30 | JSONArray jsonArray = new JSONArray(payload);
31 | return jsonArray;
32 | }
33 |
34 | public static JSONObject modelToJSON(Model model, Mapper mapper)
35 | throws NoSuchFieldException, IllegalAccessException, JSONException,
36 | NoSuchMethodException, InvocationTargetException {
37 | JSONObject jsonObject = new JSONObject();
38 | if (mapper.size() > 0) {
39 | for (@SuppressWarnings("rawtypes")
40 | Entry entry : mapper.getEntrySet()) {
41 | String value = entry.getValue().toString();
42 | String key = entry.getKey().toString();
43 | jsonObject.put(value, model.getProperty(key));
44 | }
45 | return jsonObject;
46 | } else {
47 | for (String property : model.getProperties()) {
48 | jsonObject.put(property, model.getProperty(property));
49 | }
50 | return jsonObject;
51 | }
52 | }
53 |
54 | public static JSONArray modelsToJSON(
55 | @SuppressWarnings("rawtypes") List models, Mapper mapper)
56 | throws IllegalAccessException, NoSuchFieldException, JSONException,
57 | NoSuchMethodException, InvocationTargetException {
58 | JSONArray jsonArray = new JSONArray();
59 | for (Object model : models) {
60 | jsonArray.put(modelToJSON((Model) model, mapper));
61 | }
62 | return jsonArray;
63 | }
64 |
65 | public static Model jsonObjectToModel(JSONObject jsonObject,
66 | @SuppressWarnings("rawtypes") Class model, Mapper mapper)
67 | throws IllegalAccessException, InstantiationException, JSONException,
68 | NoSuchFieldException {
69 | Model m = null;
70 | if (mapper.size() > 0) {
71 | m = (Model) model.newInstance();
72 | for (@SuppressWarnings("rawtypes")
73 | Entry entry : mapper.getEntrySet()) {
74 | String value = entry.getValue().toString();
75 | String key = entry.getKey().toString();
76 | String jValue = jsonObject.get(value).toString();
77 | m.setProperty(key, jValue);
78 | }
79 | return m;
80 | } else {
81 | m = (Model) model.newInstance();
82 | for (String property : m.getProperties()) {
83 | String jValue = jsonObject.get(property).toString();
84 | m.setProperty(property, jValue);
85 | }
86 | return m;
87 | }
88 | }
89 |
90 | public static List jsonArrayToModel(JSONArray jsonArray,
91 | @SuppressWarnings("rawtypes") Class model, Mapper mapper)
92 | throws JSONException, IllegalAccessException, NoSuchFieldException,
93 | InstantiationException {
94 | List list = new ArrayList<>();
95 | int length = jsonArray.length();
96 | for (int index = 0; index < length; index++) {
97 | list.add(
98 | jsonObjectToModel(jsonArray.getJSONObject(index), model, mapper));
99 | }
100 | return list;
101 | }
102 |
103 | private static abstract class Mapper {
104 |
105 | protected Map mapper = new HashMap<>();
106 |
107 | abstract public void init();
108 |
109 | public Mapper() {
110 | init();
111 | }
112 |
113 | public Set> getEntrySet() {
114 | return this.mapper.entrySet();
115 | }
116 |
117 | public int size() {
118 | return this.mapper.size();
119 | }
120 |
121 | public String get(String key) {
122 | return this.mapper.get(key);
123 | }
124 |
125 | }
126 |
127 | private static abstract class Model {
128 |
129 | abstract public String keyToString();
130 |
131 | public List getProperties() {
132 | List list = new ArrayList<>();
133 | for (Field field : this.getClass().getDeclaredFields()) {
134 | list.add(field.getName());
135 | }
136 | return list;
137 | }
138 |
139 | public Object getProperty(String property)
140 | throws NoSuchFieldException, IllegalAccessException,
141 | NoSuchMethodException, InvocationTargetException {
142 | Field f = this.getClass().getDeclaredField(property);
143 | f.setAccessible(true);
144 | /*
145 | if (f.getType() == Key.class) {
146 | Method method = this.getClass().getDeclaredMethod("keyToString");
147 | return method.invoke(this);
148 | }
149 | */
150 | return f.get(this);
151 | }
152 |
153 | public void setProperty(String property, Object value)
154 | throws IllegalAccessException, NoSuchFieldException {
155 | Field f = this.getClass().getDeclaredField(property);
156 | f.setAccessible(true);
157 | f.set(this, value);
158 | }
159 | }
160 | }
--------------------------------------------------------------------------------
/MouseEventDemo.java:
--------------------------------------------------------------------------------
1 | // origin: https://docs.oracle.com/javase/tutorial/displayCode.html?code=https://docs.oracle.com/javase/tutorial/uiswing/examples/events/MouseEventDemoProject/src/events/MouseEventDemo.java
2 |
3 | /*
4 | * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
5 | */
6 | // default package
7 | // package events;
8 |
9 | /*
10 | * MouseEventDemo.java
11 | */
12 |
13 | import java.awt.Color;
14 | import java.awt.Dimension;
15 | import java.awt.event.MouseListener;
16 | import java.awt.event.MouseEvent;
17 | import java.awt.Graphics;
18 | import java.awt.GridLayout;
19 |
20 | import javax.swing.*;
21 | import javax.swing.*;
22 |
23 | public class MouseEventDemo extends JPanel
24 | implements MouseListener {
25 | BlankArea blankArea;
26 | JTextArea textArea;
27 | static final String NEWLINE = System.getProperty("line.separator");
28 |
29 | public static void main(String[] args) {
30 | /* Use an appropriate Look and Feel */
31 | try {
32 | //UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
33 | //UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
34 | UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
35 | } catch (UnsupportedLookAndFeelException ex) {
36 | ex.printStackTrace();
37 | } catch (IllegalAccessException ex) {
38 | ex.printStackTrace();
39 | } catch (InstantiationException ex) {
40 | ex.printStackTrace();
41 | } catch (ClassNotFoundException ex) {
42 | ex.printStackTrace();
43 | }
44 | /* Turn off metal's use of bold fonts */
45 | UIManager.put("swing.boldMetal", Boolean.FALSE);
46 | //Schedule a job for the event dispatch thread:
47 | //creating and showing this application's GUI.
48 | javax.swing.SwingUtilities.invokeLater(new Runnable() {
49 | public void run() {
50 | createAndShowGUI();
51 | }
52 | });
53 | }
54 |
55 | /**
56 | * Create the GUI and show it. For thread safety,
57 | * this method should be invoked from the
58 | * event dispatch thread.
59 | */
60 | private static void createAndShowGUI() {
61 | //Create and set up the window.
62 | JFrame frame = new JFrame("MouseEventDemo");
63 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
64 |
65 | //Create and set up the content pane.
66 | JComponent newContentPane = new MouseEventDemo();
67 | newContentPane.setOpaque(true); //content panes must be opaque
68 | frame.setContentPane(newContentPane);
69 |
70 | //Display the window.
71 | frame.pack();
72 | frame.setVisible(true);
73 | }
74 |
75 | public MouseEventDemo() {
76 | super(new GridLayout(0,1));
77 | blankArea = new BlankArea(Color.YELLOW);
78 | add(blankArea);
79 | textArea = new JTextArea();
80 | textArea.setEditable(false);
81 | JScrollPane scrollPane = new JScrollPane(textArea);
82 | scrollPane.setVerticalScrollBarPolicy(
83 | JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
84 | scrollPane.setPreferredSize(new Dimension(200, 75));
85 | add(scrollPane);
86 |
87 | //Register for mouse events on blankArea and the panel.
88 | blankArea.addMouseListener(this);
89 | addMouseListener(this);
90 | setPreferredSize(new Dimension(450, 450));
91 | setBorder(BorderFactory.createEmptyBorder(20,20,20,20));
92 | }
93 |
94 | void eventOutput(String eventDescription, MouseEvent e) {
95 | textArea.append(eventDescription + " detected on "
96 | + e.getComponent().getClass().getName()
97 | + "." + NEWLINE);
98 | textArea.setCaretPosition(textArea.getDocument().getLength());
99 | }
100 |
101 | public void mousePressed(MouseEvent e) {
102 | eventOutput("Mouse pressed (# of clicks: "
103 | + e.getClickCount() + ")", e);
104 | }
105 |
106 | public void mouseReleased(MouseEvent e) {
107 | eventOutput("Mouse released (# of clicks: "
108 | + e.getClickCount() + ")", e);
109 | }
110 |
111 | public void mouseEntered(MouseEvent e) {
112 | eventOutput("Mouse entered", e);
113 | }
114 |
115 | public void mouseExited(MouseEvent e) {
116 | eventOutput("Mouse exited", e);
117 | }
118 |
119 | public void mouseClicked(MouseEvent e) {
120 | eventOutput("Mouse clicked (# of clicks: "
121 | + e.getClickCount() + ")", e);
122 | }
123 |
124 | public class BlankArea extends JLabel {
125 | Dimension minSize = new Dimension(100, 50);
126 |
127 | public BlankArea(Color color) {
128 | setBackground(color);
129 | setOpaque(true);
130 | setBorder(BorderFactory.createLineBorder(Color.black));
131 | }
132 |
133 | public Dimension getMinimumSize() {
134 | return minSize;
135 | }
136 |
137 | public Dimension getPreferredSize() {
138 | return minSize;
139 | }
140 | }
141 | }
142 |
143 |
--------------------------------------------------------------------------------
/src/main/java/com/github/sergueik/swet/MouseEventDemo.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 | // default package
3 | // package events;
4 |
5 | /*
6 | * MouseEventDemo.java
7 | * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
8 | */
9 | // origin: https://docs.oracle.com/javase/tutorial/displayCode.html?code=https://docs.oracle.com/javase/tutorial/uiswing/examples/events/MouseEventDemoProject/src/events/MouseEventDemo.java
10 |
11 |
12 | import java.awt.Color;
13 | import java.awt.Dimension;
14 | import java.awt.event.MouseListener;
15 | import java.awt.event.MouseEvent;
16 | import java.awt.Graphics;
17 | import java.awt.GridLayout;
18 |
19 | import javax.swing.*;
20 | import javax.swing.*;
21 |
22 | public class MouseEventDemo extends JPanel
23 | implements MouseListener {
24 | BlankArea blankArea;
25 | JTextArea textArea;
26 | static final String NEWLINE = System.getProperty("line.separator");
27 |
28 | public static void main(String[] args) {
29 | /* Use an appropriate Look and Feel */
30 | try {
31 | //UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
32 | //UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
33 | UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
34 | } catch (UnsupportedLookAndFeelException ex) {
35 | ex.printStackTrace();
36 | } catch (IllegalAccessException ex) {
37 | ex.printStackTrace();
38 | } catch (InstantiationException ex) {
39 | ex.printStackTrace();
40 | } catch (ClassNotFoundException ex) {
41 | ex.printStackTrace();
42 | }
43 | /* Turn off metal's use of bold fonts */
44 | UIManager.put("swing.boldMetal", Boolean.FALSE);
45 | //Schedule a job for the event dispatch thread:
46 | //creating and showing this application's GUI.
47 | javax.swing.SwingUtilities.invokeLater(new Runnable() {
48 | public void run() {
49 | createAndShowGUI();
50 | }
51 | });
52 | }
53 |
54 | /**
55 | * Create the GUI and show it. For thread safety,
56 | * this method should be invoked from the
57 | * event dispatch thread.
58 | */
59 | private static void createAndShowGUI() {
60 | //Create and set up the window.
61 | JFrame frame = new JFrame("MouseEventDemo");
62 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
63 |
64 | //Create and set up the content pane.
65 | JComponent newContentPane = new MouseEventDemo();
66 | newContentPane.setOpaque(true); //content panes must be opaque
67 | frame.setContentPane(newContentPane);
68 |
69 | //Display the window.
70 | frame.pack();
71 | frame.setVisible(true);
72 | }
73 |
74 | public MouseEventDemo() {
75 | super(new GridLayout(0,1));
76 | blankArea = new BlankArea(Color.YELLOW);
77 | add(blankArea);
78 | textArea = new JTextArea();
79 | textArea.setEditable(false);
80 | JScrollPane scrollPane = new JScrollPane(textArea);
81 | scrollPane.setVerticalScrollBarPolicy(
82 | JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
83 | scrollPane.setPreferredSize(new Dimension(200, 75));
84 | add(scrollPane);
85 |
86 | //Register for mouse events on blankArea and the panel.
87 | blankArea.addMouseListener(this);
88 | addMouseListener(this);
89 | setPreferredSize(new Dimension(450, 450));
90 | setBorder(BorderFactory.createEmptyBorder(20,20,20,20));
91 | }
92 |
93 | void eventOutput(String eventDescription, MouseEvent e) {
94 | textArea.append(eventDescription + " detected on "
95 | + e.getComponent().getClass().getName()
96 | + "." + NEWLINE);
97 | textArea.setCaretPosition(textArea.getDocument().getLength());
98 | }
99 |
100 | public void mousePressed(MouseEvent e) {
101 | eventOutput("Mouse pressed (# of clicks: "
102 | + e.getClickCount() + ")", e);
103 | }
104 |
105 | public void mouseReleased(MouseEvent e) {
106 | eventOutput("Mouse released (# of clicks: "
107 | + e.getClickCount() + ")", e);
108 | }
109 |
110 | public void mouseEntered(MouseEvent e) {
111 | eventOutput("Mouse entered", e);
112 | }
113 |
114 | public void mouseExited(MouseEvent e) {
115 | eventOutput("Mouse exited", e);
116 | }
117 |
118 | public void mouseClicked(MouseEvent e) {
119 | eventOutput("Mouse clicked (# of clicks: "
120 | + e.getClickCount() + ")", e);
121 | }
122 |
123 | public class BlankArea extends JLabel {
124 | Dimension minSize = new Dimension(100, 50);
125 |
126 | public BlankArea(Color color) {
127 | setBackground(color);
128 | setOpaque(true);
129 | setBorder(BorderFactory.createLineBorder(Color.black));
130 | }
131 |
132 | public Dimension getMinimumSize() {
133 | return minSize;
134 | }
135 |
136 | public Dimension getPreferredSize() {
137 | return minSize;
138 | }
139 | }
140 | }
141 |
142 |
--------------------------------------------------------------------------------
/src/main/java/com/github/sergueik/swet/ExceptionDialogEx.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 | /**
3 | * Copyright 2014 - 2019,2024 Serguei Kouzmine
4 | */
5 |
6 | import java.util.ArrayList;
7 | import java.util.List;
8 |
9 | import org.eclipse.core.runtime.IStatus;
10 | import org.eclipse.core.runtime.MultiStatus;
11 | import org.eclipse.core.runtime.Status;
12 |
13 | import org.eclipse.jface.dialogs.ErrorDialog;
14 |
15 | import org.eclipse.swt.widgets.Display;
16 | import org.eclipse.swt.widgets.Shell;
17 | // https://docs.oracle.com/javase/8/docs/api/org/omg/SendingContext/RunTime.html
18 | // The import org.omg.SendingContext.RunTime is never used
19 | // import org.omg.SendingContext.RunTime;
20 |
21 | import com.github.sergueik.swet.Utils;
22 |
23 | import org.eclipse.swt.SWTException;
24 |
25 | /**
26 | * Exception dialog for Selenium WebDriver Elementor Tool (SWET)
27 | *
28 | * @author Serguei Kouzmine (kouzmine_serguei@yahoo.com)
29 | */
30 |
31 | public class ExceptionDialogEx {
32 |
33 |
34 | private Shell shell = null;
35 | private static boolean debug = false;
36 | private static final Utils utils = Utils.getInstance();
37 | private static final String manifestVersion = utils.readManifestVersion();
38 | private static final ExceptionDialogEx instance = new ExceptionDialogEx();
39 |
40 | public static void setDebug(boolean debug) {
41 | ExceptionDialogEx.debug = debug;
42 | }
43 |
44 | public static ExceptionDialogEx getInstance() {
45 | return instance;
46 | }
47 |
48 | private static void testFunction1() throws Exception {
49 | testFunction2();
50 | }
51 |
52 | private static void testFunction2() throws Exception {
53 | testFunction3();
54 | }
55 |
56 | // throwing exception from a function to illustrate the calling stack
57 | private static void testFunction3() throws Exception {
58 | throw new Exception("This is a dummy exception thrown by testFunction3");
59 | }
60 |
61 | public void render(Throwable e) {
62 |
63 | MultiStatus status;
64 | // Collect the exception stack trace
65 | Exception eCause = (Exception) e.getCause();
66 | if (eCause != null) {
67 | if (debug) {
68 | System.err.println("Cause: " + eCause.toString());
69 | }
70 | status = createMultiStatus(e.getLocalizedMessage(), eCause);
71 | } else {
72 | status = createMultiStatus(e.getLocalizedMessage(), e);
73 | }
74 | // the following walks the stack, useful to discover the caller during the
75 | // regular execution - not so useful with thrower of the exception
76 | // https://stackoverflow.com/questions/4065518/java-how-to-get-the-caller-function-name/46590924
77 | // https://toster.ru/q/684867
78 | StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[2];
79 | String originatingMethod = String.format("%s.%s()", stackTraceElement.getClassName(),
80 | stackTraceElement.getMethodName());
81 | // [0] => getStackTrace
82 | // [1] => render
83 | // [2] => main
84 |
85 | ErrorDialog.openError(shell, "Exception",
86 | "Exception thrown from " + instance.getClass().getName() + " " + manifestVersion
87 | /* "Exception thrown" */, status);
88 |
89 | }
90 |
91 | private ExceptionDialogEx() {
92 | Display display = null;
93 | try {
94 | display = Display.getCurrent();
95 | } catch (SWTException e) {
96 | System.err.println(e.toString());
97 | throw new RuntimeException(e);
98 | }
99 | try {
100 | shell = Display.getCurrent().getActiveShell();
101 | } catch (NullPointerException e) {
102 | shell = new Shell(display);
103 | }
104 | }
105 |
106 | private static MultiStatus createMultiStatus(String description, Throwable t) {
107 |
108 | List childStatuses = new ArrayList<>();
109 |
110 | for (StackTraceElement stackTrace : t.getStackTrace()) {
111 | if (debug) {
112 | System.err.println(String.format("Adding stack trace: %s", stackTrace.toString()));
113 | }
114 |
115 | Status status = new Status(IStatus.ERROR,
116 | ExceptionDialogEx.getInstance().getClass().getPackage().toString(), stackTrace.toString());
117 | childStatuses.add(status);
118 | }
119 | for (StackTraceElement stackTraceElement : Thread.currentThread().getStackTrace()) {
120 | if (debug) {
121 | System.err.println(String.format("Adding stack trace element: %s", stackTraceElement.toString()));
122 | }
123 | Status status = new Status(IStatus.ERROR,
124 | ExceptionDialogEx.getInstance().getClass().getPackage().toString(), stackTraceElement.toString());
125 | childStatuses.add(status);
126 | }
127 |
128 | String summary = (description != null) ? description : t.toString();
129 | MultiStatus status = new MultiStatus(ExceptionDialogEx.getInstance().getClass().getPackage().toString(),
130 | IStatus.ERROR, childStatuses.toArray(new Status[] {}),
131 | (summary.length() > 120) ? summary.substring(0, 120) : summary, t);
132 | return status;
133 | }
134 |
135 | public static void main(String[] arg) {
136 | debug = true;
137 | try {
138 | testFunction1();
139 | } catch (Exception e) {
140 | // when using in SWT application,
141 | // need to defer initialization to after the application is started
142 | // to avoid org.eclipse.swt.SWTException: Invalid thread access
143 | // ExceptionDialogEx x = ExceptionDialogEx.getInstance();
144 |
145 | ExceptionDialogEx.getInstance().render(e);
146 | }
147 | }
148 |
149 | }
150 |
--------------------------------------------------------------------------------
/src/main/java/custom/swt/widgets/MultiSelectCombo.java:
--------------------------------------------------------------------------------
1 | package custom.swt.widgets;
2 |
3 | import java.awt.AWTException;
4 | import java.awt.Robot;
5 | import java.util.ArrayList;
6 | import java.util.Arrays;
7 |
8 | import org.eclipse.swt.SWT;
9 | import org.eclipse.swt.events.SelectionAdapter;
10 | import org.eclipse.swt.events.SelectionEvent;
11 | import org.eclipse.swt.graphics.Color;
12 | import org.eclipse.swt.graphics.Font;
13 | import org.eclipse.swt.graphics.Image;
14 | import org.eclipse.swt.graphics.Point;
15 | import org.eclipse.swt.layout.GridData;
16 | import org.eclipse.swt.layout.GridLayout;
17 | import org.eclipse.swt.widgets.Button;
18 | import org.eclipse.swt.widgets.Canvas;
19 | import org.eclipse.swt.widgets.Composite;
20 | import org.eclipse.swt.widgets.Control;
21 | import org.eclipse.swt.widgets.Event;
22 | import org.eclipse.swt.widgets.Listener;
23 | import org.eclipse.swt.widgets.Menu;
24 | import org.eclipse.swt.widgets.MenuItem;
25 | import org.eclipse.swt.widgets.Text;
26 |
27 | // origin: https://github.com/brotenet/swt-ext/blob/master/src/org/eclipse/swt/controls/collective/MultiSelectCombo.java
28 | public class MultiSelectCombo extends Canvas {
29 | private static final long serialVersionUID = 1L;
30 | private Text txtValues;
31 | private String[] items = new String[] {};
32 | private String separator = ",";
33 | private Image image = new Image(null, MultiSelectCombo.class
34 | .getResourceAsStream("/org/eclipse/swt/controls/collective/down.png"));
35 | private Button btnMenu;
36 |
37 | @SuppressWarnings("serial")
38 | public MultiSelectCombo(Composite parent, int style) {
39 | super(parent, style);
40 | GridLayout gridLayout = new GridLayout(2, false);
41 | gridLayout.marginHeight = 0;
42 | gridLayout.marginWidth = 0;
43 | setLayout(gridLayout);
44 |
45 | txtValues = new Text(this, SWT.BORDER);
46 | txtValues.setEditable(false);
47 | txtValues
48 | .setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1));
49 |
50 | btnMenu = new Button(this, SWT.NONE);
51 | btnMenu.addSelectionListener(new SelectionAdapter() {
52 | @Override
53 | public void widgetSelected(SelectionEvent event) {
54 | Point control_point = ((Control) event.widget).toDisplay(1,
55 | 1 + ((Control) event.widget).getBounds().height);
56 | Robot robot = null;
57 | try {
58 | robot = new Robot();
59 | } catch (AWTException exception) {
60 | exception.printStackTrace();
61 | }
62 | robot.mouseMove(control_point.x, control_point.y);
63 |
64 | Menu menu = new Menu(btnMenu);
65 | for (String item_text : getItems()) {
66 | MenuItem item = new MenuItem(menu, SWT.NONE);
67 | item.setText(item_text);
68 | item.addListener(SWT.Selection, new Listener() {
69 |
70 | @Override
71 | public void handleEvent(Event event) {
72 | if ((txtValues.getText().trim().length() > 0)
73 | & !txtValues.getText().trim().endsWith(getSeparator())) {
74 | txtValues.setText(txtValues.getText().trim() + getSeparator());
75 | }
76 | if (!txtValues.getText().contains(
77 | ((MenuItem) event.widget).getText() + getSeparator())) {
78 | txtValues.setText(txtValues.getText()
79 | + ((MenuItem) event.widget).getText() + getSeparator());
80 | } else {
81 | txtValues.setText(txtValues.getText().replace(
82 | ((MenuItem) event.widget).getText() + getSeparator(), ""));
83 | }
84 | if (txtValues.getText().endsWith(getSeparator())) {
85 | txtValues.setText(txtValues.getText().substring(0,
86 | txtValues.getText().length() - 1));
87 | }
88 | }
89 | });
90 | }
91 | menu.setVisible(true);
92 |
93 | }
94 | });
95 | btnMenu.setImage(image);
96 | }
97 |
98 | public String[] getItems() {
99 | return items;
100 | }
101 |
102 | public void setItems(String[] items) {
103 | ArrayList elements = new ArrayList(Arrays.asList(items));
104 | for (int i = 0; i < elements.size(); i++) {
105 | if (elements.get(i).trim().length() < 1) {
106 | elements.remove(i);
107 | }
108 | }
109 | this.items = elements.toArray(new String[elements.size()]);
110 | }
111 |
112 | public String getText() {
113 | return txtValues.getText();
114 | }
115 |
116 | public String getSeparator() {
117 | return separator;
118 | }
119 |
120 | public void setSeparator(String separator) {
121 | this.separator = separator;
122 | }
123 |
124 | @Override
125 | public void setForeground(Color color) {
126 | txtValues.setForeground(color);
127 | }
128 |
129 | @Override
130 | public Color getForeground() {
131 | return txtValues.getForeground();
132 | }
133 |
134 | public Image getImage() {
135 | return image;
136 | }
137 |
138 | public void setImage(Image image) {
139 | this.image = image;
140 | btnMenu.setImage(getImage());
141 | }
142 |
143 | public void setFont(Font font) {
144 | txtValues.setFont(font);
145 | }
146 |
147 | public Font getFont() {
148 | return txtValues.getFont();
149 | }
150 |
151 | public void setValues(String[] values) {
152 | txtValues.setText("");
153 | for (String value : values) {
154 | txtValues.setText(txtValues.getText() + value.trim() + getSeparator());
155 | }
156 | if (txtValues.getText().endsWith(getSeparator())) {
157 | txtValues.setText(
158 | txtValues.getText().substring(0, txtValues.getText().length() - 1));
159 | }
160 | }
161 |
162 | public String[] getValues() {
163 | return getText().split(getSeparator());
164 | }
165 | }
--------------------------------------------------------------------------------
/src/test/java/com/github/sergueik/swet/ExcelWriterTest.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 |
3 | /**
4 | * Copyright 2019 Serguei Kouzmine
5 | */
6 |
7 | import java.io.File;
8 | import java.io.FileInputStream;
9 | import java.io.FileOutputStream;
10 | import java.io.IOException;
11 |
12 | import java.nio.file.FileSystems;
13 | import java.nio.file.Files;
14 | import java.nio.file.LinkOption;
15 |
16 | import java.util.ArrayList;
17 | import java.util.List;
18 |
19 | import org.apache.poi.EncryptedDocumentException;
20 | import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
21 | import org.apache.poi.ss.usermodel.Cell;
22 | import org.apache.poi.ss.usermodel.Row;
23 | import org.apache.poi.ss.usermodel.Sheet;
24 | import org.apache.poi.ss.usermodel.Workbook;
25 | import org.apache.poi.ss.util.CellRangeAddress;
26 | import org.apache.poi.xssf.usermodel.XSSFWorkbook;
27 |
28 | import static org.hamcrest.MatcherAssert.assertThat;
29 | import static org.hamcrest.Matchers.greaterThan;
30 | import static org.hamcrest.CoreMatchers.equalTo;
31 | import static org.hamcrest.CoreMatchers.is;
32 |
33 | import org.junit.AfterClass;
34 | import org.junit.BeforeClass;
35 | import org.junit.Test;
36 |
37 | /**
38 | * Test for Selenium WebDriver Elementor Tool (SWET) Excel file writer
39 | * @author: Serguei Kouzmine (kouzmine_serguei@yahoo.com)
40 | */
41 |
42 | // see also the forum where few initially failing implementations were shown
43 | // http://software-testing.ru/forum/index.php?/topic/38373-apache-poi-dobavlenie-novoj-stranitcy-v-suschestvuiuschij-fa/
44 | // see also:
45 | // https://smearg.wordpress.com/2013/01/23/powershell-и-excel-часть-1-заполнение-таблицы/
46 | // https://powershell.org/forums/topic/dynamically-create-worksheets-in-excel/
47 | // http://ntcoder.com/bab/2018/01/18/powershell-tidbits-creating-excel-workbook-and-filling-out-data-into-worksheets/
48 | public class ExcelWriterTest {
49 | private static List dummyKeys = new ArrayList<>();
50 | private static List dummyValues = new ArrayList<>();
51 | private static String fileName = "dummy.xlsx";
52 | private static Workbook wb = null;
53 |
54 | @AfterClass
55 | public static void cleanup() throws IOException {
56 | File file = new File(fileName);
57 |
58 | if (!file.delete()) {
59 | throw new IOException("Delete " + file.getAbsolutePath() + "failed ");
60 | }
61 | }
62 |
63 | @Test
64 | public void supportedKeywordsContainsKeywordTableTest()
65 | throws IOException, EncryptedDocumentException, InvalidFormatException {
66 | dummyKeys.add("key 1");
67 | dummyKeys.add("key 2");
68 | dummyKeys.add("key 3");
69 | dummyKeys.add("key 4");
70 | dummyValues.add("10");
71 | dummyValues.add("20");
72 | dummyValues.add("30");
73 | dummyValues.add("40");
74 | addSheet("Sheet 1", dummyKeys, dummyValues, fileName);
75 | dummyKeys.clear();
76 | dummyValues.clear();
77 | dummyKeys.add("key 1");
78 | dummyKeys.add("key 2");
79 | dummyValues.add("50");
80 | dummyValues.add("60");
81 | addSheet("Sheet 2", dummyKeys, dummyValues, fileName);
82 |
83 | wb = new XSSFWorkbook(new FileInputStream(fileName));
84 | assertThat(wb.getNumberOfSheets(), greaterThan(1));
85 | wb.close();
86 | addSheet("Sheet 1", dummyKeys, dummyValues, fileName);
87 | // assertTrue(supportedKeywords.containsAll(keywordTable.keySet()));
88 | // assertFalse(keywordTable.keySet().containsAll(supportedKeywords));
89 | wb = new XSSFWorkbook(new FileInputStream(fileName));
90 | assertThat(wb.getNumberOfSheets(), equalTo(2));
91 | wb.close();
92 | }
93 |
94 | public static void addSheet(String sheetName, List keys,
95 | List values, String fileName)
96 | throws IOException, EncryptedDocumentException, InvalidFormatException {
97 |
98 | if (Files.exists(FileSystems.getDefault()
99 | .getPath(System.getProperty("user.dir"), fileName),
100 | new LinkOption[] { LinkOption.NOFOLLOW_LINKS })) {
101 |
102 | System.out.println("File exists: " + fileName);
103 | wb = new XSSFWorkbook(new FileInputStream(fileName));
104 | } else {
105 | wb = new XSSFWorkbook();
106 | }
107 | /*
108 | $idx = 1
109 | $o = new-object -ComObject 'excel.application'
110 | $o.visible = $true
111 | $excel = $o.workbooks.add()
112 | $excel.worksheets.item(1).delete()
113 |
114 | @('A1','B2','C3') | foreach-object {
115 | $group = $_
116 | $sheet = $excel.worksheets.item($idx)
117 | $sheet.name = $group
118 | $idx++
119 | $excel.worksheets.add($idx)
120 | }
121 |
122 |
123 | */
124 | Sheet sheet = wb.getSheet(sheetName) != null ? wb.getSheet(sheetName)
125 | : wb.createSheet(sheetName);
126 |
127 | Row r0 = sheet.createRow(0);
128 | Cell c0 = r0.createCell(0);
129 | c0.setCellValue("Key");
130 | Cell c1 = r0.createCell(1);
131 | c1.setCellValue("Value");
132 |
133 | Row a;
134 |
135 | List valuesInt = new ArrayList<>();
136 | for (String s : values)
137 | valuesInt.add(Integer.valueOf(s));
138 |
139 | for (int i = 0; i < keys.size(); i++) {
140 | a = sheet.createRow(i + 1);
141 | String name = keys.get(i);
142 | a.createCell(0).setCellValue(name);
143 | }
144 |
145 | for (int j = 0; j < valuesInt.size(); j++) {
146 | a = sheet.getRow(j + 1);
147 | Integer price = valuesInt.get(j);
148 | a.createCell(1).setCellValue(price);
149 | }
150 |
151 | sheet.setAutoFilter(CellRangeAddress.valueOf("A1:B" + (valuesInt.size())));
152 |
153 | FileOutputStream outputStream = new FileOutputStream(fileName);
154 |
155 | wb.write(outputStream);
156 | wb.close();
157 | outputStream.close();
158 | }
159 |
160 | }
161 |
--------------------------------------------------------------------------------
/src/main/java/com/github/sergueik/swet/ButtonSizeEx.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 |
3 | import org.eclipse.swt.SWT;
4 | import org.eclipse.swt.graphics.Point;
5 | import org.eclipse.swt.graphics.Rectangle;
6 | import org.eclipse.swt.internal.win32.OS;
7 | import org.eclipse.swt.layout.GridData;
8 | import org.eclipse.swt.layout.GridLayout;
9 | import org.eclipse.swt.widgets.Button;
10 | import org.eclipse.swt.widgets.Control;
11 | import org.eclipse.swt.widgets.Display;
12 | import org.eclipse.swt.widgets.Shell;
13 | import org.eclipse.swt.widgets.Text;
14 |
15 | import com.sun.jna.Pointer;
16 | import com.sun.jna.platform.win32.User32;
17 | // this import is windows-only
18 | import com.sun.jna.platform.win32.WinDef.HWND;
19 |
20 | // origin:
21 | // https://www.eclipsezone.com/servlet/JiveServlet/download/18120-65152-91995796-4076/ButtonSizeSnippet.java
22 | public class ButtonSizeEx {
23 | public static void main(String[] args) {
24 | final Display display = new Display();
25 | final Shell shell = new Shell(display);
26 | shell.setLayout(new GridLayout());
27 |
28 | GridLayout layout = new GridLayout(2, true);
29 | shell.setLayout(layout);
30 |
31 | Text txt = new Text(shell, SWT.BORDER | SWT.SINGLE);
32 | txt.setText("Text here");
33 | txt.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
34 |
35 | Button b = new Button(shell, SWT.PUSH);
36 | b.setText("B1");
37 | b.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
38 |
39 | txt = new Text(shell, SWT.BORDER | SWT.MULTI);
40 | txt.setText("something else here");
41 | GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
42 | data.horizontalSpan = 2;
43 | txt.setLayoutData(data);
44 |
45 | b = new Button(shell, SWT.PUSH);
46 | b.setText("B2 Wide Wide Wide Wide Button");
47 | b.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
48 |
49 | // this does not change the heght of the button
50 | b = new Button(shell, SWT.PUSH);
51 | // https://stackoverflow.com/questions/4547209/multi-line-button-text-in-swt-windowbuilder
52 | // b = new Button(shell, SWT.WRAP | SWT.PUSH);
53 |
54 | // alternatively
55 | final int style = OS.GetWindowLong(b.handle, OS.GWL_STYLE);
56 | OS.SetWindowLong(b.handle, OS.GWL_STYLE, style | OS.BS_MULTILINE);
57 |
58 | // https://markmail.org/thread/qlfoejwbue24rtne
59 |
60 | // unrelated
61 | // https://www.codota.com/code/java/methods/com.sun.jna.platform.win32.User32/GetWindowText
62 | int windowTextLength = 512;
63 | char[] windowText = new char[windowTextLength];
64 | User32 user32 = User32.INSTANCE;
65 | // the following code is windows-only
66 | HWND hwnd = new HWND();
67 | hwnd.setPointer(new Pointer(b.handle));
68 | user32.GetWindowText(hwnd, windowText, windowTextLength);
69 | System.err.println("GetWindow text: " + windowText.toString());
70 |
71 | b.setText("B3\nTall Button");
72 | b.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
73 | GridData buttonGridData = (GridData) b.getLayoutData();
74 | Point bSize = b.computeSize(SWT.DEFAULT, SWT.DEFAULT);
75 | buttonGridData.widthHint = bSize.x;
76 | buttonGridData.heightHint = (int) (bSize.y * 2.5);
77 | System.err.println(
78 | String.format("Manually adjusting size to: width: %d height: %d",
79 | buttonGridData.widthHint, buttonGridData.heightHint));
80 | b.setLayoutData(buttonGridData);
81 | // does not work.
82 | b.setSize(new Point(buttonGridData.widthHint, buttonGridData.heightHint));
83 | shell.pack();
84 |
85 | // NOTE: there appears to be no SetWindowText in user32
86 | // user32.SetWindowText(hwnd, titleText, windowTextMaxLength);
87 | // however
88 | // http://www.javased.com/?source_dir=file.monitor/com.sun.jna.examples.win32/src/com/sun/jna/examples/win32/User32.java
89 |
90 | // Get the Maximum height and width for all buttons
91 | Point y = new Point(0, 0);
92 | Control[] ca = shell.getChildren();
93 | for (int i = 0; i < ca.length; i++) {
94 | if (ca[i] instanceof Button) {
95 | Button _b = (Button) ca[i];
96 | _b.setData("name", ellipsisText(_b.getText(), 10));
97 | Point tmp = ((Button) ca[i]).computeSize(SWT.DEFAULT, SWT.DEFAULT);
98 | bSize.x = Math.max(bSize.x, tmp.x);
99 | bSize.y = Math.max(bSize.y, tmp.y);
100 | System.err.println(String.format("Measuring %s: width: %d height: %d",
101 | _b.getData("name"), tmp.x, tmp.y));
102 | }
103 | }
104 | System.err.println(String.format(
105 | "Computed the maximum height and width for all buttons: %d, %d",
106 | bSize.x, bSize.y));
107 | // Set the height and width for all buttons to the Maximum size
108 | // NOTE: hacking height
109 | bSize.y = (int) (1.7 * bSize.y);
110 | for (int i = 0; i < ca.length; i++) {
111 | if (ca[i] instanceof Button) {
112 | Button _b = (Button) ca[i];
113 | System.err.println("Resizing " + _b.getData("name"));
114 | GridData gData = (GridData) _b.getLayoutData();
115 | gData.widthHint = bSize.x;
116 | gData.heightHint = bSize.y;
117 | }
118 | }
119 |
120 | shell.pack();
121 | Rectangle screen = display.getMonitors()[0].getBounds();
122 | // center on the screen
123 | shell.setBounds(screen.width / 2 - 320, screen.height / 2 - 200, 640, 400);
124 | shell.open();
125 | while (!shell.isDisposed()) {
126 | if (!display.readAndDispatch())
127 | display.sleep();
128 | }
129 | display.dispose();
130 | }
131 |
132 | private static String ellipsisText(String text, int size) {
133 |
134 | String _text = text.replaceAll("\n", " ");
135 | return String.format("%s%s",
136 | (_text.length() > size) ? _text.substring(0, size) : _text,
137 | (OSUtils.getOsName().equals("windows")) ? "..." : "\u2026");
138 | }
139 |
140 | private static String ellipsisText(String text) {
141 | return ellipsisText(text, 10);
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/src/main/java/com/github/sergueik/swet/YamlHelper.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 | /**
3 | * Copyright 2014 - 2019 Serguei Kouzmine
4 | */
5 |
6 | import java.io.FileOutputStream;
7 | import java.io.IOException;
8 | import java.io.InputStream;
9 | import java.io.OutputStreamWriter;
10 | import java.io.Writer;
11 | import java.nio.file.Files;
12 | import java.nio.file.Paths;
13 |
14 | import java.text.DateFormat;
15 | import java.text.SimpleDateFormat;
16 | import java.util.Arrays;
17 | import java.util.Calendar;
18 | import java.util.Date;
19 | import java.util.GregorianCalendar;
20 | import java.util.HashMap;
21 | import java.util.HashSet;
22 | import java.util.Locale;
23 | import java.util.Map;
24 | import java.util.Set;
25 |
26 | import org.yaml.snakeyaml.DumperOptions;
27 | import org.yaml.snakeyaml.Yaml;
28 |
29 | // for generating the Keywords handled by KeywordLibrary
30 |
31 | // TODO: deploy to maven central
32 | // NOTE: need to package locally
33 | import com.github.sergueik.jprotractor.KeywordLibrary;
34 |
35 | /**
36 | * Common utilities for YAML configuration file for Selenium WebDriver Elementor Tool (SWET)
37 | * @author: Serguei Kouzmine (kouzmine_serguei@yahoo.com)
38 | */
39 |
40 | public class YamlHelper {
41 |
42 | private static DumperOptions options = new DumperOptions();
43 | private static Yaml yaml = null;
44 | private static Calendar calendar;
45 | private static String yamlFile = null;
46 | private static boolean debug = true;
47 |
48 | private static Map keywordTable = new HashMap<>();
49 |
50 | @SuppressWarnings("unchecked")
51 | public static Map> loadData(String fileName) {
52 | if (yaml == null) {
53 | options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
54 | options.setExplicitStart(true);
55 | yaml = new Yaml(options);
56 | }
57 |
58 | Map> data = new HashMap>();
59 | try (InputStream in = Files.newInputStream(Paths.get(fileName))) {
60 | // NOTE: unchecked conversion
61 | // required: Map>
62 | // found: capture#1 of ? extends java.util.Map
63 | data = yaml.loadAs(in, data.getClass());
64 | } catch (IOException e) {
65 | e.printStackTrace();
66 | }
67 | return data;
68 | }
69 |
70 | // NOTE: redundant, can one do generics here
71 | @SuppressWarnings("unchecked")
72 | public static Map loadHelp(String fileName) {
73 | if (yaml == null) {
74 | options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
75 | options.setExplicitStart(true);
76 | yaml = new Yaml(options);
77 | }
78 | Map data = new HashMap<>();
79 | try (InputStream in = Files.newInputStream(Paths.get(fileName))) {
80 | // NOTE: unchecked conversion
81 | // required: Map>
82 | // found: capture#1 of ? extends java.util.Map
83 | data = yaml.loadAs(in, data.getClass());
84 | } catch (IOException e) {
85 | e.printStackTrace();
86 | }
87 | return data;
88 | }
89 |
90 | public static Configuration loadConfiguration(String fileName) {
91 | if (yaml == null) {
92 | options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
93 | options.setExplicitStart(true);
94 | yaml = new Yaml(options);
95 | }
96 | Configuration config = null;
97 | try (InputStream in = Files.newInputStream(Paths.get(fileName))) {
98 | config = yaml.loadAs(in, com.github.sergueik.swet.Configuration.class);
99 | // TODO: better method naming
100 | YamlHelper.saveConfiguration(config);
101 |
102 | } catch (IOException e) {
103 | e.printStackTrace();
104 | }
105 | return config;
106 | }
107 |
108 | public static void printConfiguration(Object config) {
109 | saveConfiguration(config);
110 | }
111 |
112 | public static void saveConfiguration(Object config) {
113 | saveConfiguration(config, null);
114 | }
115 |
116 | @SuppressWarnings("deprecation")
117 | public static void saveConfiguration(Object config, String fileName) {
118 | if (yaml == null) {
119 | options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
120 | options.setExplicitStart(true);
121 | yaml = new Yaml(options);
122 | }
123 | /*
124 | String pattern = "yyyy-MM-dd";
125 | SimpleDateFormat format = new SimpleDateFormat(pattern);
126 | Date date = new Date();
127 | try {
128 | config.updated = format.parse(String.format("%4d-%2d-%2d", date.getYear(),
129 | date.getMonth(), date.getDay()));
130 | } catch (java.text.ParseException e) {
131 | config.updated = date;
132 | }
133 | */
134 | calendar = new GregorianCalendar();
135 | SimpleDateFormat dateFormat = new SimpleDateFormat(
136 | ((SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT,
137 | Locale.US)).toPattern().replaceAll("\\byy\\b", "yyyy")
138 | .replaceAll("\\bM\\b", "MM").replaceAll("\\bd\\b", "dd"));
139 |
140 | // System.err.println("Testing date format: " + dateFormat.toPattern());
141 |
142 | if (config instanceof com.github.sergueik.swet.Configuration) {
143 | try {
144 | System.err.println("Adding save date: "
145 | + dateFormat.parse(dateFormat.format(calendar.getTime())));
146 | ((Configuration) config).setUpdated(
147 | dateFormat.parse(dateFormat.format(calendar.getTime())));
148 | } catch (java.text.ParseException e) {
149 | System.err.println("Ignoring date parse exception: " + e.toString());
150 | ((com.github.sergueik.swet.Configuration) config)
151 | .setUpdated(new Date());
152 | }
153 | }
154 | if (fileName != null) {
155 | try {
156 | Writer out = new OutputStreamWriter(new FileOutputStream(fileName),
157 | "UTF8");
158 | System.err.println("Dumping the config to: " + fileName);
159 |
160 | yaml.dump(config, out);
161 | out.close();
162 | } catch (IOException e) {
163 | e.printStackTrace();
164 | }
165 | } else {
166 | System.err.println("Dumping the config: \n" + yaml.dump(config));
167 | }
168 | }
169 |
170 | }
--------------------------------------------------------------------------------
/src/main/java/com/github/sergueik/swet/RenderTemplate.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 | /**
3 | * Copyright 2014 - 2019,2021 Serguei Kouzmine
4 | */
5 |
6 | import java.util.ArrayList;
7 | import java.util.Formatter;
8 | import java.util.HashMap;
9 | import java.util.Iterator;
10 | import java.util.List;
11 | import java.util.Locale;
12 | import java.util.Map;
13 |
14 | import org.slf4j.Logger;
15 | import org.slf4j.LoggerFactory;
16 |
17 | import org.jtwig.JtwigModel;
18 | import org.jtwig.JtwigTemplate;
19 |
20 | /**
21 | * Generate source code from TestData hash of ElementData recorded page interaction and a
22 | * caller-provided twig template for Selenium WebDriver Elementor Tool (SWET)
23 | * @author: Serguei Kouzmine (kouzmine_serguei@yahoo.com)
24 | */
25 |
26 | public class RenderTemplate {
27 |
28 | private static String defaultTemplateFileName = "templates/core_selenium_java.twig";
29 | private static String defaultTemplateName = "Core Selenium Java";
30 | private String templateName = defaultTemplateName;
31 |
32 | private String templateAbsolutePath = "";
33 | private JtwigTemplate template = null;
34 | private static boolean debug = false;
35 |
36 | public static String getDefaultTemplateFileName() {
37 | return defaultTemplateFileName;
38 | }
39 |
40 | public void setTemplateName(String data) {
41 | utils.initializeLogger();
42 | logger.info("Initialized logger.");
43 | if (data != null) {
44 | this.templateName = data;
45 | }
46 | }
47 |
48 | public String getTemplateName() {
49 | return templateName;
50 | }
51 |
52 | public void setTemplateAbsolutePath(String data) {
53 | this.templateAbsolutePath = data;
54 | }
55 |
56 | public static void setDebug(boolean data) {
57 | RenderTemplate.debug = data;
58 | }
59 |
60 | public String getTemplateAbsolutePath() {
61 | return templateAbsolutePath;
62 | }
63 |
64 | private static Map createSampleElementData() {
65 | Map elementData = new HashMap<>();
66 | elementData.put("ElementId", "id");
67 | elementData.put("ElementCodeName",
68 | "name of the element, supplied during recoring");
69 | elementData.put("ElementText", "text of the element, when available");
70 | elementData.put("ElementXPath", "/html//img[1]");
71 | elementData.put("ElementVariable", "elementVariable");
72 | elementData.put("ElementCssSelector", "div#gbw > a.highlight");
73 | elementData.put("ElementSelectedBy", "ElementCssSelector");
74 | if (debug) {
75 | System.err.println("Sample Element data: " + elementData.toString());
76 | }
77 | return elementData;
78 | }
79 |
80 | private static Map> createSampleTestData() {
81 | final Map> testData = new HashMap<>();
82 | Map elementData = createSampleElementData();
83 | testData.put("1", elementData);
84 | if (debug) {
85 | // NOTE: http://mmahmoodict.wikidot.com/apache-commons-lang3-builder-example
86 | // for strongly-typed Element class
87 | System.err.println("Sample Test data: " + testData.toString());
88 | }
89 | return testData;
90 | }
91 |
92 | private static final Logger logger = LoggerFactory.getLogger(RenderTemplate.class);
93 |
94 | private static StringBuilder loggingSb = new StringBuilder();
95 | private static Formatter formatter = new Formatter(loggingSb, Locale.US);
96 |
97 | private static Utils utils = Utils.getInstance();
98 |
99 | public String renderTest() {
100 | Map> testData = new HashMap<>();
101 | testData = createSampleTestData();
102 | return renderTest(testData);
103 | }
104 |
105 | public String renderTest(Map> testData) {
106 | Iterator testDataKeys = testData.keySet().iterator();
107 | String stepId;
108 | List scripts = new ArrayList<>();
109 | while (testDataKeys.hasNext()) {
110 | stepId = testDataKeys.next();
111 | System.err.println("Rendering step " + stepId);
112 | Map elementData = testData.get(stepId);
113 | scripts.add(renderElement(elementData));
114 | }
115 | StringBuilder result = new StringBuilder();
116 | for (String line : scripts) {
117 | result.append(line);
118 | result.append("\n");
119 | }
120 | return result.toString();
121 | }
122 |
123 | private String renderElement(Map data) {
124 | // Cache template contents
125 | if (template == null) {
126 | if (this.templateAbsolutePath != "") {
127 | System.err.println(
128 | "Load tempate by absolute path: " + this.templateAbsolutePath);
129 | template = JtwigTemplate.fileTemplate(this.templateAbsolutePath);
130 | } else {
131 | System.err
132 | .println("Load tempate by resource path: " + this.templateName);
133 | template = JtwigTemplate.classpathTemplate(this.templateName);
134 | }
135 | }
136 | JtwigModel model = JtwigModel.newModel();
137 | if (debug) {
138 | System.err.println("The template: " + template.toString());
139 | }
140 |
141 | for (String key : data.keySet()) {
142 | if (debug) {
143 | System.err
144 | .println(String.format("\"%s\" = \"%s\"", key, data.get(key)));
145 | }
146 | model.with(key, data.get(key).replace("\"", "\\\""));
147 | }
148 | String output = template.render(model);
149 | if (debug) {
150 | System.err.println("renderElement : " + output);
151 | }
152 | return output;
153 | }
154 |
155 | @SuppressWarnings("unused")
156 | public static void main(String[] args) {
157 | RenderTemplate template = new RenderTemplate();
158 | RenderTemplate.setDebug(true);
159 | // TODO: tests for by name template discoveries
160 | if (args.length > 0) {
161 | template.setTemplateAbsolutePath(
162 | String.format("%s/%s", System.getProperty("user.dir"), args[0]));
163 | } else {
164 | template.setTemplateAbsolutePath(String.format("%s/src/main/resources/%s",
165 | System.getProperty("user.dir"),
166 | RenderTemplate.getDefaultTemplateFileName()));
167 | }
168 | String payload = template.renderTest();
169 | System.err.println("Rendered sample: " + payload);
170 | }
171 |
172 | }
173 |
--------------------------------------------------------------------------------
/src/main/java/com/github/sergueik/swet/User32WakeupTest.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 | /**
3 | * Copyright 2020 Serguei Kouzmine
4 | */
5 |
6 | import com.sun.jna.Native;
7 | import com.sun.jna.platform.win32.BaseTSD;
8 | import com.sun.jna.platform.win32.User32;
9 | import com.sun.jna.platform.win32.Kernel32;
10 | import com.sun.jna.platform.win32.WinNT.HANDLE;
11 | import com.sun.jna.ptr.IntByReference;
12 | import com.sun.jna.ptr.PointerByReference;
13 |
14 | import com.sun.jna.platform.win32.Win32Exception;
15 | import com.sun.jna.platform.win32.WinDef;
16 | import com.sun.jna.platform.win32.WinDef.LONG;
17 | import com.sun.jna.platform.win32.WinUser;
18 |
19 | // origin: https://stackoverflow.com/questions/28538234/sending-a-keyboard-input-with-java-jna-and-sendinput
20 | // see also: https://www.codeproject.com/Articles/5264831/How-to-Send-mouseInputs-using-Csharp
21 |
22 | public class User32WakeupTest {
23 |
24 | private static final int WM_MOUSEMOVE = 512;
25 | private static final int WM_LBUTTONDOWN = 513;
26 | // https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-lbuttonup
27 | private static final int WM_LBUTTONUP = 0x0202; // 514
28 | private static final int WM_RBUTTONDOWN = 516;
29 |
30 | // https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-keyup
31 | private static final int WM_KEYDOWN = 0x0100; // 514
32 | private static final int WM_KEYUP = 0x0101;
33 | // String to locate target window by title starting with (downcase)
34 | // like ubiquitous "Untitled - Notepad"
35 | private static String title = "untitled";
36 | private static String message = "wakeup neo";
37 | private static WinUser.INPUT input;
38 | private static WinDef.RECT rect;
39 | private static WinDef.POINT point;
40 | private static int delay = 100;
41 |
42 | public static void main(String[] args) {
43 | // inspect all windows
44 | User32.INSTANCE.EnumWindows((hWnd, data) -> {
45 | char[] name = new char[512];
46 |
47 | User32.INSTANCE.GetWindowText(hWnd, name, name.length);
48 | String windowTitle = Native.toString(name).toLowerCase();
49 | if (windowTitle.startsWith(title)) {
50 | System.err.println("Found target window: " + windowTitle);
51 | // Bring the window to the front
52 | User32.INSTANCE.SetForegroundWindow(hWnd);
53 |
54 | // instantiate keyboard input reference
55 | input = new WinUser.INPUT();
56 | input.type = new WinDef.DWORD(WinUser.INPUT.INPUT_KEYBOARD);
57 | input.input.setType("ki");
58 | // https://groups.google.com/d/msg/jna-users/NDBGwC1VZbU/cjYCQ1CjBwAJ
59 | input.input.ki.wScan = new WinDef.WORD(0);
60 | input.input.ki.time = new WinDef.DWORD(0);
61 | input.input.ki.dwExtraInfo = new BaseTSD.ULONG_PTR(0);
62 |
63 | char[] chars = message.toUpperCase().toCharArray();
64 | for (int index = 0; index < chars.length; index++) {
65 | char letter = chars[index];
66 |
67 | System.err.println(String.format("type: %c", letter));
68 | input.input.ki.wVk = new WinDef.WORD(letter);
69 | // 0x41 for 'a'etc.
70 | input.input.ki.dwFlags = new WinDef.DWORD(0);
71 | // keydown
72 |
73 | User32.INSTANCE.SendInput(new WinDef.DWORD(1),
74 | (WinUser.INPUT[]) input.toArray(1), input.size());
75 |
76 | // Release
77 | input.input.ki.wVk = new WinDef.WORD(letter);
78 | // keyup
79 | input.input.ki.dwFlags = new WinDef.DWORD(2);
80 |
81 | User32.INSTANCE.SendInput(new WinDef.DWORD(1),
82 | (WinUser.INPUT[]) input.toArray(1), input.size());
83 | try {
84 | Thread.sleep(delay);
85 | } catch (InterruptedException e) {
86 | }
87 | }
88 | // Prepare mouse button press event reference
89 | input = new WinUser.INPUT();
90 |
91 | input.type = new WinDef.DWORD(WinUser.INPUT.INPUT_MOUSE);
92 | input.input.setType("mi");
93 |
94 | // click on the center of the target window
95 | // https://www.codota.com/code/java/methods/com.sun.jna.platform.win32.User32/GetWindowRect
96 | rect = new WinDef.RECT();
97 | // https://www.codota.com/code/java/methods/com.sun.jna.platform.win32.Kernel32/GetLastError
98 | if (!User32.INSTANCE.GetWindowRect(hWnd, rect)) {
99 | throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
100 | }
101 |
102 | point = new WinDef.POINT();
103 | point.x = (rect.left + rect.right) / 2;
104 | point.y = (rect.top + rect.bottom) / 2;
105 | System.err.println(
106 | String.format("Drawing line from (%d, %d)", point.x, point.y));
107 | input.input.mi.dx = new WinDef.LONG(point.x);
108 | input.input.mi.dy = new WinDef.LONG(point.y);
109 | // https://www.programcreek.com/java-api-examples/?api=com.sun.jna.platform.win32.WinDef
110 | // https://www.programcreek.com/java-api-examples/?code=martin-lizner/trezor-ssh-agent/trezor-ssh-agent-master/src/main/java/com/trezoragent/mouselistener/JNIMouseHook.java
111 |
112 | User32.INSTANCE.SetCursorPos(point.x, point.y);
113 | input.input.mi.dwFlags = new WinDef.DWORD(
114 | WM_LBUTTONDOWN | WM_MOUSEMOVE);
115 |
116 | input.input.mi.time = new WinDef.DWORD(0);
117 | input.input.mi.dx = new WinDef.LONG(0);
118 | input.input.mi.dy = new WinDef.LONG(0);
119 | input.input.ki.dwExtraInfo = new BaseTSD.ULONG_PTR(0);
120 | User32.INSTANCE.SendInput(new WinDef.DWORD(1),
121 | (WinUser.INPUT[]) input.toArray(1), input.size());
122 |
123 | input.input.mi.dx = new WinDef.LONG(40);
124 | input.input.mi.dy = new WinDef.LONG(60);
125 | input.input.mi.dwFlags = new WinDef.DWORD(
126 | WM_LBUTTONDOWN | WM_MOUSEMOVE);
127 | User32.INSTANCE.SendInput(new WinDef.DWORD(1),
128 | (WinUser.INPUT[]) input.toArray(1), input.size());
129 | input.input.mi.dx = new WinDef.LONG(0);
130 | input.input.mi.dy = new WinDef.LONG(0);
131 | input.input.ki.dwExtraInfo = new BaseTSD.ULONG_PTR(0);
132 | input.input.mi.dwFlags = new WinDef.DWORD(WM_LBUTTONUP);
133 | User32.INSTANCE.SendInput(new WinDef.DWORD(1),
134 | (WinUser.INPUT[]) input.toArray(1), input.size());
135 |
136 | User32.INSTANCE.GetCursorPos(point);
137 | System.err.println(String.format("Releasing mouse button at (%d, %d)",
138 | point.x, point.y));
139 |
140 | return false; // exit enum windows loop
141 | }
142 |
143 | return true; // Keep searching
144 | }, null);
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/src/main/java/com/github/sergueik/swet/TemplateCache.java:
--------------------------------------------------------------------------------
1 | package com.github.sergueik.swet;
2 | /**
3 | * Copyright 2014 - 2018 Serguei Kouzmine
4 | */
5 |
6 | import java.io.File;
7 | import java.io.FileReader;
8 | import java.io.IOException;
9 | import java.io.InputStream;
10 | import java.net.URL;
11 | import java.security.CodeSource;
12 | import java.util.Collections;
13 | import java.util.HashMap;
14 | import java.util.Map;
15 | import java.util.regex.Matcher;
16 | import java.util.regex.Pattern;
17 | import java.util.zip.ZipEntry;
18 | import java.util.zip.ZipInputStream;
19 |
20 | import org.apache.commons.io.IOUtils;
21 |
22 | public class TemplateCache {
23 | private Utils utils = Utils.getInstance();
24 | private static Map cache = Collections
25 | .synchronizedMap(new HashMap());
26 |
27 | private static TemplateCache instance = new TemplateCache();
28 |
29 | private TemplateCache() {
30 | }
31 |
32 | public static TemplateCache getInstance() {
33 | return instance;
34 | }
35 |
36 | public static Map getCache() {
37 | return cache;
38 | }
39 |
40 | public void addItem(String tag, String path) {
41 | cache.put(tag, path);
42 | }
43 |
44 | public String getItem(String tag) {
45 | return cache.get(tag);
46 | }
47 |
48 | private String extractTag(String payload) {
49 |
50 | String templateTag = null;
51 |
52 | // find specially formatted twig comment in the template
53 | Matcher matcherTwigComment = Pattern
54 | .compile("\\{#(?:\\r?\\n)?(.*)(?:\\r?\\n)?#\\}", Pattern.MULTILINE)
55 | .matcher(payload);
56 | if (matcherTwigComment.find()) {
57 | String comment = matcherTwigComment.group(1);
58 | // extract template tag from the comment
59 | Matcher matcherTemplate = Pattern
60 | .compile("template: (.+)$", Pattern.MULTILINE).matcher(comment);
61 | if (matcherTemplate.find()) {
62 | templateTag = matcherTemplate.group(1);
63 | System.err
64 | .println(String.format("Discovered tag: \"%s\": ", templateTag));
65 | }
66 | }
67 | return templateTag;
68 | }
69 |
70 | public void fillTemplateDirectoryCache(final File dir, String note,
71 | Map templates) {
72 | FileReader fileReader = null;
73 | String contents = null;
74 | if (dir.listFiles().length == 0) {
75 | return;
76 | }
77 | for (final File fileEntry : dir.listFiles()) {
78 | contents = null;
79 | if (fileEntry.getName().endsWith(".twig")) {
80 | if (fileEntry.isFile()) {
81 | try {
82 | fileReader = new FileReader(fileEntry);
83 | char[] template = new char[(int) fileEntry.length()];
84 | fileReader.read(template);
85 | contents = new String(template);
86 | } catch (Exception e) {
87 | e.printStackTrace();
88 | } finally {
89 | if (fileReader != null) {
90 | try {
91 | fileReader.close();
92 | } catch (IOException e) {
93 | }
94 | }
95 | }
96 | }
97 | if (contents != null) {
98 |
99 | String templateName = extractTag(contents);
100 | if (templateName != null) {
101 | String templateLabel = String.format("%s (%s)", templateName,
102 | (note == null) ? "unknown" : note);
103 | String templateAbsolutePath = fileEntry.getAbsolutePath();
104 | System.out.println(String.format("Make option for \"%s\": \"%s\"",
105 | templateAbsolutePath, templateLabel));
106 | if (templates.containsKey(templateLabel)) {
107 | templates.replace(templateLabel, templateAbsolutePath);
108 | } else {
109 | templates.put(templateLabel, templateAbsolutePath);
110 | }
111 | System.out.println(String.format("Data for option \"%s\": \"%s\"",
112 | templateLabel, templates.get(templateLabel)));
113 | } else {
114 | System.out
115 | .println(String.format("no tag: %s", fileEntry.getName()));
116 | }
117 | }
118 | }
119 | }
120 | }
121 |
122 | public void fillEmbeddedTemplateCache() {
123 | // https://stackoverflow.com/questions/1429172/how-do-i-list-the-files-inside-a-jar-file
124 | CodeSource src = this.getClass().getProtectionDomain().getCodeSource();
125 | String note = "embedded";
126 | String templateTag = null;
127 | try {
128 | URL jar = src.getLocation();
129 | ZipInputStream zip = new ZipInputStream(jar.openStream());
130 | ZipEntry ze = null;
131 |
132 | while ((ze = zip.getNextEntry()) != null) {
133 | String templateResourcePath = ze.getName();
134 | if (templateResourcePath.startsWith("templates")
135 | && templateResourcePath.endsWith(".twig")) {
136 | InputStream inputStream = utils
137 | .getResourceStream(templateResourcePath);
138 | String templateContents = IOUtils.toString(inputStream, "UTF8");
139 |
140 | if (templateContents != null) {
141 |
142 | templateTag = extractTag(templateContents);
143 | if (templateTag != null) {
144 | String templateLabel = String.format("%s (embedded)",
145 | templateTag);
146 | System.err
147 | .println(String.format("Discovered template \"%s\": \"%s\": ",
148 | templateLabel, templateResourcePath));
149 | synchronized (cache) {
150 | if (cache.containsKey(templateLabel)) {
151 | cache.replace(templateLabel, templateResourcePath);
152 | } else {
153 | cache.put(templateLabel, templateResourcePath);
154 | }
155 | }
156 |
157 | }
158 | }
159 | IOUtils.closeQuietly(inputStream);
160 | }
161 | }
162 | } catch (Exception e) {
163 | e.printStackTrace();
164 | }
165 | }
166 |
167 | public String approxLookup(String templateTag) {
168 | Pattern pattern = Pattern.compile(Pattern.quote(templateTag),
169 | Pattern.CASE_INSENSITIVE);
170 | String matchedKey = null;
171 | for (String key : cache.keySet()) {
172 | Matcher matcher = pattern.matcher(key);
173 | if (matcher.find()) {
174 | matchedKey = key;
175 | }
176 | }
177 | return matchedKey;
178 | }
179 |
180 | public void clearCache() {
181 | cache.clear();
182 | }
183 |
184 | public Object removeEntry(String tag) {
185 | return cache.remove(tag);
186 | }
187 |
188 | public String toString() {
189 | StringBuffer result = new StringBuffer();
190 | for (String key : cache.keySet()) {
191 | result.append(key + ": " + cache.get(key));
192 | result.append("\n");
193 | }
194 | return result.toString();
195 | }
196 | }
197 |
--------------------------------------------------------------------------------
/run.cmd:
--------------------------------------------------------------------------------
1 | @echo OFF
2 | SETLOCAL
3 |
4 | set SKIP_TEST=tue
5 | if "%TOOLS_DIR%"=="" set TOOLS_DIR=c:\java
6 | if "%JAVA_VERSION%"=="" set JAVA_VERSION=1.8.0_101
7 | if "%JAVA_HOME%"=="" set JAVA_HOME=%TOOLS_DIR%\jdk%JAVA_VERSION%
8 | set JAVA_OPTS=-Xms256m -Xmx512m
9 | if "%MAVEN_VERSION%"=="" set MAVEN_VERSION=3.6.1
10 | if "%M2_HOME%"=="" set M2_HOME=%TOOLS_DIR%\apache-maven-%MAVEN_VERSION%
11 | if "%M2%"=="" set M2=%M2_HOME%\bin
12 | set MAVEN_OPTS=-Xms256m -Xmx512m
13 |
14 | REM Clear the environment entry that is created by git bash when starting cmd and ruins Maven 3.5.0 ANSI colors.
15 | REM see also: https://issues.apache.org/jira/browse/MNG-6282
16 | REM See also: https://stackoverflow.com/questions/43425304/how-to-customize-colors-in-maven-3-5-console-output
17 | set TERM=
18 |
19 | PATH=%JAVA_HOME%\bin;%M2%;%PATH%
20 |
21 | set DEBUG=true
22 | set TARGET=target
23 | set VERBOSE=true
24 |
25 | set APP_NAME=swet
26 | set APP_VERSION=0.0.10-SNAPSHOT
27 | REM if "%APP_PACKAGE%"=="" set APP_PACKAGE=com.github.sergueik.swet
28 | set DEFAULT_MAIN_CLASS=SimpleToolBarEx
29 | set SCM_CONNECTION=
30 |
31 | call :CALL_JAVASCRIPT /project/artifactId
32 | set APP_NAME=%VALUE%
33 |
34 | if NOT "%APP_PACKAGE%"=="" goto :app_package_set_explicitly
35 | call :CALL_JAVASCRIPT /project/groupId
36 | set APP_PACKAGE=%VALUE%
37 | :app_package_set_explicitly
38 |
39 | call :CALL_JAVASCRIPT /project/version
40 | set APP_VERSION=%VALUE%
41 |
42 | call :CALL_JAVASCRIPT /project/properties/mainClass
43 | set DEFAULT_MAIN_CLASS=%VALUE%
44 |
45 | call :CALL_JAVASCRIPT /project/scm/connection
46 | set SCM_CONNECTION=%VALUE:scm:git:=%
47 |
48 | set APP_JAR=%APP_NAME%.jar
49 |
50 | if /i "%SKIP_PACKAGE_VERSION%"=="true" goto :SKIP_PACKAGE_VERSION
51 | set APP_JAR=%APP_NAME%-%APP_VERSION%.jar
52 | :SKIP_PACKAGE_VERSION
53 |
54 | REM Testing skipping the default jar
55 | REM origin: https://stackoverflow.com/questions/12809559/remove-jar-created-by-default-in-maven
56 | REM see also: https://www.cyberforum.ru/javafx/thread3059580.html
57 | REM TODO: scan the "pom.xml" for the presence of the "finalName" property (custom configuration)
58 | set APP_JAR=SWTsample.jar
59 |
60 | if /i NOT "%VERBOSE%"=="true" goto :CONTINUE
61 |
62 | call :SHOW_VARIABLE APP_VERSION
63 | call :SHOW_VARIABLE APP_NAME
64 | call :SHOW_VARIABLE APP_PACKAGE
65 | call :SHOW_VARIABLE APP_JAR
66 | call :SHOW_VARIABLE DEFAULT_MAIN_CLASS
67 | call :SHOW_VARIABLE SCM_CONNECTION
68 |
69 | :CONTINUE
70 |
71 | CALL :SHOW_LAST_ARGUMENT %*
72 |
73 | set CLEAN=%1
74 |
75 | if /i "%CLEAN%" EQU "clean" shift
76 | if /i "%DEBUG%" EQU "true" (
77 | if /i "%CLEAN%" EQU "clean" echo >&2 CLEAN=%CLEAN%
78 | if "%ARGS_COUNT%" GEQ "1" echo >&2 ARG1=%1
79 | if "%ARGS_COUNT%" GEQ "2" echo >&2 ARG2=%2
80 | if "%ARGS_COUNT%" GEQ "3" echo >&2 ARG3=%3
81 | if "%ARGS_COUNT%" GEQ "4" echo >&2 ARG4=%4
82 | if "%ARGS_COUNT%" GEQ "5" echo >&2 ARG5=%5
83 | if "%ARGS_COUNT%" GEQ "6" echo >&2 ARG6=%6
84 | if "%ARGS_COUNT%" GEQ "7" echo >&2 ARG7=%7
85 | if "%ARGS_COUNT%" GEQ "8" echo >&2 ARG8=%8
86 | if "%ARGS_COUNT%" GEQ "9" echo >&2 ARG9=%9
87 | )
88 |
89 | set MAIN_CLASS=%~1
90 | if NOT "%MAIN_CLASS%" == "" shift
91 | if "%MAIN_CLASS%"=="" set MAIN_CLASS=%DEFAULT_MAIN_CLASS%
92 |
93 | set APP_HOME=%CD:\=/%
94 | REM omit the extension - on different Windows
95 | REM will be mvn.bat or mvn.cmd
96 |
97 | if "%SKIP_TEST%"=="" (
98 | REM Test
99 | call mvn test 2 > NUL
100 | ) else (
101 | if /i NOT "%SKIP_BUILD%" == "true" (
102 | REM Compile
103 |
104 | if /i "%CLEAN%" EQU "clean" (
105 | ECHO "DO CLEAN"
106 | call mvn -Dmaven.test.skip=true clean package install
107 | ) else (
108 | ECHO "DO INCREMENTAL"
109 |
110 | call mvn -Dmaven.test.skip=true package install
111 | )
112 | )
113 | )
114 | REM Run
115 | REM NOTE: shift does not modify the %*
116 | REM The log4j configuration argument seems to be ignored
117 | REM -Dlog4j.configuration=file:///%APP_HOME%/src/main/resources/log4j.properties ^
118 | set COMMAND=^
119 | java ^
120 | -cp %TARGET%\%APP_JAR%;%TARGET%\lib\* ^
121 | %APP_PACKAGE%.%MAIN_CLASS% ^
122 | %1 %2 %3 %4 %5 %6 %7 %8 %9
123 | echo %COMMAND%>&2
124 | %COMMAND%
125 | ENDLOCAL
126 | exit /b
127 |
128 | :CALL_JAVASCRIPT
129 |
130 | REM This script extracts project g.a.v a custom property from pom.xml using mshta.exe and DOM selectSingleNode method
131 | set "SCRIPT=javascript:{"
132 | set "SCRIPT=%SCRIPT% var fso = new ActiveXObject('Scripting.FileSystemObject');"
133 | set "SCRIPT=%SCRIPT% var out = fso.GetStandardStream(1);"
134 | set "SCRIPT=%SCRIPT% var fh = fso.OpenTextFile('pom.xml', 1, true);"
135 | set "SCRIPT=%SCRIPT% var xd = new ActiveXObject('Msxml2.DOMDocument');"
136 | set "SCRIPT=%SCRIPT% xd.async = false;"
137 | set "SCRIPT=%SCRIPT% data = fh.ReadAll();"
138 | set "SCRIPT=%SCRIPT% xd.loadXML(data);"
139 | set "SCRIPT=%SCRIPT% root = xd.documentElement;"
140 | set "SCRIPT=%SCRIPT% var xpath = '%~1';"
141 | set "SCRIPT=%SCRIPT% var xmlnode = root.selectSingleNode( xpath);"
142 | set "SCRIPT=%SCRIPT% if (xmlnode != null) {"
143 | set "SCRIPT=%SCRIPT% out.Write(xpath + '=' + xmlnode.text);"
144 | set "SCRIPT=%SCRIPT% } else {"
145 | set "SCRIPT=%SCRIPT% out.Write('ERR');"
146 | set "SCRIPT=%SCRIPT% }"
147 | set "SCRIPT=%SCRIPT% close();}"
148 |
149 | for /F "tokens=2 delims==" %%_ in ('mshta.exe "%SCRIPT%" 1 ^| more') do set VALUE=%%_
150 | ENDLOCAL
151 | exit /b
152 |
153 |
154 | :SHOW_VARIABLE
155 | SETLOCAL ENABLEDELAYEDEXPANSION
156 | set VAR=%1
157 | if /i "%DEBUG%"=="true" echo>&2 VAR=!VAR!
158 | set RESULT=!VAR!
159 | call :SHOW_VARIABLE_VALUE !%VAR%!
160 | set RESULT=!RESULT!="!DATA!"
161 | echo>&2 !RESULT!
162 | ENDLOCAL
163 | goto :EOF
164 |
165 | :SHOW_VARIABLE_VALUE
166 | set VAL=%1
167 | if /i "%DEBUG%"=="true" echo>&2 %1
168 | set DATA=%VAL%
169 | if /i "%DEBUG%"=="true" echo>&2 VALUE=%VAL%
170 | goto :EOF
171 |
172 |
173 | :SHOW_LAST_ARGUMENT
174 | REM https://stackoverflow.com/questions/1291941/batch-files-number-of-command-line-arguments
175 | set /A ARGS_COUNT=0
176 | for %%_ in (%*) DO SET /A ARGS_COUNT+=1
177 | if /i "%DEBUG%"=="true" echo>&2 The number of arguments is %ARGS_COUNT%
178 | REM the following does not work
179 | SETLOCAL ENABLEDELAYEDEXPANSION
180 | for /F "tokens=*" %%_ in ('echo %%!ARGS_COUNT!') DO set P=%%_
181 | if /i "%DEBUG%"=="true" echo P=%P%
182 | call :SHOW_VARIABLE_VALUE !P!
183 | set CLEAN=%VALUE%
184 | REM the value disappears after ENDLOCAL
185 | ENDLOCAL
186 | goto :EOF
187 |
--------------------------------------------------------------------------------
/src/main/java/custom/swt/widgets/SWTUtil.java:
--------------------------------------------------------------------------------
1 | package custom.swt.widgets;
2 |
3 | import org.eclipse.swt.SWT;
4 | import org.eclipse.swt.SWTException;
5 | import org.eclipse.swt.events.ShellEvent;
6 | import org.eclipse.swt.events.ShellListener;
7 | import org.eclipse.swt.graphics.Point;
8 | import org.eclipse.swt.graphics.Rectangle;
9 | import org.eclipse.swt.widgets.Composite;
10 | import org.eclipse.swt.widgets.Control;
11 | import org.eclipse.swt.widgets.Display;
12 | import org.eclipse.swt.widgets.Monitor;
13 | import org.eclipse.swt.widgets.Shell;
14 |
15 | public class SWTUtil {
16 |
17 | // ==[ Event Loop
18 | // ]==================================================================================
19 |
20 | // Main Event Loop for an application that terminates once the associated
21 | // Display is disposed
22 | public static void eventLoop() {
23 | Display dsp = getDisplay();
24 | while (!dsp.isDisposed()) {
25 | if (!dsp.readAndDispatch())
26 | dsp.sleep();
27 | }
28 | }
29 |
30 | // Event Loop that terminates once the given shell is disposed (and optionally
31 | // also disposes the display)
32 | public static void eventLoop(Shell shell, boolean dispose) {
33 | Display dsp = getDisplay();
34 | while (!shell.isDisposed())
35 | if (!dsp.readAndDispatch())
36 | dsp.sleep();
37 | if (dispose)
38 | dsp.dispose();
39 | }
40 |
41 | // Event Loop that terminates the application if the given shell is disposed
42 | public static void eventLoop(Shell shell) {
43 | eventLoop(shell, true);
44 | }
45 |
46 | // Temporary Event Loop for Dialogs... doesn't dispose the entire application
47 | // once shell closes
48 | public static void dialogLoop(Shell shell) {
49 | eventLoop(shell, false);
50 | }
51 |
52 | ///// Private helper
53 |
54 | // Get current display ( throw an exception if the current thread is not the
55 | // UI thread )
56 | private static Display getDisplay() {
57 | Display dsp = Display.getCurrent();
58 | if (dsp == null)
59 | new SWTException(SWT.ERROR_THREAD_INVALID_ACCESS);
60 | return dsp;
61 | }
62 |
63 | // ==[ Center Shell
64 | // ]================================================================================
65 |
66 | // Set shell dimensions and center the shell on the current monitor
67 | public static void center(Shell shell, int width, int height) {
68 | shell.setSize(width, height);
69 | center(shell);
70 | }
71 |
72 | // Set shell dimensions and center the shell over its parent
73 | public static void center(Shell parent, Shell child, int width, int height) {
74 | child.setSize(width, height);
75 | center(parent, child);
76 | }
77 |
78 | // Center the shell on the current monitor
79 | public static void center(Shell shell) {
80 | center(shell, 0.5, 0.5);
81 | }
82 |
83 | public static void center(Shell shell, double xfrac, double yfrac) {
84 | Display dsp = shell.getDisplay();
85 | Rectangle monitorBounds = getCurrentMonitorBounds(dsp);
86 | center(monitorBounds, shell, xfrac, yfrac);
87 | }
88 |
89 | // Center the shell over its parent
90 | public static void center(Composite parent, Shell child) {
91 | center(parent, child, 0.5, 0.5);
92 | }
93 |
94 | public static void center(Composite parent, Shell child, double xfrac,
95 | double yfrac) {
96 | Display dsp = child.getDisplay();
97 | Rectangle region = parent.isVisible() ? parent.getBounds()
98 | : getCurrentMonitorBounds(dsp);
99 | center(region, child, xfrac, yfrac);
100 | }
101 |
102 | ///// Private Helper
103 |
104 | // Center the shell over the given region
105 | private static void center(Rectangle region, Shell shell, double xfrac,
106 | double yfrac) {
107 | Rectangle s_bounds = shell.getBounds();
108 |
109 | // System.out.println("Center: " + s_bounds);
110 | // System.out.println("Over: " + region);
111 |
112 | // int x = region.x + (region.width - s_bounds.width) / 2;
113 | // int y = region.y + (region.height - s_bounds.height) / 2;
114 |
115 | int x = region.x
116 | + (int) Math.round((region.width - s_bounds.width) * xfrac);
117 | int y = region.y
118 | + (int) Math.round((region.height - s_bounds.height) * yfrac);
119 |
120 | shell.setLocation(x, y);
121 | }
122 |
123 | // Retrieve the current monitor (via the mouse cursor location)
124 | private static Rectangle getCurrentMonitorBounds(Display dsp) {
125 | Monitor monitor = dsp.getPrimaryMonitor();
126 |
127 | // Choose current Monitor
128 | Point cursor = dsp.getCursorLocation();
129 | Monitor[] monitors = dsp.getMonitors();
130 | for (Monitor mon : monitors) {
131 | Rectangle mbounds = mon.getBounds();
132 | if (mbounds.contains(cursor)) {
133 | monitor = mon;
134 | break;
135 | }
136 | }
137 |
138 | return monitor.getBounds();
139 | }
140 |
141 | // ==[ Pack Widget in only one dimension
142 | // ]===========================================================
143 |
144 | public static void packWidth(Control control) {
145 | Point prefSize = control.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
146 | Point currSize = control.getSize();
147 | control.setSize(prefSize.x, currSize.y);
148 | }
149 |
150 | public static void packHeight(Control control) {
151 | Point prefSize = control.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
152 | Point currSize = control.getSize();
153 | control.setSize(currSize.x, prefSize.y);
154 | }
155 |
156 | public static void pack(Control control, int minWidth, int minHeight) {
157 | Point prefSize = control.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
158 | if (prefSize.x < minWidth)
159 | prefSize.x = minWidth;
160 | if (prefSize.y < minHeight)
161 | prefSize.y = minHeight;
162 | control.setSize(prefSize.x, prefSize.y);
163 | }
164 |
165 | // ==[ Automatically Dispose App on Shell Exit
166 | // ]=====================================================
167 |
168 | // Dispose the associated Display when the given shell is closed (adds a
169 | // ShellListener)
170 | public static void exitOnClose(Shell shell) {
171 | shell.addShellListener(new ShellListener() {
172 | @Override
173 | public void shellActivated(ShellEvent event) {
174 | }
175 |
176 | @Override
177 | public void shellClosed(ShellEvent event) {
178 | Display dsp = shell.getDisplay();
179 | if (dsp != null)
180 | dsp.dispose();
181 | }
182 |
183 | @Override
184 | public void shellDeactivated(ShellEvent arg0) {
185 | }
186 |
187 | @Override
188 | public void shellDeiconified(ShellEvent arg0) {
189 | }
190 |
191 | @Override
192 | public void shellIconified(ShellEvent arg0) {
193 | }
194 |
195 | });
196 | }
197 | }
198 |
--------------------------------------------------------------------------------
/run2.cmd:
--------------------------------------------------------------------------------
1 | @echo OFF
2 | SETLOCAL
3 |
4 | set SKIP_TEST=tue
5 | if "%TOOLS_DIR%"=="" set TOOLS_DIR=c:\java
6 | if "%JAVA_VERSION%"=="" set JAVA_VERSION=1.8.0_101
7 | if "%JAVA_HOME%"=="" set JAVA_HOME=%TOOLS_DIR%\jdk%JAVA_VERSION%
8 | set JAVA_OPTS=-Xms256m -Xmx512m
9 | if "%MAVEN_VERSION%"=="" set MAVEN_VERSION=3.6.1
10 | if "%M2_HOME%"=="" set M2_HOME=%TOOLS_DIR%\apache-maven-%MAVEN_VERSION%
11 | if "%M2%"=="" set M2=%M2_HOME%\bin
12 | set MAVEN_OPTS=-Xms256m -Xmx512m
13 |
14 | REM Clear the environment entry that is created by git bash when starting cmd and ruins Maven 3.5.0 ANSI colors.
15 | REM see also: https://issues.apache.org/jira/browse/MNG-6282
16 | REM See also: https://stackoverflow.com/questions/43425304/how-to-customize-colors-in-maven-3-5-console-output
17 | set TERM=
18 |
19 | PATH=%JAVA_HOME%\bin;%M2%;%PATH%
20 |
21 | set DEBUG=true
22 | set TARGET=target
23 | set VERBOSE=true
24 |
25 | set APP_NAME=swet
26 | set APP_VERSION=0.0.10-SNAPSHOT
27 | REM if "%APP_PACKAGE%"=="" set APP_PACKAGE=com.github.sergueik.swet
28 | set DEFAULT_MAIN_CLASS=SimpleToolBarEx
29 | set SCM_CONNECTION=
30 |
31 | call :CALL_JAVASCRIPT /project/artifactId VALUE1
32 | set APP_NAME=%VALUE1%
33 |
34 | if NOT "%APP_PACKAGE%"=="" goto :app_package_set_explicitly
35 | call :CALL_JAVASCRIPT /project/groupId VALUE2
36 | set APP_PACKAGE=%VALUE2%
37 | :app_package_set_explicitly
38 |
39 | call :CALL_JAVASCRIPT /project/version VALUE3
40 | set APP_VERSION=%VALUE3%
41 |
42 | call :CALL_JAVASCRIPT /project/properties/mainClass VALUE4
43 | set DEFAULT_MAIN_CLASS=%VALUE4%
44 |
45 | call :CALL_JAVASCRIPT /project/scm/connection VALUE5
46 | set SCM_CONNECTION=%VALUE5:scm:git:=%
47 |
48 |
49 | call :CALL_JAVASCRIPT /project/build/plugins/plugin/configuration/finalName VALUE6
50 | set FINALNAME=%VALUE6:"=%
51 | REM TODO: detect variable interpolation and give up
52 |
53 | set APP_JAR=%APP_NAME%.jar
54 |
55 | if /i "%SKIP_PACKAGE_VERSION%"=="true" goto :SKIP_PACKAGE_VERSION
56 | set APP_JAR=%APP_NAME%-%APP_VERSION%.jar
57 | :SKIP_PACKAGE_VERSION
58 |
59 | REM Testing skipping the default jar
60 | REM origin: https://stackoverflow.com/questions/12809559/remove-jar-created-by-default-in-maven
61 | REM see also: https://www.cyberforum.ru/javafx/thread3059580.html
62 | REM TODO: scan the "pom.xml" for the presence of the "finalName" property (custom configuration)
63 | if NOT "%FINALNAME%" == "" set APP_JAR=%FINALNAME%.jar
64 |
65 | if /i NOT "%VERBOSE%"=="true" goto :CONTINUE
66 |
67 | call :SHOW_VARIABLE APP_VERSION
68 | call :SHOW_VARIABLE APP_NAME
69 | call :SHOW_VARIABLE APP_PACKAGE
70 | call :SHOW_VARIABLE APP_JAR
71 | call :SHOW_VARIABLE DEFAULT_MAIN_CLASS
72 | call :SHOW_VARIABLE SCM_CONNECTION
73 | call :SHOW_VARIABLE FINALNAME
74 |
75 | :CONTINUE
76 |
77 | CALL :SHOW_LAST_ARGUMENT %*
78 |
79 | set CLEAN=%1
80 |
81 | if /i "%CLEAN%" EQU "clean" shift
82 | if /i "%DEBUG%" EQU "true" (
83 | if /i "%CLEAN%" EQU "clean" echo >&2 CLEAN=%CLEAN%
84 | if "%ARGS_COUNT%" GEQ "1" echo >&2 ARG1=%1
85 | if "%ARGS_COUNT%" GEQ "2" echo >&2 ARG2=%2
86 | if "%ARGS_COUNT%" GEQ "3" echo >&2 ARG3=%3
87 | if "%ARGS_COUNT%" GEQ "4" echo >&2 ARG4=%4
88 | if "%ARGS_COUNT%" GEQ "5" echo >&2 ARG5=%5
89 | if "%ARGS_COUNT%" GEQ "6" echo >&2 ARG6=%6
90 | if "%ARGS_COUNT%" GEQ "7" echo >&2 ARG7=%7
91 | if "%ARGS_COUNT%" GEQ "8" echo >&2 ARG8=%8
92 | if "%ARGS_COUNT%" GEQ "9" echo >&2 ARG9=%9
93 | )
94 |
95 | set MAIN_CLASS=%~1
96 | if NOT "%MAIN_CLASS%" == "" shift
97 | if "%MAIN_CLASS%"=="" set MAIN_CLASS=%DEFAULT_MAIN_CLASS%
98 |
99 | set APP_HOME=%CD:\=/%
100 | REM omit the extension - on different Windows
101 | REM will be mvn.bat or mvn.cmd
102 |
103 | if "%SKIP_TEST%"=="" (
104 | REM Test
105 | call mvn test 2 > NUL
106 | ) else (
107 | if /i NOT "%SKIP_BUILD%" == "true" (
108 | REM Compile
109 |
110 | if /i "%CLEAN%" EQU "clean" (
111 | ECHO "DO CLEAN"
112 | call mvn -Dmaven.test.skip=true clean package install
113 | ) else (
114 | ECHO "DO INCREMENTAL"
115 |
116 | call mvn -Dmaven.test.skip=true package install
117 | )
118 | )
119 | )
120 | REM Run
121 | REM NOTE: shift does not modify the %*
122 | REM The log4j configuration argument seems to be ignored
123 | REM -Dlog4j.configuration=file:///%APP_HOME%/src/main/resources/log4j.properties ^
124 | set COMMAND=^
125 | java ^
126 | -cp %TARGET%\%APP_JAR%;%TARGET%\lib\* ^
127 | %APP_PACKAGE%.%MAIN_CLASS% ^
128 | %1 %2 %3 %4 %5 %6 %7 %8 %9
129 | echo %COMMAND%>&2
130 | %COMMAND%
131 | ENDLOCAL
132 | exit /b
133 |
134 | :CALL_JAVASCRIPT
135 |
136 | REM This script extracts project g.a.v a custom property from pom.xml using mshta.exe and DOM selectSingleNode method
137 | set "SCRIPT=javascript:{"
138 | set "SCRIPT=%SCRIPT% var fso = new ActiveXObject('Scripting.FileSystemObject');"
139 | set "SCRIPT=%SCRIPT% var out = fso.GetStandardStream(1);"
140 | set "SCRIPT=%SCRIPT% var fh = fso.OpenTextFile('pom.xml', 1, true);"
141 | set "SCRIPT=%SCRIPT% var xd = new ActiveXObject('Msxml2.DOMDocument');"
142 | set "SCRIPT=%SCRIPT% xd.async = false;"
143 | set "SCRIPT=%SCRIPT% data = fh.ReadAll();"
144 | set "SCRIPT=%SCRIPT% xd.loadXML(data);"
145 | set "SCRIPT=%SCRIPT% root = xd.documentElement;"
146 | set "SCRIPT=%SCRIPT% var xpath = '%~1';"
147 | set "SCRIPT=%SCRIPT% var xmlnode = root.selectSingleNode( xpath);"
148 | set "SCRIPT=%SCRIPT% if (xmlnode != null) {"
149 | set "SCRIPT=%SCRIPT% out.Write(xpath + '=' + xmlnode.text);"
150 | set "SCRIPT=%SCRIPT% } else {"
151 | set "SCRIPT=%SCRIPT% out.Write('ERR');"
152 | set "SCRIPT=%SCRIPT% }"
153 | set "SCRIPT=%SCRIPT% close();}"
154 |
155 | for /F "tokens=2 delims==" %%_ in ('mshta.exe "%SCRIPT%" 1 ^| more') do set "%2=%%_"
156 | ENDLOCAL
157 | exit /b
158 |
159 |
160 | :SHOW_VARIABLE
161 | SETLOCAL ENABLEDELAYEDEXPANSION
162 | set VAR=%1
163 | if /i "%DEBUG%"=="true" echo>&2 VAR=!VAR!
164 | set RESULT=!VAR!
165 | call :SHOW_VARIABLE_VALUE !%VAR%!
166 | set RESULT=!RESULT!="!DATA!"
167 | echo>&2 !RESULT!
168 | ENDLOCAL
169 | goto :EOF
170 |
171 | :SHOW_VARIABLE_VALUE
172 | set VAL=%1
173 | if /i "%DEBUG%"=="true" echo>&2 %1
174 | set DATA=%VAL%
175 | if /i "%DEBUG%"=="true" echo>&2 VALUE=%VAL%
176 | goto :EOF
177 |
178 |
179 | :SHOW_LAST_ARGUMENT
180 | REM https://stackoverflow.com/questions/1291941/batch-files-number-of-command-line-arguments
181 | set /A ARGS_COUNT=0
182 | for %%_ in (%*) DO SET /A ARGS_COUNT+=1
183 | if /i "%DEBUG%"=="true" echo>&2 The number of arguments is %ARGS_COUNT%
184 | REM the following does not work
185 | SETLOCAL ENABLEDELAYEDEXPANSION
186 | for /F "tokens=*" %%_ in ('echo %%!ARGS_COUNT!') DO set P=%%_
187 | if /i "%DEBUG%"=="true" echo P=%P%
188 | call :SHOW_VARIABLE_VALUE !P!
189 | set CLEAN=%VALUE%
190 | REM the value disappears after ENDLOCAL
191 | ENDLOCAL
192 | goto :EOF
193 |
--------------------------------------------------------------------------------