Necesito acceder a un iframe en dramaturgo que tiene un nombre que se genera automáticamente.
El nombre del iframe siempre tiene el prefijo "__privateStripeFrame" y luego un número generado aleatoriamente
¿Cómo puedo acceder al marco con page.frame({name: }) ?
¡De los documentos parece que no puedo usar una expresión regular!
El frameSelector no necesita ser especificado por el nombre. Pruebe un xpath con contains : esto funciona en la página de muestra de W3:
await page.goto('https://www.w3schools.com/tags/tryit.asp?filename=tryhtml_iframe'); await page.frame("//iframe[contains(@title,'W3s')]"); Si desea un enfoque más general, también tiene page.frames() . Eso devolverá una matriz de los marcos y puede iterar y encontrar el que necesita.
Esto funciona para mí:
let myFrames = page.frames(); console.log("#frames: " + myFrames.length) myFrames.map((f) => console.log(f.name()));(W3S no es el mejor sitio de demostración ya que hay muchos marcos anidados, pero esto genera los marcos de nivel superior que tienen nombres)
La salida:
iframeResult
__tcfapiLocator
__uspapiLocator
__tcfapiLocator
__uspapiLocator
Tuvimos el problema de que varios iframes de Stripe Elements se cargaban de forma asíncrona y muy lenta, por lo que terminamos con esta solución alternativa para volver a intentar iterar todos los marcos y consultar los campos de entrada de la tarjeta para cada uno, hasta que se encontrara o se agotara el tiempo de espera.
No es elegante, pero funcionó para nosotros.
async function findStripeElementsIframeAsync(page: Page, timeout: number) { const startTime = Date.now(); let stripeFrame = null; while (!stripeFrame && Date.now() - startTime < timeout) { const stripeIframes = await page.locator('iframe[name^=__privateStripeFrame]'); const stripeIframeCount = await stripeIframes.count(); for (let i = 0; i < stripeIframeCount; i++) { const stripeIFrameElement = await stripeIframes.nth(i).elementHandle(); if (!stripeIFrameElement) throw 'No Stripe iframe element handle.'; const cf = await stripeIFrameElement.contentFrame(); if (!cf) throw 'No Stripe iframe content frame.'; // Does this iframe have a CVC input? If so, it's our guy. // 1 ms timeout did not work, because the selector requires some time to find the element. try { await cf.waitForSelector('input[name=cvc]', { timeout: 200 }); stripeFrame = cf; console.log('Found Stripe iframe with CVC input'); return stripeFrame; } catch { // Expected for iframes without this input. } } // Give some time for iframes to load before retrying. await new Promise(resolve => setTimeout(resolve, 200)); } return null; }