Hi I am trying to login to page . but when i trying to run the code in chrome I got error .
But when i trying to login page the page give me an error -
"THE SESSION HAS EXPIRED
The page has been inactive for some time and so your session has been logged off for security reasons. Identify yourself to access your account again."
I tried to delete the history but it doesnt work.
This is my code :
async function login(page) {
try {
await page.goto(loginPageUrl);
await page.waitForSelector(MAIL_SELECTOR)
await page.click(MAIL_SELECTOR, { clickCount: 3 });
await page.keyboard.type(mail);
await page.waitForSelector(PASSWORD_SELECTOR, { visible: true });
await page.click(PASSWORD_SELECTOR, { clickCount: 3 });
await page.keyboard.type(password);
await page.click(BUTTON_SELECTOR);
await page.waitForNavigation()
} catch (err) {
console.log(err);
}
}
and before I start puppeter -
const browser = await puppeteer.launch({
headless: false,
defaultViewport: null,
});
const page = await browser.newPage();
await page.setExtraHTTPHeaders({
'accept-language': 'en-US,en;q=0.9,hy;q=0.8'
});
login(page)
Related
I'm coding a "delete account" functionality on my app and I want the user to enter their password again before triggering the deletion.
What would be the best way to implement this? I was thinking on using the "signInWithEmailAndPassword" method and capturing the result to check if the credentials are correct, but I'm afraid that would overwrite the current session.
Any tips?
If the session is too old or whatever, an error is thrown by the 'delete account' function anyways. Then you need to re-auth the user. There is a special function for that too: reauthenticateWithCredential().
Here I have an example to show the difference of the login and re-authenticate functions (copied from a project of mine and cut down a bit because there was some analytics and stuff):
public async reAuthenticate(user: User, { email, password }: IEmailLoginData): Promise<UserCredential> {
const credentials = firebase.auth.EmailAuthProvider.credential(email, password);
return user.reauthenticateWithCredential(credentials)
.catch(e => {
console.error(e);
throw e;
});
}
public async login({ email, password }: IEmailLoginData): Promise<UserCredential> {
return firebase.auth().signInWithEmailAndPassword(email, password)
.catch(e => {
console.error(e);
throw e;
});
}
// PS: IEmailLoginData is a custom interface from me, but it just contains email and password
Also, here is the code for the 'delete account'. It should be pretty self-explanatory - hope it helps a bit:
async delete(): Promise<void> {
const dialogRef = this.dialog.open(YesNoDialogComponent, {
data: {
yes: 'Yes',
no: 'No',
title: 'Are you sure that you want to delete your account?'
}
});
const result = await dialogRef.afterClosed().pipe(take(1)).toPromise();
if (result === IYesNoDialogResult.YES) {
try {
const authUser = await this.auth.nextAuthUser(); // Getting the current firebase user from my custom service
await authUser.delete();
await this.router.navigateByUrl('login');
} catch(e) {
const toast = await this.toast.create({
duration: 3000,
message: 'This is a sensitive operation. Please login again to do this'
});
await toast.present();
await this.router.navigateByUrl('reauth');
});
}
}
For different auth provider it might be slightly different, but in the essence it is still the same. Just for example with google (if you want to use the Ionic Native Google Plus Login Plugin), you need to create the re-authenticate credentials from the plugin result:
public async reAuthenticate(user: User): Promise<UserCredential> {
try {
if (this.platform.is('cordova')) {
try {
const gUser = await this.gPlus.login({
webClientId: environment.googleWebClientId,
offline: true,
scopes: 'profile email'
});
const credential = firebase.auth.GoogleAuthProvider.credential(gUser.idToken);
return await user.reauthenticateWithCredential(credential);
} catch (nativeE) { // If login failed via native method, fallback to redirects
if (nativeE == 12501 || nativeE == 13) { // User cancelled login
return null;
}
console.error(nativeE);
// In constructor:
// this._provider = new firebase.auth.GoogleAuthProvider();
await user.reauthenticateWithRedirect(this._provider);
return await firebase.auth().getRedirectResult();
}
}
else {
return await user.reauthenticateWithPopup(this._provider);
}
} catch (e) {
console.error(e);
throw e;
}
}
I am trying to use page.evaluate in Pyppeteer and capture js script response but I am unable to capture it. In the following code, I am trying to capture the result returned by js script in dimensions variable, but its capturing as None
import asyncio
from pyppeteer import launch
async def hmm():
browser = await launch(headless=False)
page = await browser.newPage()
await page.goto('https://jobs.chegg.com')
dimensions = await page.evaluate("""async () => {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/axe-core/3.1.2/axe.min.js';
document.head.appendChild(script);
var result = new Promise((resolve, reject) => {
axe.run(document, {
runOnly: {
type: "tag",
values: ["wcag2a", "wcag2aa", "best-practice"]
},
"rules": {
"skip-link": { enabled: false }
}
}, function(err, results) {
if (err) throw err;
resolve(results);
});
});
let test = await result.then((res) => {
return res;
}).catch(err => {
console.log(err);
});
console.log(test);
return test;
}
""")
print(dimensions) # None
return dimensions
asyncio.get_event_loop().run_until_complete(hmm())
Note :- Open console in any website and run the js script, then, an object/dictionary is returned.
Please suggest a workaround for this problem.
Not sure what you are trying to accomplish but if you want to capture response from the site, you should listen to response. Here is an example with your site. It will print out every response object and related information.
import asyncio
from pyppeteer import launch
def interception_fun(response):
# Response logic goes here
print("URL:", response.url)
print("Method:", response.request.method)
print("Response headers:", response.headers)
print("Request Headers:", response.request.headers)
print("Response status:", response.status)
return
async def hmm():
browser = await launch(headless=False)
page = await browser.newPage()
await page.goto('https://jobs.chegg.com')
page.on('response', interception_fun)
await browser.close()
return
asyncio.get_event_loop().run_until_complete(hmm())
Update:
As of pyppeteer version 0.2.5. page.on() should be lambda function like this:
page.on('response', lambda res: asyncio.ensure_future(interception_fun(res)))
Getting this error sometimes while using this function: My function works 2/3 times but I'd like to correct it pls. I'm using puppeteer to navigate and check if my proxy is working.
Cannot set property 'innerText' of null
How to fix it please...
Here's my code.
let proxyValidity = waiting("Checking proxy Validity", 800);
try {
await LOG('Trying to validate IP using an API');
await page.goto(ipValidityUrl, { waitUntil: "load", timeout: 30000 });
} catch (err) {
await LOG('Error occured during loading IP validation API');
await page.close();
await closeBrowser(browser);
stopWaiting(proxyValidity, (stdClrs.FgRed + "ERROR"));
return {
errorId: 3,
msg: 'Unknown Proxy Error',
error: err
};
}
await LOG('IP validation URL loaded');
let proxyInfo = await page.evaluate(() => {
let div = document.querySelector('body > pre');
console.log(div);
jsonObject = JSON.parse(div.innerText);
key = Object.keys(jsonObject);
console.log(jsonObject[key]);
return jsonObject[key];
})
await LOG(`Proxy information recorded: ${proxyInfo}`);
await LOG('Checking for validity of IP');
let isValid = defaultData.proxyAllowedCountries.find((element) => {
return (proxyInfo[0] == element)
}) == proxyInfo[0];
The error code:
UnhandledPromiseRejectionWarning: Error: Evaluation failed: TypeError: Cannot read property 'innerText' of null
at __puppeteer_evaluation_script__:4:35
[...]
You could add a waitForSelector before calling the evaluate function
await page.waitForSelector('body > pre');
await page.evaluate(...);
Below I register a user after authenticating through FB/Google. The issue here is in the try block. When I throw an error, for example when displayName already taken or user is already registered, the catch block is triggered but it appears to continue executing code in the try block because after throwing the error I am always getting redirected in the browser to '/' (last line of code in try block).
One solution would be to navigate the user programmatically on the client side but I don't see why this existing code doesn't work as expected.
app.post("/auth/register", requireAuth, async (req, res) => {
try {
if (req.user.registered === true) {
throw new Error("You have already registered.")
}
const existingUser = await User.findOne({
displayName_lower: req.body.displayName
});
if (existingUser) {
throw new Error("Display name already is use! Try another.");
}
await User.findByIdAndUpdate(
{ _id: req.user.id },
{
displayName: req.body.displayName,
displayName_lower: req.body.displayName,
registered: true,
joined: Date.now()
}
);
// Create and save new faves, follows, followers, messageBox doc for every newly reg'd user
await new Faves({
_owner: req.user.id
}).save();
await new Follows({
_owner: req.user.id
}).save();
await new Followers({
_owner: req.user.id
}).save();
await new MessageBox({
_owner: req.user.id
}).save();
res.redirect("/");
} catch (e) {
res.status(400).send({ error: e.message });
}
});
I open a website, then wait for all redirects to be done. Then I capture a captcha image, and send it via nodejs to a user. Then I recive the typed captcha:
const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
await page.goto('http://localhost/p1.php' );
await page.waitForNavigation();
const captcha_image = await page.$eval('#security', e => e.getAttribute('src'));
io.emit('send_captcha_to_client' , {text : captcha_image });
var captcha = await captchaPromise;
After I receive the typed value of the capthca, I put it in the field and click the login button:
await page.$eval('#W_CAPTCHA', (el , _captcha) => el.value = _captcha.W_CAPTCHA , captcha );
await page.click('#login-btn');
Now after clicking the button, an ajax request will be sent to the server. Lets say http://example.com/login.php - if the captcha is right, I will get redirected to my dashboard, but if the ajax call returns lets say {status:er}
And there is <span id="alert"></span> in the page it'll add .Error class to it and put the error text in there. How can I intercept the ajax call and check if the login was successful or not?
I can check the result of the ajax call or wait and check the document for div.Error. But I am not sure how can I do any of them. Here is my failed attempt:
await page.waitForNavigation();
page.waitForSelector('.Error');
const error = await page.$eval('.Error', e => e.value );
console.log(error);
browser.close();
You can wait on both simultaneously and handle whichever occurs first:
await Promise.race([
page.waitForNavigation({ waitUntil: "networkidle0" }),
page.waitForSelector(".Error")
]);
if (await page.$(".Error")) {
// there was an error
} else {
// the page changed
}
The accepted answer isn't waiting for a request but waiting for a selector. That kind of hacky-way wasn't doing it for me.
Waiting a promise resolution coupled with the request response status is the easiest way to achieve it.
await Promise.all( [
page.click( selector ), // ... action
page.waitForResponse( response => response.status() === 200 ), // ... wait for network
] );
Source # https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#pagewaitforresponseurlorpredicate-options
HTTP response status codes
Response
Description
200 OK
The HTTP 200 OK success status response code indicates that the request has succeeded. A 200 response is cacheable by default.
Source # https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200