Repository: bahmutov/cypress-map
Pull request #5 (2022-12-13 01:54:27)

feat: add cy.prop query command


Patch:
diff --git a/README.md b/README.md
index 0067e2e..691db43 100644
--- a/README.md
+++ b/README.md
@@ -106,6 +106,16 @@ cy.get('.matching')
 
 See [primo.cy.js](./cypress/e2e/primo.cy.js)
 
+### prop
+
+Works like `cy.its` for objects, but gets the property for jQuery objects, which `cy.its` does not
+
+```js
+cy.get('#items li.matching').last().prop('ariaLabel').should('equal', 'four')
+```
+
+See [prop.cy.js](./cypress/e2e/prop.cy.js)
+
 ## cy.invoke vs cy.map vs cy.mapInvoke
 
 Here are a few examples to clarify the different between the `cy.invoke`, `cy.map`, and `cy.mapInvoke` query commands, see [diff.cy.js](./cypress/e2e/diff.cy.js)
diff --git a/commands/index.d.ts b/commands/index.d.ts
index a02e6dd..4be5738 100644
--- a/commands/index.d.ts
+++ b/commands/index.d.ts
@@ -68,5 +68,14 @@ declare namespace Cypress {
      *  cy.wrap([1, 2, 3]).primo().should('equal', 1)
      */
     primo(): Chainable<any>
+
+    /**
+     * Returns the property of the object or DOM element, skipping through jQuery abstraction.
+     * @see https://github.com/bahmutov/cypress-map
+     * @param name The property name to yield
+     * @example
+     *  cy.get('#items li.matching').last().prop('ariaLabel')
+     */
+    prop(name: string): Chainable<any>
   }
 }
diff --git a/commands/index.js b/commands/index.js
index 218e4ec..cb79bbc 100644
--- a/commands/index.js
+++ b/commands/index.js
@@ -6,3 +6,4 @@ import './tap'
 import './reduce'
 import './apply'
 import './primo'
+import './prop'
diff --git a/commands/primo.js b/commands/primo.js
index 962cc53..ef5686c 100644
--- a/commands/primo.js
+++ b/commands/primo.js
@@ -1,3 +1,5 @@
+/// <reference types="cypress" />
+
 Cypress.Commands.addQuery('primo', () => {
   const log = Cypress.log({ name: 'primo' })
 
diff --git a/commands/prop.js b/commands/prop.js
new file mode 100644
index 0000000..f44cf59
--- /dev/null
+++ b/commands/prop.js
@@ -0,0 +1,12 @@
+/// <reference types="cypress" />
+
+Cypress.Commands.addQuery('prop', (propertyName) => {
+  const log = Cypress.log({ name: 'prop', message: propertyName })
+
+  return (subject) => {
+    if (Cypress.dom.isJquery(subject)) {
+      return subject.prop(propertyName)
+    }
+    return subject[propertyName]
+  }
+})
diff --git a/cypress/index.html b/cypress/index.html
index 43195a9..103434d 100644
--- a/cypress/index.html
+++ b/cypress/index.html
@@ -18,7 +18,7 @@
         <li class="matching">first</li>
         <li>second</li>
         <li class="matching">third</li>
-        <li class="matching">fourth</li>
+        <li class="matching" aria-label="four">fourth</li>
         <li>fifth</li>
       `
     }, 1000)


Test patch:
diff --git a/cypress/e2e/prop.cy.js b/cypress/e2e/prop.cy.js
new file mode 100644
index 0000000..6c196ee
--- /dev/null
+++ b/cypress/e2e/prop.cy.js
@@ -0,0 +1,28 @@
+/// <reference types="cypress" />
+// @ts-check
+
+import '../../commands'
+
+it('yields the object property using cy.its', () => {
+  const o = {}
+  cy.wrap(o).its('name').should('equal', 'Joe')
+
+  setTimeout(() => {
+    o.name = 'Joe'
+  }, 1000)
+})
+
+it('yields the object property using cy.prop', () => {
+  const o = {}
+  cy.wrap(o).prop('name').should('equal', 'Joe')
+
+  setTimeout(() => {
+    o.name = 'Joe'
+  }, 1000)
+})
+
+it('yields the DOM prop', () => {
+  cy.visit('cypress/index.html')
+  // this does not work with cy.its
+  cy.get('#items li.matching').last().prop('ariaLabel').should('equal', 'four')
+})