I am trying to click a login button using HtmlUnit 2.23, using either DomElement or executeJavaScript but none of it works. Is there any other way to get it working? This is the code:
#Test
public void noLogin() throws Exception {
final WebClient webClient = new WebClient(BrowserVersion.BEST_SUPPORTED);
//see http://stackoverflow.com/questions/3600557/turning-htmlunit-warnings-off/18563576#18563576
java.util.logging.Logger.getLogger("com.gargoylesoftware").setLevel(Level.OFF);
//see http://stackoverflow.com/questions/18556200/htmlunit-button-click
webClient.getOptions().setJavaScriptEnabled(true);
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
webClient.setAjaxController(new NicelyResynchronizingAjaxController());
final HtmlPage loginPage = webClient.getPage("https://sandbox.paydirekt.de/account/#/login");
loginPage.getElementById("username").setAttribute("value", "no");
loginPage.getElementById("password").setAttribute("value", "login");
//final HtmlPage welcomePage = ((DomElement)loginPage.getFirstByXPath("//button[#type='submit']")).click();
//see http://stackoverflow.com/questions/14474580/use-htmlunit-doesnt-work-button-click
//ScriptResult result = loginPage.executeJavaScript("javascript:document.getElementsByName('loginForm')[0].submit();");
ScriptResult result = loginPage.executeJavaScript("javascript:document.getElementsByClassName('loginBox__loginButton button button--full')[0].click()");
Page page = result.getNewPage();
if (page.isHtmlPage()) {
HtmlPage welcomePage = ((HtmlPage)page);
System.out.println(welcomePage.asText());
Assert.assertTrue(welcomePage.asText().contains("Benutzername oder Passwort nicht korrekt."));
}
webClient.close();
}
You can also use the connection wrapper that HTMLUnit offers to check for each request and response manually. Here is an example
new WebConnectionWrapper(webClient) {
public WebResponse getResponse(WebRequest request) throws IOException {
WebResponse response = super.getResponse(request);
if (request.getUrl().toExternalForm().contains("THE URL YOU WANT TO CHECK")) {
String content = response.getContentAsString("UTF-8");
//CHECK CONTENT HERE
WebResponseData data = new WebResponseData(content.getBytes("UTF-8"), response.getStatusCode(),
response.getStatusMessage(), response.getResponseHeaders());
response = new WebResponse(data, request, response.getLoadTime());
}
return response;
}
};
Related
I'm making an Android app using webview.
The app can print out receipts. What I want to do is when the printer is not working, alert box shows up to tell the printer isn't working, and return false to the form's onsubmit event to prevent form from being submitted.
Java code:
public class JSKicker {
#JavascriptInterface
public void callPrint(final String argumet) {
Thread thread = new Thread(new Runnable() {
public void run() {
int nRtn;
connectionNum = myPrinter.Connect("000.000.0.000");
if(connectionNum < 0){ //Printer not working
webview.post(new Runnable() {
#Override
public void run() {
String script = "alert('Printer Error'); return printer_connection = false;";
webview.evaluateJavascript(script, new ValueCallback<String>() {
#Override
// I can't figure out what to do here...
});
}
});
}else{ //Printer is working properly
connectionNum = myPrinter.SetLocale(8);
strText = argument;
nRtn = myPrinter.PrintText(strText, "SJIS");
nRtn = myPrinter.PaperFeed(64);
nRtn = myPrinter.CutPaper(1);
myPrinter.Disconnect();
}
}
});
thread.start();
}
JavaScript in header:
<script type="text/javascript">
function gate(){
jQuery.ajax({
url:'/cart_info.php',
type:'GET'
})
.done( (data) => {
window.JSKicker.callPrint(data);
})
if (printer_connection = false) {
return false;
}else{
return true;
}
}
</script>
HTML form tag:
<form method="post" id="order_form" onsubmit="return gate();">
How can I get this work?
Could you do it thru WebView.evaluateJavascript()?
https://developer.android.com/reference/android/webkit/WebView.html#evaluateJavascript(java.lang.String,%20android.webkit.ValueCallback%3Cjava.lang.String%3E)
So with that you could send simple CustomEvent to document in WebView
webView.evaluateJavascript("document.dispatchEvent(new Event('printer_error', { details: "No printer found!" }));");
and in JavaScript you can hook listener for your custom event to react.
document.addEventListener('printer_error', e => alert(e.details));
Didn't test this so might be that at least evaluateJavascript() needs callback function.
WebSocket can solve your problem.
WebSockets provide a persistent connection between a client and server that both parties can use to start sending data at any time. The client establishes a WebSocket connection through a process known as the WebSocket handshake.
Its very straight forward and easy to implement.
You can follow referrer links for more details:-
JAVA WebSocket:- WebSocket using Spring Boot, WebSocket using Simple JEE
Browser WebSocket(JavaScript):- WebSocket API
In Android ,if you want webview pass value to JavaScript.
First,you need to set the webview enable the JavaScript,
private WebView mWebView;
void onCreate(){
mWebView = findViewById(R.id.webview);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setSupportZoom(false);
}
And ,in you want do some thing code
if(connectionNum < 0){ //Printer not working
// I need to do something here to send a message that the printer isn't working to JS.
//In thread can not use mWebView,should send message to MainThread to do
// mWebView.loadUrl("javascript:javaCall()");
Message msg = new Message();
msg.what = 1;
myHandler.sendMessage(msg);
//myHandler can be your MainThread send to here
}
And where the mWebView created in your code, be in main thread ,you can use the
Handler to deal with the message sended to here.
private Handler myHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
// this 1 is just thread send to here
if (msg.what == 1) {
//and here can do the webview UI method
mWebView.loadUrl("javascript:javaCall()");
}
}
};
the javaCall() is where you JacaScript invoke method,in javaScript you can writre like this:
<script language="javascript">
function javaCall(){
alert("Printer Error");
//other thing you can do
}
</script>
if you have problem ,you can refer to the official document.
public void loadUrl (String url)
Loads the given URL.
Also see compatibility note on evaluateJavascript(String, ValueCallback).
webview use link
How to scrape 'handlerbars.js' javascript template in htmlunit 2.21? I try to execute this, but this message shown:
'text/x-javascript-template' is not javascript.
and script does not execute. I execute command page.asXml().
Output text is nothing. Do you know dependency for execute javascript template in Htmlunit? Please help.
This Code
HtmlUnit Config
webClient = new WebClient(BrowserVersion.CHROME);
webClient.getBrowserVersion().setBrowserLanguage("ko-kr");
ConfirmHandler okHandler = new ConfirmHandler() {
#Override
public boolean handleConfirm(Page page, String message) {
logger.info("[Confirm] " + message);
return true;
}
};
AlertHandler alertHandler = new AlertHandler() {
#Override
public void handleAlert(Page page, String message) {
logger.info("[Alert] " + message);
}
};
webClient.setRefreshHandler(new ImmediateRefreshHandler());
webClient.getOptions().setGeolocationEnabled(true);
webClient.getOptions().setRedirectEnabled(true);
webClient.getOptions().setUseInsecureSSL(true);
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setJavaScriptEnabled(script);
webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.getOptions().setTimeout(0);
webClient.setAjaxController(new NicelyResynchronizingAjaxController());
webClient.setConfirmHandler(okHandler);
webClient.setAlertHandler(alertHandler);
page move code
page = webClient.getPage("https://promotions.expediapartnercentral.com/promotions/manageroomandrate.html?htid=" + siteIdx);
webClient.waitForBackgroundJavaScript(1000);
page.asXml() repsonse is empty(script is not execute)
I'm trying to use HtmlUnit to get data fom a web site,
so far i managed to enter the data needed in order to login (username & password).
The problem begins with the fact that the website login form dosent have a submit button, instead there is an href that has an onClick JavaScript function (onclick="login_submit())
that verify data and then call window.location = "index.php";
So i tried clicking the href using:
HtmlAnchor anchor = page.getAnchorByText("כניסה");
page = anchor.click();
and tried:
page.executeJavaScript(javaScriptCode);
but the page variable dosent get the expected page, it got the same url as before clicking and there is no redirection. Once the login_submit() function is called there is a label that indicates " login.." but nothing happens from there.
Here is the code:
// javascript login_submit() -- this is not my website and not my JS code so ive deleted some things:
function login_submit()
{
if(!LOGIN_SUBMIT_PROCESSED)
{
var approved = true;
var admin_user_username_field = document.getElementById('admin_user_username');
var admin_user_username_error = document.getElementById('admin_user_username_error');
var admin_user_password_field = document.getElementById('admin_user_password');
var admin_user_password_error = document.getElementById('admin_user_password_error');
admin_user_username_field.className = "login_form_field_input_text";
admin_user_username_error.style.display = 'none';
admin_user_password_field.className = "login_form_field_input_text";
admin_user_password_error.style.display = 'none';
if(admin_user_username_field.value.length == 0)
{
//do something
}
if(admin_user_password_field.value.length == 0)
{
//do something
}
if(approved)
{
LOGIN_SUBMIT_PROCESSED = true;
document.getElementById("login_form_options").style.display = "none";
document.getElementById("login_form_process").style.display = "";
var http_request = new XHConn();
http_request.connect(
"login_submit.php?cache="+string_unique(),
"POST",
"form_anti_bot_code="+encodeURIComponent(form_anti_bot_code_field.value)
+ "&admin_user_username="+encodeURIComponent(admin_user_username_field.value)
+ "&admin_user_password="+encodeURIComponent(admin_user_password_field.value),
function(response,callback_data)
{
if(response.readyState == 4)
{
if(response.status == 200)
{
//alert(response.responseText);
try
{
var json_response = JSON.parse(response.responseText);
if(json_response["error_code"] == "0")
{
window.location = "index.php";
}
else
{
//do something
}
}
catch(error)
{
alert(error);
}
}
LOGIN_SUBMIT_PROCESSED = false;
}
},
null
);
}
}
}
Java code:
public static void main(String[] args) throws Exception {
WebClient webClient = new WebClient();
webClient.getOptions().setJavaScriptEnabled(true);
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.getOptions().setCssEnabled(true);
//webClient.getOptions().setUseInsecureSSL(true);
webClient.getOptions().setRedirectEnabled(true);
HtmlPage page = (HtmlPage) webClient
.getPage(url);
HtmlForm form = page.getFormByName("login_form");
form.getInputByName("admin_user_username").setValueAttribute("XXXXX");
HtmlInput passWordInput = form.getInputByName("admin_user_password");
passWordInput.removeAttribute("disabled");
passWordInput.setValueAttribute("XXXXXX");
HtmlAnchor anchor = page.getAnchorByText("Login");
page = anchor.click();
System.out.println(page.getBody().asText());
webClient.close();
}
I know for a fact after some testing that the login data is ok, href is clicked and there is an indicator that login is being proccesed.
the main problem is that its not redirecting and dont get the "index.php" page.
Try this and it should do the trick:
WebWindow window = page.getEnclosingWindow();
This might do the trick:
final HtmlPage page2 = page.getElementById("Login_Button").click();
This question already has an answer here:
How to check for an unique user with jQuery Ajax in Struts 2?
(1 answer)
Closed 6 years ago.
I'm building a web app using Struts2 as a framework. As the title suggest, I'm attempting to check availability of a username using an AJAX call (open to other suggestions if there is something easier that accomplishes the same result.)
Right now I'm having two issues:
Request is null in my doPost function.
Even if I set uname to a string, nothing happens.
Here is what I have for code.
Login.jsp
<s:form action="login.action" method="post" data-parsley-validate="">
<s:textfield name="user.username" key="Username" id="username" onchange="checkUsername()"/><span class="status"></span>
<s:submit method="doTheThing" align="center" onclick="hide()"/>
</s:form>
Javascript
function checkUsername(){
var uname = $(username).val();
if (uname.length > 3) {
$(".status").html("Checking availability...");
$.ajax({
type : "POST",
url : "usernameCheck.action",
data : "uname=" + uname,
success : function(msg) {
$(".status").ajaxComplete(
function(event, request, settings) {
$(".status").html(msg);
});
}
});
}
else {
$(".status").html("username should be at least 3 characters");
}
}
check.java
public class check extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ActionSupport connectionSupport = new ActionSupport();
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
Connection connection = null;
String URL = "172.ExampleIP";
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection(URL, "user","pass");
String uname = request.getParameter("user.username");
PreparedStatement ps = connection.prepareStatement("select username from users where username=?");
ps.setString(1, uname);
ResultSet rs = ps.executeQuery();
if (!rs.next()) {
out.println("<b>" + uname + "</b> is avaliable");
} else {
out.println("<font color=red><b>" + uname + "</b> is already in use</font>");
}
out.println();
} catch (Exception ex) {
out.println("Error ->" + ex.getMessage());
} finally {
out.close();
}
}
public void doGet()
throws ServletException, IOException {
doPost(ServletActionContext.getRequest(), ServletActionContext.getResponse());
}
}
Struts.xml
<action name="usernameCheck" class="java.com.my.package.check" method="doGet"></action>
I'm not sure if this is important information, but the form is on a JQuery modal box.
I found my solution. I changed my java class to extend ActionSupport based on Andrea's suggestion. I changed my struts action result to be of type stream.
<action name="usernameCheck" class="java.com.my.package.check" method="doGet">
<result type="stream">
<param name="contentType">text/html</param>
<param name="inputName">stream</param>
</result>
</action>
I added the following to my java class
private InputStream stream;
public InputStream getStream() {
return stream;
}
And changed my JavaScript success function to the following:
success : function(msg) {
$(".status").html(msg);
}
Thank you all for all the input.
I am trying to load data into android webview using
webview.loadDataWithBaseURL("", htmlcontent, "text/html", null, "");
a method returns htmlContent from a StringBuilder which populates html data.
I have enabled javascript and set webChromeClient as follows
webview.getSettings().setJavaScriptEnabled(true);
webview.setWebChromeClient(new WebChromeClient());
webview.addJavascriptInterface(new JSClass(), "Android");
my interface to javascript:
class JSClass {
public void getHTMLContent(String html)
{
Log.i(Global.TAG, "HTMLContentReceived: "+html);
}
}
and my javascript in html page:
<script type="text/javascript">
var ele = document.getElementsByClassName('test');
for(var i=0;i<ele.length;i++){
ele[i].onclick = function(){
window.Android.getHTMLContent(this.innerHTML);
}
}
</script>
but somehow the javascript is not returning any value.
It works fine with loadData(url) where url is a simple webpage in assets folder
Please help
Thanks in advance
You don't have any baseURL to use, since you're loading a dynamical generated HTML.
For this reason webview.loadData(htmlcontent, "text/html", null); should be more than enough.
Javascripts don't throw any exceptions in Java code. Remember that JS is not that type-safe/strict as Java code ... My way of doing is to put logs between sensitive Javascript calls to see if that line passes and to check values. Since you didn't provide the HTML, I would setup the WebChomeClient and override the onConsoleMessage:
webview.setWebChromeClient(new MyChromeClient());
private class MyChromeClient extends WebChromeClient {
#Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
String message = consoleMessage.message() + " -- line " + consoleMessage.lineNumber();
switch (consoleMessage.messageLevel()) {
case ERROR:
logErrorMessage(message);
break;
default:
logInfoMessage(message);
break;
}
return true;
}
private void logInfoMessage(String message) {
Log.i("JSTag", message);
}
private void logErrorMessage(String message) {
Log.e("JSTag", message);
}
}
From your JavaScript you would then call for example: console.log('check my value:' + (ele != null)). More info on this here.
Looking at your JavaScript code, I can't understand to what points this.innerHTML.