This is a solution for both the case where a click brings the user to a page in the same tab and a solution where the click opens the new page in a new browser tab
/* waitForPageLoad
* Get the Page ID before the click and after the click. Until the Page id from the first page
* is no longer equal to the page id of the second page, then we know after a click of a link
* that the new page is not yet loaded. The timeout will try this until id A is not equal to id B, or timeout.
* @param {int} timeout
* @param {string} link
* @param {string} expectedTitle
* @return {bool}
*/
async waitForPageLoad(timeout, link, expectedTitle) {
let oldHTMLId;
let newHTMLId;
let titleWaitingFor;
const oldHtmlElement = await this.driver.wait(until.elementLocated(By.tagName('html')));
await link.click();
await this.driver.wait(async () => {
const actualTitle = await this.driver.getTitle();
titleWaitingFor = actualTitle;
const newHtmlElement = await this.driver.wait(until.elementLocated(By.tagName('html')));
const newHtmlElementId = await newHtmlElement.getId();
const oldHtmlElementId = await oldHtmlElement.getId();
oldHTMLId = oldHtmlElementId;
newHTMLId = newHtmlElementId;
return newHtmlElementId !== oldHtmlElementId
&& actualTitle.includes(expectedTitle);
}, timeout);
return oldHTMLId !== newHTMLId && titleWaitingFor.includes(expectedTitle);
}
//This is what I use if the click opens the Page into another browser tab
/* getWindowHandlesAndExpetedTitle
* This function waits for the new window handle after a click instead of using a sleep.
* Once the expected title of the new window is confirmed, the expected title and url are returned.
* @param expeted title
* @return string Page Title and url { title: returnTitle, url: currentUrl }.
*/
async getWindowHandlesAndExpectedPageInfo(expectedTitle, waitTimeout = 6000) {
try {
await this.waitForWindowHandleCount(2);
let returnHandles;
let returnTitle;
await this.driver.wait(async () => {
const handles = await this.driver.getAllWindowHandles();
returnHandles = handles;
await this.driver.switchTo().window(handles[1]);
const actualTitle = await this.driver.getTitle();
returnTitle = actualTitle;
return actualTitle.includes(expectedTitle);
}, waitTimeout);
const currentUrl = await this.driver.getCurrentUrl();
await this.driver.close();
await this.driver.switchTo().window(returnHandles[0]);
return { title: returnTitle, url: currentUrl };
} catch (err) {
console.log(`Function: getWindowHandlesAndExpectedPageInfo failed ${err}`);
const handles = await this.driver.getAllWindowHandles();
await this.driver.close();
await this.driver.switchTo().window(handles[0]);
return null;
}
}
/* waitForWindowHandleCount
* This function is a wait for the epected number of window handles to be present.
* @param int
*/
async waitForWindowHandleCount(count, waitTimeout = 6000) {
try {
await this.driver.wait(async () => {
const handles = await this.driver.getAllWindowHandles();
return handles.length === count;
}, waitTimeout);
} catch (err) {
console.log(`Function: waitForWindowHandleCount failed ${err} `);
}
}