@@ -501,19 +501,19 @@ export default async function processSnapshot(snapshot: Snapshot, ctx: Context):
501501 for ( const [ key , value ] of Object . entries ( options [ ignoreOrSelectDOM ] ) ) {
502502 switch ( key ) {
503503 case 'id' :
504- selectors . push ( ...value . map ( e => '#' + e ) ) ;
504+ selectors . push ( ...value . map ( e => e . startsWith ( '#' ) ? e : '#' + e ) ) ;
505505 break ;
506506 case 'class' :
507- selectors . push ( ...value . map ( e => '.' + e ) ) ;
507+ selectors . push ( ...value . map ( e => e . startsWith ( '.' ) ? e : '.' + e ) ) ;
508508 break ;
509509 case 'xpath' :
510- selectors . push ( ...value . map ( e => 'xpath=' + e ) ) ;
510+ selectors . push ( ...value . map ( e => e . startsWith ( 'xpath=' ) ? e : 'xpath=' + e ) ) ;
511511 break ;
512512 case 'cssSelector' :
513513 selectors . push ( ...value ) ;
514514 break ;
515515 case 'coordinates' :
516- selectors . push ( ...value . map ( e => `coordinates=${ e } ` ) ) ;
516+ selectors . push ( ...value . map ( e => `coordinates=${ e } ` ) ) ;
517517 break ;
518518 }
519519 }
@@ -648,14 +648,7 @@ export default async function processSnapshot(snapshot: Snapshot, ctx: Context):
648648 }
649649
650650 // snapshot options
651- if ( processedOptions . element ) {
652- let l = await page . locator ( processedOptions . element ) . all ( )
653- if ( l . length === 0 ) {
654- throw new Error ( `for snapshot ${ snapshot . name } viewport ${ viewportString } , no element found for selector ${ processedOptions . element } ` ) ;
655- } else if ( l . length > 1 ) {
656- throw new Error ( `for snapshot ${ snapshot . name } viewport ${ viewportString } , multiple elements found for selector ${ processedOptions . element } ` ) ;
657- }
658- } else if ( selectors . length ) {
651+ if ( selectors . length ) {
659652 let height = 0 ;
660653 height = await page . evaluate ( ( ) => {
661654 const DEFAULT_HEIGHT = 16384 ;
@@ -707,52 +700,96 @@ export default async function processSnapshot(snapshot: Snapshot, ctx: Context):
707700 optionWarnings . add ( `for snapshot ${ snapshot . name } viewport ${ viewportString } , coordinates may not be accurate for multiple viewports` ) ;
708701 }
709702
710-
703+
711704 const coordinateElement = {
712705 type : 'coordinates' ,
713706 ...validation . coords
714707 } ;
715708 locators . push ( coordinateElement as any ) ;
716709 continue ;
717- }
718-
719- let l = await page . locator ( selector ) . all ( )
720- if ( l . length === 0 ) {
721- optionWarnings . add ( `for snapshot ${ snapshot . name } viewport ${ viewportString } , no element found for selector ${ selector } ` ) ;
722- continue ;
723- }
724- locators . push ( ...l ) ;
725- }
726710
727- for ( const locator of locators ) {
728- if ( locator && typeof locator === 'object' && locator . hasOwnProperty ( 'type' ) && ( locator as any ) . type === 'coordinates' ) {
729- const coordLocator = locator as any ;
730- const { top, bottom, left, right } = coordLocator ;
731- processedOptions [ ignoreOrSelectBoxes ] [ viewportString ] . push ( {
732- left : left ,
733- top : top ,
734- right : right ,
735- bottom : bottom
736- } ) ;
737- continue ;
738- }
739-
740- let bb = await locator . boundingBox ( ) ;
741- if ( bb ) {
742- // Calculate top and bottom from the bounding box properties
743- const top = bb . y ;
744- const bottom = bb . y + bb . height ;
745-
746- // Only push if top and bottom are within the calculated height
747- if ( top <= height && bottom <= height ) {
748- processedOptions [ ignoreOrSelectBoxes ] [ viewportString ] . push ( {
749- left : bb . x ,
750- top : top ,
751- right : bb . x + bb . width ,
752- bottom : bottom
753- } ) ;
711+ } else {
712+ const isXPath = selector . startsWith ( 'xpath=' ) ;
713+ const selectorValue = isXPath ? selector . substring ( 6 ) : selector ;
714+
715+ const boxes = await page . evaluate ( ( { selectorValue, isXPath } ) => {
716+ try {
717+ // First, determine the page height
718+ const DEFAULT_HEIGHT = 16384 ;
719+ const DEFAULT_WIDTH = 7680 ;
720+ const body = document . body ;
721+ const html = document . documentElement ;
722+
723+ let pageHeight ;
724+ let pageWidth ;
725+
726+ if ( ! body || ! html ) {
727+ pageHeight = DEFAULT_HEIGHT ;
728+ pageWidth = DEFAULT_WIDTH ;
729+ } else {
730+ const measurements = [
731+ body ?. scrollHeight || 0 ,
732+ body ?. offsetHeight || 0 ,
733+ html ?. clientHeight || 0 ,
734+ html ?. scrollHeight || 0 ,
735+ html ?. offsetHeight || 0
736+ ] ;
737+
738+ const allMeasurementsInvalid = measurements . every ( measurement => ! measurement ) ;
739+
740+ if ( allMeasurementsInvalid ) {
741+ pageHeight = DEFAULT_HEIGHT ;
742+ } else {
743+ pageHeight = Math . max ( ...measurements ) ;
744+ }
745+
746+ const measurementsWidth = [
747+ body ?. scrollWidth || 0 ,
748+ body ?. offsetWidth || 0 ,
749+ html ?. clientWidth || 0 ,
750+ html ?. scrollWidth || 0 ,
751+ html ?. offsetWidth || 0
752+ ] ;
753+
754+ const allMeasurementsInvalidWidth = measurementsWidth . every ( measurement => ! measurement ) ;
755+
756+ if ( allMeasurementsInvalidWidth ) {
757+ pageWidth = DEFAULT_WIDTH ;
758+ } else {
759+ pageWidth = Math . max ( ...measurementsWidth ) ;
760+ }
761+ }
762+
763+ let elements = [ ] ;
764+
765+ if ( isXPath ) {
766+ // Use XPath evaluation
767+ const xpathResult = document . evaluate (
768+ selectorValue ,
769+ document ,
770+ null ,
771+ XPathResult . ORDERED_NODE_SNAPSHOT_TYPE ,
772+ null
773+ ) ;
774+
775+ for ( let i = 0 ; i < xpathResult . snapshotLength ; i ++ ) {
776+ elements . push ( xpathResult . snapshotItem ( i ) ) ;
777+ }
778+ } else {
779+ elements = Array . from ( document . querySelectorAll ( selectorValue ) ) ;
780+ }
781+
782+ return elements ;
783+
784+ } catch ( error ) {
785+ }
786+
787+ } , { selectorValue, isXPath } ) ;
788+
789+ if ( boxes && boxes . length >= 1 ) {
790+ processedOptions [ ignoreOrSelectBoxes ] [ viewportString ] . push ( ...boxes ) ;
754791 } else {
755- ctx . log . debug ( `Bounding box for selector skipped due to exceeding height: ${ JSON . stringify ( { top , bottom , height } ) } `) ;
792+ optionWarnings . add ( ` for snapshot ${ snapshot . name } viewport ${ viewportString } , no element found for selector ${ selector } `) ;
756793 }
757794 }
758795 }
0 commit comments