Cypress: Select / highlight text

Created on 26 Nov 2018  路  15Comments  路  Source: cypress-io/cypress

Current behavior:

I'm having a hard time creating a text selection. Things I've tried:

  • document.createRange() and window.getSelection()
  • Using cy.trigger to simulate a cursor drag over the paragraph.
  • Using dblclick on the paragraph.

Desired behavior:

Test highlighting text.

Steps to reproduce:

I can provide sample code for the approaches I tried, but I'll hold off for now in case there's a completely different known way of doing this.

Versions

Cypress 3.1.1, Chrome 70.0.3538.102

4锔忊儯 existing workaround pkdriver proposal 馃挕 feature

Most helpful comment

Here are a couple of commands that are working for my team, using Cypress to test a Slate based editor:
https://gist.github.com/erquhart/37bf2d938ab594058e0572ed17d3837a

Includes the ability to naively select based on text matching:

cy.get('p').setSelection('foo')

Or set both the start and end points of the selection:

cy.get('p').setSelection('foo', 'baz')

Also setCursorBefore/After with the same text matching interface, plus some other lower level commands.

All 15 comments

What are you trying to test with highlighting text? It'll be easier to determine a fix if we understand what you're trying to do.

My application keeps a record of highlighted text. I'm trying to test that that works correctly.

We've gotten this question several times. We don't have a specific API implemented to handle highlighting text. We do have a generic cy.trigger() where you can trigger any event, so it is theoretically possible to test many of what you'd need, but would require intimate knowledge of how your application works and what events it triggers.

I will update this issue to reflect request for this feature. This issue should now track:

  • Proposals for how users would like to cypress commands work to test 'highlight' text
  • Current workarounds for testing highlighting text.
  • Any PRs/progress made for the implementation.

This feature also requires work that's already in progress for our Native Events issue: https://github.com/cypress-io/cypress/issues/311

Related comment from @tnrich on wanting ability to highlight text with cy.type('{meta}a'):

I would specifically like a way to trigger the exact same thing as a user-invoked "meta+a" on any element. That might happen to select text in some instances, or select everything in the page if not inside an input/textarea, or it might do something totally different if there are hotkeys listening to that specific keypress.

@Bkucera Would this situation be covered in the Native Events work currently?

This would have to be a new command entirely, and isn't planned for the native events release. However we do plan to support text selection in the future

In the meantime, you can try this:

cy.get('p.mytext')
.trigger('mousedown')
.then(($el) => {
  const el = $el[0]
  const document = el.ownerDocument
  const range = document.createRange()
  range.selectNodeContents(el)
  document.getSelection().removeAllRanges(range)
  document.getSelection().addRange(range)
})
.trigger('mouseup')
cy.document().trigger('selectionchange')

@Bkucera why this line cy.document().trigger('selectionchange') is needed? Btw, great solution!

Here are a couple of commands that are working for my team, using Cypress to test a Slate based editor:
https://gist.github.com/erquhart/37bf2d938ab594058e0572ed17d3837a

Includes the ability to naively select based on text matching:

cy.get('p').setSelection('foo')

Or set both the start and end points of the selection:

cy.get('p').setSelection('foo', 'baz')

Also setCursorBefore/After with the same text matching interface, plus some other lower level commands.

@vctormb it's what the browser fires if you were to select text manually, but it won't make a difference if your app code doesn't listen for it

FYI, I couldn't get the gist above working with input or textarea's and it looks like its due to lack of support: https://developer.mozilla.org/en-US/docs/Web/API/Window/getSelection#Related_objects (it also wasn't working in Chrome 80 for me), so I created a fork of the gist with a different path for those elements:
https://gist.github.com/samtsai/5cf901ba61fd8d44c8dd7eaa728cac49

@erquhart Thanks you so much !!! The highlighting works !!!

I feel maybe this can be made into an official way of highlighting text instead of just being labelled as a workaround !!! hehe

Yeah I used this Gist successfully on a selection-heavy project test suite and encountered no real issue, I'd be fine if this was the code used for official support despite its potential limitations, it's still better than no support

Glad it worked for you! It's super naive, Eg., duplicates of the targeted string can trip it up easily. We've avoided this by not using duplicate strings in our tests (they're generally short strings anyway). Probably not a viable candidate for a first class solution, but a good stopgap.

For anyone running into issues w/ the gist, our implementation has evolved a bit and may work better. You'll just have to dig a bit in the source file to find the relevant code. Here's the source as of today: https://github.com/netlify/netlify-cms/blob/a4b7481a99f58b9abe85ab5712d27593cde20096/cypress/support/commands.js#L180

@erquhart Thanks a lot! You saved us hours of work.

I really recommend you to create a separate package with all selection related commands so people can just install it via npm in the future and use it directly. I'd be the first one to star it!

For future readers: if @erquhart solution is not working for you, try to trigger a 'selectstart' after the triggered 'mousedown' in the 'selection' command. That seems to fake better a real mouse interaction.
In my case i had a popup that is triggered when text was selected.

Was this page helpful?
0 / 5 - 0 ratings