Skip to content

Commit 3ac37b3

Browse files
committed
Merge origin/feature/selenium4 into feature/selenium4
Conflicts: source/src/main/java/org/cerberus/core/engine/execution/impl/RobotServerService.java source/src/main/java/org/cerberus/core/service/robotextension/impl/SikuliService.java source/src/main/resources/documentation/D2/include/en/changelog_4.20_en.adoc
2 parents c0809f7 + 84700ab commit 3ac37b3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+3651
-94
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
/.idea/
2020
*.mwb.beforefix
2121
*.DS_Store
22+
nb-configuration.xml
2223

2324
source/\.idea/
2425

source/src/main/java/org/cerberus/core/engine/execution/impl/RobotServerService.java

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -658,45 +658,49 @@ && isNotAlreadyDefined(caps, "appWaitActivity"))) {
658658
// Setting specific capabilities of external cloud providers.
659659
switch (tCExecution.getRobotProvider()) {
660660
case TestCaseExecution.ROBOTPROVIDER_BROWSERSTACK:
661-
if (!StringUtil.isEmptyOrNull(tCExecution.getTag()) && isNotAlreadyDefined(caps, "build")) {
662-
cloudOptions.put("build", tCExecution.getTag());
661+
Map<String, Object> browserstackOptions = new HashMap<>();
662+
if (!StringUtil.isEmptyOrNull(tCExecution.getTag()) && isNotAlreadyDefined(caps, "buildName")) {
663+
browserstackOptions.put("buildName", tCExecution.getTag());
663664
}
664665

665-
if (isNotAlreadyDefined(caps, "project")) {
666-
cloudOptions.put("project", tCExecution.getApplication());
666+
if (isNotAlreadyDefined(caps, "projectName")) {
667+
browserstackOptions.put("projectName", tCExecution.getApplication());
667668
} else {
668-
cloudOptions.put("project", caps.getCapability("project"));
669+
browserstackOptions.put("projectName", caps.getCapability("projectName"));
669670
}
670671

671-
if (isNotAlreadyDefined(caps, "name")) {
672+
if (isNotAlreadyDefined(caps, "sessionName")) {
672673
String externalExeName = parameterService.getParameterStringByKey("cerberus_browserstack_defaultexename", tCExecution.getSystem(), "Exe : %EXEID%");
673674
externalExeName = externalExeName.replace("%EXEID%", String.valueOf(tCExecution.getId()));
674675
externalExeName = externalExeName.replace("%TESTFOLDER%", String.valueOf(tCExecution.getTest()));
675676
externalExeName = externalExeName.replace("%TESTID%", String.valueOf(tCExecution.getTestCase()));
676677
externalExeName = externalExeName.replace("%TESTDESCRIPTION%", String.valueOf(tCExecution.getDescription()));
677-
cloudOptions.put("name", externalExeName);
678+
browserstackOptions.put("sessionName", externalExeName);
678679
}
679680

680681
if (tCExecution.getVerbose() >= 2) {
681-
if (isNotAlreadyDefined(caps, "browserstack.debug")) {
682-
cloudOptions.put("browserstack.debug", true);
682+
if (isNotAlreadyDefined(caps, "debug")) {
683+
browserstackOptions.put("debug", true);
683684
}
684-
if (isNotAlreadyDefined(caps, "browserstack.console")) {
685-
cloudOptions.put("browserstack.console", "warnings");
685+
if (isNotAlreadyDefined(caps, "consoleLogs")) {
686+
browserstackOptions.put("consoleLogs", "warnings");
686687
}
687-
if (isNotAlreadyDefined(caps, "browserstack.networkLogs")) {
688-
cloudOptions.put("browserstack.networkLogs", true);
688+
if (isNotAlreadyDefined(caps, "networkLogs")) {
689+
browserstackOptions.put("networkLogs", true);
689690
}
690691
}
691692

692693
//Create or override these capabilities if proxy required.
693694
if (StringUtil.parseBoolean(tCExecution.getRobotExecutorObj().getExecutorProxyType())) {
694-
cloudOptions.put("browserstack.local", true);
695-
cloudOptions.put("browserstack.user", tCExecution.getRobotExecutorObj().getHostUser());
696-
cloudOptions.put("browserstack.key", tCExecution.getRobotExecutorObj().getHostPassword());
697-
cloudOptions.put("browserstack.localIdentifier", tCExecution.getExecutionUUID());
695+
browserstackOptions.put("local", true);
696+
browserstackOptions.put("userName", tCExecution.getRobotExecutorObj().getHostUser());
697+
browserstackOptions.put("accessKey", tCExecution.getRobotExecutorObj().getHostPassword());
698+
browserstackOptions.put("localIdentifier", tCExecution.getExecutionUUID());
698699
}
700+
701+
caps.setCapability("bstack:options", browserstackOptions);
699702
break;
703+
700704
case TestCaseExecution.ROBOTPROVIDER_LAMBDATEST:
701705
if (!StringUtil.isEmptyOrNull(tCExecution.getTag()) && isNotAlreadyDefined(caps, "build")) {
702706
cloudOptions.put("build", tCExecution.getTag());
@@ -723,6 +727,7 @@ && isNotAlreadyDefined(caps, "appWaitActivity"))) {
723727
cloudOptions.put("console", true);
724728
}
725729
}
730+
caps.setCapability("cloud:options", cloudOptions);
726731
break;
727732
case TestCaseExecution.ROBOTPROVIDER_KOBITON:
728733
if (isNotAlreadyDefined(caps, "sessionName")) {
@@ -749,12 +754,12 @@ && isNotAlreadyDefined(caps, "appWaitActivity"))) {
749754
if (isNotAlreadyDefined(caps, "deviceGroup")) {
750755
cloudOptions.put("deviceGroup", "KOBITON");
751756
}
757+
caps.setCapability("cloud:options", cloudOptions);
752758
break;
753759
case TestCaseExecution.ROBOTPROVIDER_NONE:
754760
break;
755761
default:
756762
}
757-
caps.setCapability("cloud:options", cloudOptions);
758763
return caps;
759764
}
760765

source/src/main/java/org/cerberus/core/enums/MessageEventEnum.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,8 @@ public enum MessageEventEnum {
189189
ACTION_SUCCESS_DOUBLECLICK(200, "OK", "Element '%ELEMENT%' double clicked.", false, false, false, MessageGeneralEnum.EXECUTION_PE_TESTSTARTED),
190190
ACTION_SUCCESS_RIGHTCLICK(200, "OK", "Right click has been done on Element '%ELEMENT%'.", false, false, false, MessageGeneralEnum.EXECUTION_PE_TESTSTARTED),
191191
ACTION_SUCCESS_URLLOGIN(200, "OK", "Opened '%URL%'.", false, false, false, MessageGeneralEnum.EXECUTION_PE_TESTSTARTED),
192-
ACTION_SUCCESS_MOUSEOVER(200, "OK", "Mouse moved over '%ELEMENT%' with an offset %OFFSET%.", false, false, false, MessageGeneralEnum.EXECUTION_PE_TESTSTARTED),
192+
ACTION_SUCCESS_MOUSEOVER(200, "OK", "Mouse moved over '%ELEMENT%' with an offset '%OFFSET%'.", false, false, false, MessageGeneralEnum.EXECUTION_PE_TESTSTARTED),
193+
ACTION_SUCCESS_MOUSEMOVE(200, "OK", "Mouse moved with coord '%COORD%'.", false, false, false, MessageGeneralEnum.EXECUTION_PE_TESTSTARTED),
193194
ACTION_SUCCESS_WAIT_TIME(200, "OK", "Waited %TIME% ms.", false, false, false, MessageGeneralEnum.EXECUTION_PE_TESTSTARTED),
194195
ACTION_SUCCESS_WAIT_TIME_WITHWARNINGS(200, "OK", "Waited %TIME% ms with warning : %MESSAGE%", false, false, false, MessageGeneralEnum.EXECUTION_PE_TESTSTARTED),
195196
ACTION_SUCCESS_WAIT_ELEMENT(200, "OK", "Waited for %ELEMENT%.", false, false, false, MessageGeneralEnum.EXECUTION_PE_TESTSTARTED),
@@ -287,6 +288,8 @@ public enum MessageEventEnum {
287288
ACTION_FAILED_DOUBLECLICK_NO_SUCH_ELEMENT(268, "FA", "Failed to double click because could not find element '%ELEMENT%'!", true, true, true, MessageGeneralEnum.EXECUTION_FA_ACTION),
288289
ACTION_FAILED_TYPE_NO_SUCH_ELEMENT(269, "FA", "Failed to type because could not find element '%ELEMENT%'!", true, true, true, MessageGeneralEnum.EXECUTION_FA_ACTION),
289290
ACTION_FAILED_MOUSEOVER_NO_SUCH_ELEMENT(270, "FA", "Failed to move mouse over because could not find element '%ELEMENT%'!", true, true, true, MessageGeneralEnum.EXECUTION_FA_ACTION),
291+
ACTION_FAILED_MOUSEOVER_OFFSETFORMAT(270, "FA", "Failed to move mouse over with offset because offset '%OFFSET%' does not respect the correct format xoffset,yoffset (ex: -50,50)!", true, true, true, MessageGeneralEnum.EXECUTION_FA_ACTION),
292+
ACTION_FAILED_MOUSEMOVE(270, "FA", "Failed to move mouse with coord '%COORD%' because '%ERROR%'!", true, true, true, MessageGeneralEnum.EXECUTION_FA_ACTION),
290293
ACTION_FAILED_WAIT_NO_SUCH_ELEMENT(271, "FA", "Failed to wait because could not find element '%ELEMENT%'!", true, true, true, MessageGeneralEnum.EXECUTION_FA_ACTION),
291294
ACTION_FAILED_WAIT_ERRATUM_MISSING_SEPARATOR(271, "FA", "Failed to wait because syntax error on erratum value (separator '%SEPARATOR%' is missing) !", true, true, true, MessageGeneralEnum.EXECUTION_FA_ACTION),
292295
ACTION_FAILED_WAIT_ERRATUM_ELEMENT_NOT_FOUND(271, "FA", "Failed to wait because Erratum could not match the element on new page ! That can happen if page is too different from the original one.", true, true, true, MessageGeneralEnum.EXECUTION_FA_ACTION),

source/src/main/java/org/cerberus/core/service/robotextension/impl/SikuliService.java

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
/**
22
* Cerberus Copyright (C) 2013 - 2025 cerberustesting
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4-
*
4+
*
55
* This file is part of Cerberus.
6-
*
6+
*
77
* Cerberus is free software: you can redistribute it and/or modify
88
* it under the terms of the GNU General Public License as published by
99
* the Free Software Foundation, either version 3 of the License, or
1010
* (at your option) any later version.
11-
*
11+
*
1212
* Cerberus is distributed in the hope that it will be useful,
1313
* but WITHOUT ANY WARRANTY; without even the implied warranty of
1414
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1515
* GNU General Public License for more details.
16-
*
16+
*
1717
* You should have received a copy of the GNU General Public License
1818
* along with Cerberus. If not, see <http://www.gnu.org/licenses/>.
1919
*/
@@ -100,7 +100,7 @@ public class SikuliService implements ISikuliService {
100100
private static final String SIKULI_EXECUTEACTION_PATH = "/extra/ExecuteSikuliAction";
101101

102102
private JSONObject generatePostParameters(String action, String locator, String locator2, String text, String text2,
103-
long defaultWait, String minSimilarity, Integer highlightElement, String typeDelay) throws JSONException, IOException, MalformedURLException, MimeTypeException {
103+
long defaultWait, String minSimilarity, Integer highlightElement, String typeDelay) throws JSONException, IOException, MalformedURLException, MimeTypeException {
104104
JSONObject result = new JSONObject();
105105
String picture = "";
106106
String extension = "";
@@ -364,7 +364,7 @@ public AnswerItem<JSONObject> doSikuliAction(Session session, String action, Str
364364

365365
// Send post request
366366
os = new PrintStream(connection.getOutputStream());
367-
LOG.debug("Sending JSON : {}", postParameters.toString());
367+
LOG.debug("Sending JSON : {}", postParameters.toString(1));
368368
os.println(postParameters.toString());
369369
// os.println("|ENDS|");
370370

@@ -593,7 +593,28 @@ public MessageEvent doSikuliActionLeftButtonRelease(Session session) {
593593

594594
@Override
595595
public MessageEvent doSikuliActionMouseMove(Session session, String xyoffset) {
596-
AnswerItem<JSONObject> actionResult = doSikuliAction(session, this.SIKULI_MOUSEMOVE, null, null, xyoffset, "");
596+
AnswerItem<JSONObject> actionResult = null;
597+
598+
if (StringUtil.isNotEmptyOrNull(xyoffset)) {
599+
actionResult = doSikuliAction(session, this.SIKULI_MOUSEMOVE, null, null, xyoffset, "");
600+
} else {
601+
MessageEvent message = new MessageEvent(MessageEventEnum.ACTION_SUCCESS_MOUSEMOVE);
602+
message.resolveDescription("%COORD%", "0,0");
603+
return message;
604+
}
605+
606+
if (actionResult == null || actionResult.getResultMessage().getCodeString().equals(new MessageEvent(MessageEventEnum.ACTION_SUCCESS).getCodeString())) {
607+
MessageEvent message = new MessageEvent(MessageEventEnum.ACTION_SUCCESS_MOUSEMOVE);
608+
message.resolveDescription("COORD", xyoffset);
609+
return message;
610+
}
611+
if (actionResult.getResultMessage().getCodeString().equals(new MessageEvent(MessageEventEnum.ACTION_FAILED).getCodeString())) {
612+
MessageEvent mes = new MessageEvent(MessageEventEnum.ACTION_FAILED_MOUSEMOVE);
613+
mes.resolveDescription("ERROR", actionResult.getMessageDescription());
614+
mes.resolveDescription("COORD", xyoffset);
615+
return mes;
616+
}
617+
597618
return actionResult.getResultMessage();
598619

599620
}
@@ -652,24 +673,39 @@ public MessageEvent doSikuliActionType(Session session, String locator, String t
652673
public MessageEvent doSikuliActionMouseOver(Session session, String locator, String text, String offset) {
653674
AnswerItem<JSONObject> actionResult = null;
654675

676+
// We check here that offxet format is correct and report an error if invalid.
677+
if (StringUtil.isNotEmptyOrNull(offset)) {
678+
try {
679+
Integer[] offsetInt = StringUtil.getxFromOffset(offset);
680+
} catch (Exception e) {
681+
MessageEvent mes = new MessageEvent(MessageEventEnum.ACTION_FAILED_MOUSEOVER_OFFSETFORMAT);
682+
mes.setDescription(mes.getDescription().replace("%OFFSET%", offset));
683+
return mes;
684+
}
685+
}
686+
655687
if (!locator.isEmpty()) {
656688
actionResult = doSikuliAction(session, this.SIKULI_MOUSEOVER, locator, null, "", "");
657-
actionResult = doSikuliAction(session, this.SIKULI_MOUSEMOVE, null, null, offset, "");
689+
if (StringUtil.isNotEmptyOrNull(offset)) {
690+
actionResult = doSikuliAction(session, this.SIKULI_MOUSEMOVE, null, null, offset, "");
691+
}
658692
} else {
659693
actionResult = doSikuliAction(session, this.SIKULI_MOUSEOVER, null, null, text, "");
660-
actionResult = doSikuliAction(session, this.SIKULI_MOUSEMOVE, null, null, offset, "");
694+
if (StringUtil.isNotEmptyOrNull(offset)) {
695+
actionResult = doSikuliAction(session, this.SIKULI_MOUSEMOVE, null, null, offset, "");
696+
}
661697
}
662698

663699
if (actionResult.getResultMessage().getCodeString().equals(new MessageEvent(MessageEventEnum.ACTION_SUCCESS).getCodeString())) {
664700
MessageEvent message = new MessageEvent(MessageEventEnum.ACTION_SUCCESS_MOUSEOVER);
665701
message.setDescription(message.getDescription().replace("%ELEMENT%", locator));
666-
message.setDescription(message.getDescription().replace("%OFFSET%", "("+offset+")"));
702+
message.setDescription(message.getDescription().replace("%OFFSET%", offset));
667703
return message;
668704
}
669705
if (actionResult.getResultMessage().getCodeString().equals(new MessageEvent(MessageEventEnum.ACTION_FAILED).getCodeString())) {
670706
MessageEvent mes = new MessageEvent(MessageEventEnum.ACTION_FAILED_MOUSEOVER_NO_SUCH_ELEMENT);
671707
mes.setDescription(mes.getDescription().replace("%ELEMENT%", locator) + " - " + actionResult.getMessageDescription());
672-
mes.setDescription(mes.getDescription().replace("%OFFSET%", "("+offset+")"));
708+
mes.setDescription(mes.getDescription().replace("%OFFSET%", offset));
673709
return mes;
674710
}
675711

source/src/main/java/org/cerberus/core/util/StringUtil.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,25 @@ public static String getLeftString(String string1, int length) {
237237
}
238238
}
239239

240+
/**
241+
* Return x part of offset.
242+
*
243+
* @param offset
244+
* @return the {length} first character of the string1.
245+
*/
246+
public static Integer[] getxFromOffset(String offset) throws NumberFormatException {
247+
Integer[] res = new Integer[2];
248+
if (offset.contains(",")) {
249+
String x = offset.split(",")[0];
250+
res[0] = Integer.valueOf(x);
251+
String y = offset.split(",")[1];
252+
res[1] = Integer.valueOf(y);
253+
return res;
254+
} else {
255+
throw new NumberFormatException();
256+
}
257+
}
258+
240259
/**
241260
* Return left part of the string adding ... at the end.
242261
*

source/src/main/resources/documentation/D2/include/en/changelog_4.20_en.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@
1111

1212
*Warning to be considered before applying the version (deprecated features)*
1313
[square]
14-
* none
14+
* none

source/src/main/resources/log4j2.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ appender.console.layout.pattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
1616
#logger.file.level = debug
1717
#logger.file.appenderRefs = file
1818
#logger.file.appenderRef.file.ref = LOGFILE
19-
rootLogger.level=info
19+
rootLogger.level=debug
2020
rootLogger.appenderRefs=stdout
2121
rootLogger.appenderRef.stdout.ref=STDOUT

source/src/main/webapp/META-INF/context.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,5 @@
2121
2222
-->
2323
<Context path="/Cerberus">
24-
<!-- <Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/> -->
24+
<Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
2525
</Context>

source/src/main/webapp/TestCaseScript.jsp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
<script type="text/javascript" src="dependencies/Tinymce-6.7.0/tinymce.min.js"></script>
3030
<script type="text/javascript" src="dependencies/Bootstrap-treeview-1.2.0/js/bootstrap-treeview.js"></script>
3131
<script type="text/javascript" src="dependencies/Ace-1.2.6/ext-language_tools.js"></script>
32+
<!-- <script type="text/javascript" src="dependencies/Ace-1.38.0/ext-language_tools.js"></script>-->
3233
<script type="text/javascript" src="js/pages/TestCaseScript.js"></script>
3334
<script type="text/javascript" src="js/transversalobject/TestCase.js"></script>
3435
<script type="text/javascript" src="js/transversalobject/ApplicationObject.js"></script>

source/src/main/webapp/dependencies/Ace-1.38.0/ace.js

Lines changed: 23 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)