Playing With DevExtreme Text Input

A common scenario for entering text using web widgets.

Typically a rich web widget UI wraps around <input ...> elements. The library hides the original plain inputs, while showing custom elements and showing formatted text. In this blog post, I will show a typical example from DevExtreme library.

🎁 You can find the source code for this blog post in the repo bahmutov/cypress-devextreme-example.

📺 Watch the explanation from this blog post in the video "Test Formatted Phone Number Input".

Let's load the example page

cypress/e2e/phone.cy.js
1
2
3
it('formats the phone number', () => {
cy.visit('app/index.html')
})

We want to validate the input entered into the phone field

How do we test the phone number?

Let's inspect the HTML markup.

The HTML markup

We have the hidden phone input element with the "raw" phone number without any formatting. We also have the textbox input element that the user sees on the page and that shows formatted text. Let's verify the starting phone number - we don't know it, but we know it is a ten digit number.

1
2
3
4
5
6
7
it('formats the phone number', () => {
cy.visit('app/index.html')
// starts with a 10 digit number
cy.get('input[name=Mobile]')
.should('have.prop', 'value')
.should('match', /^\d{10}$/)
})

Checking the initial phone number

Let's now find the textbox and enter the new number to see if sets the real form input. We will go from the input[name=Mobile] element to its parent and then find the textbox. We will type the test phone number 123 456 7890 without spaces. Once we remove the focus from the input textbox field using cy.blur it should set the actual input.

1
2
3
4
5
6
7
8
9
10
11
12
13
it('formats the phone number', () => {
cy.visit('app/index.html')
// starts with a 10 digit number
cy.get('input[name=Mobile]')
.should('have.prop', 'value')
.should('match', /^\d{10}$/)
cy.get('input[name=Mobile]')
.parent()
.find('input[role=textbox]')
.clear()
.type('1234567890')
.blur()
})

Type the test phone number

Now let's verify the hidden input; it should have the raw number text. Then we should verify the textbox; it should have the formatted phone number.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
it('formats the phone number', () => {
cy.visit('app/index.html')
// starts with a 10 digit number
cy.get('input[name=Mobile]')
.should('have.prop', 'value')
.should('match', /^\d{10}$/)
cy.get('input[name=Mobile]')
.parent()
.find('input[role=textbox]')
.clear()
.type('1234567890')
.blur()
cy.get('input[name=Mobile]')
.should('have.value', '1234567890')
.parent()
.find('input[role=textbox]')
// the text box has formatted phone number
.should('have.value', '+1 (123) 456-7890')
})

Two phone inputs

And that is how you work with rich web UI widgets in your Cypress tests.

Tip: any time you verify text on the page, you should try to make as strict as possible to catch possible regressions. Watch my video Use Stronger Assertions for example.

See also