diff --git a/README.md b/README.md index 3f70cb02..017195c0 100644 --- a/README.md +++ b/README.md @@ -306,13 +306,11 @@ Please replace them properly with your client. | :question: | :ok: | `driver.execute('flutter:waitForFirstFrame')` | Widget | | - | :ok: | (Ruby) `driver.execute_script 'flutter:connectObservatoryWsUrl'` | Flutter Driver | | - | :ok: | (Ruby) `driver.execute_script 'flutter:launchApp', 'bundleId', {arguments: ['arg1'], environment: {ENV1: 'env'}}` | Flutter Driver | -| dragAndDrop | :ok: | (Python) `driver.execute_script('flutter:commandExtension', payload)` | Command Extension | +| dragAndDropWithCommandExtension | :ok: | (Python) `driver.execute_script('flutter:dragAndDropWithCommandExtension', payload)` | Command Extension | **NOTE** +>`flutter:launchApp` launches an app via instrument service. `mobile:activateApp` and `driver.activate_app` are via XCTest API. They are a bit different. -- `flutter:launchApp` launches an app via instrument service. `mobile:activateApp` and `driver.activate_app` are via XCTest API. They are a bit different. - -- `flutter:commandExtension` is a command extension to flutter driver, which uses [CommandExtension-class](https://api.flutter.dev/flutter/flutter_driver_extension/CommandExtension-class.html) in the `ext.flutter.driver`, how to use it is [here](example/dart/README.md). ### `isolate` handling #### Change the flutter engine attache to @@ -351,6 +349,56 @@ These Appium commands can work across context - `getClipboard` - `setClipboard` +## Command Extension (Flutter Driver) + +This is a command extension for Flutter Driver, utilizing the [CommandExtension-class](https://api.flutter.dev/flutter/flutter_driver_extension/CommandExtension-class.html) within `ext.flutter.driver` + +Available commands: + +- `dragAndDropWithCommandExtension` – performs a drag-and-drop action on the screen by specifying the start and end coordinates and the action duration. + +### How to use + +Copy the [extended_commands.dart](extended_commands.dart) file to the `lib` folder of your Flutter project. + +The entry point must include the `List?` commands argument in either `main.dart` or `test_main.dart` to properly handle the command extension. + + +```dart +import 'extended_commands.dart'; + + +void main() { + enableFlutterDriverExtension( + commands: [DragCommandExtension()]); + runApp(const MyApp()); +} +``` + +#### Simple example using `dragAndDropWithCommandExtension` command in Python + +```python +# python +coord_item_1 = driver.execute_script("flutter:getCenter", item_1) +coord_item_2 = driver.execute_script("flutter:getCenter", item_2) +start_x = coord_item_1["dx"] +start_y = coord_item_1["dy"] +end_y = coord_item_2["dy"] + +payload = { + "startX": start_x, + "startY": start_y, + "endX": "0", + "endY": end_y, + "duration": "15000" # minimum 15000ms needed to drag n drop +} + +driver.execute_script("flutter:dragAndDropWithCommandExtension", payload) +``` + +For debugging or testing in other programming languages, you can use the APK available in this [repository](https://github.com/Alpaca00/command-driven-list) or build an IPA. + + ## Troubleshooting - Input texts https://github.com/appium/appium-flutter-driver/issues/417 diff --git a/driver/lib/commands/execute.ts b/driver/lib/commands/execute.ts index cb9c17d7..6e2cfbfa 100644 --- a/driver/lib/commands/execute.ts +++ b/driver/lib/commands/execute.ts @@ -84,8 +84,8 @@ export const execute = async function( return await setFrameSync(this, args[0], args[1]); case `clickElement`: return await clickElement(this, args[0], args[1]); - case `commandExtension`: - return await commandExtension(this, args[0]); + case `dragAndDropWithCommandExtension`: + return await dragAndDropWithCommandExtension(this, args[0]); default: throw new Error(`Command not support: "${rawCommand}"`); } @@ -221,35 +221,7 @@ const clickElement = async (self:FlutterDriver, elementBase64: string, opts) => }); }; -const commandExtension = async ( - self: FlutterDriver, - commandPayload: { command: string; [key: string]: any } -) => { - const { command, ...params } = commandPayload; - const commandMapping: { - [key: string]: (self: FlutterDriver, params: any) => Promise - } = { - 'dragAndDrop': dragAndDropCommand, - 'commandExtension': async (self, params) => { - const innerCommand = Object.keys(params)[0]; - const innerParams = params[innerCommand]; - if (commandMapping[innerCommand]) { - return await commandMapping[innerCommand](self, innerParams); - } else { - throw new Error(`Inner command not supported: '${innerCommand}'`); - } - }, - }; - - const commandHandler = commandMapping[command]; - if (commandHandler) { - return await commandHandler(self, params); - } else { - throw new Error(`Command not supported`); - } -}; - -const dragAndDropCommand = async ( +const dragAndDropWithCommandExtension = async ( self: FlutterDriver, params: { startX: string; @@ -261,7 +233,7 @@ const dragAndDropCommand = async ( ) => { const { startX, startY, endX, endY, duration } = params; const commandPayload = { - command: 'dragAndDrop', + command: 'dragAndDropWithCommandExtension', startX, startY, endX, diff --git a/example/dart/README.md b/example/dart/README.md deleted file mode 100644 index ac7405c7..00000000 --- a/example/dart/README.md +++ /dev/null @@ -1,49 +0,0 @@ -#### Flutter Driver Extension - -Copy the [extended_commands.dart](extended_commands.dart) file to the `lib` folder of your Flutter project. - -The entry point must include the `List?` commands argument in either `main.dart` or `test_main.dart` to properly handle the command extension. - -```dart -import 'extended_commands.dart'; - - -void main() { - enableFlutterDriverExtension( - commands: [DragCommandExtension()]); - runApp(const MyApp()); -} -``` - -#### Simple example using `dragAndDrop` command -```python -# python -coord_item_1 = driver.execute_script('flutter:getCenter', item_1) -coord_item_2 = driver.execute_script('flutter:getCenter', item_2) -start_x = coord_item_1['dx'] -start_y = coord_item_1['dy'] -end_y = coord_item_2['dy'] - -params = { - "startX": start_x, - "startY": start_y, - "endX": "0", - "endY": end_y, - "duration": "15000" # minimum duration needed to perform the drag & drop is 15000ms -} - -payload = { - "command": "commandExtension", - "dragAndDrop": params -} - -driver.execute_script("flutter:commandExtension", payload) -``` - -#### Simple app with drag and drop functionality with the `extended_commands.dart` module - -Follow the link: [command-driven-list](https://github.com/Alpaca00/command-driven-list) - ---- - -**Note:** Not recommended to use this functionality in the production environment, due to the potential risk of app crashes and other issues. \ No newline at end of file diff --git a/example/dart/extended_commands.dart b/example/dart/extended_commands.dart index d2e79555..c38aa524 100644 --- a/example/dart/extended_commands.dart +++ b/example/dart/extended_commands.dart @@ -16,7 +16,7 @@ class DragCommand extends Command { DragCommand(this.startX, this.startY, this.endX, this.endY, this.duration); @override - String get kind => 'dragAndDrop'; + String get kind => 'dragAndDropWithCommandExtension'; DragCommand.deserialize(Map params) : startX = double.parse(params['startX']!), @@ -56,7 +56,7 @@ class DragCommandExtension extends CommandExtension { } @override - String get commandKind => 'dragAndDrop'; + String get commandKind => 'dragAndDropWithCommandExtension'; @override Command deserialize(