From 9e641002d5ad689ef01ec8cdfcc8daa1da2a29fd Mon Sep 17 00:00:00 2001 From: Uladzislau Arlouski Date: Tue, 23 Mar 2021 11:47:04 +0300 Subject: [PATCH] [plugin-mobile-app] Add press key step --- .../plugins/pages/plugin-mobile-app.adoc | 17 ++++++ .../bdd/mobileapp/steps/DeviceSteps.java | 46 +++++++++++++- .../bdd/mobileapp/steps/DeviceStepsTests.java | 61 ++++++++++++++++++- .../mobile_app/MobileAppStepsTests.story | 13 ++-- 4 files changed, 128 insertions(+), 9 deletions(-) diff --git a/docs/modules/plugins/pages/plugin-mobile-app.adoc b/docs/modules/plugins/pages/plugin-mobile-app.adoc index 935db944e7..be3945be9f 100644 --- a/docs/modules/plugins/pages/plugin-mobile-app.adoc +++ b/docs/modules/plugins/pages/plugin-mobile-app.adoc @@ -618,4 +618,21 @@ When I switch to native context Then number of elements found by `xpath(html)` is equal to `0` ---- +=== Press key + +Presses an https://github.com/appium/appium-xcuitest-driver#mobile-pressbutton[iOS key] or https://appium.github.io/java-client/io/appium/java_client/android/nativekey/AndroidKey.html[Android key] + +[source,gherkin] +---- +When I press $key key +---- + +. `$key` - The key to press + +.Go to home +[source,gherkin] +---- +When I press Home key +---- + include::partial$generic-ui-steps.adoc[] diff --git a/vividus-plugin-mobile-app/src/main/java/org/vividus/bdd/mobileapp/steps/DeviceSteps.java b/vividus-plugin-mobile-app/src/main/java/org/vividus/bdd/mobileapp/steps/DeviceSteps.java index 8eee9dbc0e..c9a874198f 100644 --- a/vividus-plugin-mobile-app/src/main/java/org/vividus/bdd/mobileapp/steps/DeviceSteps.java +++ b/vividus-plugin-mobile-app/src/main/java/org/vividus/bdd/mobileapp/steps/DeviceSteps.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. @@ -17,12 +17,22 @@ package org.vividus.bdd.mobileapp.steps; import java.nio.file.Paths; +import java.util.Map; import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.EnumUtils; +import org.apache.commons.lang3.Validate; import org.jbehave.core.annotations.When; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.vividus.mobileapp.action.DeviceActions; +import org.vividus.selenium.IWebDriverProvider; +import org.vividus.selenium.manager.GenericWebDriverManager; +import org.vividus.ui.action.JavascriptActions; + +import io.appium.java_client.android.nativekey.AndroidKey; +import io.appium.java_client.android.nativekey.KeyEvent; +import io.appium.java_client.android.nativekey.PressesKey; public class DeviceSteps { @@ -30,11 +40,19 @@ public class DeviceSteps private final DeviceActions deviceActions; private final String folderForFileUpload; + private final GenericWebDriverManager genericWebDriverManager; + private final JavascriptActions javascriptActions; + private final IWebDriverProvider webDriverProvider; - public DeviceSteps(String folderForFileUpload, DeviceActions deviceActions) + public DeviceSteps(String folderForFileUpload, DeviceActions deviceActions, + GenericWebDriverManager genericWebDriverManager, JavascriptActions javascriptActions, + IWebDriverProvider webDriverProvider) { this.folderForFileUpload = folderForFileUpload; this.deviceActions = deviceActions; + this.genericWebDriverManager = genericWebDriverManager; + this.javascriptActions = javascriptActions; + this.webDriverProvider = webDriverProvider; } /** @@ -51,4 +69,28 @@ public void uploadFileToDevice(String filePath) String fileName = FilenameUtils.getName(filePath); deviceActions.pushFile(Paths.get(folderForFileUpload, fileName).toString(), filePath); } + + /** + * Presses the key + *
+ * See iOS keys and + * + * Android keys for available values + * + * @param key key to press + */ + @When("I press $key key") + public void pressKey(String key) + { + if (genericWebDriverManager.isIOSNativeApp()) + { + javascriptActions.executeScript("mobile: pressButton", Map.of("name", key)); + } + else + { + AndroidKey androidKey = EnumUtils.getEnumIgnoreCase(AndroidKey.class, key); + Validate.isTrue(androidKey != null, "Unsupported Android key: %s", key); + webDriverProvider.getUnwrapped(PressesKey.class).pressKey(new KeyEvent(androidKey)); + } + } } diff --git a/vividus-plugin-mobile-app/src/test/java/org/vividus/bdd/mobileapp/steps/DeviceStepsTests.java b/vividus-plugin-mobile-app/src/test/java/org/vividus/bdd/mobileapp/steps/DeviceStepsTests.java index d8384ecab1..ea3535dcac 100644 --- a/vividus-plugin-mobile-app/src/test/java/org/vividus/bdd/mobileapp/steps/DeviceStepsTests.java +++ b/vividus-plugin-mobile-app/src/test/java/org/vividus/bdd/mobileapp/steps/DeviceStepsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2021 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. @@ -19,10 +19,17 @@ import static com.github.valfirst.slf4jtest.LoggingEvent.info; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; import java.nio.file.Paths; import java.util.List; +import java.util.Map; import com.github.valfirst.slf4jtest.TestLogger; import com.github.valfirst.slf4jtest.TestLoggerFactory; @@ -31,11 +38,18 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.vividus.mobileapp.action.DeviceActions; +import org.vividus.selenium.IWebDriverProvider; +import org.vividus.selenium.manager.GenericWebDriverManager; +import org.vividus.ui.action.JavascriptActions; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import io.appium.java_client.android.nativekey.AndroidKey; +import io.appium.java_client.android.nativekey.KeyEvent; +import io.appium.java_client.android.nativekey.PressesKey; @SuppressFBWarnings("DMI_HARDCODED_ABSOLUTE_FILENAME") @ExtendWith({ MockitoExtension.class, TestLoggerFactoryExtension.class }) @@ -44,6 +58,9 @@ class DeviceStepsTests private static final String DEVICE_FOLDER = "/device/folder"; @Mock private DeviceActions deviceActions; + @Mock private GenericWebDriverManager genericWebDriverManager; + @Mock private JavascriptActions javascriptActions; + @Mock private IWebDriverProvider webDriverProvider; private DeviceSteps deviceSteps; private final TestLogger logger = TestLoggerFactory.getTestLogger(DeviceSteps.class); @@ -51,7 +68,8 @@ class DeviceStepsTests @BeforeEach void init() { - deviceSteps = new DeviceSteps(DEVICE_FOLDER, deviceActions); + deviceSteps = new DeviceSteps(DEVICE_FOLDER, deviceActions, genericWebDriverManager, javascriptActions, + webDriverProvider); } @Test @@ -67,4 +85,43 @@ void shoulUploadFileToDevice() info("Uploading file '{}' to a device at '{}' folder", filePath, DEVICE_FOLDER) ))); } + + @Test + void shouldPressIOSKey() + { + String key = "Home"; + + when(genericWebDriverManager.isIOSNativeApp()).thenReturn(true); + + deviceSteps.pressKey(key); + + verify(javascriptActions).executeScript("mobile: pressButton", Map.of("name", key)); + verifyNoInteractions(webDriverProvider); + } + + @Test + void shouldPressAndroidKey() + { + ArgumentCaptor keyCaptor = ArgumentCaptor.forClass(KeyEvent.class); + PressesKey pressesKey = mock(PressesKey.class); + when(genericWebDriverManager.isIOSNativeApp()).thenReturn(false); + when(webDriverProvider.getUnwrapped(PressesKey.class)).thenReturn(pressesKey); + + deviceSteps.pressKey(AndroidKey.SPACE.name()); + + verify(pressesKey).pressKey(keyCaptor.capture()); + + assertEquals(Map.of("keycode", 62), keyCaptor.getValue().build()); + verifyNoMoreInteractions(webDriverProvider, genericWebDriverManager); + } + + @Test + void shouldNotPressUnsupportedAndroidKey() + { + when(genericWebDriverManager.isIOSNativeApp()).thenReturn(false); + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> deviceSteps.pressKey("unsupported key")); + assertEquals("Unsupported Android key: unsupported key", exception.getMessage()); + verifyNoMoreInteractions(webDriverProvider, genericWebDriverManager); + } } 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 1933c000bc..6d4519d4f1 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 @@ -14,6 +14,14 @@ Given I start mobile application with capabilities: |app |${app-url}| +Scenario: Verify steps: 'When I press $key key', 'Then number of $state elements found by `$locator` is $comparisonRule `$quantity`' and Text Part Filter and Text Filter +Then number of elements found by `xpath()->filter.text(Home)` is equal to `1` +When I press Home key +Then number of elements found by `xpath()->filter.text(Home)` is equal to `0` +When I activate application with bundle identifier `${main-app}` +When I wait until element located `xpath()->filter.textPart(om)` appears + + Scenario: [Android] Verify step: 'When I change Appium session settings:$settings' and Id Locator Meta: @targetPlatform android @@ -44,11 +52,6 @@ When I change Appium session settings: Then number of elements found by `xpath():a` is equal to `1` -Scenario: Verify step: 'Then number of $state elements found by `$locator` is $comparisonRule `$quantity`' and Text Part Filter and Text Filter -Then number of elements found by `xpath()->filter.textPart(om)` is equal to `1` -Then number of elements found by `xpath()->filter.text(Home)` is equal to `1` - - Scenario: Verify step: 'Then number of $state elements found by `$locator` is $comparisonRule `$quantity`' and Accessibility Id Locator Then number of VISIBLE elements found by `accessibilityId():a` is equal to `1`