Selenium Webdriver not reading CSV file using CSVReader - selenium

I am executing a script for a Salesforce page flow with Chrome Webdriver. The flows are written in Selenium JUnit code, exported and executed as JAR (JUnit Request Sampler) in JMeter 5.4.1. The page has a pop-up which has a textbox. which should read all values from a CSV file (currently kept within Selenium Project) one by one [eg. value1, value2...value n] (1 column,'n' rows) until all values are finished. Once one data is entered, "Next" button is clicked for next value to be captured from CSV. "Tube1Id" is the element name of the textbox.
Currently the flow when run in JMeter executes till Textbox display in pop-up and stops, just on the step to read the CSV file. Can anyone please help?
public void jmeterTest() throws InterruptedException
{
try
{
String CSVPath = "C:\\Users\\user\\Documents\\CAREDx\\SeleniumProject\\SeleniumProject\\CSVSamples\\samples.csv";
driver.get("https://baseurl/");
/* code for pop up window open with Textbox*/
WebElement Tube1Id = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//input[#name='Tube1Id']")));
CSVReader reader = null;
reader = new CSVReader(new FileReader(CSVPath));
String[] samples;
while ((samples = reader.readNext()) != null)
{
String TubeId = samples[0];
Tube1Id.sendKeys(TubeId);
log.info(threadName + ":: Tube ID :: " + TubeId);
/* code for Next button click */
}
}
}

I found another way to work this out since reading data from an external csv file location didn't work.
I added a CSV Dataset config element in JMeter under JUnit Request [Thread Group>JUnit Request>CSV Data set config], added csv location and variable name (samples). I added the values in CSV file as value 1#value 2#...#value n. In the selenium code I added :
String samples = junitSampler.getThreadContext().getVariables().get("samples");
String[] arrOfStr = samples.split("#");
/* in-between code */
for (String TubeID : arrOfStr)
{
Tube1Id.clear();
Tube1Id.sendKeys(TubeID);
/* remaining code for click Next */
}
It's working.

Related

Use of TestNG #Test and #DataProvider Features causes log4j to write multiple log file entries

I am using Selenium with TestNG to run automated tests and log4j v1.2 to write log files…
TestNG has an #Test and an #DataProvider annotation feature that allows me to pass parameters saved in an Excel file to my test method…
When I only have one row in my Excel worksheet, the test method only runs once and log4j code in the test method writes to my log file properly…
When I have two or more rows in my Excel worksheet, the test method runs multiple times, once for each row in the Excel worksheet…
Unfortunately, on the second run, every log entry is duplicated…
On the third run, every log entry is triplicated…
On the fourth run, every log entry is quadruplicated, and so on…
How do I cause log4j to avoid this issue?
The material section of java code involved in the issue is below…
#Test(dataProvider="parchmentData")
public void CCRwitheTranscript(String recipient, String email, String fileattachment, String fileattachmenttype) throws InterruptedException, FileNotFoundException
{
//Console and File Logging using log4j
//Creates Pattern Layout
PatternLayout layout = new PatternLayout();
String conversionPattern = "%d %-7p [%t] %c %x - %m%n";
layout.setConversionPattern(conversionPattern);
//Creates Console Appender
ConsoleAppender consoleAppender = new ConsoleAppender();
consoleAppender.setLayout(layout);
consoleAppender.activateOptions();
//Creates Daily Rolling File Appender - User configurable to minutely (yyyy-MM-dd-HH-mm)...
DailyRollingFileAppender rollingFileAppender = new DailyRollingFileAppender();
rollingFileAppender.setFile("CCRwitheTranscript.log");
rollingFileAppender.setDatePattern("'.'yyyy-MM-dd-HH'.log'");
rollingFileAppender.setLayout(layout);
rollingFileAppender.activateOptions();
//Configures Root Logger
Logger rootLogger = Logger.getRootLogger();
rootLogger.setLevel(Level.INFO); //The level value (ALL; TRACE; DEBUG; INFO; WARN; ERROR; FATAL) determines which logger messages will be written to the log file
rootLogger.addAppender(consoleAppender);
rootLogger.addAppender(rollingFileAppender);
// creates a custom logger and log messages
Logger logger = Logger.getLogger(DDT.ParchmentCCRwitheTranscriptExcel.class);
//logger.setAdditivity(false);
logger.trace("this is a trace log message");
logger.debug("this is a debug log message");
logger.info("this is an information log message");
logger.warn("this is a warning log message");
logger.error("this is a error log message");
logger.fatal("this is a fatal log message");
logger.info("-----");
//Internet Explorer WebDriver
System.setProperty("webdriver.ie.driver", "C:\\temp\\Selenium\\IEDriverServer.exe");
WebDriver driver = new InternetExplorerDriver();
//Console Data Spacer
logger.info("-----");
//Print Current Class Name
logger.info("Class Name via logger: " + Thread.currentThread().getStackTrace()[1].getClassName());
//Print Current Method Name
logger.info("Method Name via logger: " + Thread.currentThread().getStackTrace()[1].getMethodName());
//Print Browser SessionID
logger.info("Session ID via logger: " + ((RemoteWebDriver)driver).getSessionId().toString());
logger.info("Home Page");
logger.info("Home Page Title Verified - User is able to login successfully!");
logger.info("Co-Curricular Record with eTranscript Page");
logger.info("Co-Curricular Record with eTranscript Page Title Verified!");
logger.error("Checkout button is missing on Shopping Cart Page!");
logger.error("I Accept checkbox is missing on Consent Page!");
logger.error("Confirm button is missing on Review Order Page!");
logger.error("Home link is missing on Thank You Page!");
//Close Chrome or IE Browsers
driver.close();
}
//DataProvider
#DataProvider(name="parchmentData")
public Object[][] passData()
{
ExcelDataConfig config=new ExcelDataConfig("C:\\Users\\dkedmondson\\workspace\\ParchmentTestData.xlsx");
//In order to change the sheet where the "Co-Curricular Record with eTranscript" data is located
String sheetname="CCR with eTranscript";
int sheet=config.getSheetIndex(sheetname);
String workbookname=config.getWorkbookName();
String workbookpath=config.getWorkbookPath();
int rows=config.getRowCount(sheetname);
int columns=config.getColumnCount(sheetname);
int sheets=config.getSheetCount();
Object[][] data=new Object[rows-1][columns]; //Defining data=new Object[rows-1][columns], in order to save only data rows in the Excel worksheet
for(int i=1; i<rows; i++) //Initializing i=1, in order to save only data rows in the Excel worksheet
{
for (int j=0; j<columns; j++)
{
data[i-1][j]=config.getData(sheetname, i, j); //Saving as data[i-1][j], in order to save only data rows in the Excel worksheet
}
}
return data;
}

How to Handle Authentication alert of browser in selenium webdriver?

Can anyone know that how can we handle Authenticate alert box of browser in selenium Webdriver ?
I user following code but its not working.
driver.switchTo().alert().authenticateUsing(new UserAndPassword("uname", "Password"));
Here is a screenshot of what I am trying to fill in:
Does anyone know how can I enter those credentials?
You can handle this in two ways:
You can pass the username and password directly through the URL like this:
driver..get("https://MyUserName:password#staging.www.abc.com")
You can also use AutoIT Tool for handling any kind of window popups.
For this you first have to download and install AutoIt
Then download SciTE4AutoIt3
You can do scripting in it, or you can use Au3Recorder. It is not available in new versions of SciTE, but you can download it from old versions separately. Unzip it and copy:
autoit-v3.3.14.0.zip\install\Extras\Au3Record
to
[#Install Dir of AutoIt in Program files]\Extras\Au3Record
Now you can start the recorder directly by clicking Au3Record.exe or you can find it in the Script Editor window Tools >AU3Recorder.
For it you have to create a blank .au3 file in the Script Editor. Now start recording. Perform action on Window Popup. Stop when Done. Save it with .au3 format.
Now GO to Saved File location >> Right Click on the File and compile it (Compile Script(x64) or else). It will create an .exe file in the same folder.Now run that script in your Project using:
Runtime.getRuntime().exec("File Loaction/MyAutoItScript.exe");
It will work.
Try below code:
String username = "myUsername";
String password = "myPassword";
String URL = "http://" + username + ":" + password + "#" + sso.mywebsite.com/usdf/ls/dia?kkkk;
driver.get(URL); // Basically operation done here itself still if not work use further Alert code as well
Alert alert = driver.switchTo().alert();
alert.accept();
Full code will be like:
driver.get("https://sso.mywebsite.com/usdf/ls/dia?kkkk");
String url = driver.getCurrentUrl().replaceAll("https://", "");
String username = "myUsername";
String password = "myPassword";
String URL = "https://" + username + ":" + password + "#" + url;
driver.get(URL); // Basically operation done here itself still if not work use further Alert code as well
Alert alert = driver.switchTo().alert();
alert.accept();
Note : Even alert code do not required .. use it as it works for you and this code works on chrome better
Something like this?
driver.Navigate().to("http://UserName:Password#url.‌​com")
or
WebDriverWait wait = new WebDriverWait(driver, 10);
Alert alert = wait.until(ExpectedConditions.alertIsPresent());
alert.authenticateUsing(new UserAndPassword(*username*, *password*));
I use Java for my test automation. I have searched for a decent way to deal with these sign in pop ups and cannot find one. The most common answers are either to include in a URL as prefix prior to the real url (eg https:\username:password#www.website.com) or to use a wait for alert. These have not worked for me as: on a form submit there is no simple url to use and I am not sure as to the security including the password in the start of the url; with the wait for alert the webdriver hangs until there is a response - which only comes from submitting the login response via the pop up.
The workaround I have found is poor - I've not got it to work in a headless environment and so limits this answers usefulness. Would be great to get a real answer here. Note that I am running this in a Windows environment and if I was using Linux I have read that I could use xvfb to provide a 'screen' for sikuli and then this would work - if anyone can comment on how to do this on a Windows server that would be MUCH appreciated.
I use Sikuli for the automation of things I cannot automate via Selenium. Sikuli does many things, including letting you basically feed it images that it performs actions on.
For this purpose I run Sikuli on a thread started prior to clickin the submit that leads to the sign in pop-up. As it is running on a different thread it doesn't block the main thread, so it can still execute the log in. Once it logs in it shuts down and logging in closes the pop up and reactivates the main thread.
Specifically:
Sikuli MAVEN entry for POM:
<dependency>
<groupId>com.sikulix</groupId>
<artifactId>sikulixapi</artifactId>
<version>1.1.4-20191010.160947-268</version>
</dependency>
In the main code use a runnable executed via an executor:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
private final AtomicInteger expectedResultCount;
private final AtomicInteger publishedResultCount;
private final ExecutorService executor;
ExecutorService executor = Executors.newFixedThreadPool(5);
String processName = "asic-login";
LoginPopUp login = new LoginPopUp(this, processName);
addResultExpectation(processName);
executor.execute(login);
The runnable here implements an interface I use to keep things tidy:
The main class implements the interface to manage the threads:
public class TestRunner implements ResultPublisher{
These are functions inside the main class for thread management:
private void addResultExpectation(String process){
resultMap.put(process, new JSONObject());
expectedResultCount.addAndGet(1);
}
public void publishResult(JSONObject result){
String process = result.getString("process-name");
String strResult = result.getString("result");
resultMap.put(process, result);
publishedResultCount.addAndGet(1);
if(publishedResultCount.get() == expectedResultCount.get()){
executor.shutdown();
System.out.println("shutting down executor for run " + runId);
}
}
This is the interface
import org.json.JSONObject;
public interface ResultPublisher {
void publishResult(JSONObject result);
}
This is the runnable Runnable - an inner class in the TestRunner main class:
private class LoginPopUp implements Runnable{
private ResultPublisher publisher;
private String filePath;
private String processName;
private LoginPopUp(){
}
public LoginPopUp(ResultPublisher publisher, String processName){
this.publisher = publisher;
this.processName = processName;
}
private void publish(JSONObject result){
publisher.publishResult(result);
}
public void run(){
JSONObject result = new JSONObject();
result.put("path", filePath);
try{
Screen sd = new Screen();
ScreenUtility s = new ScreenUtility(imagesDirectory);
s.clickImage("LoginTitle.PNG", 10, 2500);
s.typeImageWithOffset("UserName.PNG", userName, 30,0);
s.typeImageWithOffset("Password.PNG",String.valueOf(password), 50,0);
s.clickImage("AsicSignIn.PNG", 10, 250);
}catch(Exception ex){
result.put("result", ex.getMessage());
result.put("process-name", processName);
publish(result);
Logger.getLogger(BCSRobot.class.getName()).log(Level.SEVERE, null, ex);
return;
}
result.put("result", "logged in successfully");
result.put("process-name", processName);
publish(result);
return;
}
}

Read a file from the cache in CEFSharp

I need to navigate to a web site that ultimately contains a .pdf file and I want to save that file locally. I am using CEFSharp to do this. The nature of this site is such that once the .pdf appears in the browser, it cannot be accessed again. For this reason, I was wondering if once you have a .pdf displayed in the browser, is there a way to access the source for that file in the cache?
I have tried implementing IDownloadHandler and that works, but you have to click the save button on the embedded .pdf. I am trying to get around that.
OK, here is how I got it to work. There is a function in CEFSharp that allows you to filter an incoming web response. Consequently, this gives you complete access to the incoming stream. My solution is a little on the dirty side and not particularly efficient, but it works for my situation. If anyone sees a better way, I am open for suggestions. There are two things I have to assume in order for my code to work.
GetResourceResponseFilter is called every time a new page is downloaded.
The PDF is that last thing to be downloaded during the navigation process.
Start with the CEF Minimal Example found here : https://github.com/cefsharp/CefSharp.MinimalExample
I used the WinForms version. Implement the IRequestHandler and IResponseFilter in the form definition as follows:
public partial class BrowserForm : Form, IRequestHandler, IResponseFilter
{
public readonly ChromiumWebBrowser browser;
public BrowserForm(string url)
{
InitializeComponent();
browser = new ChromiumWebBrowser(url)
{
Dock = DockStyle.Fill,
};
toolStripContainer.ContentPanel.Controls.Add(browser);
browser.BrowserSettings.FileAccessFromFileUrls = CefState.Enabled;
browser.BrowserSettings.UniversalAccessFromFileUrls = CefState.Enabled;
browser.BrowserSettings.WebSecurity = CefState.Disabled;
browser.BrowserSettings.Javascript = CefState.Enabled;
browser.LoadingStateChanged += OnLoadingStateChanged;
browser.ConsoleMessage += OnBrowserConsoleMessage;
browser.StatusMessage += OnBrowserStatusMessage;
browser.TitleChanged += OnBrowserTitleChanged;
browser.AddressChanged += OnBrowserAddressChanged;
browser.FrameLoadEnd += browser_FrameLoadEnd;
browser.LifeSpanHandler = this;
browser.RequestHandler = this;
The declaration and the last two lines are the most important for this explanation. I implemented the IRequestHandler using the template found here:
https://github.com/cefsharp/CefSharp/blob/master/CefSharp.Example/RequestHandler.cs
I changed everything to what it recommends as default except for GetResourceResponseFilter which I implemented as follows:
IResponseFilter IRequestHandler.GetResourceResponseFilter(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response)
{
if (request.Url.EndsWith(".pdf"))
return this;
return null;
}
I then implemented IResponseFilter as follows:
FilterStatus IResponseFilter.Filter(Stream dataIn, out long dataInRead, Stream dataOut, out long dataOutWritten)
{
BinaryWriter sw;
if (dataIn == null)
{
dataInRead = 0;
dataOutWritten = 0;
return FilterStatus.Done;
}
dataInRead = dataIn.Length;
dataOutWritten = Math.Min(dataInRead, dataOut.Length);
byte[] buffer = new byte[dataOutWritten];
int bytesRead = dataIn.Read(buffer, 0, (int)dataOutWritten);
string s = System.Text.Encoding.UTF8.GetString(buffer);
if (s.StartsWith("%PDF"))
File.Delete(pdfFileName);
sw = new BinaryWriter(File.Open(pdfFileName, FileMode.Append));
sw.Write(buffer);
sw.Close();
dataOut.Write(buffer, 0, bytesRead);
return FilterStatus.Done;
}
bool IResponseFilter.InitFilter()
{
return true;
}
What I found is that the PDF is actually downloaded twice when it is loaded. In any case, there might be header information and what not at the beginning of the page. When I get a stream segment that begins with %PDF, I know it is the beginning of a PDF so I delete the file to discard any previous contents that might be there. Otherwise, I just keep appending each segment to the end of the file. Theoretically, the PDF file will be safe until you navigate to another PDF, but my recommendation is to do something with the file as soon as the page is loaded just to be safe.

selenium webdriver - report generating, taking screenshot and save to folder on desktop

After generating a script in selenium webdriver using testng framework, how to generate test report, error handling, taking screenshot and save to folder on desktop.
Code for taking screenshot and save to folder on desktop.
public static void ScreenShot() throws IOException {
WebDriver driver = new FirefoxDriver();
driver.get("http://www.yahoo.com/");
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
//Takes screenshot
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
// Now you can do whatever you need to do with it, for example copy somewhere
String path;
path = "C:/Users/owner/Desktop/screenshots/" + scrFile.getName();//goes to the path and automatically gives name
FileUtils.copyFile(scrFile, new File(path)); //copies the screenshot file to the given path.
}

How are Selenium screenshots handled with multiple instances on Grid?

How are Selenium screenshots handled with multiple instances running on Grid? Say I have a Grid Hub driving a Grid Node with 3 Firefox browsers going simultaneously on one Node machine, how do I get 3 distinct screenshots from each of the 3 node threads?
For example, take this code snippet meant for a single threaded test:
RemoteWebDriver driver;
driver = new RemoteWebDriver(new URL("http://127.1/wd/hub"), DesiredCapabilities
.firefox() );
driver.get( "http://www.google.com/" );
WebDriver augmentedDriver = new Augmenter().augment(driver);
File screenshot = (TakesScreenshot)augmentedDriver.getScreenshotAs(OutputType
.FILE);
System.out.println( "Page title is: " + driver.getTitle() );
System.out.println( "Screenshot is located at: " + screenshot.getAbsolutePath());
assertTrue( "Page did not contain string.", driver.getSource().contains(
"search") );
driver.quit();
It will work absolutely fine.
The screenshot is actually the image of that specific driver instance and not a genetic desktop image. You will not see multiple browsers in each screenshot
First and foremost, Selenium/WebDriver/Selenium Grid would not handle multi-threading for you, its your underlying test framework (TestNG/JUnit/Cucumber etc.) would handle it. WebDriver is not thread-safe, If you are running tests in parallel, you would need to make sure your code is thread-safe.
Going back to your question, the code you wrote would overwrite on the same screenshot file. You would need to copy the file somewhere else with a different name. I would suggest you to prefix the screenshot file with a time stamp with millisecond precision and then copy the screenshot file. This way you would have three unique different screenshots for three different browser instances. This worked for me in the past.
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
String file_name = "screenshot_"+ Add system_time with millisecond precision
FileUtils.copyFile(scrFile, new File(file_name));
Here is a snippet from my Utiility code which works perfectly fine
String path = null;
try {
File source = ((TakesScreenshot)
driver).getScreenshotAs(OutputType.FILE);
Calendar currentDate = Calendar.getInstance();
SimpleDateFormat formatter = new SimpleDateFormat(
"yyyy/MMM/dd HH:mm:ss");
String dateN = formatter.format(currentDate.getTime()).replace("/","_");
String dateNow = dateN.replace(":","_");
String snapShotDirectory = Files.screenShotDirectory + dateNow;
File f = new File(snapShotDirectory);
if(f.mkdir()){
path = f.getAbsolutePath() + "/" + source.getName();
FileUtils.copyFile(source, new File(path));
}
}
catch(IOException e) {
path = "Failed to capture screenshot: " + e.getMessage();
}
You can try using it.
Capture the screenshots that You would need to copy the file somewhere else with a different name. The following code help to you.
Create the method of any name. I am creating here captureScreenshot method.
public static void captureScreenshot(String path) throws IOException{
try{
File scrFile= ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File(path) );
}
catch (Exception e){
System.out.println("Failed to capture screenshot");
}
}
Then use this method in your method where you want to take the screenshots. Refer the following line of code. Here I am using the system current time in milliseconds for to save the multiple Images with different name.
captureScreenshot("././screenshots/loginerror_" + System.currentTimeMillis()+".jpg");