Skip to content

Instantly share code, notes, and snippets.

@munro
Last active June 28, 2024 21:57
Show Gist options
  • Save munro/7f81bd1657499866f7c2 to your computer and use it in GitHub Desktop.
Save munro/7f81bd1657499866f7c2 to your computer and use it in GitHub Desktop.
Selenium wait for all images to load, including background images.
from textwrap import dedent
def wait_until_images_loaded(driver, timeout=30):
"""Waits for all images & background images to load."""
driver.set_script_timeout(timeout)
driver.execute_async_script(dedent('''
// Function to extract URL from CSS 'url()' function
function extractCSSURL(text) {
var url_str = text.replace(/.*url\((.*)\).*/, '$1');
// If the URL is enclosed with double quotes
if (url_str[0] === '"') {
return JSON.parse(url_str);
}
// If the URL is enclosed with single quotes
if (url_str[0] === "'") {
return JSON.parse(
url_str
.replace(/'/g, '__DOUBLE__QUOTE__HERE__')
.replace(/"/g, "'")
.replace(/__DOUBLE__QUOTE__HERE__/g, '"')
);
}
// Return the URL as is
return url_str;
}
// Function to create a promise that resolves when the image is loaded
function imageResolved(url) {
return new Promise(function (resolve) {
var img = new Image();
img.onload = function () {
resolve(url);
};
img.src = url;
// If the image is already loaded, resolve the promise immediately
if (img.complete) {
resolve(url);
}
});
}
// The last argument is expected to be a callback function
var callback = arguments[arguments.length - 1];
Promise.all([
// Get all img tags, create a promise for each one
...Array.from(document.querySelectorAll('img[src]'), img => imageResolved(img.src)),
// Get all inline styles with 'url()' and create a promise for each one
...Array.from(document.querySelectorAll('[style*="url("]'), elem => imageResolved(extractCSSURL(elem.style.cssText)))
])
.then(function () {
// After all images are loaded, wait for all fonts to load
return document.fonts.ready;
})
.then(function() {
// After all fonts are loaded, check for images in CSS stylesheets
let cssImagesPromises = [];
for(let i = 0; i < document.styleSheets.length; i++) {
let rules = document.styleSheets[i].cssRules;
for (let j = 0; j < rules.length; j++) {
let style = rules[j].style;
// Check if a background image is found and if it's a URL
if (style && String(style.backgroundImage).startsWith('url(')) {
let url = extractCSSURL(style.backgroundImage);
cssImagesPromises.push(imageResolved(url));
}
}
}
return Promise.all(cssImagesPromises);
})
.then(function () {
// Call the callback function when all promises are resolved
callback(arguments);
});
return undefined;
'''))
@dmitridb
Copy link

dmitridb commented Jun 15, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment