Repository: bahmutov/cypress-map (js)

Issue:
Allow deep properties when mapping a list of properties to pick
```js
.map(['name.first', 'age'])
```

Pull request description:
Deep map
- closes #275 

Patch:
diff --git a/README.md b/README.md
index c49c643..8ef67d8 100644
--- a/README.md
+++ b/README.md
@@ -214,6 +214,15 @@ cy.wrap(people)
   .should('deep.equal', ['Joe', 'Anna'])
 ```
 
+If you want to pick multiple deep properties, the last segment will be the output property name
+
+```js
+// each person has nested objects like
+// { name: { first: '...', last: '...', }, human: { age: xx, ... } }
+cy.wrap(people).map(['name.first', 'human.age'])
+// each object will have "first" and "age" properties
+```
+
 ### mapInvoke
 
 ```js
diff --git a/src/commands/map.js b/src/commands/map.js
index 2ee12f2..825c8ec 100644
--- a/src/commands/map.js
+++ b/src/commands/map.js
@@ -67,10 +67,18 @@ registerQuery('map', function (fnOrProperty, options = {}) {
     if (isArrayOfStrings(fnOrProperty)) {
       const result = {}
       fnOrProperty.forEach((key) => {
-        if (!(key in $el)) {
-          throw new Error(`Cannot find property ${key}`)
+        if (key.includes('.')) {
+          // deep property pick
+          // use the last part of the key as the name
+          const name = key.split('.').pop()
+          const value = Cypress._.get($el, key)
+          result[name] = value
+        } else {
+          if (!(key in $el)) {
+            throw new Error(`Cannot find property ${key}`)
+          }
+          result[key] = $el[key]
         }
-        result[key] = $el[key]
       })
       return result
     } else if (Cypress._.isPlainObject(fnOrProperty)) {


Test patch:
diff --git a/cypress/e2e/map.cy.js b/cypress/e2e/map.cy.js
index 50b1649..21f0b00 100644
--- a/cypress/e2e/map.cy.js
+++ b/cypress/e2e/map.cy.js
@@ -72,34 +72,54 @@ it('maps properties of an object', () => {
     })
 })
 
-// https://github.com/bahmutov/cypress-map/issues/110
-it('picks the listed properties of the subject', () => {
-  const person = {
-    name: 'Joe',
-    age: 21,
-    occupation: 'student',
-  }
-  cy.wrap(person, { timeout: 0 })
-    .map(['name', 'age'])
-    .should('deep.equal', {
+describe('Picking properties', () => {
+  // https://github.com/bahmutov/cypress-map/issues/110
+  it('picks the listed properties of the subject', () => {
+    const person = {
       name: 'Joe',
       age: 21,
-    })
-})
+      occupation: 'student',
+    }
+    cy.wrap(person, { timeout: 0 })
+      .map(['name', 'age'])
+      .should('deep.equal', {
+        name: 'Joe',
+        age: 21,
+      })
+  })
 
-it('retries to find the picked properties', () => {
-  const person = {}
-  setTimeout(() => {
-    person.name = 'Joe'
-    person.occupation = 'student'
-    person.age = 21
-  }, 1000)
-  cy.wrap(person, { timeout: 1100 })
-    .map(['name', 'age'])
-    .should('deep.equal', {
-      name: 'Joe',
-      age: 21,
-    })
+  it('retries to find the picked properties', () => {
+    const person = {}
+    setTimeout(() => {
+      person.name = 'Joe'
+      person.occupation = 'student'
+      person.age = 21
+    }, 1000)
+    cy.wrap(person, { timeout: 1100 })
+      .map(['name', 'age'])
+      .should('deep.equal', {
+        name: 'Joe',
+        age: 21,
+      })
+  })
+
+  it('picks multiple nested properties', () => {
+    const person = {}
+    setTimeout(() => {
+      person.name = { first: 'Joe', last: 'Smith' }
+      person.occupation = 'student'
+      person.age = 21
+    }, 1000)
+    cy.wrap(person, { timeout: 1100 })
+      // should pick the property "age"
+      // and should pick the nested property "name.first"
+      // and store it under the name "first"
+      .map(['name.first', 'age'])
+      .should('deep.equal', {
+        first: 'Joe',
+        age: 21,
+      })
+  })
 })
 
 it('maps nested paths', () => {