@@ -935,7 +935,7 @@ describe('NgModelController', function() {
935
935
} ) ;
936
936
937
937
describe ( 'initialization' , function ( ) {
938
- var formElm , inputElm , ctrl , scope , $compile , $compileProvider ;
938
+ var formElm , inputElm , ctrl , scope , $compile , $sniffer , $ compileProvider, changeInputValueTo ;
939
939
940
940
function compileInput ( inputHtml ) {
941
941
inputElm = jqLite ( inputHtml ) ;
@@ -946,19 +946,25 @@ describe('initialization', function() {
946
946
scope . $digest ( ) ;
947
947
}
948
948
949
- function addValidator ( isValid ) {
949
+ function addValidator ( validity , shouldObserve ) {
950
+ if ( ! isDefined ( shouldObserve ) ) {
951
+ shouldObserve = true ;
952
+ }
953
+
950
954
$compileProvider . directive ( 'obs' , function ( ) {
951
955
return {
952
956
require : 'ngModel' ,
953
957
link : function ( scope , element , attrs , ngModelCtrl ) {
954
958
955
- ngModelCtrl . $validators . obs = function ( value ) {
956
- return isValid ;
959
+ ngModelCtrl . $validators . obs = isFunction ( validity ) ? validity : function ( value ) {
960
+ return validity ;
957
961
} ;
958
962
959
- attrs . $observe ( 'obs' , function ( ) {
960
- ngModelCtrl . $validate ( ) ;
961
- } ) ;
963
+ if ( shouldObserve ) {
964
+ attrs . $observe ( 'obs' , function ( ) {
965
+ ngModelCtrl . $validate ( ) ;
966
+ } ) ;
967
+ }
962
968
}
963
969
} ;
964
970
@@ -995,16 +1001,22 @@ describe('initialization', function() {
995
1001
$compileProvider = _$compileProvider_ ;
996
1002
} ) ) ;
997
1003
998
- beforeEach ( inject ( function ( _$compile_ , _$rootScope_ ) {
1004
+ beforeEach ( inject ( function ( _$compile_ , _$rootScope_ , _$sniffer_ ) {
999
1005
$compile = _$compile_ ;
1006
+ $sniffer = _$sniffer_ ;
1000
1007
scope = _$rootScope_ ;
1008
+
1009
+ changeInputValueTo = function ( value ) {
1010
+ inputElm . val ( value ) ;
1011
+ browserTrigger ( inputElm , $sniffer . hasEvent ( 'input' ) ? 'input' : 'change' ) ;
1012
+ } ;
1001
1013
} ) ) ;
1002
1014
1003
1015
afterEach ( function ( ) {
1004
1016
dealoc ( formElm ) ;
1005
1017
} ) ;
1006
1018
1007
- // This fails with string formatter
1019
+ // https://github.com/angular/angular.js/issues/9959
1008
1020
it ( 'should not change model of type number to string with validator using observer' , function ( ) {
1009
1021
addValidator ( true ) ;
1010
1022
scope . value = 12345 ;
@@ -1018,6 +1030,7 @@ describe('initialization', function() {
1018
1030
expect ( scope . ngChangeSpy ) . not . toHaveBeenCalled ( ) ;
1019
1031
} ) ;
1020
1032
1033
+ //https://github.com/angular/angular.js/issues/9063
1021
1034
it ( 'should not set a null model that is invalid to undefined' , function ( ) {
1022
1035
addValidator ( false ) ;
1023
1036
scope . value = null ;
@@ -1048,6 +1061,7 @@ describe('initialization', function() {
1048
1061
expect ( scope . ngChangeSpy ) . not . toHaveBeenCalled ( ) ;
1049
1062
} ) ;
1050
1063
1064
+ // https://github.com/angular/angular.js/issues/10025
1051
1065
it ( 'should not change a model that uses custom $formatters and $parsers' , function ( ) {
1052
1066
addValidator ( true ) ;
1053
1067
addFormatter ( function ( modelValue ) {
@@ -1064,6 +1078,63 @@ describe('initialization', function() {
1064
1078
expect ( inputElm ) . toBeValid ( ) ;
1065
1079
expect ( scope . value ) . toBe ( 'abc' ) ;
1066
1080
} ) ;
1081
+
1082
+ describe ( '$validate' , function ( ) {
1083
+
1084
+ // Sanity test: since a parse error sets the modelValue to undefined, the
1085
+ // $$rawModelValue will always be undefined, hence $validate does not have
1086
+ // a 'good' value to update
1087
+ it ( 'should not update a model that has a parse error' , function ( ) {
1088
+ scope . value = 'abc' ;
1089
+ addParser ( function ( ) {
1090
+ return undefined ;
1091
+ } ) ;
1092
+
1093
+ addValidator ( true , false ) ;
1094
+
1095
+ compileInput ( '<input type="text" name="textInput" obs parse ng-model="value"/>' ) ;
1096
+ expect ( inputElm ) . toBeValid ( ) ;
1097
+ expect ( scope . value ) . toBe ( 'abc' ) ;
1098
+
1099
+ changeInputValueTo ( 'xyz' ) ;
1100
+ expect ( inputElm ) . toBeInvalid ( ) ;
1101
+ expect ( scope . value ) . toBeUndefined ( ) ;
1102
+ expect ( ctrl . $error . parse ) . toBe ( true ) ;
1103
+
1104
+ ctrl . $validate ( ) ;
1105
+ expect ( inputElm ) . toBeInvalid ( ) ;
1106
+ expect ( scope . value ) . toBeUndefined ( ) ;
1107
+ } ) ;
1108
+
1109
+ it ( 'should restore the last valid modelValue when a validator becomes valid' , function ( ) {
1110
+ scope . value = 'abc' ;
1111
+ scope . count = 0 ;
1112
+
1113
+ addValidator ( function ( ) {
1114
+ scope . count ++ ;
1115
+ dump ( 'count' , scope . count ) ;
1116
+ return scope . count === 1 ? true : scope . count === 2 ? false : true ;
1117
+ } ) ;
1118
+
1119
+ compileInput ( '<input type="text" name="textInput" obs ng-model="value"/>' ) ;
1120
+ expect ( inputElm ) . toBeValid ( ) ;
1121
+ expect ( scope . value ) . toBe ( 'abc' ) ;
1122
+ expect ( ctrl . $viewValue ) . toBe ( 'abc' ) ;
1123
+
1124
+ ctrl . $validate ( ) ;
1125
+ scope . $digest ( ) ;
1126
+ expect ( inputElm ) . toBeInvalid ( ) ;
1127
+ expect ( scope . value ) . toBeUndefined ( ) ;
1128
+ expect ( ctrl . $viewValue ) . toBe ( 'abc' ) ;
1129
+
1130
+ ctrl . $validate ( ) ;
1131
+ scope . $digest ( ) ;
1132
+ expect ( inputElm ) . toBeValid ( ) ;
1133
+ expect ( scope . value ) . toBe ( 'abc' ) ;
1134
+ } ) ;
1135
+
1136
+
1137
+ } ) ;
1067
1138
} ) ;
1068
1139
1069
1140
describe ( 'ngModel' , function ( ) {
0 commit comments