From a208592fb8129112c98a73ec7d2980061899b8df Mon Sep 17 00:00:00 2001 From: gayablau Date: Sun, 28 Jul 2024 15:24:25 +0300 Subject: [PATCH 01/11] add tap android and basic test --- detox/detox.d.ts | 7 +++++++ detox/src/devices/runtime/RuntimeDevice.js | 4 ++++ .../src/devices/runtime/RuntimeDevice.test.js | 7 +++++++ .../runtime/drivers/DeviceDriverBase.js | 4 ++++ .../runtime/drivers/android/AndroidDriver.js | 4 ++++ detox/test/e2e/06.device.test.js | 7 +++++++ detox/test/src/Screens/DeviceTapScreen.tsx | 18 ++++++++++++++++++ detox/test/src/Screens/index.js | 2 ++ detox/test/src/app.js | 1 + 9 files changed, 54 insertions(+) create mode 100644 detox/test/src/Screens/DeviceTapScreen.tsx diff --git a/detox/detox.d.ts b/detox/detox.d.ts index f22d5baba8..228f862db9 100644 --- a/detox/detox.d.ts +++ b/detox/detox.d.ts @@ -781,6 +781,13 @@ declare global { */ setOrientation(orientation: Orientation): Promise; + + /** + * Perform a click at arbitrary coordinates on the default display specified by the user. Currently only available in the Android Simulator. + */ + tap(point?: Point2D): Promise; + + /** * Sets the simulator/emulator location to the given latitude and longitude. * diff --git a/detox/src/devices/runtime/RuntimeDevice.js b/detox/src/devices/runtime/RuntimeDevice.js index 8d7f07f55d..c8cb5e93f0 100644 --- a/detox/src/devices/runtime/RuntimeDevice.js +++ b/detox/src/devices/runtime/RuntimeDevice.js @@ -278,6 +278,10 @@ class RuntimeDevice { await this.deviceDriver.setOrientation(orientation); } + async tap(point) { + await this.deviceDriver.tap(point); + } + async setLocation(lat, lon) { lat = String(lat); lon = String(lon); diff --git a/detox/src/devices/runtime/RuntimeDevice.test.js b/detox/src/devices/runtime/RuntimeDevice.test.js index f32bcb5772..62852ea28d 100644 --- a/detox/src/devices/runtime/RuntimeDevice.test.js +++ b/detox/src/devices/runtime/RuntimeDevice.test.js @@ -816,6 +816,13 @@ describe('Device', () => { expect(driverMock.driver.setOrientation).toHaveBeenCalledWith('param'); }); + it(`tap() should pass to device driver`, async () => { + const device = await aValidDevice(); + await device.tap('param'); + + expect(driverMock.driver.tap).toHaveBeenCalledWith('param'); + }); + it(`sendUserNotification() should pass to device driver`, async () => { const device = await aValidDevice(); await device.sendUserNotification('notif'); diff --git a/detox/src/devices/runtime/drivers/DeviceDriverBase.js b/detox/src/devices/runtime/drivers/DeviceDriverBase.js index c38765aab4..658ab515b3 100644 --- a/detox/src/devices/runtime/drivers/DeviceDriverBase.js +++ b/detox/src/devices/runtime/drivers/DeviceDriverBase.js @@ -51,6 +51,10 @@ class DeviceDriverBase { return ''; } + async tap(point) { + return ''; + } + async sendToHome() { return ''; } diff --git a/detox/src/devices/runtime/drivers/android/AndroidDriver.js b/detox/src/devices/runtime/drivers/android/AndroidDriver.js index 7f0f2cbc30..00d437f428 100644 --- a/detox/src/devices/runtime/drivers/android/AndroidDriver.js +++ b/detox/src/devices/runtime/drivers/android/AndroidDriver.js @@ -245,6 +245,10 @@ class AndroidDriver extends DeviceDriverBase { await this.invocationManager.execute(call); } + async tap(point) { + await this.uiDevice.click(point.x, point.y); + } + _getAppInstallPaths(_appBinaryPath, _testBinaryPath) { const appBinaryPath = getAbsoluteBinaryPath(_appBinaryPath); const testBinaryPath = _testBinaryPath ? getAbsoluteBinaryPath(_testBinaryPath) : this._getTestApkPath(appBinaryPath); diff --git a/detox/test/e2e/06.device.test.js b/detox/test/e2e/06.device.test.js index 2aa42d88ec..f2a5ab6276 100644 --- a/detox/test/e2e/06.device.test.js +++ b/detox/test/e2e/06.device.test.js @@ -84,4 +84,11 @@ describe('Device', () => { await device.pressBack(); await expect(element(by.text('Back pressed !'))).toBeVisible(); }); + + it.only(':android: tap on screen', async () => { + await element(by.text('Device Tap')).tap(); + const point = {x: 200, y: 200} + await device.tap(point); + await expect(element(by.text('Screen Tapped'))).toBeVisible(); + }); }); diff --git a/detox/test/src/Screens/DeviceTapScreen.tsx b/detox/test/src/Screens/DeviceTapScreen.tsx new file mode 100644 index 0000000000..0fdf6b18d4 --- /dev/null +++ b/detox/test/src/Screens/DeviceTapScreen.tsx @@ -0,0 +1,18 @@ +import React, {useCallback, useState} from 'react'; +import {Text, TouchableOpacity} from 'react-native'; + +const DeviceTapScreen = () => { + const [shouldShowText, setShouldShowText] = useState(false); + + const onPressButton = useCallback(() => { + setShouldShowText(true); + }, [setShouldShowText]); + + return ( + + {shouldShowText && {'Screen Tapped'}} + + ); +}; + +export default DeviceTapScreen; diff --git a/detox/test/src/Screens/index.js b/detox/test/src/Screens/index.js index 64c60e82ff..83bcaefde1 100644 --- a/detox/test/src/Screens/index.js +++ b/detox/test/src/Screens/index.js @@ -22,6 +22,7 @@ import LaunchArgsScreen from './LaunchArgsScreen'; import LaunchNotificationScreen from './LaunchNotificationScreen'; import PickerViewScreen from './PickerViewScreen'; import DeviceScreen from './DeviceScreen'; +import DeviceTapScreen from './DeviceTapScreen'; import OverlayScreen from './OverlayScreen'; import ElementScreenshotScreen from './ElementScreenshotScreen'; import VirtualizedListStressScreen from './VirtualizedListStressScreen'; @@ -58,6 +59,7 @@ export { LaunchArgsScreen, LaunchNotificationScreen, DeviceScreen, + DeviceTapScreen, OverlayScreen, ElementScreenshotScreen, WebViewScreen, diff --git a/detox/test/src/app.js b/detox/test/src/app.js index cbb778894d..1ec9f3a61a 100644 --- a/detox/test/src/app.js +++ b/detox/test/src/app.js @@ -90,6 +90,7 @@ export default class example extends Component { {this.renderScreenButton('Network', Screens.NetworkScreen)} {this.renderAnimationScreenButtons()} {this.renderScreenButton('Device', Screens.DeviceScreen)} + {this.renderScreenButton('Device Tap', Screens.DeviceTapScreen)} {isIos && this.renderScreenButton('Overlay', Screens.OverlayScreen)} {this.renderScreenButton('Location', Screens.LocationScreen)} {this.renderScreenButton('DatePicker', Screens.DatePickerScreen)} From 2114892e93a40b4271c83b4415988dd518016161 Mon Sep 17 00:00:00 2001 From: gayablau Date: Mon, 29 Jul 2024 10:17:39 +0300 Subject: [PATCH 02/11] update tests --- detox/detox.d.ts | 2 -- .../runtime/drivers/android/AndroidDriver.js | 4 +++- detox/test/e2e/06.device.test.js | 8 ++++++- detox/test/src/Screens/DeviceTapScreen.tsx | 23 +++++++++++++------ 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/detox/detox.d.ts b/detox/detox.d.ts index 228f862db9..c1110e417c 100644 --- a/detox/detox.d.ts +++ b/detox/detox.d.ts @@ -781,13 +781,11 @@ declare global { */ setOrientation(orientation: Orientation): Promise; - /** * Perform a click at arbitrary coordinates on the default display specified by the user. Currently only available in the Android Simulator. */ tap(point?: Point2D): Promise; - /** * Sets the simulator/emulator location to the given latitude and longitude. * diff --git a/detox/src/devices/runtime/drivers/android/AndroidDriver.js b/detox/src/devices/runtime/drivers/android/AndroidDriver.js index 00d437f428..f57c06ff88 100644 --- a/detox/src/devices/runtime/drivers/android/AndroidDriver.js +++ b/detox/src/devices/runtime/drivers/android/AndroidDriver.js @@ -246,7 +246,9 @@ class AndroidDriver extends DeviceDriverBase { } async tap(point) { - await this.uiDevice.click(point.x, point.y); + let x = point?.x || await this.uiDevice.getDisplayWidth() / 2; + let y = point?.y || await this.uiDevice.getDisplayHeight() / 2; + await this.uiDevice.click(x, y); } _getAppInstallPaths(_appBinaryPath, _testBinaryPath) { diff --git a/detox/test/e2e/06.device.test.js b/detox/test/e2e/06.device.test.js index f2a5ab6276..19258844dc 100644 --- a/detox/test/e2e/06.device.test.js +++ b/detox/test/e2e/06.device.test.js @@ -86,9 +86,15 @@ describe('Device', () => { }); it.only(':android: tap on screen', async () => { + await element(by.text('Device Tap')).tap(); + await device.tap(); + await expect(element(by.text('Screen Tapped'))).toBeVisible(); + }); + + it(':android: tap on screen by coordinates', async () => { await element(by.text('Device Tap')).tap(); const point = {x: 200, y: 200} await device.tap(point); - await expect(element(by.text('Screen Tapped'))).toBeVisible(); + await expect(element(by.text('Button Tapped'))).toBeVisible(); }); }); diff --git a/detox/test/src/Screens/DeviceTapScreen.tsx b/detox/test/src/Screens/DeviceTapScreen.tsx index 0fdf6b18d4..1d258d1863 100644 --- a/detox/test/src/Screens/DeviceTapScreen.tsx +++ b/detox/test/src/Screens/DeviceTapScreen.tsx @@ -1,16 +1,25 @@ -import React, {useCallback, useState} from 'react'; -import {Text, TouchableOpacity} from 'react-native'; +import React, { useCallback, useState } from 'react'; +import { Button, Text, TouchableOpacity, View } from 'react-native'; const DeviceTapScreen = () => { - const [shouldShowText, setShouldShowText] = useState(false); + const [shouldShowScreenText, setShouldShowScreenText] = useState(false); + const [shouldShowButtonText, setShouldShowButtonText] = useState(false); + + const onPressScreen = useCallback(() => { + setShouldShowScreenText(true); + }, [setShouldShowScreenText]); const onPressButton = useCallback(() => { - setShouldShowText(true); - }, [setShouldShowText]); + setShouldShowButtonText(true); + }, [setShouldShowScreenText]); return ( - - {shouldShowText && {'Screen Tapped'}} + + +