UNPKG

3.79 kBJavaScriptView Raw
1import decamelize from 'decamelize';
2export const validObjectOrArray = (object) => (Array.isArray(object) && object.length > 0) ||
3 (typeof object === 'object' && Object.keys(object).length > 0);
4/**
5 * remove line numbers from file path, ex:
6 * `/foo:9` or `c:\bar:14:5`
7 * @param {string} filePath path to spec file
8 * @returns {string}
9 */
10export function removeLineNumbers(filePath) {
11 const matcher = filePath.match(/:\d+(:\d+$|$)/);
12 if (matcher) {
13 filePath = filePath.substring(0, matcher.index);
14 }
15 return filePath;
16}
17/**
18 * does spec file path contain Cucumber's line number, ex
19 * `/foo/bar:9` or `c:\bar\foo:14:5`
20 * @param {string|string[]} spec
21 */
22export function isCucumberFeatureWithLineNumber(spec) {
23 const specs = Array.isArray(spec) ? spec : [spec];
24 return specs.some((s) => s.match(/:\d+(:\d+$|$)/));
25}
26export function isCloudCapability(caps) {
27 return Boolean(caps && (caps['bstack:options'] || caps['sauce:options'] || caps['tb:options']));
28}
29/**
30 * validates configurations based on default values
31 * @param {Object} defaults object describing all allowed properties
32 * @param {Object} options option to check against
33 * @return {Object} validated config enriched with default values
34 */
35export function validateConfig(defaults, options, keysToKeep = []) {
36 const params = {};
37 for (const [name, expectedOption] of Object.entries(defaults)) {
38 /**
39 * check if options is given
40 */
41 if (typeof options[name] === 'undefined' && !expectedOption.default && expectedOption.required) {
42 throw new Error(`Required option "${name.toString()}" is missing`);
43 }
44 if (typeof options[name] === 'undefined' && expectedOption.default) {
45 params[name] = expectedOption.default;
46 }
47 if (typeof options[name] !== 'undefined') {
48 const optValue = options[name];
49 if (typeof optValue !== expectedOption.type) {
50 throw new Error(`Expected option "${name.toString()}" to be type of ${expectedOption.type} but was ${typeof options[name]}`);
51 }
52 if (typeof expectedOption.validate === 'function') {
53 try {
54 expectedOption.validate(optValue);
55 }
56 catch (e) {
57 throw new Error(`Type check for option "${name.toString()}" failed: ${e.message}`);
58 }
59 }
60 if (typeof optValue === 'string' && expectedOption.match && !optValue.match(expectedOption.match)) {
61 throw new Error(`Option "${name.toString()}" doesn't match expected values: ${expectedOption.match}`);
62 }
63 params[name] = options[name];
64 }
65 }
66 for (const [name, option] of Object.entries(options)) {
67 /**
68 * keep keys from source object if desired
69 */
70 if (keysToKeep.includes(name)) {
71 params[name] = option;
72 }
73 }
74 return params;
75}
76export function objectToEnv(params) {
77 /**
78 * apply all config options as environment variables
79 */
80 for (const [key, value] of Object.entries(params || {})) {
81 const envKey = decamelize(key).toUpperCase();
82 if (Array.isArray(value)) {
83 process.env[envKey] = value.join(',');
84 }
85 else if (typeof value === 'boolean' && value) {
86 process.env[envKey] = '1';
87 }
88 else if (value instanceof RegExp) {
89 process.env[envKey] = value.toString();
90 }
91 else if (typeof value === 'object') {
92 process.env[envKey] = JSON.stringify(value);
93 }
94 else if (value && typeof value.toString === 'function') {
95 process.env[envKey] = value.toString();
96 }
97 }
98}