1

I'm trying to write a small script which automatically inputs a username in this login page. According to Inspector (of Firefox), the input field is identified as the CSS selector input.input.input-text.input-default. So I wrote the script below.

(function() {
    "use strict";

    window.setTimeout(() => {
        const username = document.querySelector('input.input.input-text.input-default');
        username.setAttribute('value', 'test');
    }, 100); //waits a little until the input form becomes available

})();

This actually succeeds in inputting the username test, but when I input the password and click the submit button, the error message

username is required

is printed even though the field is not empty.

After that, if I click the username field, append any character, remove the character and then again click the submit button (see gif below), now the value of the field is correctly interpreted and the error message

Authentication failed

is printed, which is totally ok since we use the invalid test as a username.

enter image description here

I think this behavior comes from events associated with the input field. According to Inspector, focus, invalid, keydown, mousedown and onChange events are bound to the field. However, even if I execute

username.dispatchEvent(new Event('onChange'));

or such, the value is still interpreted as empty.

Two questions:

  • How can I make the script work in this case?

  • If you succeed in making the script work, could you tell me how you have analyzed the code structure of the website? Now I use Inspector but it seems insufficient.

ynn
  • 3,386
  • 2
  • 19
  • 42
  • Please provide HTML code of form also. – ikiK Mar 31 '20 at 10:57
  • @ikiK You can just visit the website I linked in the first line of OP. I'm sorry I cannot paste the entire code here because it's complicated and it's not open-source. – ynn Mar 31 '20 at 11:00

1 Answers1

0

Question 1

Just adding the line below to the first snippet, the problem has been solved.

username.dispatchEvent(new Event('input', {bubbles: true}));

So the resultant code should be

(function() {
    "use strict";

    window.setTimeout(() => {
        const username = document.querySelector('input.input.input-text.input-default');
        username.setAttribute('value', 'test');
        username.dispatchEvent(new Event('input', {bubbles: true})); //only difference
    }, 100);

})();

I do not know, however, why {bubbles: true} does the trick.

Question 2

Here is how I came up with the line:

  1. When I execute console.log(username), I found the object has the property __reactEventHandlers who has onChange method. Since
username.dispatchEvent(new Event('onChange'));
username.dispatchEvent(new Event('change'));
username.dispatchEvent(new Event('input'));

, etc. didn't work at all, I suspected the __reactEventHandlers is relevant in this case.

  1. To call the onChange method from JavaScript, I googled "javascript call react onchange" and found this answer.

Again, I do not know why {bubbles: true} does the trick, which should be appended to this answer or be explained in another answer.

ynn
  • 3,386
  • 2
  • 19
  • 42
  • Is this a React application? You definitely do NOT want to change values using DOM manipulation. No (sane) one will spend the time to figure out how your React components look like using the dev tools, if you can't post the source code then write a minimal example to reproduce your issue (hint...you have to set the value using what React offers, not setting `value` attribute). – Adriano Repetti Mar 31 '20 at 11:42
  • It might be the `setXyz()` function if you're using `useState()`, or `setState()` for a class component or start using `useReducer()` to expose an action which can be called from unrelated components if you need to set the value outside the component which holds the value itself. – Adriano Repetti Mar 31 '20 at 11:48
  • @AdrianoRepetti *Is this a React application?* I don't know. The website is not maintained by me. I'm just a user of the site and trying to write a userscript which is used only by me via greasemonkey. Thank you for your suggestion, anyway. I'll try to understand React (currently I'm not even a beginner of React). – ynn Mar 31 '20 at 12:06
  • If you need to automate a site you do not own you might want to try to send key events (keyDown & friends) instead of manipulating the HTML. – Adriano Repetti Mar 31 '20 at 13:35
  • First random result (probably many better ones out there): https://stackoverflow.com/questions/13598909/how-to-simulate-a-keypress-in-a-greasemonkey-script – Adriano Repetti Mar 31 '20 at 13:36