selenium-side-runner
Version:
Run Selenium IDE projects in cli
174 lines • 8.15 kB
JavaScript
;
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const child_process_1 = require("child_process");
const commander_1 = require("commander");
const crypto_1 = __importDefault(require("crypto"));
const fs_1 = __importDefault(require("fs"));
const merge_1 = __importDefault(require("lodash/fp/merge"));
const os_1 = __importDefault(require("os"));
const path_1 = __importDefault(require("path"));
const resolve_bin_1 = __importDefault(require("resolve-bin"));
const util_1 = __importDefault(require("util"));
const capabilities_1 = __importDefault(require("./capabilities"));
const config_1 = __importDefault(require("./config"));
const proxy_1 = __importDefault(require("./proxy"));
const metadata = require('../package.json');
const DEFAULT_TIMEOUT = 15000;
process.title = metadata.name;
const program = new commander_1.Command();
program
.usage('[options] your-project-glob-here-*.side [variadic-project-globs-*.side]')
.version(metadata.version)
.option('--base-url [url]', 'Override the base URL that was set in the IDE')
.option('-c, --capabilities [list]', 'Webdriver capabilities')
.option('-j, --jest-options [list]', 'Options to configure Jest, wrap in extra quotes to allow shell to process', '""')
.option('-s, --server [url]', 'Webdriver remote server')
.option('-r, --retries [number]', 'Retry tests N times on failures, thin wrapper on jest.retryTimes', (str) => parseInt(str), 0)
.option('-f, --filter [string]', 'Run suites matching name, takes a regex without slashes, eg (^(hello|goodbye).*$)')
.option('-w, --max-workers [number]', `Maximum amount of workers that will run your tests, defaults to number of cores`, (str) => parseInt(str))
.option('-t, --timeout [number]', `The maximimum amount of time, in milliseconds, to spend attempting to locate an element. (default: ${DEFAULT_TIMEOUT})`, (str) => parseInt(str), DEFAULT_TIMEOUT)
.option('-T, --jest-timeout [number]', `The maximimum amount of time, in milliseconds, to wait for a test to finish. (default: 60000)`, (str) => parseInt(str), 60000)
.option('-x, --proxy-type [type]', 'Type of proxy to use (one of: direct, manual, pac, socks, system)')
.option('-y, --proxy-options [list]', 'Proxy options to pass, for use with manual, pac and socks proxies')
.option('-n, --config-file [filepath]', 'Use specified YAML file for configuration. (default: .side.yml)')
.option('-o, --output-directory [directory]', 'Write test results as json to file in specified directory. Name will be based on timestamp.')
.option('-z, --screenshot-failure-directory [directory]', 'Write screenshots of failed tests to file in specified directory. Name will be based on test + timestamp.')
.option('-f, --force', "Forcibly run the project, regardless of project's version")
.option('-d, --debug', 'Print debug logs')
.option('-D, --debug-startup', 'Print debug startup logs')
.option('-X, --debug-connection-mode', 'Debug driver connection mode');
program.parse();
if (!program.args.length) {
program.outputHelp();
// eslint-disable-next-line no-process-exit
process.exit(1);
}
const options = program.opts();
let configuration = {
baseUrl: '',
capabilities: {
browserName: 'chrome',
},
debug: options.debug,
debugConnectionMode: options.debugConnectionMode,
debugStartup: options.debugStartup,
filter: options.filter || '.*',
force: options.force,
maxWorkers: os_1.default.cpus().length,
screenshotFailureDirectory: options.screenshotFailureDirectory,
// Convert all project paths into absolute paths
projects: [],
proxyOptions: {},
proxyType: undefined,
retries: options.retries,
runId: crypto_1.default.randomBytes(16).toString('hex'),
path: path_1.default.join(__dirname, '../../'),
server: '',
jestTimeout: options.jestTimeout,
timeout: DEFAULT_TIMEOUT,
};
const confPath = options.configFile || '.side.yml';
const configFilePath = path_1.default.isAbsolute(confPath)
? confPath
: path_1.default.join(process.cwd(), confPath);
try {
const configFileSettings = config_1.default.load(configFilePath);
configuration = (0, merge_1.default)(configuration, configFileSettings);
}
catch (e) {
const err = e;
if (options.configFile || err.code !== 'ENOENT') {
console.warn(err);
throw new Error('Could not load ' + configFilePath);
}
}
configuration = (0, merge_1.default)(configuration, {
baseUrl: options.baseUrl,
capabilities: capabilities_1.default.parseString(options.capabilities),
debug: options.debug,
maxWorkers: options.maxWorkers,
// Convert all project paths into absolute paths
projects: program.args.map((arg) => {
if (path_1.default.isAbsolute(arg))
return arg;
return path_1.default.join(process.cwd(), arg);
}),
proxyType: options.proxyType,
proxyOptions: options.proxyType === 'manual' || options.proxyType === 'socks'
? capabilities_1.default.parseString(options.proxyOptions)
: options.proxyOptions,
server: options.server,
timeout: options.timeout,
});
if (configuration.proxyType) {
const proxy = (0, proxy_1.default)(configuration.proxyType, configuration.proxyOptions);
configuration.capabilities.proxy = proxy;
}
const outputFilename = 'results-' + new Date().toISOString().replace(/:/g, '-') + '.json';
if (options.outputDirectory) {
if (!fs_1.default.existsSync(options.outputDirectory)) {
fs_1.default.mkdirSync(options.outputDirectory, { recursive: true });
}
const outputFile = path_1.default.join(options.outputDirectory, outputFilename);
if (!fs_1.default.existsSync(outputFile)) {
fs_1.default.writeFileSync(outputFile, '');
}
}
if (options.screenshotFailureDirectory) {
if (!fs_1.default.existsSync(options.screenshotFailureDirectory)) {
fs_1.default.mkdirSync(options.screenshotFailureDirectory, { recursive: true });
}
}
configuration.debugStartup &&
console.debug('Configuration:', util_1.default.inspect(configuration));
// All the stuff that goes into a big wrapped jest command
const jest = 'node ' + resolve_bin_1.default.sync('jest');
const jestArgs = [
'--config=' + path_1.default.join(__dirname, '..', 'runner.jest.config.js'),
'--maxConcurrency=' + configuration.maxWorkers,
]
.concat(options.outputDirectory
? [
'--json',
'--outputFile=' + path_1.default.join(options.outputDirectory, outputFilename),
]
: [])
.concat(options.jestOptions.slice(1, -1).split(' ').filter(Boolean))
.concat(['--runTestsByPath', path_1.default.join(__dirname, 'main.test.js')]);
const jestEnv = {
...process.env,
SE_CONFIGURATION: JSON.stringify(configuration),
};
configuration.debugStartup &&
console.debug('Jest command:', jest, jestArgs, jestEnv);
(0, child_process_1.spawn)(jest, jestArgs, {
cwd: process.cwd(),
env: jestEnv,
shell: true,
stdio: 'inherit',
}).on('exit', (code) => {
// This is my bin, my process
// eslint-disable-next-line no-process-exit
process.exit(code);
});
//# sourceMappingURL=bin.js.map