AngularJS form validation testing - angularjs

Sometimes forms become very complicated and it is impossible to test every case manually after code changes.
I already have unit testing with karma on the project.
Is there any tools or best practices how to test AngularJS form validation with jasmine and karma?
For example how can I test such form with jasmine and karma automatically?
<form name="appForm" novalidate>
<div>
Username: <input type="text" ng-model="data.username" name="username" ng-maxlength="15" required />
</div>
<div>
Email: <input type="email" ng-model="data.email" name="email" required />
</div>
<div>
Age: <input type="number" ng-model="data.age" name="age" />
</div>
<div>
<button ng-click="submit()" ng-disabled="appForm.$invalid">Submit</button>
</div>
</form>

It depends on what you actually want to make sure when testing form validation.
If you want to be sure invalid form will not be submited, then it is one case. And I don't see problems with this case.
If you want to be sure that appropriate messages are displayed for invalid fields, then, for example, you can make a directive, that is aware of all your possible field restrictions ('required', 'ng-maxlength', 'url', etc.) and is responsible for displaying appropriate error messages. So you will need to create tests only for this directive.
Example:
<input type="text" ng-model="data.username" my-directive name="username" ng-maxlength="15" required />
myDirective is aware of required and ng-maxlength restrictions, that were put on the field, & it is responsible for displaying appropriate error messages for invalid state of the field.

Related

two ng-model with the same value on a form

I have a simple form with two text inputs like below:
<form>
// this is visible in mobile view
<input id="mobileView" type="email" required ng-model="myValue" />
// this is visible on desktop view
<input id="desktopView" type="email" required ng-model="myValue" />
</form>
my question is does doing so violate angular form validation? because both of the inputs are in DOM and in one view one of them have value and in other view it doesn't have any value. does this break angular's validation?
Your code is correct and use ng-if it handle the DOM elements.
<form>
// this is visible in mobile view
<input id="mobileView" type="email" ng-if="condition for mobile view" required ng-model="myValue" />
// this is visible on desktop view
<input id="desktopView" type="email" ng-if="condition for desktop view" required ng-model="myValue" />
</form>

Angular input validity property without a form

I have inputs in a web page without the form tag (useless to me).
How can I get their validity status inside the HTML ? This
<input name="myInput" type="text" ng-pattern="/^[0-9]{13}$/">
<input type="button" ng-show="myInput.$valid">
doesn't work.
I'm afraid that won't work without wrapping it in a form as you need to access those fields via the form's controller.
<form name="myForm">
<input name="myInput" type="text" ng-pattern="/^[0-9]{13}$/">
<input type="button" ng-show="myForm.myInput.$valid">
</form>
Should work.
If you're unable to use the form tag for any reason, you'll have to wire that up manually.

How to receive invalid data from input fields in Angularjs

It seems that the ngModel does not return anything at all when it's invalid.
I want to play with the value when only 2 or three characters is inserted!
<input
type="tel"
class="fullinput"
ng-model="xxxxx"
ng-minlength="12"
ng-maxlength="15"
required
/>
Just add name attribute to your form and to input. Then you'll be able to access needed value via:
in template {{myForm.xxx.$viewValue}}
in controller $scope.myForm.xxx.$viewValue
<form name="myForm">
<input
type="tel"
class="fullinput"
ng-model="xxxxx"
name="xxx"
ng-minlength="12"
ng-maxlength="15"
required
/>
</form>

Clearing all inputs and restoring .ng-pristine on click

It's still the first day of me using AngularJS after inheriting the project from a fellow developer. I was wondering, I have a login/registration form on my interface that is hidden once the items/form is submitted. Now once the user has submitted is there a correct or proper way to clear the form of it's entries and restore the .ng-pristine class on the items. The reason for this is should the user choose to log out and then login again (or another user wishes to register) the form is populated and has the validation css applied to it already. I don't want this, I would want everything to be empty and no CSS applied.
I can do this in JavaScript (obviously) however with AngularJS being a different approach I was wondering if I should approach this issue another way rather than loop through the form items and append a class to each item whilst clearing it's value.
This an example of one of my forms
<form name="signupForm" novalidate ng-submit="register(user)">
<div><label for="email">email:</label><input type="email" id="email" name="email" required ng-model="user.email" ng-minlength=4></div>
<div><label for="userName">Username:</label><input type="text" name="userName" id="userName" ng-model="user.userName" required ng-pattern="/^[A-Za-z0-9 \-_.]*$/" ng-minlength=4></div>
<div><label for="firstName">Vorname:</label><input type="text" name="firstName" id="firstName" ng-model="user.firstName" required ng-pattern="/^[A-Za-z \-_.]*$/" ng-minlength=3></div>
<div><label for="lastName">Nachname:</label><input type="text" name="lastName" id="lastName" ng-model="user.lastName" required ng-pattern="/^[A-Za-z \-_.]*$/" ng-minlength=4></div>
<div><label for="password1">Passwort:</label><input type="password" name="password1" id="password1" ng-model="user.password1" required ng-minlength=4></div>
<div><label for="password2">Passwort wiederholen:</label><input type="password" name="password2" id="password2" ng-model="user.password2" valid-password2 ng-minlength=4 pw-check="password1"></div>
... and so on
Many thanks
The form will appear in the correct scope under its name, i.e. $scope.signupForm. Additionally the object populating the form is $scope.user. In your controller, do:
$scope.user = {}; // or new User() if it is your case
$scope.signupForm.$setPristine();
In case $scope.signupForm is undefined, put a controller directly on the form, and place the code above (and anything else applicable) inside this new controller:
<form name="signupForm" novalidate ng-submit="register(user)"
ng-controller="NewCtrl">
(This may happen due to scope nesting under your original controller.)
Just refer to this post :
Reset form to pristine state (AngularJS 1.0.x)
In the main question you got reference to issues and pull request on AngularJS. In resume you have to use $setPristine() method to your form.
Hope it helps !
var app = angular.module('App', []);
app.controller('formController', function($scope, $document){
$scope.Clear = function(){
angular.forEach(angular.element($document[0].querySelectorAll('input[type=text], input[type=email], input[type=password]')), function (elem, index) {
elem.value = '';
/*
Just extra do something
elem.parent().parent().removeClass('has-error has-success');
elem.parent().parent().children().find('span').removeClass('glyphicon-exclamation-sign glyphicon-ok');
*/
});
$scope.myForm.$setPristine();
}
});
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"></script>
</head>
<body ng-app="App">
<div ng-controller="formController">
<form name="myForm">
<input type="text" name="FirstName" ng-model="FN"/> <br>
<input type="text" name="LastName"/>
<br>
<input type="text" name="UserName"/>
<br>
<input type="password" name="Password"/>
</form>
<button ng-click="Clear()">Clear</button>
</div>
</body>
</html>
Here is my Example, it worked for me i am using angularjs 1.6

Is ng-model needed when using ng-disabled and $invalid on a form?

I'm using AngularJS and have a form where I want the Submit button to be disabled if some fields are not filled in.
The standard way seems to be the following:
<form ng-app name="myForm">
<label>Name</label>
<input type="text" name="name" ng-model="form.name" required>
<input type="submit" ng-disabled="myForm.name.$invalid">
</form>
http://jsfiddle.net/YMSRU/
However, if I omit the model from the input field the validation doesn't work and I don't need any models on my input fields (I submit my form using the ngUpload directive so it's actually sent to the form action in an iframe).
Is there any solution or should I add random models just to make the validation work? It seems like a bad work-around.
You could simply do the invalid check at the form level, then no need to define a model for each input:
<form ng-app name="myForm">
<label>Name</label>
<input type="text" name="name" required>
<input type="submit" ng-disabled="myForm.$invalid">
</form>
You are missing your model at your test input tag : ng-model="form.name"

Resources