Can anyone tell me how to store copied data into String in selenium?
example:
driver.findElement(By.xpath("//*[#id="x")).sendKeys(Keys.CONTROL, "a"));
driver.findElement(By.xpath("//*[#id="xy")).sendKeys(Keys.CONTROL, "c"));
driver.findElement(By.xpath("//*[#id="xy")).sendKeys(Keys.CONTROL, "v"));
I need put the copied data into String
Something like this
String text = driver.findElement(By.xpath("//*[#id="xy")).sendKeys(Keys.CONTROL, "v"));
It seems you want to send ctrl + c keys, which will copy some data in clipboard.. want to store that data in String variable..right?
You have to use Clipboard class to do so..See implementation below...
package resources;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.Test;
public class One {
#Test
public void getClipboardContents() {
String result = "";
System.setProperty("webdriver.chrome.driver", "C://WebDrivers/chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("http://www.google.com");
String copy = Keys.chord(Keys.CONTROL,Keys.chord("c"));
driver.findElement(By.linkText("Images")).sendKeys(copy);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
Transferable contents = clipboard.getContents(null);
boolean hasTransferableText = (contents != null)
&& contents.isDataFlavorSupported(DataFlavor.stringFlavor);
if (hasTransferableText) {
try {
result = (String) contents.getTransferData(DataFlavor.stringFlavor);
} catch (UnsupportedFlavorException | IOException ex) {
System.out.println(ex);
ex.printStackTrace();
}
}
System.out.println(result);
}
}
#Starlord ..modify locators as per your need.
#Gaurav Thanks for the code.. I have modified some part of the code.. now I am getting what i want exactly
public void getClipboardContents()
throws UnsupportedFlavorException, IOException {
String result = "google.com";
System.setProperty("webdriver.chrome.driver", "E:\\New folder\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("https://www.google.co.in/");
String copy = Keys.chord(Keys.CONTROL,Keys.chord("c"));
driver.findElement(By.xpath("//*[#id=\"lst-ib\"]")).sendKeys("google.com");
driver.findElement(By.xpath("//*[#id=\"lst-ib\"]")).sendKeys(Keys.CONTROL+"a");
driver.findElement(By.xpath("//*[#id=\"lst-ib\"]")).sendKeys(copy);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
Transferable contents = clipboard.getContents(null);
String x = (String) contents.getTransferData(DataFlavor.stringFlavor);
System.out.println(x);
int a= result.length();
int b = x.length();
System.out.println(a);
System.out.println(b);
if(a<=b)
{
System.out.println("Matched Character length")
}else
{
System.out.println("Issue In Character length");
}
}
}
Related
I'm trying to find a file based on the first 8 numbers i pull from an excel sheet for each iteration. Whenever I use the code below I get the error message "Local variable CaseID defined in an enclosing scope must be final or effectively final". I'm still new so i'm not sure how to fix this even though it sounds like a simple fix. The issue is happening at the caseID variable towards the bottom of the code.
package Chrome;
//CHROME
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
public class ValidateInput {
public static void main(String[] args) throws Throwable {
// TODO Auto-generated method stub
// String filePath=System.getProperty("user.dir")+"\\UP.xlsx";
//File src = new File(filePath);
//System.out.println(filePath);
File src = new File("C:\\Users\\Z246379\\Documents\\TestDataFolder\\ValidateInput.xlsx");
FileInputStream fis = new FileInputStream(src);
XSSFWorkbook wb = new XSSFWorkbook(fis);
XSSFSheet Sheet1 = wb.getSheetAt(0);
int i1 = 2;
//Username
String data0 = Sheet1.getRow(2).getCell(0).getStringCellValue();
//Password
String data01 = Sheet1.getRow(2).getCell(1).getStringCellValue();
//Case ID
String caseID = Sheet1.getRow(i1).getCell(2).getStringCellValue();
// Description
String Desc = Sheet1.getRow(2).getCell(3).getStringCellValue();
//Internal Claim File
String ICF = Sheet1.getRow(1).getCell(4).getStringCellValue();
String CRPT = Sheet1.getRow(1).getCell(5).getStringCellValue();
// final String caseID1 = caseID1;
//Chrome driver code
System.out.println("Called openBrowser");
String exePath = System.getProperty("user.dir")+"\\chromedriver.exe";
System.setProperty("webdriver.chrome.driver", exePath);
ChromeOptions options = new ChromeOptions();
options.setExperimentalOption("useAutomationExtension", false);
options.addArguments("start-maximized");
options.addArguments("--no-sandbox");
options.addArguments("--disable-extensions-except");
options.addArguments("disable-extensions");
//options.setExperimentalOption("useAutomationExtension", false);
WebDriver driver = new ChromeDriver(options);
driver.get("https://client.abc.com");
//Logging in
driver.findElement(By.xpath("//input[#id='userid']")).sendKeys(data0);
driver.findElement(By.xpath("//body[#class='no-nav']/div[#id='wrapper']/header[#class='header']/div[#class='container']/div[#class='menu']/div[#class='drop']/div[#class='login-form']/form[#method='POST']/div[2]/input[1]")).sendKeys(data01);
driver.findElement(By.xpath("//input[#value='Sign In']")).click();
Thread.sleep(2000);
//Navigate to Validate Input
driver.findElement(By.xpath("//span[#class='wpsNavLevel2'][contains(text(),'EZ-Test')]")).click();
Thread.sleep(3000);
driver.get("https://ezt.abc.com/Test/inputFiles/selectValidateInput/selectValidateInput.xhtml");
while (caseID != null)
{
caseID = Sheet1.getRow(i1).getCell(2).getStringCellValue();
//Input Validate Input stuff
driver.findElement(By.xpath("//input[#id='mainForm:caseId']")).sendKeys(caseID);
driver.findElement(By.xpath("//input[#id='mainForm:testBedDesc']")).sendKeys(Desc);
driver.findElement(By.xpath("//select[#id='mainForm:customRptOptions']")).sendKeys(ICF);
driver.findElement(By.xpath("//span[#id='mainForm:customReportLabel']")).click();
File dir = new File("C:\\Users\\Z333379\\Documents\\Test beds");
FilenameFilter filter = new FilenameFilter() {
public boolean accept (File dir, String name) {
return name.startsWith(caseID); //this is where i get the error. its not letting me make case ID a variable. but i really need the starts with stuff
}
};
String[] children = dir.list(filter);
if (children == null) {
System.out.println("Either dir does not exist or is not a directory");
} else {
for (int i=0; i< children.length; i++) {
String filename = children[i];
System.out.println(filename);
driver.findElement(By.xpath("//input[#id='mainForm:comprehensive']")).sendKeys("C:\\Users\\Z246379\\Documents\\Test beds\\" + filename);
}
}
driver.findElement(By.xpath("//button[#id='mainForm:reset']")).click();
i1=i1+1;
}
}
}
Here:
FilenameFilter filter = new FilenameFilter() {
public boolean accept (File dir, String name) {
return name.startsWith(caseID);
}
};
You cannot use a mutable variable in the definition of an inner local class. That's why you receive the error compiler.
Create a temporary variable and assign the value of caseID there, use this variable in your inner local class:
final String localCaseID = caseID;
FilenameFilter filter = new FilenameFilter() {
public boolean accept (File dir, String name) {
return name.startsWith(localCaseID);
}
};
You can use inner class instead of anonymous one. Define it like:
private static class CaseIDFilenameFilter implements FilenameFilter {
private final String caseID;
private CaseIDFilenameFilter(String caseID) {
this.caseID = caseID;
}
#Override
public boolean accept(File dir, String name) {
return name.startsWith(caseID);
}
}
And then use it in your code like:
FilenameFilter filter = new CaseIDFilenameFilter(str);
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 5 years ago.
I am new to Keyword Driven approach for selenium. I am getting NullPointerException while running below ExecuteTest.java
Folder Structure
Folder structure
Object.txt
Object.txt
TestCase.xlsx
TestCase.xlsx
Error Screenshot
Screenshot1
Screenshot2
Adding Debug screenshots
screenshot1
screenshot2
screenshot3
ReadGuru99Excel.java
import org.apache.poi.ss.usermodel.Sheet;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
public class ReadGuru99ExcelFile {
public Sheet readExcel (String filePath,String fileName, String sheetName)throws IOException{
File file = new File(filePath+"\\"+fileName);
FileInputStream inputStream = new FileInputStream(file);
Workbook guru99Workbook = null;
String fileExtensionName = fileName.substring(fileName.indexOf("."));
if(fileExtensionName.equals(".xlsx")){
guru99Workbook = new XSSFWorkbook(inputStream);
} else if(fileExtensionName.equals(".xls")) {
guru99Workbook = new HSSFWorkbook(inputStream);
}
Sheet guru99Sheet =guru99Workbook.getSheet(sheetName);
return guru99Sheet;
}
}
ReadObject.Java
package operation;
import java.util.Properties;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.File;
public class ReadObject {
Properties p = new Properties();
public Properties getObjectRepository()throws IOException{
InputStream stream = new FileInputStream(new File (System.getProperty("user.dir")+"\\src\\objects\\object.txt"));
p.load(stream);
return p;
}
}
UIOperation.java
package operation;
import org.openqa.selenium.WebDriver;
import java.util.Properties;
import org.openqa.selenium.By;
public class UIOperation {
WebDriver driver ;
public UIOperation(WebDriver driver){
this.driver = driver;
}
public void perform(Properties p, String operation, String objectName, String objectType, String value) throws Exception{
System.out.println("");
switch(operation.toUpperCase()){
case "CLICK":
driver.findElement(this.getObject(p, objectName, objectType)).click();
break;
case "SETTEXT":
driver.findElement(this.getObject(p, objectName, objectType)).sendKeys(value);
break;
case "GOTOURL":
driver.get(p.getProperty(value));
break;
case "GETTEXT":
driver.findElement(this.getObject(p, objectName, objectType)).getText();
break;
default:
break;
}
}
private By getObject(Properties p, String objectName, String objectType) throws Exception{
if(objectType.equalsIgnoreCase("XPATH")){
return By.xpath(p.getProperty(objectName));
}else if(objectType.equalsIgnoreCase("CLASSNAME")){
return By.className(p.getProperty(objectName));
}else if(objectType.equalsIgnoreCase("NAME")){
return By.name(p.getProperty(objectName));
}else if(objectType.equalsIgnoreCase("CSS")){
return By.cssSelector(p.getProperty(objectName));
}else if(objectType.equalsIgnoreCase("LINK")){
return By.linkText(p.getProperty(objectName));
}else if(objectType.equalsIgnoreCase("PARTIALLINK")){
return By.partialLinkText(p.getProperty(objectName));
}else{
throw new Exception("Wrong object type");
}
}
}
ExecuteTest.java
package testcases;
import java.util.Properties;
import operation.ReadObject;
import org.testng.annotations.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.MarionetteDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import operation.UIOperation;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Row;
import excelExportAndFileIO.ReadGuru99ExcelFile;
public class ExecuteTest {
#Test
public void testLogin()throws Exception{
/**
* System.setProperty("webdriver.gecko.driver", "E:\\Selenium-2017\\geckodriver-v0.18.0-win64\\geckodriver.exe");
* //Now you can Initialize marionette driver to launch firefox
* DesiredCapabilities capabilities = DesiredCapabilities.firefox();
* capabilities.setCapability("marionette", true);
* WebDriver driver = new RemoteWebdriver(capabilities);
*
* WebDriver webdriver = new FirefoxDriver();
**/
WebDriver driver;
System.setProperty("webdriver.chrome.driver","E:\\Selenium-2017\\chromedriver_win32\\chromedriver.exe");
driver = new ChromeDriver();
ReadGuru99ExcelFile file = new ReadGuru99ExcelFile();
ReadObject object = new ReadObject();
Properties allObjects = object.getObjectRepository();
UIOperation operation = new UIOperation(driver);
Sheet guru99Sheet = file.readExcel(System.getProperty("user.dir")+"\\test-output","TestCase.xlsx","KeywordFramework");
int rowCount =guru99Sheet.getLastRowNum()-guru99Sheet.getFirstRowNum();
System.out.println("first step clear");
for(int i = 0;i<rowCount+1; i++){
Row row =guru99Sheet.getRow(i);
System.out.println("2nd clear");
if(row.getCell(0).toString().length()==0){
System.out.println("4nd clear");
System.out.println(row.getCell(1).toString()+"-----"+row.getCell(2).toString()+"----"+row.getCell(3).toString()+"---"+row.getCell(4).toString());
System.out.println("3rd clear");
operation.perform(allObjects, row.getCell(1).toString(), row.getCell(2).toString(), row.getCell(3).toString(), row.getCell(4).toString());
} else
System.out.println("New Testcase->" + row.getCell(0).toString()+"Started");
System.out.println("testerassumption");
}
}
}
First of all, please see this wonderful post about NullPointerException and how to fix it.
In your case, the stacktrace points the NullPointerException to be occuring at line 49 of the code in ExecuteTest.java, which points to this line of code
operation.perform(allObjects, row.getCell(1).toString(), row.getCell(2).toString(), row.getCell(3).toString(), row.getCell(4).toString());
The issue here is that when you're trying to convert the contents of the cell in the getCell() method to a String, if there is nothing in the cell, then there would always be a NullPointerException.
You can either place a != null check before every cell or add a " " for every toString() method, like
operation.perform(allObjects, (row.getCell(1)+"").toString(), (row.getCell(2)+"").toString(), (row.getCell(3)+"").toString(), (row.getCell(4)+"").toString());
I'm trying to use following code :-
driver.findElement(By.xpath(".//*[#id='attach0']")).sendKeys("first path"+"\n"+"second path""+"\n"third path");
I didn't get result.
you can use AutoIT or JAVA code. Below i have used both for your reference. Try anyone of them
import java.io.IOException;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class AutoITforUpload {
private static WebDriver driver;
private static WebDriverWait waitForElement;
#FindBy(css = "span.btn.btn-success.fileinput-button")
private WebElement Add_files_btn;
#BeforeClass
public static void setUp() {
DesiredCapabilities desicap = new DesiredCapabilities();
System.setProperty("webdriver.chrome.driver", "D:/WorkSpace/Driver/chromedriver.exe");
desicap = DesiredCapabilities.chrome();
driver = new ChromeDriver(desicap);
driver.manage().window().maximize();
driver.get("https://blueimp.github.io/jQuery-File-Upload/");
waitForElement = new WebDriverWait(driver, 30);
}
#Test
public void AutoitUpload() {
// String filepath =
// "D:/Mine/GitHub/BasicProgramLearn/AutoItScript/unnamed.png";
WebElement btn = driver.findElement(By.cssSelector("span.btn.btn-success.fileinput-button"));
String file_dir = System.getProperty("user.dir");
String cmd = file_dir + "\\AutoItScript\\unnamed.png";
System.out.println("File directory is " + file_dir);
try {
// Using ordinary
Thread.sleep(3000);
for(int i=0;i<3;i++) //multiple times upload ;
driver.findElement(By.xpath("//*[#id='fileupload']/div/div[1]/span[1]/input")).sendKeys(cmd);
//use any String Array for multiple files
waitForElement(btn);
btn.click();
Thread.sleep(3000);
System.out.println(file_dir + "/AutoItScript/FileUploadCode.exe");
Runtime.getRuntime().exec(file_dir + "\\AutoItScript\\ChromeFileUpload.exe" + " " + cmd);
} catch (InterruptedException | IOException e) {
e.printStackTrace();
}
}
#AfterClass
public static void TearDown() {
try {
Thread.sleep(5000);
driver.quit();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void waitForElement(WebElement vElement) {
waitForElement.until(ExpectedConditions.visibilityOf(vElement));
}
}
The code in AutoIt is
#include<IE.au3>
If $CmdLine[0] < 2 Then
$window_name="Open"
WinWait($window_name)
ControlFocus($window_name,"","Edit1")
ControlSetText($window_name,"","Edit1",$CmdLine[1])
ControlClick($window_name,"","Button1")
EndIf
Hope this gives you an idea
I have the following three classes :
I tried making the routine of 1 & 2 and used tjava to call the main class and the method from 1 & 2 but I am unable to fetch those methods.
1)
package page_scraper;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebClientOptions;
import com.gargoylesoftware.htmlunit.html.FrameWindow;
import com.gargoylesoftware.htmlunit.html.HtmlButtonInput;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlOption;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlSelect;
import com.gargoylesoftware.htmlunit.html.HtmlTextInput;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintStream;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import page_scraper.UnitArray;
public class PageScraper {
public void Scrape() throws IOException {
try {
UnitArray object = new UnitArray();
ArrayList<String> unitList = object.getUnitArray();
WebClient webClient = new WebClient();
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
HtmlPage page = (HtmlPage)webClient.getPage("http://www.bmreports.com/servlet/com.logica.neta.bwp_PanBMUData");
List frames = page.getFrames();
HtmlPage page1 = (HtmlPage)((FrameWindow)frames.get(0)).getEnclosedPage();
HtmlTextInput settlementDay = (HtmlTextInput)page1.getHtmlElementById("param5");
HtmlSelect period = (HtmlSelect)page1.getHtmlElementById("param6");
HtmlOption periodOption = period.getOption(1);
HtmlTextInput unitId = (HtmlTextInput)page1.getHtmlElementById("param1");
HtmlButtonInput button = (HtmlButtonInput)page1.getHtmlElementById("go_button");
String outputLocation = String.valueOf(System.getProperty("user.home")) + "/Documents/output.csv";
FileWriter fileWriter = new FileWriter(outputLocation);
String errorLocation = String.valueOf(System.getProperty("user.home")) + "/Documents/error.csv";
FileWriter errorWriter = new FileWriter(errorLocation);
int i = 0;
while (i < unitList.size()) {
int x = 0;
while (x < 365) {
String errorData;
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Calendar cal = Calendar.getInstance();
cal.add(5, - x);
String dateValue = dateFormat.format(cal.getTime());
System.out.println(dateValue);
settlementDay.setValueAttribute(dateValue);
period.setSelectedAttribute(periodOption, true);
unitId.setValueAttribute(unitList.get(i));
System.out.println(unitList.get(i));
try {
button.click();
HtmlPage page2 = (HtmlPage)((FrameWindow)frames.get(1)).getEnclosedPage();
String pageSource = page2.asXml();
int firstIndex = pageSource.indexOf("csv=") + 38;
int secondIndex = pageSource.indexOf("n\"") + 1;
String csvData = pageSource.substring(firstIndex, secondIndex);
fileWriter.append(csvData);
}
catch (ClassCastException e) {
errorData = String.valueOf(dateValue) + " " + unitList.get(i) + System.getProperty("line.separator");
System.out.println(errorData);
errorWriter.append(errorData);
continue;
}
catch (StringIndexOutOfBoundsException e) {
errorData = String.valueOf(dateValue) + " " + unitList.get(i) + System.getProperty("line.separator");
System.out.println(errorData);
errorWriter.append(errorData);
continue;
}
++x;
}
++i;
}
webClient.close();
fileWriter.close();
errorWriter.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
2)
package page_scraper;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
public class UnitArray {
public ArrayList<String> getUnitArray() {
String csvList = "abc,xyz";
ArrayList<String> list = new ArrayList<String>(Arrays.asList(csvList.split(",")));
return list;
}
}
3)
package page_scraper;
import page_scraper.PageScraper;
public class main {
public static void main(String[] args) throws Exception {
PageScraper test = new PageScraper();
test.Scrape();
}
}
I made the routines for the above code(1) & 2)) in Talend and then used tjava to call the method but unable to do so..I also tried using tjava for all and did a onSubjob ok on each of the tjava.
How can I call these classes in talend and call the method ?
Firstly, routines classes in Talend need to be in routines package
package routines;
public class PageScraper {
public void Scrape() {
System.out.println("PageScraper.Scrape");
}
}
Secondly, to use it in Job you need to drag'n'drop routine to opened job area.
Then you can use your class in that way
You can easily make a jar file that contains the three classes then load the jar using tLibraryLoad or include the jar in your routine if you want to get more reusability.
As suggested in the other answers, you need to define classes under routines package.
in case you are using Takend 7.3 & above, Right click on your routine and add it as Dependent package
Get routines as a jar and in case using in bigData jobs, you may need to use tLibraryLoad to package it together with other dependencies..
I am wanting to take a screenshot of a page using HtmlUnitDriver I came across this Link where this guy has made a custom HTML unit driver to take the screenshot.
But unfortunately, while implementing that I am getting an exception.
"Exception in thread "main" java.lang.ClassCastException: [B cannot be cast to java.io.File
at Test.main(Test.java:39)"
My code is as follows-
import java.io.File;
import java.io.IOException;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.WebDriver;
import com.gargoylesoftware.htmlunit.BrowserVersion;
public class Test extends ScreenCaptureHtmlUnitDriver {
public static void main(String[] args) throws InterruptedException, IOException {
WebDriver driver = new ScreenCaptureHtmlUnitDriver(BrowserVersion.FIREFOX_38);
driver.get("https://www.google.com/?gws_rd=ssl");
try{
File scrFile = ((ScreenCaptureHtmlUnitDriver) driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File("D:\\TEMP.PNG"));
}catch (Exception e) {
e.printStackTrace();
}
}
}
HtmlUnit driver which I am using(the one which is in the link) is this-
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.openqa.selenium.Capabilities;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
import org.openqa.selenium.internal.Base64Encoder;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.WebWindow;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
public class ScreenCaptureHtmlUnitDriver extends HtmlUnitDriver implements TakesScreenshot {
private static Map<String, byte[]> imagesCache = Collections.synchronizedMap(new HashMap<String, byte[]>());
private static Map<String, String> cssjsCache = Collections.synchronizedMap(new HashMap<String, String>());
// http://stackoverflow.com/questions/4652777/java-regex-to-get-the-urls-from-css
private final static Pattern cssUrlPattern = Pattern.compile("background(-image)?[\\s]*:[^url]*url[\\s]*\\([\\s]*([^\\)]*)[\\s]*\\)[\\s]*");// ?<url>
public ScreenCaptureHtmlUnitDriver() {
super();
}
public ScreenCaptureHtmlUnitDriver(boolean enableJavascript) {
super(enableJavascript);
}
public ScreenCaptureHtmlUnitDriver(Capabilities capabilities) {
super(capabilities);
}
public ScreenCaptureHtmlUnitDriver(BrowserVersion version) {
super(version);
DesiredCapabilities var = ((DesiredCapabilities) getCapabilities());
var.setCapability(CapabilityType.TAKES_SCREENSHOT, true);
}
//#Override
#SuppressWarnings("unchecked")
public <X> X getScreenshotAs(OutputType<X> target) throws WebDriverException {
byte[] archive = new byte[0];
try {
archive = downloadCssAndImages(getWebClient(), (HtmlPage) getCurrentWindow().getEnclosedPage());
} catch (Exception e) {
}
if(target.equals(OutputType.BASE64)){
return target.convertFromBase64Png(new Base64Encoder().encode(archive));
}
if(target.equals(OutputType.BYTES)){
return (X) archive;
}
return (X) archive;
}
// http://stackoverflow.com/questions/2244272/how-can-i-tell-htmlunits-webclient-to-download-images-and-css
protected byte[] downloadCssAndImages(WebClient webClient, HtmlPage page) throws Exception {
WebWindow currentWindow = webClient.getCurrentWindow();
Map<String, String> urlMapping = new HashMap<String, String>();
Map<String, byte[]> files = new HashMap<String, byte[]>();
WebWindow window = null;
try {
window = webClient.getWebWindowByName(page.getUrl().toString()+"_screenshot");
webClient.getPage(window, new WebRequest(page.getUrl()));
} catch (Exception e) {
window = webClient.openWindow(page.getUrl(), page.getUrl().toString()+"_screenshot");
}
String xPathExpression = "//*[name() = 'img' or name() = 'link' and (#type = 'text/css' or #type = 'image/x-icon') or #type = 'text/javascript']";
List<?> resultList = page.getByXPath(xPathExpression);
Iterator<?> i = resultList.iterator();
while (i.hasNext()) {
try {
HtmlElement el = (HtmlElement) i.next();
String resourceSourcePath = el.getAttribute("src").equals("") ? el.getAttribute("href") : el
.getAttribute("src");
if (resourceSourcePath == null || resourceSourcePath.equals(""))
continue;
URL resourceRemoteLink = page.getFullyQualifiedUrl(resourceSourcePath);
String resourceLocalPath = mapLocalUrl(page, resourceRemoteLink, resourceSourcePath, urlMapping);
urlMapping.put(resourceSourcePath, resourceLocalPath);
if (!resourceRemoteLink.toString().endsWith(".css")) {
byte[] image = downloadImage(webClient, window, resourceRemoteLink);
files.put(resourceLocalPath, image);
} else {
String css = downloadCss(webClient, window, resourceRemoteLink);
for (String cssImagePath : getLinksFromCss(css)) {
URL cssImagelink = page.getFullyQualifiedUrl(cssImagePath.replace("\"", "").replace("\'", "")
.replace(" ", ""));
String cssImageLocalPath = mapLocalUrl(page, cssImagelink, cssImagePath, urlMapping);
files.put(cssImageLocalPath, downloadImage(webClient, window, cssImagelink));
}
files.put(resourceLocalPath, replaceRemoteUrlsWithLocal(css, urlMapping)
.replace("resources/", "./").getBytes());
}
} catch (Exception e) {
}
}
String pagesrc = replaceRemoteUrlsWithLocal(page.getWebResponse().getContentAsString(), urlMapping);
files.put("page.html", pagesrc.getBytes());
webClient.setCurrentWindow(currentWindow);
return createZip(files);
}
String downloadCss(WebClient webClient, WebWindow window, URL resourceUrl) throws Exception {
if (cssjsCache.get(resourceUrl.toString()) == null) {
cssjsCache.put(resourceUrl.toString(), webClient.getPage(window, new WebRequest(resourceUrl))
.getWebResponse().getContentAsString());
}
return cssjsCache.get(resourceUrl.toString());
}
byte[] downloadImage(WebClient webClient, WebWindow window, URL resourceUrl) throws Exception {
if (imagesCache.get(resourceUrl.toString()) == null) {
imagesCache.put(
resourceUrl.toString(),
IOUtils.toByteArray(webClient.getPage(window, new WebRequest(resourceUrl)).getWebResponse()
.getContentAsStream()));
}
return imagesCache.get(resourceUrl.toString());
}
public static byte[] createZip(Map<String, byte[]> files) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ZipOutputStream zipfile = new ZipOutputStream(bos);
Iterator<String> i = files.keySet().iterator();
String fileName = null;
ZipEntry zipentry = null;
while (i.hasNext()) {
fileName = i.next();
zipentry = new ZipEntry(fileName);
zipfile.putNextEntry(zipentry);
zipfile.write(files.get(fileName));
}
zipfile.close();
return bos.toByteArray();
}
List<String> getLinksFromCss(String css) {
List<String> result = new LinkedList<String>();
Matcher m = cssUrlPattern.matcher(css);
while (m.find()) { // find next match
result.add( m.group(2));
}
return result;
}
String replaceRemoteUrlsWithLocal(String source, Map<String, String> replacement) {
for (String object : replacement.keySet()) {
// background:url(http://org.com/images/image.gif)
source = source.replace(object, replacement.get(object));
}
return source;
}
String mapLocalUrl(HtmlPage page, URL link, String path, Map<String, String> replacementToAdd) throws Exception {
String resultingFileName = "resources/" + FilenameUtils.getName(link.getFile());
replacementToAdd.put(path, resultingFileName);
return resultingFileName;
}
}
UPDATE
Code provided by Andrew works- but I wanted to know if there is a way by which we can download only selected resources. For eg this website I would like to download only captcha image those id is "//*[#id='cimage']" because downloading all the resources will take a long time. Is there a way by which we can download only the specific resource. Because with the existing code provided
below all the resources get downloaded.
byte[] zipFileBytes = ((ScreenCaptureHtmlUnitDriver) driver).getScreenshotAs(OutputType.BYTES);
FileUtils.writeByteArrayToFile(new File("D:\\TEMP.PNG"), zipFileBytes);
The error says that the code is trying to convert a byte[] to a File. It's easy to see why if you just strip out the unused paths from getScreenshotAs:
public <X> X getScreenshotAs(OutputType<X> target) throws WebDriverException {
byte[] archive = new byte[0];
try {
archive = downloadCssAndImages(getWebClient(), (HtmlPage) getCurrentWindow().getEnclosedPage());
} catch (Exception e) {
}
return (X) archive;
}
There's no way you can get a File out of that. OutputType.FILE is not supported, so you have to handle file output yourself. Luckily, that's easy. You can change your code to:
byte[] zipFileBytes = ((ScreenCaptureHtmlUnitDriver) driver).getScreenshotAs(OutputType.BYTES);
FileUtils.writeByteArrayToFile(new File("D:\\TEMP.PNG"), zipFileBytes);
See FileUtils.writeByteArrayToFile() for more.
Check this out this may helpful for you
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File("C:/Users/home/Desktop/screenshot.png"));// copy it somewhere