Reputation: 203
I use this long line to check the selected value on any list on my page (using Ember power-select which is not a but a complex set of ), selector being the parent so I can target the list I want, and trimming being there so I can chain a .should('eq', expected_value)
cy.get(selector).find('span[class="ember-power-select-selected-item"]').invoke("text").then((text) => text.trim())
I would love to shorten all the commands after get in one, and be able to call something like
cy.get(selector).selected_value()
I've started reading on custom commands, wrap, invoke... but am too new on Cypress to understand the right way to do this.
Upvotes: 0
Views: 1822
Reputation: 31904
Creating a custom command can make your test more readable, encapsulate a group of commands that are repeated and need to be parameterized.
For your example testing the text of dropdown items, you can pass in the text and return the select so that chaining is possible
NOTES
In your code, .find().invoke("text")
returns all the item text in one string, so I added .contains()
to select an individual item.
If you're only interested in a partial match, the command chain can stop at .contain(text.trim())
Cypress.Commands.add('hasSelectedItemText',
{ prevSubject: true },
(subject, text) => {
cy.wrap(subject)
.find('span[class="ember-power-select-selected-item"]')
.contains(text.trim())
.invoke("text")
.should('eq', text.trim())
cy.wrap(subject) // returns the original select
}
)
cy.get(selector)
.hasSelectedItemText('one')
.hasSelectedItemText('two')
.hasSelectedItemText('three')
A more complicated example using the dual type command. Here the command can be parent or child, so the parameters have different meanings depending on usage
Cypress.Commands.add("dropdownItemText",
{ prevSubject: "optional" },
(subject, arg1, arg2) => {
if (subject) {
const text = arg1
cy.wrap(subject)
.find('span[class="ember-power-select-selected-item"]')
.contains(text.trim())
.invoke("text")
.should('eq', text.trim())
cy.wrap(subject) // returns the original select
} else {
const text = arg2
cy.get(arg1)
.find('span[class="ember-power-select-selected-item"]')
.contains(text.trim())
.invoke("text")
.should('eq', text.trim())
cy.get(arg1) // make select the returned "subject" for further chaining
}
}
)
cy.dropdownItemText(selector, 'one')
.dropdownItemText('two')
.dropdownItemText('three')
Upvotes: 3
Reputation: 1104
To add a custom command, you may add the following inside cypress/support/commands.js
file:
Cypress.Commands.add('selected_value', { prevSubject: true}, (subject) => {
return cy.wrap(subject).find('span[class="ember-power-select-selected-item"]').invoke("text").then((text) => text.trim())
})
Note that we use the prevSubject
option to be able to chain our command from an initial cy.get(selector)
one.
And now you are able to use the command:
cy.get(selector).selected_value().should('eq', expected_value)
Also, it's better to provide a type script definition file for the new command so IDE can be aware of it and provide the autocomplete and other features.
Adding a command might look a bit complicated for a beginner or annoying for an experienced user. There is Cypress Pro plugin (I'm the author) for the IntelliJ platform that can simplify creating and maintaining custom commands.
Upvotes: 1