Marcas y máscaras
Una marca es el nodo del navegador, no un número de orden, y se comprueba de nuevo en el instante del clic. Las máscaras se dibujan sobre los píxeles capturados, con cualquier escala de pantalla y cualquier zoom de página.
Una marca es un nodo, no un número de orden
Un número de orden dice «el tercer botón». Cuando la página inserta un banner o una línea, el tercer botón es otro, y puede ser el botón de pago. El servidor liga cada marca al nodo que el navegador guarda para ese elemento en esa instantánea. Cuando el modelo actúa:
- el servidor busca el nodo que hay detrás de la marca y comprueba que es el
mismo nodo, todavía en la página; un elemento movido o sustituido se rechaza
con
element_stale, una página que ha cambiado desde la observación consnapshot_stale; - pregunta al navegador qué nodo está en el punto que va a pulsar, y rechaza con
element_obscuredcuando no es ni el objetivo ni uno de sus descendientes: un banner o un modal sobre el objetivo se llevaría el clic; - después de mover el puntero y antes de pulsar, vuelve a preguntar, porque un menú que se abre al pasar el puntero o un banner que se desliza desplaza la página en ese momento.
En cada rechazo no se hace clic en nada, y el modelo observa de nuevo.
Medido en Chromium 141 con una página de prueba que desplaza cada objetivo 60 píxeles CSS hacia abajo en el primer movimiento del puntero y pone otro botón en su lugar: antes de la tercera comprobación, 24 clics de 24 no devolvían ningún error y caían en el botón puesto en lugar del objetivo; con ella, se rechazan 24 de 24. Lo que las comprobaciones no detectan está en Límites.
Una máscara se dibuja sobre los píxeles
Las marcas y las máscaras las dibuja el servidor sobre la imagen capturada,
nunca dentro de la página. Una superposición dibujada en la página podría ser
movida, ocultada o leída por los propios scripts de la página; un rectángulo
pintado sobre los píxeles capturados cubre lo que el servidor midió, y el valor
que hay debajo no puede recuperarse de la imagen. Si no se puede dibujar una
máscara, no se publica ninguna imagen (capture: unavailable); el árbol se sigue
sirviendo.
Cada caja está en píxeles CSS, de modo que una máscara se sitúa sobre su campo sea cual sea la escala de la pantalla. Medido en Chromium 141, ventana de 1280 × 800, sobre el campo de contraseña de la página de demostración:
| Escala | La caja del navegador y la del servidor ahora | La caja del servidor antes de la corrección |
|---|---|---|
| 1,5 | 98.7, 154.1, 252.0 × 27.3 | 148.0, 231.2, 378.0 × 41.0 |
| 2 | 98.7, 154.4, 252.0 × 27.5 | 197.4, 308.9, 504.0 × 55.0 |
Con las escalas 1, 1,5 y 2, cada píxel del campo queda ahora bajo su máscara, y la máscara no se extiende más de dos píxeles más allá.
El zoom de página (Ctrl y +) cambia el tamaño de un píxel CSS; el servidor
multiplica el recorte de la imagen por el zoom que informa el navegador. Al 100,
125, 150 y 200 %, en un navegador sin interfaz, cada píxel del campo queda bajo
su máscara; antes de la corrección, desde el 125 % ninguno lo estaba, y
capture seguía indicando ok. Ahora la imagen se retiene, con
capture: unavailable, cuando el navegador no da un zoom utilizable, cuando el
zoom cambia durante la captura o cuando la imagen difiere de la vista en más de
dos píxeles en cualquiera de los dos ejes.
Para repetir las mediciones con un navegador en su PATH, desde el repositorio:
.venv/bin/python -m pytest -q tests/test_scale_integration.py
.venv/bin/python -m pytest -q tests/test_zoom_integration.py
.venv/bin/python -m pytest -q tests/test_zoom_scrolled_integration.py
Las tablas completas y lo que no se midió están en la sección 7 de la guía del operador.