I have two input fields, Username and Password and a spinner button. When i click on this spinner button these two input fields get disabled and I am redirected to another page. I am writing an end-to-end testing to check whether these input fields are disabled.
element(by.model('username')).sendKeys('rabi');
element(by.model('password')).sendKeys('rabi');
/* click on spin button */
spinBtn = element(by.className('call-to-action'));
spinBtn.click();
/* check if input is disabled */
var loginInput = element(by.id('login-username'));
expect(loginInput.isEnabled()).toBe(false);
The previous example of
expect(loginInput.getAttribute('disabled')).toEqual('disabled');
Will not work for checking if something is enabled.
You should use
expect(loginInput.isEnabled()).toBe([true|false]);
to accurately verify if something is enabled/disabled.
If that isn't working for you, there's probably something else going on.
I want to add that #TaylorRose's answer (the most voted answer) is very good and thank him for that.
// passes when the button does not have 'disabled' attribute
expect($('#saveChangesBtn').isEnabled()).toBe(true);
However when I tried to run this I got an error:
Error: TSError: тип Unable to compile TypeScript e2e/specs/element.e2e-spec.ts:
Argument of type 'false' is not assignable to parameter of type 'Expected<Promise<boolean>>'.
There are multiple solutions to this issue and here are two of them:
1.Cast your expect to type 'any'
expect<any>($('#saveChangesBtn').isEnabled()).toBe(true);
2.Add #types/jasminewd2 to your package json (and run 'npm install' of course) (thanks to aktraore#github)
"devDependencies": {
...,
"#types/jasminewd2": "2.0.6",
...
}
And then no more errors from typescript and it solves this problem.
P.s. Version 2.0.6 is the latest as of writing this post and the magic version could be different for your case.
So this is addition to the most voted answer if anybody here is having this issue.
When using "getAttribute('disabled').toEqual('true') " did not work
I used className instead, to complete my test, as the classNames changed when disabled.
Related
good evening.
I'm having trouble while trying to validate a variable using Joi. I've read this page link
Joi usually validates object through schemas, however, the page I mentioned show that Joi also supports a more "direct" approach to validation. In my case, I'm trying just to validate a variable.
I'm trying the following:
const {error, value} = Joi.number().validate("SAMPLE TEXT");
It's not precisely what I'm trying to do (I'd change "SAMPLE TEXT" for a variable), but It's a good example to show my problem.
What I'd expect from this code is that an error is thrown (because validation should fail), meaning that ** error should not be null or undefined **, however, when trying:
console.log(`Error: ${error}`};
I get:
Error: undefined
Can anyone help me?
[]
Check your package is installed perfectly. I did not find any issue in your code. I have run it properly.
const Joi = require('#hapi/joi'); check this line also
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 use ActiveForms often and find it handy as it includes client-side validation scripts yii.js and yii.activeForm.js. It normally takes care of model rules and basic validation on its own.
Until Yii 2.0.9:
We could use following script to prevent multiple form submission due to rapid button clicks:
$('form').submit(function(){
$(this).find('button[type!="button"],input[type="submit"]').attr("disabled",true);
setTimeout(function(){
$('form .has-error').each(function(index, element) {
$(this).parents("form:first").find(":submit").removeAttr("disabled");
});
},1000);
});
But,
Current Yii 2.0.10 release brought some changes and fails above script. Now, it will not submit the form if above code executes.
It has also been discussed earlier here and has been identified as bug.
Since, yii.js had two changes:
Bug #10358: Fixed race condition in yii.js AJAX prefilter (silverfire)
Enh #12580: Make yii.js comply with strict and non-strict javascript mode to allow concatenation with external code (mikehaertl)
and, yii.activeForm.js had four changes:
Bug #10681: Reverted fix of beforeValidate event calling in yii.activeForm.js (silverfire)
Enh #12376: Added parameter to yii.activeForm.js validate() method to be able to force validation (DrDeath72)
Enh #12499: When AJAX validation in enabled, yii.activeForm.js will run it forcefully on form submit to display all possible errors (silverfire)
Enh #12744: Added afterInit event to yii.activeForm.js (werew01f)
Can they be replaced with oder js files from v2.0.9?
Will replacing js files cause breakdown and unexpected behaviours?
Are there any better solution to prevent multiple submissions?
It looks like the issue had been taken care of, already.
Those who have installed fresh Yii 2.0.10 via composer will not have this issue; while, those who downloaded an archived file from 'Install from an Archive File' section may still have this issue since they might not have updated the archive files.
If you are facing this specific issue, then all you have to do is replace a specific file framework/assets/yii.activeForm.js from the github source.
In case of local copy, this file can be located at vendor\yiisoft\yii2\assets\yii.activeForm.js.
I suggest you to use uiBlocking to prevent multiple click or entries. Here is complte guide how to block ui while there is some task in progress.
http://malsup.com/jquery/block/
Works Like a Charm
I implemented and tested the following extension:
https://github.com/Faryshta/yii2-disable-submit-buttons
Composer Require
"faryshta/yii2-disable-submit-buttons": "*"
Register Asset Globaly
class AppAsset extends yii\web\AssetBundle
{
public $depends = [
'faryshta\\assets\\ActiveFormDisableSubmitButtonsAsset',
// other dependencies
];
}
Usage
$form = ActiveForm::begin([
'options' => ['class' => 'disable-submit-buttons'],
// other configurations
]);
// inputs
Html::submitButton('Submit', [
// optional, will show the value of `data-disabled-text` attribute
// while handling the validation and submit
'data' => ['disabled-text' => 'Please Wait']
])
$form->end();
Recently got some bug that my forms we not submiting, and button stayed disabled, so I changed it to this. Mostly posting it here for my future reference so I can find it out fast :D
<?php $this->registerJs("
$(function () {
$('body').on('submit', 'form', function() {
$(this).find('button[type!=\"button\"],input[type=\"submit\"]').attr('disabled',true);
setTimeout(function(){
$(this).find('.has-error').each(function(index, element) {
$(this).parents('form:first').find(':submit').removeAttr('disabled');
});
},1000);
});
});
", View::POS_END, 'prevent-double-form-submit'); ?>
Has anyone workaround for getting all errors per field in Mongoose validation? Right now, when some field has an error, validation for that field stops, because of that, you need to resubmit form to see next error.
This behaviour might be fixed in future (https://github.com/Automattic/mongoose/issues/2612), but before that, I would love to see a workaround, which would let me to use validation method, for e.g.:
User.schema.path('hashed_password').validate(function (value) {
if ( ! something)
this.invalidate('password', 'Something is wrong with the password');
});
Note: Using validation method, I can bind error to any field, not just the one validated at the moment. Right now there is no plugin which would let me do that (I have tested mongoose-validator-all and mongoose-validate-all and those plugins are using different strategy).
I made myself a custom validator, that works exactly as I want with AngularJS 1.2 but now I would like to upgrade to the latest and almost stable version of 1.3 but after debugging for some time I found that it doesn't work as expected because I use both $timeout with inside a ctrl.$setValidity. My original and working code (of course it's just a subset of the actual code) is the following:
var validator = function(value) {
// invalidate field before doing any validation,
// so that it's invalid before typing timeout has time to finish and execute
ctrl.$setValidity('validation', false);
$timeout.cancel(timer);
timer = $timeout(function() {
var isValid = validate(value);
ctrl.$setValidity('validation', isValid);
}, 1500);
return value;
}; // end of validator()
// attach the Validator object to the element
ctrl.$parsers.unshift(validator);
ctrl.$formatters.unshift(validator);
I manually change the $setValidity to false because I want to make sure that the user will not post the form before the field is actually finished validated. The timeout is there only so that it gives the user a smoother experience by displaying the error (if there is) only after he finished typing (or at least stop typing after 1.5sec). After that timeout of 1.5sec is finished, the validate(value) kicks in and should update the $setValidity to true or false... This is working perfectly fine in AngularJS 1.2 but not at all in 1.3. Even if I manually set the $setValidity to true by myself it doesn't work and actually stays to a false state, but if I remove the $timeout wrapper, then it's working fine.... but I really need and want my timeout to work! For a reference point of view, my custom validator is available freely to anyone at this Github link
Any help is greatly appreciated.
EDIT
After having help from #SKYWALKR (thanks for starting help), I further went to debug my problem and it is actually much more than what I described at first. My problem seems in fact related to a bunch of things all together, ng-model binding inside ng-repeat that execute a custom validator which has problem only if I enable the $timeout... now with all that together, the binding does not function correctly, wow took me a while to build a proper testing case for this. So here is the sample of my problem: plunker
When you run the sample at first, you will see that none of the Output A:{{binding}} is working (it's suppose to display whatever you type just below it) that it does not work, but then if you comment out the var timer and $timeout (comment out line 39, 42 and 44) and then run it again, now it works...so why? what's broken?
Your correct, 1.3 is not a stable release as of yet. Your directive works fine using 1.3.0-rc.0...see plunkr below.
http://embed.plnkr.co/GSU2Ldn0D2YM0aD9PQla/preview