Skip to content
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ If you'd like to test a release app, which can be released from app store as-is,

Appium Flutter Driver version `3.0.0` requires Appium 3.

The driver package is ESM-only. Appium loads it as an extension automatically; programmatic Node.js consumers must use `import` or dynamic `import()` instead of `require()`.

```
appium driver install --source=npm appium-flutter-driver
```
Expand Down
3 changes: 3 additions & 0 deletions driver/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## Next
- Convert the driver package from CommonJS to ESM

## 3.10.1
- Fix loading the ESM-only `appium-flutter-finder` dependency from the CommonJS driver ([#923](https://github.com/appium/appium-flutter-driver/issues/923))

Expand Down
14 changes: 4 additions & 10 deletions driver/lib/commands/assertions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type {SerializableFinder} from 'appium-flutter-finder';
import {byValueKey, byText, byTooltip, type SerializableFinder} from 'appium-flutter-finder';

import type {FlutterDriver} from '../driver';
import type {FlutterDriver} from '../driver.js';

export type FinderInput =
| {key: string}
Expand All @@ -10,10 +10,6 @@ export type FinderInput =
| string
| {getRawFinder: () => SerializableFinder}; // FlutterElement-like input

let finderModule: Promise<typeof import('appium-flutter-finder')> | undefined;

const loadFinder = () => (finderModule ??= import('appium-flutter-finder'));

// Serialize a finder to base64
const serializeFinder = (finder: SerializableFinder): string => Buffer.from(JSON.stringify(finder)).toString('base64');

Expand All @@ -25,7 +21,7 @@ const isFlutterElementLike = (input: any): input is {getRawFinder: () => Seriali
input && typeof input === 'object' && typeof input.getRawFinder === 'function';

// Convert FinderInput to base64 string
async function getFinderBase64(input: FinderInput): Promise<string> {
function getFinderBase64(input: FinderInput): string {
if (typeof input === 'string') {
return input; // already base64
}
Expand All @@ -38,8 +34,6 @@ async function getFinderBase64(input: FinderInput): Promise<string> {
return serializeFinder(input);
}

const {byValueKey, byText, byTooltip} = await loadFinder();

if ('key' in input) {
return byValueKey(input.key);
}
Expand All @@ -63,7 +57,7 @@ async function executeAssertion(
timeout = 5000,
extraArgs: object = {},
): Promise<void> {
const base64 = await getFinderBase64(input);
const base64 = getFinderBase64(input);
try {
await driver.executeElementCommand(command, base64, {
timeout,
Expand Down
2 changes: 1 addition & 1 deletion driver/lib/commands/clipboard.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type {FlutterDriver} from '../driver';
import type {FlutterDriver} from '../driver.js';

/**
* Set clipboard content via each native app driver
Expand Down
4 changes: 2 additions & 2 deletions driver/lib/commands/context.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type {FlutterDriver} from '../driver';
import {log} from '../logger';
import type {FlutterDriver} from '../driver.js';
import {log} from '../logger.js';

export const FLUTTER_CONTEXT_NAME = `FLUTTER`;
export const NATIVE_CONTEXT_NAME = `NATIVE_APP`;
Expand Down
2 changes: 1 addition & 1 deletion driver/lib/commands/element.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type {FlutterDriver} from '../driver';
import type {FlutterDriver} from '../driver.js';

export const getText = async function (this: FlutterDriver, el: string): Promise<string | null> {
const response = await this.executeElementCommand(`get_text`, el);
Expand Down
12 changes: 6 additions & 6 deletions driver/lib/commands/execute.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import B from 'bluebird';

/* eslint-disable @typescript-eslint/no-non-null-assertion */
import type {FlutterDriver} from '../driver';
import {reConnectFlutterDriver} from '../sessions/session';
import {launchApp} from './../ios/app';
import {assertVisible, assertNotVisible, assertTappable, type FinderInput} from './assertions';
import {longTap, scroll, scrollIntoView, scrollUntilVisible, scrollUntilTapable} from './execute/scroll';
import {waitFor, waitForAbsent, waitForTappable} from './execute/wait';
import type {FlutterDriver} from '../driver.js';
import {reConnectFlutterDriver} from '../sessions/session.js';
import {launchApp} from './../ios/app.js';
import {assertVisible, assertNotVisible, assertTappable, type FinderInput} from './assertions.js';
import {longTap, scroll, scrollIntoView, scrollUntilVisible, scrollUntilTapable} from './execute/scroll.js';
import {waitFor, waitForAbsent, waitForTappable} from './execute/wait.js';

const flutterCommandRegex = /^[\s]*flutter[\s]*:(.+)/;

Expand Down
4 changes: 2 additions & 2 deletions driver/lib/commands/execute/scroll.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import _ from 'lodash';

import type {FlutterDriver} from '../../driver';
import {waitFor, waitForTappable} from './wait';
import type {FlutterDriver} from '../../driver.js';
import {waitFor, waitForTappable} from './wait.js';

export const scroll = async (
self: FlutterDriver,
Expand Down
2 changes: 1 addition & 1 deletion driver/lib/commands/execute/wait.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type {FlutterDriver} from '../../driver';
import type {FlutterDriver} from '../../driver.js';

const waitForConstructor =
(command: `waitForAbsent` | `waitFor` | `waitForTappable`) =>
Expand Down
4 changes: 2 additions & 2 deletions driver/lib/commands/gesture.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type {FlutterDriver} from '../driver';
import {longTap as longClick} from './execute/scroll';
import type {FlutterDriver} from '../driver.js';
import {longTap as longClick} from './execute/scroll.js';

export const click = async function (this: FlutterDriver, el: string) {
const retVal = await this.tapEl(el, false);
Expand Down
4 changes: 2 additions & 2 deletions driver/lib/commands/screen.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type {FlutterDriver} from '../driver';
import type {IsolateSocket} from '../sessions/isolate_socket';
import type {FlutterDriver} from '../driver.js';
import type {IsolateSocket} from '../sessions/isolate_socket.js';

export const getScreenshot = async function (this: FlutterDriver) {
const response = (await (this.socket as IsolateSocket).call(`_flutter.screenshot`)) as any;
Expand Down
28 changes: 14 additions & 14 deletions driver/lib/driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,30 @@ import type {
} from '@appium/types';
import type {AndroidUiautomator2Driver} from 'appium-uiautomator2-driver';
import {XCUITestDriver} from 'appium-xcuitest-driver';
import {BaseDriver} from 'appium/driver';
import {BaseDriver} from 'appium/driver.js';
// @ts-ignore: no 'errors' export module
import _ from 'lodash';

import {getClipboard, setClipboard} from './commands/clipboard';
import {getClipboard, setClipboard} from './commands/clipboard.js';
import {
driverShouldDoProxyCmd,
FLUTTER_CONTEXT_NAME,
getContexts,
getCurrentContext,
NATIVE_CONTEXT_NAME,
setContext,
} from './commands/context';
import {clear, getText, setValue} from './commands/element';
import {execute} from './commands/execute';
import {click, longTap, performTouch, tap, tapEl} from './commands/gesture';
import {getScreenshot} from './commands/screen';
import {desiredCapConstraints} from './desired-caps';
import {log as logger} from './logger';
import {PLATFORM} from './platform';
import type {IsolateSocket} from './sessions/isolate_socket';
import type {LogMonitor} from './sessions/log-monitor';
import {executeElementCommand, executeGetVMCommand, executeGetIsolateCommand} from './sessions/observatory';
import {createSession, reConnectFlutterDriver} from './sessions/session';
} from './commands/context.js';
import {clear, getText, setValue} from './commands/element.js';
import {execute} from './commands/execute.js';
import {click, longTap, performTouch, tap, tapEl} from './commands/gesture.js';
import {getScreenshot} from './commands/screen.js';
import {desiredCapConstraints} from './desired-caps.js';
import {log as logger} from './logger.js';
import {PLATFORM} from './platform.js';
import type {IsolateSocket} from './sessions/isolate_socket.js';
import type {LogMonitor} from './sessions/log-monitor.js';
import {executeElementCommand, executeGetVMCommand, executeGetIsolateCommand} from './sessions/observatory.js';
import {createSession, reConnectFlutterDriver} from './sessions/session.js';

type FluttertDriverConstraints = typeof desiredCapConstraints;
// Need to not proxy in WebView context
Expand Down
2 changes: 1 addition & 1 deletion driver/lib/ios/app.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {services, INSTRUMENT_CHANNEL} from 'appium-ios-device';

import {log} from './../logger';
import {log} from './../logger.js';

/**
* Launch the given bundle id via instrument service.
Expand Down
10 changes: 5 additions & 5 deletions driver/lib/sessions/android.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type {InitialOpts, StringRecord} from '@appium/types';
import type {AndroidUiautomator2Driver} from 'appium-uiautomator2-driver';

import type {FlutterDriver} from '../driver';
import type {IsolateSocket} from './isolate_socket';
import {LogMonitor} from './log-monitor';
import type {LogEntry} from './log-monitor';
import {connectSocket, extractObservatoryUrl, OBSERVATORY_URL_PATTERN} from './observatory';
import type {FlutterDriver} from '../driver.js';
import type {IsolateSocket} from './isolate_socket.js';
import {LogMonitor} from './log-monitor.js';
import type {LogEntry} from './log-monitor.js';
import {connectSocket, extractObservatoryUrl, OBSERVATORY_URL_PATTERN} from './observatory.js';

const VM_SERVICE_PORT_EXTRA = `vm-service-port`;
const DISABLE_SERVICE_AUTH_CODES_EXTRA = `disable-service-auth-codes`;
Expand Down
12 changes: 6 additions & 6 deletions driver/lib/sessions/ios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import net from 'node:net';

import {utilities} from 'appium-ios-device';
import {XCUITestDriver} from 'appium-xcuitest-driver';
import type {XCUITestDriverOpts} from 'appium-xcuitest-driver/build/lib/driver';
import type {XCUITestDriverOpts} from 'appium-xcuitest-driver/build/lib/driver.js';
import B from 'bluebird';
import {checkPortStatus} from 'portscanner';

import type {FlutterDriver} from '../driver';
import type {IsolateSocket} from './isolate_socket';
import {LogMonitor} from './log-monitor';
import type {LogEntry} from './log-monitor';
import {connectSocket, extractObservatoryUrl, OBSERVATORY_URL_PATTERN} from './observatory';
import type {FlutterDriver} from '../driver.js';
import type {IsolateSocket} from './isolate_socket.js';
import {LogMonitor} from './log-monitor.js';
import type {LogEntry} from './log-monitor.js';
import {connectSocket, extractObservatoryUrl, OBSERVATORY_URL_PATTERN} from './observatory.js';

const LOCALHOST = `127.0.0.1`;

Expand Down
8 changes: 4 additions & 4 deletions driver/lib/sessions/observatory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import {URL} from 'node:url';
import {retryInterval} from 'asyncbox';
import _ from 'lodash';

import type {FlutterDriver} from '../driver';
import {decode} from './base64url';
import {IsolateSocket} from './isolate_socket';
import type {LogEntry} from './log-monitor';
import type {FlutterDriver} from '../driver.js';
import {decode} from './base64url.js';
import {IsolateSocket} from './isolate_socket.js';
import type {LogEntry} from './log-monitor.js';

const truncateLength = 500;
// https://github.com/flutter/flutter/blob/f90b019c68edf4541a4c8273865a2b40c2c01eb3/dev/devicelab/lib/framework/runner.dart#L183
Expand Down
8 changes: 4 additions & 4 deletions driver/lib/sessions/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import type {AndroidUiautomator2Driver} from 'appium-uiautomator2-driver';
import type {XCUITestDriver} from 'appium-xcuitest-driver';
import _ from 'lodash';

import type {FlutterDriver} from '../driver';
import {PLATFORM} from '../platform';
import {startAndroidSession, connectAndroidSession} from './android';
import {startIOSSession, connectIOSSession} from './ios';
import type {FlutterDriver} from '../driver.js';
import {PLATFORM} from '../platform.js';
import {startAndroidSession, connectAndroidSession} from './android.js';
import {startIOSSession, connectIOSSession} from './ios.js';

export const reConnectFlutterDriver = async function (this: FlutterDriver, caps: Record<string, any>) {
// setup proxies - if platformName is not empty, make it less case sensitive
Expand Down
5 changes: 3 additions & 2 deletions driver/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@
"npm-shrinkwrap.json",
"scripts"
],
"type": "module",
"main": "./build/lib/driver.js",
"types": "./build/lib/index.d.ts",
"types": "./build/lib/driver.d.ts",
"scripts": {
"build": "tsc -b",
"dev": "npm run build -- --watch",
Expand All @@ -36,7 +37,7 @@
"format:check": "oxfmt -c oxfmt.config.mjs --check .",
"prepublishOnly": "cp ../README.md ../LICENSE ./",
"prepare": "npm run clean && npm run build",
"test": "npm run build && node --test test/*.test.cjs",
"test": "npm run build && node --test test/*.test.mjs",
"clean-dependency": "rm -rf node_modules && rm -f package-lock.json"
},
"dependencies": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const assert = require('node:assert/strict');
const {it} = require('node:test');
import assert from 'node:assert/strict';
import {it} from 'node:test';

const {assertVisible} = require('../build/lib/commands/assertions.js');
import {assertVisible} from '../build/lib/commands/assertions.js';

it('loads the ESM finder from the CommonJS driver', async () => {
it('loads the ESM finder from the ESM driver', async () => {
let command;
let finder;
let options;
Expand All @@ -23,3 +23,9 @@ it('loads the ESM finder from the CommonJS driver', async () => {
});
assert.deepEqual(options, {timeout: 5000, visible: true});
});

it('loads the driver entry point as ESM', async () => {
const {FlutterDriver} = await import('../build/lib/driver.js');

assert.equal(typeof FlutterDriver, 'function');
});
Loading