Can't log in through Facebook using Puppeteer - Error: Cookies required - automation

This is my code to login using facebook to a website I'm automating:
const loginButton = await page.waitForXPath(
"//button[contains(#name, 'login')]"
);
const email = await page.waitForSelector("#email");
const pass = await page.waitForSelector("#pass");
await page.evaluate((text) => {
email.value = text;
}, "my email");
await page.evaluate((text) => {
pass.value = text;
}, "my password");
await loginButton.click();
Usually it works well, but once every 4 or 5 times, I get the following error after clicking the loginButton:
"Cookies required. Cookies are not enabled on your browser. Please enable cookies in your browser preferences to continue."
I changed from Chromium to Chrome to see if this would solve the issue, but it didn't work.
I also checked the cookies settings and they are enabled.

The problem was that the inputs were being filled to quickly and facebook was suspecting that I wasn't a real person. I solved it by introducing some delay between the login steps:
const loginButton = await page.waitForXPath(
"//button[contains(#name, 'login')]"
);
const email = await page.waitForSelector("#email");
const pass = await page.waitForSelector("#pass");
await page.waitFor(1000);
await page.evaluate((text) => {
email.value = text;
}, "casas.farach#yahoo.com");
await page.waitFor(1000);
await page.evaluate((text) => {
pass.value = text;
}, "789654123");
await page.waitFor(1000);
await loginButton.click();

Related

E2e testing for Google Login with Puppeteer

I'm new to Puppeteer and trying to write an e2e test for a React app that enables logins using the GoogleLogin component from #react-oauth/google.
The code below works until the Google sign in window opens, but then I don't know how to access elements. I've looked at the element and I know that there's an input of type email, so I'd like to wait for that selector, but page doesn't seem to be the place to access it.
How do I move to the next step with this test?
const chalk = require( 'chalk' );
class LoginAccount {
constructor( page ) {
this.url = "http://localhost:3000"
this.page = page;
}
async login( username, password ) {
try {
const navigationPromise = page.waitForNavigation();
await this.page.goto( this.url );
const selector = '[role="button"]';
await this.page.waitForSelector( selector );
const button_handler = await page.$(selector);
await button_handler.evaluate(b => b.click());
await navigationPromise
const email_field = 'input[type="email"]'
await page.waitForSelector( email_field )
// Times out here
console.log("Got email input")
await this.page.type( email_field, username );
} catch ( err ) {
console.log( chalk.red( 'ERROR => ', err ) );
}
}
}
module.exports = ( page ) => new LoginAccount( page );
I was able to solve this. The browser.waitForTarget method gets me a handle to the new browser window that I need. The modified code below (starting just before the button click) works correctly:
const pageTarget = page.target();
await button_handler.evaluate(b => b.click());
const newTarget = await browser.waitForTarget(target => target.opener() === pageTarget);
const newPage = await newTarget.page();
const email_field = 'input[type="email"]'
await newPage.waitForSelector( email_field )
console.log("Got email input")

TypeScript Playwright: Saving Storagestate via Sign in via API request and then using inside BowserContext does not work - takes me back to login page

I need to decide whether to go with Playwright as an E2E Automation tool or not.
The following piece of code using backend API for sign in is working fine.
But when I use the saved Storagestate file inside the BrowserContext, then it fails to sign me in, hence taking me back to the Login page.
test.describe('User login', async () => {
var browser: any;
test.beforeEach(async () => {
browser = await chromium.launch({
channel: 'chrome',
headless: false
});
});
const requestContext = await request.newContext();
const response = await requestContext.post(`${testConfig.envConfig.apiURL}/login/authorize`, {
form: {
'email': 'user.tech+admin#xxxx.com',
'password': 'xxxxxx'
}
});
const responseJson = await response.json();
console.log(responseJson);
expect(response.ok()).toBeTruthy();
// Save signed-in state.
await requestContext.storageState({ path: './.storagestates/adminUserStorageState.json' });
await requestContext.dispose();
// Using the Storagesate in the BrowserContext
// page should sign in as a admin user.
test.use({ storageState: './.storagestates/adminUserStorageState.json' });
test('Version 1: Cookies stored via Auth. by backend API', async ({ page }) => {
let url = `/brand/f99f06fb1f121234aaf/gallery`;
await page.goto(url, {timeout: 60000});
});
test('Version 2: Cookies stored via Auth. by backend API', async () => {
// page should sign in as a buyer user.
const userContext = await browser.newContext({ storageState: './.storagestates/buyerUserStorageState.json' });
const page = await userContext.newPage();
await page.goto(`/`, {timeout: 60000});
});
});

Testing stripe.redirectToCheckout using selenium

The problem that I am experiencing is that when I click the checkout button on Stripe domain page (the selenium is losing the session ). I am using JWT tokens, so the question is how should I access localStorage to get the token and later on to pass it to the browser ( I am not sure that this will actually work, so if there is some other way please give me a hand ). I got this code before the execution of the test:
const { Before, After } = require('cucumber');
const { Builder } = require('selenium-webdriver');
const firefox = require('selenium-webdriver/firefox');
const config = require('../config');
let driver;
Before(async () => {
driver = await new Builder().forBrowser('firefox');
if (config.headlessBrowser === 'true') {
const screen = {
width: 1920,
height: 1200,
};
driver = driver
.setFirefoxOptions(new firefox.Options().headless().windowSize(screen));
}
driver = driver
.build();
driver.manage().window().maximize();
exports.driver = driver;
});
After(() => {
driver.quit();
});
And the tests for clicking the submit button and expected URL when redirected:
Then('I press stripe checkout button', {timeout: waitTime}, async () => {
await d.driver.findElement(By.className('SubmitButton')).click();
})
Then(/I should be redirected to "(.*)"/, {timeout: waitTime}, async (path) => {
await d.driver.wait(until.urlIs(config.url + path), waitTime);
});
I can see that it is trying to redirect me to the correct success URL, but unfortunately, it logs me out( I assume that is happening because the session is lost ).

TestCafe - How Do I Use Roles with auth0 login

I have an app with an auth0 login. I haven't been able to figure out how to make t.useRole in this scenario.
Fortunately, this is easy to reproduce. auth0 (the application) uses the same process. It fails the exact same way as my app.
Expected Outcome
- User logs in
- User goes to dashboard
- User remains log in
- User goes to dashboard again (second test)
Actual
- User logs in
- User goes to dashboard
- User is no longer authenticated
- User goes to login page
import { Role, Selector, ClientFunction } from 'testcafe';
const getPageUrl = ClientFunction(() => window.location.href.toString());
const exampleRole: Role = Role('https://auth0.com/auth/login', async t => {
const userNameInput = Selector('input').withAttribute('name', 'email');
const passwordInput = Selector('input').withAttribute('name', 'password');
const loginButton = Selector('button').withAttribute('name', 'submit');
await t
.wait(5000)
.click(userNameInput)
.typeText(userNameInput, userName)
.click(passwordInput)
.typeText(passwordInput, password)
.click(loginButton);
})
fixture(`SAMPLE`)
.page('https://manage.auth0.com/dashboard')
.beforeEach(async t => {
await t.useRole(exampleRole)
})
test('My first test', async t => {
await t
.expect(getPageUrl()).contains('dashboard')
});
test('My next test', async t => {
await t
.expect(getPageUrl()).contains('dashboard')
})
Output
SAMPLE
√ My first test
× My next test
1) AssertionError: expected
'https://auth0.auth0.com/login?state=***&client=***&protocol=oauth2&response_type=code&redirect_uri=https%3A%2F%2Fmanage.auth0.com%2Fcallback&scope=openid%20profile%20name%20email%20nickname%20created_at'
to include 'dashboard'
```
I had a similar issue reported here: Testcafe: Is there a way to keep the logged-in session intact between pages?
The workaround was to add a wait after .click(loginButton) in the Role block and set presreveUrl to true.
const exampleRole: Role = Role('https://auth0.com/auth/login', async t => {
const userNameInput = Selector('input').withAttribute('name', 'email');
const passwordInput = Selector('input').withAttribute('name', 'password');
const loginButton = Selector('button').withAttribute('name', 'submit');
await t
.wait(5000)
.click(userNameInput)
.typeText(userNameInput, userName)
.click(passwordInput)
.typeText(passwordInput, password)
.click(loginButton);
.wait(10000);
}, { preserveUrl: true });
**Edited to include preserveUrl: true. Thanks #dapperdan1985.

How to use c8yClient code in the Angular 6 App (typescript file)

For Example:
import { Client } from '#c8y/client';
const baseUrl = 'https://demos.cumulocity.com/';
const tenant = 'demos';
const user = 'user';
const password = 'pw';
(async () => {
const client = await Client.authenticate({
tenant,
user,
password
}), baseUrl);
const { data, paging } = await client.inventory.list();
// data = first page of inventory
const nextPage = await paging.next();
// nextPage.data = second page of inventory
})();
Consider that I have login module in an angular 6 application. How to use this above code and authenticate the user in the login.component.ts file?
Cumulocity has released a demo on Stackblitz how to log in the user. Basically you build a ngForm with username, password and tenant and pass that to the Cumulocity client:
async login() {
const client = new Client(new BasicAuth(
{
user: this.model.user,
password: this.model.password,
tenant: this.model.tenant
}),
`https://${this.model.tenant}.cumulocity.com`
);
try {
let user = await client.user.current();
this.cumulocity.client = client;
} catch (ex) {
this.cumulocity.client = null;
this.error.shown = true;
this.error.msg = ex.message;
}
}
In this case this.model is the data coming from an ngFrom and on button click the login()? function is executed. The this.cumulocity variable contains a service so that you can share the logged in client with other components.
Note: If you run this on a different server (not hosted), then you need to enable CORS in the Cumulocity administration.