From baad4598964e8ba7a064c20913374592500f48b5 Mon Sep 17 00:00:00 2001 From: Ivan Kalinin Date: Mon, 12 Sep 2022 12:30:34 +0300 Subject: [PATCH 1/2] [plugin-mobile-app] Make JavaScript executing steps available for mobile app tests --- .../modules/plugins/pages/plugin-web-app.adoc | 19 --- .../plugins/partials/generic-ui-steps.adoc | 55 +++++++ .../steps/ui/AbstractExecuteScriptSteps.java | 46 ++++++ .../vividus/steps/ui/ExecuteScriptSteps.java | 86 +++++++++++ .../steps/ui/web/model/JsArgument.java | 2 +- .../steps/ui/web/model/JsArgumentType.java | 2 +- .../resources/vividus-extension/spring.xml | 3 + .../steps/ui/ExecuteScriptStepsTests.java | 134 ++++++++++++++++++ .../org/vividus/steps/ui/web/CodeSteps.java | 94 ++---------- .../vividus/steps/ui/web/CodeStepsTests.java | 79 ----------- .../system/mobile_app/locators/android.table | 2 + .../system/mobile_app/locators/ios.table | 2 + .../story/integration/CodeSteps.story | 8 ++ .../mobile_app/MobileAppStepsTests.story | 44 +++++- 14 files changed, 389 insertions(+), 187 deletions(-) create mode 100644 vividus-extension-selenium/src/main/java/org/vividus/steps/ui/AbstractExecuteScriptSteps.java create mode 100644 vividus-extension-selenium/src/main/java/org/vividus/steps/ui/ExecuteScriptSteps.java rename {vividus-plugin-web-app => vividus-extension-selenium}/src/main/java/org/vividus/steps/ui/web/model/JsArgument.java (95%) rename {vividus-plugin-web-app => vividus-extension-selenium}/src/main/java/org/vividus/steps/ui/web/model/JsArgumentType.java (95%) create mode 100644 vividus-extension-selenium/src/test/java/org/vividus/steps/ui/ExecuteScriptStepsTests.java diff --git a/docs/modules/plugins/pages/plugin-web-app.adoc b/docs/modules/plugins/pages/plugin-web-app.adoc index b0cafe8188..13edb8cdc9 100644 --- a/docs/modules/plugins/pages/plugin-web-app.adoc +++ b/docs/modules/plugins/pages/plugin-web-app.adoc @@ -1219,25 +1219,6 @@ Given I am on the main application page ---- === Code steps -==== Execute JavaScript and save result. - -https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/JavascriptExecutor.html[Executes JavaScript] code and saves result into variable. - -[source,gherkin] ----- -When I execute javascript `$jsCode` and save result to $scopes variable `$variableName` ----- -* `$jsCode` - Any JavaScript code. In order to save a result https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/return[return] statement should be used. -* `$scopes` - xref:commons:variables.adoc#_scopes[The comma-separated set of the variables scopes]. -* `$variableName` - The variable name to save the cookie value. - -.Validate timings -[source,gherkin] ----- -Given I am on a page with the URL 'http://vividus-test-site.herokuapp.com/mouseEvents.html' -When I execute javascript `return JSON.stringify(window.performance.timing)` and save result to scenario variable `timings` -Then number of JSON elements from `${timings}` by JSON path `$.connectStart` is = 1 ----- ==== Execute async JavaScript and save result. diff --git a/docs/modules/plugins/partials/generic-ui-steps.adoc b/docs/modules/plugins/partials/generic-ui-steps.adoc index c12eab2355..2e8ad473d6 100644 --- a/docs/modules/plugins/partials/generic-ui-steps.adoc +++ b/docs/modules/plugins/partials/generic-ui-steps.adoc @@ -405,3 +405,58 @@ When I find >= `0` elements `xpath(//*[@class='menu enabled'])` and while they e |step | |When I click on element located `id(disable)`| ---- + +=== Execute JavaScript with arguments + +Executes JavaScript via https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/JavascriptExecutor.html[JavascriptExecutor]. Step executes the script either without any arguments or with `String` or `Object` argument types. + +[source,gherkin] +---- +When I execute javascript `$script` with arguments:$arguments +---- + +* `$script` - The JavaScript code to execute. +* `$arguments` - The examples table with set of arguments and their type: +** [subs=+quotes]`*value*` - The value of the argument. +** [subs=+quotes]`*type*` - The type of the argument. Either `string` or `object`. + +.Remove noisy assistant +[source,gherkin] +---- +When I execute javascript `document.querySelector('#assistant').remove()` with arguments: +---- + +.Inject image +[source,gherkin] +---- +When I execute javascript `sauce:inject-image` with arguments: +|value |type | +|iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=|string| + +.Throttle CPU +[source,gherkin] +---- +When I execute javascript `sauce:throttleCPU` with arguments: +|value |type | +|{"rate" : 4}|object| +---- + +==== Execute JavaScript and save result. + +https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/JavascriptExecutor.html[Executes JavaScript] code and saves result into variable. + +[source,gherkin] +---- +When I execute javascript `$jsCode` and save result to $scopes variable `$variableName` +---- +* `$jsCode` - Any JavaScript code. In order to save a result https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/return[return] statement should be used. +* `$scopes` - xref:commons:variables.adoc#_scopes[The comma-separated set of the variables scopes]. +* `$variableName` - The variable name to script execution result. + +.Validate timings +[source,gherkin] +---- +Given I am on a page with the URL 'http://vividus-test-site.herokuapp.com/mouseEvents.html' +When I execute javascript `return JSON.stringify(window.performance.timing)` and save result to scenario variable `timings` +Then number of JSON elements from `${timings}` by JSON path `$.connectStart` is = 1 +---- diff --git a/vividus-extension-selenium/src/main/java/org/vividus/steps/ui/AbstractExecuteScriptSteps.java b/vividus-extension-selenium/src/main/java/org/vividus/steps/ui/AbstractExecuteScriptSteps.java new file mode 100644 index 0000000000..54a9ffdcc6 --- /dev/null +++ b/vividus-extension-selenium/src/main/java/org/vividus/steps/ui/AbstractExecuteScriptSteps.java @@ -0,0 +1,46 @@ +/* + * Copyright 2019-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.vividus.steps.ui; + +import java.util.Set; +import java.util.function.Supplier; + +import org.vividus.context.VariableContext; +import org.vividus.softassert.ISoftAssert; +import org.vividus.variable.VariableScope; + +@SuppressWarnings("PMD.AbstractClassWithoutAbstractMethod") +public abstract class AbstractExecuteScriptSteps +{ + private final ISoftAssert softAssert; + private final VariableContext variableContext; + + protected AbstractExecuteScriptSteps(ISoftAssert softAssert, VariableContext variableContext) + { + this.softAssert = softAssert; + this.variableContext = variableContext; + } + + protected void assertAndSaveResult(Supplier resultProvider, Set scopes, String variableName) + { + Object result = resultProvider.get(); + if (softAssert.assertNotNull("Returned result is not null", result)) + { + variableContext.putVariable(scopes, variableName, result); + } + } +} diff --git a/vividus-extension-selenium/src/main/java/org/vividus/steps/ui/ExecuteScriptSteps.java b/vividus-extension-selenium/src/main/java/org/vividus/steps/ui/ExecuteScriptSteps.java new file mode 100644 index 0000000000..321ebd81a8 --- /dev/null +++ b/vividus-extension-selenium/src/main/java/org/vividus/steps/ui/ExecuteScriptSteps.java @@ -0,0 +1,86 @@ +/* + * Copyright 2019-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.vividus.steps.ui; + +import java.util.List; +import java.util.Set; + +import org.jbehave.core.annotations.When; +import org.vividus.context.VariableContext; +import org.vividus.softassert.ISoftAssert; +import org.vividus.steps.ui.web.model.JsArgument; +import org.vividus.steps.ui.web.model.JsArgumentType; +import org.vividus.ui.action.JavascriptActions; +import org.vividus.variable.VariableScope; + +public class ExecuteScriptSteps extends AbstractExecuteScriptSteps +{ + private final JavascriptActions javascriptActions; + + public ExecuteScriptSteps(JavascriptActions javascriptActions, VariableContext variableContext, + ISoftAssert softAssert) + { + super(softAssert, variableContext); + this.javascriptActions = javascriptActions; + } + + /** + * Executes passed JavaScript code on the opened page + * and saves returned value into the variable + * + * @param scopes The set (comma separated list of scopes e.g.: STORY, NEXT_BATCHES) of variable's scope
+ * Available scopes: + *
    + *
  • STEP - the variable will be available only within the step, + *
  • SCENARIO - the variable will be available only within the scenario, + *
  • STORY - the variable will be available within the whole story, + *
  • NEXT_BATCHES - the variable will be available starting from next batch + *
+ * @param variableName A name under which the value should be saved + * @param jsCode Code in javascript that returns some value as result + * (e.g. var a=1; return a;) + */ + @When("I execute javascript `$jsCode` and save result to $scopes variable `$variableName`") + public void saveValueFromJS(String jsCode, Set scopes, String variableName) + { + assertAndSaveResult(() -> javascriptActions.executeScript(jsCode), scopes, variableName); + } + + /** + * Executes JavaScript code with specified arguments + * + * @param jsCode JavaScript code + * @param args A table containing JS command argument value and type (one of STRING or OBJECT). + * The parameter is optional and could be omitted.
+ */ + @When("I execute javascript `$jsCode` with arguments:$args") + public void executeJavascriptWithArguments(String jsCode, List args) + { + javascriptActions.executeScript(jsCode, args.stream().map(this::convertRowToArgument).toArray()); + } + + private Object convertRowToArgument(JsArgument arg) + { + JsArgumentType type = arg.getType(); + String value = arg.getValue(); + if (type == null || value == null) + { + throw new IllegalArgumentException("Please, specify command argument values and types"); + } + return type.convert(value); + } +} diff --git a/vividus-plugin-web-app/src/main/java/org/vividus/steps/ui/web/model/JsArgument.java b/vividus-extension-selenium/src/main/java/org/vividus/steps/ui/web/model/JsArgument.java similarity index 95% rename from vividus-plugin-web-app/src/main/java/org/vividus/steps/ui/web/model/JsArgument.java rename to vividus-extension-selenium/src/main/java/org/vividus/steps/ui/web/model/JsArgument.java index a3017e5c5c..c99ba7fbd4 100644 --- a/vividus-plugin-web-app/src/main/java/org/vividus/steps/ui/web/model/JsArgument.java +++ b/vividus-extension-selenium/src/main/java/org/vividus/steps/ui/web/model/JsArgument.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2021 the original author or authors. + * Copyright 2019-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/vividus-plugin-web-app/src/main/java/org/vividus/steps/ui/web/model/JsArgumentType.java b/vividus-extension-selenium/src/main/java/org/vividus/steps/ui/web/model/JsArgumentType.java similarity index 95% rename from vividus-plugin-web-app/src/main/java/org/vividus/steps/ui/web/model/JsArgumentType.java rename to vividus-extension-selenium/src/main/java/org/vividus/steps/ui/web/model/JsArgumentType.java index f12bd90e73..8e5ea0ad75 100644 --- a/vividus-plugin-web-app/src/main/java/org/vividus/steps/ui/web/model/JsArgumentType.java +++ b/vividus-extension-selenium/src/main/java/org/vividus/steps/ui/web/model/JsArgumentType.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2021 the original author or authors. + * Copyright 2019-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/vividus-extension-selenium/src/main/resources/vividus-extension/spring.xml b/vividus-extension-selenium/src/main/resources/vividus-extension/spring.xml index b76a76e38d..a12631a5f8 100644 --- a/vividus-extension-selenium/src/main/resources/vividus-extension/spring.xml +++ b/vividus-extension-selenium/src/main/resources/vividus-extension/spring.xml @@ -174,7 +174,10 @@ + + + diff --git a/vividus-extension-selenium/src/test/java/org/vividus/steps/ui/ExecuteScriptStepsTests.java b/vividus-extension-selenium/src/test/java/org/vividus/steps/ui/ExecuteScriptStepsTests.java new file mode 100644 index 0000000000..7a732b8c2b --- /dev/null +++ b/vividus-extension-selenium/src/test/java/org/vividus/steps/ui/ExecuteScriptStepsTests.java @@ -0,0 +1,134 @@ +/* + * Copyright 2019-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.vividus.steps.ui; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Stream; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.vividus.context.VariableContext; +import org.vividus.softassert.ISoftAssert; +import org.vividus.steps.ui.web.model.JsArgument; +import org.vividus.steps.ui.web.model.JsArgumentType; +import org.vividus.ui.action.JavascriptActions; +import org.vividus.variable.VariableScope; + +@ExtendWith(MockitoExtension.class) +class ExecuteScriptStepsTests +{ + private static final String JS_RESULT_ASSERTION_MESSAGE = "Returned result is not null"; + private static final String JS_CODE = "return 'value'"; + private static final String JS_ARGUMENT_ERROR_MESSAGE = "Please, specify command argument values and types"; + private static final String VALUE = "value"; + private static final String BODY = "body"; + private static final Set VARIABLE_SCOPE = Set.of(VariableScope.SCENARIO); + private static final String VARIABLE_NAME = "variableName"; + + @Mock + private JavascriptActions javascriptActions; + + @Mock + private ISoftAssert softAssert; + + @Mock + private VariableContext variableContext; + + @InjectMocks + private ExecuteScriptSteps executeScriptSteps; + + static Stream executeJavascriptWithArguments() + { + // CHECKSTYLE:OFF + return Stream.of( + Arguments.of("document.querySelector(arguments[0])", createJsArgument(JsArgumentType.STRING, BODY), BODY ), + Arguments.of("remote:throttle", createJsArgument(JsArgumentType.OBJECT, "{\"condition\": \"Wifi\"}"), Map.of("condition", "Wifi")) + ); + // CHECKSTYLE:ON + } + + @ParameterizedTest + @MethodSource("executeJavascriptWithArguments") + void testExecuteJavascriptWithStringArguments(String jsCode, JsArgument argument, Object arg) + { + executeScriptSteps.executeJavascriptWithArguments(jsCode, Collections.singletonList(argument)); + verify(javascriptActions).executeScript(jsCode, arg); + } + + @Test + void testExecuteJavascriptWithEmptyArguments() + { + String jsCode = "document.readyState"; + executeScriptSteps.executeJavascriptWithArguments(jsCode, List.of()); + verify(javascriptActions).executeScript(jsCode); + } + + @ParameterizedTest + @CsvSource({ + ", body", + "OBJECT, " + }) + void testExecuteJavascriptWithArgumentsNoType(JsArgumentType type, String value) + { + List arguments = List.of(createJsArgument(type, value)); + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> executeScriptSteps.executeJavascriptWithArguments("document.querySelector(arguments[0])", + arguments)); + assertEquals(JS_ARGUMENT_ERROR_MESSAGE, exception.getMessage()); + } + + @Test + void testGettingValueFromJS() + { + when(javascriptActions.executeScript(JS_CODE)).thenReturn(VALUE); + when(softAssert.assertNotNull(JS_RESULT_ASSERTION_MESSAGE, VALUE)).thenReturn(true); + executeScriptSteps.saveValueFromJS(JS_CODE, VARIABLE_SCOPE, VARIABLE_NAME); + verify(variableContext).putVariable(VARIABLE_SCOPE, VARIABLE_NAME, VALUE); + } + + @Test + void testGettingValueFromJSNullIsReturned() + { + executeScriptSteps.saveValueFromJS(JS_CODE, VARIABLE_SCOPE, VARIABLE_NAME); + verify(softAssert).assertNotNull(JS_RESULT_ASSERTION_MESSAGE, null); + verifyNoInteractions(variableContext); + } + + private static JsArgument createJsArgument(JsArgumentType type, String value) + { + JsArgument argument = new JsArgument(); + argument.setType(type); + argument.setValue(value); + return argument; + } +} diff --git a/vividus-plugin-web-app/src/main/java/org/vividus/steps/ui/web/CodeSteps.java b/vividus-plugin-web-app/src/main/java/org/vividus/steps/ui/web/CodeSteps.java index 4559e0ab29..81b68a29bf 100644 --- a/vividus-plugin-web-app/src/main/java/org/vividus/steps/ui/web/CodeSteps.java +++ b/vividus-plugin-web-app/src/main/java/org/vividus/steps/ui/web/CodeSteps.java @@ -21,9 +21,6 @@ import java.io.IOException; import java.util.List; import java.util.Set; -import java.util.function.Supplier; - -import javax.inject.Inject; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -34,9 +31,8 @@ import org.vividus.context.VariableContext; import org.vividus.softassert.ISoftAssert; import org.vividus.steps.ComparisonRule; +import org.vividus.steps.ui.AbstractExecuteScriptSteps; import org.vividus.steps.ui.validation.IBaseValidations; -import org.vividus.steps.ui.web.model.JsArgument; -import org.vividus.steps.ui.web.model.JsArgumentType; import org.vividus.ui.action.search.Locator; import org.vividus.ui.action.search.SearchParameters; import org.vividus.ui.action.search.Visibility; @@ -45,43 +41,21 @@ import org.vividus.ui.web.action.search.WebLocatorType; import org.vividus.variable.VariableScope; -public class CodeSteps +public class CodeSteps extends AbstractExecuteScriptSteps { private static final ObjectMapper MAPPER = new ObjectMapper(); - @Inject private IBaseValidations baseValidations; - @Inject private WebJavascriptActions javascriptActions; - @Inject private ISoftAssert softAssert; - @Inject private VariableContext variableContext; - - /** - * Executes JavaScript code with specified arguments - * @param jsCode JavaScript code - * @param args A table containing JS command argument value and type (one of STRING or OBJECT)
- * Example: - *

- * - * When I execute javaScript `remote:throttle` with arguments:
- * |value |type |
- * |{"condition": "Wifi"}|object| - *
- *

- */ - @When("I execute javascript `$jsCode` with arguments:$args") - public void executeJavascriptWithArguments(String jsCode, List args) - { - javascriptActions.executeScript(jsCode, args.stream().map(this::convertRowToArgument).toArray()); - } + private final IBaseValidations baseValidations; + private final WebJavascriptActions javascriptActions; + private final ISoftAssert softAssert; - private Object convertRowToArgument(JsArgument arg) + public CodeSteps(WebJavascriptActions javascriptActions, VariableContext variableContext, ISoftAssert softAssert, + IBaseValidations baseValidations) { - JsArgumentType type = arg.getType(); - String value = arg.getValue(); - if (type == null || value == null) - { - throw new IllegalArgumentException("Please, specify command argument values and types"); - } - return type.convert(value); + super(softAssert, variableContext); + this.baseValidations = baseValidations; + this.javascriptActions = javascriptActions; + this.softAssert = softAssert; } /** @@ -172,28 +146,6 @@ public List doesInvisibleQuantityOfElementsExists(Locator locator, } - /** - * Executes passed JavaScript code on the opened page - * and saves returned value into the variable - * - * @param scopes The set (comma separated list of scopes e.g.: STORY, NEXT_BATCHES) of variable's scope
- * Available scopes: - *
    - *
  • STEP - the variable will be available only within the step, - *
  • SCENARIO - the variable will be available only within the scenario, - *
  • STORY - the variable will be available within the whole story, - *
  • NEXT_BATCHES - the variable will be available starting from next batch - *
- * @param variableName A name under which the value should be saved - * @param jsCode Code in javascript that returns some value as result - * (e.g. var a=1; return a;) - */ - @When("I execute javascript `$jsCode` and save result to $scopes variable `$variableName`") - public void saveValueFromJS(String jsCode, Set scopes, String variableName) - { - assertAndSaveResult(() -> javascriptActions.executeScript(jsCode), scopes, variableName); - } - /** * Executes passed async javascript code on the opened page * and saves returned value into the variable @@ -217,28 +169,4 @@ public void saveValueFromAsyncJS(String jsCode, Set scopes, Strin { assertAndSaveResult(() -> javascriptActions.executeAsyncScript(jsCode), scopes, variableName); } - - private void assertAndSaveResult(Supplier resultProvider, Set scopes, String variableName) - { - Object result = resultProvider.get(); - if (softAssert.assertNotNull("Returned result is not null", result)) - { - variableContext.putVariable(scopes, variableName, result); - } - } - - public void setJavascriptActions(WebJavascriptActions javascriptActions) - { - this.javascriptActions = javascriptActions; - } - - public void setBaseValidations(IBaseValidations baseValidations) - { - this.baseValidations = baseValidations; - } - - public void setSoftAssert(ISoftAssert softAssert) - { - this.softAssert = softAssert; - } } diff --git a/vividus-plugin-web-app/src/test/java/org/vividus/steps/ui/web/CodeStepsTests.java b/vividus-plugin-web-app/src/test/java/org/vividus/steps/ui/web/CodeStepsTests.java index 66e77b4fc3..6b689266e3 100644 --- a/vividus-plugin-web-app/src/test/java/org/vividus/steps/ui/web/CodeStepsTests.java +++ b/vividus-plugin-web-app/src/test/java/org/vividus/steps/ui/web/CodeStepsTests.java @@ -17,8 +17,6 @@ package org.vividus.steps.ui.web; import static org.hamcrest.Matchers.containsString; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; @@ -28,20 +26,12 @@ import static org.mockito.Mockito.when; import java.io.IOException; -import java.util.Collections; -import java.util.List; -import java.util.Map; import java.util.Set; -import java.util.stream.Stream; import com.fasterxml.jackson.databind.node.TextNode; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.CsvSource; -import org.junit.jupiter.params.provider.MethodSource; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -50,8 +40,6 @@ import org.vividus.softassert.ISoftAssert; import org.vividus.steps.ComparisonRule; import org.vividus.steps.ui.validation.IBaseValidations; -import org.vividus.steps.ui.web.model.JsArgument; -import org.vividus.steps.ui.web.model.JsArgumentType; import org.vividus.ui.action.search.Locator; import org.vividus.ui.action.search.SearchParameters; import org.vividus.ui.action.search.Visibility; @@ -65,8 +53,6 @@ class CodeStepsTests { private static final String JS_RESULT_ASSERTION_MESSAGE = "Returned result is not null"; private static final String JS_CODE = "return 'value'"; - private static final String JS_ARGUMENT_ERROR_MESSAGE = "Please, specify command argument values and types"; - private static final String BODY = "body"; private static final String FAVICON = "Favicon"; private static final String FIELD_VALUE_FROM_THE_JSON_OBJECT_IS_EQUAL_TO_VALUE = "Field value from the JSON object is equal to 'value'"; @@ -183,63 +169,6 @@ void testDoesInvisibleQuantityOfElementsExists() 1, ComparisonRule.EQUAL_TO); } - static Stream executeJavascriptWithArguments() - { - // CHECKSTYLE:OFF - return Stream.of( - Arguments.of("document.querySelector(arguments[0])", createJsArgument(JsArgumentType.STRING, BODY), BODY ), - Arguments.of("remote:throttle", createJsArgument(JsArgumentType.OBJECT, "{\"condition\": \"Wifi\"}"), Map.of("condition", "Wifi")) - ); - // CHECKSTYLE:ON - } - - @ParameterizedTest - @MethodSource("executeJavascriptWithArguments") - void testExecuteJavascriptWithStringArguments(String jsCode, JsArgument argument, Object arg) - { - codeSteps.executeJavascriptWithArguments(jsCode, Collections.singletonList(argument)); - verify(javascriptActions).executeScript(jsCode, arg); - } - - @Test - void testExecuteJavascriptWithEmptyArguments() - { - String jsCode = "document.readyState"; - codeSteps.executeJavascriptWithArguments(jsCode, List.of()); - verify(javascriptActions).executeScript(jsCode); - } - - @ParameterizedTest - @CsvSource({ - ", body", - "OBJECT, " - }) - void testExecuteJavascriptWithArgumentsNoType(JsArgumentType type, String value) - { - JsArgument argument = createJsArgument(type, value); - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, - () -> codeSteps.executeJavascriptWithArguments("document.querySelector(arguments[0])", - Collections.singletonList(argument))); - assertEquals(JS_ARGUMENT_ERROR_MESSAGE, exception.getMessage()); - } - - @Test - void testGettingValueFromJS() - { - when(javascriptActions.executeScript(JS_CODE)).thenReturn(VALUE); - when(softAssert.assertNotNull(JS_RESULT_ASSERTION_MESSAGE, VALUE)).thenReturn(true); - codeSteps.saveValueFromJS(JS_CODE, VARIABLE_SCOPE, VARIABLE_NAME); - verify(variableContext).putVariable(VARIABLE_SCOPE, VARIABLE_NAME, VALUE); - } - - @Test - void testGettingValueFromJSNullIsReturned() - { - codeSteps.saveValueFromJS(JS_CODE, VARIABLE_SCOPE, VARIABLE_NAME); - verify(softAssert).assertNotNull(JS_RESULT_ASSERTION_MESSAGE, null); - verifyNoInteractions(variableContext); - } - @Test void testGettingValueFromAsyncJS() { @@ -257,14 +186,6 @@ void testGettingValueFromAsyncJSNullIsReturned() verifyNoInteractions(variableContext); } - private static JsArgument createJsArgument(JsArgumentType type, String value) - { - JsArgument argument = new JsArgument(); - argument.setType(type); - argument.setValue(value); - return argument; - } - private void mockScriptActions(boolean isValueExist) { when(javascriptActions.executeScript("return JSON.stringify(script)")).thenReturn("{\"name\": \"value\"}"); diff --git a/vividus-tests/src/main/resources/data/tables/system/mobile_app/locators/android.table b/vividus-tests/src/main/resources/data/tables/system/mobile_app/locators/android.table index 6f0d227981..aa5457374f 100644 --- a/vividus-tests/src/main/resources/data/tables/system/mobile_app/locators/android.table +++ b/vividus-tests/src/main/resources/data/tables/system/mobile_app/locators/android.table @@ -15,3 +15,5 @@ |textFieldValueAttribute |text | |scrollableMenuXpath |//android.widget.ScrollView | |qrCodeContainerXpath |//android.view.ViewGroup[@resource-id='RNE__Image__children__container'] | +|firstItemAccessibilityId |Item 1 | +|secondItemAccessibilityId |Item 2 | diff --git a/vividus-tests/src/main/resources/data/tables/system/mobile_app/locators/ios.table b/vividus-tests/src/main/resources/data/tables/system/mobile_app/locators/ios.table index c5390a5449..5a6f61bb57 100644 --- a/vividus-tests/src/main/resources/data/tables/system/mobile_app/locators/ios.table +++ b/vividus-tests/src/main/resources/data/tables/system/mobile_app/locators/ios.table @@ -16,3 +16,5 @@ |keyboardLocator |xpath(//XCUIElementTypeKeyboard) | |scrollableMenuXpath |//XCUIElementTypeScrollView | |qrCodeContainerXpath |//XCUIElementTypeOther[@name='RNE__Image__children__container'] | +|firstItemAccessibilityId |Item 1 | +|secondItemAccessibilityId |Item 2 | diff --git a/vividus-tests/src/main/resources/story/integration/CodeSteps.story b/vividus-tests/src/main/resources/story/integration/CodeSteps.story index d319158bcd..868513a81a 100644 --- a/vividus-tests/src/main/resources/story/integration/CodeSteps.story +++ b/vividus-tests/src/main/resources/story/integration/CodeSteps.story @@ -10,11 +10,19 @@ Given I am on a page with the URL '${vividus-test-site-url}' When I execute javascript `return JSON.stringify(window.performance.timing)` and save result to scenario variable `timings` Then number of JSON elements from `${timings}` by JSON path `$.connectStart` is = 1 + Scenario: Step verification: "When I perform async javascript '$jsCode' and save result to the '$scopes' variable '$variableName'" !-- Deprecated When I perform async javascript 'arguments[0](JSON.stringify(window.performance.timing))' and save result to the 'scenario' variable 'timings' Then number of JSON elements from `${timings}` by JSON path `$.connectStart` is = 1 + Scenario: Step verification: "When I execute async javascript `$jsCode` and save result to $scopes variable `$variableName`" When I execute async javascript `arguments[0](JSON.stringify(window.performance.timing))` and save result to scenario variable `timings` Then number of JSON elements from `${timings}` by JSON path `$.connectStart` is = 1 + + +Scenario: Step verification: "When I execute javascript `$jsCode` with arguments:$args" +Then number of elements found by `xpath(//img)` is = `1` +When I execute javascript `document.querySelector('[name="vividus-logo"]').remove()` with arguments: +Then number of elements found by `xpath(//img)` is = `0` diff --git a/vividus-tests/src/main/resources/story/system/mobile_app/MobileAppStepsTests.story b/vividus-tests/src/main/resources/story/system/mobile_app/MobileAppStepsTests.story index 4f97e56314..d2c034aa81 100644 --- a/vividus-tests/src/main/resources/story/system/mobile_app/MobileAppStepsTests.story +++ b/vividus-tests/src/main/resources/story/system/mobile_app/MobileAppStepsTests.story @@ -1,4 +1,4 @@ -Description: Integration tests for mobile app steps +]Description: Integration tests for mobile app steps Meta: @epic vividus-plugin-mobile-app @@ -14,6 +14,10 @@ Given I start mobile application with capabilities: |app |${app-url}| +Scenario: VerifyStep: 'When I execute javascript `$wcript` and save result to $scopes variable `$variableName`' +When I execute javascript `mobile: deviceInfo` and save result to scenario variable `deviceInfo` +Then `${deviceInfo}` matches `.*timeZone.*` + Scenario: Verify step: 'When I reinstall mobile application with bundle identifier `$bundleId`' Meta: @requirementId 2073 @@ -313,9 +317,41 @@ Then number of elements found by `accessibilityId()` i Then number of elements found by `accessibilityId()` is = `0` When I reset context -Examples: -|firstItemAccessibilityId|secondItemAccessibilityId| -|Item 1 |Item 2 | + +Scenario: Verify step: 'When I execute javascript `$script` with arguments:$args' on iOS +Meta: + @targetPlatform ios +When I execute javascript `mobile: swipe` with arguments: +|value |type | +|{"direction" : "left"}|object| +Then number of elements found by `accessibilityId()` is = `0` +Then number of elements found by `accessibilityId()` is = `1` +When I execute javascript `mobile: swipe` with arguments: +|value |type | +|{"direction" : "right"}|object| +Then number of elements found by `accessibilityId()` is = `1` +Then number of elements found by `accessibilityId()` is = `0` + + +Scenario: Verify step: 'When I execute javascript `$script` with arguments:$args' on Android +Meta: + @targetPlatform android +When I change context to element located `xpath(//android.view.ViewGroup[./android.widget.TextView[@content-desc=""]])` +When I initialize the scenario variable `x` with value `${context-x-coordinate}` +When I initialize the scenario variable `y` with value `${context-y-coordinate}` +When I initialize the scenario variable `width` with value `${context-width}` +When I initialize the scenario variable `height` with value `#{eval(${context-height} / 3 )}` +When I reset context +When I execute javascript `mobile: swipeGesture` with arguments: +|value |type | +|{"left": ${x}, "top": ${y}, "width": ${width}, "height": ${height}, "direction": "left", "percent": 1.0, "speed" : 300}|object| +Then number of elements found by `accessibilityId()` is = `0` +Then number of elements found by `accessibilityId()` is = `1` +When I execute javascript `mobile: swipeGesture` with arguments: +|value |type | +|{"left": ${x}, "top": ${y}, "width": ${width}, "height": ${height}, "direction": "right", "percent": 1.0, "speed" : 300}|object| +Then number of elements found by `accessibilityId()` is = `1` +Then number of elements found by `accessibilityId()` is = `0` Scenario: Verify steps: "When I scan barcode from screen and save result to $scopes variable `$variableName`" From 6c8859d69db1b4e39df509285399ea71a0152ad4 Mon Sep 17 00:00:00 2001 From: Ivan Kalinin Date: Mon, 12 Sep 2022 15:10:30 +0300 Subject: [PATCH 2/2] Update vividus-tests/src/main/resources/story/system/mobile_app/MobileAppStepsTests.story Co-authored-by: Valery Yatsynovich --- .../resources/story/system/mobile_app/MobileAppStepsTests.story | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vividus-tests/src/main/resources/story/system/mobile_app/MobileAppStepsTests.story b/vividus-tests/src/main/resources/story/system/mobile_app/MobileAppStepsTests.story index d2c034aa81..d8b03c2e5e 100644 --- a/vividus-tests/src/main/resources/story/system/mobile_app/MobileAppStepsTests.story +++ b/vividus-tests/src/main/resources/story/system/mobile_app/MobileAppStepsTests.story @@ -1,4 +1,4 @@ -]Description: Integration tests for mobile app steps +Description: Integration tests for mobile app steps Meta: @epic vividus-plugin-mobile-app