appium-espresso-driver
Version:
Espresso integration for Appium
185 lines • 8.08 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.GRADLE_URL_TEMPLATE = exports.VERSION_KEYS = exports.ServerBuilder = void 0;
exports.buildServerSigningConfig = buildServerSigningConfig;
const teen_process_1 = require("teen_process");
const support_1 = require("appium/support");
const lodash_1 = __importDefault(require("lodash"));
const path_1 = __importDefault(require("path"));
const os_1 = require("os");
const utils_1 = require("./utils");
const GRADLE_VERSION_KEY = 'gradle';
const GRADLE_URL_PREFIX = 'distributionUrl=';
const GRADLE_URL_TEMPLATE = 'https\\://services.gradle.org/distributions/gradle-VERSION-all.zip';
exports.GRADLE_URL_TEMPLATE = GRADLE_URL_TEMPLATE;
const DEPENDENCY_PROP_NAMES = ['additionalAppDependencies', 'additionalAndroidTestDependencies'];
const VERSION_KEYS = [
GRADLE_VERSION_KEY,
'androidGradlePlugin',
'compileSdk',
'buildTools',
'minSdk',
'targetSdk',
'kotlin',
'sourceCompatibility',
'targetCompatibility',
'jvmTarget',
'composeVersion',
'espressoVersion',
'annotationVersion'
];
exports.VERSION_KEYS = VERSION_KEYS;
function buildServerSigningConfig(args) {
return {
zipAlign: true,
keystoreFile: args.keystoreFile,
keystorePassword: args.keystorePassword,
keyAlias: args.keyAlias,
keyPassword: args.keyPassword
};
}
class ServerBuilder {
constructor(log, args = {}) {
this.log = log;
this.serverPath = args.serverPath;
this.showGradleLog = args.showGradleLog;
const buildConfiguration = args.buildConfiguration || {};
const versionConfiguration = buildConfiguration.toolsVersions || {};
this.serverVersions = lodash_1.default.reduce(versionConfiguration, (acc, value, key) => {
if (VERSION_KEYS.includes(key)) {
acc[key] = value;
}
else {
log.warn(`Got unexpected '${key}' in toolsVersion block of the build configuration`);
}
return acc;
}, {});
this.testAppPackage = args.testAppPackage;
this.signingConfig = args.signingConfig;
for (const propName of DEPENDENCY_PROP_NAMES) {
this[propName] = buildConfiguration[propName] || [];
}
}
async build() {
if (this.serverVersions[GRADLE_VERSION_KEY]) {
await this.setGradleWrapperVersion(this.serverVersions[GRADLE_VERSION_KEY]);
}
await this.insertAdditionalDependencies();
await this.runBuildProcess();
}
/**
* @returns {{cmd: string, args: string[]}}
*/
getCommand() {
const cmd = support_1.system.isWindows() ? 'gradlew.bat' : path_1.default.resolve(this.serverPath, 'gradlew');
const buildProperty = (key, value) => value ? `-P${key}=${value}` : null;
/** @type {string[]} */
// @ts-ignore Typescript does not understand filter(Boolean)
const args = VERSION_KEYS
.filter((key) => key !== GRADLE_VERSION_KEY)
.map((key) => {
const serverVersion = this.serverVersions[key];
const gradleProperty = `appium${key.charAt(0).toUpperCase()}${key.slice(1)}`;
return buildProperty(gradleProperty, serverVersion);
})
.filter(Boolean);
if (this.signingConfig) {
// @ts-ignore Typescript does not understand filter(Boolean)
args.push(...(lodash_1.default.keys(this.signingConfig)
.map((key) => [`appium${lodash_1.default.upperFirst(key)}`, this.signingConfig[key]])
.map(([k, v]) => buildProperty(k, v))
.filter(Boolean)));
}
if (this.testAppPackage) {
// @ts-ignore Typescript does not understand filter(Boolean)
args.push(buildProperty('appiumTargetPackage', this.testAppPackage));
}
args.push('app:assembleAndroidTest');
return { cmd, args };
}
async setGradleWrapperVersion(version) {
const propertiesPath = path_1.default.resolve(this.serverPath, 'gradle', 'wrapper', 'gradle-wrapper.properties');
const originalProperties = await support_1.fs.readFile(propertiesPath, 'utf8');
const newProperties = this.updateGradleDistUrl(originalProperties, version);
await support_1.fs.writeFile(propertiesPath, newProperties, 'utf8');
}
updateGradleDistUrl(propertiesContent, version) {
return propertiesContent.replace(new RegExp(`^(${lodash_1.default.escapeRegExp(GRADLE_URL_PREFIX)}).+$`, 'gm'), `$1${GRADLE_URL_TEMPLATE.replace('VERSION', version)}`);
}
async insertAdditionalDependencies() {
let hasAdditionalDeps = false;
for (const propName of DEPENDENCY_PROP_NAMES) {
if (!lodash_1.default.isArray(this[propName])) {
throw new Error(`'${propName}' must be an array`);
}
if (lodash_1.default.isEmpty(this[propName].filter((line) => lodash_1.default.trim(line)))) {
continue;
}
for (const dep of this[propName]) {
if (/[\s'\\$]/.test(dep)) {
throw new Error('Single quotes, dollar characters and whitespace characters' +
` are disallowed in additional dependencies: ${dep}`);
}
}
hasAdditionalDeps = true;
}
if (!hasAdditionalDeps) {
return;
}
const buildPath = path_1.default.resolve(this.serverPath, 'app', 'build.gradle.kts');
let configuration = await support_1.fs.readFile(buildPath, 'utf8');
for (const propName of DEPENDENCY_PROP_NAMES) {
const prefix = propName === DEPENDENCY_PROP_NAMES[0]
? 'api'
: 'androidTestImplementation';
const deps = this[propName]
.filter((line) => lodash_1.default.trim(line))
.map((line) => `${prefix}("${line}")`);
if (lodash_1.default.isEmpty(deps)) {
continue;
}
this.log.info(`Adding the following ${propName} to build.gradle.kts: ${deps}`);
configuration = (0, utils_1.updateDependencyLines)(configuration, propName, deps);
}
await support_1.fs.writeFile(buildPath, configuration, 'utf8');
}
async runBuildProcess() {
const { cmd, args } = this.getCommand();
this.log.debug(`Beginning build with command '${cmd} ${args.join(' ')}' ` +
`in directory '${this.serverPath}'`);
const gradlebuild = new teen_process_1.SubProcess(cmd, args, {
cwd: this.serverPath,
stdio: ['ignore', 'pipe', 'pipe'],
// https://github.com/nodejs/node/issues/52572
shell: support_1.system.isWindows(),
windowsVerbatimArguments: true
});
/** @type {string[]} */
let gradleError = [];
const logMsg = `Output from Gradle ${this.showGradleLog ? 'will' : 'will not'} be logged`;
this.log.debug(`${logMsg}. To change this, use 'showGradleLog' desired capability`);
gradlebuild.on('line-stderr', (line) => {
this.log.warn(`[Gradle] ${line}`);
gradleError.push(line);
});
gradlebuild.on('line-stdout', (line) => this.log.info(`[Gradle] ${line}`));
try {
await gradlebuild.start();
await gradlebuild.join();
}
catch (err) {
const msg = `Unable to build Espresso server - ${err.message}\n` +
`Gradle error message:${os_1.EOL}${gradleError.join('\n')}`;
throw this.log.errorWithException(msg);
}
finally {
gradlebuild.removeAllListeners();
}
}
}
exports.ServerBuilder = ServerBuilder;
exports.default = ServerBuilder;
//# sourceMappingURL=server-builder.js.map