Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Fix/add address #27

Merged
merged 3 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 29 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand All @@ -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

Expand All @@ -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() {
Expand Down Expand Up @@ -91,11 +93,11 @@ 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
Expand All @@ -108,18 +110,20 @@ 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
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

Expand All @@ -140,30 +144,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<WebdriverIO.Element>` | 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<WebdriverIO.Element>` | 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).
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"appium",
"flutter"
],
"version": "1.0.0-beta.14",
"version": "1.0.0-beta.15",
"author": "",
"license": "MIT License",
"repository": {
Expand Down
5 changes: 4 additions & 1 deletion src/desiredCaps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,8 @@ export const desiredCapConstraints = {
},
flutterSystemPort: {
isNumber: true,
}
},
address: {
isString: true,
},
} as const;
51 changes: 31 additions & 20 deletions src/driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,9 @@ export class AppiumFlutterDriver extends BaseDriver<FlutterDriverConstraints> {
'flutter: dragAndDrop': {
command: 'dragAndDrop',
params: {
required: ['source', 'target']
}
}
required: ['source', 'target'],
},
},
};

async doubleClick(origin: any, offset: any) {
Expand Down Expand Up @@ -246,28 +246,39 @@ export class AppiumFlutterDriver extends BaseDriver<FlutterDriverConstraints> {
: 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<FlutterDriverConstraints> = {
flutterServerLaunchTimeout: this.internalCaps.flutterServerLaunchTimeout || 5000,
flutterSystemPort: this.internalCaps.flutterSystemPort || await getFreePort(),
flutterServerLaunchTimeout:
this.internalCaps.flutterServerLaunchTimeout || 5000,
flutterSystemPort:
this.internalCaps.flutterSystemPort || (await getFreePort()),
} as DriverCaps<FlutterDriverConstraints>;
const systemPort =
this.proxydriver instanceof XCUITestDriver &&
Expand All @@ -281,7 +292,7 @@ export class AppiumFlutterDriver extends BaseDriver<FlutterDriverConstraints> {
packageName,
...portcallbacks,
systemPort,
flutterCaps
flutterCaps,
});

if (!this.flutterPort) {
Expand All @@ -294,7 +305,7 @@ export class AppiumFlutterDriver extends BaseDriver<FlutterDriverConstraints> {

// @ts-ignore
this.proxy = new JWProxy({
server: '127.0.0.1',
server: this.internalCaps.address || '127.0.0.1',
port: this.flutterPort,
});

Expand Down
Loading
Loading