{"ScriptPreparationCode":"var obj = {\r\n officeIpAddresses: [],\r\n customDomainHasUpdatedDns: false,\r\n stylePermissions: {\r\n styleAccess: {\r\n block: true,\r\n text: true,\r\n css: true,\r\n toolbar: true,\r\n motion: true,\r\n },\r\n editStyle: false,\r\n },\r\n permissions: {\r\n userInvitePermission: \u0022admin\u0022,\r\n defaultProjectAccess: \u0022none\u0022,\r\n },\r\n notifications: {\r\n subscriptions: [],\r\n projectFirstOpen: true,\r\n },\r\n modules: {\r\n quote: {\r\n savedLineItems: [{\r\n type: \u0022fixedCost\u0022,\r\n description: {\r\n content: \u0022\u003Cp\u003E\u003Cbr\u003E\u003C/p\u003E\u0022,\r\n widgets: {},\r\n tokens: [{\r\n type: \u0022block\u0022,\r\n subType: \u0022paragraph\u0022,\r\n },\r\n {\r\n type: \u0022inline\u0022,\r\n subType: \u0022text\u0022,\r\n content: \u0022TMS and ESS Licences\u0022,\r\n style: {},\r\n },\r\n ],\r\n },\r\n quantity: 1,\r\n discount: {\r\n enabled: false,\r\n type: \u0022percent\u0022,\r\n units: 0,\r\n },\r\n rate: {\r\n unit: \u0022Employee Licence\u0022,\r\n rate: 4.05,\r\n },\r\n isTaxExempt: false,\r\n interactive: {\r\n isOptional: false,\r\n isOptionalSelected: false,\r\n isQuantityOptional: false,\r\n quantityRange: {\r\n min: 0,\r\n max: 0,\r\n },\r\n isOptionalQuantity: false,\r\n },\r\n currency: \u0022GBP\u0022,\r\n id: \u0022k55w3lGzGM4\u0022,\r\n },\r\n {\r\n type: \u0022fixedCost\u0022,\r\n description: {\r\n content: \u0022\u003Cp\u003E\u003Cbr\u003E\u003C/p\u003E\u0022,\r\n widgets: {},\r\n tokens: [{\r\n type: \u0022block\u0022,\r\n subType: \u0022paragraph\u0022,\r\n },\r\n {\r\n type: \u0022inline\u0022,\r\n subType: \u0022text\u0022,\r\n content: \u0022MF901 Stainless Steel T\u0026amp;A/Muster Point - PoE - (Beta Test Sites Only) (Reader Required - To be Identified from External Readers)\u0022,\r\n style: {},\r\n },\r\n ],\r\n },\r\n quantity: 1,\r\n discount: {\r\n enabled: false,\r\n type: \u0022percent\u0022,\r\n units: 0,\r\n },\r\n rate: {\r\n unit: \u0022Unit\u0022,\r\n rate: 1750,\r\n },\r\n isTaxExempt: false,\r\n interactive: {\r\n isOptional: false,\r\n isOptionalSelected: false,\r\n isQuantityOptional: false,\r\n quantityRange: {\r\n min: 0,\r\n max: 0,\r\n },\r\n isOptionalQuantity: false,\r\n },\r\n currency: \u0022GBP\u0022,\r\n id: \u0022AOqDHpIIeAI\u0022,\r\n },\r\n ],\r\n },\r\n },\r\n};","TestCases":[{"Name":"lodash.cloneDeep","Code":"_.cloneDeep(obj);","IsDeferred":false},{"Name":"cleanJson [modified to clone] (Recursive)","Code":"function cleanJson(obj) {\r\n // LOOP THROUGH ARRAYS\r\n let cleaned;\r\n if (obj instanceof Array) {\r\n cleaned = [];\r\n for (const elem of obj) {\r\n cleaned.push(cleanJson(elem));\r\n }\r\n return cleaned;\r\n\r\n // CLEAN AN OBJECT\r\n } else if (obj \u0026\u0026 typeof obj === \u0022object\u0022) {\r\n cleaned = {};\r\n for (const key of Object.keys(obj)) {\r\n // If key starts with \u0022$\u0022 it is a private variable\r\n // If the key starts with _ we are expecting it to be\r\n // _id, __v or __t, all of which we don\u0027t allow in the clean\r\n // JSON as it is not something we want affecting Mongo\r\n // switch (key.charAt(0)) {\r\n // case \u0022$\u0022:\r\n // case \u0022_\u0022:\r\n // continue;\r\n // }\r\n\r\n // If the key is not one of those on our persistance\r\n // blacklist, we clean the sub-JSON\r\n cleaned[key] = cleanJson(obj[key]);\r\n }\r\n return cleaned;\r\n } else {\r\n return obj;\r\n }\r\n}\r\n\r\ncleanJson(obj);","IsDeferred":false},{"Name":"customDeepClone (Recursive)","Code":"function deepClone(obj) {\r\n let out;\r\n\r\n if (Array.isArray(obj)) {\r\n out = [];\r\n for (let index = 0; index \u003C obj.length; \u002B\u002Bindex) {\r\n const subArray = obj[index];\r\n out.push(typeof subArray === \u0022object\u0022 ? deepClone(subArray) : subArray);\r\n }\r\n } else {\r\n out = {};\r\n for (const key in obj) {\r\n const subObject = obj[key];\r\n out[key] = typeof subObject === \u0022object\u0022 ? deepClone(subObject) : subObject;\r\n }\r\n }\r\n return out;\r\n}\r\n\r\ndeepClone(obj);","IsDeferred":false},{"Name":"cloneJson (Loop)","Code":"function cloneJsonLoop(value) {\r\n if (!Array.isArray(value) \u0026\u0026 typeof value !== \u0022object\u0022) return value;\r\n\r\n let copyObj;\r\n const vs = [];\r\n if (Array.isArray(value)) {\r\n copyObj = [...value];\r\n } else if (typeof value === \u0022object\u0022) {\r\n copyObj = { ...value };\r\n }\r\n vs.push(copyObj);\r\n\r\n while (vs.length != 0) {\r\n const obj = vs.pop();\r\n if (obj instanceof Array) {\r\n for (let i = 0; i \u003C obj.length; i\u002B\u002B) {\r\n const value = obj[i];\r\n if (value instanceof Array) {\r\n obj[i] = value.slice();\r\n vs.push(obj[i]);\r\n } else if (typeof value === \u0022object\u0022) {\r\n obj[i] = Object.assign({}, value);\r\n vs.push(obj[i]);\r\n }\r\n }\r\n } /** typeof obj === object */ else {\r\n for (const key in obj) {\r\n const value = obj[key];\r\n if (value instanceof Array) {\r\n obj[key] = value.slice();\r\n vs.push(obj[key]);\r\n } else if (typeof value === \u0022object\u0022) {\r\n obj[key] = Object.assign({}, value);\r\n vs.push(obj[key]);\r\n }\r\n }\r\n }\r\n }\r\n return copyObj;\r\n}\r\n\r\ncloneJsonLoop(obj);","IsDeferred":false}]}