Skip to content

Commit b6030dd

Browse files
Evgeniy LukoyanovDavertMik
authored andcommitted
Fix multiple run falsy parameter overriding (codeceptjs#1756)
* move replacevalue to utils * add tests for utils.replacevalue * fix bug with unreplacing of falsy values * rename replacevalue to replacevaluedeep
1 parent c700ba5 commit b6030dd

File tree

3 files changed

+207
-25
lines changed

3 files changed

+207
-25
lines changed

lib/command/run-multiple.js

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const runHook = require('../hooks');
88
const event = require('../event');
99
const collection = require('./run-multiple/collection');
1010
const clearString = require('../utils').clearString;
11+
const replaceValueDeep = require('../utils').replaceValueDeep;
1112

1213
const runner = path.join(__dirname, '/../../bin/codecept');
1314
let config;
@@ -119,7 +120,7 @@ function executeRun(runName, runConfig) {
119120
const browserName = browserConfig.browser;
120121

121122
for (const key in browserConfig) {
122-
overriddenConfig.helpers = replaceValue(overriddenConfig.helpers, key, browserConfig[key]);
123+
overriddenConfig.helpers = replaceValueDeep(overriddenConfig.helpers, key, browserConfig[key]);
123124
}
124125

125126
let outputDir = `${runName}_`;
@@ -135,9 +136,9 @@ function executeRun(runName, runConfig) {
135136
outputDir = clearString(outputDir);
136137

137138
// tweaking default output directories and for mochawesome
138-
overriddenConfig = replaceValue(overriddenConfig, 'output', path.join(config.output, outputDir));
139-
overriddenConfig = replaceValue(overriddenConfig, 'reportDir', path.join(config.output, outputDir));
140-
overriddenConfig = replaceValue(overriddenConfig, 'mochaFile', path.join(config.output, outputDir, `${browserName}_report.xml`));
139+
overriddenConfig = replaceValueDeep(overriddenConfig, 'output', path.join(config.output, outputDir));
140+
overriddenConfig = replaceValueDeep(overriddenConfig, 'reportDir', path.join(config.output, outputDir));
141+
overriddenConfig = replaceValueDeep(overriddenConfig, 'mochaFile', path.join(config.output, outputDir, `${browserName}_report.xml`));
141142

142143
// override tests configuration
143144
if (overriddenConfig.tests) {
@@ -185,24 +186,3 @@ function executeRun(runName, runConfig) {
185186
return onProcessEnd(1);
186187
});
187188
}
188-
189-
190-
/**
191-
* search key in object recursive and replace value in it
192-
*/
193-
function replaceValue(obj, key, value) {
194-
if (!obj) return;
195-
if (obj instanceof Array) {
196-
for (const i in obj) {
197-
replaceValue(obj[i], key, value);
198-
}
199-
}
200-
if (obj[key]) obj[key] = value;
201-
if (typeof obj === 'object' && obj !== null) {
202-
const children = Object.keys(obj);
203-
for (let childIndex = 0; childIndex < children.length; childIndex++) {
204-
replaceValue(obj[children[childIndex]], key, value);
205-
}
206-
}
207-
return obj;
208-
}

lib/utils.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,3 +305,32 @@ module.exports.beautify = function (code) {
305305
const format = require('js-beautify').js;
306306
return format(code, { indent_size: 2, space_in_empty_paren: true });
307307
};
308+
309+
/**
310+
* Recursively search key in object and replace it's value.
311+
*
312+
* @param {*} obj source object for replacing
313+
* @param {string} key key to search
314+
* @param {*} value value to set for key
315+
*/
316+
module.exports.replaceValueDeep = function replaceValueDeep(obj, key, value) {
317+
if (!obj) return;
318+
319+
if (obj instanceof Array) {
320+
for (const i in obj) {
321+
replaceValueDeep(obj[i], key, value);
322+
}
323+
}
324+
325+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
326+
obj[key] = value;
327+
}
328+
329+
if (typeof obj === 'object' && obj !== null) {
330+
const children = Object.values(obj);
331+
for (const child of children) {
332+
replaceValueDeep(child, key, value);
333+
}
334+
}
335+
return obj;
336+
};

test/unit/utils_test.js

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,177 @@ describe('utils', () => {
6060
.should.eql('concat(\'can\',"\'",\'t find thing\')');
6161
});
6262
});
63+
64+
describe('#replaceValueDeep', () => {
65+
let target;
66+
67+
it('returns updated object', () => {
68+
target = {
69+
timeout: 1,
70+
helpers: {
71+
something: 2,
72+
},
73+
};
74+
75+
utils.replaceValueDeep(target.helpers, 'something', 1234).should.eql({ something: 1234 });
76+
target.should.eql({
77+
timeout: 1,
78+
helpers: {
79+
something: 1234,
80+
},
81+
});
82+
});
83+
84+
it('do not replace unexisting value', () => {
85+
target = {
86+
timeout: 1,
87+
helpers: {
88+
something: 2,
89+
},
90+
};
91+
92+
utils.replaceValueDeep(target, 'unexisting', 1234);
93+
target.should.eql({
94+
timeout: 1,
95+
helpers: {
96+
something: 2,
97+
},
98+
});
99+
});
100+
101+
it('replace simple value', () => {
102+
target = {
103+
timeout: 1,
104+
helpers: {
105+
something: 2,
106+
},
107+
};
108+
109+
utils.replaceValueDeep(target, 'timeout', 1234);
110+
target.should.eql({
111+
timeout: 1234,
112+
helpers: {
113+
something: 2,
114+
},
115+
});
116+
});
117+
118+
it('replace simple falsy value', () => {
119+
target = {
120+
zeroValue: {
121+
timeout: 0,
122+
},
123+
falseValue: {
124+
timeout: false,
125+
},
126+
undefinedValue: {
127+
timeout: undefined,
128+
},
129+
emptyStringValue: {
130+
timeout: '',
131+
},
132+
nullValue: {
133+
timeout: null,
134+
},
135+
};
136+
137+
utils.replaceValueDeep(target, 'timeout', 1234);
138+
target.should.eql({
139+
zeroValue: {
140+
timeout: 1234,
141+
},
142+
falseValue: {
143+
timeout: 1234,
144+
},
145+
undefinedValue: {
146+
timeout: 1234,
147+
},
148+
emptyStringValue: {
149+
timeout: 1234,
150+
},
151+
nullValue: {
152+
timeout: 1234,
153+
},
154+
});
155+
});
156+
157+
it('replace value in array of objects', () => {
158+
target = {
159+
timeout: 1,
160+
something: [{
161+
a: 1,
162+
b: 2,
163+
}, {
164+
a: 3,
165+
},
166+
123,
167+
0,
168+
[{ a: 1 }, 123]],
169+
};
170+
171+
utils.replaceValueDeep(target, 'a', 1234);
172+
target.should.eql({
173+
timeout: 1,
174+
something: [{
175+
a: 1234,
176+
b: 2,
177+
}, {
178+
a: 1234,
179+
},
180+
123,
181+
0,
182+
[{ a: 1234 }, 123]],
183+
});
184+
});
185+
186+
it('replace simple value deep in object', () => {
187+
target = {
188+
timeout: 1,
189+
helpers: {
190+
something: {
191+
otherthing: 2,
192+
},
193+
},
194+
};
195+
196+
utils.replaceValueDeep(target, 'otherthing', 1234);
197+
target.should.eql({
198+
timeout: 1,
199+
helpers: {
200+
something: {
201+
otherthing: 1234,
202+
},
203+
},
204+
});
205+
});
206+
207+
it('replace object value', () => {
208+
target = {
209+
timeout: 1,
210+
helpers: {
211+
WebDriver: {
212+
timeouts: 0,
213+
url: 'someurl',
214+
},
215+
someHelper: {
216+
timeouts: 3,
217+
},
218+
},
219+
};
220+
221+
utils.replaceValueDeep(target.helpers, 'WebDriver', { timeouts: 1234 });
222+
target.should.eql({
223+
timeout: 1,
224+
helpers: {
225+
WebDriver: {
226+
timeouts: 1234,
227+
// url is not described in new object
228+
},
229+
someHelper: {
230+
timeouts: 3,
231+
},
232+
},
233+
});
234+
});
235+
});
63236
});

0 commit comments

Comments
 (0)