mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-05-15 18:23:09 +00:00
chore(scenario tests): make scenario tests pass again
This commit is contained in:
parent
085e3c611f
commit
9c06394376
19 changed files with 156 additions and 225 deletions
|
|
@ -34,7 +34,28 @@ detection, and preventing invalid form submission.
|
||||||
save: function() {
|
save: function() {
|
||||||
this.master = this.form;
|
this.master = this.form;
|
||||||
this.cancel();
|
this.cancel();
|
||||||
|
},
|
||||||
|
|
||||||
|
addContact: function() {
|
||||||
|
this.form.contacts.push({type:'', value:''});
|
||||||
|
},
|
||||||
|
|
||||||
|
removeContact: function(contact) {
|
||||||
|
for ( var i = 0, ii = this.form.contacts.length; i < ii; i++) {
|
||||||
|
if (contact === this.form.contacts[i]) {
|
||||||
|
this.form.contacts.splice(i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
isCancelDisabled: function() {
|
||||||
|
return angular.equals(this.master, this.form);
|
||||||
|
},
|
||||||
|
|
||||||
|
isSaveDisabled: function() {
|
||||||
|
return this.myForm.$invalid || angular.equals(this.master, this.form);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<div ng:controller="UserForm">
|
<div ng:controller="UserForm">
|
||||||
|
|
@ -53,7 +74,7 @@ detection, and preventing invalid form submission.
|
||||||
ng:pattern="zip" required/><br/><br/>
|
ng:pattern="zip" required/><br/><br/>
|
||||||
|
|
||||||
<label>Contacts:</label>
|
<label>Contacts:</label>
|
||||||
[ <a href="" ng:click="form.contacts.$add()">add</a> ]
|
[ <a href="" ng:click="addContact()">add</a> ]
|
||||||
<div ng:repeat="contact in form.contacts">
|
<div ng:repeat="contact in form.contacts">
|
||||||
<select ng:model="contact.type">
|
<select ng:model="contact.type">
|
||||||
<option>email</option>
|
<option>email</option>
|
||||||
|
|
@ -62,10 +83,10 @@ detection, and preventing invalid form submission.
|
||||||
<option>IM</option>
|
<option>IM</option>
|
||||||
</select>
|
</select>
|
||||||
<input type="text" ng:model="contact.value" required/>
|
<input type="text" ng:model="contact.value" required/>
|
||||||
[ <a href="" ng:click="form.contacts.$remove(contact)">X</a> ]
|
[ <a href="" ng:click="removeContact(contact)">X</a> ]
|
||||||
</div>
|
</div>
|
||||||
<button ng:click="cancel()" ng:disabled="{{master.$equals(form)}}">Cancel</button>
|
<button ng:click="cancel()" ng:disabled="{{isCancelDisabled()}}">Cancel</button>
|
||||||
<button ng:click="save()" ng:disabled="{{myForm.$invalid || master.$equals(form)}}">Save</button>
|
<button ng:click="save()" ng:disabled="{{isSaveDisabled()}}">Save</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,18 @@ allow a user to enter data.
|
||||||
};
|
};
|
||||||
this.state = /^\w\w$/;
|
this.state = /^\w\w$/;
|
||||||
this.zip = /^\d\d\d\d\d$/;
|
this.zip = /^\d\d\d\d\d$/;
|
||||||
|
|
||||||
|
this.addContact = function() {
|
||||||
|
this.user.contacts.push({type:'', value:''});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.removeContact = function(contact) {
|
||||||
|
for ( var i = 0, ii = this.user.contacts.length; i < ii; i++) {
|
||||||
|
if (contact === this.user.contacts[i]) {
|
||||||
|
this.user.contacts.splice(i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<div ng:controller="FormController" class="example">
|
<div ng:controller="FormController" class="example">
|
||||||
|
|
@ -34,7 +46,7 @@ allow a user to enter data.
|
||||||
ng:pattern="zip" required><br/><br/>
|
ng:pattern="zip" required><br/><br/>
|
||||||
|
|
||||||
<label>Phone:</label>
|
<label>Phone:</label>
|
||||||
[ <a href="" ng:click="user.contacts.$add()">add</a> ]
|
[ <a href="" ng:click="addContact()">add</a> ]
|
||||||
<div ng:repeat="contact in user.contacts">
|
<div ng:repeat="contact in user.contacts">
|
||||||
<select ng:model="contact.type">
|
<select ng:model="contact.type">
|
||||||
<option>email</option>
|
<option>email</option>
|
||||||
|
|
@ -43,7 +55,7 @@ allow a user to enter data.
|
||||||
<option>IM</option>
|
<option>IM</option>
|
||||||
</select>
|
</select>
|
||||||
<input type="text" ng:model="contact.value" required/>
|
<input type="text" ng:model="contact.value" required/>
|
||||||
[ <a href="" ng:click="user.contacts.$remove(contact)">X</a> ]
|
[ <a href="" ng:click="removeContact(contact)">X</a> ]
|
||||||
</div>
|
</div>
|
||||||
<hr/>
|
<hr/>
|
||||||
Debug View:
|
Debug View:
|
||||||
|
|
|
||||||
|
|
@ -54,15 +54,26 @@ You can try evaluating different expressions here:
|
||||||
function Cntl2() {
|
function Cntl2() {
|
||||||
this.exprs = [];
|
this.exprs = [];
|
||||||
this.expr = '3*10|currency';
|
this.expr = '3*10|currency';
|
||||||
|
this.addExp = function(expr) {
|
||||||
|
this.exprs.push(expr);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.removeExp = function(contact) {
|
||||||
|
for ( var i = 0, ii = this.exprs.length; i < ii; i++) {
|
||||||
|
if (contact === this.exprs[i]) {
|
||||||
|
this.exprs.splice(i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<div ng:controller="Cntl2" class="expressions">
|
<div ng:controller="Cntl2" class="expressions">
|
||||||
Expression:
|
Expression:
|
||||||
<input type='text' ng:model="expr" size="80"/>
|
<input type='text' ng:model="expr" size="80"/>
|
||||||
<button ng:click="exprs.$add(expr)">Evaluate</button>
|
<button ng:click="addExp(expr)">Evaluate</button>
|
||||||
<ul>
|
<ul>
|
||||||
<li ng:repeat="expr in exprs">
|
<li ng:repeat="expr in exprs">
|
||||||
[ <a href="" ng:click="exprs.$remove(expr)">X</a> ]
|
[ <a href="" ng:click="removeExp(expr)">X</a> ]
|
||||||
<tt>{{expr}}</tt> => <span ng:bind="$parent.$eval(expr)"></span>
|
<tt>{{expr}}</tt> => <span ng:bind="$parent.$eval(expr)"></span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
@ -175,7 +186,7 @@ Extensions: You can further extend the expression vocabulary by adding new metho
|
||||||
Search: <input ng:model="searchText"/>
|
Search: <input ng:model="searchText"/>
|
||||||
<table class="example3">
|
<table class="example3">
|
||||||
<tr><th>Name</th><th>Phone</th><tr>
|
<tr><th>Name</th><th>Phone</th><tr>
|
||||||
<tr ng:repeat="friend in friends.$filter(searchText)">
|
<tr ng:repeat="friend in friends | filter:searchText">
|
||||||
<td>{{friend.name}}</td>
|
<td>{{friend.name}}</td>
|
||||||
<td>{{friend.phone}}</td>
|
<td>{{friend.phone}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,16 @@ The following example demonstrates:
|
||||||
save: function() {
|
save: function() {
|
||||||
this.master = this.form;
|
this.master = this.form;
|
||||||
this.cancel();
|
this.cancel();
|
||||||
|
},
|
||||||
|
|
||||||
|
isCancelDisabled: function() {
|
||||||
|
return angular.equals(this.master, this.form);
|
||||||
|
},
|
||||||
|
|
||||||
|
isSaveDisabled: function() {
|
||||||
|
return this.userForm.$invalid || angular.equals(this.master, this.form);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<div ng:controller="UserFormCntl">
|
<div ng:controller="UserFormCntl">
|
||||||
|
|
@ -172,10 +181,9 @@ The following example demonstrates:
|
||||||
</ng:form>
|
</ng:form>
|
||||||
|
|
||||||
<button ng:click="cancel()"
|
<button ng:click="cancel()"
|
||||||
ng:disabled="{{master.$equals(form)}}">Cancel</button>
|
ng:disabled="{{isCancelDisabled()}}">Cancel</button>
|
||||||
<button ng:click="save()"
|
<button ng:click="save()"
|
||||||
ng:disabled="{{userForm.$invalid || master.$equals(form)}}">
|
ng:disabled="{{isSaveDisabled()}}">Save</button>
|
||||||
Save</button>
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
@ -278,9 +286,9 @@ This example shows how to implement a custom HTML editor widget in Angular.
|
||||||
this.htmlContent = '<b>Hello</b> <i>World</i>!';
|
this.htmlContent = '<b>Hello</b> <i>World</i>!';
|
||||||
}
|
}
|
||||||
|
|
||||||
function HTMLEditorWidget(element) {
|
HTMLEditorWidget.$inject = ['$element', 'html$Filter'];
|
||||||
|
function HTMLEditorWidget(element, htmlFilter) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var htmlFilter = angular.filter('html');
|
|
||||||
|
|
||||||
this.$parseModel = function() {
|
this.$parseModel = function() {
|
||||||
// need to protect for script injection
|
// need to protect for script injection
|
||||||
|
|
@ -309,7 +317,7 @@ This example shows how to implement a custom HTML editor widget in Angular.
|
||||||
}
|
}
|
||||||
|
|
||||||
angular.directive('ng:html-editor-model', function() {
|
angular.directive('ng:html-editor-model', function() {
|
||||||
function linkFn($formFactory, element) {
|
return ['$formFactory', '$element', function ($formFactory, element) {
|
||||||
var exp = element.attr('ng:html-editor-model'),
|
var exp = element.attr('ng:html-editor-model'),
|
||||||
form = $formFactory.forElement(element),
|
form = $formFactory.forElement(element),
|
||||||
widget;
|
widget;
|
||||||
|
|
@ -318,15 +326,13 @@ This example shows how to implement a custom HTML editor widget in Angular.
|
||||||
scope: this,
|
scope: this,
|
||||||
model: exp,
|
model: exp,
|
||||||
controller: HTMLEditorWidget,
|
controller: HTMLEditorWidget,
|
||||||
controllerArgs: [element]});
|
controllerArgs: {$element: element}});
|
||||||
// if the element is destroyed, then we need to
|
// if the element is destroyed, then we need to
|
||||||
// notify the form.
|
// notify the form.
|
||||||
element.bind('$destroy', function() {
|
element.bind('$destroy', function() {
|
||||||
widget.$destroy();
|
widget.$destroy();
|
||||||
});
|
});
|
||||||
}
|
}];
|
||||||
linkFn.$inject = ['$formFactory'];
|
|
||||||
return linkFn;
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<form name='editorForm' ng:controller="EditorCntl">
|
<form name='editorForm' ng:controller="EditorCntl">
|
||||||
|
|
|
||||||
|
|
@ -31,16 +31,18 @@ myController.$inject = ['$location', '$log'];
|
||||||
<doc:example>
|
<doc:example>
|
||||||
<doc:source>
|
<doc:source>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
angular.service('notify', function(win) {
|
angular.module.MyServiceModule = ['$provide', function($provide){
|
||||||
var msgs = [];
|
$provide.factory('notify', ['$window', function(win) {
|
||||||
return function(msg) {
|
var msgs = [];
|
||||||
msgs.push(msg);
|
return function(msg) {
|
||||||
if (msgs.length == 3) {
|
msgs.push(msg);
|
||||||
win.alert(msgs.join("\n"));
|
if (msgs.length == 3) {
|
||||||
msgs = [];
|
win.alert(msgs.join("\n"));
|
||||||
}
|
msgs = [];
|
||||||
};
|
}
|
||||||
}, {$inject: ['$window']});
|
};
|
||||||
|
}]);
|
||||||
|
}];
|
||||||
|
|
||||||
function myController(notifyService) {
|
function myController(notifyService) {
|
||||||
this.callNotify = function(msg) {
|
this.callNotify = function(msg) {
|
||||||
|
|
@ -51,7 +53,7 @@ function myController(notifyService) {
|
||||||
myController.$inject = ['notify'];
|
myController.$inject = ['notify'];
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div ng:controller="myController">
|
<div ng:controller="myController" ng:module="MyServiceModule">
|
||||||
<p>Let's try this simple notify service, injected into the controller...</p>
|
<p>Let's try this simple notify service, injected into the controller...</p>
|
||||||
<input ng:init="message='test'" type="text" ng:model="message" />
|
<input ng:init="message='test'" type="text" ng:model="message" />
|
||||||
<button ng:click="callNotify(message);">NOTIFY</button>
|
<button ng:click="callNotify(message);">NOTIFY</button>
|
||||||
|
|
|
||||||
|
|
@ -19,28 +19,32 @@ text upper-case and assigns color.
|
||||||
<doc:example>
|
<doc:example>
|
||||||
<doc:source>
|
<doc:source>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
angular.filter('reverse', function(input, uppercase, color) {
|
angular.module.MyReverseModule = function MyModule($provide) {
|
||||||
var out = "";
|
$provide.filter('reverse', function() {
|
||||||
for (var i = 0; i < input.length; i++) {
|
return function(input, uppercase, color) {
|
||||||
out = input.charAt(i) + out;
|
var out = "";
|
||||||
|
for (var i = 0; i < input.length; i++) {
|
||||||
|
out = input.charAt(i) + out;
|
||||||
|
}
|
||||||
|
// conditional based on optional argument
|
||||||
|
if (uppercase) {
|
||||||
|
out = out.toUpperCase();
|
||||||
|
}
|
||||||
|
// DOM manipulation using $element
|
||||||
|
if (color) {
|
||||||
|
this.$element.css('color', color);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
// conditional based on optional argument
|
|
||||||
if (uppercase) {
|
|
||||||
out = out.toUpperCase();
|
|
||||||
}
|
|
||||||
// DOM manipulation using $element
|
|
||||||
if (color) {
|
|
||||||
this.$element.css('color', color);
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function Ctrl() {
|
function Ctrl() {
|
||||||
this.greeting = 'hello';
|
this.greeting = 'hello';
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div ng:controller="Ctrl">
|
<div ng:controller="Ctrl" ng:module="MyReverseModule">
|
||||||
<input ng:model="greeting" type="greeting"><br>
|
<input ng:model="greeting" type="greeting"><br>
|
||||||
No filter: {{greeting}}<br>
|
No filter: {{greeting}}<br>
|
||||||
Reverse: {{greeting|reverse}}<br>
|
Reverse: {{greeting|reverse}}<br>
|
||||||
|
|
|
||||||
|
|
@ -474,3 +474,11 @@ td.empty-corner-lt {
|
||||||
.error {
|
.error {
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.odd {
|
||||||
|
background-color: #808080;
|
||||||
|
}
|
||||||
|
|
||||||
|
.even {
|
||||||
|
background-color: #d3d3d3;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
<hr/>
|
<hr/>
|
||||||
<h2>Logs:</h2>
|
<h2>Logs:</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li ng:repeat="log in logs.$orderBy('-at')">
|
<li ng:repeat="log in logs | orderBy:'-at'">
|
||||||
{{log.at | date:'yy-MM-dd HH:mm'}} {{log.msg}}
|
{{log.at | date:'yy-MM-dd HH:mm'}} {{log.msg}}
|
||||||
[<a href="" ng:click="rmLog(log)">x</a>]
|
[<a href="" ng:click="rmLog(log)">x</a>]
|
||||||
</li>
|
</li>
|
||||||
|
|
|
||||||
132
src/Angular.js
132
src/Angular.js
|
|
@ -498,10 +498,6 @@ function map(obj, iterator, context) {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ngdoc function
|
|
||||||
* @name angular.Object.size
|
|
||||||
* @function
|
|
||||||
*
|
|
||||||
* @description
|
* @description
|
||||||
* Determines the number of elements in an array, the number of properties an object has, or
|
* Determines the number of elements in an array, the number of properties an object has, or
|
||||||
* the length of a string.
|
* the length of a string.
|
||||||
|
|
@ -512,29 +508,6 @@ function map(obj, iterator, context) {
|
||||||
* @param {Object|Array|string} obj Object, array, or string to inspect.
|
* @param {Object|Array|string} obj Object, array, or string to inspect.
|
||||||
* @param {boolean} [ownPropsOnly=false] Count only "own" properties in an object
|
* @param {boolean} [ownPropsOnly=false] Count only "own" properties in an object
|
||||||
* @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.
|
* @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* <doc:example>
|
|
||||||
* <doc:source>
|
|
||||||
* <script>
|
|
||||||
* function SizeCtrl() {
|
|
||||||
* this.fooStringLength = angular.Object.size('foo');
|
|
||||||
* }
|
|
||||||
* </script>
|
|
||||||
* <div ng:controller="SizeCtrl">
|
|
||||||
* Number of items in array: {{ [1,2].$size() }}<br/>
|
|
||||||
* Number of items in object: {{ {a:1, b:2, c:3}.$size() }}<br/>
|
|
||||||
* String length: {{fooStringLength}}
|
|
||||||
* </div>
|
|
||||||
* </doc:source>
|
|
||||||
* <doc:scenario>
|
|
||||||
* it('should print correct sizes for an array and an object', function() {
|
|
||||||
* expect(binding('[1,2].$size()')).toBe('2');
|
|
||||||
* expect(binding('{a:1, b:2, c:3}.$size()')).toBe('3');
|
|
||||||
* expect(binding('fooStringLength')).toBe('3');
|
|
||||||
* });
|
|
||||||
* </doc:scenario>
|
|
||||||
* </doc:example>
|
|
||||||
*/
|
*/
|
||||||
function size(obj, ownPropsOnly) {
|
function size(obj, ownPropsOnly) {
|
||||||
var size = 0, key;
|
var size = 0, key;
|
||||||
|
|
@ -566,11 +539,11 @@ function indexOf(array, obj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function arrayRemove(array, value) {
|
function arrayRemove(array, value) {
|
||||||
var index = indexOf(array, value);
|
var index = indexOf(array, value);
|
||||||
if (index >=0)
|
if (index >=0)
|
||||||
array.splice(index, 1);
|
array.splice(index, 1);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isLeafNode (node) {
|
function isLeafNode (node) {
|
||||||
if (node) {
|
if (node) {
|
||||||
|
|
@ -590,15 +563,6 @@ function isLeafNode (node) {
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* @description
|
* @description
|
||||||
* Alias for {@link angular.Object.copy}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ngdoc function
|
|
||||||
* @name angular.Object.copy
|
|
||||||
* @function
|
|
||||||
*
|
|
||||||
* @description
|
|
||||||
* Creates a deep copy of `source`, which should be an object or an array.
|
* Creates a deep copy of `source`, which should be an object or an array.
|
||||||
*
|
*
|
||||||
* * If no destination is supplied, a copy of the object or array is created.
|
* * If no destination is supplied, a copy of the object or array is created.
|
||||||
|
|
@ -614,46 +578,6 @@ function isLeafNode (node) {
|
||||||
* @param {(Object|Array)=} destination Destination into which the source is copied. If
|
* @param {(Object|Array)=} destination Destination into which the source is copied. If
|
||||||
* provided, must be of the same type as `source`.
|
* provided, must be of the same type as `source`.
|
||||||
* @returns {*} The copy or updated `destination`, if `destination` was specified.
|
* @returns {*} The copy or updated `destination`, if `destination` was specified.
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* <doc:example>
|
|
||||||
* <doc:source>
|
|
||||||
<script>
|
|
||||||
function Ctrl() {
|
|
||||||
this.master = {
|
|
||||||
salutation: 'Hello',
|
|
||||||
name: 'world'
|
|
||||||
};
|
|
||||||
this.copy = function() {
|
|
||||||
this.form = angular.copy(this.master);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<div ng:controller="Ctrl">
|
|
||||||
Salutation: <input type="text" ng:model="master.salutation" ><br/>
|
|
||||||
Name: <input type="text" ng:model="master.name"><br/>
|
|
||||||
<button ng:click="copy()">copy</button>
|
|
||||||
<hr/>
|
|
||||||
|
|
||||||
The master object is <span ng:hide="master.$equals(form)">NOT</span> equal to the form object.
|
|
||||||
|
|
||||||
<pre>master={{master}}</pre>
|
|
||||||
<pre>form={{form}}</pre>
|
|
||||||
</div>
|
|
||||||
* </doc:source>
|
|
||||||
* <doc:scenario>
|
|
||||||
it('should print that initialy the form object is NOT equal to master', function() {
|
|
||||||
expect(element('.doc-example-live input[ng\\:model="master.salutation"]').val()).toBe('Hello');
|
|
||||||
expect(element('.doc-example-live input[ng\\:model="master.name"]').val()).toBe('world');
|
|
||||||
expect(element('.doc-example-live span').css('display')).toBe('inline');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should make form and master equal when the copy button is clicked', function() {
|
|
||||||
element('.doc-example-live button').click();
|
|
||||||
expect(element('.doc-example-live span').css('display')).toBe('none');
|
|
||||||
});
|
|
||||||
* </doc:scenario>
|
|
||||||
* </doc:example>
|
|
||||||
*/
|
*/
|
||||||
function copy(source, destination){
|
function copy(source, destination){
|
||||||
if (!destination) {
|
if (!destination) {
|
||||||
|
|
@ -693,15 +617,6 @@ function copy(source, destination){
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* @description
|
* @description
|
||||||
* Alias for {@link angular.Object.equals}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ngdoc function
|
|
||||||
* @name angular.Object.equals
|
|
||||||
* @function
|
|
||||||
*
|
|
||||||
* @description
|
|
||||||
* Determines if two objects or two values are equivalent. Supports value types, arrays and
|
* Determines if two objects or two values are equivalent. Supports value types, arrays and
|
||||||
* objects.
|
* objects.
|
||||||
*
|
*
|
||||||
|
|
@ -720,43 +635,6 @@ function copy(source, destination){
|
||||||
* @param {*} o2 Object or value to compare.
|
* @param {*} o2 Object or value to compare.
|
||||||
* @returns {boolean} True if arguments are equal.
|
* @returns {boolean} True if arguments are equal.
|
||||||
*
|
*
|
||||||
* @example
|
|
||||||
* <doc:example>
|
|
||||||
* <doc:source>
|
|
||||||
<script>
|
|
||||||
function Ctrl() {
|
|
||||||
this.master = {
|
|
||||||
salutation: 'Hello',
|
|
||||||
name: 'world'
|
|
||||||
};
|
|
||||||
this.greeting = angular.copy(this.master);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<div ng:controller="Ctrl">
|
|
||||||
Salutation: <input type="text" ng:model="greeting.salutation"><br/>
|
|
||||||
Name: <input type="text" ng:model="greeting.name"><br/>
|
|
||||||
<hr/>
|
|
||||||
|
|
||||||
The <code>greeting</code> object is
|
|
||||||
<span ng:hide="greeting.$equals(master)">NOT</span> equal to
|
|
||||||
<code>{salutation:'Hello', name:'world'}</code>.
|
|
||||||
|
|
||||||
<pre>greeting={{greeting}}</pre>
|
|
||||||
</div>
|
|
||||||
* </doc:source>
|
|
||||||
* <doc:scenario>
|
|
||||||
it('should print that initialy greeting is equal to the hardcoded value object', function() {
|
|
||||||
expect(element('.doc-example-live input[ng\\:model="greeting.salutation"]').val()).toBe('Hello');
|
|
||||||
expect(element('.doc-example-live input[ng\\:model="greeting.name"]').val()).toBe('world');
|
|
||||||
expect(element('.doc-example-live span').css('display')).toBe('none');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should say that the objects are not equal when the form is modified', function() {
|
|
||||||
input('greeting.name').enter('kitty');
|
|
||||||
expect(element('.doc-example-live span').css('display')).toBe('inline');
|
|
||||||
});
|
|
||||||
* </doc:scenario>
|
|
||||||
* </doc:example>
|
|
||||||
*/
|
*/
|
||||||
function equals(o1, o2) {
|
function equals(o1, o2) {
|
||||||
if (o1 === o2) return true;
|
if (o1 === o2) return true;
|
||||||
|
|
|
||||||
4
src/angular-mocks.js
vendored
4
src/angular-mocks.js
vendored
|
|
@ -344,7 +344,9 @@ angular.mock.$Browser.prototype = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
addJs: function() {}
|
notifyWhenNoOutstandingRequests: function(fn) {
|
||||||
|
fn();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ angular.scenario.Application.prototype.executeAction = function(action) {
|
||||||
if (!$window.angular) {
|
if (!$window.angular) {
|
||||||
return action.call(this, $window, _jQuery($window.document));
|
return action.call(this, $window, _jQuery($window.document));
|
||||||
}
|
}
|
||||||
var element = $window.angular.element($window.document.body);
|
var element = $window.angular.element($window.document);
|
||||||
var $injector = element.inheritedData('$injector');
|
var $injector = element.inheritedData('$injector');
|
||||||
$injector(function($browser){
|
$injector(function($browser){
|
||||||
$browser.notifyWhenNoOutstandingRequests(function() {
|
$browser.notifyWhenNoOutstandingRequests(function() {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ngdoc function
|
* @ngdoc function
|
||||||
* @name angular.Array.filter
|
* @name angular.service.filter.filter
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* @description
|
* @description
|
||||||
|
|
@ -44,7 +44,7 @@
|
||||||
Search: <input ng:model="searchText"/>
|
Search: <input ng:model="searchText"/>
|
||||||
<table id="searchTextResults">
|
<table id="searchTextResults">
|
||||||
<tr><th>Name</th><th>Phone</th><tr>
|
<tr><th>Name</th><th>Phone</th><tr>
|
||||||
<tr ng:repeat="friend in friends.$filter(searchText)">
|
<tr ng:repeat="friend in friends | filter:searchText">
|
||||||
<td>{{friend.name}}</td>
|
<td>{{friend.name}}</td>
|
||||||
<td>{{friend.phone}}</td>
|
<td>{{friend.phone}}</td>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
Phone only <input ng:model="search.phone"/><br>
|
Phone only <input ng:model="search.phone"/><br>
|
||||||
<table id="searchObjResults">
|
<table id="searchObjResults">
|
||||||
<tr><th>Name</th><th>Phone</th><tr>
|
<tr><th>Name</th><th>Phone</th><tr>
|
||||||
<tr ng:repeat="friend in friends.$filter(search)">
|
<tr ng:repeat="friend in friends | filter:search">
|
||||||
<td>{{friend.name}}</td>
|
<td>{{friend.name}}</td>
|
||||||
<td>{{friend.phone}}</td>
|
<td>{{friend.phone}}</td>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,6 @@
|
||||||
* @param {string=} symbol Currency symbol or identifier to be displayed.
|
* @param {string=} symbol Currency symbol or identifier to be displayed.
|
||||||
* @returns {string} Formatted number.
|
* @returns {string} Formatted number.
|
||||||
*
|
*
|
||||||
* @css ng-format-negative
|
|
||||||
* When the value is negative, this css class is applied to the binding making it (by default) red.
|
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
<doc:example>
|
<doc:example>
|
||||||
|
|
@ -66,8 +64,6 @@
|
||||||
input('amount').enter('-1234');
|
input('amount').enter('-1234');
|
||||||
expect(binding('amount | currency')).toBe('($1,234.00)');
|
expect(binding('amount | currency')).toBe('($1,234.00)');
|
||||||
expect(binding('amount | currency:"USD$"')).toBe('(USD$1,234.00)');
|
expect(binding('amount | currency:"USD$"')).toBe('(USD$1,234.00)');
|
||||||
expect(element('.doc-example-live .ng-binding').prop('className')).
|
|
||||||
toMatch(/ng-format-negative/);
|
|
||||||
});
|
});
|
||||||
</doc:scenario>
|
</doc:scenario>
|
||||||
</doc:example>
|
</doc:example>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ngdoc function
|
* @ngdoc function
|
||||||
* @name angular.Array.limitTo
|
* @name angular.service.filter.limitTo
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* @description
|
* @description
|
||||||
|
|
@ -32,23 +32,23 @@
|
||||||
</script>
|
</script>
|
||||||
<div ng:controller="Ctrl">
|
<div ng:controller="Ctrl">
|
||||||
Limit {{numbers}} to: <input type="integer" ng:model="limit"/>
|
Limit {{numbers}} to: <input type="integer" ng:model="limit"/>
|
||||||
<p>Output: {{ numbers.$limitTo(limit) | json }}</p>
|
<p>Output: {{ numbers | limitTo:limit | json }}</p>
|
||||||
</div>
|
</div>
|
||||||
</doc:source>
|
</doc:source>
|
||||||
<doc:scenario>
|
<doc:scenario>
|
||||||
it('should limit the numer array to first three items', function() {
|
it('should limit the numer array to first three items', function() {
|
||||||
expect(element('.doc-example-live input[ng\\:model=limit]').val()).toBe('3');
|
expect(element('.doc-example-live input[ng\\:model=limit]').val()).toBe('3');
|
||||||
expect(binding('numbers.$limitTo(limit) | json')).toEqual('[1,2,3]');
|
expect(binding('numbers | limitTo:limit | json')).toEqual('[1,2,3]');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update the output when -3 is entered', function() {
|
it('should update the output when -3 is entered', function() {
|
||||||
input('limit').enter(-3);
|
input('limit').enter(-3);
|
||||||
expect(binding('numbers.$limitTo(limit) | json')).toEqual('[7,8,9]');
|
expect(binding('numbers | limitTo:limit | json')).toEqual('[7,8,9]');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not exceed the maximum size of input array', function() {
|
it('should not exceed the maximum size of input array', function() {
|
||||||
input('limit').enter(100);
|
input('limit').enter(100);
|
||||||
expect(binding('numbers.$limitTo(limit) | json')).toEqual('[1,2,3,4,5,6,7,8,9]');
|
expect(binding('numbers | limitTo:limit | json')).toEqual('[1,2,3,4,5,6,7,8,9]');
|
||||||
});
|
});
|
||||||
</doc:scenario>
|
</doc:scenario>
|
||||||
</doc:example>
|
</doc:example>
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@
|
||||||
<th><a href="" ng:click="predicate = 'phone'; reverse=!reverse">Phone Number</a></th>
|
<th><a href="" ng:click="predicate = 'phone'; reverse=!reverse">Phone Number</a></th>
|
||||||
<th><a href="" ng:click="predicate = 'age'; reverse=!reverse">Age</a></th>
|
<th><a href="" ng:click="predicate = 'age'; reverse=!reverse">Age</a></th>
|
||||||
<tr>
|
<tr>
|
||||||
<tr ng:repeat="friend in friends.$orderBy(predicate, reverse)">
|
<tr ng:repeat="friend in friends | orderBy:predicate:reverse">
|
||||||
<td>{{friend.name}}</td>
|
<td>{{friend.name}}</td>
|
||||||
<td>{{friend.phone}}</td>
|
<td>{{friend.phone}}</td>
|
||||||
<td>{{friend.age}}</td>
|
<td>{{friend.age}}</td>
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,9 @@
|
||||||
this.html = '<b>Hello</b> <i>World</i>!';
|
this.html = '<b>Hello</b> <i>World</i>!';
|
||||||
}
|
}
|
||||||
|
|
||||||
function HTMLEditorWidget(element) {
|
HTMLEditorWidget.$inject = ['$element', 'html$Filter'];
|
||||||
|
function HTMLEditorWidget(element, htmlFilter) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var htmlFilter = angular.filter('html');
|
|
||||||
|
|
||||||
this.$parseModel = function() {
|
this.$parseModel = function() {
|
||||||
// need to protect for script injection
|
// need to protect for script injection
|
||||||
|
|
@ -59,7 +59,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
angular.directive('ng:contenteditable', function() {
|
angular.directive('ng:contenteditable', function() {
|
||||||
function linkFn($formFactory, element) {
|
return ['$formFactory', '$element', function ($formFactory, element) {
|
||||||
var exp = element.attr('ng:contenteditable'),
|
var exp = element.attr('ng:contenteditable'),
|
||||||
form = $formFactory.forElement(element),
|
form = $formFactory.forElement(element),
|
||||||
widget;
|
widget;
|
||||||
|
|
@ -68,14 +68,12 @@
|
||||||
scope: this,
|
scope: this,
|
||||||
model: exp,
|
model: exp,
|
||||||
controller: HTMLEditorWidget,
|
controller: HTMLEditorWidget,
|
||||||
controllerArgs: [element]});
|
controllerArgs: {$element: element}});
|
||||||
// if the element is destroyed, then we need to notify the form.
|
// if the element is destroyed, then we need to notify the form.
|
||||||
element.bind('$destroy', function() {
|
element.bind('$destroy', function() {
|
||||||
widget.$destroy();
|
widget.$destroy();
|
||||||
});
|
});
|
||||||
}
|
}];
|
||||||
linkFn.$inject = ['$formFactory'];
|
|
||||||
return linkFn;
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<form name='editorForm' ng:controller="EditorCntl">
|
<form name='editorForm' ng:controller="EditorCntl">
|
||||||
|
|
|
||||||
|
|
@ -112,22 +112,20 @@ describe('angular.scenario.Application', function() {
|
||||||
expect(called).toBeTruthy();
|
expect(called).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should wait for pending requests in executeAction', function() {
|
it('should wait for pending requests in executeAction', inject(function($injector, $browser) {
|
||||||
var called, polled;
|
var called, polled;
|
||||||
var handlers = [];
|
var handlers = [];
|
||||||
var testWindow = {
|
var testWindow = {
|
||||||
document: _jQuery('<div class="test-foo"></div>'),
|
document: jqLite('<div class="test-foo"></div>'),
|
||||||
angular: {
|
angular: {
|
||||||
|
element: jqLite,
|
||||||
service: {}
|
service: {}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
testWindow.angular.service.$browser = function() {
|
$browser.notifyWhenNoOutstandingRequests = function(fn) {
|
||||||
return {
|
handlers.push(fn);
|
||||||
notifyWhenNoOutstandingRequests: function(fn) {
|
|
||||||
handlers.push(fn);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
testWindow.document.data('$injector', $injector);
|
||||||
app.getWindow_ = function() {
|
app.getWindow_ = function() {
|
||||||
return testWindow;
|
return testWindow;
|
||||||
};
|
};
|
||||||
|
|
@ -138,5 +136,6 @@ describe('angular.scenario.Application', function() {
|
||||||
});
|
});
|
||||||
expect(handlers.length).toEqual(1);
|
expect(handlers.length).toEqual(1);
|
||||||
handlers[0]();
|
handlers[0]();
|
||||||
});
|
dealoc(testWindow.document);
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,14 @@ describe("angular.scenario.dsl", function() {
|
||||||
var $window, $root;
|
var $window, $root;
|
||||||
var application, eventLog;
|
var application, eventLog;
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(inject(function($injector) {
|
||||||
eventLog = [];
|
eventLog = [];
|
||||||
$window = {
|
$window = {
|
||||||
document: _jQuery("<div></div>"),
|
document: jqLite('<div class="document"></div>'),
|
||||||
angular: new angular.scenario.testing.MockAngular()
|
angular: new angular.scenario.testing.MockAngular()
|
||||||
};
|
};
|
||||||
$root = angular.injector('NG')('$rootScope');
|
$window.document.data('$injector', $injector);
|
||||||
|
$root = $injector('$rootScope');
|
||||||
$root.emit = function(eventName) {
|
$root.emit = function(eventName) {
|
||||||
eventLog.push(eventName);
|
eventLog.push(eventName);
|
||||||
};
|
};
|
||||||
|
|
@ -45,6 +46,10 @@ describe("angular.scenario.dsl", function() {
|
||||||
// Just use the real one since it delegates to this.addFuture
|
// Just use the real one since it delegates to this.addFuture
|
||||||
$root.addFutureAction = angular.scenario.
|
$root.addFutureAction = angular.scenario.
|
||||||
SpecRunner.prototype.addFutureAction;
|
SpecRunner.prototype.addFutureAction;
|
||||||
|
}));
|
||||||
|
|
||||||
|
afterEach(function(){
|
||||||
|
jqLite($window.document).removeData('$injector');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Pause', function() {
|
describe('Pause', function() {
|
||||||
|
|
@ -201,11 +206,14 @@ describe("angular.scenario.dsl", function() {
|
||||||
// ex. jQuery('#foo').find('[name="bar"]') // fails
|
// ex. jQuery('#foo').find('[name="bar"]') // fails
|
||||||
// ex. jQuery('#foo [name="bar"]') // works, wtf?
|
// ex. jQuery('#foo [name="bar"]') // works, wtf?
|
||||||
//
|
//
|
||||||
beforeEach(function() {
|
beforeEach(inject(function($injector) {
|
||||||
doc = _jQuery('<div id="angular-scenario-binding"></div>');
|
doc = _jQuery('<div id="angular-scenario-binding"></div>');
|
||||||
_jQuery(document.body).html('').append(doc);
|
_jQuery(document.body).html('').append(doc);
|
||||||
$window.document = window.document;
|
|
||||||
});
|
dealoc($window.document); // we are about to override it
|
||||||
|
$window.document = window.document;
|
||||||
|
jqLite($window.document).data('$injector', $injector);
|
||||||
|
}));
|
||||||
|
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
_jQuery(document.body).
|
_jQuery(document.body).
|
||||||
|
|
|
||||||
|
|
@ -4,32 +4,18 @@ angular.scenario.testing = angular.scenario.testing || {};
|
||||||
|
|
||||||
angular.scenario.testing.MockAngular = function() {
|
angular.scenario.testing.MockAngular = function() {
|
||||||
this.reset();
|
this.reset();
|
||||||
this.service = this;
|
this.element = jqLite;
|
||||||
};
|
};
|
||||||
|
|
||||||
angular.scenario.testing.MockAngular.prototype.reset = function() {
|
angular.scenario.testing.MockAngular.prototype.reset = function() {
|
||||||
this.log = [];
|
this.log = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
angular.scenario.testing.MockAngular.prototype.element = function(e) {
|
|
||||||
return jqLite(e);
|
|
||||||
};
|
|
||||||
|
|
||||||
angular.scenario.testing.MockAngular.prototype.$browser = function() {
|
|
||||||
this.log.push('$brower()');
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
angular.scenario.testing.MockAngular.prototype.poll = function() {
|
angular.scenario.testing.MockAngular.prototype.poll = function() {
|
||||||
this.log.push('$brower.poll()');
|
this.log.push('$brower.poll()');
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
angular.scenario.testing.MockAngular.prototype.notifyWhenNoOutstandingRequests = function(fn) {
|
|
||||||
this.log.push('$brower.notifyWhenNoOutstandingRequests()');
|
|
||||||
fn();
|
|
||||||
};
|
|
||||||
|
|
||||||
angular.scenario.testing.MockRunner = function() {
|
angular.scenario.testing.MockRunner = function() {
|
||||||
this.listeners = [];
|
this.listeners = [];
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue