Best JavaScript code snippet using appium-xcuitest-driver
driver.js
Source:driver.js  
...555  }556  async deleteSession () {557    await removeAllSessionWebSocketHandlers(this.server, this.sessionId);558    for (const recorder of _.compact([this._recentScreenRecorder, this._audioRecorder])) {559      await recorder.interrupt(true);560      await recorder.cleanup();561    }562    if (!_.isEmpty(this._perfRecorders)) {563      await B.all(this._perfRecorders.map((x) => x.stop(true)));564      this._perfRecorders = [];565    }566    await this.stop();567    if (this.wda && !this.opts.webDriverAgentUrl) {568      if (this.opts.clearSystemFiles) {569        let synchronizationKey = XCUITestDriver.name;570        const derivedDataPath = await this.wda.retrieveDerivedDataPath();571        if (derivedDataPath) {572          synchronizationKey = path.normalize(derivedDataPath);573        }...recordscreen.js
Source:recordscreen.js  
1import { fs, tempDir, logger } from 'appium-support';2import { SubProcess } from 'teen_process';3import log from '../logger';4import { encodeBase64OrUpload } from '../utils';5import iProxy from '../wda/iproxy';6let commands = {};7const MAX_RECORDING_TIME_SEC = 60 * 30;8const DEFAULT_RECORDING_TIME_SEC = 60 * 3;9const DEFAULT_MJPEG_SERVER_PORT = 9100;10const MP4_EXT = '.mp4';11const DEFAULT_FPS = 10;12const FFMPEG_BINARY = 'ffmpeg';13const ffmpegLogger = logger.getLogger(FFMPEG_BINARY);14class ScreenRecorder {15  constructor (udid, videoPath, opts = {}) {16    this.videoPath = videoPath;17    this.opts = opts;18    this.udid = udid;19    this.mainProcess = null;20    this.iproxy = null;21    this.timeoutHandler = null;22  }23  async start (timeoutMs) {24    try {25      await fs.which(FFMPEG_BINARY);26    } catch (err) {27      throw new Error(`'${FFMPEG_BINARY}' binary is not found in PATH. Install it using 'brew install ffmpeg'. ` +28        `Check https://www.ffmpeg.org/download.html for more details.`);29    }30    const localPort = this.opts.remotePort;31    if (this.opts.usePortForwarding) {32      await this.startIproxy(localPort);33    }34    const args = [35      '-f', 'mjpeg',36      '-r', this.opts.videoFps,37      '-i', `http://localhost:${localPort}`,38      '-vcodec', 'mjpeg',39      '-y', this.videoPath,40    ];41    this.mainProcess = new SubProcess(FFMPEG_BINARY, args);42    this.mainProcess.on('output', (stdout, stderr) => {43      if (stderr && !stderr.includes('frame=')) {44        ffmpegLogger.info(`${stderr}`);45      }46    });47    // Give ffmpeg some time for init48    await this.mainProcess.start(5000);49    log.info(`Starting screen capture on the device '${this.udid}' with command: '${FFMPEG_BINARY} ${args.join(' ')}'. ` +50      `Will timeout in ${timeoutMs}ms`);51    this.timeoutHandler = setTimeout(async () => {52      if (!await this.interrupt()) {53        log.warn(`Cannot finish the active screen recording on the device '${this.udid}' after ${timeoutMs}ms timeout`);54      }55    }, timeoutMs);56  }57  async startIproxy (localPort) {58    this.iproxy = new iProxy(this.udid, localPort, this.opts.remotePort);59    try {60      await this.iproxy.start();61    } catch (err) {62      log.warn(`Cannot start iproxy. Assuming it is already forwarding the remote port ${this.opts.remotePort} to ${localPort} ` +63        `for the device ${this.udid}. Set the custom value to 'mjpegServerPort' capability if this is an undesired behavior. ` +64        `Original error: ${err.message}`);65      this.iproxy = null;66    }67  }68  async stopIproxy () {69    if (!this.iproxy) {70      return;71    }72    const quitPromise = this.iproxy.quit();73    this.iproxy = null;74    try {75      await quitPromise;76    } catch (err) {77      log.warn(`Cannot stop iproxy. Original error: ${err.message}`);78    }79  }80  async interrupt (force = false) {81    let result = true;82    if (this.timeoutHandler) {83      clearTimeout(this.timeoutHandler);84      this.timeoutHandler = null;85    }86    if (this.mainProcess && this.mainProcess.isRunning) {87      const interruptPromise = this.mainProcess.stop(force ? 'SIGTERM' : 'SIGINT');88      this.mainProcess = null;89      try {90        await interruptPromise;91      } catch (e) {92        log.warn(`Cannot ${force ? 'terminate' : 'interrupt'} ${FFMPEG_BINARY}. ` +93          `Original error: ${e.message}`);94        result = false;95      }96    }97    if (this.opts.usePortForwarding) {98      await this.stopIproxy();99    }100    return result;101  }102  async finish () {103    await this.interrupt();104    return this.videoPath;105  }106  async cleanup () {107    if (await fs.exists(this.videoPath)) {108      await fs.rimraf(this.videoPath);109    }110  }111}112/**113 * @typedef {Object} StartRecordingOptions114 *115 * @property {?string} remotePath - The path to the remote location, where the resulting video should be uploaded.116 *                                  The following protocols are supported: http/https, ftp.117 *                                  Null or empty string value (the default setting) means the content of resulting118 *                                  file should be encoded as Base64 and passed as the endpount response value.119 *                                  An exception will be thrown if the generated media file is too big to120 *                                  fit into the available process memory.121 *                                  This option only has an effect if there is screen recording process in progreess122 *                                  and `forceRestart` parameter is not set to `true`.123 * @property {?string} user - The name of the user for the remote authentication. Only works if `remotePath` is provided.124 * @property {?string} pass - The password for the remote authentication. Only works if `remotePath` is provided.125 * @property {?string} method - The http multipart upload method name. The 'PUT' one is used by default.126 *                              Only works if `remotePath` is provided.127 * @property {?string} videoType - The format of the screen capture to be recorded.128 *                                 Available formats: "h264", "mp4" or "fmp4". Default is "mp4".129 * @property {?string} videoQuality - The video encoding quality (low, medium, high, photo - defaults to medium).130 * @property {?string} videoFps - The Frames Per Second rate of the recorded video. Change this value if the resulting video131 *                                is too slow or too fast. Defaults to 10.132 * @property {?boolean} forceRestart - Whether to try to catch and upload/return the currently running screen recording133 *                                     (`false`, the default setting) or ignore the result of it and start a new recording134 *                                     immediately.135 * @property {?string|number} timeLimit - The maximum recording time, in seconds.136 *                                        The default value is 180, the maximum value is 600 (10 minutes).137 */138/**139 * Record the display of devices running iOS Simulator since Xcode 8.3 or real devices since iOS 8140 * (ios-minicap utility is required: https://github.com/openstf/ios-minicap).141 * It records screen activity to a MPEG-4 file. Audio is not recorded with the video file.142 * If screen recording has been already started then the command will stop it forcefully and start a new one.143 * The previously recorded video file will be deleted.144 *145 * @param {?StartRecordingOptions} options - The available options.146 * @returns {string} Base64-encoded content of the recorded media file if147 *                   any screen recording is currently running or an empty string.148 * @throws {Error} If screen recording has failed to start.149 */150commands.startRecordingScreen = async function (options = {}) {151  const {152    videoType,153    timeLimit = DEFAULT_RECORDING_TIME_SEC,154    videoQuality = 'medium',155    videoFps = DEFAULT_FPS,156    forceRestart,157  } = options;158  let result = '';159  if (!forceRestart) {160    log.info(`Checking if there is/was a previous screen recording. ` +161      `Set 'forceRestart' option to 'true' if you'd like to skip this step.`);162    result = await this.stopRecordingScreen(options);163  }164  const videoPath = await tempDir.path({165    prefix: `appium_${Math.random().toString(16).substring(2, 8)}`,166    suffix: MP4_EXT,167  });168  const screenRecorder = new ScreenRecorder(this.opts.device.udid, videoPath, {169    // TODO: Apply type and quality options170    videoType,171    videoQuality,172    videoFps: videoFps || DEFAULT_FPS,173    remotePort: this.opts.mjpegServerPort || DEFAULT_MJPEG_SERVER_PORT,174    usePortForwarding: this.isRealDevice(),175  });176  if (!await screenRecorder.interrupt(true)) {177    log.errorAndThrow('Unable to stop screen recording process');178  }179  if (this._recentScreenRecorder) {180    await this._recentScreenRecorder.cleanup();181    this._recentScreenRecorder = null;182  }183  const timeoutSeconds = parseFloat(timeLimit);184  if (isNaN(timeoutSeconds) || timeoutSeconds > MAX_RECORDING_TIME_SEC || timeoutSeconds <= 0) {185    log.errorAndThrow(`The timeLimit value must be in range [1, ${MAX_RECORDING_TIME_SEC}] seconds. ` +186      `The value of '${timeLimit}' has been passed instead.`);187  }188  try {189    await screenRecorder.start(timeoutSeconds * 1000);190  } catch (e) {191    await screenRecorder.interrupt(true);192    await screenRecorder.cleanup();193    throw e;194  }195  this._recentScreenRecorder = screenRecorder;196  return result;197};198/**199 * @typedef {Object} StopRecordingOptions200 *201 * @property {?string} remotePath - The path to the remote location, where the resulting video should be uploaded.202 *                                  The following protocols are supported: http/https, ftp.203 *                                  Null or empty string value (the default setting) means the content of resulting204 *                                  file should be encoded as Base64 and passed as the endpount response value.205 *                                  An exception will be thrown if the generated media file is too big to206 *                                  fit into the available process memory.207 * @property {?string} user - The name of the user for the remote authentication. Only works if `remotePath` is provided.208 * @property {?string} pass - The password for the remote authentication. Only works if `remotePath` is provided.209 * @property {?string} method - The http multipart upload method name. The 'PUT' one is used by default.210 *                              Only works if `remotePath` is provided.211 */212/**213 * Stop recording the screen. If no screen recording process is running then214 * the endpoint will try to get the recently recorded file.215 * If no previously recorded file is found and no active screen recording216 * processes are running then the method returns an empty string.217 *218 * @param {?StopRecordingOptions} options - The available options.219 * @returns {string} Base64-encoded content of the recorded media file if 'remotePath'220 *                   parameter is empty or null or an empty string.221 * @throws {Error} If there was an error while getting the name of a media file222 *                 or the file content cannot be uploaded to the remote location.223 */224commands.stopRecordingScreen = async function (options = {}) {225  const {226    remotePath,227    user,228    pass,229    method,230  } = options;231  if (!this._recentScreenRecorder) {232    log.info('Screen recording is not running. There is nothing to stop.');233    return '';234  }235  try {236    const videoPath = await this._recentScreenRecorder.finish();237    if (!await fs.exists(videoPath)) {238      log.errorAndThrow(`The screen recorder utility has failed ` +239        `to store the actual screen recording at '${videoPath}'`);240    }241    return await encodeBase64OrUpload(videoPath, remotePath, {242      user,243      pass,244      method245    });246  } finally {247    await this._recentScreenRecorder.interrupt(true);248    await this._recentScreenRecorder.cleanup();249    this._recentScreenRecorder = null;250  }251};252export { commands };...record-audio.js
Source:record-audio.js  
1import { fs, tempDir, logger, util } from 'appium-support';2import { SubProcess } from 'teen_process';3import log from '../logger';4import { encodeBase64OrUpload } from '../utils';5import { waitForCondition } from 'asyncbox';6const commands = {};7const AUDIO_RECORD_FEAT_NAME = 'audio_record';8const MAX_RECORDING_TIME_SEC = 60 * 60 * 12;9const DEFAULT_RECORDING_TIME_SEC = 60 * 3;10const PROCESS_STARTUP_TIMEOUT_MS = 5000;11const DEFAULT_SOURCE = 'avfoundation';12const DEFAULT_BITRATE = '128k';13const DEFAULT_CODEC = 'aac';14const DEFAULT_CHANNELS = 2;15const DEFAULT_RATE = 44100;16const DEFAULT_EXT = '.mp4';17const FFMPEG_BINARY = 'ffmpeg';18const ffmpegLogger = logger.getLogger(FFMPEG_BINARY);19class AudioRecorder {20  constructor (input, audioPath, opts = {}) {21    this.audioPath = audioPath;22    this.opts = opts;23    this.input = input;24    this.mainProcess = null;25  }26  async start (timeoutSeconds) {27    try {28      await fs.which(FFMPEG_BINARY);29    } catch (err) {30      throw new Error(`'${FFMPEG_BINARY}' binary is not found in PATH. Install it using 'brew install ffmpeg'. ` +31        `Check https://www.ffmpeg.org/download.html for more details.`);32    }33    const {34      audioSource = DEFAULT_SOURCE,35      audioCodec,36      audioBitrate,37      audioChannels,38      audioRate,39    } = this.opts;40    const args = [41      '-t', `${timeoutSeconds}`,42      '-f', audioSource,43      '-i', this.input,44      '-c:a', audioCodec,45      '-b:a', audioBitrate,46      '-ac', `${audioChannels}`,47      '-ar', `${audioRate}`,48      this.audioPath,49    ];50    this.mainProcess = new SubProcess(FFMPEG_BINARY, args);51    let isCaptureStarted = false;52    this.mainProcess.on('output', (stdout, stderr) => {53      if (stderr) {54        if (stderr.trim().startsWith('size=')) {55          if (!isCaptureStarted) {56            isCaptureStarted = true;57          }58        } else {59          ffmpegLogger.info(`${stderr}`);60        }61      }62    });63    await this.mainProcess.start(0);64    try {65      await waitForCondition(() => isCaptureStarted, {66        waitMs: PROCESS_STARTUP_TIMEOUT_MS,67        intervalMs: 300,68      });69    } catch (e) {70      log.warn(`Audio recording process did not start within ${PROCESS_STARTUP_TIMEOUT_MS}ms. Continuing anyway`);71    }72    if (!this.mainProcess.isRunning) {73      this.mainProcess = null;74      throw new Error(`The audio recording process '${FFMPEG_BINARY}' died unexpectedly. ` +75        `Check server logs for more details`);76    }77    log.info(`Starting capture on audio input '${this.input}' with command: '${util.quote([FFMPEG_BINARY, ...args])}'. ` +78      `Will timeout in ${timeoutSeconds}s`);79    this.mainProcess.once('exit', (code, signal) => {80      // ffmpeg returns code 255 if SIGINT arrives81      if ([0, 255].includes(code)) {82        log.info(`The recording session on audio input '${this.input}' has been finished`);83      } else {84        log.debug(`The recording session on audio input '${this.input}' has exited ` +85          `with code ${code}, signal ${signal}`);86      }87    });88  }89  isRecording () {90    return !!(this.mainProcess?.isRunning);91  }92  async interrupt (force = false) {93    if (this.isRecording()) {94      const interruptPromise = this.mainProcess.stop(force ? 'SIGTERM' : 'SIGINT');95      this.mainProcess = null;96      try {97        await interruptPromise;98      } catch (e) {99        log.warn(`Cannot ${force ? 'terminate' : 'interrupt'} ${FFMPEG_BINARY}. ` +100          `Original error: ${e.message}`);101        return false;102      }103    }104    return true;105  }106  async finish () {107    await this.interrupt();108    return this.audioPath;109  }110  async cleanup () {111    if (await fs.exists(this.audioPath)) {112      await fs.rimraf(this.audioPath);113    }114  }115}116/**117 * @typedef {Object} StartRecordingOptions118 *119 * @property {!string} audioInput - The name of the corresponding audio input device to use for the120 * capture. The full list of capture devices could be shown using `ffmpeg -f avfoundation -list_devices true -i ""`121 * Terminal command.122 * @property {?string} audioCodec [aac] - The name of the audio codec. The Advanced Audio Codec is used by default.123 * @property {?string} audioBitrate [128k] - The bitrate of the resulting audio stream. 128k by default.124 * @property {?string|number} audioChannels [2] - The count of audio channels in the resulting stream. Setting it to `1`125 * will create a single channel (mono) audio stream.126 * @property {?string|number} audioRate [44100] - The sampling rate of the resulting audio stream.127 * @property {?string|number} timeLimit [180] - The maximum recording time, in seconds.128 * The default value is 180, the maximum value is 43200 (12 hours).129 * @property {?boolean} forceRestart [false] - Whether to restart audio capture process forcefully when130 * startRecordingAudio is called (`true`) or ignore the call until the current audio recording is completed.131 */132/**133 * Records the given hardware audio input into an .mp4 file.134 *135 * @param {?StartRecordingOptions} options - The available options.136 * @throws {Error} If audio recording has failed to start.137 */138commands.startAudioRecording = async function startAudioRecording (options = {}) {139  if (!this.isFeatureEnabled(AUDIO_RECORD_FEAT_NAME)) {140    log.errorAndThrow(`Audio capture feature must be enabled on the server side. ` +141      `Please set '--relaxed-security' or '--allow-insecure' with '${AUDIO_RECORD_FEAT_NAME}' option. ` +142      `Read https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/security.md for more details.`);143  }144  const {145    timeLimit = DEFAULT_RECORDING_TIME_SEC,146    audioInput,147    // Undocumented feature148    audioSource,149    audioCodec = DEFAULT_CODEC,150    audioBitrate = DEFAULT_BITRATE,151    audioChannels = DEFAULT_CHANNELS,152    audioRate = DEFAULT_RATE,153    forceRestart,154  } = options;155  if (!audioInput) {156    log.errorAndThrow(`The mandatory audioInput option is not provided. Please set it ` +157      `to a correct value (e. g. ':1'). Use 'ffmpeg -f avfoundation -list_devices true -i ""' ` +158      `command to list available input sources`);159  }160  if (this._audioRecorder?.isRecording()) {161    log.info(`There is an active audio recording process`);162    if (forceRestart) {163      log.info(`Stopping it because 'forceRestart' option is set to true`);164      await this._audioRecorder.interrupt(true);165    } else {166      log.info(`Doing nothing. ` +167        `Set 'forceRestart' option to true if you'd like to start a new audio recording session`);168      return;169    }170  }171  if (this._audioRecorder) {172    await this._audioRecorder.cleanup();173    this._audioRecorder = null;174  }175  const audioPath = await tempDir.path({176    prefix: `appium_${util.uuidV4().substring(0, 8)}`,177    suffix: DEFAULT_EXT,178  });179  const audioRecorder = new AudioRecorder(audioInput, audioPath, {180    audioSource,181    audioCodec,182    audioBitrate,183    audioChannels,184    audioRate,185  });186  const timeoutSeconds = parseInt(timeLimit, 10);187  if (isNaN(timeoutSeconds) || timeoutSeconds > MAX_RECORDING_TIME_SEC || timeoutSeconds <= 0) {188    log.errorAndThrow(`The timeLimit value must be in range [1, ${MAX_RECORDING_TIME_SEC}] seconds. ` +189      `The value of '${timeLimit}' has been passed instead.`);190  }191  try {192    await audioRecorder.start(timeoutSeconds);193  } catch (e) {194    await audioRecorder.interrupt(true);195    await audioRecorder.cleanup();196    throw e;197  }198  this._audioRecorder = audioRecorder;199};200/**201 * Stop recording of the audio input. If no audio recording process is running then202 * the endpoint will try to get the recently recorded file.203 * If no previously recorded file is found and no active audio recording204 * processes are running then the method returns an empty string.205 *206 * @returns {string} Base64-encoded content of the recorded media file or an207 * empty string if no audio recording has been started before.208 * @throws {Error} If there was an error while getting the recorded file.209 */210commands.stopAudioRecording = async function stopAudioRecording () {211  if (!this._audioRecorder) {212    log.info('Audio recording has not been started. There is nothing to stop');213    return '';214  }215  let resultPath;216  try {217    resultPath = await this._audioRecorder.finish();218    if (!await fs.exists(resultPath)) {219      log.errorAndThrow(`${FFMPEG_BINARY} has failed ` +220        `to store the actual audio recording at '${resultPath}'`);221    }222  } catch (e) {223    await this._audioRecorder.interrupt(true);224    await this._audioRecorder.cleanup();225    this._audioRecorder = null;226    throw e;227  }228  return await encodeBase64OrUpload(resultPath);229};230export { commands };...server.js
Source:server.js  
1const WebSocket = require('ws')2const { randomString, rand } = require('./rand.js')3const CMD_NOTE_ON = 14const fromCmd = (cmd) => (cmd>>4) & 75const ROOT_SECRET = '0000000000000000'6const ROOT_USR = 07const ROOT_GRP = 08const PORT = process.env.PORT || 110889const wss = new WebSocket.Server({ port: PORT })10const groups = Array.from({ length: 255 }).map(() => new Set()) // 255 is offline 'room''11const identities = {} // {[secret]: { name: 'pianco', gid: 0, uid: 0 }}12const send = (gid, uid, message) => { // to specific identity13  wss.clients.forEach(client => {14    const { gid: clientGid, uid: clientUid } = identities[client.secret] || {}15    if (clientGid === gid && clientUid === uid && client.readyState === WebSocket.OPEN) {16      client.send(message)17    }18  })19}20const broadcast = (data) => { // to everyone in group21  const [gid, uid] = data22  wss.clients.forEach(client => {23    const { gid: clientGid } = identities[client.secret] || {}24    if (clientGid === gid && client.readyState === WebSocket.OPEN) {25      client.send(new Uint8Array(data))26    }27  })28}29const broadcastText = (gid, text) => {30  wss.clients.forEach(client => {31    const { gid: clientGid } = identities[client.secret] || {}32    if (clientGid === gid && client.readyState === WebSocket.OPEN) {33      client.send(text)34    }35  })36}37const echo = (data) => { // to eveyone in group except origin38  const [gid, uid] = data39  wss.clients.forEach(client => {40    const { gid: clientGid, uid: clientUid } = identities[client.secret] || {}41    if (clientGid === gid && clientUid !== uid && client.readyState === WebSocket.OPEN) {42      client.send(data)43    }44  })45}46const status = () => { // broadcast state of the world to everyone47  const data = JSON.stringify({48    groups: groups.map(uids => [...uids]),49    names: groups.map((_, group) => // [0: {0: 'draho'}, 3: {}]50      Object.values(identities)51        .filter(({ gid }) => gid === group)52        .reduce((map, {uid, name}) => ({...map, [uid]: name}), {})53    ),54    // TODO additional data in the future55  })56  wss.clients.forEach(client => {57    if (client.readyState === WebSocket.OPEN) {58      client.send(`status ${data}`)59    }60  })61}62wss.send = send63wss.broadcast = broadcast64wss.echo = echo65wss.status = status66groups[ROOT_GRP].add(ROOT_USR) // add ghost player to main room permanently67identities[ROOT_SECRET] = { name: 'pianco', gid: 0, uid: 0 }68const Autoplay = require('./autoplay.js')(wss)69const autoplayers = groups.map((_, gid) => new Autoplay(gid, ROOT_USR)) // init autoplaye for each group70const Recorder = require('./recorder.js')(wss)71const recorders = groups.map((_, gid) => new Recorder(gid)) // init recorder for each group72// return uid which is not yet in the group73const genUid = (gid) => {74  if (groups[gid].size >= 255) {75    return null76  }77  let uid78  do {79    uid = rand(255) // 0-254 - 255 is ghost80  } while (uid === ROOT_USR || groups[gid].has(uid))81  return uid82}83wss.on('connection', async function connection(ws) {84  console.log('client connected')85  ws.isAlive = true86  ws.send('connected')87  ws.on('message', function incoming(message) {88    // common vars89    let { uid, gid } = identities[ws.secret] || { uid: undefined, gid: undefined}90    const isDirectApi = ws.secret === undefined 91    if (isDirectApi) { // assume gid=0 for gopiano92      gid = ROOT_GRP93    }94    if (message instanceof Buffer) {95      if (message[0] !== 255 && message[0] !== -1) {96        echo(message) // <--- this is the most important97        recorders[gid].pass(message) // pass message to recorder98      }99      // interrupt ghost:100      if (gid === ROOT_GRP) { // gopiano also triggesr this101        const [_, __, cmd] = new Uint8Array(message)102        if (fromCmd(cmd) === CMD_NOTE_ON) { // note on103          autoplayers[ROOT_GRP].resetGhost({104            delay: 120,105            stopCurrent: true,106            pretendScared: !isDirectApi,107          })108        }109      }110    }111    if (typeof message === "string") {112      const [cmd, ...values] = message.split(' ')113      if (cmd === 'ping') {114        ws.send('pong')115      }116      if (cmd === 'reaction') {117        const [gid, uid] = values.map(Number)118        broadcastText(gid, message)119      }120      if (cmd === "regroup") {121        const [_, __, newGid] = values.map(Number)122        let [secret, name] = values.slice(3) // optional123        const { uid: oldUid, gid: oldGid } = identities[secret] ||124          { uid: undefined, gid: undefined } // after reset, or for new users - to force gen of new uid125        let newUid = oldUid // possibly unchanged126        // wipe user activity in group127        if (oldUid && oldGid >=0) {128          autoplayers[oldGid].stop(oldUid)129          recorders[oldGid].stop(oldUid)130        }131        // prepare new values:132        if (oldGid !== newGid || oldUid === undefined) { // only change uid when changing gid133          if (newGid >= 0) {134            newUid = genUid(newGid)135          } else {136            newUid = -1137          }138          if (newUid === null) {139            ws.send(`group full ${newGid} ${newUid}`)140            wss.status()141            return142          }143        }144        if (!secret) {145          if (ws.secret) {146            return console.error('cant change secret of wssecre')147          }148          secret = randomString(16)149        }150        if (!name) { // assign default random name151          name = `anon${newUid}`152        }153        // update stored values154        groups[oldGid] && groups[oldGid].delete(oldUid)155        if (newGid >= 0) {156          groups[newGid].add(newUid)157        }158        identities[secret] = { name, gid: newGid, uid: newUid }159        // update sockets160        ws.secret = secret161        // inform clients of secret162        wss.clients.forEach(ws => {163          const { uid, gid } = identities[secret]164          // send response to all ws from device165          if (ws.secret === secret && ws.readyState === WebSocket.OPEN) {166            ws.send(`regroup ${newGid} ${newUid} ${secret} ${name}`)167            console.log(`${secret}:${name} - ${uid}@${gid} => ${newUid}@${newGid}`)168          }169        })170        wss.status()171        // reset ghost player timer172        if (newGid === 0) {173          autoplayers[newGid].resetGhost({174            delay: 60,175            stopCurrent: false,176          })177        }178      }179      const recorder = recorders[gid]180      if (gid !== -1) {181        if (cmd === 'record') {182          recorder.record(uid)183        }184        if (cmd === 'stop') {185          recorder.stop(uid)186        }187        if (cmd === 'replay') {188          recorder.replay(uid)189        }190        if (cmd === 'pause') {191          recorder.pause(uid)192        }193        // debug only:194        if (cmd === 'autoplayurl') {195          const [gid, uid] = values.map(Number)196          const url = values[2]197          autoplayers[gid].requestHandler(ws)(url)198        }199        if (cmd === 'playrandomfile') {200          const [gid, uid] = values.map(Number)201          autoplayers[gid].playRandomFile(uid)202        }203        if (cmd === 'playrandomnotes') {204          const [gid, uid, count] = values.map(Number)205          autoplayers[gid].playRandomNotes(uid, count)206        }207        if (cmd === 'stopplay') {208          const [gid, uid] = values.map(Number)209          autoplayers[gid].stop(uid)210        }211      }212      // console.log(cmd, values)213    }214  })215  ws.on('close', () => {216    const { gid, uid } = identities[ws.secret] || {}217    let isLast = true218    wss.clients.forEach((client) => {219      if (client !== ws && client.readyState === WebSocket.OPEN220        && client.secret === ws.secret221      ) {222        isLast = false223      }224    })225    if (isLast && gid !== undefined && uid !== undefined) {226      if (gid >=0) {227        autoplayers[gid].stop(uid)228        recorders[gid].stop(uid)229        groups[gid].delete(uid)230      }231      if (ws.secret in identities) {232        identities[ws.secret].uid = undefined233        identities[ws.secret].gid = undefined234      }235      console.log(`${uid}@${gid} => close`)236      wss.status()237    }238  })239})240const healthInterval = setInterval(() => {241  wss.clients.forEach(ws => {242    if (ws.secret === undefined) { // ignore health of gopiano connection243      return 244    }245    if (ws.isAlive === false) {246      console.log(`ws.secret`, ws.secret)247      ws.terminate()248      return249    }250    ws.isAlive = false251    ws.ping()252    ws.once('pong', () => {253      ws.isAlive = true254    })255  })256}, 30000)257wss.on('close', () => {258  clearInterval(healthInterval)259})...saveVideo.js
Source:saveVideo.js  
1import React, { Component } from 'react';2export default class SaveVideo extends Component {3    constructor() {4        super();5        // åä¾6        if (!SaveVideo.instance) {7            this.state = {8                ongoing: false9            };10            SaveVideo.instance = this;11        } else {12            return SaveVideo.instance;13        }14        this.state = {15            recorder: null, 16            recorder_timeout: null,17            full_recorded: false,18            videoData: null19        }20    }21    22    initRecoder() {23        if (this.state.ongoing) {24            return25        }26        else {27            this.setState({28                ongoing: true29            })30        }31        var canvas = document.getElementById(this.props.canvas);32        33        var stream = canvas.captureStream();34        // add audio35        // let videoOrAudioElement = document.getElementById('audio');36        // let ctx = new AudioContext();37        // let dest = ctx.createMediaStreamDestination();38        // let sourceNode = ctx.createMediaElementSource(videoOrAudioElement);39        // sourceNode.connect(dest);40        // videoOrAudioElement.play();41        // sourceNode.connect(ctx.destination);42        // let audioTrack = dest.stream.getAudioTracks()[0];43        // stream.addTrack(audioTrack);44        // var recorder = new MediaRecorder(stream, { mimeType: "video/webm"});45        46        var videoData = [];47        var recorder = new MediaRecorder(stream, { mimeType: "video/webm"});48        this.setState({49            recorder: recorder50        })51        recorder.onstart = () => {52            console.log("start")53            // ææ¾è§é¢54            this.props.draw();55            // æ ¹æ®æ¶é´åæ¢å½å¶56            var recorder_timeout = setTimeout(() => {57                this.setState({58                    full_recorded: true59                })60                recorder.stop(); 61            }, this.props.duration + 1000);62            this.setState({63                recorder_timeout: recorder_timeout64            });65            console.log(this.state.recorder_timeout)66        }67        recorder.ondataavailable = function(event) {68            console.log("recording");69            videoData.push(event.data);   70        }71        recorder.onstop = () => {72            // æ¸
é¤timeout73            if (this.state.recorder_timeout !== null) {74                clearTimeout(this.state.recorder_timeout);75                this.setState({76                    recorder_timeout: null77                })78            }79            // å¦ææ¯æ£å¸¸å½å¶å®æ¯80            if (this.state.full_recorded) {81                var url = URL.createObjectURL(new Blob(videoData, { type: "video/webm" }));82                const link = document.createElement('a');83                link.style.display = 'none';84                link.href = url;85                link.download = 'media.mp4';86                document.body.appendChild(link);87                link.click();88                link.remove();89            }90            91            this.setState({92                recorder: null,93                ongoing: false94            })95        }96        97        this.startRecoder(recorder);98    }99    startRecoder(recorder) {100        recorder.start(this.props.timeSlice);101    }102    // TODO: why stop?103    stopRecorder() {104        if (this.state.recorder !== null)105            this.state.recorder.stop();106    }107    render() {108        return (109            <div>110                <button className="saving" 111                        onClick={() => this.initRecoder()}>112                    save113                </button>114                <button onClick={() => this.stopRecorder()}>115                    Interrupt116                </button>117            </div>118        )119    }...Using AI Code Generation
1const wdio = require('webdriverio');2const opts = {3    desiredCapabilities: {4    }5};6async function main () {7    const client = await wdio.remote(opts);8    await client.pause(10000);9    const result = await client.execute('mobile: stopRecordingScreen');10    console.log(result);11}12main();13const wdio = require('webdriverio');14const opts = {15    desiredCapabilities: {16    }17};18async function main () {19    const client = await wdio.remote(opts);20    await client.pause(10000);21    const result = await client.execute('mobile: stopRecordingScreen');22    console.log(result);23}24main();25const wdio = require('webdriverio');26const opts = {27    desiredCapabilities: {28    }29};30async function main () {31    const client = await wdio.remote(opts);32    await client.pause(10000);33    const result = await client.execute('mobile: stopRecordingScreen');34    console.log(result);35}36main();37const wdio = require('webdriverio');38const opts = {39    desiredCapabilities: {40    }41};42async function main () {Using AI Code Generation
1const wd = require('wd');2driver.init({3}).then(() => {4  return driver.sleep(5000);5}).then(() => {6  return driver.elementByName('Buttons');7}).then((el) => {8  return el.click();9}).then(() => {10  return driver.elementByName('Rounded');11}).then((el) => {12  return el.click();13}).then(() => {14  return driver.elementByName('Rounded');15}).then((el) => {16  return el.click();17}).then(() => {18  return driver.interrupt();19}).then(() => {20  return driver.elementByName('Rounded');21}).then((el) => {22  return el.click();23}).then(() => {24  return driver.elementByName('Rounded');25}).then((el) => {26  return el.click();27}).then(() => {28  return driver.quit();29}).catch((err) => {30  console.log(err);31});Using AI Code Generation
1const wdio = require('webdriverio');2const options = {3    desiredCapabilities: {4    }5};6const client = wdio.remote(options);7(async function () {8    try {9        await client.init();10        await client.pause(5000);11        await client.interrupt();12        await client.pause(5000);13        await client.end();14    } catch (e) {15        console.log(e);16    }17})();18const wdio = require('webdriverio');19const options = {20    desiredCapabilities: {21    }22};23const client = wdio.remote(options);24(async function () {25    try {26        await client.init();27        await client.pause(5000);28        await client.background(5);29        await client.interrupt();30        await client.pause(5000);31        await client.end();32    } catch (e) {33        console.log(e);34    }35})();Using AI Code Generation
1const wd = require('wd');2driver.init({3}).then(() => {4}).then(() => {5  return driver.elementByAccessibilityId('Search');6}).then((el) => {7  return el.click();8}).then(() => {9  return driver.elementByAccessibilityId('Cancel');10}).then((el) => {11  return el.click();12}).then(() => {13  return driver.interrupt();14}).then(() => {15  return driver.quit();16});17const wd = require('wd');18driver.init({19}).then(() => {20}).then(() => {21  return driver.elementByAccessibilityId('Search');22}).then((el) => {23  return el.click();24}).then(() => {25  return driver.elementByAccessibilityId('Cancel');26}).then((el) => {27  return el.click();28}).then(() => {29  return driver.interrupt('com.apple.mobilesafari');30}).then(() => {31  return driver.quit();32});332017-05-25 09:28:05:792 - [debug] [BaseDriver] Event 'newSessionRequested' logged at 1495671285789 (09:28:05 GMT+Using AI Code Generation
1let recorder = await driver.startRecordingScreen();2await driver.pause(10000);3await recorder.interrupt();4await driver.pause(10000);5await recorder.stop();6let recorder = await driver.startRecordingScreen();7await driver.pause(10000);8await recorder.interrupt();9await driver.pause(10000);10await recorder.stop();11let recorder = await driver.startRecordingScreen();12await driver.pause(10000);13await recorder.interrupt();14await driver.pause(10000);15await recorder.stop();16let recorder = await driver.startRecordingScreen();17await driver.pause(10000);18await recorder.interrupt();19await driver.pause(10000);20await recorder.stop();21let recorder = await driver.startRecordingScreen();22await driver.pause(10000);23await recorder.interrupt();24await driver.pause(10000);25await recorder.stop();26let recorder = await driver.startRecordingScreen();27await driver.pause(10000);28await recorder.interrupt();29await driver.pause(10000);30await recorder.stop();31let recorder = await driver.startRecordingScreen();32await driver.pause(10000);33await recorder.interrupt();34await driver.pause(10000);35await recorder.stop();36let recorder = await driver.startRecordingScreen();37await driver.pause(10000);38await recorder.interrupt();39await driver.pause(10000);40await recorder.stop();41let recorder = await driver.startRecordingScreen();42await driver.pause(10000);43await recorder.interrupt();44await driver.pause(10000);45await recorder.stop();Using AI Code Generation
1const wd = require('wd');2const path = require('path');3const fs = require('fs');4const _ = require('lodash');5const { exec } = require('child_process');6const { execSync } = require('child_process');7const { sleep } = require('asyncbox');8const { retryInterval } = require('asyncbox');9const { retry } = require('asyncbox');10const { waitForCondition } = require('asyncbox');11const { waitForConditionInLoop } = require('asyncbox');12const { waitForConditionInLoopWithRetries } = require('asyncbox');13const { retrying } = require('asyncbox');14const { retryingInterval } = require('asyncbox');15const { retryingWithBackOff } = require('asyncbox');16const { retryingWithBackOffInterval } = require('asyncbox');17const { retryingWithBackOffIntervalAndTimeout } = require('asyncbox');18const { retryingWithBackOffIntervalAndTimeoutAndJitter } = require('asyncbox');19const { retryingWithBackOffIntervalAndTimeoutAndJitterAndExceptions } = require('asyncbox');20const { retryingWithBackOffIntervalAndTimeoutAndJitterAndExceptionsAndCondition } = require('asyncbox');21const { retryingWithBackOffIntervalAndTimeoutAndJitterAndExceptionsAndConditionAndRetries } = require('asyncbox');22const { retryingWithBackOffIntervalAndTimeoutAndJitterAndExceptionsAndConditionAndRetriesAndTimeout } = require('asyncbox');23const { retryingWithBackOffIntervalAndTimeoutAndJitterAndExceptionsAndConditionAndRetriesAndTimeoutAndInterval } = require('asyncbox');24const { retryingWithBackOffIntervalAndTimeoutAndJitterAndExceptionsAndConditionAndRetriesAndTimeoutAndIntervalAndIntervalModulus } = require('asyncbox');25const { retryingWithBackOffIntervalAndTimeoutAndJitterAndExceptionsAndConditionAndRetriesAndTimeoutAndIntervalAndIntervalModulusAndIntervalMultiplier } = require('asyncbox');26const { retryingWithBackOffIntervalAndTimeoutAndJitterAndExceptionsAndConditionAndRetriesAndTimeoutAndIntervalAndIntervalModulusAndIntervalMultiplierAndBackOffFactor } = require('asyncbox');27const { retryingWithBackOffIntervalLearn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
