1 | import decamelize from 'decamelize';
|
2 | export const validObjectOrArray = (object) => (Array.isArray(object) && object.length > 0) ||
|
3 | (typeof object === 'object' && Object.keys(object).length > 0);
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 | export 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 |
|
19 |
|
20 |
|
21 |
|
22 | export function isCucumberFeatureWithLineNumber(spec) {
|
23 | const specs = Array.isArray(spec) ? spec : [spec];
|
24 | return specs.some((s) => s.match(/:\d+(:\d+$|$)/));
|
25 | }
|
26 | export function isCloudCapability(caps) {
|
27 | return Boolean(caps && (caps['bstack:options'] || caps['sauce:options'] || caps['tb:options']));
|
28 | }
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 | export function validateConfig(defaults, options, keysToKeep = []) {
|
36 | const params = {};
|
37 | for (const [name, expectedOption] of Object.entries(defaults)) {
|
38 | |
39 |
|
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 |
|
69 |
|
70 | if (keysToKeep.includes(name)) {
|
71 | params[name] = option;
|
72 | }
|
73 | }
|
74 | return params;
|
75 | }
|
76 | export function objectToEnv(params) {
|
77 | |
78 |
|
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 | }
|