I am currently working on a pretty simple input form with various input elements, such as selects, texts and radiobuttons. The form is validated upon post and if not validated successfully the form is displayed again with erroneous fields highlighted. The highlight is achieved by adding a class has-error and appending a div with an error message. Upon correcting the error - say checking one of the radio-buttons in a group - the onChange event is captured and it removes the has-error class and the div:
if ($(obj).parents('div.has-error')) {
$(obj).parents('div.has-error').removeClass('has-error');
$(obj).parents('div.has-error').find('div.help-block').remove();
}
It works exactly as intended when performed by a "real" user. However when the exact same thing is performed by a Selenium (GEB) test, the radiobutton isn't checked. For a short while it has the "focus" dotted line as if it tabbed through the element.
Hence the test fails since the radiobutton is never checked. If I remove the above mentioned javascript it works just fine... And likewise if I remove just one of the two statements....
The test is written with GEB and uses "form-control-shortcuts" to set the value of the fields by name, like:
class FormModule extends Module {
static base = { $('form#personform') }
static content = {
personskoen { "person.koen"().module(RadioButtons) }
}
}
class OpretPersonPage extends Page {
static url = "person/opret"
static at = { title.contains("person.opret.titel") }
static content = {
form { module FormModule }
}
}
And the value is set in the test like this:
def () {
given:
at OpretPersonPage
when:
page.form.persoenskoen = "KVINDE"
then:
page.form.persoenskoen == "KVINDE"
}
I am completely stuck and have no further ideas to test. I really hope you guys have some!
I am using:
org.seleniumhq.selenium:selenium-firefox-driver:2.52.0
org.seleniumhq.selenium:selenium-support:2.52.0
org.seleniumhq.selenium:selenium-server:2.52.0
Related
I recently had a good setup for preventing gmail, hotmail, yahoo etc. emails from being able to be submitted on our forms for requesting a demo for our company. However, we now have multiple forms on certain pages, some of which we will allow personal emails.
My question is how do I adjust the following script to prohibit the input on a particular form id? Is it possible to simply add something that detects the form ID (let's call it #form-id for now).
// EMAIL DOMAINS TO BLOCK
var emailList = /^([\w-\.]+#(?!gmail.com)(?!yahoo.com)(?!icloud.com)(?!hotmail.com)(?!aol.com)
// ALERT MESSAGE TO BE SHOWN
var emailAlert = 'Please input a valid work email address (NOT Gmail, Outlook, Yahoo, etc.)'
// VALIDATE
$('input[type=submit]').click(function() {
$("input[type=email]").each(function() {
var email = $(this).val().toLowerCase();
if (emailList.test(email)) {
(this).setCustomValidity('');
} else {
(this).setCustomValidity(emailAlert);
}
})
})
// PREVENTS ALERT FROM APPEARING WITH EACH KEYPRESS
$('input[type=email]').on('input', function() {
(this).setCustomValidity('');
});
Without knowing much else about your situation, in basic principle you should be able to scope your code by modifying the selector portion of your jquery function calls.
For example if you wanted to enact this validation only on the form with id #form-id in theory you should be able to change your code to this:
$('#form-id input[type=submit]').click(function() {
$("#form-id input[type=email]").each(function() {
var email = $(this).val().toLowerCase();
if (emailList.test(email)) {
(this).setCustomValidity('');
} else {
(this).setCustomValidity(emailAlert);
}
})
})
// PREVENTS ALERT FROM APPEARING WITH EACH KEYPRESS
$('#form-id input[type=email]').on('input', function() {
(this).setCustomValidity('');
});
The format of this - two sub selectors seperated by a space - means that the 2nd sub-selector will only match when it appears inside the first sub-selector.
Consider example #form-id input[type=submit]
This selector will match on inputs of type submit found inside your form (or any parent element) with id form-id
To do the opposite you could change the selector to:
form:not(#form-id) input[type=submit]
Here is my code where i am trying to select the images which only the specific class attached to it
$("#allimages").change(function () {
$('input:checkbox:not("#checkAll")').prop('checked', $(this).prop('checked',$(this).hasClass('isImage')));
});
but it is selecting all checkboxes ignoring if any class is attached to it or not
Without seeing the HTML, it's hard to know what you're trying to accomplish.
I would suggest the following based on what you have provided:
$("#allimages").change(function() {
$("input[type='checkbox'].isImage:not('#checkAll')").prop('checked', $(this).prop("checked"));
});
When #allimages is changed, that same value will be sent to all checkboxes that have class isImage and is not #checkAll.
I've taken a bootstrap directive that watches all the input elements on a form and updates the CSS of its parent div to show validation errors in a Bootstrap way. The watch looks at the elements css class and if ng-invalid is present it adds has-error to the parent.
element.find('.form-group').each(function () {
var formGroup = $(this);
var inputs = formGroup.find('input[ng-model],textarea[ng-model],select[ng-model]');
if (inputs.length > 0) {
inputs.each(function () {
var input = $(this);
scope.$watch(function () {
return input.hasClass('ng-invalid') && (!input.hasClass('ng-pristine') || form.$submitted);
}, function (isInvalid) {
formGroup.toggleClass('has-error', isInvalid);
});
});
}
});
The original directive was taken from an answer on S.O. I think the original answer derives from this Reconcile Angular.js and Bootstrap form validation styling but someone took it and expanded on it and I can't find their answer. It also takes more code from this show validation error messages on submit in angularjs to handle preventing the form being submitted but I'm omitting that for now
The directive works fine when using synchronous validators but when I use an async validator it gets the validation states mixed up. After making the field invalid, the watch fires but input.hasClass('ng-invalid') returns false. I'm at a loss about why it might happen.
I've created a plunkr here http://plnkr.co/edit/0wUUPdZc0fYN6euvsIMl?p=preview
One thing that could possibly be done here is to use child forms for each form group and if the child forms are invalid, then the parent form itself will not be valid.
Here's an example.
http://jsbin.com/luvegecalo/1
I have made a custom directive to do input validation, now the directive works fine in most cases but the way I have done it is to invalidate the field before I inspect it with ctrl.$setValidity('validation', false); and then I validate the field change it's $setValidity to true if it's valid. But my problem is when I use onBlur event inside my directive, because I invalidate the field as soon as I start typing it becomes dirty and shows invalid even though I just want it invalid after the onBlur, so I found out that the best is to invalidate the Form instead of each fields.
So to make it short how can I find the parent form of the input element and set it to invalidate?
When knowing the form name, I know I can do this scope.myFormName.$setValidity('validation', false); and it works, but I am trying to be generic and find the form object by myself and then invalidate it. I am trying to loop with the elm.parent() but not much success yet...and I'm trying to stay as generic as possible so with jqLite.
EDIT
I got some code working but it's not exactly clean code, does anyone have a better way?
var j = 0;
var parentElm = elm.parent();
var parentFormElm = null;
do {
if(parentElm.prop('tagName').toUpperCase() === "FORM") {
parentFormElm = parentElm;
break;
}
parentElm = parentElm.parent(); // next parent
}while(parentElm !== "form" && j++ < 50);
scope[parentFormElm.prop('name')].$setValidity('validation', false);
Since it's just a matter of styling things (as pointed out in the comments) you can just tweak Angular's CSS classes so the input field gets highlighted only when it's not focused:
.ng-invalid.ng-dirty:not(:focus) {
background-color: #ff7373;
}
Plunker
If you can't afford to use CSS3 selectors, then you'll need two CSS classes:
.ng-invalid.ng-dirty {
background-color: #ff7373;
}
.ng-invalid.ng-dirty:focus {
background-color: #fff;
}
Plunker
I am very new to building forms with js. I copied and applied a bit of code to get fields to pop up depending on the Radio button I select. This works great for two radio buttons, but my issues is that I want to include several (5+) and would like to reset the fields with every change.
I was thinking I can input additional code to reset all fields "onchange" but I can't get this piece of code to work... here is what I copied and modified for my use:
works great with 2 buttons as designed:
{
toggleSelectionFields: function() {
var isLaptop = ca_fdIsSelectRadio('showhide','group','short');
if (isLaptop) {
ca_fdHideField('showhide','longfields');
ca_fdShowField('showhide','shortfields');
} else {
ca_fdHideField('showhide','shortfields');
ca_fdShowField('showhide','longfields');
}
}
}
Here is what I tried to do:
{
toggleSelectionFields: function() {
Var discovery = ca_fdIsSelectRadio('phone','deskphone4610','selectproblem','SelectIssue','discovery');
Var headset = ca_fdIsSelectRadio('phone','deskphone4610','selectproblem','SelectIssue','headset');
Var fac = ca_fdIsSelectRadio('phone','deskphone4610','selectproblem','SelectIssue','feature');
Var calls = ca_fdIsSelectRadio('phone','deskphone4610','selectproblem','SelectIssue','calls');
if (discovery)
{ca_fdShowField('phone','deskphone4610','selectproblem','discovermode')}
if (headset)
{ca_fdShowField('phone','deskphone4610','selectproblem','headset')}
if (fac)
{ca_fdShowField('phone','deskphone4610','selectproblem','feature')}
if (calls)
{ca_fdShowField('phone','deskphone4610','selectproblem','calls')}
}
}
}
This appears to be a JavaScript question (not Java) and related to a particular framework (CA Service Catalog), so questions about how to do things with particular CA functions would probably be best answered on the CA Service Management Global User Community message boards.
As a general logic/JavaScript question, though, you need to hide the fields you don't want to see in addition to showing the ones you do want to see. Notice that your first example calls ca_fdHideField to hide one set of fields, then ca_fdShowField to show the other. If you don't want to duplicate a lot of code, you could hide them all before the if statements, then just show the one that corresponds with the radio button that was selected:
ca_fdHideField(...)
ca_fdHideField(...)
...
if (discovery) {
...
}
etc.