Using GEB, how can I very text and click OK in an alert box - webdriver

I have a basic alert box with OK or Cancel options
Using selenium, it was easy to use alert.getText() and alert.accept. How can I handle this same scenario using GEB?
It looks like I can verify the text using withConfirm, but I can't figure out how to click the OK button.
assert withConfirm(true) { $("input", name: "showConfirm").click() } == "Do you like Geb?"

The code you have shown us should work, you have copied it straight from the Geb manual.
The assertion will check the text in a pop up following a click action on a html element. In the case below (the code you pasted) when an html element with the name "showConfirm" is clicked, assert that a pop up is displayed with the text "Do you like Geb?".
assert withConfirm(true) { $("input", name: "showConfirm").click() } == "Do you like Geb?"
So you need to change the code to relate to whatever element action causes your pop up to appear:
assert withConfirm(true) { $("input", name: "thisIsTheNameOfMyElementThatWillCauseAPopUpToAppear").click() } == "Are you sure?"
Note that the Geb AlertAndConfirmSupport class that deals with alert and confirm dialog methods should actually prevent the popup from being displayed.

The answer is the ...(true) part.
withConfirm(true) { performSomeAction} == "Some expected text" is loosely equivalent to -
performSomeAction
getAlert().text() == "Some expected text"
getAlert().accept()
And on the other side of the coin withConfirm(false) { performSomeAction} == "Some expected text" is loosely equivalent to -
performSomeAction
getAlert().text() == "Some expected text"
getAlert().dismiss()
I say loosely equivalent here because as mentioned by #Rushby Geb deals with withConfirm blocks by intercepting the alert and not displaying it.

Related

Validate Image on Web Page Using Geb and Spock

I'm new to using geb and spock, but I'm trying to validate an image displayed on a webpage when I only have the view-source of the code. Any advice is appreciated! I modeled this code off of a link test I previously wrote, so I'm certain I'm missing something. An example of my page file is:
// code not included where I have defined the url/etc. Below is content
someImage { $("img", file: "image-logo.png") }
And an example of my spec page is:
def "Valid image"() {
given: "an image checker"
to SomePage
when:
someImage.hover()
then:
verifyAt()
You can validate that the image styling is set to displayed, any content that has the css property display: none cannot be interacted with via the webdriver API.
I have experienced some issues with using the isDisplayed method on navigator objects in Geb so I would do the following:
Where you define the page content add a method for checking the content can be interacted with (therefore is set to displayed):
someImage { $("img", file: "image-logo.png") }
Boolean contentDisplayed(Navigator content) {
content
}
Then your test will look like this:
def "Valid image"() {
given: "an image checker"
to SomePage
when:
someImage.hover()
then:
contentDisplayed(someImage)
its worth noting here that simply accessing the .hover method here you are validating that the image is displayed as far as the css is concerned. So you could simplify the test to:
def "Valid image"() {
when: "an image checker"
to SomePage
then:
contentDisplayed(someImage)

How to clear the Output message on a Submit button click using JavaScript

Hi Everyone out there..!!
I'm Facing a serious issue on clearing the retrieved message.
Flow of My project:
I'm having four text boxes and one submit button in my .aspx page.
And the four text boxes are required field.
If i give values in all the text boxes and click submit button i am getting the desired output.
This is the flow of my project.
Problem:
Now the problem is i don't have clear button in my screen.
I just clear a value from one of the text box and now I am clicking submit button.
It throws the required field validator error message as expected.
But the output from the previous execution is not getting cleared in this click event.
Expected:
I want the required field validator to throw the error and also the Output i got from the previous execution should be cleared.
This is the code i have tried
<script>
function hide()
{
document.getElementById('pnlResult').style.display = 'none';
}
</script>
I have tried this script in submit button OnClientClick() event
the problem in this is i have set required field validator for all the text but there is no value in one of the text box but it does execution and fetches me the result that
"no record is found"
Actually since one of the text box field is empty it should not do the execution at all.
You need to Put your result in particular panel and then you can hide the panel.
<script>
function hide() {
if (document.getElementById("<%=textbox1.ClientID%>").value == "" || document.getElementById("<%=textbox3.ClientID%>").value == "" || document.getElementById("<%=textbox3.ClientID%>").value == "" || document.getElementById("<%=textbox4.ClientID%>").value == "") {
var panel = document.getElementById("<%= pnlResult.ClientID%>");
if (panel) {
document.getElementById("<%=pnlResult.ClientID%>").style.display = 'none';
}
return false;
}
return true;
}
</script>
Now you need to call this script in submit Button Onclientclick

Ext-JS Html Editor get selected text

I am trying to insert a button into HtmlEditor's ToolBar. Button should get selected text by mouse or keyboard and add '#' character at the start of that selected text for locating it as a url.
As i understand the best solution is creating a plugin for adding buttons into html editor toolbar. I found creation codes but the problem is; how can i get selected text? Ext-js version 2.2
And there is the code that provides to create a plugin for html editor toolbar button:
Ext.ns('Ext.ux.form.HtmlEditor');
Ext.ux.form.HtmlEditor.NewLine = Ext.extend(Ext.util.Observable, {
init:function (cmp) {
this.cmp = cmp;
this.cmp.on('render', this.onRender, this);
},
onRender:function () {
this.cmp.getToolbar().addButton([
{
iconCls:'newline', //your iconCls here
handler:function () {
this.cmp.insertAtCursor('<br> ');
},
scope:this
}
]);
}
});
You can get the selected text like this: window.getSelection()
That gives you a Selection object. If you want to get the text only: window.getSelection().toString()
but if you want to make stuff bold or something, you need to check if the selection is inside the editor. Everything you need for that is inside the selection object.
=> correction: the htmlEditor uses an iframe you can get the iframe window by the getWin function.
Note that this is only for modern browser (not < IE9) judging from the legacy Ext version you use, that might be an issue for you... but there are workarounds for IE.
more info

How do I clear MVC client side validation errors when a cancel button is clicked when a user has invalidated a form?

I have a partial view that is rendered within a main view. The partial view takes advantage of System.ComponentModel.DataAnnotations and Html.EnableClientValidation().
A link is clicked, and div containing the partial view is displayed within a JQuery.Dialog().
I then click the save button without entering any text in my validated input field. This causes the client side validation to fire as expected, and display the '*required' message beside the invalid field.
When the cancel button is clicked, I want to reset the client side MVC validation back to it's default state and remove any messages, ready for when the user opens the dialog again. Is there a recommended way of doing this?
This answer is for MVC3. See comments below for help updating it to MVC 4 and 5
If you just want to clear the validation-messages so that they are not shown to the user you can do it with javascript like so:
function resetValidation() {
//Removes validation from input-fields
$('.input-validation-error').addClass('input-validation-valid');
$('.input-validation-error').removeClass('input-validation-error');
//Removes validation message after input-fields
$('.field-validation-error').addClass('field-validation-valid');
$('.field-validation-error').removeClass('field-validation-error');
//Removes validation summary
$('.validation-summary-errors').addClass('validation-summary-valid');
$('.validation-summary-errors').removeClass('validation-summary-errors');
}
If you need the reset to only work in your popup you can do it like this:
function resetValidation() {
//Removes validation from input-fields
$('#POPUPID .input-validation-error').addClass('input-validation-valid');
$('#POPUPID .input-validation-error').removeClass('input-validation-error');
//Removes validation message after input-fields
$('#POPUPID .field-validation-error').addClass('field-validation-valid');
$('#POPUPID .field-validation-error').removeClass('field-validation-error');
//Removes validation summary
$('#POPUPID .validation-summary-errors').addClass('validation-summary-valid');
$('#POPUPID .validation-summary-errors').removeClass('validation-summary-errors');
}
I hope this is the effect you seek.
If you are using unobtrusive validation that comes with MVC you can simply do:
$.fn.clearErrors = function () {
$(this).each(function() {
$(this).find(".field-validation-error").empty();
$(this).trigger('reset.unobtrusiveValidation');
});
};
------------------------------------------------------------------------
Third Party Edit:
This mostly worked in my case, but I had to remove the $(this).find(".field-validation-error").empty(); line. This appeared to affect the re-showing of the validation messages when resubmitting.
I used the following:
$.fn.clearErrors = function () {
$(this).each(function() {
$(this).trigger('reset.unobtrusiveValidation');
});
};
and then called it like this:
$('#MyFormId input').clearErrors();
function resetValidation() {
$('.field-validation-error').html("");
}
You can simply define a new function in jQuery:
$.fn.resetValidation = function () {
$(this).each(function (i, e) {
$(e).trigger('reset.unobtrusiveValidation');
if ($(e).next().is('span')) {
$(e).next().empty();
}
});
};
and then use it for your input fields:
$('#formId input').resetValidation();
Thank you. I had a similar question for a slightly different scenario. I have a screen where when you click one of the submit buttons it downloads a file. In MVC when you return a file for download, it doesn't switch screens, so any error messages which were already there in the validation summary remain there forever. I certainly don't want the error messages to stay there after the form has been submitted again. But I also don't want to clear the field-level validations which are caught on the client-side when the submit button is clicked. Also, some of my views have more than one form on them.
I added the following code (thanks to you) at the bottom of the Site.Master page so it applies to all of my views.
<!-- This script removes just the summary errors when a submit button is pressed
for any form whose id begins with 'form' -->
<script type="text/javascript">
$('[id^=form]').submit(function resetValidation() {
//Removes validation summary
$('.validation-summary-errors').addClass('validation-summary-valid');
$('.validation-summary-errors').removeClass('validation-summary-errors');
});
</script>
Thanks again.
You can tap into the validation library methods to do this.
There are two objects of interest: FormContext and FieldContext. You can access the FormContext via the form's __MVC_FormValidation property, and one FieldContext per validated property via the FormContext's fields property.
So, to clear the validation errors, you can do something like this to a form:
var fieldContexts = form.__MVC_FormValidation.fields;
for(i = 0; i < fieldContexts.length; i++) {
var fieldContext = fieldContexts[i];
// Clears validation message
fieldContext.clearErrors();
}
// Clears validation summary
form.__MVC_FormValidation.clearErrors();
Then, you can hook that piece of code to whichever event you need.
Sources for this (quite undocumented) insight:
http://bradwilson.typepad.com/presentations/advanced-asp-net-mvc-2.pdf (Mentions FieldContext)
https://stackoverflow.com/a/3868490/525499 (For pointing out this link, which metions how to trigger client-side validation via javascript)
In order to complete clear the validation artifacts including the message, the coloured background of the input field, and the coloured outline around the input field, I needed to use the following code, where this was (in my case) a Bootstrap modal dialog containing an imbedded form.
$(this).each(function () {
$(this).find(".field-validation-error").empty();
$(this).find(".input-validation-error").removeClass("input-validation-error");
$(this).find(".state-error").removeClass("state-error");
$(this).find(".state-success").removeClass("state-success");
$(this).trigger('reset.unobtrusiveValidation');
});
Here you can use simply remove error message
$('.field-validation-valid span').html('')
OR
$('.field-validation-valid span').text('')
I've this issue for "Validation summery" after form ajax submit and done it like this:
$form.find('.validation-summary-errors ul').html('');
and complete code is:
$("#SubmitAjax").on('click', function (evt) {
evt.preventDefault();
var $form = $(this).closest('form');
if ($form.valid()) {
//Do ajax call . . .
//Clear validation summery
$form.find('.validation-summary-errors ul').html('');
}
});

Flex Alert control: Activating the "default" button on enter/space key-press

No matter what I try, I can't seem to fire the click event on the "default" button in an Alert control in a Flex 3.4 application.
Alert.show(
'Are you sure you want to delete the selected link?',
'Confirm Delete',
Alert.YES | Alert.CANCEL,
null,
confirmDelete,
null,
Alert.YES
);
In the above code sample, the final argument: Alert.YES is specifying that the "default" option (from the bitwise list in the 3rd argument) is the "Yes" button. In theory, and based on my experience designing Windows applications, "default button" means that hitting the enter key (or sometimes the space bar) fires the click event for that button.
If it matters, the Alert in question is modal.
I can see that the button is styled as the default: it gets a bit of a halo or extra border when compared to the Cancel button or when compared to itself when passing null as the last argument.
However, hitting the enter and space keys seem to have no affect. Am I doing something wrong, or missing some crucial step in getting this functionality to work?
Update 2010-02-17:
Based on my 2nd comment on #rhtx's answer:
Ok, finally got around to trying this. Since the Alert class uses lots of static methods, I essentially just copied the Alert and AlertForm classes into my project (and fixed some relative paths for includes), and what I ended up with was an uglier alert box that works (or doesn't, depending on your perspective) the same way as the vanilla Alert class. I did realize, however, that if you hit TAB it will focus the alert buttons, at which point hitting Escape/Enter will have the desired effect... So how do I eliminate the need to hit TAB?
I tried a few more things and didn't get anywhere.
I tried faking a TAB keypress after opening the alert (with both KEY_DOWN and KEY_UP event types):
var a:Alert = Alert.show(msg, title, Alert.YES | Alert.CANCEL, null, fnCb);
var tabEvent:KeyboardEvent = new KeyboardEvent(
KeyboardEvent.KEY_DOWN,
true,
false,
0,
Keyboard.TAB
);
a.dispatchEvent(tabEvent);
I also found this blog post and tried doing this to focus the alertForm:
var a:Alert = Alert.show(msg, title, Alert.YES | Alert.CANCEL, null, fnCb);
a.mx_internal::alertForm.setFocus();
Neither of these threw errors, but neither produced the desired result, either.
I would approach this by extending the Alert class to include functionality that listens for keyUp events from the Enter and Space keys.
In the createChildren method of your subclass:
override public function createChildren():void
{
super.createChildren();
this.addEventListener(KeyboardEvent.KEY_UP, keyUpListener);
this.stage.addEventListener(KeyboardEvent.KEY_UP, keyUpListener);
}
private function keyUpListener(e:KeyboardEvent):void
{
if(e.keyCode == Keyboard.ENTER || e.keyCode == Keyboard.SPACE)
{
//Trigger the Alert.YES functionality...
}
}
I'm having some issues with my set up this morning and can't get into the Alert class to provide info on how to "Trigger the Alert.YES functionality", but I'll try to post some more on this later on. Hope this little bit helps.
Also - I'm not 100% on this - but I think you will need to manually remove the event listeners when the Alert popup is removed.
Aaand... you may not need both of those listeners. Can't test right now to make sure.
UPDATE: -----------------
After a little more looking, maybe the best way to go about this is to extend the AlertForm class (which manages the Alert's buttons), and then extend the Alert class to use your extended AlertForm class.
The AlertForm class has a keyDownHandler method, which it defines like this:
override protected function keyDownHandler(event:KeyboardEvent):void
{
var buttonFlags:uint = Alert(parent).buttonFlags;
if (event.keyCode == Keyboard.ESCAPE)
{
if ((buttonFlags & Alert.CANCEL) || !(buttonFlags & Alert.NO))
removeAlert("CANCEL");
else if (buttonFlags & Alert.NO)
removeAlert("NO");
}
}
You can see that it is setting up the 'close' behavior in response to pressing the Escape key. You add a little logic, based on the code in the above 'keyUpListener' function to make a call to the AlertForm's removeAlert method, passing in the appropriate String value for the Yes button.
For reference, the removeAlert method looks like this:
private function removeAlert(buttonPressed:String):void
{
var alert:Alert = Alert(parent);
alert.visible = false;
var closeEvent:CloseEvent = new CloseEvent(CloseEvent.CLOSE);
if (buttonPressed == "YES")
closeEvent.detail = Alert.YES;
else if (buttonPressed == "NO")
closeEvent.detail = Alert.NO;
else if (buttonPressed == "OK")
closeEvent.detail = Alert.OK;
else if (buttonPressed == "CANCEL")
closeEvent.detail = Alert.CANCEL;
alert.dispatchEvent(closeEvent);
mx.managers.PopUpManager.removePopUp(alert);
}
I ran into a similar situation. What got me out of it was:
(1) defining the default button in Alert.show(), (2) using a callLater(), and (3) setting the focus manually on the default button.
For example, using Alert.CANCEL as the intended default button (can change to Alert.YES if needed):
var a:Alert = Alert.show(msg, title, Alert.YES | Alert.CANCEL, null, fnCb, null, Alert.CANCEL);
callLater(setAlertButtonFocus,[a]);
...
private function setAlertButtonFocus(a:Alert):void {
a.mx_internal::alertForm.mx_internal::defaultButton.setFocus();
}
This enables the Escape and Enter keys to act as if the user clicked the default button with the mouse.

Resources