Copy W3C/Element keys instead of renaming them
MODIFY
lib/basedriver/helpers.js
lib/basedriver/helpers.js
@@ -317,24 +317,40 @@ function getSwipeTouchDuration (waitGesture) {
}
/**
- * Recursively find all instances of the key 'inKey' and rename them 'outKey'
+ * Finds all instances 'firstKey' and create a duplicate with the key 'secondKey',
+ * Do the same thing in reverse. If we find 'secondKey', create a duplicate with the key 'firstKey'.
+ *
+ * This will cause keys to be overwritten if the object contains 'firstKey' and 'secondKey'.
+
* @param {*} input Any type of input
- * @param {String} inKey The key name to replace
- * @param {String} outKey The key name to replace it with
+ * @param {String} firstKey The first key to duplicate
+ * @param {String} secondKey The second key to duplicate
*/
-function renameKey (input, inKey, outKey) {
+function duplicateKeys (input, firstKey, secondKey) {
+ // If array provided, recursively call on all elements
if (_.isArray(input)) {
- return input.map((item) => renameKey(item, inKey, outKey));
- } else if (_.isPlainObject(input)) {
- return _.reduce(input, (resultObj, value, key) => ({
- ...resultObj,
- [key === inKey ? outKey : key]: renameKey(value, inKey, outKey),
- }), {});
+ return input.map((item) => duplicateKeys(item, firstKey, secondKey));
+ }
+
+ // If object, create duplicates for keys and then recursively call on values
+ if (_.isPlainObject(input)) {
+ const resultObj = {};
+ for (let [key, value] of _.toPairs(input)) {
+ const recursivelyCalledValue = duplicateKeys(value, firstKey, secondKey);
+ if (key === firstKey) {
+ resultObj[secondKey] = recursivelyCalledValue;
+ } else if (key === secondKey) {
+ resultObj[firstKey] = recursivelyCalledValue;
+ }
+ resultObj[key] = recursivelyCalledValue;
+ }
+ return resultObj;
}
+ // Base case. Return primitives without doing anything.
return input;
}
export {
- configureApp, isPackageOrBundle, getCoordDefault, getSwipeTouchDuration, renameKey,
+ configureApp, isPackageOrBundle, getCoordDefault, getSwipeTouchDuration, duplicateKeys,
};

MODIFY
lib/protocol/protocol.js
lib/protocol/protocol.js
@@ -4,7 +4,7 @@ import { validators } from './validators';
import { errors, isErrorType, errorFromMJSONWPStatusCode, errorFromW3CJsonCode,
getResponseForW3CError, getResponseForJsonwpError } from './errors';
import { METHOD_MAP, NO_SESSION_ID_COMMANDS } from './routes';
-import { renameKey } from '../basedriver/helpers';
+import { duplicateKeys } from '../basedriver/helpers';
import B from 'bluebird';
import BaseDriver from '../basedriver/driver';
import LRU from 'lru-cache';
@@ -381,14 +381,11 @@ function buildHandler (app, method, path, spec, driver, isSessCmd) {
};
}
}
- // If the MJSONWP element key format (ELEMENT) was provided translate it to W3C element key format (element-6066-11e4-a52e-4f735466cecf)
- // and vice-versa
+
+ // If the MJSONWP element key format (ELEMENT) was provided, add a duplicate key (element-6066-11e4-a52e-4f735466cecf)
+ // If the W3C element key format (element-6066-11e4-a52e-4f735466cecf) was provided, add a duplicate key (ELEMENT)
if (driverRes) {
- if (currentProtocol === BaseDriver.DRIVER_PROTOCOL.W3C) {
- driverRes = renameKey(driverRes, MJSONWP_ELEMENT_KEY, W3C_ELEMENT_KEY);
- } else {
- driverRes = renameKey(driverRes, W3C_ELEMENT_KEY, MJSONWP_ELEMENT_KEY);
- }
+ driverRes = duplicateKeys(driverRes, MJSONWP_ELEMENT_KEY, W3C_ELEMENT_KEY);
}
// convert undefined to null, but leave all other values the same

MODIFY
test/basedriver/helpers-specs.js
test/basedriver/helpers-specs.js
-import { isPackageOrBundle, renameKey } from '../../lib/basedriver/helpers';
+import { isPackageOrBundle, duplicateKeys } from '../../lib/basedriver/helpers';
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
@@ -18,25 +18,44 @@ describe('helpers', function () {
});
});
- describe('#renameKey', function () {
+ describe('#duplicateKeys', function () {
it('should translate key in an object', function () {
- renameKey({'foo': 'hello world'}, 'foo', 'bar').should.eql({'bar': 'hello world'});
+ duplicateKeys({'foo': 'hello world'}, 'foo', 'bar').should.eql({'foo': 'hello world', 'bar': 'hello world'});
});
it('should translate key in an object within an object', function () {
- renameKey({'key': {'foo': 'hello world'}}, 'foo', 'bar').should.eql({'key': {'bar': 'hello world'}});
+ duplicateKeys({'key': {'foo': 'hello world'}}, 'foo', 'bar').should.eql({'key': {'foo': 'hello world', 'bar': 'hello world'}});
});
it('should translate key in an object with an array', function () {
- renameKey([
+ duplicateKeys([
{'key': {'foo': 'hello world'}},
{'foo': 'HELLO WORLD'}
], 'foo', 'bar').should.eql([
- {'key': {'bar': 'hello world'}},
- {'bar': 'HELLO WORLD'}
+ {'key': {'foo': 'hello world', 'bar': 'hello world'}},
+ {'foo': 'HELLO WORLD', 'bar': 'HELLO WORLD'}
]);
});
+ it('should duplicate both keys', function () {
+ duplicateKeys({
+ 'keyOne': {
+ 'foo': 'hello world',
+ },
+ 'keyTwo': {
+ 'bar': 'HELLO WORLD',
+ },
+ }, 'foo', 'bar').should.eql({
+ 'keyOne': {
+ 'foo': 'hello world',
+ 'bar': 'hello world',
+ },
+ 'keyTwo': {
+ 'bar': 'HELLO WORLD',
+ 'foo': 'HELLO WORLD',
+ }
+ });
+ });
it('should not do anything to primitives', function () {
[0, 1, -1, true, false, null, undefined, "", "Hello World"].forEach((item) => {
- should.equal(renameKey(item), item);
+ should.equal(duplicateKeys(item), item);
});
});
it('should rename keys on big complex objects', function () {
@@ -55,20 +74,22 @@ describe('helpers', function () {
0
];
const expectedOutput = [
- {'FOO': 'bar'},
+ {'foo': 'bar', 'FOO': 'bar'},
{
hello: {
world: {
+ 'foo': 'BAR',
'FOO': 'BAR',
}
},
+ foo: 'bahr',
FOO: 'bahr'
},
'foo',
null,
0
];
- renameKey(input, 'foo', 'FOO').should.deep.equal(expectedOutput);
+ duplicateKeys(input, 'foo', 'FOO').should.deep.equal(expectedOutput);
});
});
});

MODIFY
test/protocol/protocol-e2e-specs.js
test/protocol/protocol-e2e-specs.js
@@ -531,10 +531,12 @@ describe('Protocol', function () {
const expectedValue = [
{
something: {
+ [MJSONWP_ELEMENT_KEY]: 'fooo',
[W3C_ELEMENT_KEY]: 'fooo',
other: 'bar'
}
}, {
+ [MJSONWP_ELEMENT_KEY]: 'bar',
[W3C_ELEMENT_KEY]: 'bar'
},
'ignore',

Copy W3C/Element keys instead of renaming them (#290)