appium
Version:
Automation for Apps.
147 lines (135 loc) • 4.92 kB
JavaScript
import axios from 'axios';
import {fs} from '@appium/support';
import logger from './logger';
import _ from 'lodash';
const hubUri = (config) => {
const protocol = config.hubProtocol || 'http';
return `${protocol}://${config.hubHost}:${config.hubPort}`;
};
/**
* Registers a new node with a selenium grid
* @param {string|object} data - Path or object representing selenium grid node config file. If a `string`, all subsequent arguments are required!
* @param {string} [addr] - Bind to this address
* @param {number} [port] - Bind to this port
* @param {string} [basePath] - Base path for the grid
*/
async function registerNode(data, addr, port, basePath) {
let configFilePath;
if (_.isString(data)) {
configFilePath = data;
try {
data = await fs.readFile(data, 'utf-8');
} catch (err) {
logger.error(
`Unable to load node configuration file ${configFilePath} to register with grid: ${err.message}`
);
return;
}
try {
data = JSON.parse(data);
} catch (err) {
throw logger.errorWithException(
`Syntax error in node configuration file ${configFilePath}: ${err.message}`
);
}
}
postRequest(data, addr, port, basePath);
}
async function registerToGrid(postOptions, configHolder) {
try {
const {status} = await axios(postOptions);
if (status !== 200) {
throw new Error(`Request failed with code ${status}`);
}
logger.debug(
`Appium successfully registered with the the grid on ` + hubUri(configHolder.configuration)
);
} catch (err) {
logger.error(`An attempt to register with the grid was unsuccessful: ${err.message}`);
}
}
function postRequest(configHolder, addr, port, basePath) {
// Move Selenium 3 configuration properties to configuration object
if (!_.has(configHolder, 'configuration')) {
let configuration = {};
for (const property in /** @type {import('@appium/types').StringRecord} */ (configHolder)) {
if (_.has(configHolder, property) && property !== 'capabilities') {
configuration[property] = configHolder[property];
delete configHolder[property];
}
}
/** @type {import('@appium/types').StringRecord} */ (configHolder).configuration = configuration;
}
// if the node config does not have the appium/webdriver url, host, and port,
// automatically add it based on how appium was initialized
// otherwise, we will take whatever the user setup
// because we will always set localhost/127.0.0.1. this won't work if your
// node and grid aren't in the same place
if (
!configHolder.configuration.url ||
!configHolder.configuration.host ||
!configHolder.configuration.port
) {
configHolder.configuration.url = `http://${addr}:${port}${basePath}`;
configHolder.configuration.host = addr;
configHolder.configuration.port = port;
}
// if the node config does not have id automatically add it
if (!configHolder.configuration.id) {
configHolder.configuration.id = `http://${configHolder.configuration.host}:${configHolder.configuration.port}`;
}
// the post options
const regRequest = {
url: `${hubUri(configHolder.configuration)}/grid/register`,
method: 'POST',
data: configHolder,
};
if (configHolder.configuration.register !== true) {
logger.debug(`No registration sent (${configHolder.configuration.register} = false)`);
return;
}
const registerCycleInterval = configHolder.configuration.registerCycle;
if (isNaN(registerCycleInterval) || registerCycleInterval <= 0) {
logger.warn(
`'registerCycle' is not a valid positive number. ` +
`No registration request will be sent to the grid.`
);
return;
}
// initiate a new Thread
let first = true;
logger.debug(
`Starting auto register thread for the grid. ` +
`Will try to register every ${registerCycleInterval} ms.`
);
setInterval(async function registerRetry() {
if (first) {
first = false;
await registerToGrid(regRequest, configHolder);
} else if (!(await isAlreadyRegistered(configHolder))) {
// make the http POST to the grid for registration
await registerToGrid(regRequest, configHolder);
}
}, registerCycleInterval);
}
async function isAlreadyRegistered(configHolder) {
//check if node is already registered
const id = configHolder.configuration.id;
try {
const {data, status} = await axios({
url: `${hubUri(configHolder.configuration)}/grid/api/proxy?id=${id}`,
timeout: 10000,
});
if (status !== 200) {
throw new Error(`Request failed with code ${status}`);
}
if (!data.success) {
// if register fail, print the debug msg
logger.debug(`Grid registration error: ${data.msg}`);
}
return data.success;
} catch (err) {
logger.debug(`Hub down or not responding: ${err.message}`);
}
}
export default registerNode;