Skip to content

Commit

Permalink
feat: Switch babel to typescript (#84)
Browse files Browse the repository at this point in the history
  • Loading branch information
mykola-mokhnach committed Aug 31, 2023
1 parent c7d6736 commit 68ebc60
Show file tree
Hide file tree
Showing 18 changed files with 202 additions and 108 deletions.
17 changes: 14 additions & 3 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
{
"extends": "@appium/eslint-config-appium",
"extends": ["@appium/eslint-config-appium-ts"],
"overrides": [
{
"files": "test/**/*.js",
"rules": {
"func-names": "off"
"func-names": "off",
"@typescript-eslint/no-var-requires": "off"
}
},
{
"files": "scripts/**/*",
"parserOptions": {"sourceType": "script"},
"rules": {
"@typescript-eslint/no-var-requires": "off"
}
}
]
],
"rules": {
"require-await": "error"
}
}
20 changes: 11 additions & 9 deletions .github/workflows/functional-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,33 @@ jobs:
e2e:
runs-on: macos-12
env:
CI: true
PLATFORM_VERSION: '16.0'
XCODE_VERSION: '14.0'
DEVICE_NAME: iPhone 11 Pro Max
PYTHON_VERSION: '3.7'
PYTHON_VERSION: '3.9'

steps:
- uses: actions/checkout@v2
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: ${{ env.XCODE_VERSION }}
- run: xcrun simctl list
- run: brew install python@3.7
- run: |
target_sim_id=$(xcrun simctl list devices available | grep "$DEVICE_NAME (" | cut -d "(" -f2 | cut -d ")" -f1)
open -Fn "$(xcode-select -p)/Applications/Simulator.app"
xcrun simctl bootstatus $target_sim_id -b
xcrun simctl shutdown $target_sim_id
name: Preboot ${{ env.DEVICE_NAME }}
- run: brew install python@${PYTHON_VERSION}
- run: |
brew tap facebook/fb
# use 1.1.7 because xctest doesn't seem to work with 1.1.8 https://github.com/facebook/idb/issues/811
pushd /usr/local/Homebrew/Library/Taps/facebook/homebrew-fb
git checkout f660049bdec9965934973052e6331119a4985096
brew install idb-companion || true
popd
/usr/local/opt/python@3.7/bin/python3.7 -m pip install --user fb-idb
/usr/local/opt/python@${PYTHON_VERSION}/bin/python${PYTHON_VERSION} -m pip install --user fb-idb
- uses: actions/setup-node@v3
with:
node-version: lts/*
check-latest: true
- run: npm install
- run: |
export PATH="${PATH}:$(/usr/local/opt/python@3.7/bin/python3.7 -c 'import site; print(site.USER_BASE)')/bin"
export PATH="${PATH}:$(/usr/local/opt/python@${PYTHON_VERSION}/bin/python${PYTHON_VERSION} -c 'import site; print(site.USER_BASE)')/bin"
_FORCE_LOGS=1 npm run e2e-test
4 changes: 1 addition & 3 deletions .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ jobs:
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: |
npm i -g npm
npm install
- run: npm install
- run: npm run lint
- run: npm run test
2 changes: 1 addition & 1 deletion .mocharc.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
require: ['@babel/register'],
require: ['ts-node/register'],
forbidOnly: Boolean(process.env.CI)
};
25 changes: 0 additions & 25 deletions babel.config.json

This file was deleted.

16 changes: 8 additions & 8 deletions lib/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ const IDB_ENV_PREFIX = 'IDB_';
/**
* @typedef {Object} PidLookupOptions
*
* @property {?boolean} multi [true] - Set it to true if multiple matching
* @property {boolean} [multi=true] - Set it to true if multiple matching
* pids are expected to be found. Only the newest process id is going to
* be returned instead
* @property {?boolean} ignoreCase [true] - Set it to false to make the search
* @property {boolean} [ignoreCase=true] - Set it to false to make the search
* case-sensitive
*/

Expand All @@ -23,8 +23,8 @@ const IDB_ENV_PREFIX = 'IDB_';
* having the particular command line pattern.
*
* @param {string} pattern - pgrep-compatible search pattern.
* @param {?PidLookupOptions} opts
* @return {Array<string>} An array of process ids as strings
* @param {Partial<PidLookupOptions>} opts
* @return {Promise<string[]|string>} An array of process ids as strings
* or an empty array
*/
async function getPids (pattern, opts = {}) {
Expand All @@ -38,15 +38,15 @@ async function getPids (pattern, opts = {}) {
const result = stdout.split('\n')
.filter(Number)
.map((x) => `${x}`);
return multi ? result : (_.isEmpty(result) ? [] : _.first(result));
return multi ? result : (_.isEmpty(result) ? [] : result[0]);
} catch (err) {
return [];
}
}
/**
* Converts an env object to the format what IDB process expects
* @param {Object} env The object of environment variables
* @return {Object}
* @param {Record<string, any>?} env The object of environment variables
* @return {Record<string, any>?}
*/
function convertToIDBEnv (env) {
if (!_.isPlainObject(env) || _.isEmpty(env)) {
Expand All @@ -65,7 +65,7 @@ function convertToIDBEnv (env) {
* a valid array.
*
* @param {string} output The original command output
* @returns {Array<object>} Array of objects or an empty array
* @returns {any[]} Array of objects or an empty array
*/
function fixOutputToArray (output) {
if (!_.trim(output)) {
Expand Down
38 changes: 38 additions & 0 deletions lib/idb.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,45 @@ const DEFAULT_OPTS = {
verbose: false,
};

/**
* @typedef {Object} IdbExecutable
* @property {string} path
* @property {number?} [port]
* @property {number?} [grpcPort]
* @property {string[]} defaultArgs
*/

/**
* @typedef {Object} IdbCompanion
* @property {string} path
* @property {number?} [port]
* @property {number?} [grpcPort]
* @property {string?} [logPath]
*/


class IDB {
/** @type {string} */
udid;
/** @type {string|undefined} */
logLevel;
/** @type {number} */
execTimeout;
/** @type {boolean} */
verbose;
/** @type {IdbExecutable} */
executable;
/** @type {IdbCompanion} */
companion;
/** @type {(cmd: string[], args?: string [], opts?: import('teen_process').TeenProcessExecOptions & {timeoutCapName?: string}) => Promise<string>} */
exec;
/** @type {() => Promise<void>} */
disconnect;
/** @type {(timeout?: number) => Promise<void>} */
waitForDevice;
/** @type {(command?: string[], args?: string[], opts?: import('teen_process').SubProcessOptions) => import('teen_process').SubProcess} */
createSubProcess;

constructor (opts = {}) {
Object.assign(this, opts);
_.defaultsDeep(this, _.cloneDeep(DEFAULT_OPTS));
Expand Down
6 changes: 4 additions & 2 deletions lib/tools/accessibility-commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ const accessibilityCommands = {};
/**
* Describes the Accessibility tree on the device under test
*
* @returns {Array<object>} JSON formatted list of all the elements currently on screen,
* @this {import('../idb.js').IDB}
* @returns {Promise<any[]>} JSON formatted list of all the elements currently on screen,
* including their bounds and accessibility information
*/
accessibilityCommands.describeAll = async function describeAll () {
Expand All @@ -18,7 +19,8 @@ accessibilityCommands.describeAll = async function describeAll () {
* Describes the Accessibility tree on the device under test at
* the particular coordinate point
*
* @returns {?Array<object>} JSON formatted information about a specific point on
* @this {import('../idb.js').IDB}
* @returns {Promise<any[]?>} JSON formatted information about a specific point on
* the screen, if an element exists there.
*/
accessibilityCommands.describePoint = async function describePoint (x, y) {
Expand Down
10 changes: 5 additions & 5 deletions lib/tools/app-commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const appCommands = {};
* {"bundle_id": "com.apple.test.IntegrationTests_1-Runner", "name": "IntegrationTests_1-Runner", "install_type": "user", "architectures": ["x86_64", "i386"], "process_state": "Unknown", "debuggable": false}
* {"bundle_id": "com.apple.mobilesafari", "name": "MobileSafari", "install_type": "system", "architectures": ["x86_64"], "process_state": "Unknown", "debuggable": false}
*
* @returns {Array<object>}
* @returns {Promise<any[]>}
*/
appCommands.listApps = async function listApps () {
log.debug(`Listing the info about installed apps on the device '${this.udid}'`);
Expand All @@ -29,10 +29,10 @@ appCommands.installApp = async function installApp (appPath) {
/**
* @typedef {Object} LaunchOptions
*
* @property {?boolean} foregroundIfRunning [true] - If set to true then
* @property {boolean} [foregroundIfRunning=true] - If set to true then
* the method call will put the given app in foreground if it is
* already running
* @property {?boolean} wait [false] - Set it to true if process
* @property {boolean} [wait=false] - Set it to true if process
* monitoring is needed. See the description of the returned result
* for more details
*/
Expand All @@ -41,8 +41,8 @@ appCommands.installApp = async function installApp (appPath) {
* Starts an installed app on the device under test.
*
* @param {string} bundleId Bundle identifier of the application to launch.
* @param {?LaunchOptions} opts
* @returns {?SubProcess} If `opts.wait` is set to true then SubProcess instance
* @param {LaunchOptions} opts
* @returns {Promise<import('teen_process').SubProcess?>} If `opts.wait` is set to true then SubProcess instance
* is returned, which represents the executed process monitor. The monitor
* will be terminated when the launched is closed. stdout and stderr of the
* remote process will also be forwarded. `null` is returned otherwise.
Expand Down
15 changes: 9 additions & 6 deletions lib/tools/crashlog-commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ const logCommands = {};
/**
* Fetches a list of crash logs present on the target
*
* @returns {Array<object>} The list of fetched logs or an empty array
* @this {import('../idb.js').IDB}
* @returns {Promise<any[]>} The list of fetched logs or an empty array
*/
logCommands.listCrashLogs = async function listCrashLogs (opts = {}) {
const {
Expand All @@ -33,8 +34,9 @@ logCommands.listCrashLogs = async function listCrashLogs (opts = {}) {
/**
* Fetches the crash log with the specified name
*
* @this {import('../idb.js').IDB}
* @param {string} name The name of the log to fetch
* @returns {string} The content of the log
* @returns {Promise<string>} The content of the log
*/
logCommands.fetchCrashLog = async function fetchCrashLog (name) {
log.debug(`Fetching the crash log '${name}' from the device '${this.udid}'`);
Expand All @@ -44,19 +46,20 @@ logCommands.fetchCrashLog = async function fetchCrashLog (name) {
/**
* @typedef {Object} DeleteCrashLogOptions
*
* @property {string} name - If present then only
* @property {string} [name] - If present then only
* this particular log is going to be deleted
* @property {string} before - If set then only logs
* @property {string} [before] - If set then only logs
* before this date will be deleted
* @property {string} since - If set then only logs
* @property {string} [since] - If set then only logs
* after this date will be deleted
* @property {boolean} all - If set then all crash logs
* @property {boolean} [all] - If set then all crash logs
* are going to be deleted
*/

/**
* Deletes crash logs
*
* @this {import('../idb.js').IDB}
* @param {DeleteCrashLogOptions} opts
*/
logCommands.deleteCrashLogs = async function deleteCrashLogs (opts = {}) {
Expand Down
12 changes: 8 additions & 4 deletions lib/tools/interaction-commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,19 @@ const interactionCommands = {};
/**
* Taps at given coordinates
*
* @this {import('../idb.js').IDB}
* @param {number|string} x Tap X coordinate
* @param {number|string} y Tap Y coordinate
*/
interactionCommands.tap = async function tap (x, y) {
log.debug(`Performing tap at (${x}, ${y}) on the device '${this.udid}'`);
await this.exec(['ui', 'tap'], [x, y]);
await this.exec(['ui', 'tap'], [`${x}`, `${y}`]);
};

/**
* Presses a hardware button on device under test
*
* @this {import('../idb.js').IDB}
* @param {string} name One of {APPLE_PAY,HOME,LOCK,SIDE_BUTTON,SIRI}
*/
interactionCommands.pressButton = async function pressButton (name) {
Expand All @@ -29,6 +31,7 @@ interactionCommands.pressButton = async function pressButton (name) {
/**
* Types the given text on the device under test
*
* @this {import('../idb.js').IDB}
* @param {string} text The text to type
*/
interactionCommands.typeText = async function typeText (text) {
Expand All @@ -39,14 +42,15 @@ interactionCommands.typeText = async function typeText (text) {
/**
* @typedef {Object} KeycodeOpts
*
* @property {number|string} duration - The key press duration in float seconds.
* @property {number|string} [duration] - The key press duration in float seconds.
* The option is ignored if multiple key codes are set.
*/

/**
* Send a keycode or key codes sequence to the device under test
*
* @param {number|string|Array<string>|Array<number>} codeOrCodes Single key code
* @this {import('../idb.js').IDB}
* @param {number|string|string[]|number[]} codeOrCodes Single key code
* or array of codes
* @param {KeycodeOpts} opts
*/
Expand All @@ -66,7 +70,7 @@ interactionCommands.pressKeycode = async function pressKeycode (codeOrCodes, opt
}
args.push(codeOrCodes);
}
await this.exec(command, args);
await this.exec(command, args.map(String));
};

export default interactionCommands;

0 comments on commit 68ebc60

Please sign in to comment.