I'm trying to fill out a form in Puppeteer with an email and password, and then hit submit.
Each time the tests are run either the email or password isn't fully entered before the submit button is pressed. This is a cut-down version of what I'm doing:
await page.type(selectorSlackInputEmail, email);
await page.type(selectorSlackInputPassword, password);
await page.click(selectorSlackButtonSignIn);
I think it might be because the test isn't properly awaiting the completion of page.type and therefore focus switches to the next input or the submit button is pressed before each input field is complete.
How do I get around this problem?
I would expect your await directives to cover the issue you're seeing - my best guess is that because the type method simply...
sends keydown, keypress/input and keyup events [1]
... that maybe some listeners are taking a little while to execute their hooked functions between the sending of those events and the calling of the click method.
How about a workaround that explicitly checks that those selectors have the expected data before clicking submit?
await page.type(selectorSlackInputEmail, email);
await page.type(selectorSlackInputPassword, password);
await page.waitFor(() => {
return document.querySelector(selectorSlackInputEmail).value = email) &&
document.querySelector(selectorSlackInputPassword).value = password);
});
// And only *then*
await page.click(selectorSlackButtonSignIn);
After trying other methods (including await page.type and await page.focus followed by await page.keyboard.type) this is the only thing that works for me to fill multiple form fields:
await signInPage.evaluate(
(email, password) => {
document.querySelector('input#email').value = email;
document.querySelector('input#password').value = password;
},
email,
password
);
This doesn't satisfy my original use case though. I want to properly simulate a user typing into forms but this method circumvents that and directly inserts values into the fields.
I'd welcome a 'proper' solution to this problem.
I had the same problem in my code and decided to just use a delay with the click function.
await page.click('input[value="SUBMIT"]', {delay: 100});
Related
I'm making a mobile app that should login in a Website. I'm using this function to login and it is working. Values user and pass are taken from a TextField.
late WebViewController controller;
String user;
String pass;
Future<void> login() async {
await controller.loadUrl(urlToLogin);
await Future.delayed(Duration(seconds: 1));
final user = await storage.read(key: 'user');
final pass = await storage.read(key: 'pass');
await controller
.runJavascript("document.getElementById('j_username').value='$user'");
await controller
.runJavascript("document.getElementById('j_password').value='$pass'");
await Future.delayed(Duration(seconds: 1));
await controller.runJavascript('document.forms[0].submit()');
}
The problem is that sometimes could not be data connection, like I'm walking inside a tunnel. So if a user faces this issue I'd like to popup an alert that tells user to try again later.
Another task is that I want to know if the login succeeded because maybe user, by mistake, typed a wrong user or pass inside the TextField.
In other words, is that the possibility to know, using controller.runJavaScript if the login succeeded?
Thanks in advance
L.
I have to use PuppeteerSharp to login to one web site.
The web page uses JavaScript to generate dynamic class, so each time when I tried to login, I can see different class name.
So using Puppeteer Recorder is useless, I can't use its code to login.
But I checked its HTML structure, I found it is rather simple: there is one submit form with 3 input fields, the first one is input field for User_Name,
the second input field for Password, the third is button to submit the form.
So nowadays, I can use the following code to login with a lot of keyboard typings. But my code was NOT a good one, as other keyboard actions will make it a mess.
But I can't find any good PuppeteerSharp code to do something like this:
Find all 3 input fields, then type the user name in the first one, type the password in the second one, and click on the third one.
Please advise!
_page = await _bookie_browser.NewPageAsync();
await _page.SetViewportAsync((new ViewPortOptions { Width = 1920, Height = 3938 }));
await _page.GoToAsync("https://www.webpage.com");
await _page.WaitForTimeoutAsync(2000);
await _page.FocusAsync("input");
await _page.Keyboard.TypeAsync("username");
await _page.WaitForTimeoutAsync(1000);
await _page.Keyboard.PressAsync("Tab");
await _page.WaitForTimeoutAsync(1000);
await _page.Keyboard.TypeAsync("password");
await _page.Keyboard.PressAsync("Tab");
await _page.WaitForTimeoutAsync(1000);
await _page.Keyboard.PressAsync("Enter");
await _page.WaitForTimeoutAsync(1000);
I am trying to automate login in a Flash object via Puppeteer. I have automated focusing on the Flash TextArea just by clicking, and that seems to work (the vertical blinking bar that indicates that you are typing appears). However, I have tried using page.keyboard.press, page.keyboard.up/page.keyboard.down, and page.keyboard.type, and none successfully enter text into the username or password field. Furthermore, I have set a piece of injected Javascript to console.log the key name of every keypress event on the Flash object, and it only fires when I am manually typing while focused on the Flash object. It does not log anything during my attempts to use Puppeteer keyboard inputs. My code is as follows:
const login = async (page) => {
await page.waitFor(20);
const username = process.env.SIGNIN_USERNAME;
await page.click(500,500); // Select the username field
await page.waitFor(20); // Allow the blinking bar to appear
await page.keyboard.type(username);
for(let char of username) {
await page.keyboard.press(char);
await page.waitFor(20); // So that it appears like a user is typing
}
for(let char of username){
await page.keyboard.down(char);
await page.waitFor(10);
await page.keyboard.up(char);
await page.waitFor(20);
}
await page.type("object",username); // The Flash object is the first object on the page
console.log(username) // The username is logged to the console and is defined
};
This code does not result in any text appearing in the Flash TextArea. However, the correct username is logged to the console.
Am I making a mistake, or is there some general way in Puppeteer or even just in browser Javascript to enter text into a Flash TextArea that I'm missing? Thanks.
Try using a more low-level function like keyboard.sendCharacter, which doesn't deal with all the weird event handling of keyboard.press.
I'm using adonisjs and there is a problem with my update method:
async update(id, data) {
const user = await User.find(id);
user.merge(data);
return await user.save();
}
For some reason, the merge method doesn't modify the provided fields (data is an object with the fields I want to update and its new values) but updates everything... including the hashed user's password which is a big problem for me. I don't want to do such a thing, just update the provided fields. Is there a way to fix it?
I've stoped the application, served it once again and created a fresh new database just to be sure. It keeps updating fields that shouldn't be edited. Later, if the user tries to log in, it gets the next error message (obviously):
{
"message": "auth/login/error",
"error": "E_PASSWORD_MISMATCH: Cannot verify user password"
}
Images displaying the user's password being updated:
Before the update:
After the update:
What's up?
So, you can just update values instead of replacing it, for example:
user.name = "foo"
in the end
await user.save()
I would like to check if username and email address is unique on client side.
Is there any way to add custom validation for constraint validation?
Or is there any other recommended way for this?
I assume I have to send async http request (I am using node js on server side) but would like to follow best practice for this one.
Yes you can use the setCustomValidity function from the constraint validation api, which is part of every form field (e.g., HTMLInputElement).
<input name="username">
<script>
const field = document.querySelector('[name="username"]');
field.addEventListener('change', () => {
fetch('https://example.com/myapiforcheckingusername' {
method:'POST',
body: JSON.stringify({username: field.value})
}).then((response) => {
const alreadyExists = // process response to check if username already exists
if (alreadyExists) {
field.setCustomValidity('The username already exists!');
}
});
});
</script>
The above code shows how to make an async validation on an input field. If the setCustomValidity is not the empty string it means it is a form error. If checkValidity is called on the accompanying form it returns false then.
You can check the MDN documentation for further examples on this matter.
you can make a request on input's blur to check if what user has written in input is unique or not and show result to user with check mark or red X
or you can show user after he clicked on signup button but i prefer the first solution