appium-xcuitest-driver
Version:
Appium driver for iOS using XCUITest for backend
135 lines • 5.31 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.IOSCrashLog = void 0;
const support_1 = require("appium/support");
const bluebird_1 = __importDefault(require("bluebird"));
const path_1 = __importDefault(require("path"));
const lodash_1 = __importDefault(require("lodash"));
const py_ios_device_client_1 = require("../real-device-clients/py-ios-device-client");
const ios_log_1 = require("./ios-log");
const helpers_1 = require("./helpers");
// The file format has been changed from '.crash' to '.ips' since Monterey.
const CRASH_REPORTS_GLOB_PATTERN = '**/*.@(crash|ips)';
// The size of a single diagnostic report might be hundreds of kilobytes.
// Thus we do not want to store too many items in the memory at once.
const MAX_RECENT_ITEMS = 20;
class IOSCrashLog extends ios_log_1.IOSLog {
constructor(opts) {
super({
log: opts.log,
maxBufferSize: MAX_RECENT_ITEMS,
});
this._udid = opts.udid;
this._sim = opts.sim;
this._realDeviceClient = this._isRealDevice()
? new py_ios_device_client_1.Pyidevice({
udid: this._udid,
log: opts.log,
})
: null;
this._logDir = this._isRealDevice()
? null
: path_1.default.resolve(process.env.HOME || '/', 'Library', 'Logs', 'DiagnosticReports');
this._recentCrashFiles = [];
this._started = false;
}
async startCapture() {
this._recentCrashFiles = await this._listCrashFiles(false);
this._started = true;
}
async stopCapture() {
this._started = false;
}
get isCapturing() {
return this._started;
}
async getLogs() {
const crashFiles = (await this._listCrashFiles(true)).slice(-MAX_RECENT_ITEMS);
const diffFiles = lodash_1.default.difference(crashFiles, this._recentCrashFiles);
if (lodash_1.default.isEmpty(diffFiles)) {
return [];
}
this.log.debug(`Found ${support_1.util.pluralize('fresh crash report', diffFiles.length, true)}`);
await this._serializeCrashes(diffFiles);
this._recentCrashFiles = crashFiles;
return super.getLogs();
}
_serializeEntry(value) {
return value;
}
_deserializeEntry(value) {
const [message, timestamp] = value;
return (0, helpers_1.toLogEntry)(message, timestamp);
}
async _serializeCrashes(paths) {
const tmpRoot = await support_1.tempDir.openDir();
try {
for (const filePath of paths) {
let fullPath = filePath;
if (this._isRealDevice()) {
const fileName = filePath;
try {
await this._realDeviceClient.exportCrash(fileName, tmpRoot);
}
catch (e) {
this.log.warn(`Cannot export the crash report '${fileName}'. Skipping it. ` +
`Original error: ${e.message}`);
return;
}
fullPath = path_1.default.join(tmpRoot, fileName);
}
const { ctime } = await support_1.fs.stat(fullPath);
this.broadcast([await support_1.fs.readFile(fullPath, 'utf8'), ctime.getTime()]);
}
}
finally {
await support_1.fs.rimraf(tmpRoot);
}
}
async _gatherFromRealDevice(strict) {
if (!this._realDeviceClient) {
return [];
}
if (!await this._realDeviceClient.assertExists(strict)) {
this.log.info(`The ${lodash_1.default.toLower(this._realDeviceClient.constructor.name)} tool is not present in PATH. ` +
`Skipping crash logs collection for real devices.`);
return [];
}
return await this._realDeviceClient.listCrashes();
}
async _gatherFromSimulator() {
if (!this._logDir || !this._sim || !(await support_1.fs.exists(this._logDir))) {
this.log.debug(`Crash reports root '${this._logDir}' does not exist. Got nothing to gather.`);
return [];
}
const foundFiles = await support_1.fs.glob(CRASH_REPORTS_GLOB_PATTERN, {
cwd: this._logDir,
absolute: true,
});
const simUdid = this._sim.udid;
// For Simulator only include files, that contain current UDID
return await bluebird_1.default.filter(foundFiles, async (filePath) => {
try {
return await (0, helpers_1.grepFile)(filePath, simUdid, { caseInsensitive: true });
}
catch (err) {
this.log.warn(err);
return false;
}
});
}
async _listCrashFiles(strict) {
return this._isRealDevice()
? await this._gatherFromRealDevice(strict)
: await this._gatherFromSimulator();
}
_isRealDevice() {
return Boolean(this._udid);
}
}
exports.IOSCrashLog = IOSCrashLog;
exports.default = IOSCrashLog;
//# sourceMappingURL=ios-crash-log.js.map