diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..c3fe9a6 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,8 @@ +.github/ +README.md +docs/commands.md +finder.ts +flutter-by/wdio-flutter-by-service/package.json +flutter-by/wdio-flutter-by-service/package-lock.json +*.conf.ts +CHANGELOG.md diff --git a/.prettierrc b/.prettierrc index 1e02497..8df92ae 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,7 +1,7 @@ { - "singleQuote": true, - "tabWidth": 3, - "semi": true, - "trailingComma": "all", - "useTabs": false + "singleQuote": true, + "tabWidth": 3, + "semi": true, + "trailingComma": "all", + "useTabs": false } diff --git a/android.conf.ts b/android.conf.ts index 03be472..dc6f9da 100644 --- a/android.conf.ts +++ b/android.conf.ts @@ -2,17 +2,17 @@ import { join } from 'node:path'; import { config as baseConfig } from './wdio.conf.ts'; export const config: WebdriverIO.Config = { - ...baseConfig, - capabilities: [ - { - // capabilities for local Appium web tests on an Android Emulator - platformName: 'Android', - 'appium:automationName': 'FlutterIntegration', - 'appium:orientation': 'PORTRAIT', - 'appium:app': - process.env.APP_PATH || join(process.cwd(), 'app-debug.apk'), - 'appium:newCommandTimeout': 240, - 'appium:flutterServerLaunchTimeout': 10000, - }, - ], + ...baseConfig, + capabilities: [ + { + // capabilities for local Appium web tests on an Android Emulator + platformName: 'Android', + 'appium:automationName': 'FlutterIntegration', + 'appium:orientation': 'PORTRAIT', + 'appium:app': + process.env.APP_PATH || join(process.cwd(), 'app-debug.apk'), + 'appium:newCommandTimeout': 240, + 'appium:flutterServerLaunchTimeout': 10000, + }, + ], }; diff --git a/finder.ts b/finder.ts index ba66303..3ee5948 100644 --- a/finder.ts +++ b/finder.ts @@ -3,122 +3,122 @@ import { command } from 'webdriver'; import path from 'path'; export async function registerCommands() { - const utils = await import( - path.join( - require.resolve('webdriverio').replace('cjs/index.js', ''), - 'utils', - 'getElementObject.js', - ) - ); + const utils = await import( + path.join( + require.resolve('webdriverio').replace('cjs/index.js', ''), + 'utils', + 'getElementObject.js', + ) + ); - function handler(multi: boolean = false) { - return async function (value: string) { - let findElement; + function handler(multi: boolean = false) { + return async function (value: string) { + let findElement; - let args = ['key', value]; - let suffix = multi ? 'elements' : 'element'; - if (this['elementId']) { - args = [this['elementId'], 'key', value]; - findElement = command( - 'POST', - `/session/:sessionId/element/:elementId/${suffix}`, - { - command: 'flutterFinderByKey', - description: 'a new WebDriver command', - ref: 'https://vendor.com/commands/#myNewCommand', - variables: [ - { - name: 'elementId', - type: 'string', - description: 'a valid parameter', - required: true, - }, - ], - parameters: [ - { - name: 'using', - type: 'string', - description: 'a valid parameter', - required: true, - }, - { - name: 'value', - type: 'string', - description: 'a valid parameter', - required: true, - }, - ], - returns: { - type: 'object', - name: 'element', - description: - "A JSON representation of an element object, e.g. `{ 'element-6066-11e4-a52e-4f735466cecf': 'ELEMENT_1' }`.", - }, - }, - ); - } else { - findElement = command('POST', `/session/:sessionId/${suffix}`, { - command: 'flutterFinderByKey', - description: 'a new WebDriver command', - ref: 'https://vendor.com/commands/#myNewCommand', - variables: [], - parameters: [ - { - name: 'using', - type: 'string', - description: 'a valid parameter', - required: true, - }, - { - name: 'value', - type: 'string', - description: 'a valid parameter', - required: true, - }, - { - name: 'context', - type: 'string', - description: 'a valid parameter', - required: false, - }, - ], - returns: { - type: 'object', - name: 'element', - description: - "A JSON representation of an element object, e.g. `{ 'element-6066-11e4-a52e-4f735466cecf': 'ELEMENT_1' }`.", - }, - }); - } + let args = ['key', value]; + let suffix = multi ? 'elements' : 'element'; + if (this['elementId']) { + args = [this['elementId'], 'key', value]; + findElement = command( + 'POST', + `/session/:sessionId/element/:elementId/${suffix}`, + { + command: 'flutterFinderByKey', + description: 'a new WebDriver command', + ref: 'https://vendor.com/commands/#myNewCommand', + variables: [ + { + name: 'elementId', + type: 'string', + description: 'a valid parameter', + required: true, + }, + ], + parameters: [ + { + name: 'using', + type: 'string', + description: 'a valid parameter', + required: true, + }, + { + name: 'value', + type: 'string', + description: 'a valid parameter', + required: true, + }, + ], + returns: { + type: 'object', + name: 'element', + description: + "A JSON representation of an element object, e.g. `{ 'element-6066-11e4-a52e-4f735466cecf': 'ELEMENT_1' }`.", + }, + }, + ); + } else { + findElement = command('POST', `/session/:sessionId/${suffix}`, { + command: 'flutterFinderByKey', + description: 'a new WebDriver command', + ref: 'https://vendor.com/commands/#myNewCommand', + variables: [], + parameters: [ + { + name: 'using', + type: 'string', + description: 'a valid parameter', + required: true, + }, + { + name: 'value', + type: 'string', + description: 'a valid parameter', + required: true, + }, + { + name: 'context', + type: 'string', + description: 'a valid parameter', + required: false, + }, + ], + returns: { + type: 'object', + name: 'element', + description: + "A JSON representation of an element object, e.g. `{ 'element-6066-11e4-a52e-4f735466cecf': 'ELEMENT_1' }`.", + }, + }); + } - const response = await findElement.call(browser, ...args); - console.log(utils.getElement); - try { - if (multi) { - return response.map((element: any) => - utils.getElement.call(this, null, element), - ); - } else { - return utils.getElement.call(this, null, response); - } - } catch (e) { - console.log(e); - } - }; - } - browser.addCommand('flutterFinderByKey$', handler()); - browser.addCommand('flutterFinderByKey$', handler(), true); + const response = await findElement.call(browser, ...args); + console.log(utils.getElement); + try { + if (multi) { + return response.map((element: any) => + utils.getElement.call(this, null, element), + ); + } else { + return utils.getElement.call(this, null, response); + } + } catch (e) { + console.log(e); + } + }; + } + browser.addCommand('flutterFinderByKey$', handler()); + browser.addCommand('flutterFinderByKey$', handler(), true); - browser.addCommand('flutterFinderByKey$$', handler(true)); - browser.addCommand('flutterFinderByKey$$', handler(true), true); + browser.addCommand('flutterFinderByKey$$', handler(true)); + browser.addCommand('flutterFinderByKey$$', handler(true), true); - /** - * - * 1. Element visible - * 2. Element not visible - * 3. element enable/disabled - * 4. Element count - * 6. - * - */ + /** + * + * 1. Element visible + * 2. Element not visible + * 3. element enable/disabled + * 4. Element count + * 6. + * + */ } diff --git a/ios.conf.ts b/ios.conf.ts index 37fd47e..e9e7729 100644 --- a/ios.conf.ts +++ b/ios.conf.ts @@ -14,7 +14,6 @@ export const config: WebdriverIO.Config = { 'appium:newCommandTimeout': 240, 'appium:usePreinstalledWDA': true, 'appium:showIOSLog': true, - 'appium:flutterSystemPort': 31321, 'appium:wdaLocalPort': 8456, 'appium:flutterServerLaunchTimeout': 25000, }, diff --git a/src/driver.ts b/src/driver.ts index fe3b9ab..65813b5 100644 --- a/src/driver.ts +++ b/src/driver.ts @@ -212,7 +212,8 @@ export class AppiumFlutterDriver extends BaseDriver { } const systemPort = - this.internalCaps.flutterSystemPort ?? (await getFreePort()); + this.internalCaps.flutterSystemPort || + (isIosSimulator ? null : await getFreePort()); const udid = this.proxydriver.opts.udid!; this.flutterPort = await fetchFlutterServerPort.bind(this)({ @@ -352,13 +353,10 @@ export class AppiumFlutterDriver extends BaseDriver { ); // Add port parameter to launch argument and only supported for iOS - if ( - this.proxydriver instanceof XCUITestDriver && - this.internalCaps?.flutterSystemPort - ) { + if (this.proxydriver instanceof XCUITestDriver) { launchArgs.arguments = _.flatten([ launchArgs.arguments, - `--flutter-server-port=${this.internalCaps.flutterSystemPort}`, + `--flutter-server-port=${this.internalCaps?.flutterSystemPort || this.flutterPort}`, ]); this.log.info( 'Attaching launch arguments to XCUITestDriver ' + diff --git a/src/utils.ts b/src/utils.ts index a6eb2aa..3e0ef32 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -124,16 +124,19 @@ export async function fetchFlutterServerPort( let devicePort = startPort; let forwardedPort = systemPort; - if (isIosSimulator && systemPort) { + if (isIosSimulator && (systemPort || devicePort)) { try { this.log.info( - `Checking if flutter server is running on port ${systemPort} for simulator with id ${udid}`, + `Checking if flutter server is running on port ${systemPort || devicePort} for simulator with id ${udid}`, + ); + await waitForFlutterServer.bind(this)( + (systemPort || devicePort)!, + packageName, ); - await waitForFlutterServer.bind(this)(systemPort!, packageName); this.log.info( - `Flutter server is successfully running on port ${systemPort}`, + `Flutter server is successfully running on port ${systemPort || devicePort}`, ); - return systemPort!; + return (systemPort || devicePort)!; } catch (e) { return null; } diff --git a/test/specs/test.e2e.js b/test/specs/test.e2e.js index f527c33..76f33ad 100644 --- a/test/specs/test.e2e.js +++ b/test/specs/test.e2e.js @@ -9,7 +9,12 @@ async function performLogin(userName = 'admin', password = '1234') { await browser.flutterByValueKey$('password_text_field').clearValue(); await browser.flutterByValueKey$('password').addValue(password); - expect(await browser.flutterByType$('ElevatedButton').flutterByType$("Text").getText()).toEqual('Login'); + expect( + await browser + .flutterByType$('ElevatedButton') + .flutterByType$('Text') + .getText(), + ).toEqual('Login'); await browser.flutterByType$('ElevatedButton').click(); } @@ -30,7 +35,7 @@ describe('My Login application', () => { } await browser.installApp(process.env.APP_PATH); await browser.pause(2000); - if (await browser.isAppInstalled(appID)){ + if (await browser.isAppInstalled(appID)) { console.log('App is installed'); await browser.execute('flutter: launchApp', { appId: appID, diff --git a/tsconfig.json b/tsconfig.json index de968ec..c9eac9c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,25 +1,25 @@ { - "$schema": "https://json.schemastore.org/tsconfig", - "extends": "@appium/tsconfig/tsconfig.json", - "compilerOptions": { - "sourceMap": false, - "target": "es2020", - "module": "NodeNext", - "removeComments": true, - "noImplicitAny": true, - "strictPropertyInitialization": true, - "strictNullChecks": true, - "outDir": "build", - "types": [ - "node", - "@wdio/globals/types", - "@wdio/mocha-framework", - "expect-webdriverio", - "@wdio/types" - ], - "checkJs": true, - "moduleResolution": "Node16", - "resolvePackageJsonExports": true - }, - "include": ["src", "typings/*.d.ts", "finder.ts", "./wdio"] + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@appium/tsconfig/tsconfig.json", + "compilerOptions": { + "sourceMap": false, + "target": "es2020", + "module": "NodeNext", + "removeComments": true, + "noImplicitAny": true, + "strictPropertyInitialization": true, + "strictNullChecks": true, + "outDir": "build", + "types": [ + "node", + "@wdio/globals/types", + "@wdio/mocha-framework", + "expect-webdriverio", + "@wdio/types" + ], + "checkJs": true, + "moduleResolution": "Node16", + "resolvePackageJsonExports": true + }, + "include": ["src", "typings/*.d.ts", "finder.ts", "./wdio"] }