How to execute JavaScript in HtmlUnit without running page scripts - java

So, I'm having a bit of an issue in HtmlUnit
I'm trying to run a bit of Javascript on Facebook's message page to send someone a message. The JavaScript I'm using is this, and it runs just fine in the browser's console:
document.getElementsByName("message_body")[0].value = "test"; var e = document.createEvent('KeyboardEvent'); e.initKeyEvent('keydown', true, true, window, false, false, false, false, 13, 0); document.getElementsByName("message_body")[0].dispatchEvent(e);
It first selects the message body textarea by its name, types in "test", and then presses the enter key, sending the message.
When trying to use the executeJavaScript() in HtmlUnit method it fails, but not even because of my code.
I'm receiving this error:
net.sourceforge.htmlunit.corejs.javascript.EvaluatorException: Java class "com.gargoylesoftware.htmlunit.ScriptException" has no public instance field or method named "message". (https://fbstatic-a.akamaihd.net/rsrc.php/v2/yj/r/zt0nwbhPchP.js#36)
...which appears to be an error in Facebook's JavaScript, not mine.
The problem? I can't run any of my own JavaScript on the page without HtmlUnit seeing Facebook's code and breaking with an exception.
Is there any way I could circumvent this? Also, if the script works perfectly fine in the browser, why would it break HtmlUnit?
Thanks!

ok, so the question is two years old, but in my case if I set
webClient.getOptions().setThrowExceptionOnScriptError(false)
I can work around it.

Related

How to handle authentication popup in Chrome with Selenium WebDriver using Java

I am trying to handle an authentication pop-up in one of my new Webdriver scripts. I have a working solution for IE, but I am struggling with Chrome. IE was as simple as following the advice on [this page]:How to handle authentication popup with Selenium WebDriver using Java. That thread doesn't show a great solution for Chrome, although several commentors point out, that the solution does not work for Chrome. The problem is, when you try to do the below code on Chrome, the login popup isn't an Alert.
WebDriverWait wait = new WebDriverWait(driver, 10);
Alert alert = wait.until(ExpectedConditions.alertIsPresent());
alert.authenticateUsing(new UserAndPassword(**username**, **password**));
It's not a windows level () authentication pop-up, the web page is simply password protected. I know there are several other instances of this question on Stack Overflow, but I don't see any more recently than 2 years old. I am hoping there is a better solution now in 2017. Thanks in advance.
May be helpful for others to solve this problem in chrome with the help of chrome extension. Thanks to #SubjectiveReality who gave me this idea.
Sending username and password as part of url like https://username:password#www.mytestsite.com may be helpful if same server performs both authentication and hosts the application. However most corporate applications have firmwide authentications and app server may reroute the request to authentication servers. In such cases, passing credentials in URL wont work.
Here is the solution:
#Step1: Create chrome extension#
Create a folder named 'extension'
Create a file named 'manifest.json' inside 'extension' folder. Copy below code into the file and save it.
{
"name":"Webrequest API",
"version":"1.0",
"description":"Extension to handle Authentication window",
"permissions":["<all_urls>","webRequest","webRequestBlocking"],
"background": {
"scripts" : ["webrequest.js"]
},
"manifest_version": 2
}
Create a file named 'webrequest.js' inside 'extension' folder and copy paste below code into the file and save it.
chrome.webRequest.onAuthRequired.addListener(
function handler(details){
return {'authCredentials': {username: "yourusername", password: "yourpassword"}};
},
{urls:["<all_urls>"]},
['blocking']);
Open chrome browser, go to chrome://extensions and turn on developer mode
Click 'Pack Extension', select root directory as 'extension' and pack extension. It should create a file with extension '.crx'
#Step2: Add extension into your test automation framework #
Copy the .crx file into your framework
Configure your webdriver creation to load the extension like
options.addExtensions(new File("path/to/extension.crx"));
options.addArguments("--no-sandbox");
Invoke your webdriver and application URL
You wont see the authentication popup appearing as its handled by above extension
Happy Testing!
References:
http://www.adambarth.com/experimental/crx/docs/webRequest.html#apiReference
https://developer.chrome.com/extensions/webRequest#event-onAuthRequired
chrome.webRequest.onAuthRequired Listener
https://gist.github.com/florentbr/25246cd9337cebc07e2bbb0b9bf0de46
*edit Chrome no longer supports this.
Isn't that a "restricted" pop-up that can be handled by prepending the address with username and password?
Instead of driver.get("http://www.example.com/"); go for driver.get("http://username:password#www.example.com");.
Updated answer of the solution provided by #Bhuvanesh Mani
manifest.json
{
"name": "Webrequest API",
"version": "1.0",
"description": "Extension to handle Authentication window",
"permissions": [
"webRequest",
"webRequestBlocking",
"<all_urls>"
],
"background": {
"scripts": [
"webrequest.js"
]
},
"manifest_version": 2
}
webrequest.js
chrome.webRequest.onAuthRequired.addListener(function(details){
console.log("chrome.webRequest.onAuthRequired event has fired");
return {
authCredentials: {username: "yourusername", password: "yourpassword"}
};
},
{urls:["<all_urls>"]},
['blocking']);
Not certain why the '--no sandbox' option is required, but for me this is not required.
I did need to perform a registry edit to allow adding extensions since this is disabled with a corporate AD policy:
Open regedit.exe as admin
navigate to
Computer\HKEY_USERS\
Change the REG_SZ value that is now set to * to for example -.
restart the chrome instance in which you want add extensions to.
The only difference with the original answer is the url's that also need to be present in the permissions.
extra's
if you want to see console output, turn on developer mode and click on the Inspect views background page for your extension in the extensions screen in Chrome
I know your situation is Java, but this might be helpful. I was able to get past the alert using this approach in C#:
// I am using a static instance of the driver for this.
Driver.Instance.Navigate().GoToUrl(url);
var alert = Driver.Instance.SwitchTo().Alert();
alert.SendKeys($"{Driver.user_name}" + Keys.Tab + $"{Driver.user_password}" + Keys.Tab);
alert.Accept();
Driver.Instance.SwitchTo().DefaultContent();
I then utilized a test user account as the values of the user_name and password.
Selenium 4 supports authenticating using Basic and Digest auth . It's using the CDP and currently only supports chromium-derived browsers
Java Example :
Webdriver driver = new ChromeDriver();
((HasAuthentication) driver).register(UsernameAndPassword.of("username", "pass"));
driver.get("http://sitewithauth");
Note : In Alpha-7 there is bug where it send username for both user/password. Need to wait for next release of selenium version as fix is available in trunk https://github.com/SeleniumHQ/selenium/commit/4917444886ba16a033a81a2a9676c9267c472894

Spring controller method called twice

I'm making a Spring MVC web app.
The problem is that on single method is called twice and I don't know why.
#RequestMapping(value="/profile/{id}", method = RequestMethod.GET)
public String displayUserProfile( #PathVariable String id) {
System.out.println("asdasddsasd");
return "account/userProfile";
}
I commented many line from this method, but is still not working. Also tried to return other view..no good luck.
In console(ulr requests are written):
/demo/account/profile/f91b3a38-6921-41e0-98b7-58dff5cb1152
asdasddsasd
/demo/account/profile/0
asdasddsasd
After the second call of tihs method, it's going to my view
Any other method work fine.
Does anyone know what's the problem here?
*I also read similar question from here..nothing helped
LE: what I also said in the comments.
What is funny is that, if I set o model to the view, on the second call of the method, my view get's the model from the first call. (on the second call, with id 0, the model is null)
I have also observed one GET request causing the controller method to execute twice. The problem occurred when requesting the service using a Chrome browser (the problem did not occur when using Postman). In my case the culprit was the JSONView Chrome extension.
I determined the cause by using the Network tab of the Chrome developer tools. It showed my GET service being requested two times. The second request was initiated by content.js, which is a JavaScript file bundled with JSONView.
After I disabled the JSONView extension, a GET request through Chrome would cause the controller method to execute only once.
I experienced this called-twice phenomenon because BrowserSync replayed HTTP requests in each open BrowserSync browser window.
I finally got some time to find a solution here.
Tried many things, but it didn't worked.
I replaced #PathVariable with #RequestParam and the URL is not accessed twice :)
Had the same problem.
Eventually I found that I have a null in a background-image url like so:
style="background-image: url(null);"
that caused to send another GET with a path variable null.
I have the same problem and find a lot of solution and finally I found the simple reason. It's in my html template css: background:url() .
This cold will run the same url again. So I just remove it out or put url in the bracket and it works.
Sounds like an issue on client side.
Open up your browser, enter <host/port/whatever_you_need_to access_the_app>/demo/account/profile/f91b3a38-6921-41e0-98b7-58dff5cb1152
and check the logs. The chances are that you'll see only one entry
Now run your client code and check network requests to the service. If you're call the controller from the browser like Chrome F12->Network tab should help.
I know it's a kind of obvious, but I think there is nothing really "unusual" in this controller, so it should be more at the level of general flow. In this case maybe it's the best to trace the HTTP traffic and see how many/when/how does it generate requests to your controller.
This might also occur due to one more reason. Because i found samething and observed following.
1st time its when your request processed and you see println statement in Console.
And if you refresh browser at method request of controller method ( example http://localhost:8080/DemoMVC/add?***) each refresh your tomcat processes request again and you get same println statement in console.
Perhaps this is too late. However, I still face these issues and forget the solution every time.
In case you are using any JS library like Angular or React then in your service call observe the response as well.
Here is a code snippet
return this.http.get<User>(`${this.resourceUrl}/activate`, { params: options, observe: 'response' })
.pipe(
filter((response: HttpResponse<User>) => response.ok),
map((response: HttpResponse<User>) => response.body),
catchError(error => {
return of(error)
})
);
The key area to focus is { params: options, observe: 'response' }
I had a controller which was listening to localhost/ and a get method which matched on a path variable something like this:
#GetMapping("/{foo}")
String get(#PathVariable(required = false) String foo)
{
return "hello world";
}
And the problem was, that after calling localhost/ I got the first call, and after that, I got the second call for the favicon.
The same would be true if you would define a context root.

How to make the control to wait in javascript till the call made to applet gets response which ideally works in JRE1.6V?

I have the below code which usually runs good with JRE 1.6.32 but when we upgraded to JRE 1.7.0_15 the call to applet is not fetching any response .
I even tried to use setTimeout() but it is not working , is their any way to get the response from the applet in JRE 1.7V .??
Code :
openPlsWait();//-->**Will open a popup showing the user to wait**
var Refresh = document.Grid.retry(datesIncreament,aForm.txt_retry.value);//**Call to applet where it will wait for the boolean response value.**
if(Refresh)
{
parent.frames["main"].document.OnePlusCal.refresh();//upon receiving the response the applet will refresh
}
closePlsWait();//**Close the opened popup**
Yes there is:
Sign you applet with an official certificate
Set the attributes are correctly set
See the LiveConnect (JavaScript<->Java Applet) changes

JQuery unresponsive script error

I have more than six functions like the following retrieving data to html page via server and update html which continues to run all the time when the web page is viewed. The Issue I'm having is after a while the web page pops up a warning as,
Alert Popup Warning in Firefox
A script on this page may be busy, or it may have stopped responding.
You can stop the script now, or you can continue to see if the script
will complete.
Script: "http://../javax.faces.resource/jquery-1.7.2.js?ln=js:3983"
After getting this warning the web page functionality gets unresponsive, Is there a solution to this problem? Is it because of a issue in the way I have coded? Why is it pointing to jquery library?
Code:
function myDatapoll(){
$.ajax({
type : "GET",
url : '../jsonData/',
dataType : "json",
async : true,
cache : false,
success: function(data) {
if(data!=null){
if($("span[id='accBal-"+data.pID+"']").length>0){
$("span[id='accBal-"+data.pID+"']").text(parseFloat(data.accBal).toFixed(2));
}else{
$("#cash").html('<span id="accBal-'+data.pID+'">'+parseFloat(data.accBal).toFixed(2)+'</span>');
}
}
setTimeout('myDatapoll()',1000);
},
error : function() {
}
});
}
Just a shot: put a setInterval outside your function instead of the setTimeout:
setInterval('myDatapoll()',1000);
function myDatapoll(){
//same as before but remove the setTimeout
}
Do not use setInterval in this case. Using setInterval, myDatapoll() executes every 1000 ms regardless the request is complete or not. It will only add to the trouble. The setTimeout approach you have implemented is the right way to do it. I am not sure why you are getting that exception in Firefox.
Are you sure about the dataType? You are requesting a xhtml file and the data type is set to "json"?

how to make error page (http 500) work in IceFaces?

Using Icefaces 2, if an error occurs during execution of an action method on a standard (=not icefaces) h:commandButton, it just seems the button has no action. No error page is displayed, although it is configured to do so in web.xml.
I can make it work by surrounding the tag with
<f:ajax disabled="true">...</f:ajax>
But I'd want to either disable this automatic ajax from Icefaces (see question How to disable unsollicited ajax on standard components (h:commandButton) while using Icefaces? ), or make the error page work anyway.
JSF implementation is Mojarra 2.1 which comes with Glassfish 3.1.
The basic problem is that Icefaces captures the submit button and puts ajax in it. I think this is simply bad behavior: I understand that something like that could happen in a ice:commandButton or even under ice:form, but it happens to h:commandButton to h:form as well. This can be disabled, as per http://wiki.icefaces.org/display/ICE/Configuration , by setting autorender context parameter to false in web.xml . But then, you need to explicitely enable this behavior on every icefaces form (you get an error otherwise).
Anyway, as stated here: http://wiki.icefaces.org/display/ICE/Handling+Exceptions, putting this script in the page basically solves the problem:
//Assign your error handling function to a variable
var iceErrorCallback = function iceHandleError(statusCode, responseTxt, responseDOM) {
//Handle all errors by simply redirecting to an error page
window.location.href = "./generalError.xhtml";
}
//Safely check if ICEfaces is available
if (ice) {
//Turn off the popups as we plan to handle this ourselves
ice.configuration.disableDefaultIndicators = true;
//Register your error handler as a callback
ice.onServerError(iceErrorCallback);
}
Update: I had to patch some Icefaces javascript for it to work, see http://jira.icefaces.org/browse/ICE-6546 . I know realize normal Icefaces behavior is displaying a popup with the error, which didn't happen.

Categories