Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    SmartClientWebDriver Screenshots

    It appears that the SmartClientWebDriver and it's compatriots don't implement/expose the ability to take screenshots?

    https://selenium.googlecode.com/svn/trunk/docs/api/java/org/openqa/selenium/TakesScreenshot.html

    This is on:
    v9.1p_2015-05-06/PowerEdition Deployment (built 2015-05-06)

    #2
    SmartClientWebDriver provides a (pass through) API for taking screenshots in SC 10.0p and newer. However, that API is not present in older versions, such as SC 9.1p. Unfortunately, we can't port it back without bumping the Selenium library we use for WebDriver in 9.1p from 2.39 to a newer version, and we'd rather not do that as it might impact other customers.

    However, with a little bit of Java code using Reflection, you can achieve what you need:

    Code:
    // somewhere in your existing code, you create the SmartClientWebDriver instance
    SmartClientWebDriver smartClientWebDriver = new SmartClientFirefoxDriver();
    
        :
    
    // we can use Reflection to extract the Selenium RemoteWebDriver    
    Field privateDriverField = SmartClientWebDriver.class.getDeclaredField("driver");
    privateDriverField.setAccessible(true);
    RemoteWebDriver remoteWebDriver = (RemoteWebDriver)privateDriverField.get(smartClientWebDriver);
    
    // now you can take the screenshot you need into a temporary file
    File file = ((FirefoxDriver)remoteWebDriver).getScreenshotAs(OutputType.FILE);
    
        :
    Note that you may have to add a few new imports. You should probably have these at a minimum:
    Code:
    import com.isomorphic.webdriver.*;
    
    import org.openqa.selenium.*;
    import org.openqa.selenium.remote.*;
    import org.openqa.selenium.firefox.*;
    
    import java.lang.reflect.Field;
    import java.io.File;
    The same approach should work for Chrome - just replace firefox with chrome wherever it appears, and follow the special instructions Selenium provides for running ChromeDriver - https://code.google.com/p/selenium/wiki/ChromeDriver.

    Comment


      #3
      Thanks, that's very helpful. ;)

      It's also pretty easy to use the RemoteWebDriver Augmenter, which saves having to check what type of SmartClientWebDriver you have at hand. I packaged this up into a little utility that I create in my base WebTest's @BeforeClass, which also provides convenient takeScreenshot() proxy methods.

      Code:
      import java.io.File;
      import java.lang.reflect.Field;
      
      import org.apache.commons.io.FileUtils;
      import org.openqa.selenium.OutputType;
      import org.openqa.selenium.TakesScreenshot;
      import org.openqa.selenium.WebDriver;
      import org.openqa.selenium.remote.Augmenter;
      import org.openqa.selenium.remote.RemoteWebDriver;
      
      import com.isomorphic.webdriver.SmartClientWebDriver;
      
      public class SnapshotUtil {
      
      	private final TakesScreenshot takesScreenshot;
      	
      	public SnapshotUtil(WebDriver webDriver) throws Exception {
      		if (webDriver instanceof TakesScreenshot) {
      			takesScreenshot = (TakesScreenshot)webDriver;
      		}
      		else {
      			WebDriver remoteWebDriver = null;
      			TakesScreenshot shotter = null;
      			
      			// if we have a SmartClientWebDriver, get the internal RemoteWebDriver.
      			if (webDriver instanceof SmartClientWebDriver)  {
      				Field privateDriverField = SmartClientWebDriver.class.getDeclaredField("driver");
      				privateDriverField.setAccessible(true);
      				remoteWebDriver = (RemoteWebDriver)privateDriverField.get(webDriver);
      			}
      			else {
      				// Not a SmartClientWebDriver, but is it a RemoteWebDriver?
      				if (webDriver instanceof RemoteWebDriver) {
      					remoteWebDriver = (RemoteWebDriver)webDriver;
      				}
      			}
      			// we have a RemoteWebDriver, augment it.
      			// if it's screenshot compatible, use it.
      			if (remoteWebDriver != null) {	
      				remoteWebDriver = (new Augmenter().augment(remoteWebDriver));
      				if (remoteWebDriver instanceof TakesScreenshot) {
      					shotter = (TakesScreenshot)remoteWebDriver;
      				}
      			}		
      		
      			takesScreenshot = shotter;
      		}
      	}
      	
      	
      	public File takeScreenShot() throws Exception {
      		if (takesScreenshot == null) {
      			throw new Exception("Driver could not be converted to a TakesScreenshot instance.");
      		}
      		return takesScreenshot.getScreenshotAs(OutputType.FILE);
      	}
      	
      	public void takeScreenShot(String outFile) throws Exception {
      		takeScreenShot(new File(outFile));
      	}
      	
      	public void takeScreenShot(File destFile) throws Exception {
      		File srcFile = takeScreenShot();
      		FileUtils.copyFile(srcFile, destFile);		
      	}
      }
      Last edited by mandrachek; 9 May 2015, 16:32.

      Comment

      Working...
      X