Have you seen web sites that show you a list of random words to write down when signing up? When you go to log in, the site shows the same random words with some words missing. You need to enter the missing words exactly as they appeared, and this is how you log in. Here is a Cypress test showing this login in action:
Let's see how the Cypress test can "remember" the words and type them at the correct positions. The application has two screens: the first one shows the words to find and save, the second one shows the input elements instead of some words. We need to look up the saved word at that position and enter it.
🎁 You can find the source code for this blog post in the repository bahmutov/cypress-login-words. You can also watch the explanation in the video Log In Using Words.
Login fails
First, let's confirm the application does not let log in with incorrect words. On the second screen we can simply type "word" + index number.
1 | it('does not log in with wrong words', () => { |
We are using my favorite Cypress commands cy.contains, cy.get, cy.each, and cy.wrap.
📚 You can find lots of Cypress command examples at my site https://glebbahmutov.com/cypress-examples. It has a good search that quickly shows my practical Cypress use examples.
Save the words
In order for the end-to-end test to log in correctly, the test needs to save the shown words. We can store the words in a regular array.
1 | it('remembers the words', () => { |
We store the extracted words in the local variable words
. After the cy.each
command finishes, that array is filled with words. We can use the array after cy.each
command by using cy.then callback.
🤔 Are you not sure why and how Cypress executes its commands? Read my blog post Visualize Cypress Command Queue.
Type the saved words
Now that we have the words in the correct order, we need to look at the list shown on the second page. Some of the list items are <input>
elements and we need to enter the correct string from the array of strings. Here is how we look at each li
item, and use cy.each
command to check if there is an input element inside. We are using the jQuery .find
method to synchronously see if there is <li><input>...</li>
situation. If yes, we need to type the word at index k
using a Cypress command.
1 | cy.get('#login .words li').each(($li, k) => { |
Nice!
😳 Wait, isn't this an example of "Conditional Testing", which is an anti-pattern? Yes, we are looking at the page to decide what the test needs to do. Sometimes it is necessary, so I have a few recipes how to handle it.
Here is the full test that saves and types the words, and checks if the page transitions are successful.
1 | it('logs in', () => { |
Beautiful, isn't it.