( object: Record<string, any>, propertyPath: string | Array<string>, )
| 57 | }; |
| 58 | |
| 59 | export const getPath = ( |
| 60 | object: Record<string, any>, |
| 61 | propertyPath: string | Array<string>, |
| 62 | ): GetPath => { |
| 63 | if (!Array.isArray(propertyPath)) { |
| 64 | propertyPath = pathAsArray(propertyPath); |
| 65 | } |
| 66 | |
| 67 | if (propertyPath.length > 0) { |
| 68 | const lastProp = propertyPath.length === 1; |
| 69 | const prop = propertyPath[0]; |
| 70 | const newObject = object[prop]; |
| 71 | |
| 72 | if (!lastProp && (newObject === null || newObject === undefined)) { |
| 73 | // This is not the last prop in the chain. If we keep recursing it will |
| 74 | // hit a `can't access property X of undefined | null`. At this point we |
| 75 | // know that the chain has broken and we can return right away. |
| 76 | return { |
| 77 | hasEndProp: false, |
| 78 | lastTraversedObject: object, |
| 79 | traversedPath: [], |
| 80 | }; |
| 81 | } |
| 82 | |
| 83 | const result = getPath(newObject, propertyPath.slice(1)); |
| 84 | |
| 85 | if (result.lastTraversedObject === null) { |
| 86 | result.lastTraversedObject = object; |
| 87 | } |
| 88 | |
| 89 | result.traversedPath.unshift(prop); |
| 90 | |
| 91 | if (lastProp) { |
| 92 | // Does object have the property with an undefined value? |
| 93 | // Although primitive values support bracket notation (above) |
| 94 | // they would throw TypeError for in operator (below). |
| 95 | result.endPropIsDefined = !isPrimitive(object) && prop in object; |
| 96 | result.hasEndProp = newObject !== undefined || result.endPropIsDefined; |
| 97 | |
| 98 | if (!result.hasEndProp) { |
| 99 | result.traversedPath.shift(); |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | return result; |
| 104 | } |
| 105 | |
| 106 | return { |
| 107 | lastTraversedObject: null, |
| 108 | traversedPath: [], |
| 109 | value: object, |
| 110 | }; |
| 111 | }; |
| 112 | |
| 113 | // Strip properties from object that are not present in the subset. Useful for |
| 114 | // printing the diff for toMatchObject() without adding unrelated noise. |
no test coverage detected