How to handle "Accept Cookies" message when an automation script runs - selenium-webdriver

I am writing a selenium test script which navigates to the url, say https://www.flipkart.com/ (This is just an example website)
When you first time navigate to the home page, a message regarding Cookies is displayed and there is a button "Accept Cookies".
Whenever my selenium script runs and navigates to the home page, every time it gets the cookie message as described earlier. My question is what needs to be done so that the script will not encounter such cookie consent message?
I have managed to store the cookies in in a file. It is as below
_gut_UB-97923818-1;1;.mycompany.com;/;Fri Mar 29 18:12:07 EET 2019;false
I have also tried to set its expiry with below code
public void retrieveCookie()
{
try{
File file = new File("Cookie.data");
FileReader fileReader = new FileReader(file);
BufferedReader Buffreader = new BufferedReader(fileReader);
String strline;
while((strline=Buffreader.readLine())!=null){
StringTokenizer token = new StringTokenizer(strline,";");
while(token.hasMoreTokens()){
String name = token.nextToken();
String value = token.nextToken();
String domain = token.nextToken();
String path = token.nextToken();
Date expiry = null;
String val;
if(!(val=token.nextToken()).equals("null")){ //Thu Mar 28 23:26:39 EET 2019
expiry = new Date(val);
}
Boolean isSecure = new Boolean(token.nextToken()).booleanValue();
Cookie ck = new Cookie(name,value,domain,path,expiry,isSecure);
BaseDriver.getDriver().manage().addCookie(ck); // This will add the stored cookie to our current session
}
}
}catch(Exception ex){
ex.printStackTrace();
}
BaseDriver.getDriver().get("https://www.flipkart.com/");
}
However I get java.lang.IllegalArgumentException exception at line,
expiry = new Date(val);
It is because it is not able to parse the date
Can someone share the code so that the date can be parsed?
My only intention is whenever the test script runs, it should not encounter the cookie consent message. If there is any other way to achieve this, please suggest.

Related

Taking Screen shots on specific error page in selenium web driver

My scenario is, I'm getting same error page on many of my button clicks on the site.
I want to take screenshots, of this same error page, with reference on which link of the site this error page occured.
So I want screenshot whenever this error page occurs on any click.
Can you suggest me how to write the function for this and how to call that function in some other function in selenium Webdriver.
Please share some code sample for that.
As of currently, I'm writing it only as :
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); FileUtils.copyFile(scrFile, new File("D:\\Home\\Ruchi\\failure.png"));
But in this I need to write these lines of code after every failure occurrence.
use try and catch block
try{
// Put your script here
}
catch(Exception ex)
{
File scrn=((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
// extracting date for folder name.
SimpleDateFormat sdfDate1 = new SimpleDateFormat("yyyy-MM-dd");//dd/MM/yyyy
Date now1 = new Date();
String strDate1 = sdfDate1.format(now1);
// extracting date and time for snapshot file
SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");//dd/MM/yyyy
Date now = new Date();
String strDate = sdfDate.format(now);
String filefolder="./Snap/"+strDate1+"/"; // create a folder as snap in your project directory
// Creating folders and files
File f = new File(filefolder+strDate+".jpeg");
FileUtils.copyFile(scrn, new File(f.getPath()));
}
If your script fails then the program jumps to catch block and then code will take screen shot for you
Hope it will help you :)

Selenium login time- Am I calculating right?

I have searched quite a bit on how to get login time but could not find any definitive answer. I do not want to introduce any timers in my scripts. My aim is to find how much time it took exactly to login and logout in my selenium script.
I have following so far-
I am getting start time and finish time and getting the login time as follows-
public void testLogin(){
String csvFile = "C:\Users\users.csv";
BufferedReader br = null;
String line = "";
String cvsSplitBy = ",";
try {
br = new BufferedReader(new FileReader(csvFile));
while ((line = br.readLine()) != null) {
// use comma as separator
String[] value = line.split(cvsSplitBy);
WebDriver driver = new HtmlUnitDriver();
//WebDriver driver = new FirefoxDriver();
driver.get("www.test.com");
long start=System.currentTimeMillis();
driver.findElement(By.id("txt-username")).sendKeys(value[0]);
driver.findElement(By.id("pwd-password")).sendKeys(value[1]);
driver.findElement(By.id("login-widget-submit")).click();
long finish=System.currentTimeMillis();
long OverallTime =finish-start;
System.out.println("Total time for login -"+OverallTime);
driver.close()
If you want to only measure the time taken to log in (not to load the login page and then log in), you will want to add a WebDriverWait after driver.get() and wait for a specific element to load to ensure that the page is fully loaded. You will want to add another wait after clicking Submit to ensure that the page after login has loaded completely. That is a better test of login time. What you have now is you start the timer potentially before the login page is loaded and then stop the timer when you click the Submit button... but the user isn't actually logged in yet.
I personally use the StopWatch class that's a part of apache.commons to do timings.

GAE/Java LocalChannelFailureException at development server

I'm using Channel API (Java) with Google App Engine for my web application. I have implemented a Token-reusing-mechanism for not exceeding the Channel API Quotas that fast.
This means, that my implementation reuses an existing channel for a user that refreshes the page as long as the expiration time of the token received by the ChannelService.createChannel() call, is not over.
When refreshing my page I get the following exception (with x starting at 0 and increasing for every refresh). However, my page continues to work as intended. Is there a way to avoid the exception being thrown? Or can I just ignore the exception?
com.google.appengine.api.channel.dev.LocalChannelFailureException: Client connection with ID connection-x not found.
at com.google.appengine.api.channel.dev.Channel.getClientMessageQueue(Channel.java:79)
at com.google.appengine.api.channel.dev.ChannelManager.getNextClientMessage(ChannelManager.java:300)
at com.google.appengine.api.channel.dev.LocalChannelServlet.doGet(LocalChannelServlet.java:120)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
...
Im reusing tokens with the following classes:
When calling ChannelService.createChannel() I save the expiration date and the generated token in an Entity called "Channel"
public class Channel {
private String id;
private String token;
private Date expiration;
}
Then I have a ChannelService class that returns a valid Channel with its get() method. The channelDAO is a class that just uses a Map for storing Channels. So there is no database persistence, which would keep a token alive over a server restart.
public Channel get(String clientId) {
Calendar calendar = Calendar.getInstance();
Channel channel = channelDAO.get(clientId);
if (channel == null || calendar.getTime().after(channel.getExpiration())) {
com.google.appengine.api.channel.ChannelService channelService = ChannelServiceFactory
.getChannelService();
calendar.add(Calendar.MINUTE, CHANNEL_UPTIME);
String token = channelService.createChannel(player.toString(), CHANNEL_UPTIME);
channel = new Channel(clientId, token, calendar.getTime());
channelDAO.persist(channel);
}
return channel;
}
I fixed the problem by further investigations on the source of the exception. The Channel API works with polling requests that are executed every 500ms. I used Firefox's console to track these. Here is an example poll:
[20:40:15.978] GET http://localhost:8080/_ah/channel/dev?command=poll&channel=920a60f9b27ece1a1ba43d251fdacf2e-channel-eqt3xi-1385927324758-{clientId}&client=connection-2 [HTTP/1.1 200 OK 0ms]
In my question I stated, that the exception occurs on page reload, so the problem with this was: When the page is reloaded, something (I don't know what exactly, but i assume it has something to do with sockets getting closed and reopened on page refresh) happens which causes the client (last parameter of the GET request) to no longer be available. However, a new client is available: the client "connection-{i+1}". So when you enter the page initially, the client is "connection-0". After page refresh it is "connection-1". But as the old page used a delayed execution for the poll, a false request (still connection-0) is sent to the server, that, as a result, throws the Exception.
I fixed the problem by manually cancelling the delayed execution, when leaving the page with jQuery.
var channel = new goog.appengine.Channel('${channel.token}');
var socket = channel.open(handler);
$(window).on('beforeunload', function() {
clearTimeout(socket.pollingTimer_);
});
Your token re-use scheme should be carefully checked for bugs as that exception shouldn't occur each page reload.
There is a known issue after local server restarts but as stated it should only be only if the development server restarted.
I had the same issue using GWT and gwt-gae-channel. The solution would be something like:
Socket socket = channel.open(new SocketListener() {...});
Window.addWindowClosingHandler(new ClosingHandler() {
#Override
public void onWindowClosing(ClosingEvent event) {
socket.close();
}
});

Google Plus DomainsAPI wide-domain autorization

Good morning I'm trying to integrate the Google+ Domains API with my company domain but I'm facing some problems.
I'm trying the java approach following the quick start for java but after implement the code the response from the google server is :
Authenticate the domain for hugo.catarino#outsystems.com
Inserting activity
10/Set/2013 17:08:49 com.google.api.client.googleapis.services.AbstractGoogleClient <init>
WARNING: Application name is not set. Call Builder#setApplicationName.
Exception in thread "main" com.google.api.client.auth.oauth2.TokenResponseException:400 Bad Request
{
"error" : "access_denied"
}
at com.google.api.client.auth.oauth2.TokenResponseException.from(TokenResponseException.java:105)
at com.google.api.client.auth.oauth2.TokenRequest.executeUnparsed(TokenRequest.java:287)
at com.google.api.client.auth.oauth2.TokenRequest.execute(TokenRequest.java:307)
at com.google.api.client.googleapis.auth.oauth2.GoogleCredential.executeRefreshToken(GoogleCredential.java:269)
at com.google.api.client.auth.oauth2.Credential.refreshToken(Credential.java:489)
at com.google.api.client.auth.oauth2.Credential.intercept(Credential.java:217)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:858)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:410)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:343)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:460)
at com.google.plus.samples.quickstart.domains.DomainDelegation.main(DomainDelegation.java:160)
here is used authentication method and my variables:
private static final String SERVICE_ACCOUNT_EMAIL = "638852846577#developer.gserviceaccount.com";
private static final String SERVICE_ACCOUNT_PKCS12_FILE_PATH =
"src/com/google/plus/samples/quickstart/domains/05cab8e819cbd0a747b180c1f22fc93dba916b7b-privatekey.p12";
private static final String USER_EMAIL = "hugo.catarino#outsystems.com";
private static Plus authenticate() throws GeneralSecurityException, IOException {
System.out.println(String.format("Authenticate the domain for %s", USER_EMAIL));
HttpTransport httpTransport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
// Setting the sub field with USER_EMAIL allows you to make API calls using the special keyword
// 'me' in place of a user id for that user.
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(SCOPE)
.setServiceAccountUser(USER_EMAIL)
.setServiceAccountPrivateKeyFromP12File(
new java.io.File(SERVICE_ACCOUNT_PKCS12_FILE_PATH)).build();
// Create and return the Plus service object
Plus service = new Plus.Builder(httpTransport, jsonFactory, credential).build();
return service;
}
My main class has the following code like in the sample:
Plus service = authenticate();
String userId = "me";
String msg = "Happy Monday! #caseofthemondays";
System.out.println("Inserting activity");
// Create the audience of the post
PlusAclentryResource res = new PlusAclentryResource();
// Share to the domain
res.setType("domain");
List<PlusAclentryResource> aclEntries = new ArrayList<PlusAclentryResource>();
aclEntries.add(res);
Acl acl = new Acl();
acl.setItems(aclEntries);
// Required, this does the domain restriction
acl.setDomainRestricted(true);
Activity activity = new Activity()
.setObject(new Activity.PlusObject().setOriginalContent(msg))
.setAccess(acl);
activity = service.activities().insert(userId, activity).execute();
System.out.println(activity);
In domain cPanel the company defined for me the next scopes:
https://www.googleapis.com/auth/plus.circles.read
https://www.googleapis.com/auth/plus.circles.write
https://www.googleapis.com/auth/plus.me
https://www.googleapis.com/auth/plus.media.upload
https://www.googleapis.com/auth/plus.stream.read
https://www.googleapis.com/auth/plus.stream.write
My scope definition is:
private static final List<String> SCOPE = Arrays.asList(
"https://www.googleapis.com/auth/plus.circles.read",
"https://www.googleapis.com/auth/plus.circles.write",
"https://www.googleapis.com/auth/plus.me",
"https://www.googleapis.com/auth/plus.media.upload",
"https://www.googleapis.com/auth/plus.stream.read",
"https://www.googleapis.com/auth/plus.stream.write");
I'm a bit lost here , is there any way of debug this problem or know why is this access denied?
There are several things that you should check.
First, is the private key file that you downloaded from the Google APIs Console in the correct path with your code? This file is referenced by the following variable. This needs to tell the OAuth client library where to find the file.
private static final String SERVICE_ACCOUNT_PKCS12_FILE_PATH =
"/path/to/<public_key_fingerprint>-privatekey.p12";
It is very important that you do not rename the file.
Second, does your scope list in your code match the list of scopes set in the Admin console?
The configuration in the Admin console for your Google Apps domain, and the scopes provided in the request must be identical. Try adjusting the SCOPE variable in your code to be:
private static final List<String> SCOPE = Arrays.asList(
"https://www.googleapis.com/auth/plus.me",
"https://www.googleapis.com/auth/plus.circles.read",
"https://www.googleapis.com/auth/plus.circles.write",
"https://www.googleapis.com/auth/plus.media.upload",
"https://www.googleapis.com/auth/plus.stream.read",
"https://www.googleapis.com/auth/plus.stream.write");
In general, it is best to only request the scopes that you will need, rather than all scopes available.
Third, make sure that the client ID you generated is the one listed on the Admin console entry that specifies the scopes permitted.

Problems downloading a page updated everyday

I'm developing an application on GAE that fetches a web page and searches it for a link.
This page gets updated every morning, so a cron job is executed each morning every 15 minutes for a couple of hours, to obtain current day's page.
Here's the problem: if at the first execution of the cron job the application finds the older page (yesterday's one), it keeps fetching that one, although a new page is available at the same URL.
Seems that a cache is used somewhere, but I can't disable it.
The code that the application uses for downloading the page is simply Java I/O:
InputStream input = null;
ByteArrayOutputStream output = null;
HttpURLConnection conn = null;
URL url = new URL("http://www.page.url.net");
try {
conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(0);
conn.setUseCaches(false);
int httpResponseCode = conn.getResponseCode();
if (httpResponseCode == HttpURLConnection.HTTP_OK) {
input = conn.getInputStream();
output = writeByteArrayOutputStreamFromInputStream(input);
} else {
throw new IOException("response code " + httpResponseCode);
}
} finally {
if (input != null) {
output.close();
conn.disconnect();
}
}
What's wrong?
In order to avoid caching, I suggest to use this simple trick: add a "fake" query parameter to the end of the query string, for example if the page you are fetching is
http://www.page.url.net
add a parameter named dummy= so the url becomes:
http://www.page.url.net?dummy=2013-05-25
Just be sure the "dummy" paramater is not actually interpreted by the remote server.
Hope this helps.

Resources