8
8
import com .saucelabs .visual .graphql .type .*;
9
9
import com .saucelabs .visual .model .*;
10
10
import com .saucelabs .visual .model .DiffingMethodSensitivity ;
11
- import com .saucelabs .visual .utils .CapabilityUtils ;
12
- import com .saucelabs .visual .utils .ConsoleColors ;
13
- import com .saucelabs .visual .utils .EnvironmentVariables ;
11
+ import com .saucelabs .visual .utils .*;
14
12
import dev .failsafe .Failsafe ;
15
13
import dev .failsafe .RetryPolicy ;
14
+ import java .awt .image .BufferedImage ;
16
15
import java .lang .reflect .Field ;
17
16
import java .net .URL ;
18
17
import java .time .Duration ;
@@ -565,10 +564,9 @@ private void sauceVisualCheckSauce(String snapshotName, CheckOptions options) {
565
564
input .setCaptureDom (captureDom );
566
565
}
567
566
568
- if (options .getClipElement () != null ) {
569
- input .setClipElement (options .getClipElement ());
570
- } else if (options .getClipSelector () != null ) {
571
- input .setClipElement (this .driver .findElement (By .cssSelector (options .getClipSelector ())));
567
+ WebElement clipElement = getClipElement (options );
568
+ if (clipElement != null ) {
569
+ input .setClipElement (clipElement );
572
570
}
573
571
574
572
FullPageScreenshotConfig fullPageScreenshotConfig =
@@ -604,7 +602,37 @@ private void sauceVisualCheckSauce(String snapshotName, CheckOptions options) {
604
602
}
605
603
606
604
private void sauceVisualCheckLocal (String snapshotName , CheckOptions options ) {
607
- byte [] screenshot = driver .getScreenshotAs (OutputType .BYTES );
605
+ Window window = new Window (this .driver );
606
+ Rectangle viewport = window .getViewport ();
607
+
608
+ byte [] screenshot ;
609
+
610
+ // clip image if required
611
+ WebElement clipElement = getClipElement (options );
612
+ if (clipElement != null ) {
613
+ Rectangle clipRect = clipElement .getRect ();
614
+
615
+ // Scroll to the clipped element
616
+ Rectangle newViewport = window .scrollTo (clipRect .getPoint ());
617
+ screenshot = driver .getScreenshotAs (OutputType .BYTES );
618
+
619
+ // Restore the original scroll
620
+ window .scrollTo (viewport .getPoint ());
621
+
622
+ Optional <Rectangle > cropRect = CartesianHelpers .intersect (clipRect , newViewport );
623
+ if (!cropRect .isPresent ()) {
624
+ throw new VisualApiException ("Clipping would result in an empty image" );
625
+ }
626
+
627
+ BufferedImage image = ImageHelpers .loadImage (screenshot );
628
+ BufferedImage cropped =
629
+ ImageHelpers .cropImage (
630
+ image , CartesianHelpers .relativeTo (newViewport .getPoint (), cropRect .get ()));
631
+ screenshot = ImageHelpers .saveImage (cropped , "png" );
632
+ viewport = cropRect .get ();
633
+ } else {
634
+ screenshot = driver .getScreenshotAs (OutputType .BYTES );
635
+ }
608
636
609
637
// create upload and get urls
610
638
CreateSnapshotUploadMutation mutation =
@@ -617,7 +645,6 @@ private void sauceVisualCheckLocal(String snapshotName, CheckOptions options) {
617
645
this .client .upload (uploadResult .getImageUploadUrl (), screenshot , "image/png" );
618
646
619
647
// add ignore regions
620
- WindowScroll scroll = getWindowScroll ();
621
648
List <RegionIn > ignoreRegions = extractIgnoreList (options );
622
649
623
650
for (WebElement element : options .getIgnoreElements ()) {
@@ -633,8 +660,10 @@ private void sauceVisualCheckLocal(String snapshotName, CheckOptions options) {
633
660
}
634
661
635
662
for (RegionIn region : ignoreRegions ) {
636
- region .setX (region .getX () - scroll .getX ());
637
- region .setY (region .getY () - scroll .getY ());
663
+ Point newPoint =
664
+ CartesianHelpers .relativeTo (viewport .getPoint (), new Point (region .getX (), region .getY ()));
665
+ region .setX (newPoint .x );
666
+ region .setY (newPoint .y );
638
667
}
639
668
640
669
// upload dom if present / enabled
@@ -729,20 +758,14 @@ private DiffingMethodTolerance getDiffingMethodTolerance(CheckOptions checkOptio
729
758
return sensitivity != null ? sensitivity : this .diffingMethodTolerance ;
730
759
}
731
760
732
- private WindowScroll getWindowScroll () {
733
- Object result = driver .executeScript ("return [window.scrollX, window.scrollY]" );
734
- if (!(result instanceof List <?>)) {
735
- return new WindowScroll (0 , 0 );
761
+ private WebElement getClipElement (CheckOptions checkOptions ) {
762
+ if (checkOptions .getClipElement () != null ) {
763
+ return checkOptions .getClipElement ();
764
+ } else if (checkOptions .getClipSelector () != null ) {
765
+ return this .driver .findElement (By .cssSelector (checkOptions .getClipSelector ()));
736
766
}
737
767
738
- List <?> list = (List <?>) result ;
739
- Object rawScrollX = list .get (0 );
740
- Object rawScrollY = list .get (1 );
741
-
742
- int scrollX = rawScrollX instanceof Long ? ((Long ) rawScrollX ).intValue () : 0 ;
743
- int scrollY = rawScrollY instanceof Long ? ((Long ) rawScrollY ).intValue () : 0 ;
744
-
745
- return new WindowScroll (scrollX , scrollY );
768
+ return null ;
746
769
}
747
770
748
771
private VisualRegion getIgnoreRegionFromSelector (IgnoreSelectorIn ignoreSelector ) {
0 commit comments