I'm doing some e2e tests with Jest and Puppeteer and I hit a bottleneck.
I want to move step definitions to separate file so that I can reuse them across different tests.
I encounter the following issue:
Here is my setup:
File dummyTest.test.js:
import {loginUser} from '../steps/test';
describe(
'dummy test',
() => {
let page;
beforeAll( async () => {
const context = await browser.createIncognitoBrowserContext();
page = await context.newPage();
await page.setViewport( { width: 1200, height: 960 } );
await page.goto( 'http://localhost:8080' );
}, timeout );
afterAll( async () => {
await page.close();
delay( 1000 );
console.log( 'killing all chromium zombies' );
exec( 'kill -9 $(ps aux | grep \'chromium\' | awk \'{print $2})\'' );
exec( 'kill -9 $(ps aux | grep \'http-server\' | awk \'{print $2})\'' );
}, 10000 );
it( 'should see login page', loginUser, 10000 );
},
10000 );
File test.js:
export const loginUser = async () => {
await page.waitForSelector( 'form' );
await page.click( 'input[name=email]' );
await page.type( 'input[name=email]', 'me#me.com' );
await page.click( 'input[name=password]' );
await page.type( 'input[name=password]', 'test123' );
await page.screenshot( { path: './test-results/PrefilledLogin.png' } );
await page.keyboard.down( 'Enter' );
await page.screenshot( { path: './test-results/LoginSubmit.png' } );
};
What am I doing wrong?
I solved it.
In order for this to work, I had to pass the page object, and the done callback to the function:
it( 'should see login page', ( done ) => loginUser( done, page ), 10000 );
Related
i'm converting my puppeteer code to puppeteer cluster it was working just fine now i'm facing this error "page.solveRecaptchas is not a function" when trying to 2captcha to solve hcaptcha
this is the complete code that i wrote, it just takes data from an excel file and then filled them on the website
number of the pages depends
`
const xlsx = require('xlsx')
const puppeteer = require('puppeteer-extra')
const StealthPlugin = require('puppeteer-extra-plugin-stealth')
const RecaptchaPlugin = require('puppeteer-extra-plugin-recaptcha')
puppeteer.use(StealthPlugin())
puppeteer.use(
RecaptchaPlugin({
provider: {
id: '2captcha',
token: 'xxxxxxxxxxxx'
},
visualFeedback: true
})
)
const {executablePath} = require('puppeteer')
const { Cluster } = require('puppeteer-cluster');
(async () => {
const cluster = await Cluster.launch({
concurrency: Cluster.CONCURRENCY_PAGE,
maxConcurrency: 10,
timeout: 150 * 1000 ,
puppeteerOptions: {
headless: false,
args: ["--no-sandbox", "--disable-setuid-sandbox","--disable-web-security"],
defaultViewport: null,
executablePath: executablePath()
},
});
cluster.on('taskerror', (err, url) => {
console.error((new Date()).toJSON() + ` Error crawling ${url}: ${err.message}`);
});
//get excele data
let fileURL = 'C:/xxxx/xxxx/xxxxx/clients2.xlsx'
let workbook = xlsx.readFile(fileURL)
const sheet_name_list = workbook.SheetNames;
let clientsArr = xlsx.utils.sheet_to_json(workbook.Sheets[sheet_name_list[0]])
console.log(clientsArr);
await cluster.task(async ({ page, data: [email , password,appiontment, firstName , lastName ] }) => {
await page.goto('https://website.com/')
await page.waitForTimeout(1000)
// close popup 1
await page.waitForSelector('#IDBodyPanelapp > div.popup-appCloseIcon');
await page.click('#IDBodyPanelapp > div.popup-appCloseIcon')
//choose region
await page.waitForSelector('#juridiction');
if(region == 'ALGER'){
region = "15#Al#10"
await page.select('#juridiction', region);
}
else{
region = "14#Ora#9"
await page.select('#juridiction', region);
}
// click to get 2nd otp
page.$eval(`#verification_code`, element =>
element.click()
)
// close popup 2
await page.waitForTimeout(1500)
await page.waitForSelector('#IDBodyPanelapp > div.popup-appCloseIcon');
await page.click('#IDBodyPanelapp > div.popup-appCloseIcon')
//solve hcaptcha and submit form
await page.waitForTimeout(2000)
await page.waitForSelector('#category');
if(appiontment == 'Normal'){
appiontment = "Normal"
await page.select('#category', appiontment);
}
else{
appiontment = "Premuim"
await page.select('#category', appiontment);
}
await page.waitForTimeout(15000)
await page.solveRecaptchas()
await Promise.all([
page.waitForNavigation(),
//click submit
page.click(`#em_tr > div.col-sm-6 > input`)
])
await page.screenshot({ path: 'screenshot.png', fullPage: true })
});
clientsArr.map((data)=>{
cluster.execute([data.email, data.password , data.appiontment, data.firstname , data.lastPrenom ]);
})
// await cluster.idle();
// await cluster.close();
})();
`
i have already searched but there are no solutions
need help and thank you
I have a nextjs page which consists of a react video player which plays a YouTube video based on some id passed in the url. The YouTube video is fetched in getServerSideProps based on the id. Then on the client side I am using /api/some-route to take a screenshot of that video player div using Puppeteer. Problem is when in api side I am opening a browser with Puppeteer with that particular URL, getServerSideProps is called and again my api/some-routes is getting called. So It has made a loop and is not finishing. How do I stop this?
My page:
export default function Home() {
useEffect(() => {
if (typeof window === undefined) {
return;
}
const url = window.location.href;
setTimeout(() => {
fetch(`/api/scrapper?url=${url}`)
.then((res) => {
res.json();
})
.then((data) => {
console.log(data);
});
}, 10000);
}, [params.slug[0]);
return (
<>
<Layout>
<Frame id="capture" />
</Layout>
</>
);
}
export const getServerSideProps = async ({ params }) => {
return {
props: { params, serverData },
};
}
/api/scrapper.js
import puppeteer from "puppeteer";
export default async function My(req, res) {
const url = req.query.url;
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(url);
const img = await page.screenshot({ path: "output.png" });
console.log("img", img);
await page.close();
await browser.close();
return res.json("done");
}
I'm getting the error Cannot read property 'createEvent' of null when I use setTimeout in the code to wait for a while before navigating. The timeout is needed for a reason. The test is passing when I remove the timeout but need to make it work with the timeout really.
Here is the code I have.
useEffect(() => {
(async () => {
if (hasInternetConnection) {
...
} else {
setTimeout(() => {
navigation.dispatch(state => {
const routes = state.routes.filter(route => route.name === splashScreen)
routes.push({ name: homeNavigation, params: { screen: offlineDashboardScreen } })
return CommonActions.reset({
...state,
routes,
index: routes.length - 1
})
})
}, 1000)
}
})()
}, [hasInternetConnection, conductor])
it('navigates OfflineDashboardScreen if there is no internet connection', async () => {
useNetInfo.mockReturnValueOnce({
type: 'test', // not 'unknown'
isInternetReachable: false,
details: {},
isConnected: false
})
const component = (
<NavigationContainer>
<AppProviders>
<ThemeProvider theme={mockTheme}>
<AppNavigation/>
</ThemeProvider>
</AppProviders>
</NavigationContainer>
)
const rendered = render(component)
expect(await rendered.findByText(strings.om1)).toBeTruthy()
})
I've added jest.useFakeTimers() to setup files.
Helper files that use other browser commands have to be moved to before hook.
NavigationByTextInSideMenu(page) {
const sideMenu = {}
await browser.waitUntil(async () => {
await this.$$sideBarMenu.map(async (elem) => elem.isDisplayed()).length > 10;
}, { timeout: 10000, timeoutMsg: 'Not all elements were visible' });
await this.$$sideBarMenu.forEach(async (element) => {
sideMenu[await element.getText()] = element;
});
console.log(Object.keys(sideMenu))
await sideMenu[page].click();
} ```
My aim is to generate pdf contact with puppeteer with an html page that I built.
I succesfully generate this pdf in my back. But I have a problem to send data to my front. I tried many things but... One I got an arrayBuffer, once a blob, now a readableStream and I can read with my front none of theses...
Is there a way to easily send pdf and preview it in browser (in modal) ?
Here is my back :
const date = Date.now();
const pathPDF = `contract-${date}.pdf`;
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(
`http://localhost:3000/admin/reservation/${req.params.reservation}/contract`,
{
waitUntil: 'networkidle2',
}
);
const pdf = await page.pdf({
path: pathPDF,
format: 'A4',
printBackground: true,
});
await browser.close();
// res.json(pdf) <-- I tried this first, don't work
// res.contentType('application/pdf');
// res.sendFile(pathPDF); <-- Then this, not working...
// const data = fs.readFileSync(`./${pathPDF}`);
// res.contentType('application/pdf');
// res.send(data); <-- I tryed this too, same...
Here action :
export const createContract = (reservation) => {
return fetch(`${API}/reservation/contract/${reservation}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
})
.then((response) => {
// return response.blob(); <-- Tried this
return response.json();
})
.catch((err) => console.log(err));
};
Here my call in page :
const generateContract = () => {
setLoading(true);
createContract(reservation._id).then((result) => {
if (result.error) {
setLoading(false);
snackbarShowMessage(`${result.error}`);
} else {
setPdf(URL.createObjectURL(result)); <-- Tried this
setPdf(result) <-- This too
setLoading(false);
snackbarShowMessage(`${result.message}`, 'success');
setOpen(true);
}
});
};
Do you have any idea where I doing wrong..?