abhinaba-ghosh / cypress-react-selector

:zap: cypress plugin to locate react elements by component, props and state
https://www.cypress.io/
MIT License
274 stars 28 forks source link

Not able to find component- Multiple reasons #58

Closed aditya-3008 closed 4 years ago

aditya-3008 commented 4 years ago

Hi Abhinaba,

I have updated my Cypress.json file with the env for cypress-react-selector. I am getting error, while inspecting Component using React-Dev tool. Multiple reasons error.

Component not found <* name="tradition">

There can be multiple reasons for it.

Check the root is defined as a env parameter (cypress.json config file).

If the root is defined correctly, check other parameters - component name, props and state objects

cy.waitForReact(); const btn = cy.react('Anonymous', { props: { name: 'abc' } }); //const btn = cy.react('CatalogGridItem', { props: { name: 'xyz' } }); btn.click();

I am writing End to end tests and doesn't have access to source code, so is there any way to get the component name from React dev tool which I can use in my test scripts using Cyrpess-react-selector.

issue-label-bot[bot] commented 4 years ago

Issue-Label Bot is automatically applying the label question to this issue, with a confidence of 0.61. Please mark this comment with :thumbsup: or :thumbsdown: to give our bot feedback!

Links: app homepage, dashboard and code for this bot.

abhinaba-ghosh commented 4 years ago

Hi @aditya-3008 , the error you are receiving because the component is not found. If you are sure that you are mentioning the react-root correctly in the configuration file, then the only reason is an exact match with the props is not found. It is like any other selection process. If you can provide a similar repository where I can reproduce the bug, it will be helpful. You don't need to have the access to the source code, but you need to know what the react-root of the application. If the root is explicitly not provided, then cypress-reactselector` automatically figure it out. Now, the problem is there can be multiple roots. In that case, you need to provide the target one. For a zoom jam, connect me here

aditya-3008 commented 4 years ago

Can you share some example to find react-root of application, in my DOM I had " div id="root" class ="

So I took this root and put it in my config file. Do I need to take some other root for react, if yes how it will be.

abhinaba-ghosh commented 4 years ago

Those who do not have the access to source code can use react-dev-tool to fetch the real-time component information like:

Root: The parent where the object resides

Screenshot 2020-10-08 at 4 27 31 PM

Component:

Screenshot 2020-10-08 at 4 26 19 PM

So, the cypress test for this can be written like:

  it('enter data into the fields', () => {
    cy.react('MyTextInput', {props:{ field: { name: 'email' } }}).type(EMAILADDRESS);
    cy.react('MyTextInput', {props:{ field: { name: 'password' } }}).type(PASSWORD);
  });
aditya-3008 commented 4 years ago

I am using exactly the same syntax as per my application, but still, it is not able to find out. It is giving the same error. I think my application is having complex components structure with a lot of Anonymous components. Can you share URL of some application so that I can try my hands if I am finding components correctly or not.

abhinaba-ghosh commented 4 years ago

Can you check these tests

aditya-3008 commented 4 years ago

Thank you, I tested these tests and have much clear understanding now. However, I was using correct pattern in my scripts maybe the component name in my application is not appropriate or something. I want to ask that can we use other tags like { props: { item: { label: 'email' }}} as well instead of " name: 'mail' " considering the above example.

xshadowlegendx commented 4 years ago

hello, I also met this issue and I already made sure the root is found by setting non existence root which gave me root not found error and setting correct root which does not give me any error but when I try to use cy.react or cy.getReact it always through me the error

abhinaba-ghosh commented 4 years ago

Thank you, I tested these tests and have much clear understanding now. However, I was using correct pattern in my scripts maybe the component name in my application is not appropriate or something. I want to ask that can we use other tags like { props: { item: { label: 'email' }}} as well instead of " name: 'mail' " considering the above example.

@aditya-3008 you can use any of the props available for the target component.

abhinaba-ghosh commented 4 years ago

@xshadowlegendx @aditya-3008 It seems like the issue is happening on a larger scale. Using a production instance and not having the access to source code is a pain here. Would you guys mind sharing a private/public repository with some dummy codes and tests that you find difficult to construct? I can then give a proper look and re-constrcut the tests. I think in that way the learning will be complete from both the sides.

abhinaba-ghosh commented 4 years ago

Guys, for a better understanding, you also pull down this repository and play with it.

aditya-3008 commented 4 years ago

@xshadowlegendx @abhinaba-ghosh Yes it happens pn larger scale because I have tried with small basic react apps and it works fine but in real production sites it is not able to find any component using this pattern.

abhinaba-ghosh commented 4 years ago

Hey @aditya-3008, sometimes in production environment React components get minified and changed their names. Kindly inspect the component names and props in production vs beta/stage environments. If components and props adhere to the same nomenclature, then there should be no problem to fetch the elements with react-selector identifiers. In case if you find there are deviations in the production instance, you can build the react app in profiling mode to have the same component nomenclature.

403-html commented 4 years ago

I have problem with finding my component too. I want just check if it exist. I have many buttons but Cypress can't find my TextButton with children prop "Today"

Code:

cy.getReact('TextButton', { props: { children: 'Today' } })
      .getProps('children')
      .should(prop => {
        expect(prop).to.eq('Today');
      });

Env: image

Output: Previous subject found null. getProps() is a child command. Use with cy.getReact()

abhinaba-ghosh commented 4 years ago

@htd-tstepien This is happening because the component TextButton is not loaded at the time of you run the operation. This will be fixed with https://github.com/abhinaba-ghosh/cypress-react-selector/issues/48

Meanwhile, add extra logic to wait until the component gets loaded, then you execute the getReact. Something like:

cy.react('TextButton').should('exists');  // retries until existence 

cy.getReact('TextButton', { props: { children: 'Today' } })
      .getProps('children')
      .should(prop => {
        expect(prop).to.eq('Today');
      });

Let me know if that solves the problem.

aditya-3008 commented 4 years ago

Hi , I am still not able to find the component. Please have a sample DOM look of my app.

Code I am writing to inspect component const btn = cy.getReact('CatalogGridViewToggleBase', { props: { item: { name: 'abc' } } });

image

abhinaba-ghosh commented 4 years ago

Hey @aditya-3008, Can you be more specific? This is an interesting issue and I would like to understand which error it is throwing exactly. Can you try running the below code and inspect in cypress electron runner which exact error it is showing?

cy.react('CatalogGridViewToggleBase', { props: { item: { name: 'abc' } } }).should('exist');

Side note, cy.getReact returns RESQ node where cy.react returns the DOM element.

aditya-3008 commented 4 years ago

@abhinaba-ghosh - Issue is still the same, component not found. There can be multiple reasons for it.

Check the root is defined as a env parameter (cypress.json config file).

If the root is defined correctly, check other parameters - component name, props and state objects.

For your more understanding, let say we have multiple components with name CatalogGridViewToggleBase as tiles but we are giving the props name abc which is only one, I think the above code should work or do we have to follow other pattern to find a component which is having common name on the page but each of their props have different names. Because other child objects are also having same name i.e. CatalogGridViewToggleBase but inside its prop the name will be let say xyz. So I explained you scenario now what do you think the pattern of finding is correct or any other suggestion

abhinaba-ghosh commented 4 years ago

@aditya-3008 can you share a repository where I can reproduce the issue? Above code should work if cy.waitForReact executed without issues.

abhinaba-ghosh commented 4 years ago

Hi @aditya-3008 @xshadowlegendx @htd-tstepien Please upgrade to v2.1.0 and check if your issue gets resolved. I have added some fluent retry mechanism. If the issue is asynchronous loading, then this version will help you tremendously.

maga-polito commented 4 years ago

I'm having the same issues on tests that used to work no it seems like it can find any component even if the cypress-react-selector is loaded correctly, now if I try to wait for component existance it gives me following error {timeout: 30100}, function(){} Could not find instance of React in given element

abhinaba-ghosh commented 4 years ago

@maga-polito I think the thrown error is correct. Make sure the component you are searching should fall under the root you are specifying. I highly suggest going through a couple of projects that use the react-selector mentioned here. This library requires some understanding of how the app is built. Feel free to chat with me in Gitter if you need some assistance.

403-html commented 4 years ago

@htd-tstepien This is happening because the component TextButton is not loaded at the time of you run the operation. This will be fixed with #48

Meanwhile, add extra logic to wait until the component gets loaded, then you execute the getReact. Something like:

cy.react('TextButton').should('exists');  // retries until existence 

cy.getReact('TextButton', { props: { children: 'Today' } })
      .getProps('children')
      .should(prop => {
        expect(prop).to.eq('Today');
      });

Let me know if that solves the problem.

Hey @abhinaba-ghosh , sorry for the late response. Still without a result. (ps. "exists" doesn't exist, it's "exist")

    cy.react('TextButton').should('exist');

    cy.getReact('TextButton', { props: { children: 'Today' } })
      .getProps('children')
      .should(prop => {
        expect(prop).to.eq('Today');
      });

And I've got

image
abhinaba-ghosh commented 4 years ago

@htd-tstepien now this is something interesting. Can you share a repository where I can reproduce the issue? Feel free to connect with me in Gitter.

403-html commented 4 years ago

hmm, it'll be hard because it's a private project and I wanted to test this module if it can fit into our tech stack to simplify tests and expand possibilities 😕 I will keep an eye on the development of this module because it is promising, but it is a little bit incomprehensible to me to keep it in this situation.

abhinaba-ghosh commented 4 years ago

Sure @htd-tstepien. just curious to know,

  1. Are you running the tests with the raw components or you are using a production build of the application?
  2. I hope, you have tested some other components with this library. Is this the only component making the trouble?
403-html commented 4 years ago
  1. Raw
  2. Yes it works on other components
abhinaba-ghosh commented 4 years ago
  1. Raw
  2. Yes it works on other components

@htd-tstepien Good to know that it works with other components. Now specifically check if this component falls under a different react root or not. Sometimes apps do have different roots. If this is the case, then you can explicitly pass the root as:

cy.react('TextButton', {root:"#other-root"}).should('exists');
abhinaba-ghosh commented 4 years ago

Closing this thread. This is an error that can be caused for multiple reasons. If anyone gets the same, raise a separate ticket with a proper code example.

drecali commented 2 years ago

Thank you @abhinaba-ghosh for the advice below (and of course for maintaining such a useful plugin 🙏 )! My tests were passing locally in headless and headed mode, but cy.react() could never find the right components in the deployed version. In case it helps others, I'll include a comparison of how different my component names were.

...sometimes in production environment React components get minified and changed their names...

Local Deploy
image image
abhinaba-ghosh commented 2 years ago

Hi @drecali you can try this solution - https://stackoverflow.com/a/69760307