cypress-io / cypress

Fast, easy and reliable testing for anything that runs in a browser.
https://cypress.io
MIT License
47.52k stars 3.2k forks source link

Selector playground doesn't correctly escape period in id #3902

Closed ngbrown closed 1 year ago

ngbrown commented 5 years ago

Current behavior:

When using the selector playground on an element (select or input in my case). The selected element it has a name attribute and an id attribute. Both attributes have a periods in them, like id="form.name.last". The code shown and copied to clipboard from the selector playground is incorrect.

This is what gets shown and copied to the clipboard:

Screenshot - 2019-04-06 , 11_02_37 AM

cy.get('#form\.name\.last')

JavaScript is treating this as if the period is being escaping and not passing the slash (\) through to Cypress. Thus the above is equivalent to this:

cy.get('#form.name.last')

When the test runs, the selector doesn't work:

CypressError: Timed out retrying: Expected to find element: '#form.name.last', but never found it.

Desired behavior:

To get the slash (\) passed through to Cypress, then the slash itself needs escaped:

cy.get('#form\\.name\\.last')

Note the two slashes (\\). The tests work correctly with the slash being properly escaped.

However typing that into the selector playground shows an red error and the "Print to console" button is grayed out, so fixing that that would be part of what needs fixed:

Screenshot - 2019-04-06 , 10_58_34 AM

Versions

Cypress 3.2.0 Chrome 72

must-git-good commented 5 years ago

The spirit of Cypress (as I see it) is to make sure your applications work as expected. I feel like changing Cypress to support non-typical html naming conventions would (even inadvertently) support practices that aren't universally recognized (which just increases the chance of running into some other kind of actual breaking-behavior somewhere else).

Maybe I'm wrong and dot notation in html has some actual use-case (I may be), but if not, I'd rather Cypress not support wonky behaviors (and just consider this a reminder that html usually considers dash-notation to be a best practice).

Edit: That said, you may be testing html that you didn't write, or that exists so broadly that 'fixing' it isn't an option. Maybe changing the selector playground to at least 'send back' the 'escaped \' solution correctly would be fine (if still probably an edge case).

desfero commented 5 years ago

@must-git-good but it's completely valid id selector and the same with name. So not supporting such cases is just a bug in the implementation.

must-git-good commented 5 years ago

@ngbrown

I dove into the issue a bit more today, and here's what I found:

You are correct in how the 'escaping' pattern works.

However, I don't think that this is a bug, really (or at least not worth 'fixing', as everything is behaving as expected for the . and \ behavior).

That is, without 'tricking' the playground selector into ignoring normal js behavior, there's no easy solution here. The \\. just passes on the \. to the selector (writing that was tricky...), which can then "see" the . in the document without being confused. Everything is just .js, and the use-case follows a pretty specific order. If dot.notation is a reality, you can just write your tests using \\. and assume that the playground selector won't work 'backwards'. (or that it will work, but just not in direct copy/paste scenarios.

Or...

I DID however, find what might be a solution for you or others trying to escape dot notation characters in a cypress test, but who want 'copy/paste' functionality within the selector playground.

It's not super-elegant, and depending on your use-case it might not apply. So do with it as you will.

Escaping the need to use \ by calling your string and then using a template literal:
<div data-testid="`dot.notation.test`">
^ returns that exact value in the playground selector and can be copy/pasted using the button.
cy.get('div[data-testid="`dot.notation.test`"]');
^ finds the value you're looking for, and plays nice with the playground.

Now, there's lots of cases where that's not the best solution, or where that solution is more problem than the initial problem...but it's something! And if you're going to have to type two characters anyway (the \\), perhaps instead inserting some `` might make your user-flow a bit more fluid.

Dunno, other thoughts on this are welcome. I could be WAY off base in how I think about the \ issue. Maybe that helps someone. shrug

calvinballing commented 5 years ago

Not sure if this is related enough to roll into this issue, or if it should be it's own bug, but:

Single quotes in selectors are not being escaped in the selector playground. So for the following element: image

The selector playground produces: image

Which when copied and pasted into Cypress does not work until the single quotes have escape characters prefixed to them manually.

jberthe commented 4 years ago

Hello Guys,

I know that the post and the "bug" is from 1 year ago, but, I'am working on SAPui5 with Annotated UI driven framework (SAP Fiori Elements). I try to test CyPress for E2E testing for SAP and I cannot change the id which is automatically generated with the namsespace in it. So There is lot of dot and double dot (:) in it.

When I try the selector playground (which I found amising feature... well done) I was stuck when the selector tel me it found my control and when I copy and past in my script, it dumps.

In UX point of you, when providing such a practical tool, it is important to have a minimum of consistency between the UI world and the Scripting world. I spent a bit too much time finding the bug in the script.

If you look at how $() works, it takes into account double slashes. So you should reconsider your point of view and fix this "bug" which can't be difficult to locate and fix.

It would bring a much better user experience.

vladtheimpala commented 4 years ago

Do we have general issues about id selector shorthand and some special chars ?

Template : <button id="product-add">

Not working :

.get('button#product-add')
.get('button#product\-add')

Working :

.get('button[id=product-add]')

Using an underscore char works perfectly with shorthand.

Cypress version : 5.0.0 Electron 83 / Chrome 84

Schrank commented 2 years ago

Same for [] as in id="group[6][15]"

IS: cy.get('#group\[7\]\[18\]') SHOULD BE: cy.get('#group\\[7\\]\\[18\\]')

But I understand the argument, that it is normal JS behaviour. But as long as I should be able to just copy from the selector, the selector should be copy pasteable and work.

I'm very thankful for cypress and it is an awesome tool! But I don't have any doubt, this is a bug and should be fixed for better developer experience :-)

cypress-app-bot commented 1 year ago

This issue has been closed due to inactivity.

dgodongm commented 1 year ago

I encountered issue on https://joinmastodon.org/ where Cypress app suggested: cy.get(':nth-child(1) > .full-width-bg__inner > .xl\:col-start-2 > .h4')

Given there's now been a handful of people who've encountered the issue over last few years, seems at least worth documenting (perhaps a new "selectors" section on the common issues table at https://docs.cypress.io/guides/references/troubleshooting). Can this be bug be re-reviewed for consideration?

nagash77 commented 1 year ago

Hi @dgodongm this issue is quite old. If you have a suggestion for an improvement to either how these this scenario is handled or ideas on ways we can better document the existing behavior would you mind opening up a new issue with specific examples of what you are encountering?

dgodongm commented 1 year ago

@nagash77 Not clear mine is really a separate issue, but logged new bug at #27258