Selenium WebDriver: Variable for different countries - java

Hi I'm new to Java and Selenium and I am trying to figure out some things. And please forgive my English.
Let's assume I have 2 or more countries and I only have one "testclass" for logging in.
For Country1 I have the username:"user1" and the password "pass1".
For country2 it is "user2" and "password2". I do not want to hardcode the username and the password into the testclass so I created another one which holds the variable e.g
public static final String iUsername = "user1";
and
public static final String mUsername = "user2";.
In the testclass I would call it e.g
driver.findElement(By.id("username")).sendKeys(Constant.iUsername);.
My Question is how can I select before I start the test the other username (mUsername) without always changing the code at the testclass.
Like I said I'm new and I am not so good at explain things.
Thanks

This is a pseudo-code that shows a possible design for your test:
Create a class for Users:
public class User {
public String username;
public String password;
public Users(String username, String password) {
this.username = username;
this.password = password;
}
}
Create a class to store their information (similar to your static class):
public class UserFixture {
public static User userUSA = new User("userUSA", "passUSA");
public static User userUK = new User("userUK", "passUK");
public static User userChina = new User("userChina", "passChina");
public static User userFrance = new User("userFrance", "passFrance");
}
Create a HashMap with the list of countries you want to test:
public class AccessTest {
List<String> countries = Arrays.asList(
"www.website.com",
"www.website.co.uk",
"www.website.ch",
"www.website.com.fr");
Map<Users, List<String>> userCountries = new HashMap<Users, List<String>>();
userCountries.put(UserFixture.userUSA, countries);
userCountries.put(UserFixture.userUK, countries);
userCountries.put(UserFixture.userChina, countries);
userCountries.put(UserFixture.userFrance, countries);
public static test() {
// u = user; c = country
userCountries.forEach((u, c) ->
c.forEach( country ->
goToUrl(country);
login(u);
// Write the rest of the test below
)
)
}
}

There are many ways to do this, but easiest one is -
You can have one properties file containing your user ids and passwords and one extra parameter (say Choice = 1 or 2) defining which user you want to use. This way you will not need to have the class holding constants. Then you can have one class for reading parameter file. Create a login function where you can pass the login data. Then in your test class you can use ids and their passwords based on the value of Choice.
if(properties.getProperty("Choice") == 1)
{ Login(properties.getProperty("User1Id"),properties.getProperty("Pass1"));
else if (properties.getProperty("Choice") == 2)
{ Login(properties.getProperty("User2Id"),properties.getProperty("Pass2"));
}
else //some error
This way you just have to change the value of choice variable in your properties file.

Related

Hash maps to link several domains into one report - Java Eclipse

I am new to Java and am using Java Eclipse, so please be kind! I hope I'm going to pose this question correctly so it makes sense.
I have four domains - each domain is pulling data from four different servers, hence the need to have them separate. But now I need to create a report that links all the data from the four domains into one report. Someone suggested using hashmaps, which I haven't used before. My four domains each have two fields that can be used as a key - CostCenter and Serial. The data being pulled is from machines all over the country. I need all the data for each machine in one report.
This is all being added to an existing project that creates a webpage with tabs for the user to click on for various tables and get data specific to a location, or to create a report for each page for all machines/locations. I just need to add a new link for the user to click on that will create this spreadsheet for them.
I've already created the domains (DAO, DAOImpl, DTO, and so on) and then I was going to create the combined report in my MainService.java. Here are the domains (lists) as declared in my MainService:
public List<Volume> getVolumeReport();
public List<BadFmPumps> getBadFmPumpsReport();
public List<BadCorobPumps> getBadCorobPumpsReport();
public List<McService> getMcServiceReport();
And here is data being pulled from the databases for each of them (domains):
public class Volume {
private String costCenter;
private String DAD;
private String division;
private String model;
private String serial;
private String numDispensers;
private String colorantSys;
private String CCEGals2017;
private String BACGals2017;
private String CCEGals2018;
private String BACGals2018;
private String DNR2017;
private String DNR2018;
private String DNR2019;
public class BadFmPumps {
private String costCenter;
private String model;
private String serial;
private String badFmPumps;
private String over10;
private String under10;
public class BadCorobPumps {
private String costCenter;
private String model;
private String serial;
private String badPumpCount;
public class McService {
private String costCenter;
private String model;
private String serial;
private String crChargeTotals;
private String emgCalls;
So I need to pull this data into one report wherever CostCenter + Serial matches. How do I declare the hashmaps for each object and how do I declare the key?
EDIT ----
I think I have something close here with
public List<Volume> getVolumeReport();
Map<String, Volume> VolumeMap = new HashMap<String, Volume>();
for (Volume dispenser : VolumeList)
{
String volumeKey = new StringBuilder().append(Volume.getCostCenter()).append(Volume.getSerial()).toString();
VolumeMap.put(volumeKey, dispenser);
}
Is this correct? I am getting one syntax error - the Map declaration
Map<String, Volume> VolumeMap = new HashMap<String, Volume>();
is giving me the error
Syntax error on token ";", { expected after this token
Is there something I need to change there?
There are some unusual things in your code. My guess is that you came from C# you are not using proper naming conventions see it here: https://www.oracle.com/technetwork/java/codeconventions-135099.html
You defined your method wrong, the error is not in the Map but the method definition
public List<Volume> getVolumeReport(); <-------- this
Should be
public List<Volume> getVolumeReport() {
And then close your method at its end (using }).
And inside your FOR you trying to direct access the Volume methods when you should use the variable you created: dispenser
String volumeKey = new StringBuilder()
.append(Volume.getCostCenter())
.append(Volume.getSerial())
.toString();
Should be
String volumeKey = new StringBuilder()
.append(dispenser.getCostCenter())
.append(dispenser.getSerial())
.toString();

How to keep user information after login in JavaFX Desktop Application

I have an application with login screen, after the user is authenticated some "data" is retrieved from a database (username and privileges), until here everything is well.
After the login process I need to access to the privileges to generate some menus across different JavaFX scenes, this all throughout the entire application in any moment, but I donĀ“t know how to do it.
What I am looking for is a behavior such as SESSION variable in PHP (yep, I come from web development), which keeps information alive and accesible during a certain period of time (usually while user is logged in).
The information I have found about this topic is unclear and outdated, I mean, solutions that do not apply for JavaFX 2 or solutions with old design patterns.
I have created an image because in other forums I have found the same question but that is misunderstood, so I hope this could help.
Thanks to everyone.
You can use singleton design patter. For example:
public final class UserSession {
private static UserSession instance;
private String userName;
private Set<String> privileges;
private UserSession(String userName, Set<String> privileges) {
this.userName = userName;
this.privileges = privileges;
}
public static UserSession getInstace(String userName, Set<String> privileges) {
if(instance == null) {
instance = new UserSession(userName, privileges);
}
return instance;
}
public String getUserName() {
return userName;
}
public Set<String> getPrivileges() {
return privileges;
}
public void cleanUserSession() {
userName = "";// or null
privileges = new HashSet<>();// or null
}
#Override
public String toString() {
return "UserSession{" +
"userName='" + userName + '\'' +
", privileges=" + privileges +
'}';
}
}
and use the UserSession whenever you need. When you do login you just call: UserSession.getInstace(userName, privileges) and when you do log out: UserSession.cleanUserSession()
You can use the Java Preferences. At the first successful authentication, you need to write information about user in the Preferences like this:
Preferences userPreferences = Preferences.userRoot();
userPreferences.put(key,value);
And then take the data from the Preferences:
Preferences userPreferences = Preferences.userRoot();
String info = userPreferences.get(key,value);
you can put the user data into a local cache, such as Guava Cache.
for example, we use HashMap to store the user data:
class Session{ private HashMap<String,Object> store = new HashMap(); public static final Session INSTANCE = Session(); public void put(String key, Object value){ this.store.put(key,value); } public Object get(String key) { return this.store.get(key); } } in your controller: // call server side API to retrieve user User user = userApi.login(username,password); if(user != null){ Session.INSTANCE.put("USER",user); } // in other class User user = Session.INSTANCE.get("USER");

Why cant I say variable.array in this case?

I don't see why I cant do this, without getting an error saying "Songs cannot be resolved or is not a field". I am a noob by the way, trying to learn this stuff :) Thanks in advance for you time, and please tell me if you need more information.
import java.util.ArrayList;
public class Band {
public String bandName;
public ArrayList<String> musician = new ArrayList<String>();
public ArrayList<String> songs = new ArrayList<String>();
// Constructor
public Band(String bandName) {
this.bandName = bandName;
}
public void getBandSongs(String bandName){
for (String s : bandName.songs) { <<<<<<<<<<<ERROR HERE
String rating = s.substring(0,1);
s = s.substring(1);
System.out.println("Rating: " + rating + " - Song name: " + s);
}
}
}
Sometimes the errors that the IDE gives you are misleading, but this one is quite clear.
So, let's analyse it:
"Songs cannot be resolved or is not a field"
So that should ring up an alarm. First thing you should do is look at the type that is your variable bandName.
public void getBandSongs(String bandName){
for (String s : bandName.songs) ...
It's a String! Of course you won't be able to access a field "songs" of a type String.
Maybe in your method signature you meant to have the following:
public void getBandSongs(Band band)
In that case, you should be able to access band.songs just fine.
Or you could have meant the following:
for (String s : this.songs)
That means you would be accessing the "songs" variable of the object instantiation of the class Band.
In summary:
The attributes that you define in your class:
public String bandName;
public ArrayList<String> musician = new ArrayList<String>();
public ArrayList<String> songs = new ArrayList<String>();
can be accessed through a variable that is of type of that class (in this case Band).
Hope this has made it a bit clear. Are you following any book in particular? I recommend the O'Reilly series. Good luck!
ps: I don't want to add too much since you are starting. But I advise you to read up on "encapsulation". That means that, unless strictly necessary, your should, by default, make your class's arguments private and let other classes access them through "getters" and "setters". Such that:
public class Band {
private String bandName;
private ArrayList<String> musician = new ArrayList<String>();
private ArrayList<String> songs = new ArrayList<String>();
public String getBandName(){
return this.bandName;
}
public void setBandName(String bandName){
this.bandName = bandName;
}
//And like that for the other two attributes. That way the classes that need access
// to these will either use a "get" method or a "set" method without directly
// accessing the attributes.
}
The work of creating getters and setters is so redundant that both Eclipse and Netbeans IDEs have a functionality that allows you to do these automatically.
songs is a part of Band, not bandName.
use this.songs instead (or just songs).
It should be noted though that public fields are against encapsulation (and thus OOP). Is this really what you want?
The major benefit of encapsulation (providing getters & setters for instance members) is to have a unified way of accessing your fields in a class. This allows you to, for example, add validation logic to your data.
private List<String> songs = new ArrayList<>();
public List<String> getSongs(){
return songs;
}
public List<String> setSongs(List<String> songlist) {
this.songs = songlist;
}
Now you can add validation to these methods. For example if you want to make sure you can only set the songlist if it has at least 5 songs in it:
public List<String> setSongs(List<String> songlist) {
if(songlist.size() > 5) {
this.songs = songlist;
}
}

How to save an ArrayList in Play?

This might seem like a very basic question, but I have a model (User) which I want to store an ArrayList of Strings (they are the id's of other users). I declare the List like this:
public List<String> friends = new ArrayList<String>();
After I add an entry to the array, I save the user. But friends is always null when I try to use it. Is there a specific way to save an ArrayList? Any help would be appreciated.
My model:
#Entity
public class User extends Model {
#Id
public String username;
public String password;
public List<String> friends = new ArrayList<String>();
public static Finder<String, User> find = new Finder<String, User>(String.class, User.class);
// Constructor
public User(String username, String password){
this.username = username;
this.password = password;
}
// Methods
public void addFriend(String friend){
friends.add(friend);
}
// Static Methods
public static User authenticate(String username, String password){
return find.where().eq("username", username).eq("password", password).findUnique();
}
public static void befriend(String user1, String user2){
User.find.ref(user1).addFriend(user2));
User.find.ref(user2).addFriend(user1);
User.find.ref(user1).save();
User.find.ref(user2).save();
}
}
The controller method:
return ok(index.render(
User.find.byId(request().username()).friends,
));
And a very simple view:
#(friends: List[User])
<div id="current_friends">
#for(friend <- friends) {
#friend.username
}
</div>
You need to save the relations 'manually' with saveManyToManyAssociations(String fieldname), for an example:
public static void befriend(String userName1, String userName2){
User user1 = User.find.byId(userName1);
User user2 = User.find.byId(userName2);
user1.friends.add(user2);
user2.friends.add(user1);
user1.save();
user2.save();
// here...
user1.saveManyToManyAssociations("friends");
user2.saveManyToManyAssociations("friends");
}
(note: written from top of my had so debug it yourself pls)
One potential reason for this problem could be your view:
The first line of your view is
#(friends: List[User])
The User does not have a package name, which could cause the null pointer exception.
In my case, my User bean is under models package, so I have the following line:
#(friends: List[models.User])
I encountered the exact same problem, and here is how I fixed it (with a little explanation coming along).
In fact, you try to save an ArrayList (thus something which size is undefined) in a DataBase. And apparently (and quite logically), the Play Framework doesn't really like it ; you have to use whether annotations or a transient class. I decided to use the class way (also because i don't know how to use the annotations to make a sub table, so I didn't took the risk, but it's not the best way to do it. In fact, it's an horrible way of doing it. But still, here it is).
In your case, you could to this :
#Entity
public class Friends extends Model {
#Id
public Long id;
#Required
public String user1;
#Required
public String user2;
public static Finder<Long, Friends> find = new Finder<Long, Friends>(Long.class, Friends.class);
//Here put your functions, I myself only added an insert method for the moment :
public static void add(String user1, String user2){
Friends f = new Friends();
f.user1 = user1;
f.user2 = user2;
bu.save();
}
}
And in your User model, just change the part in which you save both user into each other's List by this function.
Hope this will help.
Note : the id is here because I like numeric ids, feel free to change it.
Note 2 : Of course, it would be much better to use #ManyToOne and #OneToMany annotations, but as I wrote before, I don't know exactly how does it work.

java trouble making a correct interface

I want to make a class that can interact with a database, which has the following desired functionality:
It has a method to return all fields from the database, later can be changed such that it can also limit with it returns.
It has a method to insert a specific instance of this class.
It has a method to update a specific instance of this class.
I will show the code in a moment after further explanation.
Now I want to extract an interface, or rather an abstract class I think might be more appriopiate, to be sure that all classes/datafields follow the same 'interface', and to be able to use them as a supertype in Lists etc.
The data class, in this case Account.java, should represent a table in a database which stores {Username, Password}, I am omitting an explicite unique identifier for now, still not sure if I will make an additional ID field or use the uniqueness of the Username field.
It would be best if the abstract class itself would handle all the MySQL interaction 'mess'.
Account.java so far:
package testthing;
import java.util.Map;
/**
*
* #author Frank
*/
public class Account {
private final static String ALL_QUERY = "SELECT * FROM accounts";
private final static String INSERT_QUERY = "INSERT INTO accounts (username, password) VALUES(?, ?)";
private final static String UPDATE_QUERY = "UPDATE accounts SET password=? WHERE username=?";
private String username;
private String password;
public Account(final String username, final String password) {
this.username = username;
this.password= password;
}
public String getUsername() {
return username;
}
public void setUsername(final String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(final String password) {
this.password = password;
}
public static Map<String, Account> getAll() {
//return a map using the ALL_QUERY string
}
public void insert() {
//insert this using INSERT_QUERY
}
public void update() {
//update this using UPDATE_QUERY
}
}
I know that I haven't been that clear I'm afraid, but I hope this is enough to help me get going.
Basically I want to always be able to use the followings methods when working with a TableObject, which Account would be a subset of:
Account.getAll();
new Account("test", "test").insert();
currentAccount.setPassword("newPassword"); currentAccount.update();
All the nasty SQL stuff should be hidden inside the proposed abstract class. The only thing you cannot escape in a TableObject class is the definition of the SQL queries.
Regards.
EDIT: In current example Account.getAll() returns a Map<String, Account>, but in reality the first generic argument should be the type of the key in the database. So if you would use an unique ID then it would need to return a Map<Integer, Account>. I hope this change makes it in time for people to read it.
Is it not more logical, to have the connection code and all the "nasty" stuff in the superclass, but simply have a more general method in the superclass, that is used by it's sub classes. For example:
public void executeUpdate(String query)
{
// Code to execute update.
}
public Map<String, Data> getData(String query)
{
// Code to get data.
return data;
}
This way, these methods are more general. It means that you can implement several classes that simply pass query data, rather than constantly having to update a superclass every single time you want to add new functionality.
Obviously I've just assumed a type Data here, but that might be something to look into. The aim here is to decouple your classes as much as possible. This means you can add as many new classes as you want, and they can use their supertype without hinderence.
This also means things like
Account.getAll();
is a little less complicated, because if you have getAll in your superclass, where is the reference that you want to get all accounts? If the code is actually in the Account class, you can customize the query, and send it off to the getData method to be executed.

Categories