Selenium test saving screenshots - java

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

Related

How do I use the Grafana client for java to upload dashboards with a time-series filled panel to Grafana?

I am currently comparing time-series. They are stored in InfluxDB. My task is to get two time-series from InfluxDB, compare them and upload a visualization to Grafana. The comparison result would be output to console and the two time-series would be uploaded to Grafana in a dashboard and they should be in the same panel. I am trying to use the grafana-api-java-client found here. My problem is that I can not figure out how to do this with the provided examples and Javadocs. There is not a lot of documentation and the examples don't work properly in my case. I hope that someone has worked with this client and can explain how to properly add two time-series to a panel in a dashboard and upload it.
I will provide what I am doing and then post the examples from the github page of the API.
First of all this is how I am getting my time series:
public List<Double> getTimeSeries(String streetName, String start, String stop) {
//gets the query result
QueryResult queryResult = influxDB.query(new Query(String.format("SELECT value FROM your_measurement WHERE street='%s' " +
"AND time >= '%s' AND time <= '%s'", streetName, start, stop)));
//Gets the values from the query result
List<List<Object>> values = queryResult.getResults().iterator().next().getSeries().iterator().next().getValues();
//Adds the values to a list
List<Double> timeSeries = new ArrayList<>();
for (List<Object> li : values) {
timeSeries.add(Double.valueOf(li.get(1).toString()));
}
return timeSeries;
}
I can convert this list to an array of doubles:
double[] timeSeriesArray = timeSeries.stream().mapToDouble(d -> d).toArray();
The following is the first example. It works properly up until the getDashboard() and deleteDashboard() methods, where I get the error that such a dashboard does not exist, even though it does. I don't know what causes this error. Every new dashboard ends up in the folder "General". The method createDashboard() creates, as expected, an empty dashboard in Grafana.
import com.appnexus.grafana.client.GrafanaClient;
//Setup the client
GrafanaConfiguration grafanaConfiguration =
new GrafanaConfiguration().host("your_grafana_host").apiKey("Bearer your_secret_key");
GrafanaClient grafanaClient = new GrafanaClient(grafanaConfiguration);
//Setup the dashboard
String DASHBOARD_NAME = "new_dashboard";
Dashboard dashboard = new Dashboard()
.title(DASHBOARD_NAME)
.version(0);
GrafanaDashboard grafanaDashboard = new GrafanaDashboard().dashboard(dashboard);
//Make API calls
grafanaClient.createDashboard(grafanaDashboard);
grafanaClient.getDashboard(DASHBOARD_NAME);
grafanaClient.deleteDashboard(DASHBOARD_NAME);
This is the second example. I assume that I have to modify it in order to solve my problem. I had to replace two things to get this example to work, which I will explain with code comments. When executing this code it creates a dashboard with an empty panel. I expected something to be shown on the panel but it is empty and there are no axes.
import com.appnexus.grafana.client.GrafanaClient;
//Setup the client
GrafanaConfiguration grafanaConfiguration =
new GrafanaConfiguration().host("your_grafana_host").apiKey("Bearer your_secret_key");
GrafanaClient grafanaClient = new GrafanaClient(grafanaConfiguration);
//Setup the dashboard
String DASHBOARD_NAME = "new_dashboard";
DashboardPanelTarget dashboardPanelTarget =
new DashboardPanelTarget().refId("getSomeMetric").target("*");
DashboardPanelXAxis dashboardPanelXAxis =
new DashboardPanelXAxis().show(true).mode(DashboardPanelXAxis.Mode.TIME);
DashboardPanelYAxis dashboardPanelYAxis =
new DashboardPanelYAxis().format(DashboardPanelYAxis.Format.SHORT).logBase(1).show(true);
//Datasource is required or alerts cannot be added
DashboardPanel dashboardPanel =
new DashboardPanel()
//This might be where my data has to go but I am not sure.
.targets(new ArrayList<>(Collections.singletonList(dashboardPanelTarget)))
//Had to change DASHBOARD_DATA_SOURCE to a String -> "DASHBOARD_DATA_SOURCE", I assume it's just the name of the datasource.
//.datasource(DASHBOARD_DATA_SOURCE)
.datasource("DASHBOARD_DATA_SOURCE")
.type(DashboardPanel.Type.GRAPH)
.fill(1)
.title(dashboardName)
.linewidth(1)
.lines(true)
.height("300px")
.span(12)
.xaxis(dashboardPanelXAxis)
.yaxes(new ArrayList<>(Arrays.asList(dashboardPanelYAxis, dashboardPanelYAxis)));
DashboardRow dashboardRow =
new DashboardRow()
.collapse(false)
.panels(new ArrayList<>(Collections.singletonList(dashboardPanel)));
Dashboard dashboard =
new Dashboard()
.title(dashboardName)
.schemaVersion(1)
.rows(new ArrayList<>(Collections.singletonList(dashboardRow)));
DashboardMeta dashboardMeta = new DashboardMeta().canSave(true).slug(dashboardName);
GrafanaDashboard grafanaDashboard =
new GrafanaDashboard().meta(dashboardMeta).dashboard(dashboard);
//create new dashboard
//Had to change createDashboardTest() to createDashboard(), because createDashboardTest() doesn't seem to exist
//DashboardMeta createdDashboardMeta = createDashboardTest(grafanaDashboard);
DashboardMeta createdDashboardMeta = createDashboard(grafanaDashboard);

Unable to create Apple Music user playlist within playlist folder using Java Applescript library wrapper com.tagtraum.obstmusic

Trying to use https://github.com/japlscript/obstmusic to talk to Apple Music app on Macos with Java, I used to write native applescript and then java applescript library but that was removed from Java.
In this case I cant work out to create a user playlist within a folder playlist, when I run the code
public void createPlaylist() throws Exception
{
FolderPlaylist songkongPlaylistFolder = getPlayListFolder();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd kk:mm");
String playlistname = "SongKong:" + sdf.format(new Date());
Application app = Application.getInstance();
Map<String, Reference> properties = new HashMap<>();
Object userPlaylist = app.make(TypeClass.fromClass(UserPlaylist.class), songkongPlaylistFolder, properties);
((UserPlaylist)userPlaylist).setName(playlistname);
}
I get exception
04/04/2022
14.52.44:BST:OSXUpdateItunesWithChanges:updateItunes:SEVERE: *** Unable to run itunes update:{ NSAppleScriptErrorAppName = Music;
NSAppleScriptErrorBriefMessage = "Can’t make some data into the
expected type."; NSAppleScriptErrorMessage = "Music got an error:
Can’t make some data into the expected type.";
NSAppleScriptErrorNumber = "-1700"; NSAppleScriptErrorRange =
"NSRange: {23, 93}"; }
com.tagtraum.japlscript.execution.JaplScriptException: {
NSAppleScriptErrorAppName = Music; NSAppleScriptErrorBriefMessage
= "Can’t make some data into the expected type."; NSAppleScriptErrorMessage = "Music got an error: Can’t make some data
into the expected type."; NSAppleScriptErrorNumber = "-1700";
NSAppleScriptErrorRange = "NSRange: {23, 93}"; } at
com.tagtraum.japlscript.execution.CocoaScriptExecutor.execute(Native
Method) at
com.tagtraum.japlscript.execution.CocoaScriptExecutor.executeImpl(CocoaScriptExecutor.java:28)
at
com.tagtraum.japlscript.execution.ScriptExecutor.execute(ScriptExecutor.java:102)
at
com.tagtraum.japlscript.ObjectInvocationHandler.executeAppleScript(ObjectInvocationHandler.java:476)
at
com.tagtraum.japlscript.ObjectInvocationHandler.executeAppleScript(ObjectInvocationHandler.java:468)
at
com.tagtraum.japlscript.ObjectInvocationHandler.executeAppleScript(ObjectInvocationHandler.java:464)
at
com.tagtraum.japlscript.ObjectInvocationHandler.invokeCommand(ObjectInvocationHandler.java:280)
at
com.tagtraum.japlscript.ObjectInvocationHandler.invoke(ObjectInvocationHandler.java:191)
at jdk.proxy2/jdk.proxy2.$Proxy59.make(Unknown Source) at
com.jthink.songkong.ituneshelper.OSXUpdateMusicWithChanges.createPlaylist(OSXUpdateMusicWithChanges.java:62)
at
com.jthink.songkong.ituneshelper.OSXUpdateItunesWithChanges.analyseFiles(OSXUpdateItunesWithChanges.java:246)
at
com.jthink.songkong.ituneshelper.OSXUpdateItunesWithChanges.updateItunes(OSXUpdateItunesWithChanges.java:126)
at
com.jthink.songkong.ituneshelper.UpdateItunesWithChanges.call(UpdateItunesWithChanges.java:184)
at
com.jthink.songkong.ituneshelper.UpdateItunesWithChanges.call(UpdateItunesWithChanges.java:33)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
I think the problem is how I call app.make() but I cant work out how to do it.
Found it buried quite away down in the README.md file of the base project https://github.com/japlscript/japlscript
Reference reference = app.make(UserPlaylist.CLASS, songkongPlaylistFolder, null);
UserPlaylist userPlaylist = reference.cast(UserPlaylist.class);
userPlaylist.setName(playlistname);

How to replace a JSON String with Java?

In my JSON Array inside of its file, it has an array set that goes as follows:
{
"user_interface_fields" : {
"tip_identifier" : {
"uuid": "12345678-1234-1234-1234-123456789112"
}
"insert_time" : "2001-01-01T00:00:00Z"
}
And now I got this file written in java
#Test
public void testExampleMessageToJson() throws Throwable {
log.info("\n\nTesting persist service [message to json]?\n");
//Setup
String rawJson = TestUtils.getResourceMessage("examples/life.json");
String tip_identifier_uuid = "12345678-1234-1234-1234-123456789112";
log.info("Raw Json:\n():", rawJson);
assertTrue(StringUtils.isNotBlank(rawJson));
//Test
JSONObject foundObj = persistService.messageToJson(rawJson);
//Verify
String tip_identifier_time = foundObj.getString("insert_time");
String new_time = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").format(Calendar.getInstance().getTime());
foundObj.put(new_time, foundObj).getString("insert_time");\
assertNotNull(foundObj);
String new_uuid = foundObj.getJSONObject("user_interface_fields").getJSONObject("tip_identifier").getString("uuid");
assertEquals(tip_identifier_uuid , new_uuid);
assertEquals(tip_identifier_time, new_time);
log.info("\n\nTesting persist service [message to json] COMPLETE!\n");
}
My goal is to have life.json's time to be nearly identical to our current time (so like if it's 11/11/21 01:30:21.22, insert_time's data should be around 01:30:21.2234 or whatever and at any time i or any other person runs the code it should be a near match..)
But in my failure trace it tells me:
org.junit.ComparisonFailure: expected:<202[0-02-19'T'00:00:]00> but was:<202[1-11T17:46:46+00]00>
I'm thinking that the logging is messed up because expected should be nearly matched as the current time (as stated in my goal). Since messagetoJson gets the current time and inserts it, when my test pulls out the insert_time it should be a couple of milliseconds behind and so I need to validate that it's within a second or ~1000 milliseconds.
But I don't know what the heck I should do or where I should go from here in order to fix that.

Mockito Unit tests - Timestamps are different

Having some issues with a Mockito test.
I currently get this error:
Argument(s) are different! Wanted:
repository.save(
uk.co.withersoft.docservice.repositories.hibernate.MetaDataEntity#3e437e6c
);
-> at uk.co.withersoft.docservice.datastore.impl.MetaDataStoreImplTest.storeClaimMetadata(MetaDataStoreImplTest.java:55)
Actual invocation has different arguments:
repository.save(
uk.co.withersoft.docservice.repositories.hibernate.MetaDataEntity#3e361ee2
);
I'm pretty sure its because the times within MetaDataEntity are different
//This is what I should be getting
id = null
metaData = "{"caseReference":"CN00000001","claimReference":"LN00000001","rpsDocumentType":"REJ","documentTitle":"Claims LN00000001 (Claimant: Mr LOCAL HOST) REJ-Rejection letter"}"
batchId = 0
state = "Saved MetaData to DB"
lastUpdatedDate = {Timestamp#1517} "2018-07-25 18:39:21.993"
createdDate = {Timestamp#1518} "2018-07-25 18:39:21.993"
// This is actually what I get.
id = null
metaData = "{"caseReference":"CN00000001","claimReference":"LN00000001","rpsDocumentType":"REJ","documentTitle":"Claims LN00000001 (Claimant: Mr LOCAL HOST) REJ-Rejection letter"}"
batchId = 0
state = "Saved MetaData to DB"
lastUpdatedDate = {Timestamp#1530} "2018-07-25 18:39:49.274"
createdDate = {Timestamp#1531} "2018-07-25 18:39:52.716"
Here is my test case:
#Test
public void storeClaimMetadata () throws JsonProcessingException {
ClaimMetaData metaData = constructMetaData();
MetaDataEntity mockResponseMetaDataEntity = new MetaDataEntity();
mockResponseMetaDataEntity.setId(1);
when(repository.save(any(MetaDataEntity.class))).thenReturn(mockResponseMetaDataEntity);
Integer result = testSubject.storeClaimMetadata(metaData);
assertEquals(Integer.valueOf(1), result);
final ObjectMapper mapper = new ObjectMapper();
String jsonMetaData = mapper.writeValueAsString(metaData);
MetaDataEntity expectedMetaDataEntity = new MetaDataEntity(null,
jsonMetaData,
0,
"Saved MetaData to DB",
new Timestamp(System.currentTimeMillis()),
new Timestamp(System.currentTimeMillis()));
Mockito.verify(repository, times(1)).save(expectedMetaDataEntity);
}
//Creates a ClaimRequest
private ClaimMetaData constructMetaData() {
final ClaimMetaData metaData = new ClaimMetaData("CN00000001",
"LN00000001",
"REJ",
"Claims LN00000001 (Claimant: Mr LOCAL HOST) REJ-Rejection letter");
return metaData;
}
Any help would be much appreciated. This has been driving me crazy!!
This is exactly why people use dependency injection, so they can specify test collaborators that give back predictable results. Replace the hardcoded new Timestamp(System.currentTimeMillis) stuff with calls to Timestamp.from(Instant.now(clock)).
java.time.Clock is an interface that you can use to get your timestamp values. The real implementation can be injected into the code being tested, using one of the factory methods that returns a system clock, like this (using Spring Java configuration):
#Bean
public Clock clock() {
return Clock.systemDefaultZone();
}
and for the test code you can have an implementation where you specify the time you want the clock to return:
#Before
public void setUp() {
clock = Clock.fixed(date.toInstant(), ZoneId.of("America/NewYork"));
systemUnderTest.setClock(clock);
}
This is "works as designed".
You are invoking a service that computes timestamps. Like, now.
Then you have a test case that has some setup going on, and fetches time stamps, too. Now.
Guess what: albeit these two "nows above are close to each other, there is still a bit of delay between them.
You are checking for equality, can only work when the time stamps are identical! But they aren't, because they are created one after the other, with very well noticeable delays in between!
Meaning: you need to look how you could control which timestamps are created within your application, like saying "the timestamps should be t1 and t2". So that your test can then check "I found t1 and t2".
Alternatively, you simply change your verification step: instead of trying to have "equal" objects (that can't be equal because different time stamps!), you could compare those parts that should be equal, and for the time stamps, you could check that they are "close enough".
In Code , instead of using new Timestamp(System.currentTimeMillis()) , you can use
new Timestamp(DateTimeUtils.currentTimeMillis()). Here DateTimeUtils is from jodatime.
In test cases, can use below.
private SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss:SSS");
#Before
public void before() throws Exception {
// define a fixed date-time
Date fixedDateTime = DATE_FORMATTER.parse("01/07/2016 16:45:00:000");
DateTimeUtils.setCurrentMillisFixed(fixedDateTime.getTime());
}
#After
public void after() throws Exception {
// Make sure to cleanup afterwards
DateTimeUtils.setCurrentMillisSystem();
}````

I am not able to write the xpath for dynamic element

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.

Categories

Resources