I'm quite new to JS.
I have this code:
async function downloadOriginalFile(page, scanData, delay = 10000) {
const { url, zipFname, caseId, scanId } = scanData;
await page.goto(url);
if (page.url().includes('/sign_in')) {
console.log('Not logged in');
throw new Error('Login failed');
} else {
console.log(`/${caseId}/${scanId} => Opened Scan Page`);
}
await page.waitForTimeout(delay);
const page4Promise = page.waitForEvent('popup');
const download2Promise = page.waitForEvent('download');
// lines in question:
await page.getByRole('main').getByRole('link').first().click(); // multi-grader
await page.locator('div:nth-child(6) > a').waitForTimeout().click(); // solo grader
const download = await download2Promise;
console.log(`/${scanData.caseId}/${scanData.scanId} => Downloading original file`);
await page.waitForTimeout(delay);
await download.saveAs(path.join(path.dirname(zipFname), caseId, scanId, 'original_file', download.suggestedFilename()));
// wait for the download and delete the temporary file
await download.delete();
}
My problem is that I can only have one of those:
await page.getByRole('main').getByRole('link').first().click(); // multi-grader
// or
await page.locator('div:nth-child(6) > a').waitForTimeout().click(); // solo grader
depending on the page was loaded. I'd like to use somehow try/catch with timeout to test whatever the two works after, say, 3 s. But I'm open to suggestions as well.
UPDATE: Based on @Ermi answer, I was able to better troubleshot my problem.
I found out that
await page.getByRole('main').getByRole('link').first().click(); // multi-grader
will also show up in solo-grader
page, so I reverse the order.
Also, I should originally have used:
await page.locator('div:nth-child(6) > a').click(); // solo-grader`
This is what works if I load solo-grader page, even with page.getByRole('main')...
there.
updated code:
async function downloadOriginalFile(page, scanData, delay = 10000) {
const { url, zipFname, caseId, scanId } = scanData;
await page.goto(url);
if (page.url().includes('/sign_in')) {
console.log('Not logged in');
throw new Error('Login failed');
} else {
console.log(`/${caseId}/${scanId} => Opened Scan Page`);
}
await page.waitForTimeout(delay);
const page4Promise = page.waitForEvent('popup');
const download2Promise = page.waitForEvent('download');
let download;
try {
// Try solo-grader
await page.waitForTimeout(delay).locator('div:nth-child(6) > a').click(); // solo-grader
console.log(`/${caseId}/${scanId} => Clicked on solo-grader link`);
download = await download2Promise;
} catch (error) {
console.log(`Failed to click on solo-grader link: ${error.message}`);
try {
// Try multi-grader
await page.getByRole('main').getByRole('link').first().click(); // multi-grader
console.log(`/${caseId}/${scanId} => Clicked on multi-grader link`);
download = await download2Promise;
} catch (error) {
console.log(`Failed to click on multi-grader link: ${error.message}`);
throw new Error('Failed to download original file');
}
}
console.log(`/${caseId}/${scanId} => Downloading original file`);
await page.waitForTimeout(delay);
await download.saveAs(path.join(path.dirname(zipFname), caseId, scanId, 'original_file', download.suggestedFilename()));
// Wait for the download and delete the temporary file
await download.delete();
}
However, this line:
await page.waitForTimeout(delay).locator('div:nth-child(6) > a').click(); // solo-grader
fails with:
Failed to click on solo grader link: page.waitForTimeout(...).locator is not a function
So basically, I want to try:
await page.locator('div:nth-child(6) > a').click(); // solo-grader`
for 10000 ms or so.
waitForTimeout
is used to wait for a certain amount of time, and locator is used to locate elements on the page. They are separate functions and should not be chained together like that.
You can achieve it using only { timeout }
as the following:
let download;
try {
// Try solo-grader
const soloGraderLink = await page.locator('div:nth-child(6) > a');
await soloGraderLink.click({ timeout: delay / 5 }); // solo-grader with timeout
console.log(`/${caseId}/${scanId} => Clicked on solo-grader link`);
download = await download2Promise;
} catch (error) {
console.log(`Failed to click on solo-grader link: ${error.message}`);
try {
// Try multi-grader
await page.getByRole('main').getByRole('link').first().click(); // multi-grader
console.log(`/${caseId}/${scanId} => Clicked on multi-grader link`);
download = await download2Promise;
} catch (error) {
console.log(`Failed to click on multi-grader link: ${error.message}`);
throw new Error('Failed to download original file');
}
}