2

I'm trying to simulate a click using the developer console for a react element. For making it easy for you guys to test instead of using my code, use the following react website https://www.tradingview.com/chart/?symbol=COINBASE%3ABTCUSD

This occurs on other websites like Facebook as well on some items. This is just an easy no login site to test.

The section I'm trying to click is an item in the watchlist. In the picture below I put an arrow pointing to it. The particular menu appears when you click the button above the alarm clock icon in the far upper right of the screen under the 'Start free trial' blue buton.

enter image description here

To understand what I expect to happen, try clicking on any of the columns in the row, like SPX, NDQ, DJI, etc... (you should see the page and stock graph change)

I can 'sort' of simulate a click currently, but all it does is highlight the row but not actually change the page like when you perform an actual click.

To see what I mean, press F12 to open the developer console and type a command like below.

document.getElementsByClassName("wrap-XdW9S1Ib")[2].dispatchEvent(new Event('click',{bubbles:true}));

enter image description here

The class name might be different for you, so you might have to hunt around in the element menu of the developer console to find out what it is for you. Do a search for the word wrap- and you should eventually find the right set of classes.

In the picture I uploaded you will notice that the click event triggers a blue background around the NDQ (since that is the '3rd' element of the wrap class). Note that it DID NOT change the actual page and stock graph however.

I have tried sending other events like 'input', 'select', 'submit', 'dblclick' to no avail. I have tried clicking sub elements of that wrapper as well, every single one with no luck.

My goal is to get it to simulate the click and actually get it to change the page as a result of that click.

What am I doing wrong with my current approach?

7
  • somewhat facetious: What you're doing wrong is expecting someone to analyze an external (possibly proprietary) website for you. Commented Jun 22, 2022 at 2:48
  • @Tibrogargan I used this website merely as an example since this happens with other react websites, I can use another website as the example if you want? This is just the easiest one to test on. I couldn't figure out why it didn't work here. Commented Jun 22, 2022 at 2:54
  • That would be preferable. This is pretty far from a minimal reproducible example Commented Jun 22, 2022 at 2:55
  • Have you tried 'hover'? Commented Jun 22, 2022 at 3:01
  • Thank you, I have not yet, I will give it a try shortly Commented Jun 22, 2022 at 3:15

2 Answers 2

2

Okay so I figured it out. It turns out that react is very picky about the events being isTrusted: true AND it also needs a property nativeEvent : {detail:1}

So this will be complicated but to simulate the click correctly you have to first identify where the 'onClick' react element is.

In my case the element was the <div class="wrap-XdW9S1Ib" draggable="true"> from my tradingview example.

Thanks to the handy command monitorEvents($0,"click") which you can type in the console it will record all clicks for the last selected item in the elements tab view.

Using this you can type something like: var elem = $0; to easily set the element, or you can just select it like how I did in my question.

Next, a key thing to understand is that the isTrusted property of events is there to determine if the click was a genuine click or not. This is why elem.click() will not work!

So how do we get around this?

By putting a click event manually on top and recording the event to a global variable called event!

var event;
elem.addEventListener("click",function(e){console.log("click detected");event=e});

The key here is event=e to store it to the global variable. Now doing this alone is not enough, as if you call elem.click() this will just simply call both click events and it still will not work.

But, REACT works using synthetic events and takes the 'event' object to work with to pass on its data.

Therefore, if you know where its true onClick event is that supercedes the usual onclick you can call it directly with this isTrusted: true event.

Type a command like this to find the __reactProps for the object.

for(key in elem){console.log(key)}

This will print out all the objects. In my case onClick was hiding inside of elem.__reactProps$3jcigo40r49

Now simply call:

elem.__reactProps$3jcigo40r49.onClick(event);

and it will correctly treat it like an actual mouse click and trigger all the changes as you would expect. Except... wait, it still didn't work cause you get an error saying Cannot read properties of undefined (reading 'detail').

To fix this simply say in console.

event.nativeEvent = {detail:1}

Now try the previous command again and it will work!


EDIT -- Even easier Answer Below

Turns out there is an even easier solution.

It appears that in my case isTrusted does not matter. It was the nativeEvent: {details:1} that did.

Simply create a new pointer event like this.

var testEvent = new PointerEvent("click");
testEvent.nativeEvent = {detail:1}
elem.__reactProps$3jcigo40r49.onClick(testEvent);

3 lines of code and you can click!

Sign up to request clarification or add additional context in comments.

2 Comments

Nice analysis. This seems like it could be useful for a number of things
Indeed, its useful when you are trying to make test suites to automatically test your code to make sure it will work for the public.
0

When I try this I get an error:

Uncaught TypeError: document.querySelector(...).__reactProps$6jhf67fyckh.onClick is not a function

I am doing this in the Chrome Dev console. the document.querySelector(path) is autocompleting the __reactProps which displays:

document.querySelector("#root > div > div > div.sc-hQRsPl.bqPigl > div > div.sc-papXJ.iIImKA > form > div:nth-child(9) > input").__reactProps$6jhf67fyckh
{value: 'Redeem', disabled: false, type: 'submit', className: 'sc-jZiqTT izoCLX'}
className: "sc-jZiqTT izoCLX"
disabled: false
type: "submit"
value: "Redeem"
[[Prototype]]: Object

Also, as the __reactPops$6jhf67fyckh appears to be generated each time, is it possible to grab this some other way?

3 Comments

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
This seems more like you are asking a question then giving an answer?
SO is not designed to act as a forum. Top level comments should be answers. This is more of a comment sort of affair.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.