I am not able to write the xpath for dynamic element - java

I am facing a problem in the following scenario. Please help me guys.
Scenario-
open URL- https://member.bseindia.com/
Click on <MF> folder.
Click on <COMMON>.
Click on <DEC-2017> folder.
Click on <Current date> folder
<Current date> folder is generating dynamically everyday.
I have written the code but not able to write the xpath for dynamic folder. ex-11-12-2017
public class bseIndia
{
String driverPath = "C:\\Users\\Public\\Public Desktop";
public WebDriver driver;
#BeforeClass
public void setUp()
{
System.setProperty("webdriver.chrome.driver","F:\\Abhishek\\chromedriver.exe");
driver = new ChromeDriver();
driver.manage().window().maximize();
}
#Test
public void nav() throws InterruptedException
{
System.setProperty("webdriver.gecko.driver", "F:\\Abhishek\\Document\\geckodriver.exe");
System.setProperty("webdriver.chrome.driver", driverPath+"chromedriver.exe");
driver.navigate().to("https://member.bseindia.com");
driver.findElement(By.xpath("//a[#id='FileGridVB1_gvFiles_ctl06_lbFolderItem']")).click();
driver.findElement(By.xpath("//a[#id='FileGridVB1_gvFiles_ctl02_lbFolderItem']")).click();
driver.findElement(By.xpath("//a[#id='FileGridVB1_gvFiles_ctl02_lbFolderItem']")).click();
//driver.findElement(By.xpath("//a[#id='FileGridVB1_gvFiles_ctl06_lbFolderItem']")).click();
Date date=new Date();
SimpleDateFormat sm = new SimpleDateFormat("dd-mm-yyyy");
driver.findElements(By.xpath("//a[#id='FileGridVB1_gvFiles_ctl02_lbFolderItem']"));
boolean b= driver.findElements(By.xpath("//a[#id='FileGridVB1_gvFiles_ctl02_lbFolderItem']")).contains(sm.format(date));
if(b==true)
{
here I have write the xpath for dynamic folder.
}
}
}

I would do things a bit differently. I generally try to look at things like this where I'm repeating actions and try to come up with a general function that will take care of it. In this case, you are clicking a folder given a particular expected name. I would then write a function clickOnFolder(String folderName) so that I can handle that case. Then you would just call that function each time you needed to click a folder. The code is below
public static void clickOnFolder(String folderName)
{
driver.findElement(By.xpath("//a[contains(., '" + folderName + "')]")).click();
}
Using XPath, we are finding an A tag that contains the text of the folder name whether it be "MF" or "COMMON" or today's date. This general function can be used to click any folder.
In your question, one of your issues is that you need to find the folder by today's date. You've asked for the final folder name that contains the day/month/year but you really need it for the containing folder also to do it properly (DEC-2017).
To handle these dates, you just need to get today's date in the desired format and find the A tag that represents the folder using XPath. The code to get today's date into the proper format is below.
I've tested the code below and it works.
String url = "https://member.bseindia.com/";
driver.navigate().to(url);
// get date formats for folder names
LocalDateTime currentTime = LocalDateTime.now();
String todaysDate = currentTime.format(DateTimeFormatter.ofPattern("dd-MM-yyyy"));
String monthYear = currentTime.format(DateTimeFormatter.ofPattern("MMM-yyyy")).toUpperCase();
clickOnFolder("MF");
clickOnFolder("COMMON");
clickOnFolder(monthYear);
clickOnFolder(todaysDate);
Your code line that starts with boolean b will not work for several reasons.
You are using .findElements() (plural) which returns a collection so you would need to look at an individual element, e.g. .get(0), to do a comparison.
You are comparing a String to a WebElement which will always fail. What you want is something like driver.findElement(locator).getText().contains("some string");.
Your date format is using mm which in datetime formats means minutes, not months. You want MM.

Related

Java: Formatting a Date inside of a string

I know I'm probably doing something wrong, but I am trying to format a Date that is currently stored inside of a string but it won't let me parse it to a String because it doesn't recognize it as a Date (because it's in a String variable) and won't let me format it because it cannot format it in its current state. For reference, I am making a time clock application.
I apologize if I'm doing something stupid but I am fairly new to this and have never used SimpleDateFormat before. I put some snippets of code below:
ArrayList<String> punchHistoryTimes = new ArrayList<String>();
SimpleDateFormat sdf =new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
public void updatePunchHistory(Sheet sheet){
for(int rowNum:rowNumbers){
punchHistoryTimes.add(sheet.getRow(rowNum).getCell(1).getStringCellValue());
punchHistory.add(new JLabel(sheet.getRow(rowNum).getCell(0).getRichStringCellValue().getString()+ " " + sheet.getRow(rowNum).getCell(1).getRichStringCellValue().getString()+ " " + sheet.getRow(rowNum).getCell(2).getRichStringCellValue().getString()));
}
}
//other code is above this but not relevant to the issue
currentEmployee.setEndTime(sdf.format(currentDate));
if(punchHistory.get(punchHistory.size()-1).getText().contains("Clocked In")){
calcTimeWorked(punchHistory.get(punchHistoryTimes.size()-1).getText(),currentEmployee.getEndTime());
}else{
//This line below is where the error is happening
//value of currentEmployee.getStartTime() at error: 1654653731536
//value of currentEmployee.getEndTime() at error: 07-06-2022 21:02:12
//Both currentEmployee.getStartTime() and currentEmployee.getEndTime() are stored as Strings
calcTimeWorked(currentEmployee.getStartTime(),currentEmployee.getEndTime());
}
currentEmployee.setHoursWorked(differenceInTime);
I tried using the debugger and it shows the error is that it cannot parse 1654653731536. I understand the issue but cannot get a solution. I believe the issue is because when it stores the value in the excel file it is storing the date as a string but then when it pulls the date back out of the excel later (the application would have been closed between these events) it views it as a string and does not recognize that there is a Date inside of the String. Is there any way to cast the String 1654653731536 to a Date?

Java finding latest file in directory from date in file name

I have a directory where I receive files matching pattern ABC_STOCK_List_YYYYMMDD_YYYYMMDD.csv.
I am writing a scheduled service in java where I need to check the file is for today;s date and then do my process on that file.
ABC_STOCK_List_20200220_20200220.csv
ABC_STOCK_List_20200219_20200219.csv
ABC_STOCK_List_20200218_20200218.csv
ABC_STOCK_List_20200217_20200217.csv
I have this so far:
private Optional<File> findLatestFile(final String dir) {
return Stream.of(new File(dir).listFiles())
.filter(
file -> !file.isDirectory()
&& file.getName().startsWith(prefix)
&& file.getName().endsWith(".csv")
&& isTodaysFile(file)
)
.findFirst();
}
private boolean isTodaysFile(File file) {
return false;
}
I need help with isTodaysFile() that should check the latter YYYYMMDD is today's date. It should not only rely on date from file name, but also filesystem created or modified time that should also be today.
Here's my approach to this problem. At first, I've created two helper functions, one that retrieves the end date from the filename, and the other one that retrieves the filesystem modified time. I don't think it's necessary to check for the created time, since always created time is less than or equal to modified date time.
The function that retrieves the file name's end date:
private LocalDate getEndDate(File file) {
String fileName = file.getName();
String fileNameWithoutExtension = fileName.substring(0, fileName.lastIndexOf("."));
String[] fileNameChunks = fileNameWithoutExtension.split("_");
String endDateAsString = fileNameChunks[fileNameChunks.length - 1];
return LocalDate.parse(endDateAsString, DateTimeFormatter.ofPattern("yyyyMMdd"));
}
Next, the function that retrieves the filesystem modified date for a file. For this, I'm using the Files#getLastModifiedTime to retrieve the modified date:
private LocalDate getLastModifiedDate(File file, ZoneId zoneId) {
try {
return ZonedDateTime
.ofInstant(Files.getLastModifiedTime(file.toPath()).toInstant(), zoneId)
.toLocalDate();
} catch (IOException e) {
throw new RuntimeException("Could not read file attributes: " + file.getAbsolutePath());
}
}
In the end, it's just using calling these functions and performing the validations:
boolean isTodaysFile(File file) {
Clock systemUTCClock = Clock.systemUTC();
LocalDate localDateNow = LocalDate.now(systemUTCClock);
LocalDate fileEndDate = getEndDate(file);
// first check - validate that the file name's end date is today
if (!fileEndDate.isEqual(localDateNow)) {
return false;
}
LocalDate lastModifiedDate = getLastModifiedDate(file, systemUTCClock.getZone());
// second check - validate that the modified that is today
// no need to check the creation date, since creation date is always less or equal to the last modified date
return lastModifiedDate.equals(localDateNow);
}
I'm using Clock.systemUTC() and instantiating all dates based on this, to make sure we are always using UTC.
LocalDate.now(systemUTCClock)
systemUTCClock.getZone()
If the input files in the directory are:
ABC_STOCK_List_20200220_20200220.csv
ABC_STOCK_List_20200219_20200219.csv
ABC_STOCK_List_20200218_20200218.csv
ABC_STOCK_List_20200217_20200217.csv
ABC_STOCK_List_20200305_20200305.csv
At the date of writing this, the current date is 03-05-2020. The output file, when calling findLatestFile is:
ABC_STOCK_List_20200217_20200305.csv
Notes:
I didn't perform any validations on the file name format. If something is wrong with the format, you may get some errors when retrieving the end date.

DBunit - Unable to typecast <1997/02/14> to TimeStamp

I'm doing an integration testing with DBUnit (2.49) + Hibernate (4.1.3) following this tutorial.
Production database : Oracle 10
Test database : Hsqldb 2.3.3
Context
My data contains the current format of date : yyyy/MM/dd. However,according to DBUnit faq, DBUnit only supports this format yyyy-mm-dd hh:mm:ss.fffffffff, so I had to create a new format for TimeStamp.
How I tried to fix it
I created a CustomTimeStampDataType based on this tutorial. I changed this part:
String formats[] = {"yyyy-MM-dd HH:mm", "yyyy-MM-dd HH:mm a", "yyyy-MM-dd HH:mm:ss.fffffffff"};
into this one:
String formats[] = {"yyyy/MM/dd"};
I created a CustomeDataTypeFactory following the same tutorial. I only make it extend Oracle10DataTypeFactory rather than DefaultDatatTypeFactory.
In HibernateDBUnitTestCase, I override setDatabaseConfig() with the following:
#Override
protected void setUpDatabaseConfig(DatabaseConfig config){
config.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new CustomDataTypeFactory());
}
But I got new errors
I ran a unit test and got this error.
org.dbunit.dataset.datatype.TypeCastException: Unable to typecast value <1997/02/14> of type <java.lang.String> to TIMESTAMP
at org.dbunit.dataset.datatype.TimestampDataType.typeCast(TimestampDataType.java:120)
at org.dbunit.dataset.datatype.TimestampDataType.setSqlValue(TimestampDataType.java:176)
at org.dbunit.database.statement.SimplePreparedStatement.addValue(SimplePreparedStatement.java:73)
at org.dbunit.operation.RefreshOperation$RowOperation.execute(RefreshOperation.java:189)
at org.dbunit.operation.RefreshOperation.execute(RefreshOperation.java:113)
at org.dbunit.AbstractDatabaseTester.executeOperation(AbstractDatabaseTester.java:190)
at org.dbunit.AbstractDatabaseTester.onSetup(AbstractDatabaseTester.java:103)
at org.dbunit.DatabaseTestCase.setUp(DatabaseTestCase.java:156)
at test.HibernateDbUnitTestCase.setUp(HibernateDbUnitTestCase.java:85)
at test.PlayerTest.setUp(PlayerTest.java:117)
Caused by: java.lang.IllegalArgumentException: Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]
at java.sql.Timestamp.valueOf(Unknown Source)
at org.dbunit.dataset.datatype.TimestampDataType.typeCast(TimestampDataType.java:116)
... 20 more
That was weird, it seemed like my CustomTimeStamp was not called, so I changed the date in the dataset using the default format : 1997-02-14 00:00:00.0, and ran the unit test again. Then I got:
org.dbunit.dataset.datatype.TypeCastException: Unable to typecast value <1997-02-14 00:00:00.0> of type <java.lang.String> to TIMESTAMP
at test.CustomTimestampDataType.typeCast(CustomTimestampDataType.java:69)
at test.CustomTimestampDataType.setSqlValue(CustomTimestampDataType.java:84)
at org.dbunit.database.statement.SimplePreparedStatement.addValue(SimplePreparedStatement.java:73)
at org.dbunit.operation.RefreshOperation$RowOperation.execute(RefreshOperation.java:189)
at org.dbunit.operation.RefreshOperation.execute(RefreshOperation.java:113)
at org.dbunit.AbstractDatabaseTester.executeOperation(AbstractDatabaseTester.java:190)
at org.dbunit.AbstractDatabaseTester.onSetup(AbstractDatabaseTester.java:103)
at org.dbunit.DatabaseTestCase.setUp(DatabaseTestCase.java:156)
at test.HibernateDbUnitTestCase.setUp(HibernateDbUnitTestCase.java:85)
at test.PlayerTest.setUp(PlayerTest.java:117)
That means CustomTimeStamp was actually called. Seems like, the problem stemed from DatabaseTestCase.setUp which somehow called the wrong TimeStampDataType.
How could I fix this issue?
My first option was to replace every yyyy/MM/dd into yyyy-mm-dd in the dataset using regular expressions. This worked fine, until I had to test a method that selected a date based on a request (so the format is yyyy-mm-dd) and compared it to the current date. ( so the format is yyyy / mm / dd). Hsqldb can't compare two dates with different format.
My second option was to decompile dbunit.jar, rewrite TimeStampDataType based on the tutorial. I'm unfamiliar with bytecode writing so before entering uncharted waters, I wanted to know if you had another solution.
Thank you in advance
Fixed it!
So I ended up using my second option.
This is the detailed path for those who need it.
Download dbUnit.2.2.source.jar
Unzip the jar
Go to Eclipse, File > New > Java Project
Uncheck "Use default location"
In Location : specify the path to the new folder created from the jar
Click on Finish
Modify the TimestampDataType.java (if needed)
Instead of ts = java.sql.Timestamp.valueOf(stringValue); use the code below
String formats[] =
{"dd/MM/yyyy HH:mm:ss.SS"}; //and more depending on your need
Timestamp ts = null;
for (int i = 0; i < formats.length; i++)
{
SimpleDateFormat sdf = new SimpleDateFormat(formats[i]);
try {
java.util.Date date = sdf.parse(stringValue);
ts = new Timestamp(date.getTime());
return ts;
}
catch( ParseException e) {
}
Modify the DateDataType.java (if needed)
Instead of return java.sql.Date.valueOf(stringValue); , use the code below
String formats[] =
{"dd/MM/yyyy"}; //and more depending on your need
for (int i = 0; i < formats.length; i++)
{
SimpleDateFormat sdf = new SimpleDateFormat(formats[i]);
try {
java.util.Date date = sdf.parse(stringValue);
java.sql.Date datesql = new java.sql.Date(date.getTime());
return datesql;
}
catch( ParseException e) {
}
}
Right-click on your project, then Export
Select JAR file, then Next
Fill the export destination then Finish.
You just have to add this new jar to the library to make it work.

Selenium test saving screenshots

I currently have a Selenium test that runs through a website on 11 different languages and takes screenshots of each part. The pictures themselves get saved in respective folders like this in a property file
screenshotsEnglish.dir=/screenshots/Languages/English
screenshotsSwedish.dir=/screenshots/Languages/Swedish
What I want to do different is each time a test suite is run, a new base folder is created with the current date stamp followed up with the same structure as before. How can I make this work? I can't hardcode it in the property file obviously because the date will constantly change.
To give a overall better view how it all works
public static Object[][] dp() {
return new Object[][]{
{
"https://example-URL.net/example.php?lang=EN",
"screenshotsEnglish.dir"
},
{
"https://example-URL.net/example.php?lang=SV",
"screenshotsSwedish.dir"
}
};
}
#Test(dataProvider = "dp")
public void t(String url, String directory) {
driver.get(url);
Properties settings = PropertiesLoader.fromResource("settings.properties");
String screenshotDir = settings.getProperty(directory);
screenShooter = new ScreenShooter(driver, screenshotDir, "en");
/*...*/
}
Tests are written in Java with TestNG
I hope I've made myself clear and as always, appreciate all help loads
Why not like this (not tried to compile, just a quick try, so typos are possible):
String screenshotDir = settings.getProperty(directory); //this is what you already have
String date = new SimpleDateFormat("dd-MM-yyyy").format(new Date()); //added: get current date
screenshotDir = screenshotDir + "/" + date; //added: create modified path
new File(screenshotDir).mkdirs(); //added: make the new directory
screenShooter = new ScreenShooter(driver, screenshotDir, "en"); //this is what you already have

Formatting a date as a string, from bean to javascript

In my bean, I'm formatting a date as a string:
public void setStrDate(Date dte) {
DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
this.strDate = df.format(dte);
}
In my js file, I'm grabbing the data:
$('#content').data("myDate", <c:out value="${myBean.strDate}"/>);
And in my js, displaying the data:
$('#sideBar').find("p[class=stat]").append($('#content').data("myDate"));
The date comes over as 10/10/2014. I even see it in the developer tools this way:
$('#content').data("myDate", 10/10/2014);
But on the webpage, it shows up as 0.0004965243296921549
How can I format this?
You need to put quotes around your date when you output it. Make it read:
$('#content').data("myDate", "<c:out value="${myBean.strDate}"/>");
Why is it resulting in 0.0004965243296921549
10/10/2014 is actually being evaluated as math, 10/10 = 1 -> 1/2014=0.0004965243296921549
*if this code "<c:out value="${myBean.strDate}"/>" is making your editor flip out about the quotes then you can use single quotes as well '<c:out value="${myBean.strDate}"/>'

Categories

Resources