I'm learning CasperJS and have been able to login to a website using fill() but haven't been able to using this.evaluate() or this.sendKeys()
What am I doing wrong with this.evaluate() & this.sendKeys()?
This works:
casper.then(function() {
this.fill('form[class="login-form"]', {
'session_key': 'username',
'session_password': 'password'
}, true);
});
However, neither of these do:
casper.then(function() {
this.evaluate(function(username, password) {
document.querySelector('input#login-email').value = username;
document.querySelector('input#login-password').value = password;
document.querySelector('input[value="Sign in"]').click();
}, 'username', 'password');
})
or
casper.then(function() {
this.sendKeys('input#login-email', 'username');
this.sendKeys('input#login-password', 'password');
this.click('input[value="Sign in"]')
})
Since your question is more general than specific, I will try to answer in the same vein.
fill and fillSelectors are there to quickly fill simple forms.
If you have javascript heavy websites, with events being triggered on actions, then you have SendKeys, which will try to trigger those events as they go.
Finally, if SendKeys does not do the job, you can always go with evaluate and trigger those events manually. If you open your browser console and inspect elements you want to make action on, you will see the events attached to them. From there, you can see if they are DOM events or JQuery events, so you can use document.querySelector or $ accordingly. Before coding anything, know that if you jump to your browser javascript console, any code that you execute there will be what you will end up having in your evaluate scope ; You can quickly test your code in your browser before applying it to your script.
I did not go in details, I just went through the surface of "fill() vs evaluate() vs sendKeys()" with my personal experience but to answer your question specifically, we do not have the page HTML so it is hard to tell. There would be many reasons why SendKeys would not work but not evaluate. In your evaluate scope, the selectors might be wrong or an event is missing.
Finally, as Artjom mentioned, for clicking it's always best to go with casper.click(selector)
Related
I'm a Back-end dev, and recently inherited a couple of legacy Apache Tapestry systems. My skills with Tapestry are null my knowledge on javascript medium.
I want to disable a submit button right before the submit is made to avoid multiple submits.
A very simple
$(document).ready(function () {
$("#form").submit(function () {
$("#submitbutton").attr("disabled", true);
return true;
});
});
approach wont do because the submit event is propagated before Tapestry does the client-side validation, so I could be disabling the button on a submint attempt that will fail validation.
On this question I learned that Tapestry also propagetes its own events, and if I could listen on tapestry:formprocesssubmit That would probably solve my problem.
I have my CreateContract.tml file with the form, fields and buttons that already work, I have my CreateContract.java file with
#Import(library = {
"context:js/jquery.mask.min.js",
"context:js/maintain-contracts.js",
"context:js/zone-overlay.js"},
stylesheet = "context:layout/zone-overlay.css")
And my maintain-contracts.js file with
$(document).ready(function () {
$("#form").on('tapestry:formprepareforsubmit', function () {
console.log("I want to arrive here!");
});
});
But it doesn't work.
On this mailing list thread I see people discussing very similar matters, but they go about listening on events on a different fashion, that I don't quite grasp.
Should I create the listener inside the initializer?
I'm reffering to the event as 'tapestry:formprepareforsubmit' instead of Tapestry.FORM_PREPARE_FOR_SUBMIT_EVENT because on both my maintain-contracts.js and my console the Tapestry variable is empty - why is that?
What about the .on versus .bind versus .observe trichotomy?
the first links's question was solved using ProptypeJS Class.create, but I think i dont have access to that.
I'm I going about that wrong?
Thank you, any help is appreciated.
Not an analysis of why your approach doesn't work, but a useful referral nonetheless:
Geoff Callender, creator of Tapestry JumpStart, has an excellent description of how duplicate form submissions can be avoided using a mixin.
See http://jumpstart.doublenegative.com.au/jumpstart/examples/javascript/creatingmixins1
After reading Tapestry's source code, i found out that the event is not called tapestry:formprepareforsubmit, but t5:form:prepare-for-submit, even though I found no documentation of that anywhere.
So
$(document).ready(function () {
$("#form").on('t5:form:prepare-for-submit', function () {
console.log("I want to arrive here!");
});
});
Works perfectly.
I'm working on a fairly simple form using crowd-html elements, which makes everything very simple. As part of our study, we want to see how workers interact with the form, so we have a bunch of basic JS logging. That is all prepared as a JSON and the idea is to log it using AWS API Gateway and AWS Lambda. The code all seems to work in unit tests, but not in the real form. I am trying to do this:
document.querySelector('crowd-form').onsubmit = function (e) {
if (!validateForm()) {
window.alert("Please check the form carefully, it isn't filled out completely!");
e.preventDefault();
} else {
let event_data = {
'specific_scroll_auditor': auditor_scrolled_pixels_specific.submit_callable(),
'specific_clicks_auditor': auditor_clicks_specific.submit_callable(),
'mouse_movements_total': auditor_mouse_movement_total.submit_callable(),
'on_focus_time': auditor_on_focus_time.submit_callable(),
'total_task_time': auditor_total_task_time.submit_callable(),
'focus_changes': auditor_focus_changes.submit_callable()
};
log_client_event('auditors', event_data);
post_event_log()
}
}
Note that the validation bit works, but the logging does not. I've tested post_event_log() on it's own, and that works just fine, so it seems like either 1) for some reason I never get to that else clause, or 2) the submission happens more quickly than I can call the logging functions. (but why, since the validation works?)
I also tried this, borrowed from the turkey code (https://github.com/CuriousG102/turkey) which was our inspiration.
$(window).ready(function () {
window.onbeforeunload = function () {
let event_data = {
'specific_scroll_auditor': auditor_scrolled_pixels_specific.submit_callable(),
'specific_clicks_auditor': auditor_clicks_specific.submit_callable(),
'mouse_movements_total': auditor_mouse_movement_total.submit_callable(),
'on_focus_time': auditor_on_focus_time.submit_callable(),
'total_task_time': auditor_total_task_time.submit_callable(),
'focus_changes': auditor_focus_changes.submit_callable()
};
log_client_event('auditors', event_data);
post_event_log()
}
});
That also doesn't work. I would prefer to do this in some simple way like what I have above, rather than completely rewrite the submit function, but maybe I have to?
your custom UI is placed inside a sandboxed iFrame by Ground Truth. It does that only for the real job, and not for previews (you're code might work while previewing the UI from AWS Console). The sandbox attribute on the iFrame goes like this
sandbox="allow-scripts allow-same-origin allow-forms"
Refer https://www.w3schools.com/tags/att_iframe_sandbox.asp for descriptions. Ajax calls are blocked regardless of the presence of allow-same-origin (not that you could change it in any way). See for a thorough explanation IFRAME sandbox attribute is blocking AJAX calls
This example might help.
It updates the onSubmit function to do some pre-submit validations.
https://github.com/aws-samples/amazon-sagemaker-ground-truth-task-uis/blob/master/images/keypoint-additional-answer-validation.liquid.html
Hope this helps. Let us know if not.
Thank you,
Amazon Mechanical Turk
I have a window-box with two buttons 'add' and 'close'. I need to test below scenario:
When clicked on 'add' button it throws error and the window remains open. I need to click on 'close' button to proceed.
I used below code:
if(element(by.xpath("xpath_of_error_box")).isEnabled())
{
element(by.xpath("xpath_of_close_button")).click();
}
But it throws below error:
No element found using locator: By(xpath, xpath_of_error_box)
Is there any way to handle this?
According to the error, it seems that your xpath locator didn't match any element. And according to the additional clarification in the question you could try:
element(by.xpath("xpath_of_error_box")).isDisplayed().then(isDisplayed => {
if (isDisplayed) {
// do what you need when it is visible
} else {
// if not then proceed
}
});
As it was pointed out, isEnabled might not be the proper method you should use in this case. If it seems that the element you try to find is always present in the dom, you might better try to check for its visibility using isDisplay instead.
An advice. It's not a good idea to use xpath locators in your tests, because this ties them to the html DOM structire of the web page you are observing. As we know, the UI happens to change often, which would make your tests to brake often as well. Although this is of cource a personal preference, it is such until you end up with tons of brocken tests after a single small change in the html.
If you need to check if an element is present you can use the following code:
if (element(by.xpath("yourXpath")).isPresent())
But your problem is not on your if code, your problem is that the xpath your are searching doesn't exist.
isEnabled() and isPresent() returns promise (not boolean) and have to be resolved.
isEnabled() could be only used for <button>.
You can use XPath all the time, don't listen to anyone.
PS. Of course it would be glad to see your HTML to check the correctness of your XPath.
I am trying to detect when an HBO Go movie has completed using javascript. Unfortunately, HBO Go uses Flash, and I have no Flash experience.
I noticed that when the movie ends, the Chrome javascript console shows this:
00:02:30:0596 TimeEvent.COMPLETE
(anonymous function) # VM12786:1
I followed VM12786:1 and found this:
try { __flash__toXML(console.error("00:02:30:0596 TimeEvent.COMPLETE")) ; } catch (e) { "<exception>" + e + "</exception>"; }
I'm not quite sure what either of these mean. Can someone briefly explain it? I have extensively googled, but haven't found anything that I understand.
And, is there any way that I can detect with javascript or jQuery that this has been triggered?
Here's a briefing on those JS bits:
try {
__flash__toXML(console.error("00:02:30:0596 TimeEvent.COMPLETE"));
} catch (e) {
"<exception>" + e + "</exception>";
}
The __flash__toXML function is a mechanism to allow the Flash program to communicate with the webpage via JavaScript (brief explanation here, unrelated article). It seems like that snippet is part of a larger section that handles the video ending event.
The weird stringy thing seems like a useless piece of code that is just there as a placeholder, but I would need to look at the context to understand it better. As it is, it does nothing.
Here's my answer to your question:
Unfortunately, there's no event you can capture for console actions directly. You would need to replace the functions with your own that trigger a custom event, and then handle that event. This article explains the process excellently. You would need to modify the internal intercept function to trigger an event on the main window, which you can handle in the traditional ways:
$(window).trigger("myapp.console.log");
Note: This may not work for content scripts, but that's advanced and depends on implementation. If you are using something injected into the browser, replacing the function will only affect the content script's sandbox.
I learned on StackOverflow that you can hijack the console functions, as in the example, where I've added an alert to the console.error function.
var conerr = console.error;
console.error = function()
{
alert("console error: " + arguments[0]); /* do stuff here */
return conerr.apply(console, arguments);
}
setTimeout(function() {console.error("00:02:30:0596 TimeEvent.COMPLETE");}, 1000);
Currently i'm experementing with the the chrome.fileSystem-Api and i was curious about the new EntryChangedEvent that was added in Version 38. But im writing because i do not really know how to receive this event in my app. I tried it like this, what obviously didn't worked :
chrome.fileSystem.chooseEntry({type: 'openDirectory'}, function(folder) {
if (!folder) {
output.textContent = 'No Folder selected.';
return;
}
folder.on("entrychangedevent",function(v){
console.log(v);
});
});
How do i have to change my code so that i really can use receive EntryChangedEvents?
Thanks!
Link to documentation:
https://developer.chrome.com/apps/fileSystem#type-EntryChangedEvent
I actually think that this feature is not implemented yet. I don't know why it is in the documentation, but if you look at the chromium source there is a function called chrome.fileSystem.observeDirectory (which has a callback that should get these events) but when looking at the implementation it just says:
bool FileSystemObserveDirectoryFunction::RunSync() {
NOTIMPLEMENTED();
error_ = kUnknownIdError;
return false;
}
I found this document which is a request for the API:
https://docs.google.com/document/d/1aW-37JOBZgoD2CIPvoBEgw6bog8gFSowpfqtDEKt5Vo/edit#heading=h.w8inspeo32bj
Anyways, great feature and will probably be available soon.
Three issues here:
It's not clear from the documentation what object this listener should be attached to. In your example, you have attached it to the DirectoryEntry representing a directory. While I don't know the answer, that sounds like it's probably wrong, as a DirectoryEntry is only a means for accessing a directory, and is not itself a directory.
The documentation says that this event is fired for only certain filesystems, and I guess neither of us knows whether it is even effective for whatever file systems we're testing with.
In your example, even if the code were right and the event were enabled, you don't have any changes to the directory, so the event wouldn't fire.