From 3e39e573efdc747e3c121fee4cccf65edf60d96b Mon Sep 17 00:00:00 2001 From: Sudharsan Selvaraj Date: Mon, 1 Jul 2024 11:08:55 +0530 Subject: [PATCH 1/3] add appium:address capabaility --- README.md | 55 +++++++++++++++++++++++++--------------------- package-lock.json | 4 ++-- package.json | 2 +- src/desiredCaps.ts | 5 ++++- src/driver.ts | 51 +++++++++++++++++++++++++----------------- src/utils.ts | 15 +++++++++---- 6 files changed, 79 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index 67d4cda..622872f 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ The current Appium Flutter Driver is built on top of the `flutter_test` SDK, whi This driver is built using [Flutter Integration Test](https://docs.flutter.dev/cookbook/testing/integration/introduction). - :star: **⁠Strong Typing & Fluent APIs:** Ensures robust and easy-to-use interfaces. +:star: **⁠Strong Typing & Fluent APIs:** Ensures robust and easy-to-use interfaces. :star: **⁠Element Handling**: Automatically waits for elements to attach to the DOM before interacting. @@ -35,7 +35,7 @@ This driver is built using [Flutter Integration Test](https://docs.flutter.dev/c :star: **Simplified Powerful Gestures**: Supports powerful yet simplified gestures like LongPress, ScrollToElement, DragAndDrop, and DoubleClick. -:star:*⁠*Element Chaining**: Allows chaining of elements, enabling you to find child elements under a specific parent easily. +:star:*⁠*Element Chaining\*\*: Allows chaining of elements, enabling you to find child elements under a specific parent easily. ## How to Use Appium Flutter Integration Driver @@ -60,7 +60,9 @@ This driver is built using [Flutter Integration Test](https://docs.flutter.dev/c initializeTest(app: const MyApp()); } ``` + If you are in need to configure certain prerequists before the testing app is loaded, you can try the following code: + ```dart import 'package:appium_testing_app/main.dart'; as app; void main() { @@ -91,11 +93,13 @@ Bingo! You are ready to run your tests using Appium Flutter Integration Driver. Check if your Flutter app is running on the device or emulator. For Android + ``` 1. Run adb command `adb logcat | grep flutter` to check if the Flutter app is running. 2. Open the application in the device or emulator manually. 3. Verify the logs in the console. ``` + ``` 06-17 17:02:13.246 32697 32743 I flutter : The Dart VM service is listening on http://127.0.0.1:33339/E2REX61NaiI=/ 06-17 17:02:13.584 32697 32735 I flutter : 00:00 +0: appium flutter server @@ -108,12 +112,13 @@ For Android For iOS Simulator: -```xcrun simctl spawn booted log stream | grep flutter``` +`xcrun simctl spawn booted log stream | grep flutter` Real Device: Check xcode device logs. 2. Open the application in the device or emulator manually. -``` + +```` 06-17 17:02:13.246 32697 32743 I flutter : The Dart VM service is listening on http://127.0.0.1:33339/E2REX61NaiI=/ 06-17 17:02:13.584 32697 32735 I flutter : 00:00 +0: appium flutter server 06-17 17:02:14.814 32697 32735 I flutter : shelfRun HTTP service running on port 9000 @@ -125,7 +130,7 @@ Real Device: Check xcode device logs. ```bash appium driver install --source npm appium-flutter-integration-driver -``` +```` ## Appium Flutter Integration Driver vs. Appium UiAutomator2/XCUITest Driver @@ -140,30 +145,30 @@ For more details, refer to the documentation for each driver: ## Capabilities for Appium Flutter Integration Driver -| Capability | Description | Required | -|----------------------------------|-------------------------------------------------------------------------|----------| -| appium:flutterServerLaunchTimeout | Time in ms to wait for flutter server to be pingable. Default is 5000ms | No | -| appium:flutterSystemPort | The number of the port on the host machine used for the Flutter server. By default the first free port from 10000..11000 range is selected. It is recommended to set this value if you are running parallel tests on the same machine.| No | - +| Capability | Description | Required | +| --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | +| appium:flutterServerLaunchTimeout | Time in ms to wait for flutter server to be pingable. Default is 5000ms | No | +| appium:flutterSystemPort | The number of the port on the host machine used for the Flutter server. By default the first free port from 10000..11000 range is selected. It is recommended to set this value if you are running parallel tests on the same machine. | No | +| appium:address | Address to connect with flutter server | No | ## Locating Elements You can use the following locators to find elements in your Flutter app. Custom finders are built for WDIO. Refer to the [wdio-flutter-by-service](https://www.npmjs.com/package/wdio-flutter-by-service?activeTab=readme). -| Locator | Description | -|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------| -| `flutterByValueKey(value: string): Flutter.Locator` | Locate by value key | -| `flutterByValueKey$(value: string): WebdriverIO.Element` | Locate single element by value key | -| `flutterByValueKey$$(value: string): WebdriverIO.Element[]` | Locate multiple elements by value key | -| `flutterBySemanticsLabel(label: string): Flutter.Locator` | Locate by semantics label | -| `flutterBySemanticsLabel$(label: string): WebdriverIO.Element` | Locate single element by semantics label | -| `flutterBySemanticsLabel$$(label: string): WebdriverIO.Element[]` | Locate multiple elements by semantics label | -| `flutterByText(text: string): Flutter.Locator` | Locate by text | -| `flutterByText$(text: string): WebdriverIO.Element` | Locate single element by text | -| `flutterByType$(text: string): WebdriverIO.Element` | Locate single element by Type(Checkbox, RadioButton, ListView) | -| `flutterByType$$(text: string): WebdriverIO.Element[]` | Locate multiple elements by text(Checkbox, RadioButton, ListView)| -| `flutterDoubleClick(element: WebdriverIO.Element): WebdriverIO.Element` | Double click on an element | -| `flutterWaitForAbsent(options: { element: WebdriverIO.Element; locator: Flutter.Locator; }): void` | Wait for an element to be absent | -| `flutterScrollTillVisible(options: { finder: WebdriverIO.Element; scrollView?: WebdriverIO.Element; scrollDirection?: 'up','right','down','left'; delta?: number; maxScrolls?: number; settleBetweenScrollsTimeout?: number; dragDuration?: number; }): Promise` | Scroll until an element is visible | +| Locator | Description | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | +| `flutterByValueKey(value: string): Flutter.Locator` | Locate by value key | +| `flutterByValueKey$(value: string): WebdriverIO.Element` | Locate single element by value key | +| `flutterByValueKey$$(value: string): WebdriverIO.Element[]` | Locate multiple elements by value key | +| `flutterBySemanticsLabel(label: string): Flutter.Locator` | Locate by semantics label | +| `flutterBySemanticsLabel$(label: string): WebdriverIO.Element` | Locate single element by semantics label | +| `flutterBySemanticsLabel$$(label: string): WebdriverIO.Element[]` | Locate multiple elements by semantics label | +| `flutterByText(text: string): Flutter.Locator` | Locate by text | +| `flutterByText$(text: string): WebdriverIO.Element` | Locate single element by text | +| `flutterByType$(text: string): WebdriverIO.Element` | Locate single element by Type(Checkbox, RadioButton, ListView) | +| `flutterByType$$(text: string): WebdriverIO.Element[]` | Locate multiple elements by text(Checkbox, RadioButton, ListView) | +| `flutterDoubleClick(element: WebdriverIO.Element): WebdriverIO.Element` | Double click on an element | +| `flutterWaitForAbsent(options: { element: WebdriverIO.Element; locator: Flutter.Locator; }): void` | Wait for an element to be absent | +| `flutterScrollTillVisible(options: { finder: WebdriverIO.Element; scrollView?: WebdriverIO.Element; scrollDirection?: 'up','right','down','left'; delta?: number; maxScrolls?: number; settleBetweenScrollsTimeout?: number; dragDuration?: number; }): Promise` | Scroll until an element is visible | For more examples, see the [test file](https://github.com/AppiumTestDistribution/appium-flutter-integration-driver/blob/main/test/specs/test.e2e.js). diff --git a/package-lock.json b/package-lock.json index 76616f7..fe09758 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "appium-flutter-integration-driver", - "version": "1.0.0-beta.14", + "version": "1.0.0-beta.15", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "appium-flutter-integration-driver", - "version": "1.0.0-beta.14", + "version": "1.0.0-beta.15", "license": "MIT License", "dependencies": { "@appium/base-driver": "^9.6.0", diff --git a/package.json b/package.json index 882cbd6..c75e4b2 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "appium", "flutter" ], - "version": "1.0.0-beta.14", + "version": "1.0.0-beta.15", "author": "", "license": "MIT License", "repository": { diff --git a/src/desiredCaps.ts b/src/desiredCaps.ts index 200099d..ff196ee 100644 --- a/src/desiredCaps.ts +++ b/src/desiredCaps.ts @@ -22,5 +22,8 @@ export const desiredCapConstraints = { }, flutterSystemPort: { isNumber: true, - } + }, + address: { + isString: true, + }, } as const; diff --git a/src/driver.ts b/src/driver.ts index 6c98185..ae7b9f0 100644 --- a/src/driver.ts +++ b/src/driver.ts @@ -114,9 +114,9 @@ export class AppiumFlutterDriver extends BaseDriver { 'flutter: dragAndDrop': { command: 'dragAndDrop', params: { - required: ['source', 'target'] - } - } + required: ['source', 'target'], + }, + }, }; async doubleClick(origin: any, offset: any) { @@ -246,28 +246,39 @@ export class AppiumFlutterDriver extends BaseDriver { : this.proxydriver.opts.bundleId!; const portcallbacks: { - portForwardCallback?: PortForwardCallback, - portReleaseCallback?: PortReleaseCallback, + portForwardCallback?: PortForwardCallback; + portReleaseCallback?: PortReleaseCallback; } = {}; if (this.proxydriver instanceof AndroidUiautomator2Driver) { - portcallbacks.portForwardCallback = async (_: string, systemPort: number, devicePort: number) => await androidPortForward( - // @ts-ignore ADB instance is ok - (this.proxydriver as AndroidUiautomator2Driver).adb, - systemPort, - devicePort - ); - portcallbacks.portReleaseCallback = async (_: string, systemPort: number) => await androidRemovePortForward( - // @ts-ignore ADB instance is ok - (this.proxydriver as AndroidUiautomator2Driver).adb, - systemPort - ); + portcallbacks.portForwardCallback = async ( + _: string, + systemPort: number, + devicePort: number, + ) => + await androidPortForward( + // @ts-ignore ADB instance is ok + (this.proxydriver as AndroidUiautomator2Driver).adb, + systemPort, + devicePort, + ); + portcallbacks.portReleaseCallback = async ( + _: string, + systemPort: number, + ) => + await androidRemovePortForward( + // @ts-ignore ADB instance is ok + (this.proxydriver as AndroidUiautomator2Driver).adb, + systemPort, + ); } else if (this.proxydriver.isRealDevice()) { portcallbacks.portForwardCallback = iosPortForward; portcallbacks.portReleaseCallback = iosRemovePortForward; } const flutterCaps: DriverCaps = { - flutterServerLaunchTimeout: this.internalCaps.flutterServerLaunchTimeout || 5000, - flutterSystemPort: this.internalCaps.flutterSystemPort || await getFreePort(), + flutterServerLaunchTimeout: + this.internalCaps.flutterServerLaunchTimeout || 5000, + flutterSystemPort: + this.internalCaps.flutterSystemPort || (await getFreePort()), } as DriverCaps; const systemPort = this.proxydriver instanceof XCUITestDriver && @@ -281,7 +292,7 @@ export class AppiumFlutterDriver extends BaseDriver { packageName, ...portcallbacks, systemPort, - flutterCaps + flutterCaps, }); if (!this.flutterPort) { @@ -294,7 +305,7 @@ export class AppiumFlutterDriver extends BaseDriver { // @ts-ignore this.proxy = new JWProxy({ - server: '127.0.0.1', + server: this.internalCaps.address || '127.0.0.1', port: this.flutterPort, }); diff --git a/src/utils.ts b/src/utils.ts index 3dda795..b2f9771 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -58,7 +58,11 @@ export async function getFreePort() { return await findAPortNotInUse(start, end); } -async function waitForFlutterServer(port: number, packageName: string, flutterCaps: DriverCaps) { +async function waitForFlutterServer( + port: number, + packageName: string, + flutterCaps: DriverCaps, +) { const proxy = new JWProxy({ server: '127.0.0.1', port: port, @@ -71,12 +75,15 @@ async function waitForFlutterServer(port: number, packageName: string, flutterCa return false; } if (response?.appInfo?.packageName === packageName) { - log.info(`Flutter server version the application is build with ${response.serverVersion}`); + log.info( + `Flutter server version the application is build with ${response.serverVersion}`, + ); return true; } else { - throw new Error( + log.info( `Looking for flutter server with package ${packageName}. But found ${response.appInfo?.packageName}`, ); + return false; } } catch (err: any) { log.info(`FlutterServer not reachable on port ${port}, Retrying..`); @@ -96,7 +103,7 @@ export async function fetchFlutterServerPort({ portForwardCallback, portReleaseCallback, packageName, - flutterCaps + flutterCaps, }: { udid: string; systemPort?: number | null; From cbb7b69b8b6ce8d60ef435afe652f0271721f812 Mon Sep 17 00:00:00 2001 From: Sudharsan Selvaraj Date: Mon, 1 Jul 2024 11:14:07 +0530 Subject: [PATCH 2/3] Fix readme --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 622872f..24a061e 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ The current Appium Flutter Driver is built on top of the `flutter_test` SDK, whi This driver is built using [Flutter Integration Test](https://docs.flutter.dev/cookbook/testing/integration/introduction). -:star: **⁠Strong Typing & Fluent APIs:** Ensures robust and easy-to-use interfaces. +:star: **⁠Strong Typing & Fluent APIs**: Ensures robust and easy-to-use interfaces. :star: **⁠Element Handling**: Automatically waits for elements to attach to the DOM before interacting. @@ -35,7 +35,7 @@ This driver is built using [Flutter Integration Test](https://docs.flutter.dev/c :star: **Simplified Powerful Gestures**: Supports powerful yet simplified gestures like LongPress, ScrollToElement, DragAndDrop, and DoubleClick. -:star:*⁠*Element Chaining\*\*: Allows chaining of elements, enabling you to find child elements under a specific parent easily. +:star: **Element Chaining**: Allows chaining of elements, enabling you to find child elements under a specific parent easily. ## How to Use Appium Flutter Integration Driver @@ -118,19 +118,20 @@ Real Device: Check xcode device logs. 2. Open the application in the device or emulator manually. -```` +``` 06-17 17:02:13.246 32697 32743 I flutter : The Dart VM service is listening on http://127.0.0.1:33339/E2REX61NaiI=/ 06-17 17:02:13.584 32697 32735 I flutter : 00:00 +0: appium flutter server 06-17 17:02:14.814 32697 32735 I flutter : shelfRun HTTP service running on port 9000 06-17 17:02:14.814 32697 32735 I flutter : [APPIUM FLUTTER] Appium flutter server is listening on port 9000 06-17 17:02:14.866 32697 32735 I flutter : [APPIUM FLUTTER] New Request [GET] http://127.0.0.1:10000/status 06-17 +``` ## Install the Flutter Integration Driver ```bash appium driver install --source npm appium-flutter-integration-driver -```` +``` ## Appium Flutter Integration Driver vs. Appium UiAutomator2/XCUITest Driver From 8f80587854ccc2fe638a9937f8cc81cfe9d7089a Mon Sep 17 00:00:00 2001 From: Sudharsan Selvaraj Date: Mon, 1 Jul 2024 11:14:55 +0530 Subject: [PATCH 3/3] fix --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 24a061e..1125754 100644 --- a/README.md +++ b/README.md @@ -94,11 +94,9 @@ Check if your Flutter app is running on the device or emulator. For Android -``` 1. Run adb command `adb logcat | grep flutter` to check if the Flutter app is running. 2. Open the application in the device or emulator manually. 3. Verify the logs in the console. -``` ``` 06-17 17:02:13.246 32697 32743 I flutter : The Dart VM service is listening on http://127.0.0.1:33339/E2REX61NaiI=/