Skip to content

Commit

Permalink
chore: Replace occurrences of the deprecated errorAndThrow API
Browse files Browse the repository at this point in the history
  • Loading branch information
mykola-mokhnach committed Dec 12, 2024
1 parent 4f86b4c commit f151ece
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 27 deletions.
4 changes: 2 additions & 2 deletions lib/commands/applescript.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ export async function macosExecAppleScript (opts = {}) {
timeout,
} = opts;
if (!script && !command) {
this.log.errorAndThrow('AppleScript script/command must not be empty');
throw this.log.errorWithException('AppleScript script/command must not be empty');
}
if (/\n/.test(/** @type {string} */(command))) {
this.log.errorAndThrow('AppleScript commands cannot contain line breaks');
throw this.log.errorWithException('AppleScript commands cannot contain line breaks');
}
// 'command' has priority over 'script'
const shouldRunScript = !command;
Expand Down
77 changes: 52 additions & 25 deletions lib/commands/record-screen.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import _ from 'lodash';
import { waitForCondition } from 'asyncbox';
import { util, fs, net, tempDir } from 'appium/support';
import log from '../logger';
import { SubProcess } from 'teen_process';
import B from 'bluebird';

Expand All @@ -17,6 +16,7 @@ const DEFAULT_PRESET = 'veryfast';

/**
*
* @this {Mac2Driver}
* @param {string} localFile
* @param {string?} remotePath
* @param {import('@appium/types').StringRecord} [uploadOptions={}]
Expand All @@ -25,7 +25,7 @@ const DEFAULT_PRESET = 'veryfast';
async function uploadRecordedMedia (localFile, remotePath = null, uploadOptions = {}) {
if (_.isEmpty(remotePath) || _.isNil(remotePath)) {
const {size} = await fs.stat(localFile);
log.debug(`The size of the resulting screen recording is ${util.toReadableSizeString(size)}`);
this.log.debug(`The size of the resulting screen recording is ${util.toReadableSizeString(size)}`);
return (await util.toInMemoryBase64(localFile)).toString();
}

Expand All @@ -43,17 +43,29 @@ async function uploadRecordedMedia (localFile, remotePath = null, uploadOptions
return '';
}

async function requireFfmpegPath () {
/**
* @param {import('@appium/types').AppiumLogger} log
*/
async function requireFfmpegPath (log) {
try {
return await fs.which(FFMPEG_BINARY);
} catch (e) {
log.errorAndThrow(`${FFMPEG_BINARY} has not been found in PATH. ` +
`Please make sure it is installed`);
throw log.errorWithException(
`${FFMPEG_BINARY} has not been found in PATH. ` +
`Please make sure it is installed`
);
}
}

class ScreenRecorder {
constructor (videoPath, opts = {}) {
/**
*
* @param {string} videoPath
* @param {import('@appium/types').AppiumLogger} log
* @param {ScreenRecorderOptions} opts
*/
constructor (videoPath, log, opts) {
this._log = log;
this._videoPath = videoPath;
this._process = null;
this._fps = (opts.fps && opts.fps > 0) ? opts.fps : DEFAULT_FPS;
Expand All @@ -77,7 +89,7 @@ class ScreenRecorder {

async _enforceTermination () {
if (this._process && this.isRunning()) {
log.debug('Force-stopping the currently running video recording');
this._log.debug('Force-stopping the currently running video recording');
try {
await this._process.stop('SIGKILL');
} catch (ign) {}
Expand All @@ -91,16 +103,17 @@ class ScreenRecorder {
}

async start () {
const ffmpeg = await requireFfmpegPath();
const ffmpeg = await requireFfmpegPath(this._log);

/** @type {string[]} */
const args = [
'-loglevel', 'error',
'-t', `${this._timeLimit}`,
'-f', 'avfoundation',
...(this._captureCursor ? ['-capture_cursor', '1'] : []),
...(this._captureClicks ? ['-capture_mouse_clicks', '1'] : []),
'-framerate', `${this._fps}`,
'-i', this._deviceId,
'-i', `${this._deviceId}`,
'-vcodec', 'libx264',
'-preset', this._preset,
'-tune', 'zerolatency',
Expand All @@ -112,25 +125,26 @@ class ScreenRecorder {
...(this._videoFilter ? ['-filter:v', this._videoFilter] : []),
];

/** @type {string[]} */
const fullCmd = [
ffmpeg,
...args,
this._videoPath,
];
this._process = new SubProcess(fullCmd[0], fullCmd.slice(1));
log.debug(`Starting ${FFMPEG_BINARY}: ${util.quote(fullCmd)}`);
this._log.debug(`Starting ${FFMPEG_BINARY}: ${util.quote(fullCmd)}`);
this._process.on('output', (stdout, stderr) => {
if (_.trim(stdout || stderr)) {
log.debug(`[${FFMPEG_BINARY}] ${stdout || stderr}`);
this._log.debug(`[${FFMPEG_BINARY}] ${stdout || stderr}`);
}
});
this._process.once('exit', async (code, signal) => {
this._process = null;
if (code === 0) {
log.debug('Screen recording exited without errors');
this._log.debug('Screen recording exited without errors');
} else {
await this._enforceTermination();
log.warn(`Screen recording exited with error code ${code}, signal ${signal}`);
this._log.warn(`Screen recording exited with error code ${code}, signal ${signal}`);
}
});
await this._process.start(0);
Expand All @@ -149,10 +163,12 @@ class ScreenRecorder {
});
} catch (e) {
await this._enforceTermination();
log.errorAndThrow(`The expected screen record file '${this._videoPath}' does not exist. ` +
`Check the server log for more details`);
throw this._log.errorWithException(
`The expected screen record file '${this._videoPath}' does not exist. ` +
`Check the server log for more details`
);
}
log.info(`The video recording has started. Will timeout in ${util.pluralize('second', this._timeLimit, true)}`);
this._log.info(`The video recording has started. Will timeout in ${util.pluralize('second', this._timeLimit, true)}`);
}

async stop (force = false) {
Expand All @@ -161,7 +177,7 @@ class ScreenRecorder {
}

if (!this.isRunning()) {
log.debug('Screen recording is not running. Returning the recent result');
this._log.debug('Screen recording is not running. Returning the recent result');
return await this.getVideoPath();
}

Expand Down Expand Up @@ -215,12 +231,12 @@ export async function startRecordingScreen (options) {
}

if (this._screenRecorder?.isRunning?.()) {
log.debug('The screen recording is already running');
this.log.debug('The screen recording is already running');
if (!forceRestart) {
log.debug('Doing nothing');
this.log.debug('Doing nothing');
return;
}
log.debug('Forcing the active screen recording to stop');
this.log.debug('Forcing the active screen recording to stop');
await this._screenRecorder.stop(true);
}
this._screenRecorder = null;
Expand All @@ -229,7 +245,7 @@ export async function startRecordingScreen (options) {
prefix: util.uuidV4().substring(0, 8),
suffix: `.${DEFAULT_EXT}`,
});
this._screenRecorder = new ScreenRecorder(videoPath, {
this._screenRecorder = new ScreenRecorder(videoPath, this.log, {
fps: parseInt(`${fps}`, 10),
timeLimit: parseInt(`${timeLimit}`, 10),
preset,
Expand Down Expand Up @@ -260,19 +276,30 @@ export async function startRecordingScreen (options) {
*/
export async function stopRecordingScreen (options = {}) {
if (!this._screenRecorder) {
log.debug('No screen recording has been started. Doing nothing');
this.log.debug('No screen recording has been started. Doing nothing');
return '';
}

log.debug('Retrieving the resulting video data');
this.log.debug('Retrieving the resulting video data');
const videoPath = await this._screenRecorder.stop();
if (!videoPath) {
log.debug('No video data is found. Returning an empty string');
this.log.debug('No video data is found. Returning an empty string');
return '';
}
return await uploadRecordedMedia(videoPath, options.remotePath, options);
return await uploadRecordedMedia.bind(this)(videoPath, options.remotePath, options);
};

/**
* @typedef {import('../driver').Mac2Driver} Mac2Driver
*/

/**
* @typedef {Object} ScreenRecorderOptions
* @property {number} [fps]
* @property {string|number} deviceId
* @property {string} [preset]
* @property {boolean} [captureCursor]
* @property {boolean} [captureClicks]
* @property {string} [videoFilter]
* @property {number} [timeLimit]
*/

0 comments on commit f151ece

Please sign in to comment.