Signing into Office with Puppeteer not working? - javascript

Whenever I try to use Puppeteer to sign into an Office account, it always says to "Enter a valid email address" on the logging in site (and I know the email is valid, I have tested it). I looked through some other questions, and one of them mentioned that they might have login preventions for Puppeteer, Selenium, etc, though I am not sure. I am able to login if I do it manually.
Here's the code that handles all of that:
var email = "myemail#outlook.com"
await page.evaluate((em)=>{
document.querySelector(`[type="email"]`).value = em;
},email);
await page.screenshot({
path:"./email_input.png"
})
await page.waitForTimeout(1000);
await page.evaluate((em)=>{
var interval = setInterval(() => {
if(document.querySelector(`[type="email"]`).value === em){
document.querySelector(`[type="submit"]`).dispatchEvent(new Event('click'));
clearInterval(interval);
}
});
},email);
await page.screenshot({
path:"./sign_in_email.png"
})
edit to ManuelMB's comment: It was just a check to make sure that the value was actually the email. It still doesn't work without it.

Related

Playwright Javascript skip fill selector in Google Form

I use Playwright framework on JS to autofill unknow Google form (which means i dont know Xpath to specify the answer, i just know to question. In my situation, form ask about address, name, size, phone number).
const { webkit } = require('playwright');
const URL = 'https://forms.gle/B4r6qZKdyxZCApTWA';
(async () => {
const browser = await webkit.launch({ headless: false });
const page = await browser.newPage();
await page.goto(URL);
await page.fill('input:below(:has-text("Họ và tên"))','name');
await page.fill('input:below(:has-text("Số điện thoại"))','phone number');
await page.fill('input:below(:has-text("Địa chỉ"))','Address');
await page.fill('input:below(:has-text("CMND"))','id');
await page.fill('input:below(:has-text("Game"))','LOL');
await page.pause();
await browser.close();
})();
URL: https://forms.gle/B4r6qZKdyxZCApTWA
The name and number field is fine but in the address field, things get mess up. It skip and jump to the id field and fill 'address'->'LOL'->'id'
The answer field of Google Form has 2 kind: input and textarea. I just need to change it. But any better way to do more "general" to fit that kind of GForm?

Webscrape testing on a text field with jest-puppeteer

Okay everyone, got a bit of a doozy here. I am attempting to write a test using Jest and puppeteer for an email field. The problem is that I cannot seem to figure out how to get this test working. What I want to test is that if a user types in nothing into the email field, then an error message is displayed properly. I have attached photos of the CSS selector properties where you will find a customError: This cycles between true and false if valid inputs are in or not. I have also attached the HTML snippet where you will find the Id. I am a beginner at webscraping, JS, puppeteer, and Jest so I know this isn't ideal and I am sure there are many issues with my code. email text field image
CSS selector props close-up image
full view with devtools
I guess I cant embed images yet either so the links are provided!
test('empty field', async () => {
browser = await puppeteer.launch();
page = await browser.newPage();
await page.goto('https://platform.adcritter.com/')
await page.click('input[name=email]');
await page.type('input[name=email]', '') // no input
const doesItPass = await page.$$eval('input#if248af80-b989-11eb-8fad-f1ae53f1cff4',
validity => {expect({customError:true})}
)
browser.close()
}, 10000)
<input type="text" id="if248af80-b989-11eb-8fad-f1ae53f1cff4" name="email" placeholder="username#domain.com" class="euiFieldText euiFieldText--withIcon euiFieldText--fullWidth" tabindex="1" autocomplete="email" value="" aria-describedby="if248af80-b989-11eb-8fad-f1ae53f1cff4-error-0">

The click action in mailinator page does not work with protractor

I'm trying to automate the verification code sent to an email in mailinator, when I run the test therror is: "TimeoutError: Wait timed out after 35001ms", I'm thinking that is a problem with the async functions but I'm not secure about that.
const emailRow = element(by.className("tr.even.pointer.ng-scope"));
this.setCode = async function() {
let windows = await browser.getAllWindowHandles();
await browser.switchTo().window(windows[1]);
await browser.wait(ExpectedConditions.visibilityOf(emailRow), 50000);
browser.actions().mouseMove(emailRow).click().perform();
await browser.wait(ExpectedConditions.visibilityOf(emailCode), 35000);
}
I also tried this
this.setCode = async function() {
let windows = await browser.getAllWindowHandles();
await browser.switchTo().window(windows[1]);
await browser.wait(ExpectedConditions.elementToBeClickable(emailRow), 50000);
emailRow.click();
await browser.wait(ExpectedConditions.visibilityOf(emailCode), 35000);
}
But I have the same problem, in the screen I can't see that the test perform the click, I put an sleep after the click in the emailRow but doesn't work, in the image there is the page that i want to perform the click.
I think your best bet is to use their api, instead of going to their website and read the email there. In protractor, this is very easy. depending on whether or not you have a premium account with them you can use a public or a private team inbox. In the case of a public inbox, perform something similar to the following:
const checkMailinatorPublicEmail = async () => {
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
let requestUrl = 'https://mailinator.com/api/v2/domains/public/inboxes/your_inbox_name_here';
let responseBody = await fetch(requestUrl);
let responseJson = await responseBody.json();
return responseJson;
}
Now, you have all the email in the inbox in your response body as a json object. To keep this simple, do not use a static public team inbox, instead use a random inbox name so that each time you will only have one email in the inbox and you can parse that email to your needs.
I believe you should try the second approach. In the first approach, you are waiting for an element to be visible that does not guarantee an element is clickable.
By looking at second approach, the code looks fine. My suggestion is to try changing click method like below
browser.executeScript('arguments[0].click()', emailRow.getWebElement());
Hope this will help
Happy coding!

Entering data into multiple form inputs in Puppeteer

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});

Trouble Logging In To Google with Headless Chrome / Puppeteer

I'm trying to automate certain tasks for work. We have a portal that requires you to sign in through Google. I've created a Puppeteer instance that navigates to the Google auth page, types in my email and password, then stores the cookies so I can navigate through and manipulate the portal.
This works perfectly on my local environment, but I've deployed it to Heroku and Google adds a sign in challenge. After entering the password, I'm given the 'Verify it's you' page that says 'This device isn't recognized' and asks me to complete 2-FA auth.
I know I can't turn off 2-FA, so what would be the best way to bypass this?
Alternatively, is there an easier way to log in to a website guarded by Google auth and store the session cookies?
Here's my puppeteer code, any help would be much appreciated:
async function getCookies() {
const browser = await puppeteer.launch({
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-gpu'
]
})
const page = await browser.newPage()
await page.setUserAgent('Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36')
await page.goto(process.env.URL)
await page.waitForSelector('#identifierId')
await page.type('#identifierId', process.env.EMAIL, { delay: 5 })
await page.click('#identifierNext')
await page.waitForSelector('#password input[type="password"]', { visible: true });
await page.type('#password input[type="password"]', process.env.PASS, { delay: 5 })
await page.click('#passwordNext')
await page.waitFor(3000)
const cookies = await page.cookies()
await browser.close()
return cookies
}
Not possible I am afraid and not the answer you want.
I know I can't turn off 2-FA, so what would be the best way to bypass
this?`
If it was possible to bypass then it kinda opens the door for hackers as Two-factor authentication works as an extra step in the process, a second security layer, that will reconfirm your identity. Its purpose is to make attackers' life harder and reduce fraud risks!
I would have added an Android app in the mix too. You can set up the 2FA with SMS codes and an Android app with SMS read permission can read the SMS and connect with a backend.
The backend can send push message, probably using Firebase Cloud Messaging to the local Node.js instance where the headless Chrome is running to input it in the 2FA screen.
I don't think there's any other way to do it. Although I would recommend not doing it, since it may open some backdoor for security issues.
I is actually possible using Twilio API within Puppeteer to programatically receive the SMS code. You will have to setup a special Google account for this to work with the Twilio number as mobile phone OR change your current Google account primary mobile number for the Twilio number, and use your regular number as a secondary contact in your Google account info.
My working solution (needs some refactoring)
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: false, // for debugging only
ignoreHTTPSErrors: true // This happens when you use a self signed certificate locally
})
const page = await browser.newPage()
await page.setViewport({ width: 1280, height: 800 })
await page.goto('https://myawesomesystem/loginFrm01')
const navigationPromise = page.waitForNavigation()
// Clicks on the login button
const googleLoginButtonSelector = 'body > section > ... > div'
await page.waitForSelector( googleLoginButtonSelector )
await page.click( googleLoginButtonSelector )
// wait for the google oauth page to open
const googleOAuthTarget = await browser.waitForTarget( target => {
// console.log( target.url() ); // debugging
return target.url().indexOf('https://accounts.google.com/signin/oauth/identifier') !== -1
})
const googleOAuthPage = await googleOAuthTarget.page()
await googleOAuthPage.waitForSelector('#identifierId')
await googleOAuthPage.type('#identifierId', CRED.user, { delay: 5 } )
await googleOAuthPage.click('#identifierNext')
await googleOAuthPage.waitForSelector('input[type="password"]', { visible: true })
await googleOAuthPage.type('input[type="password"]', CRED.pass )
await googleOAuthPage.waitForSelector('#passwordNext', { visible: true })
await googleOAuthPage.click('#passwordNext')
await navigationPromise
// HERE:
// the user has been authenticated
// or login window was closed
// or whatever else, please check
await browser.close()
})()

Categories