Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 1a09053

Browse files
committed
Add overloaded shootElement for dynamically finding elements to avoid StaleElementReference
1 parent 555c841 commit 1a09053

File tree

2 files changed

+252
-1
lines changed

2 files changed

+252
-1
lines changed

‎src/main/java/com/assertthat/selenium_shutterbug/core/Shutterbug.java‎

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,19 @@ public static ElementSnapshot shootElement(WebDriver driver,
201201
return shootElement(driver, element, capture, true);
202202
}
203203

204+
/**
205+
* To be used when need to screenshot particular element.
206+
*
207+
* @param driver WebDriver instance
208+
* @param element By element locator
209+
* @return ElementSnapshot instance
210+
*/
211+
public static ElementSnapshot shootElement(WebDriver driver,
212+
By element,
213+
CaptureElement capture) {
214+
return shootElement(driver, element, capture, true);
215+
}
216+
204217
/**
205218
* To be used when need to screenshot particular element.
206219
* Doesn't account for scrollable elements.
@@ -251,6 +264,39 @@ public static ElementSnapshot shootElement(WebDriver driver,
251264
return elementSnapshot;
252265
}
253266

267+
/**
268+
* To be used when need to screenshot particular element.
269+
* Can take screenshots of scrollable elements if Capture type is supplied.
270+
*
271+
* @param driver WebDriver instance
272+
* @param by By element locator
273+
* @param capture Capture type
274+
* @param useDevicePixelRatio whether to account for device pixel ratio
275+
* @return ElementSnapshot instance
276+
*/
277+
public static ElementSnapshot shootElement(WebDriver driver,
278+
By by,
279+
CaptureElement capture,
280+
boolean useDevicePixelRatio) {
281+
Browser browser = new Browser(driver, useDevicePixelRatio);
282+
ElementSnapshot elementSnapshot = new ElementSnapshot(driver, browser.getDevicePixelRatio());
283+
browser.scrollToElement(by);
284+
switch (capture) {
285+
case VERTICAL_SCROLL:
286+
elementSnapshot.setImage(browser.takeFullElementVerticalScreenshotScroll(by));
287+
break;
288+
case HORIZONTAL_SCROLL:
289+
elementSnapshot.setImage(browser.takeFullElementHorizontalScreenshotScroll(by));
290+
break;
291+
case FULL_SCROLL:
292+
elementSnapshot.setImage(browser.takeFullElementScreenshotScroll(by));
293+
break;
294+
default:
295+
elementSnapshot.setImage(browser.takeElementViewportScreenshot(by));
296+
}
297+
return elementSnapshot;
298+
}
299+
254300
/**
255301
* To be used when need to screenshot particular element by vertically centering it within viewport.
256302
*

‎src/main/java/com/assertthat/selenium_shutterbug/utils/web/Browser.java‎

Lines changed: 206 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,59 @@ public BufferedImage takeFullElementScreenshotScroll(WebElement element) {
368368
return combinedImage;
369369
}
370370

371+
public BufferedImage takeFullElementScreenshotScroll(By element) {
372+
Coordinates coordinates = getCoordinates(element);
373+
final int scrollableHeight = coordinates.getScrollHeight();
374+
final int scrollableWidth = coordinates.getScrollWidth();
375+
int elementWidth = coordinates.getWidth();
376+
int elementHeight = coordinates.getHeight();
377+
final int scrollBarMaxWidth = getElementScrollBarWidth(element);
378+
final int scrollBarMaxHeight = getElementScrollBarHeight(element);
379+
380+
381+
if (elementWidth < scrollableWidth || (elementHeight < scrollableHeight && elementWidth - scrollBarMaxHeight < scrollableWidth)) {
382+
elementHeight -= scrollBarMaxHeight;
383+
}
384+
if (elementHeight < scrollableHeight) {
385+
elementWidth -= scrollBarMaxWidth;
386+
}
387+
BufferedImage combinedImage = new BufferedImage(scrollableWidth,
388+
scrollableHeight,
389+
BufferedImage.TYPE_INT_ARGB);
390+
Graphics2D g = combinedImage.createGraphics();
391+
392+
int horizontalIterations =
393+
(int) Math.ceil((double) scrollableWidth / elementWidth);
394+
int verticalIterations = (int) Math.ceil((double) scrollableHeight / elementHeight);
395+
wait(beforeShootCondition, beforeShootTimeout);
396+
outer_loop:
397+
for (int j = 0; j < verticalIterations; j++) {
398+
399+
this.scrollElement(element, 0,
400+
j *
401+
elementHeight);
402+
for (int i = 0; i < horizontalIterations; i++) {
403+
this.scrollElement(element,
404+
i *
405+
elementWidth, j *
406+
elementHeight);
407+
wait(betweenScrollTimeout);
408+
BufferedImage image = takeFullPageElementScreenshot();
409+
image = image.getSubimage(coordinates.getAbsoluteX(),
410+
coordinates.getAbsoluteY(),
411+
elementWidth,
412+
elementHeight);
413+
g.drawImage(image, this.getElementCurrentScrollX(element),
414+
this.getElementCurrentScrollY(element), null);
415+
if (scrollableWidth == image.getWidth(null) && scrollableHeight == image.getHeight(null)) {
416+
break outer_loop;
417+
}
418+
}
419+
}
420+
g.dispose();
421+
return combinedImage;
422+
}
423+
371424
public BufferedImage takeFullElementVerticalScreenshotScroll(WebElement element) {
372425
Coordinates coordinates = getCoordinates(element);
373426

@@ -414,6 +467,52 @@ public BufferedImage takeFullElementVerticalScreenshotScroll(WebElement element)
414467
return combinedImage;
415468
}
416469

470+
public BufferedImage takeFullElementVerticalScreenshotScroll(By element) {
471+
Coordinates coordinates = getCoordinates(element);
472+
473+
final int scrollableHeight = coordinates.getScrollHeight();
474+
final int scrollableWidth = coordinates.getScrollWidth();
475+
int elementWidth = coordinates.getWidth();
476+
int elementHeight = coordinates.getHeight();
477+
final int scrollBarMaxWidth = getElementScrollBarWidth(element);
478+
final int scrollBarMaxHeight = getElementScrollBarHeight(element);
479+
480+
481+
if (elementWidth < scrollableWidth || (elementHeight < scrollableHeight && elementWidth - scrollBarMaxHeight < scrollableWidth)) {
482+
elementHeight -= scrollBarMaxHeight;
483+
}
484+
if (elementHeight < scrollableHeight) {
485+
elementWidth -= scrollBarMaxWidth;
486+
}
487+
BufferedImage combinedImage = new BufferedImage(elementWidth,
488+
scrollableHeight,
489+
BufferedImage.TYPE_INT_ARGB);
490+
Graphics2D g = combinedImage.createGraphics();
491+
492+
int verticalIterations =
493+
(int) Math.ceil(((double) scrollableHeight) / elementHeight);
494+
BufferedImage image;
495+
for (int j = 0; j < verticalIterations; j++) {
496+
this.scrollElement(element, getElementCurrentScrollX(element),
497+
j *
498+
elementHeight);
499+
wait(betweenScrollTimeout);
500+
image = takeFullPageElementScreenshot();
501+
image = image.getSubimage(coordinates.getAbsoluteX(),
502+
coordinates.getAbsoluteY(),
503+
elementWidth,
504+
elementHeight);
505+
506+
g.drawImage(image, 0, getElementCurrentScrollY(element),
507+
null);
508+
if (scrollableHeight == image.getHeight(null)) {
509+
break;
510+
}
511+
}
512+
g.dispose();
513+
return combinedImage;
514+
}
515+
417516
public BufferedImage takeFullElementHorizontalScreenshotScroll(WebElement element) {
418517
Coordinates coordinates = getCoordinates(element);
419518
final int scrollableHeight = coordinates.getScrollHeight();
@@ -459,6 +558,51 @@ public BufferedImage takeFullElementHorizontalScreenshotScroll(WebElement elemen
459558
return combinedImage;
460559
}
461560

561+
public BufferedImage takeFullElementHorizontalScreenshotScroll(By element) {
562+
Coordinates coordinates = getCoordinates(element);
563+
final int scrollableHeight = coordinates.getScrollHeight();
564+
final int scrollableWidth = coordinates.getScrollWidth();
565+
int elementWidth = coordinates.getWidth();
566+
int elementHeight = coordinates.getHeight();
567+
final int scrollBarMaxWidth = getElementScrollBarWidth(element);
568+
final int scrollBarMaxHeight = getElementScrollBarHeight(element);
569+
570+
571+
if (elementWidth < scrollableWidth || (elementHeight < scrollableHeight && elementWidth - scrollBarMaxHeight < scrollableWidth)) {
572+
elementHeight -= scrollBarMaxHeight;
573+
}
574+
if (elementHeight < scrollableHeight) {
575+
elementWidth -= scrollBarMaxWidth;
576+
}
577+
BufferedImage combinedImage = new BufferedImage(scrollableWidth,
578+
elementHeight,
579+
BufferedImage.TYPE_INT_ARGB);
580+
Graphics2D g = combinedImage.createGraphics();
581+
582+
int horizontalIterations =
583+
(int) Math.ceil(((double) scrollableWidth) / elementWidth);
584+
BufferedImage image;
585+
for (int j = 0; j < horizontalIterations; j++) {
586+
this.scrollElement(element,
587+
j *
588+
elementWidth, getElementCurrentScrollY(element));
589+
wait(betweenScrollTimeout);
590+
image = takeFullPageElementScreenshot();
591+
image = image.getSubimage(coordinates.getAbsoluteX(),
592+
coordinates.getAbsoluteY(),
593+
elementWidth,
594+
elementHeight);
595+
596+
g.drawImage(image, getElementCurrentScrollX(element), 0,
597+
null);
598+
if (scrollableWidth == image.getWidth(null)) {
599+
break;
600+
}
601+
}
602+
g.dispose();
603+
return combinedImage;
604+
}
605+
462606
public BufferedImage takeElementViewportScreenshot(WebElement element) {
463607
Coordinates coordinates = getCoordinates(element);
464608
final int scrollableHeight = coordinates.getScrollHeight();
@@ -490,9 +634,39 @@ public BufferedImage takeElementViewportScreenshot(WebElement element) {
490634
return combinedImage;
491635
}
492636

637+
public BufferedImage takeElementViewportScreenshot(By element) {
638+
Coordinates coordinates = getCoordinates(element);
639+
final int scrollableHeight = coordinates.getScrollHeight();
640+
final int scrollableWidth = coordinates.getScrollWidth();
641+
int elementWidth = coordinates.getWidth();
642+
int elementHeight = coordinates.getHeight();
643+
final int scrollBarMaxWidth = getElementScrollBarWidth(element);
644+
final int scrollBarMaxHeight = getElementScrollBarHeight(element);
645+
646+
if (elementWidth < scrollableWidth || (elementHeight < scrollableHeight && elementWidth - scrollBarMaxHeight < scrollableWidth)) {
647+
elementHeight -= scrollBarMaxHeight;
648+
}
649+
if (elementHeight < scrollableHeight) {
650+
elementWidth -= scrollBarMaxWidth;
651+
}
652+
BufferedImage combinedImage = new BufferedImage(elementWidth,
653+
elementHeight,
654+
BufferedImage.TYPE_INT_ARGB);
655+
Graphics2D g = combinedImage.createGraphics();
656+
wait(betweenScrollTimeout);
657+
BufferedImage image = takeFullPageElementScreenshot();
658+
image = image.getSubimage(coordinates.getAbsoluteX(),
659+
coordinates.getAbsoluteY(),
660+
elementWidth,
661+
elementHeight);
662+
g.drawImage(image, 0, 0,
663+
null);
664+
g.dispose();
665+
return combinedImage;
666+
}
493667

494-
public BufferedImage takeFrameViewportScreenshot(Coordinates coordinates) {
495668

669+
public BufferedImage takeFrameViewportScreenshot(Coordinates coordinates) {
496670
final int scrollableHeight = coordinates.getScrollHeight();
497671
final int scrollableWidth = coordinates.getScrollWidth();
498672
int elementWidth = coordinates.getWidth();
@@ -591,6 +765,14 @@ public int getElementScrollBarHeight(WebElement element) {
591765
return (int) (Double.parseDouble(executeJsScript(Browser.ELEMENT_SCROLL_BAR_HEIGHT, element).toString()) * devicePixelRatio);
592766
}
593767

768+
public int getElementScrollBarWidth(By by) {
769+
return (int) (Double.parseDouble(executeJsScript(Browser.ELEMENT_SCROLL_BAR_WIDTH, driver.findElement(by)).toString()) * devicePixelRatio);
770+
}
771+
772+
public int getElementScrollBarHeight(By by) {
773+
return (int) (Double.parseDouble(executeJsScript(Browser.ELEMENT_SCROLL_BAR_HEIGHT, driver.findElement(by)).toString()) * devicePixelRatio);
774+
}
775+
594776
public int getCurrentScrollY() {
595777
return (int) (Double.parseDouble(executeJsScript(Browser.CURRENT_SCROLL_Y_JS).toString()) * devicePixelRatio);
596778
}
@@ -603,6 +785,14 @@ public int getElementCurrentScrollY(WebElement element) {
603785
return (int) (Double.parseDouble(executeJsScript(Browser.ELEMENT_CURRENT_SCROLL_Y_JS, element).toString()) * devicePixelRatio);
604786
}
605787

788+
public int getElementCurrentScrollX(By by){
789+
return (int) (Double.parseDouble(executeJsScript(Browser.ELEMENT_CURRENT_SCROLL_X_JS, driver.findElement(by)).toString()) * devicePixelRatio);
790+
}
791+
792+
public int getElementCurrentScrollY(By by) {
793+
return (int) (Double.parseDouble(executeJsScript(Browser.ELEMENT_CURRENT_SCROLL_Y_JS, driver.findElement(by)).toString()) * devicePixelRatio);
794+
}
795+
606796
public int getDocWidth() {
607797
if (docWidth == -1)
608798
docWidth =
@@ -640,10 +830,19 @@ public Coordinates getCoordinates(WebElement element) {
640830
devicePixelRatio);
641831
}
642832

833+
public Coordinates getCoordinates(By by) {
834+
return getCoordinates(driver.findElement(by));
835+
}
836+
643837
public void scrollToElement(WebElement element) {
644838
executeJsScript(SCROLL_INTO_VIEW_JS, element);
645839
}
646840

841+
public void scrollToElement(By by) {
842+
driver.findElement(by);
843+
executeJsScript(SCROLL_INTO_VIEW_JS, by);
844+
}
845+
647846
public void scrollToElementVerticalCentered(WebElement element) {
648847
executeJsScript(SCROLL_INTO_VIEW_VERTICAL_CENTERED_JS, element);
649848
}
@@ -662,6 +861,12 @@ public void scrollElement(WebElement element, int x, int y) {
662861
y / devicePixelRatio);
663862
}
664863

864+
865+
public void scrollElement(By by, int x, int y) {
866+
executeJsScript(SCROLL_ELEMENT, driver.findElement(by), x / devicePixelRatio,
867+
y / devicePixelRatio);
868+
}
869+
665870
public Object executeJsScript(String filePath, Object... arg) {
666871
String script = FileUtil.getJsScript(filePath);
667872
JavascriptExecutor js = (JavascriptExecutor) driver;

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /