Compare commits

..

263 Commits

Author SHA1 Message Date
Igor Minar 652feebd86 chore(release): cut the 1.0.4 bewildering-hair release 2013-01-23 10:57:51 -08:00
Igor Minar 16ccbc4f61 docs(changelog): release notes for 1.1.2 and 1.0.4 2013-01-23 10:57:51 -08:00
Igor Minar 072d45fd01 chore(changelog.js): improve the changelog script 2013-01-23 10:57:51 -08:00
pavelgj 4439e39319 fix(ngResource): correct leading slash removal.
Fixed an issues with ngResource param substitution where it was incorrectly removing leading slash when param was followed by a non-slash character.
Ex:
'/:foo/:bar.baz/:aux'

params = {
  foo: 'aaa',
  bar: undefined,
  aux: undefined
}

The above params were incorrectly producing '/aaa.baz' but now it results in '/aaa/.baz'.
2013-01-22 11:32:27 -08:00
Miško Hevery b49c3a1a1e docs(q): added testing information 2013-01-22 11:32:27 -08:00
Igor Minar c7addd4886 fix(angular.equals): relax the comparison for undefined properties
in 5ae63fd3 the comparison was made consistent but strict, so that

angular.equals({}, {foo: undefined}) // always returns false

this turns out to cause issues for data that is being roundtripped via network
and serialized via JSON because JSON.stringify serializes {foo: undefined} as {}.

Since angular.equals() behaved like this before the 5ae63fd3 in 50% of the cases,
changing the behavior in this way should not introduce any significant issues.

Closes #1648
2013-01-22 07:35:06 -08:00
Igor Minar 6df60aff52 chore(Rakefile): skip build parallelization on Travis
Due to a infrastructure change on Travis starting JVMs in forked
processes doesn't currently work. Since we don't really care that
much about the build speed on Travis, I'm going to disable it there.

Related issue: https://github.com/travis-ci/travis-ci/issues/845
2013-01-21 07:50:24 -08:00
sergiopantoja e7a080d6e6 docs(jqLite): fix typo 2013-01-20 18:59:43 +01:00
Will Moore 661a728764 docs(contribute): adding npm install to step-by-step
npm install is listed in the dependencies section of the contribute guide but
is missing from the step-by-step. This adds it as step 4.
2013-01-18 21:33:58 -08:00
danilsomsikov 89303fd2dc fix(ngSwitch): don't leak when destroyed while not attached
The leak can occur when ngSwich is used inside ngRepeat or any other
directive which is destroyed while its transcluded content (which
includes ngSwitch) is not attached to the DOM.

Refactor ngSwitch to use controller instead of storing data on compile
node. This means that we don't need to clean up the jq data cache.
Controller reference is released when the linking fn is released.

Closes #1621
2013-01-18 00:03:42 -08:00
Fred Sauer 1f8be1ca66 docs(exceptionHandler): document testing
Update src/ng/exceptionHandler.js

Here's an iniitla attempt at documenting how one might write a
test using $exceptionHandlerProvider. The key take-away is the use
of this pattern:

it(...

 module(...
   $exceptionHandlerProvider.mode('log');
 });

 inject(...
 );

});
2013-01-17 23:11:02 -08:00
Matthew Browne cbc2024092 docs(rootScope): correct code examples 2013-01-17 23:11:02 -08:00
Amir H. Hajizamani f0ff7023c3 docs(cookbook): change prototype methods to scope methods in Buzz
As explained in 'Understanding the Controller Component', Controllers
written for new (post 1.0 RC) versions of Angular need to add methods to
the scope directly, not the function's prototype. Correcting this
example should remove any ambiguity, especially for beginners.
2013-01-18 00:56:52 -05:00
Amir H. Hajizamani 6e8728a364 docs(guide): change prototype methods to scope methods in DI examples
As explained in 'Understanding the Controller Component', Controllers
written for new (post 1.0 RC) versions of Angular need to add methods to
the scope directly, not the function's prototype. Correcting this
example should remove any ambiguity, especially for beginners.
2013-01-18 00:56:52 -05:00
Fred Sauer f179a63dd4 docs(ngMock.$httpBackend): fix variable declaration 2013-01-18 00:15:20 -05:00
Shai Reznik 3a71c1e595 doc(guide): Fix examples of $location.html5mode 2013-01-17 23:46:19 -05:00
Shai Reznik ef7a61a67e doc(guide): Fixed typos at the unit tests guide 2013-01-17 23:46:19 -05:00
Igor Minar a6b2ee785b fix(angular.equals): consistently compare undefined object props
previously:

a = {};
b = {x:undefined};
angular.equals(a, b) == angular.equals(b, a) // returns false.

both should return false because these objects are not equal.

unlike in implemented in #1695 the comparison should be stricter
and return false not true. if we need to relax this in the future
we can always do so.

Closes #1648
2013-01-17 17:49:07 -08:00
Daniel Demmel d5a1336e6b docs: recommend using Google CDN 2013-01-17 16:53:32 -08:00
Matt Rohrer d4312b731a docs(guide): minor grammar fixes 2013-01-17 19:36:14 -05:00
Martin Probst 66f051386e feat($compile): support modifying the DOM structure in postlink fn
Support modifying the DOM structure in the post link function of a directive
by creating a defensive copy of the node list, as opposed to a live DOM list.
This is useful for directives to actually replace their entire DOM fragment,
e.g. with the HTML fragment generated by a 3rd party component (Closure, Bootstrap ...).
Fix the indentation of the compileNodes function (was one too little).
2013-01-17 12:57:36 -08:00
Igor Minar 8b3f9684e0 style($compile): fix indentation 2013-01-17 12:55:21 -08:00
Gergely Imreh 331f32deac chore(Rakefile): force 32bit JVM mode only when java supports it
Some Java installs don't have '-d32' flag (e.g. OpenJDK which is standard
for some Linux systems), and the closure_compile fails because of forcing
that flag. Test, and only run in faster 32bit mode if supported, or
else just run with no flag (default mode).
2013-01-17 10:44:39 -08:00
Igor Minar bb80c96754 chore(docs): use done() instead of end() in gen-docs.js 2013-01-17 00:52:19 -08:00
Pete Bacon Darwin 0d8e19c26f fix($compile): do not wrap empty root text nodes in spans
Closes #1059
2013-01-17 00:28:56 -08:00
Pete Bacon Darwin ed2fd2d0ca fix(ngRepeat): correctly apply $last if repeating over object
If the $last property is calculated from the original collectionLength
on an object and properties starting with $ were filtered out, then $last
is never applied and $middle is applied erroniously.

Closes #1789
2013-01-17 00:25:07 -08:00
James deBoer 7c60151cb8 chore(Rakefile): remove a duplicate file in angularFiles.js 2013-01-16 23:45:13 -08:00
James deBoer 965308a32c chore(Rakefile): generate version.json
Changes 'rake version' to output a version.json file which
contains the structured version info which can be used in other tools.
2013-01-16 23:41:51 -08:00
Igor Minar 92c612a9de fix(scenario): don't trigger input events on IE9
input.enter() should trigger 'change' rather than 'input' event on IE9 because
input events on IE9 are broken and angular doesn't rely on them
2013-01-16 23:30:16 -08:00
Kanwei Li a7b53abcad docs(CHANGELOG): fix typo 2013-01-16 23:29:11 -08:00
Martin Probst d575e1f613 fix($route): support route params not separated with slashes.
Commit 773ac4a broke support for route parameters that are not seperated
from other route parts by slashes, which this change fixes. It also adds
some documentation about path parameters to the when() method and
escapes all regular expression special characters in the URL, not just
some.
2013-01-16 09:42:35 -08:00
Igor Minar 2ba458387d fix($compile): safely create transclude comment nodes
Closes #1740
2013-01-14 21:59:23 -08:00
Lucas Galfasó 98489a1d0c doc(directive): Fix typos in dialog widget
Fixes #1799
2013-01-13 10:09:22 +00:00
Igor Minar 51d501aab2 chore(*): remove obsolete files 2013-01-09 21:29:13 -08:00
naomiblack 841bdf1c07 Update docs/content/misc/faq.ngdoc
Updated the canonical video to a recent one. Fixed a typo.
2013-01-09 09:50:27 +00:00
Pete Bacon Darwin 86cac55c7c fix(jqLite): children() should only return elements
The jQuery implementation of children only returns child nodes of the given element that are elements themselves. The previous jqLite implementation was returning all nodes except those that are text nodes. Use jQLite.contents() to get all the child nodes.

The jQuery implementation of contents returns [] if the object has no child nodes.  The previous jqLite implementation was returning undefined, causing a stack overflow in test/testabilityPatch.js when it tried to `cleanup()` a window object.

The testabilityPatch was incorrectly using children() rather than contents() inside cleanup() to iterate down through all the child nodes of the element to clean up.
2013-01-09 09:42:05 +00:00
Keyamoon c0995399d4 fix(jqLite): make next() ignore non-element nodes
next() is supposed to return the next sibling *element* so it
should ignore text nodes. To achieve this, nextElementSibling()
should be used instead of nextSibling().
2013-01-08 14:54:56 -08:00
Igor Minar de6cc287e5 fix($injector): remove bogus fn arg
getService fn takes only one argument, removing the second one.

Closes #1711
2013-01-08 14:36:36 -08:00
Igor Minar afd6771163 refactor($browser): remove faulty 20+ cookies warning
the warning is defunct (and the test is incorrect) so obviously nobody is using
it and it just takes up space.

also the browser behavior varies (ff and chrome allow up to 150 cookies, safari
even more), so it's not very useful.

Closes #1712
2013-01-08 14:27:51 -08:00
Igor Minar 4cda028609 revert: fix(a): prevent Opera from incorrectly navigating on link click
This reverts commit c81d8176cc.

This commit causes several issues (#1651, #1674, #1662) and doesn't even
contain a test that proves that anything on Opera got actually fixed.

If the original Opera resurfaces, we'll fix it properly.
2013-01-08 11:51:17 -08:00
kim lokoy 8ecce7642b docs(guide): fix typos in unit test guide 2013-01-07 21:00:13 +01:00
Pawel Kozlowski d1d5761232 docs(forms): fix code example for a custom form control
Closes #1021
2013-01-05 23:04:33 +01:00
naomiblack 759cba1a8d docs(faq): add info on logo reuse and how to get t-shirts and stickers 2013-01-04 19:22:00 +01:00
Jonathan Card 23cd40a8ec docs(form): minor form doc and example fixes
Form documentation fixes:
- Fix broken form example in docs
- A few small other corrections in form docs.
2013-01-04 17:25:24 +01:00
Per Rovegård f3188c1d09 docs($http): clarify documentation on error status codes
Modify the documentation for $http to correspond to what Angular
considers a success status code.

Closes #1693
2013-01-03 20:47:55 +01:00
Matt Hardy 2f4967f100 docs(guide): change example controller to properly call greet method on greeter 2012-12-31 13:21:29 +01:00
Murilo da Silva 4fe4e7457c docs(anchorScroll): correct word "location" 2012-12-19 21:14:09 +01:00
John Fletcher d4e7274d4b docs(guide): minor English corrections to the Directive guide 2012-12-19 20:55:22 +01:00
Miško Hevery cffa015554 docs(directive): old syntax 2012-12-18 20:39:17 -08:00
Pawel Kozlowski 1104c7d75b docs(ngView): fix code example (change template to templateUrl)
Closes #1715
2012-12-18 17:56:04 +01:00
Gonzalo Ruiz de Villa 4c6b4447db fix($route): correctly extract $routeParams from urls
Routes like '/bar/foovalue/barvalue' matching '/bar/:foo/:bar'
now are well mapped in $routeParams to:
{bar:'barvalue', foo:'foovalue'}

Closes: #1501
Signed-off-by: Gonzalo Ruiz de Villa <gonzaloruizdevilla@gmail.com>
2012-12-14 01:16:07 +01:00
ggoodman 741a37b338 feat(docs): Add angularjs tag to plunks and make private
This is a minor edit to allow Plunks created by way of the docs.angularjs.org site to be appropriately tagged as `angularjs`.
Also, make these generated Plunks private by default.
2012-12-12 21:00:41 +00:00
Peter Evjan 1157c5d341 docs(README.md): add missing 'you' and a comma 2012-12-11 19:33:28 +01:00
Romain Neutron e48adebfb7 docs(guide): fix injector service code example
Fix syntax and update code to the latest API
2012-12-10 23:50:12 +01:00
Juha Syrjälä 0a61dcb486 docs($resource): document port number escaping and fix typo 2012-12-09 17:49:42 +01:00
Eric Case 4b51eaadf8 docs(tutorial): typo fix commandx -> command 2012-12-08 11:39:56 +01:00
Eric Case e2457ca16d docs($q): typo fix - programing -> programming 2012-12-07 21:00:25 +01:00
János Rusiczki bd62790080 doc(concepts): Fix typo in $render() function 2012-12-07 10:19:08 +00:00
Jeremy Tymes 53fdcafa44 docs($http): fix link typo in $http doc
Should be $httpBackend instead of $httpBacked

Closes #1516
2012-12-06 21:50:21 +01:00
Fred Sauer af6f2483be docs(mocks): update src/ngMock/angular-mocks.js documentation
Clarify how to use `$exceptionHandlerProvider.mode('log')` in tests
2012-12-06 21:50:21 +01:00
Fred Sauer d8522aa349 docs(mocks): fix documentation bug: angular.mock.debug 2012-12-06 21:50:20 +01:00
Igor Minar bae3121683 chore(bootstrap-prettify): update urls to code.angularjs.org
Closes #1599
2012-12-05 02:55:19 +01:00
_pants 54c0d464b0 fix(select): support optgroup + select[multiple] combo
Closes #1553
2012-12-05 02:21:31 +01:00
Sudhir Jonathan cf89e8653c fix($injector): provider can now be defined in the array format
`injector.instantiate` is now called for arrays too, instead of only for functions.

Closes #1452
2012-12-01 19:09:36 +01:00
Sudhir Jonathan 0c3500f532 fix($resource): HTTP method should be case-insensitive
Perform call `angular.uppercase` on all given action methods.

Closes #1403
2012-11-30 23:23:34 +01:00
Cezar Berea c12f525df4 refactor($resource): fix indentation and move a method definition
Moved Resource.bind out of the actions forEach
2012-11-30 22:47:25 +01:00
Igor Minar e7ba830691 fix(Scope): ensure that a scope is destroyed only once
Due to bd524fc4 calling $destroy() on a scope mupltiple times cases NPE.

Closes #1627
2012-11-30 13:09:50 +01:00
Daniel Luz 4eb0716711 docs(directive): correct expression, fix typo and re-wrap lines 2012-11-29 20:22:41 +01:00
Johannes Hansen ed90f3b7ea fix(docs): add missing </div> tag to sourceEdit directive template 2012-11-29 20:22:40 +01:00
Igor Minar 14b19ecf5e docs(menu): fix the navbar drop down links 2012-11-28 23:56:21 +01:00
Igor Minar 644432a14c chore(release): start 1.0.4 bewildering-hair iteration 2012-11-28 15:51:23 +01:00
Igor Minar a03e370a09 chore(release): cut the 1.0.3 bouncy-thunder release 2012-11-27 01:44:46 +01:00
Igor Minar 23677d3ddb docs(CHANGELOG): release notes for 1.0.3 and 1.1.1 releases 2012-11-27 01:44:46 +01:00
Rado Kirov fc781560a3 fix($location): reset $location.$$replace with every watch call
Closes #1111
2012-11-26 23:24:39 +01:00
Vojta Jina c9199ee663 docs: load angular from CDN only on production
So that when running the docs locally, eg. during e2e testing, we use the latest build version of angular, rather than the stable one from CDN.

This fixes e2e tests running with Testacular.
2012-11-26 21:33:45 +01:00
Igor Minar 6f18adedef fix(ngClassOdd/ngClassEven): support shrinking/reordering in repeaters
We need to watch $index in addition to cssClasses because only then
we can correctly respond to shrinking or reordered repeaters.

Closes #1076
2012-11-26 21:33:45 +01:00
Igor Minar 6ad894cd58 style(jqLite): better variable names
selector => cssClasses
2012-11-26 21:33:45 +01:00
Igor Minar cde2f1a868 fix(ngRepeat): support mostly-stable repeating for primitives
I'm reverting changes that were originally done to ngRepeat to fix #933,
because these are now not necessary after the previous changes to keep
ngModel always synced with the DOM.
2012-11-26 21:33:45 +01:00
Igor Minar 6a831495de fix(ngModel): sync ngModel state with scope state
In cases when we reuse elements in a repeater but associate
them with a new scope (see #933 - repeating over array of
primitives) it's possible for the internal ngModel state and
the scope state to get out of sync. This change ensure that
the two are always sync-ed up even in cases where we
reassociate an element with a different (but similar) scope.

In the case of repeating over array of primitives it's still
possible to run into issue if we iterate over primitives and
use form controls or similar widgets without ngModel - oh well,
we'd likely need a special repeater for primitives to deal
with this properly, even then there might be cornercases.

Closes #933
2012-11-26 21:33:45 +01:00
Igor Minar 6e2c38f54d test(ngRepeat): clean up and improve tests 2012-11-26 20:39:10 +01:00
Igor Minar 00e7e31418 fix(ngRepeat): attempt to simplify and improve existing fix for #933
I'm keeping this in for future reference. The issue with this solution
is that if we shift() the first item in the array, the whole repeater
DOM will be rebuilt from scratch, we need to do better than that.
2012-11-26 20:39:00 +01:00
Igor Minar ff4b3e20c1 test(ngRepeat): add test for issue #1076 2012-11-26 20:38:51 +01:00
Igor Minar 269fb43b36 fix(jqLite): fire $destroy event via triggerHandler
in jQuery 1.8.x the data() data structure is changed and events are
not accessible via data().events. Since all we need is to trigger
all event handlers, we can do so via triggerHandler() api instead of
mocking with the internal jQuery data structures.

This fix was originally proposed by PeteAppleton via PR #1512.

Closes #1512
2012-11-26 16:03:43 +01:00
Igor Minar 7530654328 feat(jqLite): add triggerHandler()
we need triggerHandler() to become jQuery 1.8.x compatible.

this is not fully featured triggerHandler() implementation - it doesn't
bother creating new DOM events and passing them into the event handlers.

this is intentional, we don't need access to the native DOM event for our
own purposes and creating these event objects is really tricky.
2012-11-26 16:03:39 +01:00
Iristyle c7bd464384 docs(CONTRIBUTING.md): add contrib info file for GitHub 2012-11-25 21:00:56 +01:00
Vojta Jina ef1874d1f3 fix(Scope): allow removing a listener during event 2012-11-25 11:41:32 +01:00
Kevin Western c6d8205fdd docs(README.md): fix "API Docs" link
use direct link to api docs
2012-11-25 01:24:03 +01:00
Dean Sofer 55150a669a docs(api): add ngRequired to input/select/textarea directives
Closes #1202
2012-11-25 01:19:47 +01:00
Jeremy Tymes 1eb9e22d45 fix($cacheFactory): return undefined when removing non-existent entry
Instead of throwning an exception, remove should return undefined when
cache entry to be removed doesn't exist.

Closes #1497
2012-11-24 21:58:17 +01:00
Adrian Gheorghe c0de8fb737 fix($resource): prevent default params to be shared between actions
Having a $resource defined as:

var R = $resource('/Path', {}, {
  get: {method: 'GET', params: {objId: '1'}},
  perform: {method: 'GET'}
});

was causing both actions to call the same URI (if called in this order):

R.get({}); // => /Path?objId=1
R.perform({}); // => /Path?objId=1
2012-11-24 21:29:16 +01:00
Kris Jenkins 557e3894d7 docs(): Fix a couple of typos in the documentation 2012-11-22 08:28:49 +01:00
Dave Clayton 38a9695413 docs(guide/concepts): some typo/grammar fixes 2012-11-22 08:28:49 +01:00
John Hume 293e0336b0 docs(guide/directive): fix typo 2012-11-22 08:28:49 +01:00
Uri Goldshtein 1f5bc0a1cd docs($q): fix missing bracket in the example 2012-11-22 08:28:49 +01:00
Igor Minar 1fe666192b fix($rootScope): workaround for Chrome's memleak
Under certain circumstances chrome fails to GC scopes
because of buggy optimizations and caching. Nulling out
references to (not from!) other scopes helps Chrome to
realize that this object should be GC-ed.

This is really just a workaround as the real problem needs
to be fixed in Chrome.

See discusstion at:
https://github.com/angular/angular.js/issues/1313#issuecomment-10378451

And chrome bug at:
https://code.google.com/p/v8/issues/detail?id=2073

Closes #1313
2012-11-14 19:53:29 +01:00
Igor Minar 29541e735d revert($resource): support custom headers per action
This reverts commit b936e52874.

This commit introduces a feature and should haven't been merged
into the stable branch.
2012-11-11 12:07:26 +01:00
Igor Minar f5b567d44b chore(validate-commit-msg): recognize 'revert' as valid commit type 2012-11-11 12:06:05 +01:00
Haralan Dobrev 5ee3bbee90 docs(angular.module): improve angular.Module#run docs 2012-11-11 11:40:52 +01:00
Jamison Dance 80927c5811 docs(guide): fix run-on sentence in modules guide 2012-11-11 11:35:20 +01:00
Jamison Dance ca8b344e20 docs(tutorial): change module name in step-7 2012-11-11 11:35:15 +01:00
Wes Alvaro 3dab93874d docs($timeout): set return type to Promise instead of *.
The cancel function accepts a Promise, but the timeout function
fails to specify returning a Promise.
2012-11-11 11:32:00 +01:00
Josh Adams 7550f90a57 docs(ngList): fix typo 2012-11-11 11:25:40 +01:00
Josh Adams d78fea87d1 docs(encodeUriSegment): fix typo 2012-11-11 11:23:46 +01:00
Tim Macfarlane 27cee7db0a docs(guide/directive): fix names in scope '='; easier to grok 2012-11-11 11:20:57 +01:00
Christian Vuerings 60acba3840 docs(ngHide): Fix typo and make it more in line with ngShow 2012-11-11 10:37:59 +01:00
Igor Minar 51bed36370 chore(docs): fix docs-scenario.html 2012-11-08 22:18:34 +01:00
Igor Minar 6d940213ac chore(docs): remove obsolete gae files 2012-11-08 22:18:34 +01:00
Miško Hevery 494b527fa7 docs(directive): fix typo 2012-11-05 19:35:31 -08:00
Sudhir Jonathan 8ce84cb2ea chore(testacular): use local testacular version
Making testacular a dependency to avoid having to install it globally.
(Causes npm issues on some machines)
2012-10-31 17:00:00 -07:00
Sudhir Jonathan d981c2a3ec fix(select): select option with a label of 0 is not shown
Bug caused by the use of the `||` operator to replace all non-truthy
values with an empty string. Changed to replace only `undefined` values.

Closes #1401
2012-10-31 15:03:48 -07:00
Igor Minar 537e20065a chore(validate-commit-msg): allow '/' in scope 2012-10-31 14:48:24 -07:00
Fred Sauer 97578b4dae docs(guide/location): fix table formatting
Fix table formatting so headings are bold, rows are separated by lines, and rows have :hover style
2012-10-31 14:48:18 -07:00
Tim Macfarlane fa12564607 docs(module): fix typo in example
fixed example app, `simpleAppModule` should have been `myAppModule`.
2012-10-31 14:22:12 -07:00
sqwishy trick 54bcb9ae25 chore(injector): fix typo in injector documentation 2012-10-31 14:19:52 -07:00
Adam Macejak ad7ce0d402 fix(scenario-runner): support data-ng and x-ng based attributes
Prefixed attributes like data-ng-model and x-ng-model were not being
found by the Selector. It was only looking at ng: and ng- prefixed
attributes.
Added a few tests as well to ensure the aforementioned prefixed
attributes are being matched properly.

Closes #1020
2012-10-31 14:10:26 -07:00
Daniel Luz 085e0ea8ef docs(contribute): fix task name for continuous testing 2012-10-31 13:13:33 -07:00
Igor Minar bb52c4e8d3 fix(docs): correctly generate filenames for plunkr/fiddle
previously examples like $http where broken because we would strip part of the
filename (http-hello.html -> http)

we really want to strip only the id suffix that we append to disambiguate
common filenames (like index.html) which appear in many examples.
2012-10-31 13:06:22 -07:00
Shyam Seshadri 295af335c1 feat(docs): add plunkr support
Add option to edit source in Angular Docs in Plunkr in addition to JsFiddle
2012-10-31 13:06:16 -07:00
Daniel Luz 2c2e18c37a fix(doc): typo on FAQ
Closes #1493
2012-10-31 10:26:00 -07:00
Igor Minar adfb75e3c6 fix($compile): don't look for class directives in empty string
if className is undefined or empty string, don't bother looking for directives in there
2012-10-29 19:39:34 -07:00
Igor Minar 9bff5c60df fix($compile): compilation should not recurse into empty nodes
if a node doesn't have children then don't try to compile these non-existent children
2012-10-29 19:39:21 -07:00
Igor Minar 3ba008d4b2 style($compile): better fn names for debugging 2012-10-29 19:38:57 -07:00
Igor Minar 4e45a2f8e2 refactor($compile): simplify nodeLinkFn 2012-10-29 19:38:29 -07:00
Igor Minar 4dbd8452eb fix($compile): prevent double attr interpolation w/ templateUrl
This fixes the issue that caused two attr interpolation observers
to be registered for the same attribute as a result of isolate
scope definition with attr (@) property for this attribute.

Duplicate observers would then fight with each other updating the
model.

The issue occured only when this directive was used in a repeater
because that's when we clone the template node which caused the
two observers to point to two different sets of $attr instances.

Closes #1166, #836
2012-10-29 19:38:03 -07:00
Braden Shepherdson 45a8db9c08 fix(currency): Handle not-quite-zero values
IEEE 754 floating point sometimes results in values that are very small,
rather than zero. One example is 1.0 + 1.07 - 2.07, which returns
4.440892098500626e-16 instead of 0.

This change tweaks the number formatting logic so that an exponential
value with a negative exponent that is larger than the precision+1
returns 0 instead. For example: with precision 2, anything with an
exponent of -4, -5 or more would become 0. 9e-3 = 0.009 = 0.01, but 9e-4
= 0.0009 = 0.001 = 0.00. This detail is unlikely to matter since this
quirk is usually only triggered with values very close to zero.

Closes #1469
2012-10-29 19:37:52 -07:00
Braden Shepherdson d930a410fb doc(faq): Add Common Pitfalls section
Describes several common pitfalls new users of Angular fall into that
I've observed in #angularjs.
2012-10-29 19:37:38 -07:00
Braden Shepherdson 66505ffc40 doc(faq): Fix minor spelling and wording errors 2012-10-29 19:37:29 -07:00
Igor Minar 045de959b9 chore(check-size.sh): fix rake target 2012-10-29 19:37:21 -07:00
Igor Minar 3ca11d5235 docs(contribute): add CLA note to code submission section 2012-10-19 09:15:34 -07:00
Igor Minar d5d8ac01e3 docs(contribute): add visible link to github project 2012-10-19 09:15:34 -07:00
Igor Minar ace81c053c chore(validate-commit-msg): allow * and - in scope string 2012-10-18 03:29:12 -07:00
Igor Minar 1e95c419b8 chore(jasmine): remove Jasmine from our repo
it's bundled with Testacular, so we don't need it here
2012-10-18 03:29:12 -07:00
Igor Minar 49ed63d26a chore(jstd): remove JsTestDriver from our repo
Testacular FTW!
2012-10-18 03:29:12 -07:00
Igor Minar 6ff2685668 docs(tutorial): replace JsTD with Testacular + drop snapshots
JsTD references have been replaced with Testacular stuff.

snapshots are PITA to maintain so I'm dropping them, everyone loves the Git
version anyway.
2012-10-18 02:34:27 -07:00
Igor Minar c4573c04aa chore(Rakefile): remove test_out dir when cleaning 2012-10-17 20:20:54 -07:00
Igor Minar d57abdb3f7 chore(Rakefile): tune JVM for closure compiler
Using the client VM and forcing 32bit mode gives us huge perf boost.

before:

reali   0m8.173s
user    0m39.984s
sys     0m1.408s

after:

real    0m3.000s
user    0m12.687s
sys     0m0.852s
2012-10-17 20:20:53 -07:00
Igor Minar 4050e89446 chore(Rakefile): paralelize closure compilation
this speeds up the build by paralelizing closure compilation (the slowest
piece of the build process)

before:

real  0m14.372s
user  0m31.649s
sys   0m1.006s

after:

real  0m8.191s
user  0m40.473s
sys   0m1.378s
2012-10-17 20:16:36 -07:00
Vojta Jina b6620c737f chore(test): add junit config for testacular 2012-10-17 20:16:36 -07:00
Igor Minar 0c8e908841 chore(Rakefile): misc_options should support + -> , conversion 2012-10-17 20:16:35 -07:00
Igor Minar 5595e196a8 chore(Rakefile): use exec for webserver
exec unlike system replaces the current process. this way when we kill
the webserver process we don't get scary looking 'rake aborted' error
2012-10-17 12:44:38 -07:00
Misko Hevery f92e4146d1 fix(doc): disable directory listing in docs.angularjs.org 2012-10-08 15:09:06 -07:00
Vojta Jina 8b7108e3c9 chore: add travis config 2012-10-05 10:20:02 -07:00
Igor Minar caf702cc88 docs(downloading): update the downloading docs 2012-10-05 03:15:11 -07:00
Vojta Jina cf2c49ed7f fix($compile): reference local in isolate scope
This was really corner case:
Watcher needs to return changed value, to notify that model might have changed and one more $digest cycle needs to be performed.

The watcher, that takes care of reference binding into an isolate scope ("="), did not return changed value, if the change was from the isolate scope to the parent.

If any other watcher returned change, it worked fine, as this change caused re-digest.

Closes #1272
2012-09-22 12:00:16 -07:00
Igor Minar ccd52abf5d docs(README): update README.md with new rake tasks 2012-09-17 14:52:06 -07:00
Igor Minar 74c574015d chore(Rakefile): fix test:jquery task 2012-09-17 14:52:06 -07:00
Igor Minar 1f1a6fb6d2 docs(contribute): update contribute docs 2012-09-17 09:46:34 -07:00
Igor Minar 8632e893b0 chore(): remove unused files 2012-09-17 09:46:34 -07:00
Igor Minar c2b6e127fa docs(contribute): update misc/contribute docs with Testacular info 2012-09-17 09:46:34 -07:00
Igor Minar 06eceeb09f chore(testing): Testacular config files + rake tasks
- adds testacular config files for jqlite, jquery, modules and e2e tests
- replaces obsolete JsTD Rake tasks with Testacular onces
- rake tasks are parameterazied so that they can be used locally as well as on CI server

usage:

rake test  # run all tests on Chrome
rake test[Safari+Chrome+Opera]  # run all tests on Safari, Chrome and Opera
rake test[Safari]  # run all tests on Safari
rake test:jqlite # run unit tests using jqlite on Chrome
rake test:jqlite[Safari,"--reporter=dots"]  # run jqlite-based unit tests on Safari with dots reporter
rake autotest:jquery  # start testacular with jquery-based config and watch fs for changes
rake test:e2e # run end to end tests
2012-09-17 09:46:13 -07:00
Miško Hevery 8133d468b9 docs(directive): remove reference to old isolation syntax 2012-09-13 11:32:13 -07:00
Misko Hevery 074a354fa9 fix($route): support inline annotation on .resolve 2012-09-11 23:16:41 -07:00
Vojta Jina e191582a02 chore(scripts): add init-repo script 2012-09-11 23:16:38 -07:00
Jay Zeng 6fbe926cda docs(ngResource): Spelling typo (agressive => aggressive) 2012-09-11 16:39:46 -07:00
Igor Minar ebbc224e09 fix($resource): fix isDefined -> angular.isDefined 2012-09-11 16:39:46 -07:00
Shyam Seshadri 2c6aa4c300 fix(*): name all anonymous watch functions in Angular
This will allow us to see function names in Batarang and debugger.

Closes #1119
2012-09-11 16:39:46 -07:00
Zhenbo Zhang f7a8f17fc7 fix(ng-repeat) to work with primitive types 2012-09-11 16:38:42 -07:00
Brian Ford 191efbb558 docs(guide): fix directive interpolation example code
Closes #1339
2012-09-11 16:19:45 -07:00
Shyam Seshadri bf873d6f02 fix(scenario): emit RunnerBegin event 2012-09-11 16:19:44 -07:00
Vojta Jina e741107c55 chore(scripts): add commit-msg hook (validation) 2012-09-11 16:19:44 -07:00
Jimmy Zhuo 82f4b99d99 fix(scenario): NPE when no angular loaded in test page 2012-09-11 16:19:44 -07:00
Daniel Luz 7210b7ae1d docs($rootScope): fix iteration limit described by $watch, it's actually 10 as of now 2012-09-11 16:19:44 -07:00
Daniel Luz afed23c001 docs($rootScope): fix typos and minor wording tweaks on $watch 2012-09-11 16:19:44 -07:00
Daniel Luz 1f69cc2989 docs($rootScope): fix quoting on expression 2012-09-11 16:19:43 -07:00
Daniel Luz 3401833c83 docs($rootScope): standardize on present, third-person actions for descriptions 2012-09-11 16:19:43 -07:00
Daniel Luz 06606e2816 docs($rootScope): backquote attribute types too on $on 2012-09-11 16:19:43 -07:00
Daniel Luz eba64e1f31 docs($cacheFactory): fix backquotes on method descriptions 2012-09-11 16:19:43 -07:00
Daniel Luz 81dd1df1b1 docs($rootScope): fix typos on $new 2012-09-11 16:19:43 -07:00
Daniel Luz dbafbb0de5 docs($rootScope): fix typo on $eval 2012-09-11 16:19:42 -07:00
Daniel Luz 1d0aa7b7c6 docs($rootScope): fix typos on $watch 2012-09-11 16:19:42 -07:00
Igor Minar afd02ca48c fix(docs): update docs top menu links 2012-09-06 15:56:11 -07:00
sgtpep 67db7616ad fix(a): prevent Opera from incorrectly navigating on link click
we handle the navigation by ourselves, so we need to prevent the default action.

Opera ignores event.preventDefault() call so we must return false.
2012-09-06 15:54:20 -07:00
Kai Groner 3d7c752e27 fix(FormController): propagate dirty state to parent forms 2012-09-06 15:54:19 -07:00
Jonathan Zacsh f02833d634 chore(docs): get correct location for jasmine-node 2012-09-06 15:54:19 -07:00
Misko Hevery 0eb373e0e6 fix($injector): more conservative annotation parsing 2012-09-06 15:49:50 -07:00
Xiangru Chen fd3071843c fix(ngSrc): don't set src if value is empty string
Current implementation of ngSrc may lead to empty src attribute when page is loading.

For example:

<img ng-src="{{image.url}}">
can be temporarily rendered as

<img src="">
before the image resource is loaded.

Some browser emits a request to the current page when seeing <img src=""> (Firefox13 and IE8 will, Chromium20 won't), which leads to performance problems.
2012-09-06 15:49:49 -07:00
Iwein Fuld a631ceb223 fix(dateFilter): make timezone optional
Makes the time zone optional in the date filter

Problem with the current R_ISO8601_STR regex was that the time was optional, but the zone was not.
This results in the filter not formatting local date times, which it could easily do.

For example:
2012-08-30 -> formatted
2012-08-30T06:06:06.123Z -> formatted
2012-08-30T06:06:06.123 -> NOT formatted

A simple change in the regex fixes this. Arguably this is closer to the ISO8601 spec which specifies
local dates being in the "current time zone" and not requiring a Z. In any case it behaves more like
a user would expect.
2012-09-06 15:49:49 -07:00
Misko Hevery a713928210 docs(concept): correct example for creating injector 2012-09-06 15:49:49 -07:00
Godmar Back 05fa20df81 docs(module): fixed module example and corrected typos 2012-09-06 15:49:49 -07:00
Benjamín Eidelman 125573602f fix($resource): allow falsy values in URL parameters
Close #1212

when a param value was 0 (or false) it was ignored and removed from url.
after this fix that only happens if the value is undefined or null.
2012-09-06 15:49:49 -07:00
Jay Zeng ed5dfbcd66 docs(module): myAppModule -> simpleAppModule 2012-09-06 15:49:49 -07:00
petrovalex d2e52b2376 fix($resource): ignore undefined parameters
- $resource should handle multiple params with same name
- ignore slashes of undefined parameters
- fix default parameters issue, mentioned in #875

Closes #875
Closes #782
2012-09-06 15:49:49 -07:00
petrovalex a56aaa9877 fix(ngClassEven/Odd): filtering/ordering and repeater
Closes #1076
2012-09-06 15:49:48 -07:00
Max Martinsson 79bb7b1f0b fix(ngClass): works with class interpolation
Closes #1016
2012-09-06 15:49:48 -07:00
Max Martinsson b936e52874 feat($resource): support custom headers per action
Closes #736
2012-09-06 15:49:48 -07:00
petrovalex 0d52ff0f10 fix($parser): string concatination with undefined model
Closes #988
2012-09-06 15:49:48 -07:00
Stein Jakob Nordbø baf52e902d fix(dateFilter): support sub-second precision on dateFilter 2012-09-06 15:49:48 -07:00
Igor Minar dffea9e2b7 docs($route): rename leftover $afterRouteChange to $routeChangeSuccess 2012-09-06 15:03:58 -07:00
Igor Minar 4a411b8f82 chore(release): prepare 1.0.3 bouncy-thunder iteration 2012-09-06 08:42:51 -07:00
Misko Hevery 278bfc4bb2 fix(docs): broken url to angular-bootstrap 2012-09-04 18:16:52 -07:00
Igor Minar 18731173f9 chore(Rakefile): add 'version' rake task to generate version.txt 2012-09-04 16:38:29 -07:00
Igor Minar d43fb404d7 chore(docs): bump up the stable version 2012-09-04 16:30:33 -07:00
Igor Minar da984ad187 chore(release): cut the 1.0.2 debilitating-awesomeness release 2012-09-04 11:08:40 -07:00
Igor Minar 4015357ce5 chore(docs): don't rewrite colons in doc filenames 2012-09-04 11:08:40 -07:00
Igor Minar dc3d11ad19 chore(Rakefile): zip only the build dir 2012-09-04 11:08:40 -07:00
Igor Minar 0e1545eb04 revert: fix(ng-repeat) to work with primitive types
this commit was accidentaly merged. it needs more work and we don't
have CLA signature

This reverts commit 98d489712e.
2012-08-31 13:44:36 -07:00
Igor Minar ec7cabf5c9 docs(changelog): release notes for 1.0.2 and 1.1.0 releases 2012-08-31 13:23:23 -07:00
Jonathan Zacsh 3051beba2f fix(docs): Making sure gen_docs.sh looks for a globally installed copy of jasmine-node as well as local. 2012-08-30 22:38:54 -07:00
Fernando Correia 92304323b1 docs(tutorial): correct typos and clarify a few sections 2012-08-30 22:38:54 -07:00
Brice Burgess c28123a872 fix(docs): indicate support for passing a string as the controller property on $routeProvider's route object 2012-08-30 22:38:53 -07:00
brettcannon d798423813 doc(misc) Mention how attribute names map to directive names. 2012-08-30 22:38:52 -07:00
Sahat Yalkabov 2583e77cc7 doc(module) changed simpleApp to myApp in the Module page guide for consistency 2012-08-30 21:34:43 -07:00
Steve Nicolai f66836fee4 doc(devguide) - Fix typos and small grammatical errors in the developer guide. 2012-08-30 21:34:42 -07:00
Uri Goldshtein 0ccc445d53 Loading from Google CDN
As you guys had mansion, we can and need to do it through Google CDN for better performance,
so i've updated it accordingly
2012-08-30 21:34:42 -07:00
Tyson Benson b7d5fa1cbe docs(typos): fix typos in dev guide 2012-08-30 21:34:42 -07:00
German Galvis 8bb3942453 fix(scenario): Adding meta tag to avoid cache issues 2012-08-30 21:34:42 -07:00
phil 51a79cebcb docs(api): fix typo on home page
Refference -> Reference
2012-08-30 21:34:41 -07:00
csugden 36bcf64008 Update docs/content/guide/overview.ngdoc
Corrects video information
2012-08-30 21:34:41 -07:00
Jamie Krug 5c6630605b fix(docs): Fix typos and improve grammar. 2012-08-30 21:34:41 -07:00
Jamie Krug 125827406c fix(docs): Fix bad links. 2012-08-30 21:34:41 -07:00
Colin Frei 62c21422a6 docs(module) fix typo 2012-08-30 21:34:41 -07:00
Zhenbo Zhang 98d489712e fix(ng-repeat) to work with primitive types 2012-08-30 21:34:41 -07:00
Igor Minar 2cab2d8ef1 test(locationSpec): fix broken tests after vojta's commit 2012-08-30 16:54:07 -07:00
Vojta Jina 8fa2bb72bc fix(mocks): free up memory after every spec 2012-08-30 16:53:52 -07:00
Igor Minar d151f94937 chore(docs): ask GAE to serve docs-keywords.js 2012-08-30 15:59:29 -07:00
Igor Minar 5b74b7185b test(bootstrap): test exception siling during bootstrap
Closes #1018
2012-08-30 15:18:11 -07:00
Igor Minar 4f0be2ae4e test(ngApp): add missing test for [ng-app] bootstrap 2012-08-30 15:18:02 -07:00
Igor Minar bb9badeb2a fix(jqLite): better support for xhtml
it turns out that some stuff doesn't work in xhtml as it does in html.

for example &nbsp; can't be innerHTML-ed and auto-closing of elements
doesn't work.

the reporter of the referenced issue claimed that innerHTML vs text on
script made a difference but that doesn't appear to be true in my testing.

I'm not including test for this because testacular doesn't currently
run tests in xhtml yet.

Closes #1301
2012-08-30 10:52:36 -07:00
Igor Minar c287c8361d chore(docs): correctly link docs images 2012-08-30 08:59:17 -07:00
Igor Minar ade7127c79 chore(Rakefile): fix the default task 2012-08-30 08:58:51 -07:00
Igor Minar d341483f1f chore(Rakefile): remove bogus symlink from build 2012-08-30 08:58:39 -07:00
Igor Minar b36acbc857 chore(docs): use symlinks to build docs
so that we can just edit source files without rebuilding docs.

this works for all docs files, except for those that are generated
or rewritten during build.
2012-08-28 16:08:03 -07:00
Igor Minar a4fea38b94 chore(Rakefile): various build script changes
- restructure rake tasks

  this splits up the concatination and minification into two
  tasks so that we can just build angular.js quickly without wasting
  time with minification which is often not needed when just debugging
  some issue on 3rd party site.

- use symlinks when creating final zip file

- switch from btar to zip

- get rid of version numbers from filenames

- rewrite version numbers in all index files

Closes #1226
2012-08-28 16:07:47 -07:00
Misko Hevery 300c5c0c99 doc($log): correct non-working example 2012-08-27 21:20:51 -07:00
Misko Hevery 152537c4e9 doc(guide): add concepts 2012-08-27 21:20:51 -07:00
Misko Hevery 8b46bf6bc9 fix(ngdoc): failing test 2012-08-27 21:20:50 -07:00
Colin Frei aef861eb41 doc(directive) correct typos 2012-08-27 21:20:50 -07:00
Misko Hevery f61d36861d fix(docs) typo 2012-08-27 21:20:50 -07:00
Misko Hevery 2af0348cea fix(ng-list): remove data bound flicker 2012-08-27 21:20:50 -07:00
Misko Hevery 78c5743494 doc(misc) updated getting started to reflect the new homepage 2012-08-27 21:20:49 -07:00
Misko Hevery 2cb9fbd043 doc(guide) simplify the guide home page 2012-08-27 21:20:49 -07:00
Igor Minar e9dad5dbf4 chore(Rakefile): rewrite version numbers in all index files 2012-08-27 12:25:40 -07:00
Igor Minar 54895fc2a1 chore(docs): support _escaped_fragment_ hack for crawler 2012-08-25 02:31:20 -07:00
Igor Minar 60a12b4161 chore(docs): use GAE and Google CDN for docs
Short summary: if you use local node server everything should work as before,
if you use GAE, everything should work now as well, but we pull assets from CDN.

- GAE doesn't support ':' in filenames, so I had to replace it with '_'
  but only in the filename, all servers were reconfigured to rewrite the
  urls from : to _ when doing file lookup
- We now pull angular assets from google CDN when deployed on GAE (locally
  or in production). When running on a non GAE server we pull assets from
  ../ directory as before
- Since only certain versions of Angular are available on CDN and we want
  to be able to autodeploy docs, I had to pin down the Angular files
  to a "stable" version when running on GAE
2012-08-24 15:00:36 -07:00
Igor Minar cd7e58ba41 docs(a): expose hidden docs
It seems that docs for these directive were previously hidden by accident
2012-08-24 14:59:52 -07:00
johnlindquist 9391475dc3 docs(ngRoute): fix typo
aftre -> after
2012-08-24 14:59:43 -07:00
phil 7840803add docs(tutorial): fix typo in step_00
Just removed an extra comma. No big deal.
2012-08-24 14:59:21 -07:00
Igor Minar 7d77de2834 fix($compile): denormalize directive templates
Since developers are allowed to customize start/end interpolation
strings, but third-party directive creators don't know about these
customizations, we should standardize on {{ }} in templates of
reusable (third-party) directives. During the compilation, these
templates are then denormalized to use whatever the custom
start/end symbol is, effectively translating the template into the
syntax of the runtime environment.

This addresses an issue raised at http://goo.gl/e8VPV

Existing code should not be affected by this change since project
that do use custom interpolation markers are not expected to use
{{ }} in existing directive templates.
2012-08-13 14:35:32 -07:00
Igor Minar ab044cada6 refactor($compile): code cleanup 2012-08-13 12:36:42 -07:00
Brian Ford d010e0cc7d fix(ngPluralize): fixes ng-pluralize when using non-standard start/end symbols
Closes #1134
2012-08-13 12:36:33 -07:00
Igor Minar 40f728b1aa style(ngPluralizeSpec): fix indentation 2012-08-13 12:36:22 -07:00
Igor Minar 23abb26405 feat($interpolate): expose start/end symbols in run phase
previously the startSymbol() and endSymbol() getters were exposed only via provider
in the config phase
2012-08-13 12:36:14 -07:00
Igor Minar fd55bc8e1d docs($interpolateProvider): fixing docs 2012-08-13 09:51:57 -07:00
Igor Minar 541aaa4e08 fix($interpolate): $interpolateProvider.endSymbol() returns startSymbol
I also added missing tests.
2012-08-13 09:51:45 -07:00
Igor Minar f22c422547 docs($interpolate): fix typo in description 2012-08-13 09:51:35 -07:00
Vojta Jina 0e461f0c07 docs($compileProvider): remove duplicate of .directive() 2012-08-12 11:04:32 -07:00
Vojta Jina 5074448443 docs: fix broken links to $compileProvider.directive() 2012-08-12 11:04:20 -07:00
Brian Ford 8d66af11e6 fix(docs): fixed documentation for using linky 2012-08-10 16:38:01 -07:00
Brian Ford 169948bb47 chore(ngDoc): add support for custom @usage metadata 2012-08-10 16:37:54 -07:00
Brian Ford 58d9469574 fix(docs): added note about using JSON3 as a polyfill for IE7 2012-08-10 16:37:42 -07:00
Brian Ford 8d858a2360 fix(docs): added note about needing JSON shim for IE7 and earlier 2012-08-10 16:36:56 -07:00
Igor Minar 5540748890 fix(option): support option elements in datalist
previously we expected to find option elements only within select element and if
that was not the case we throw an error. This made it impossible to include datalist
element with nested option elements in the template.

Closes #1165
2012-08-10 16:14:49 -07:00
unirgy f8a52be817 docs($rootScope): fix $on listener signature doc
Added args in $on() listener syntax declaration
2012-08-10 14:52:57 -07:00
Igor Minar 3b5f1105f6 test(jqLite): add missing test for $destroy event 2012-08-10 14:21:11 -07:00
Igor Minar 663ccc5449 fix(form): prevent page reload when form destroyed
this fix ensures that we prevent the default action on form submission
(full page reload) even in cases when the form is being destroyed as
a result of the submit event handler (e.g. when route change is
triggered).

The fix is more complicated than I'd like it to be mainly because
we need to ensure that we don't create circular references between
js closures and dom elements via DOM event handlers that would then
result in a memory leak.

Also the differences between IE8, IE9 and normal browsers make testing
this ugly.

Closes #1238
2012-08-10 14:21:02 -07:00
Igor Minar 263f47819f test(form): fix broken preventDefault test
the original test relied on incorrect assumptions about how jasmine async
tests work (when setTimeout is triggered) and how browser reloads a page
(the sequence of events) and thus the test passes even when the default
is not prevented.

this change fixes the test by registering an extra submit event handler
that checks if the default was prevented.

if the default was not prevented, the test will fail and the page will
be reloaded causing the test runner to panic.
2012-08-10 14:20:52 -07:00
Igor Minar 6b75475ce3 refactor(formSpec): group preventDefault specs into a describe 2012-08-10 14:20:28 -07:00
Igor Minar 07c354a8c0 docs(faq): update faq docs 2012-08-10 14:20:13 -07:00
Igor Minar 1391579599 docs(styles): fix the cog icon alignment 2012-08-10 14:19:57 -07:00
Vojta Jina 5d2bd1d84c chore(nodeserver): add font mime type 2012-08-10 14:19:47 -07:00
Vojta Jina bf77e212af docs(guide): hide scenario for directive example
scenario test for this example would be tricky, we need to teach
the runner how to inject mocks first.
2012-08-10 14:19:37 -07:00
Vojta Jina eef2f9c31e docs(design): fix icons
Copy fontawesome during build
2012-08-10 14:18:45 -07:00
brettcannon 438627c2c3 fix(docs): "in depth" -> "in-depth" 2012-08-10 14:18:06 -07:00
55 changed files with 4091 additions and 4873 deletions
+20 -1
View File
@@ -57,6 +57,25 @@ task :concat_scenario => :init do
end
desc 'Concat JSTD Scenario Adapter'
task :concat_jstd_scenario_adapter => :init do
concat_file('jstd-scenario-adapter.js', [
'src/ngScenario/jstd-scenario-adapter/angular.prefix',
'src/ngScenario/jstd-scenario-adapter/Adapter.js',
'src/ngScenario/jstd-scenario-adapter/angular.suffix',
])
# TODO(vojta) use jstd configuration when implemented
# (instead of including jstd-adapter-config.js)
File.open(path_to('jstd-scenario-adapter-config.js'), 'w') do |f|
f.write("/**\r\n" +
" * Configuration for jstd scenario adapter \n */\n" +
"var jstdScenarioAdapter = {\n relativeUrlPrefix: '/build/docs/'\n};\n")
end
end
desc 'Concat AngularJS files'
task :concat => :init do
@@ -96,7 +115,7 @@ end
desc 'Minify JavaScript'
task :minify => [:init, :concat, :concat_scenario] do
task :minify => [:init, :concat, :concat_scenario, :concat_jstd_scenario_adapter] do
[ 'angular.js',
'angular-cookies.js',
'angular-loader.js',
+3651 -3687
View File
File diff suppressed because it is too large Load Diff
+4 -2
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1 +1 @@
1.8.2
1.7.2
+6 -5
View File
@@ -410,10 +410,9 @@ function createInjector(modulesToLoad) {
decorator: decorator
}
},
providerInjector = (providerCache.$injector =
createInternalInjector(providerCache, function() {
throw Error("Unknown provider: " + path.join(' <- '));
})),
providerInjector = createInternalInjector(providerCache, function() {
throw Error("Unknown provider: " + path.join(' <- '));
}),
instanceCache = {},
instanceInjector = (instanceCache.$injector =
createInternalInjector(instanceCache, function(servicename) {
@@ -490,7 +489,9 @@ function createInjector(modulesToLoad) {
try {
for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {
var invokeArgs = invokeQueue[i],
provider = providerInjector.get(invokeArgs[0]);
provider = invokeArgs[0] == '$injector'
? providerInjector
: providerInjector.get(invokeArgs[0]);
provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
}
+3 -4
View File
@@ -353,11 +353,11 @@ var JQLitePrototype = JQLite.prototype = {
// value on get.
//////////////////////////////////////////
var BOOLEAN_ATTR = {};
forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) {
forEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {
BOOLEAN_ATTR[lowercase(value)] = value;
});
var BOOLEAN_ELEMENTS = {};
forEach('input,select,option,textarea,button,form,details'.split(','), function(value) {
forEach('input,select,option,textarea,button,form'.split(','), function(value) {
BOOLEAN_ELEMENTS[uppercase(value)] = true;
});
@@ -659,9 +659,8 @@ forEach({
append: function(element, node) {
forEach(new JQLite(node), function(child){
if (element.nodeType === 1 || element.nodeType === 11) {
if (element.nodeType === 1)
element.appendChild(child);
}
});
},
+1 -3
View File
@@ -14,7 +14,7 @@
* @returns {object} Newly created cache object with the following set of methods:
*
* - `{object}` `info()` — Returns id, size, and options of cache.
* - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns it.
* - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.
* - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.
* - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.
* - `{void}` `removeAll()` — Removes all cached values.
@@ -53,8 +53,6 @@ function $CacheFactoryProvider() {
if (size > capacity) {
this.remove(staleEnd.key);
}
return value;
},
-31
View File
@@ -272,37 +272,6 @@
* @param {string} expression Angular expression that will be evaluated.
*/
/**
* @ngdoc directive
* @name ng.directive:ngOpen
* @restrict A
*
* @description
* The HTML specs do not require browsers to preserve the special attributes such as open.
* (The presence of them means true and absence means false)
* This prevents the angular compiler from correctly retrieving the binding expression.
* To solve this problem, we introduce the `ngOpen` directive.
*
* @example
<doc:example>
<doc:source>
Check me check multiple: <input type="checkbox" ng-model="open"><br/>
<details id="details" ng-open="open">
<summary>Show/Hide me</summary>
</details>
</doc:source>
<doc:scenario>
it('should toggle open', function() {
expect(element('#details').prop('open')).toBeFalsy();
input('open').check();
expect(element('#details').prop('open')).toBeTruthy();
});
</doc:scenario>
</doc:example>
*
* @element DETAILS
* @param {string} expression Angular expression that will be evaluated.
*/
var ngAttributeAliasDirectives = {};
+2 -31
View File
@@ -5,8 +5,7 @@ var nullFormCtrl = {
$addControl: noop,
$removeControl: noop,
$setValidity: noop,
$setDirty: noop,
$setPristine: noop
$setDirty: noop
};
/**
@@ -38,8 +37,7 @@ function FormController(element, attrs) {
var form = this,
parentForm = element.parent().controller('form') || nullFormCtrl,
invalidCount = 0, // used to easily determine if we are valid
errors = form.$error = {},
controls = [];
errors = form.$error = {};
// init state
form.$name = attrs.name;
@@ -63,8 +61,6 @@ function FormController(element, attrs) {
}
form.$addControl = function(control) {
controls.push(control);
if (control.$name && !form.hasOwnProperty(control.$name)) {
form[control.$name] = control;
}
@@ -77,8 +73,6 @@ function FormController(element, attrs) {
forEach(errors, function(queue, validationToken) {
form.$setValidity(validationToken, true, control);
});
arrayRemove(controls, control);
};
form.$setValidity = function(validationToken, isValid, control) {
@@ -126,29 +120,6 @@ function FormController(element, attrs) {
parentForm.$setDirty();
};
/**
* @ngdoc function
* @name ng.directive:form.FormController#$setPristine
* @methodOf ng.directive:form.FormController
*
* @description
* Sets the form to its pristine state.
*
* This method can be called to remove the 'ng-dirty' class and set the form to its pristine
* state (ng-pristine class). This method will also propagate to all the controls contained
* in this form.
*
* Setting a form back to a pristine state is often useful when we want to 'reuse' a form after
* saving or resetting it.
*/
form.$setPristine = function () {
element.removeClass(DIRTY_CLASS).addClass(PRISTINE_CLASS);
form.$dirty = false;
form.$pristine = true;
forEach(controls, function(control) {
control.$setPristine();
});
};
}
+3 -34
View File
@@ -28,8 +28,6 @@ var inputType = {
* patterns defined as scope expressions.
* @param {string=} ngChange Angular expression to be executed when input changes due to user
* interaction with the input element.
* @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trimming the
* input.
*
* @example
<doc:example>
@@ -37,12 +35,12 @@ var inputType = {
<script>
function Ctrl($scope) {
$scope.text = 'guest';
$scope.word = /^\s*\w*\s*$/;
$scope.word = /^\w*$/;
}
</script>
<form name="myForm" ng-controller="Ctrl">
Single word: <input type="text" name="input" ng-model="text"
ng-pattern="word" required ng-trim="false">
ng-pattern="word" required>
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.pattern">
@@ -71,12 +69,6 @@ var inputType = {
input('text').enter('hello world');
expect(binding('myForm.input.$valid')).toEqual('false');
});
it('should not be trimmed', function() {
input('text').enter('untrimmed ');
expect(binding('text')).toEqual('untrimmed ');
expect(binding('myForm.input.$valid')).toEqual('true');
});
</doc:scenario>
</doc:example>
*/
@@ -390,14 +382,7 @@ function isEmpty(value) {
function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
var listener = function() {
var value = element.val();
// By default we will trim the value
// If the attribute ng-trim exists we will avoid trimming
// e.g. <input ng-model="foo" ng-trim="false">
if (toBoolean(attr.ngTrim || 'T')) {
value = trim(value);
}
var value = trim(element.val());
if (ctrl.$viewValue !== value) {
scope.$apply(function() {
@@ -978,22 +963,6 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
parentForm.$setValidity(validationErrorKey, isValid, this);
};
/**
* @ngdoc function
* @name ng.directive:ngModel.NgModelController#$setPristine
* @methodOf ng.directive:ngModel.NgModelController
*
* @description
* Sets the control to its pristine state.
*
* This method can be called to remove the 'ng-dirty' class and set the control to its pristine
* state (ng-pristine class).
*/
this.$setPristine = function () {
this.$dirty = false;
this.$pristine = true;
$element.removeClass(DIRTY_CLASS).addClass(PRISTINE_CLASS);
};
/**
* @ngdoc function
+1 -33
View File
@@ -37,7 +37,7 @@
*/
var ngEventDirectives = {};
forEach(
'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup'.split(' '),
'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),
function(name) {
var directiveName = directiveNormalize('ng-' + name);
ngEventDirectives[directiveName] = ['$parse', function($parse) {
@@ -164,38 +164,6 @@ forEach(
*/
/**
* @ngdoc directive
* @name ng.directive:ngKeydown
*
* @description
* Specify custom behavior on keydown event.
*
* @element ANY
* @param {expression} ngKeydown {@link guide/expression Expression} to evaluate upon
* keydown. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
*
* @example
* See {@link ng.directive:ngClick ngClick}
*/
/**
* @ngdoc directive
* @name ng.directive:ngKeyup
*
* @description
* Specify custom behavior on keyup event.
*
* @element ANY
* @param {expression} ngKeyup {@link guide/expression Expression} to evaluate upon
* keyup. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
*
* @example
* See {@link ng.directive:ngClick ngClick}
*/
/**
* @ngdoc directive
* @name ng.directive:ngSubmit
+4 -8
View File
@@ -330,22 +330,18 @@ function dateFilter($locale) {
var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
// 1 2 3 4 5 6 7 8 9 10 11
function jsonStringToDate(string) {
function jsonStringToDate(string){
var match;
if (match = string.match(R_ISO8601_STR)) {
var date = new Date(0),
tzHour = 0,
tzMin = 0,
dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear,
timeSetter = match[8] ? date.setUTCHours : date.setHours;
tzMin = 0;
if (match[9]) {
tzHour = int(match[9] + match[10]);
tzMin = int(match[9] + match[11]);
}
dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3]));
timeSetter.call(date, int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));
date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));
date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));
return date;
}
return string;
+33 -50
View File
@@ -6,20 +6,20 @@
* @function
*
* @description
* Creates a new array or string containing only a specified number of elements. The elements
* are taken from either the beginning or the end of the source array or string, as specified by
* the value and sign (positive or negative) of `limit`.
* Creates a new array containing only a specified number of elements in an array. The elements
* are taken from either the beginning or the end of the source array, as specified by the
* value and sign (positive or negative) of `limit`.
*
* Note: This function is used to augment the `Array` type in Angular expressions. See
* {@link ng.$filter} for more information about Angular arrays.
*
* @param {Array|string} input Source array or string to be limited.
* @param {string|number} limit The length of the returned array or string. If the `limit` number
* is positive, `limit` number of items from the beginning of the source array/string are copied.
* If the number is negative, `limit` number of items from the end of the source array/string
* are copied. The `limit` will be trimmed if it exceeds `array.length`
* @returns {Array|string} A new sub-array or substring of length `limit` or less if input array
* had less than `limit` elements.
* @param {Array} array Source array to be limited.
* @param {string|Number} limit The length of the returned array. If the `limit` number is
* positive, `limit` number of items from the beginning of the source array are copied.
* If the number is negative, `limit` number of items from the end of the source array are
* copied. The `limit` will be trimmed if it exceeds `array.length`
* @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`
* elements.
*
* @example
<doc:example>
@@ -27,76 +27,59 @@
<script>
function Ctrl($scope) {
$scope.numbers = [1,2,3,4,5,6,7,8,9];
$scope.letters = "abcdefghi";
$scope.numLimit = 3;
$scope.letterLimit = 3;
$scope.limit = 3;
}
</script>
<div ng-controller="Ctrl">
Limit {{numbers}} to: <input type="integer" ng-model="numLimit">
<p>Output numbers: {{ numbers | limitTo:numLimit }}</p>
Limit {{letters}} to: <input type="integer" ng-model="letterLimit">
<p>Output letters: {{ letters | limitTo:letterLimit }}</p>
Limit {{numbers}} to: <input type="integer" ng-model="limit">
<p>Output: {{ numbers | limitTo:limit }}</p>
</div>
</doc:source>
<doc:scenario>
it('should limit the number array to first three items', function() {
expect(element('.doc-example-live input[ng-model=numLimit]').val()).toBe('3');
expect(element('.doc-example-live input[ng-model=letterLimit]').val()).toBe('3');
expect(binding('numbers | limitTo:numLimit')).toEqual('[1,2,3]');
expect(binding('letters | limitTo:letterLimit')).toEqual('abc');
it('should limit the numer array to first three items', function() {
expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');
expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');
});
it('should update the output when -3 is entered', function() {
input('numLimit').enter(-3);
input('letterLimit').enter(-3);
expect(binding('numbers | limitTo:numLimit')).toEqual('[7,8,9]');
expect(binding('letters | limitTo:letterLimit')).toEqual('ghi');
input('limit').enter(-3);
expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');
});
it('should not exceed the maximum size of input array', function() {
input('numLimit').enter(100);
input('letterLimit').enter(100);
expect(binding('numbers | limitTo:numLimit')).toEqual('[1,2,3,4,5,6,7,8,9]');
expect(binding('letters | limitTo:letterLimit')).toEqual('abcdefghi');
input('limit').enter(100);
expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');
});
</doc:scenario>
</doc:example>
*/
function limitToFilter(){
return function(input, limit) {
if (!isArray(input) && !isString(input)) return input;
return function(array, limit) {
if (!(array instanceof Array)) return array;
limit = int(limit);
if (isString(input)) {
//NaN check on limit
if (limit) {
return limit >= 0 ? input.slice(0, limit) : input.slice(limit, input.length);
} else {
return "";
}
}
var out = [],
i, n;
// check that array is iterable
if (!array || !(array instanceof Array))
return out;
// if abs(limit) exceeds maximum length, trim it
if (limit > input.length)
limit = input.length;
else if (limit < -input.length)
limit = -input.length;
if (limit > array.length)
limit = array.length;
else if (limit < -array.length)
limit = -array.length;
if (limit > 0) {
i = 0;
n = limit;
} else {
i = input.length + limit;
n = input.length;
i = array.length + limit;
n = array.length;
}
for (; i<n; i++) {
out.push(input[i]);
out.push(array[i]);
}
return out;
+17 -65
View File
@@ -29,43 +29,6 @@ function parseHeaders(headers) {
}
var IS_SAME_DOMAIN_URL_MATCH = /^(([^:]+):)?\/\/(\w+:{0,1}\w*@)?([\w\.-]*)?(:([0-9]+))?(.*)$/;
/**
* Parse a request and location URL and determine whether this is a same-domain request.
*
* @param {string} requestUrl The url of the request.
* @param {string} locationUrl The current browser location url.
* @returns {boolean} Whether the request is for the same domain.
*/
function isSameDomain(requestUrl, locationUrl) {
var match = IS_SAME_DOMAIN_URL_MATCH.exec(requestUrl);
// if requestUrl is relative, the regex does not match.
if (match == null) return true;
var domain1 = {
protocol: match[2],
host: match[4],
port: int(match[6]) || DEFAULT_PORTS[match[2]] || null,
// IE8 sets unmatched groups to '' instead of undefined.
relativeProtocol: match[2] === undefined || match[2] === ''
};
match = URL_MATCH.exec(locationUrl);
var domain2 = {
protocol: match[1],
host: match[3],
port: int(match[5]) || DEFAULT_PORTS[match[1]] || null
};
return (domain1.protocol == domain2.protocol || domain1.relativeProtocol) &&
domain1.host == domain2.host &&
(domain1.port == domain2.port || (domain1.relativeProtocol &&
domain2.port == DEFAULT_PORTS[domain2.protocol]));
}
/**
* Returns a function that provides access to parsed headers.
*
@@ -125,7 +88,7 @@ function $HttpProvider() {
JSON_END = /[\}\]]\s*$/,
PROTECTION_PREFIX = /^\)\]\}',?\n/;
var defaults = this.defaults = {
var $config = this.defaults = {
// transform incoming response data
transformResponse: [function(data) {
if (isString(data)) {
@@ -145,7 +108,8 @@ function $HttpProvider() {
// default headers
headers: {
common: {
'Accept': 'application/json, text/plain, */*'
'Accept': 'application/json, text/plain, */*',
'X-Requested-With': 'XMLHttpRequest'
},
post: {'Content-Type': 'application/json;charset=utf-8'},
put: {'Content-Type': 'application/json;charset=utf-8'}
@@ -251,6 +215,7 @@ function $HttpProvider() {
*
* - `$httpProvider.defaults.headers.common` (headers that are common for all requests):
* - `Accept: application/json, text/plain, * / *`
* - `X-Requested-With: XMLHttpRequest`
* - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)
* - `Content-Type: application/json`
* - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)
@@ -385,7 +350,7 @@ function $HttpProvider() {
* to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie
* called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that
* runs on your domain could read the cookie, your server can be assured that the XHR came from
* JavaScript running on your domain. The header will not be set for cross-domain requests.
* JavaScript running on your domain.
*
* To take advantage of this, your server needs to set a token in a JavaScript readable session
* cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the
@@ -419,8 +384,6 @@ function $HttpProvider() {
* - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the
* XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5
* requests with credentials} for more information.
* - **responseType** - `{string}` - see {@link
* https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType requestType}.
*
* @returns {HttpPromise} Returns a {@link ng.$q promise} object with the
* standard `then` method and two http specific methods: `success` and `error`. The `then`
@@ -513,12 +476,10 @@ function $HttpProvider() {
function $http(config) {
config.method = uppercase(config.method);
var reqTransformFn = config.transformRequest || defaults.transformRequest,
respTransformFn = config.transformResponse || defaults.transformResponse,
defHeaders = defaults.headers,
xsrfToken = isSameDomain(config.url, $browser.url()) ?
$browser.cookies()['XSRF-TOKEN'] : undefined,
reqHeaders = extend({'X-XSRF-TOKEN': xsrfToken},
var reqTransformFn = config.transformRequest || $config.transformRequest,
respTransformFn = config.transformResponse || $config.transformResponse,
defHeaders = $config.headers,
reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},
defHeaders.common, defHeaders[lowercase(config.method)], config.headers),
reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),
promise;
@@ -528,10 +489,6 @@ function $HttpProvider() {
delete reqHeaders['Content-Type'];
}
if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {
config.withCredentials = defaults.withCredentials;
}
// send request
promise = sendReq(config, reqData, reqHeaders);
@@ -663,11 +620,11 @@ function $HttpProvider() {
*
* @description
* Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of
* default headers, withCredentials as well as request and response transformations.
* default headers as well as request and response transformations.
*
* See "Setting HTTP Headers" and "Transforming Requests and Responses" sections above.
*/
$http.defaults = defaults;
$http.defaults = $config;
return $http;
@@ -702,7 +659,7 @@ function $HttpProvider() {
* Makes the request
*
* !!! ACCESSES CLOSURE VARS:
* $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests
* $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests
*/
function sendReq(config, reqData, reqHeaders) {
var deferred = $q.defer(),
@@ -743,7 +700,7 @@ function $HttpProvider() {
// if we won't have the response in cache, send the request to the backend
if (!cachedResp) {
$httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,
config.withCredentials, config.responseType);
config.withCredentials);
}
return promise;
@@ -798,15 +755,10 @@ function $HttpProvider() {
var parts = [];
forEachSorted(params, function(value, key) {
if (value == null || value == undefined) return;
if (!isArray(value)) value = [value];
forEach(value, function(v) {
if (isObject(v)) {
v = toJson(v);
}
parts.push(encodeURIComponent(key) + '=' +
encodeURIComponent(v));
});
if (isObject(value)) {
value = toJson(value);
}
parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
});
return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');
}
+3 -7
View File
@@ -32,7 +32,7 @@ function $HttpBackendProvider() {
function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {
// TODO(vojta): fix the signature
return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {
return function(method, url, post, callback, headers, timeout, withCredentials) {
$browser.$$incOutstandingRequestCount();
url = url || $browser.url();
@@ -65,8 +65,8 @@ function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument,
// always async
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
completeRequest(callback, status || xhr.status, xhr.response || xhr.responseText,
xhr.getAllResponseHeaders());
completeRequest(
callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());
}
};
@@ -74,10 +74,6 @@ function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument,
xhr.withCredentials = true;
}
if (responseType) {
xhr.responseType = responseType;
}
xhr.send(post || '');
if (timeout > 0) {
+10 -16
View File
@@ -52,7 +52,7 @@ function $InterpolateProvider() {
};
this.$get = ['$parse', '$exceptionHandler', function($parse, $exceptionHandler) {
this.$get = ['$parse', function($parse) {
var startSymbolLength = startSymbol.length,
endSymbolLength = endSymbol.length;
@@ -124,24 +124,18 @@ function $InterpolateProvider() {
if (!mustHaveExpression || hasInterpolation) {
concat.length = length;
fn = function(context) {
try {
for(var i = 0, ii = length, part; i<ii; i++) {
if (typeof (part = parts[i]) == 'function') {
part = part(context);
if (part == null || part == undefined) {
part = '';
} else if (typeof part != 'string') {
part = toJson(part);
}
for(var i = 0, ii = length, part; i<ii; i++) {
if (typeof (part = parts[i]) == 'function') {
part = part(context);
if (part == null || part == undefined) {
part = '';
} else if (typeof part != 'string') {
part = toJson(part);
}
concat[i] = part;
}
return concat.join('');
}
catch(err) {
var newErr = new Error('Error while interpolating: ' + text + '\n' + err.toString());
$exceptionHandler(newErr);
concat[i] = part;
}
return concat.join('');
};
fn.exp = text;
fn.parts = parts;
+1 -45
View File
@@ -33,33 +33,7 @@
</example>
*/
/**
* @ngdoc object
* @name ng.$logProvider
* @description
* Use the `$logProvider` to configure how the application logs messages
*/
function $LogProvider(){
var debug = true,
self = this;
/**
* @ngdoc property
* @name ng.$logProvider#debugEnabled
* @methodOf ng.$logProvider
* @description
* @param {string=} flag enable or disable debug level messages
* @returns {*} current value if used as getter or itself (chaining) if used as setter
*/
this.debugEnabled = function(flag) {
if (isDefined(flag)) {
debug = flag;
return this;
} else {
return debug;
}
};
this.$get = ['$window', function($window){
return {
/**
@@ -100,25 +74,7 @@ function $LogProvider(){
* @description
* Write an error message
*/
error: consoleLog('error'),
/**
* @ngdoc method
* @name ng.$log#debug
* @methodOf ng.$log
*
* @description
* Write a debug message
*/
debug: (function () {
var fn = consoleLog('debug');
return function() {
if (debug) {
fn.apply(self, arguments);
}
}
}())
error: consoleLog('error')
};
function formatError(arg) {
+5 -13
View File
@@ -20,8 +20,6 @@ var OPERATORS = {
'%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},
'^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},
'=':noop,
'===':function(self, locals, a, b){return a(self, locals)===b(self, locals);},
'!==':function(self, locals, a, b){return a(self, locals)!==b(self, locals);},
'==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},
'!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},
'<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},
@@ -72,14 +70,9 @@ function lex(text, csp){
continue;
} else {
var ch2 = ch + peek(),
ch3 = ch2 + peek(2),
fn = OPERATORS[ch],
fn2 = OPERATORS[ch2],
fn3 = OPERATORS[ch3];
if (fn3) {
tokens.push({index:index, text:ch3, fn:fn3});
index += 3;
} else if (fn2) {
fn2 = OPERATORS[ch2];
if (fn2) {
tokens.push({index:index, text:ch2, fn:fn2});
index += 2;
} else if (fn) {
@@ -101,9 +94,8 @@ function lex(text, csp){
return chars.indexOf(lastCh) != -1;
}
function peek(i) {
var num = i || 1;
return index + num < text.length ? text.charAt(index + num) : false;
function peek() {
return index + 1 < text.length ? text.charAt(index + 1) : false;
}
function isNumber(ch) {
return '0' <= ch && ch <= '9';
@@ -464,7 +456,7 @@ function parser(text, json, $filter, csp){
function equality() {
var left = relational();
var token;
if ((token = expect('==','!=','===','!=='))) {
if ((token = expect('==','!='))) {
left = binaryFn(left, token.fn, equality());
}
return left;
+11 -11
View File
@@ -196,6 +196,7 @@ function $RootScopeProvider(){
child['this'] = child;
child.$$listeners = {};
child.$parent = this;
child.$$asyncQueue = [];
child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;
child.$$prevSibling = this.$$childTail;
if (this.$$childHead) {
@@ -362,7 +363,7 @@ function $RootScopeProvider(){
$digest: function() {
var watch, value, last,
watchers,
asyncQueue = this.$$asyncQueue,
asyncQueue,
length,
dirty, ttl = TTL,
next, current, target = this,
@@ -371,19 +372,18 @@ function $RootScopeProvider(){
beginPhase('$digest');
do { // "while dirty" loop
do {
dirty = false;
current = target;
while(asyncQueue.length) {
try {
current.$eval(asyncQueue.shift());
} catch (e) {
$exceptionHandler(e);
do {
asyncQueue = current.$$asyncQueue;
while(asyncQueue.length) {
try {
current.$eval(asyncQueue.shift());
} catch (e) {
$exceptionHandler(e);
}
}
}
do { // "traverse the scopes" loop
if ((watchers = current.$$watchers)) {
// process our watches
length = watchers.length;
+7 -28
View File
@@ -35,24 +35,12 @@ function $RouteProvider(){
* - `controller` `{(string|function()=}` Controller fn that should be associated with newly
* created scope or the name of a {@link angular.Module#controller registered controller}
* if passed as a string.
* - `template` `{string=|function()=}` html template as a string or function that returns
* an html template as a string which should be used by {@link ng.directive:ngView ngView} or
* - `template` `{string=}` html template as a string that should be used by
* {@link ng.directive:ngView ngView} or
* {@link ng.directive:ngInclude ngInclude} directives.
* This property takes precedence over `templateUrl`.
*
* If `template` is a function, it will be called with the following parameters:
*
* - `{Array.<Object>}` - route parameters extracted from the current
* `$location.path()` by applying the current route
*
* - `templateUrl` `{string=|function()=}` path or function that returns a path to an html
* template that should be used by {@link ng.directive:ngView ngView}.
*
* If `templateUrl` is a function, it will be called with the following parameters:
*
* - `{Array.<Object>}` - route parameters extracted from the current
* `$location.path()` by applying the current route
*
* this property takes precedence over `templateUrl`.
* - `templateUrl` `{string=}` path to an html template that should be used by
* {@link ng.directive:ngView ngView}.
* - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should
* be injected into the controller. If any of these dependencies are promises, they will be
* resolved and converted to a value before the controller is instantiated and the
@@ -407,18 +395,9 @@ function $RouteProvider(){
values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));
});
if (isDefined(template = next.template)) {
if (isFunction(template)) {
template = template(next.params);
}
} else if (isDefined(template = next.templateUrl)) {
if (isFunction(template)) {
template = template(next.params);
}
if (isDefined(template)) {
next.loadedTemplateUrl = template;
template = $http.get(template, {cache: $templateCache}).
then(function(response) { return response.data; });
}
template = $http.get(template, {cache: $templateCache}).
then(function(response) { return response.data; });
}
if (isDefined(template)) {
keys.push('$template');
+6 -7
View File
@@ -5,7 +5,6 @@
*
* @name ng.$sniffer
* @requires $window
* @requires $document
*
* @property {boolean} history Does the browser support html5 history api ?
* @property {boolean} hashchange Does the browser support hashchange event ?
@@ -14,10 +13,9 @@
* This is very simple implementation of testing browser's features.
*/
function $SnifferProvider() {
this.$get = ['$window', '$document', function($window, $document) {
this.$get = ['$window', function($window) {
var eventSupport = {},
android = int((/android (\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]),
document = $document[0];
android = int((/android (\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]);
return {
// Android has history.pushState, but it does not update location correctly
@@ -27,7 +25,7 @@ function $SnifferProvider() {
history: !!($window.history && $window.history.pushState && !(android < 4)),
hashchange: 'onhashchange' in $window &&
// IE8 compatible mode lies
(!document.documentMode || document.documentMode > 7),
(!$window.document.documentMode || $window.document.documentMode > 7),
hasEvent: function(event) {
// IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have
// it. In particular the event is not fired when backspace or delete key are pressed or
@@ -35,13 +33,14 @@ function $SnifferProvider() {
if (event == 'input' && msie == 9) return false;
if (isUndefined(eventSupport[event])) {
var divElm = document.createElement('div');
var divElm = $window.document.createElement('div');
eventSupport[event] = 'on' + event in divElm;
}
return eventSupport[event];
},
csp: document.securityPolicy ? document.securityPolicy.isActive : false
// TODO(i): currently there is no way to feature detect CSP without triggering alerts
csp: false
};
}];
}
+35 -61
View File
@@ -1352,49 +1352,17 @@ function MockXhr() {
* @description
*
* This service is just a simple decorator for {@link ng.$timeout $timeout} service
* that adds a "flush" and "verifyNoPendingTasks" methods.
*/
* that adds a "flush" method.
*/
angular.mock.$TimeoutDecorator = function($delegate, $browser) {
/**
* @ngdoc method
* @name ngMock.$timeout#flush
* @methodOf ngMock.$timeout
* @description
*
* Flushes the queue of pending tasks.
*/
$delegate.flush = function() {
$browser.defer.flush();
};
/**
* @ngdoc method
* @name ngMock.$timeout#verifyNoPendingTasks
* @methodOf ngMock.$timeout
* @description
*
* Verifies that there are no pending tasks that need to be flushed.
*/
$delegate.verifyNoPendingTasks = function() {
if ($browser.deferredFns.length) {
throw Error('Deferred tasks to flush (' + $browser.deferredFns.length + '): ' +
formatPendingTasksAsString($browser.deferredFns));
}
};
function formatPendingTasksAsString(tasks) {
var result = [];
angular.forEach(tasks, function(task) {
result.push('{id: ' + task.id + ', ' + 'time: ' + task.time + '}');
});
return result.join(', ');
}
return $delegate;
};
/**
* @ngdoc method
* @name ngMock.$timeout#flush
* @methodOf ngMock.$timeout
* @description
*
* Flushes the queue of pending tasks.
*/
/**
*
@@ -1420,9 +1388,15 @@ angular.module('ngMock', ['ng']).provider({
$httpBackend: angular.mock.$HttpBackendProvider,
$rootElement: angular.mock.$RootElementProvider
}).config(function($provide) {
$provide.decorator('$timeout', angular.mock.$TimeoutDecorator);
$provide.decorator('$timeout', function($delegate, $browser) {
$delegate.flush = function() {
$browser.defer.flush();
};
return $delegate;
});
});
/**
* @ngdoc overview
* @name ngMockE2E
@@ -1636,20 +1610,14 @@ window.jstestdriver && (function(window) {
})(window);
(window.jasmine || window.mocha) && (function(window) {
var currentSpec = null;
beforeEach(function() {
currentSpec = this;
});
window.jasmine && (function(window) {
afterEach(function() {
var injector = currentSpec.$injector;
var spec = getCurrentSpec();
var injector = spec.$injector;
currentSpec.$injector = null;
currentSpec.$modules = null;
currentSpec = null;
spec.$injector = null;
spec.$modules = null;
if (injector) {
injector.get('$rootElement').unbind();
@@ -1671,8 +1639,13 @@ window.jstestdriver && (function(window) {
angular.callbacks.counter = 0;
});
function getCurrentSpec() {
return jasmine.getEnv().currentSpec;
}
function isSpecRunning() {
return currentSpec && currentSpec.queue.running;
var spec = getCurrentSpec();
return spec && spec.queue.running;
}
/**
@@ -1697,10 +1670,11 @@ window.jstestdriver && (function(window) {
return isSpecRunning() ? workFn() : workFn;
/////////////////////
function workFn() {
if (currentSpec.$injector) {
var spec = getCurrentSpec();
if (spec.$injector) {
throw Error('Injector already created, can not register a module!');
} else {
var modules = currentSpec.$modules || (currentSpec.$modules = []);
var modules = spec.$modules || (spec.$modules = []);
angular.forEach(moduleFns, function(module) {
modules.push(module);
});
@@ -1767,13 +1741,13 @@ window.jstestdriver && (function(window) {
return isSpecRunning() ? workFn() : workFn;
/////////////////////
function workFn() {
var modules = currentSpec.$modules || [];
var spec = getCurrentSpec();
var modules = spec.$modules || [];
modules.unshift('ngMock');
modules.unshift('ng');
var injector = currentSpec.$injector;
var injector = spec.$injector;
if (!injector) {
injector = currentSpec.$injector = angular.injector(modules);
injector = spec.$injector = angular.injector(modules);
}
for(var i = 0, ii = blockFns.length; i < ii; i++) {
try {
+15 -42
View File
@@ -24,8 +24,7 @@
* number, like this: `$resource('http://example.com\\:8080/api')`.
*
* @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in
* `actions` methods. If any of the parameter value is a function, it will be executed every time
* when a param value needs to be obtained for a request (unless the param was overriden).
* `actions` methods.
*
* Each key value in the parameter object is first bound to url template if present and then any
* excess keys are appended to the url search query after the `?`.
@@ -37,40 +36,21 @@
* the data object (useful for non-GET operations).
*
* @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the
* default set of resource actions. The declaration should be created in the format of {@link
* ng.$http#Parameters $http.config}:
* default set of resource actions. The declaration should be created in the following format:
*
* {action1: {method:?, params:?, isArray:?, headers:?, ...},
* action2: {method:?, params:?, isArray:?, headers:?, ...},
* {action1: {method:?, params:?, isArray:?},
* action2: {method:?, params:?, isArray:?},
* ...}
*
* Where:
*
* - **`action`** {string} The name of action. This name becomes the name of the method on your
* - `action` {string} The name of action. This name becomes the name of the method on your
* resource object.
* - **`method`** {string} HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,
* and `JSONP`.
* - **`params`** {Object=} Optional set of pre-bound parameters for this action. If any of the
* parameter value is a function, it will be executed every time when a param value needs to be
* obtained for a request (unless the param was overriden).
* - **`isArray`** {boolean=} If true then the returned object for this action is an array, see
* - `method` {string} HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,
* and `JSONP`
* - `params` {object=} Optional set of pre-bound parameters for this action.
* - isArray {boolean=} If true then the returned object for this action is an array, see
* `returns` section.
* - **`transformRequest`** `{function(data, headersGetter)|Array.<function(data, headersGetter)>}`
* transform function or an array of such functions. The transform function takes the http
* request body and headers and returns its transformed (typically serialized) version.
* - **`transformResponse`** `{function(data, headersGetter)|Array.<function(data, headersGetter)>}`
* transform function or an array of such functions. The transform function takes the http
* response body and headers and returns its transformed (typically deserialized) version.
* - **`cache`** `{boolean|Cache}` If true, a default $http cache will be used to cache the
* GET request, otherwise if a cache instance built with
* {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
* caching.
* - **`timeout`** `{number}` timeout in milliseconds.
* - **`withCredentials`** - `{boolean}` - whether to to set the `withCredentials` flag on the
* XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5
* requests with credentials} for more information.
* - **`responseType`** - `{string}` - see {@link
* https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType requestType}.
*
* @returns {Object} A resource "class" object with methods for the default set of resource actions
* optionally extended with custom `actions`. The default set contains these actions:
@@ -152,7 +132,7 @@
* The object returned from this function execution is a resource "class" which has "static" method
* for each action in the definition.
*
* Calling these methods invoke `$http` on the `url` template with the given `method`, `params` and `headers`.
* Calling these methods invoke `$http` on the `url` template with the given `method` and `params`.
* When the data is returned from the server then the object is an instance of the resource type and
* all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD
* operations (create, read, update, delete) on server-side data.
@@ -344,7 +324,6 @@ angular.module('ngResource', ['ng']).
var ids = {};
actionParams = extend({}, paramDefaults, actionParams);
forEach(actionParams, function(value, key){
if (isFunction(value)) { value = value(); }
ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;
});
return ids;
@@ -397,17 +376,11 @@ angular.module('ngResource', ['ng']).
}
var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));
var httpConfig = {};
forEach(action, function(value, key) {
if (key != 'params' && key != 'isArray' ) {
httpConfig[key] = copy(value);
}
});
httpConfig.data = data;
httpConfig.url = route.url(extend({}, extractParams(data, action.params || {}), params))
$http(httpConfig).then(function(response) {
$http({
method: action.method,
url: route.url(extend({}, extractParams(data, action.params || {}), params)),
data: data
}).then(function(response) {
var data = response.data;
if (data) {
+2 -23
View File
@@ -8,7 +8,6 @@
* plain email address links.
*
* @param {string} text Input text.
* @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in.
* @returns {string} Html-linkified text.
*
* @usage
@@ -25,7 +24,6 @@
'mailto:us@somewhere.org,\n'+
'another@somewhere.org,\n'+
'and one more: ftp://127.0.0.1/.';
$scope.snippetWithTarget = 'http://angularjs.org/';
}
</script>
<div ng-controller="Ctrl">
@@ -45,15 +43,6 @@
<div ng-bind-html="snippet | linky"></div>
</td>
</tr>
<tr id="linky-target">
<td>linky target</td>
<td>
<pre>&lt;div ng-bind-html="snippetWithTarget | linky:'_blank'"&gt;<br>&lt;/div&gt;</pre>
</td>
<td>
<div ng-bind-html="snippetWithTarget | linky:'_blank'"></div>
</td>
</tr>
<tr id="escaped-html">
<td>no filter</td>
<td><pre>&lt;div ng-bind="snippet"&gt;<br>&lt;/div&gt;</pre></td>
@@ -86,11 +75,6 @@
toBe('new <a href="http://link">http://link</a>.');
expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');
});
it('should work with the target property', function() {
expect(using('#linky-target').binding("snippetWithTarget | linky:'_blank'")).
toBe('<a target="_blank" href="http://angularjs.org/">http://angularjs.org/</a>');
});
</doc:scenario>
</doc:example>
*/
@@ -98,7 +82,7 @@ angular.module('ngSanitize').filter('linky', function() {
var LINKY_URL_REGEXP = /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/,
MAILTO_REGEXP = /^mailto:/;
return function(text, target) {
return function(text) {
if (!text) return text;
var match;
var raw = text;
@@ -107,10 +91,6 @@ angular.module('ngSanitize').filter('linky', function() {
var writer = htmlSanitizeWriter(html);
var url;
var i;
var properties = {};
if (angular.isDefined(target)) {
properties.target = target;
}
while ((match = raw.match(LINKY_URL_REGEXP))) {
// We can not end in these as they are sometimes found at the end of the sentence
url = match[0];
@@ -118,8 +98,7 @@ angular.module('ngSanitize').filter('linky', function() {
if (match[2] == match[3]) url = 'mailto:' + url;
i = match.index;
writer.chars(raw.substr(0, i));
properties.href = url;
writer.start('a', properties);
writer.start('a', {href:url});
writer.chars(match[0].replace(MAILTO_REGEXP, ''));
writer.end('a');
raw = raw.substring(i + match[0].length);
+1 -1
View File
@@ -123,7 +123,7 @@ var START_TAG_REGEXP = /^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:
BEGING_END_TAGE_REGEXP = /^<\s*\//,
COMMENT_REGEXP = /<!--(.*?)-->/g,
CDATA_REGEXP = /<!\[CDATA\[(.*?)]]>/g,
URI_REGEXP = /^((ftp|https?):\/\/|mailto:|tel:|#)/,
URI_REGEXP = /^((ftp|https?):\/\/|mailto:|#)/,
NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; // Match everything outside of normal chars and " (quote character)
-27
View File
@@ -298,8 +298,6 @@ angular.scenario.dsl('select', function() {
option = select.find('option:contains("' + value + '")');
if (option.length) {
select.val(option.val());
} else {
return done("option '" + value + "' not found");
}
}
select.trigger('change');
@@ -327,7 +325,6 @@ angular.scenario.dsl('select', function() {
* Usage:
* element(selector, label).count() get the number of elements that match selector
* element(selector, label).click() clicks an element
* element(selector, label).mouseover() mouseover an element
* element(selector, label).query(fn) executes fn(selectedElements, done)
* element(selector, label).{method}() gets the value (as defined by jQuery, ex. val)
* element(selector, label).{method}(value) sets the value (as defined by jQuery, ex. val)
@@ -368,30 +365,6 @@ angular.scenario.dsl('element', function() {
});
};
chain.dblclick = function() {
return this.addFutureAction("element '" + this.label + "' dblclick", function($window, $document, done) {
var elements = $document.elements();
var href = elements.attr('href');
var eventProcessDefault = elements.trigger('dblclick')[0];
if (href && elements[0].nodeName.toUpperCase() === 'A' && eventProcessDefault) {
this.application.navigateTo(href, function() {
done();
}, done);
} else {
done();
}
});
};
chain.mouseover = function() {
return this.addFutureAction("element '" + this.label + "' mouseover", function($window, $document, done) {
var elements = $document.elements();
elements.trigger('mouseover');
done();
});
};
chain.query = function(fn) {
return this.addFutureAction('element ' + this.label + ' custom query', function($window, $document, done) {
fn.call(this, $document.elements(), done);
@@ -0,0 +1,177 @@
'use strict';
/**
* JSTestDriver adapter for angular scenario tests
*
* Example of jsTestDriver.conf for running scenario tests with JSTD:
<pre>
server: http://localhost:9877
load:
- lib/angular-scenario.js
- lib/jstd-scenario-adapter-config.js
- lib/jstd-scenario-adapter.js
# your test files go here #
proxy:
- {matcher: "/your-prefix/*", server: "http://localhost:8000/"}
</pre>
*
* For more information on how to configure jstd proxy, see {@link http://code.google.com/p/js-test-driver/wiki/Proxy}
* Note the order of files - it's important !
*
* Example of jstd-scenario-adapter-config.js
<pre>
var jstdScenarioAdapter = {
relativeUrlPrefix: '/your-prefix/'
};
</pre>
*
* Whenever you use <code>browser().navigateTo('relativeUrl')</code> in your scenario test, the relativeUrlPrefix will be prepended.
* You have to configure this to work together with JSTD proxy.
*
* Let's assume you are using the above configuration (jsTestDriver.conf and jstd-scenario-adapter-config.js):
* Now, when you call <code>browser().navigateTo('index.html')</code> in your scenario test, the browser will open /your-prefix/index.html.
* That matches the proxy, so JSTD will proxy this request to http://localhost:8000/index.html.
*/
/**
* Custom type of test case
*
* @const
* @see jstestdriver.TestCaseInfo
*/
var SCENARIO_TYPE = 'scenario';
/**
* Plugin for JSTestDriver
* Connection point between scenario's jstd output and jstestdriver.
*
* @see jstestdriver.PluginRegistrar
*/
function JstdPlugin() {
var nop = function() {};
this.reportResult = nop;
this.reportEnd = nop;
this.runScenario = nop;
this.name = 'Angular Scenario Adapter';
/**
* Called for each JSTD TestCase
*
* Handles only SCENARIO_TYPE test cases. There should be only one fake TestCase.
* Runs all scenario tests (under one fake TestCase) and report all results to JSTD.
*
* @param {jstestdriver.TestRunConfiguration} configuration
* @param {Function} onTestDone
* @param {Function} onAllTestsComplete
* @returns {boolean} True if this type of test is handled by this plugin, false otherwise
*/
this.runTestConfiguration = function(configuration, onTestDone, onAllTestsComplete) {
if (configuration.getTestCaseInfo().getType() != SCENARIO_TYPE) return false;
this.reportResult = onTestDone;
this.reportEnd = onAllTestsComplete;
this.runScenario();
return true;
};
this.getTestRunsConfigurationFor = function(testCaseInfos, expressions, testRunsConfiguration) {
testRunsConfiguration.push(
new jstestdriver.TestRunConfiguration(
new jstestdriver.TestCaseInfo(
'Angular Scenario Tests', function() {}, SCENARIO_TYPE), []));
return true;
};
}
/**
* Singleton instance of the plugin
* Accessed using closure by:
* - jstd output (reports to this plugin)
* - initScenarioAdapter (register the plugin to jstd)
*/
var plugin = new JstdPlugin();
/**
* Initialise scenario jstd-adapter
* (only if jstestdriver is defined)
*
* @param {Object} jstestdriver Undefined when run from browser (without jstd)
* @param {Function} initScenarioAndRun Function that inits scenario and runs all the tests
* @param {Object=} config Configuration object, supported properties:
* - relativeUrlPrefix: prefix for all relative links when navigateTo()
*/
function initScenarioAdapter(jstestdriver, initScenarioAndRun, config) {
if (jstestdriver) {
// create and register ScenarioPlugin
jstestdriver.pluginRegistrar.register(plugin);
plugin.runScenario = initScenarioAndRun;
/**
* HACK (angular.scenario.Application.navigateTo)
*
* We need to navigate to relative urls when running from browser (without JSTD),
* because we want to allow running scenario tests without creating its own virtual host.
* For example: http://angular.local/build/docs/docs-scenario.html
*
* On the other hand, when running with JSTD, we need to navigate to absolute urls,
* because of JSTD proxy. (proxy, because of same domain policy)
*
* So this hack is applied only if running with JSTD and change all relative urls to absolute.
*/
var appProto = angular.scenario.Application.prototype,
navigateTo = appProto.navigateTo,
relativeUrlPrefix = config && config.relativeUrlPrefix || '/';
appProto.navigateTo = function(url, loadFn, errorFn) {
if (url.charAt(0) != '/' && url.charAt(0) != '#' &&
url != 'about:blank' && !url.match(/^https?/)) {
url = relativeUrlPrefix + url;
}
return navigateTo.call(this, url, loadFn, errorFn);
};
}
}
/**
* Builds proper TestResult object from given model spec
*
* TODO(vojta) report error details
*
* @param {angular.scenario.ObjectModel.Spec} spec
* @returns {jstestdriver.TestResult}
*/
function createTestResultFromSpec(spec) {
var map = {
success: 'PASSED',
error: 'ERROR',
failure: 'FAILED'
};
return new jstestdriver.TestResult(
spec.fullDefinitionName,
spec.name,
jstestdriver.TestResult.RESULT[map[spec.status]],
spec.error || '',
spec.line || '',
spec.duration);
}
/**
* Generates JSTD output (jstestdriver.TestResult)
*/
angular.scenario.output('jstd', function(context, runner, model) {
model.on('SpecEnd', function(spec) {
plugin.reportResult(createTestResultFromSpec(spec));
});
model.on('RunnerEnd', function() {
plugin.reportEnd();
});
});
@@ -0,0 +1,6 @@
/**
* @license AngularJS v"NG_VERSION_FULL"
* (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window) {
@@ -0,0 +1,2 @@
initScenarioAdapter(window.jstestdriver, angular.scenario.setUpAndRun, window.jstdScenarioAdapter);
})(window);
+1 -1
View File
@@ -175,7 +175,7 @@ describe('Binder', function() {
$rootScope.error['throw'] = function() {throw 'MyError';};
errorLogs.length = 0;
$rootScope.$apply();
expect(errorLogs.shift().message).toBe('Error while interpolating: {{error.throw()}}\nMyError');
expect(errorLogs.shift()).toBe('MyError');
$rootScope.error['throw'] = function() {return 'ok';};
$rootScope.$apply();
+8 -15
View File
@@ -3,13 +3,11 @@
describe('injector', function() {
var providers;
var injector;
var providerInjector;
beforeEach(module(function($provide, $injector) {
beforeEach(module(function($provide) {
providers = function(name, factory, annotations) {
$provide.factory(name, extend(factory, annotations||{}));
};
providerInjector = $injector;
}));
beforeEach(inject(function($injector){
injector = $injector;
@@ -74,11 +72,6 @@ describe('injector', function() {
});
it('should create a new $injector for the run phase', inject(function($injector) {
expect($injector).not.toBe(providerInjector);
}));
describe('invoke', function() {
var args;
@@ -556,26 +549,26 @@ describe('injector', function() {
it('should decorate the missing service error with module name', function() {
angular.module('TestModule', [], function(xyzzy) {});
angular.module('TestModule', [], function($injector) {});
expect(function() {
createInjector(['TestModule']);
}).toThrow('Unknown provider: xyzzy from TestModule');
}).toThrow('Unknown provider: $injector from TestModule');
});
it('should decorate the missing service error with module function', function() {
function myModule(xyzzy){}
function myModule($injector){}
expect(function() {
createInjector([myModule]);
}).toThrow('Unknown provider: xyzzy from ' + myModule);
}).toThrow('Unknown provider: $injector from ' + myModule);
});
it('should decorate the missing service error with module array function', function() {
function myModule(xyzzy){}
function myModule($injector){}
expect(function() {
createInjector([['xyzzy', myModule]]);
}).toThrow('Unknown provider: xyzzy from ' + myModule);
createInjector([['$injector', myModule]]);
}).toThrow('Unknown provider: $injector from ' + myModule);
});
+1 -6
View File
@@ -955,14 +955,9 @@ describe('jqLite', function() {
expect(root.append('text')).toEqual(root);
expect(root.html()).toEqual('text');
});
it('should append to document fragment', function() {
it('should not append anything if parent node is not of type element', function() {
var root = jqLite(document.createDocumentFragment());
expect(root.append('<p>foo</p>')).toBe(root);
expect(root.children().length).toBe(1);
});
it('should not append anything if parent node is not of type element or docfrag', function() {
var root = jqLite('<p>some text node</p>').contents();
expect(root.append('<p>foo</p>')).toBe(root);
expect(root.children().length).toBe(0);
});
});
-6
View File
@@ -104,12 +104,6 @@ describe('$cacheFactory', function() {
cache.remove(123);
expect(cache.info().size).toBe(0);
}));
it("should return value from put", inject(function($cacheFactory) {
var obj = {};
expect(cache.put('k1', obj)).toBe(obj);
}));
});
-10
View File
@@ -74,16 +74,6 @@ describe('boolean attr directives', function() {
$rootScope.$digest();
expect(element.attr('multiple')).toBeTruthy();
}));
it('should bind open', inject(function($rootScope, $compile) {
element = $compile('<details ng-open="isOpen"></details>')($rootScope)
$rootScope.isOpen=false;
$rootScope.$digest();
expect(element.attr('open')).toBeFalsy();
$rootScope.isOpen=true;
$rootScope.$digest();
expect(element.attr('open')).toBeTruthy();
}));
});
-106
View File
@@ -430,110 +430,4 @@ describe('form', function() {
expect(doc).toBeDirty();
});
});
describe('$setPristine', function() {
it('should reset pristine state of form and controls', function() {
doc = $compile(
'<form name="testForm">' +
'<input ng-model="named1" name="foo">' +
'<input ng-model="named2" name="bar">' +
'</form>')(scope);
scope.$digest();
var form = doc,
formCtrl = scope.testForm,
input1 = form.find('input').eq(0),
input1Ctrl = input1.controller('ngModel'),
input2 = form.find('input').eq(1),
input2Ctrl = input2.controller('ngModel');
input1Ctrl.$setViewValue('xx');
input2Ctrl.$setViewValue('yy');
scope.$apply();
expect(form).toBeDirty();
expect(input1).toBeDirty();
expect(input2).toBeDirty();
formCtrl.$setPristine();
expect(form).toBePristine();
expect(formCtrl.$pristine).toBe(true);
expect(formCtrl.$dirty).toBe(false);
expect(input1).toBePristine();
expect(input1Ctrl.$pristine).toBe(true);
expect(input1Ctrl.$dirty).toBe(false);
expect(input2).toBePristine();
expect(input2Ctrl.$pristine).toBe(true);
expect(input2Ctrl.$dirty).toBe(false);
});
it('should reset pristine state of anonymous form controls', function() {
doc = $compile(
'<form name="testForm">' +
'<input ng-model="anonymous">' +
'</form>')(scope);
scope.$digest();
var form = doc,
formCtrl = scope.testForm,
input = form.find('input').eq(0),
inputCtrl = input.controller('ngModel');
inputCtrl.$setViewValue('xx');
scope.$apply();
expect(form).toBeDirty();
expect(input).toBeDirty();
formCtrl.$setPristine();
expect(form).toBePristine();
expect(formCtrl.$pristine).toBe(true);
expect(formCtrl.$dirty).toBe(false);
expect(input).toBePristine();
expect(inputCtrl.$pristine).toBe(true);
expect(inputCtrl.$dirty).toBe(false);
});
it('should reset pristine state of nested forms', function() {
doc = $compile(
'<form name="testForm">' +
'<div ng-form>' +
'<input ng-model="named" name="foo">' +
'</div>' +
'</form>')(scope);
scope.$digest();
var form = doc,
formCtrl = scope.testForm,
nestedForm = form.find('div'),
nestedFormCtrl = nestedForm.controller('form'),
nestedInput = form.find('input').eq(0),
nestedInputCtrl = nestedInput.controller('ngModel');
nestedInputCtrl.$setViewValue('xx');
scope.$apply();
expect(form).toBeDirty();
expect(nestedForm).toBeDirty();
expect(nestedInput).toBeDirty();
formCtrl.$setPristine();
expect(form).toBePristine();
expect(formCtrl.$pristine).toBe(true);
expect(formCtrl.$dirty).toBe(false);
expect(nestedForm).toBePristine();
expect(nestedFormCtrl.$pristine).toBe(true);
expect(nestedFormCtrl.$dirty).toBe(false);
expect(nestedInput).toBePristine();
expect(nestedInputCtrl.$pristine).toBe(true);
expect(nestedInputCtrl.$dirty).toBe(false);
});
});
});
-20
View File
@@ -117,18 +117,6 @@ describe('NgModelController', function() {
});
});
describe('setPristine', function() {
it('should set control to its pristine state', function() {
ctrl.$setViewValue('edit');
expect(ctrl.$dirty).toBe(true);
expect(ctrl.$pristine).toBe(false);
ctrl.$setPristine();
expect(ctrl.$dirty).toBe(false);
expect(ctrl.$pristine).toBe(true);
});
});
describe('view -> model', function() {
@@ -394,14 +382,6 @@ describe('input', function() {
});
it('should update the model and not trim the value', function() {
compileInput('<input type="text" ng-model="name" name="alias" ng-trim="false" />');
changeInputValueTo(' a ');
expect(scope.name).toEqual(' a ');
});
it('should allow complex reference binding', function() {
compileInput('<input type="text" ng-model="obj[\'abc\'].name"/>');
-29
View File
@@ -1,29 +0,0 @@
'use strict';
describe('ngKeyup and ngKeydown directives', function() {
var element;
afterEach(function() {
dealoc(element);
});
it('should get called on a keyup', inject(function($rootScope, $compile) {
element = $compile('<input ng-keyup="touched = true">')($rootScope);
$rootScope.$digest();
expect($rootScope.touched).toBeFalsy();
browserTrigger(element, 'keyup');
expect($rootScope.touched).toEqual(true);
}));
it('should get called on a keydown', inject(function($rootScope, $compile) {
element = $compile('<input ng-keydown="touched = true">')($rootScope);
$rootScope.$digest();
expect($rootScope.touched).toBeFalsy();
browserTrigger(element, 'keydown');
expect($rootScope.touched).toEqual(true);
}));
});
+14 -19
View File
@@ -253,37 +253,32 @@ describe('filters', function() {
});
it('should support various iso8061 date strings with timezone as input', function() {
var format = 'yyyy-MM-dd ss';
it('should support various iso8061 date strings as input', function() {
var format = 'yyyy-MM ss';
//full ISO8061
expect(date('2003-09-10T13:02:03.000Z', format)).toEqual('2003-09-10 03');
expect(date('2003-09-10T13:02:03.000Z', format)).toEqual('2003-09 03');
expect(date('2003-09-10T13:02:03.000+00:00', format)).toEqual('2003-09-10 03');
expect(date('2003-09-10T13:02:03.000+00:00', format)).toEqual('2003-09 03');
expect(date('20030910T033203-0930', format)).toEqual('2003-09-10 03');
expect(date('2003-09-10T13:02:03-08:00', format)).toEqual('2003-09 03');
expect(date('20030910T033203-0930', format)).toEqual('2003-09 03');
//no timezone
expect(date('2003-09-10T13:02:03.000', format)).toEqual('2003-09 03');
//no millis
expect(date('2003-09-10T13:02:03Z', format)).toEqual('2003-09-10 03');
expect(date('2003-09-10T13:02:03Z', format)).toEqual('2003-09 03');
//no seconds
expect(date('2003-09-10T13:02Z', format)).toEqual('2003-09-10 00');
expect(date('2003-09-10T13:02Z', format)).toEqual('2003-09 00');
//no minutes
expect(date('2003-09-10T13Z', format)).toEqual('2003-09-10 00');
});
it('should parse iso8061 date strings without timezone as local time', function() {
var format = 'yyyy-MM-dd HH-mm-ss';
//full ISO8061 without timezone
expect(date('2003-09-10T03:02:04.000', format)).toEqual('2003-09-10 03-02-04');
expect(date('20030910T030204', format)).toEqual('2003-09-10 03-02-04');
expect(date('2003-09-10T13Z', format)).toEqual('2003-09 00');
//no time
expect(date('2003-09-10', format)).toEqual('2003-09-10 00-00-00');
expect(date('2003-09-10', format)).toEqual('2003-09 00');
});
it('should support different degrees of subsecond precision', function () {
+5 -24
View File
@@ -2,12 +2,10 @@
describe('Filter: limitTo', function() {
var items;
var str
var limitTo;
beforeEach(inject(function($filter) {
items = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
str = "tuvwxyz";
limitTo = $filter('limitTo');
}));
@@ -15,16 +13,12 @@ describe('Filter: limitTo', function() {
it('should return the first X items when X is positive', function() {
expect(limitTo(items, 3)).toEqual(['a', 'b', 'c']);
expect(limitTo(items, '3')).toEqual(['a', 'b', 'c']);
expect(limitTo(str, 3)).toEqual("tuv");
expect(limitTo(str, '3')).toEqual("tuv");
});
it('should return the last X items when X is negative', function() {
expect(limitTo(items, -3)).toEqual(['f', 'g', 'h']);
expect(limitTo(items, '-3')).toEqual(['f', 'g', 'h']);
expect(limitTo(str, -3)).toEqual("xyz");
expect(limitTo(str, '-3')).toEqual("xyz");
});
@@ -36,17 +30,11 @@ describe('Filter: limitTo', function() {
expect(limitTo(items, undefined)).toEqual([]);
});
it('should return an empty string when X cannot be parsed', function() {
expect(limitTo(str, 'bogus')).toEqual("");
expect(limitTo(str, 'null')).toEqual("");
expect(limitTo(str, 'undefined')).toEqual("");
expect(limitTo(str, null)).toEqual("");
expect(limitTo(str, undefined)).toEqual("");
});
it('should return input if not String or Array', function() {
expect(limitTo(1,1)).toEqual(1);
it('should return an empty array when input is not Array type', function() {
expect(limitTo('bogus', 1)).toEqual('bogus');
expect(limitTo(null, 1)).toEqual(null);
expect(limitTo(undefined, 1)).toEqual(undefined);
expect(limitTo(null, 1)).toEqual(null);
expect(limitTo(undefined, 1)).toEqual(undefined);
expect(limitTo({}, 1)).toEqual({});
@@ -54,18 +42,11 @@ describe('Filter: limitTo', function() {
it('should return a copy of input array if X is exceeds array length', function () {
expect(limitTo(items, 9)).toEqual(items);
expect(limitTo(items, 19)).toEqual(items);
expect(limitTo(items, '9')).toEqual(items);
expect(limitTo(items, -9)).toEqual(items);
expect(limitTo(items, '-9')).toEqual(items);
expect(limitTo(items, 9)).not.toBe(items);
});
it('should return the entire string if X exceeds input length', function() {
expect(limitTo(str, 9)).toEqual(str);
expect(limitTo(str, '9')).toEqual(str);
expect(limitTo(str, -9)).toEqual(str);
expect(limitTo(str, '-9')).toEqual(str);
})
});
-18
View File
@@ -135,24 +135,6 @@ describe('$httpBackend', function() {
});
it('should set responseType and return xhr.response', function() {
$backend('GET', '/whatever', null, callback, {}, null, null, 'blob');
var xhrInstance = MockXhr.$$lastInstance;
expect(xhrInstance.responseType).toBe('blob');
callback.andCallFake(function(status, response) {
expect(response).toBe(xhrInstance.response);
});
xhrInstance.response = {some: 'object'};
xhrInstance.readyState = 4;
xhrInstance.onreadystatechange();
expect(callback).toHaveBeenCalledOnce();
});
describe('JSONP', function() {
var SCRIPT_URL = /([^\?]*)\?cb=angular\.callbacks\.(.*)/;
+10 -69
View File
@@ -147,12 +147,6 @@ describe('$http', function() {
$httpBackend.expect('GET', '/url?a=1&b=%7B%22c%22%3A3%7D').respond('');
$http({url: '/url', params: {a:1, b:{c:3}}, method: 'GET'});
}));
it('should expand arrays in params map', inject(function($httpBackend, $http) {
$httpBackend.expect('GET', '/url?a=1&a=2&a=3').respond('');
$http({url: '/url', params: {a: [1,2,3]}, method: 'GET'});
}));
});
@@ -377,7 +371,8 @@ describe('$http', function() {
it('should set default headers for GET request', function() {
$httpBackend.expect('GET', '/url', undefined, function(headers) {
return headers['Accept'] == 'application/json, text/plain, */*';
return headers['Accept'] == 'application/json, text/plain, */*' &&
headers['X-Requested-With'] == 'XMLHttpRequest';
}).respond('');
$http({url: '/url', method: 'GET', headers: {}});
@@ -388,6 +383,7 @@ describe('$http', function() {
it('should set default headers for POST request', function() {
$httpBackend.expect('POST', '/url', 'messageBody', function(headers) {
return headers['Accept'] == 'application/json, text/plain, */*' &&
headers['X-Requested-With'] == 'XMLHttpRequest' &&
headers['Content-Type'] == 'application/json;charset=utf-8';
}).respond('');
@@ -399,6 +395,7 @@ describe('$http', function() {
it('should set default headers for PUT request', function() {
$httpBackend.expect('PUT', '/url', 'messageBody', function(headers) {
return headers['Accept'] == 'application/json, text/plain, */*' &&
headers['X-Requested-With'] == 'XMLHttpRequest' &&
headers['Content-Type'] == 'application/json;charset=utf-8';
}).respond('');
@@ -409,7 +406,8 @@ describe('$http', function() {
it('should set default headers for custom HTTP method', function() {
$httpBackend.expect('FOO', '/url', undefined, function(headers) {
return headers['Accept'] == 'application/json, text/plain, */*';
return headers['Accept'] == 'application/json, text/plain, */*' &&
headers['X-Requested-With'] == 'XMLHttpRequest';
}).respond('');
$http({url: '/url', method: 'FOO', headers: {}});
@@ -420,6 +418,7 @@ describe('$http', function() {
it('should override default headers with custom', function() {
$httpBackend.expect('POST', '/url', 'messageBody', function(headers) {
return headers['Accept'] == 'Rewritten' &&
headers['X-Requested-With'] == 'XMLHttpRequest' &&
headers['Content-Type'] == 'Rewritten';
}).respond('');
@@ -430,17 +429,6 @@ describe('$http', function() {
$httpBackend.flush();
});
it('should not set XSRF cookie for cross-domain requests', inject(function($browser) {
$browser.cookies('XSRF-TOKEN', 'secret');
$browser.url('http://host.com/base');
$httpBackend.expect('GET', 'http://www.test.com/url', undefined, function(headers) {
return headers['X-XSRF-TOKEN'] === undefined;
}).respond('');
$http({url: 'http://www.test.com/url', method: 'GET', headers: {}});
$httpBackend.flush();
}));
it('should not send Content-Type header if request data/body is undefined', function() {
$httpBackend.expect('POST', '/url', undefined, function(headers) {
@@ -971,13 +959,12 @@ describe('$http', function() {
});
it('should pass timeout, withCredentials and responseType', function() {
it('should pass timeout and withCredentials', function() {
var $httpBackend = jasmine.createSpy('$httpBackend');
$httpBackend.andCallFake(function(m, u, d, c, h, timeout, withCredentials, responseType) {
$httpBackend.andCallFake(function(m, u, d, c, h, timeout, withCredentials) {
expect(timeout).toBe(12345);
expect(withCredentials).toBe(true);
expect(responseType).toBe('json');
});
module(function($provide) {
@@ -985,56 +972,10 @@ describe('$http', function() {
});
inject(function($http) {
$http({
method: 'GET', url: 'some.html', timeout: 12345, withCredentials: true, responseType: 'json'
});
$http({method: 'GET', url: 'some.html', timeout: 12345, withCredentials: true});
expect($httpBackend).toHaveBeenCalledOnce();
});
$httpBackend.verifyNoOutstandingExpectation = noop;
});
it('should use withCredentials from default', function() {
var $httpBackend = jasmine.createSpy('$httpBackend');
$httpBackend.andCallFake(function(m, u, d, c, h, timeout, withCredentials, responseType) {
expect(withCredentials).toBe(true);
});
module(function($provide) {
$provide.value('$httpBackend', $httpBackend);
});
inject(function($http) {
$http.defaults.withCredentials = true;
$http({
method: 'GET', url: 'some.html', timeout: 12345, responseType: 'json'
});
expect($httpBackend).toHaveBeenCalledOnce();
});
$httpBackend.verifyNoOutstandingExpectation = noop;
});
describe('isSameDomain', function() {
it('should support various combinations of urls', function() {
expect(isSameDomain('path/morepath',
'http://www.adomain.com')).toBe(true);
expect(isSameDomain('http://www.adomain.com/path',
'http://www.adomain.com')).toBe(true);
expect(isSameDomain('//www.adomain.com/path',
'http://www.adomain.com')).toBe(true);
expect(isSameDomain('//www.adomain.com/path',
'https://www.adomain.com')).toBe(true);
expect(isSameDomain('//www.adomain.com/path',
'http://www.adomain.com:1234')).toBe(false);
expect(isSameDomain('https://www.adomain.com/path',
'http://www.adomain.com')).toBe(false);
expect(isSameDomain('http://www.adomain.com:1234/path',
'http://www.adomain.com')).toBe(false);
expect(isSameDomain('http://www.anotherdomain.com/path',
'http://www.adomain.com')).toBe(false);
});
});
});
-23
View File
@@ -26,29 +26,6 @@ describe('$interpolate', function() {
expect($interpolate('{{ false }}')()).toEqual('false');
}));
it('should rethrow exceptions', inject(function($interpolate, $rootScope) {
$rootScope.err = function () {
throw new Error('oops');
};
expect(function () {
$interpolate('{{err()}}')($rootScope);
}).toThrow('Error while interpolating: {{err()}}\nError: oops');
}));
it('should stop interpolation when encountering an exception', inject(function($interpolate, $compile, $rootScope) {
$rootScope.err = function () {
throw new Error('oops');
};
var dom = jqLite('<div>{{1 + 1}}</div><div>{{err()}}</div><div>{{1 + 2}}</div>');
$compile(dom)($rootScope);
expect(function () {
$rootScope.$apply();
}).toThrow('Error while interpolating: {{err()}}\nError: oops');
expect(dom[0].innerHTML).toEqual('2');
expect(dom[1].innerHTML).toEqual('{{err()}}');
expect(dom[2].innerHTML).toEqual('{{1 + 2}}');
}));
it('should return interpolation function', inject(function($interpolate, $rootScope) {
$rootScope.name = 'Misko';
+8 -45
View File
@@ -1,24 +1,17 @@
'use strict';
function initService(debugEnabled) {
return module(function($logProvider){
$logProvider.debugEnabled(debugEnabled);
});
}
describe('$log', function() {
var $window, logger, log, warn, info, error, debug;
var $window, logger, log, warn, info, error;
beforeEach(module(function($provide){
$window = {navigator: {}, document: {}};
$window = {navigator: {}};
logger = '';
log = function() { logger+= 'log;'; };
warn = function() { logger+= 'warn;'; };
info = function() { logger+= 'info;'; };
error = function() { logger+= 'error;'; };
debug = function() { logger+= 'debug;'; };
$provide.provider('$log', $LogProvider);
$provide.value('$exceptionHandler', angular.mock.rethrow);
@@ -30,16 +23,14 @@ describe('$log', function() {
$window.console = {log: log,
warn: warn,
info: info,
error: error,
debug: debug};
error: error};
},
function($log) {
$log.log();
$log.warn();
$log.info();
$log.error();
$log.debug();
expect(logger).toEqual('log;warn;info;error;debug;');
expect(logger).toEqual('log;warn;info;error;');
}
));
@@ -53,8 +44,7 @@ describe('$log', function() {
$log.warn();
$log.info();
$log.error();
$log.debug();
expect(logger).toEqual('log;log;log;log;log;');
expect(logger).toEqual('log;log;log;log;');
}
));
@@ -65,7 +55,6 @@ describe('$log', function() {
$log.warn();
$log.info();
$log.error();
$log.debug();
}
));
@@ -75,48 +64,22 @@ describe('$log', function() {
log.apply = log.call =
warn.apply = warn.call =
info.apply = info.call =
error.apply = error.call =
debug.apply = debug.call = null;
error.apply = error.call = null;
$window.console = {log: log,
warn: warn,
info: info,
error: error,
debug: debug};
error: error};
},
function($log) {
$log.log.apply($log);
$log.warn.apply($log);
$log.info.apply($log);
$log.error.apply($log);
$log.debug.apply($log);
expect(logger).toEqual('log;warn;info;error;debug;');
expect(logger).toEqual('log;warn;info;error;');
})
);
describe("$log.debug", function () {
beforeEach(initService(false));
it("should skip debugging output if disabled", inject(
function(){
$window.console = {log: log,
warn: warn,
info: info,
error: error,
debug: debug};
},
function($log) {
$log.log();
$log.warn();
$log.info();
$log.error();
$log.debug();
expect(logger).toEqual('log;warn;info;error;');
}
));
});
describe('$log.error', function() {
var e, $log, errorArgs;
+3 -13
View File
@@ -91,8 +91,8 @@ describe('parser', function() {
expect(tokens[1].text).toEqual('b');
});
it('should tokenize relation and equality', function() {
var tokens = lex("! == != < > <= >= === !==");
it('should tokenize relation', function() {
var tokens = lex("! == != < > <= >=");
expect(tokens[0].text).toEqual('!');
expect(tokens[1].text).toEqual('==');
expect(tokens[2].text).toEqual('!=');
@@ -100,8 +100,6 @@ describe('parser', function() {
expect(tokens[4].text).toEqual('>');
expect(tokens[5].text).toEqual('<=');
expect(tokens[6].text).toEqual('>=');
expect(tokens[7].text).toEqual('===');
expect(tokens[8].text).toEqual('!==');
});
it('should tokenize statements', function() {
@@ -199,20 +197,12 @@ describe('parser', function() {
expect(scope.$eval("false")).toBeFalsy();
expect(scope.$eval("!true")).toBeFalsy();
expect(scope.$eval("1==1")).toBeTruthy();
expect(scope.$eval("1==true")).toBeTruthy();
expect(scope.$eval("1===1")).toBeTruthy();
expect(scope.$eval("1==='1'")).toBeFalsy();
expect(scope.$eval("1===true")).toBeFalsy();
expect(scope.$eval("'true'===true")).toBeFalsy();
expect(scope.$eval("1!==2")).toBeTruthy();
expect(scope.$eval("1!=='1'")).toBeTruthy();
expect(scope.$eval("1!=2")).toBeTruthy();
expect(scope.$eval("1<2")).toBeTruthy();
expect(scope.$eval("1<=1")).toBeTruthy();
expect(scope.$eval("1>2")).toEqual(1>2);
expect(scope.$eval("2>=1")).toEqual(2>=1);
expect(scope.$eval("true==2<3")).toEqual(true == 2<3);
expect(scope.$eval("true===2<3")).toEqual(true === 2<3);
expect(scope.$eval("true==2<3")).toEqual(true === 2<3);
});
it('should parse logical', function() {
+1 -1
View File
@@ -457,7 +457,7 @@ describe('Scope', function() {
child.$evalAsync(function(scope) { log += 'child.async;'; });
child.$watch('value', function() { log += 'child.$digest;'; });
$rootScope.$digest();
expect(log).toEqual('parent.async;child.async;parent.$digest;child.$digest;');
expect(log).toEqual('parent.async;parent.$digest;child.async;child.$digest;');
}));
it('should cause a $digest rerun', inject(function($rootScope) {
-47
View File
@@ -715,53 +715,6 @@ describe('$route', function() {
});
it('should allow using a function as a template', function() {
var customTemplateWatcher = jasmine.createSpy('customTemplateWatcher');
function customTemplateFn(routePathParams) {
customTemplateWatcher(routePathParams);
expect(routePathParams).toEqual({id: 'id3'});
return '<h1>' + routePathParams.id + '</h1>';
}
module(function($routeProvider){
$routeProvider.when('/bar/:id/:subid/:subsubid', {templateUrl: 'bar.html'});
$routeProvider.when('/foo/:id', {template: customTemplateFn});
});
inject(function($route, $location, $rootScope) {
$location.path('/foo/id3');
$rootScope.$digest();
expect(customTemplateWatcher).toHaveBeenCalledWith({id: 'id3'});
});
});
it('should allow using a function as a templateUrl', function() {
var customTemplateUrlWatcher = jasmine.createSpy('customTemplateUrlWatcher');
function customTemplateUrlFn(routePathParams) {
customTemplateUrlWatcher(routePathParams);
expect(routePathParams).toEqual({id: 'id3'});
return 'foo.html';
}
module(function($routeProvider){
$routeProvider.when('/bar/:id/:subid/:subsubid', {templateUrl: 'bar.html'});
$routeProvider.when('/foo/:id', {templateUrl: customTemplateUrlFn});
});
inject(function($route, $location, $rootScope) {
$location.path('/foo/id3');
$rootScope.$digest();
expect(customTemplateUrlWatcher).toHaveBeenCalledWith({id: 'id3'});
expect($route.current.loadedTemplateUrl).toEqual('foo.html');
});
});
describe('reload', function() {
it('should reload even if reloadOnSearch is false', function() {
+6 -24
View File
@@ -2,10 +2,9 @@
describe('$sniffer', function() {
function sniffer($window, $document) {
function sniffer($window) {
$window.navigator = {};
$document = jqLite($document || {});
return new $SnifferProvider().$get[2]($window, $document);
return new $SnifferProvider().$get[1]($window);
}
describe('history', function() {
@@ -21,15 +20,15 @@ describe('$sniffer', function() {
describe('hashchange', function() {
it('should be true if onhashchange property defined', function() {
expect(sniffer({onhashchange: true}, {}).hashchange).toBe(true);
expect(sniffer({onhashchange: true, document: {}}).hashchange).toBe(true);
});
it('should be false if onhashchange property not defined', function() {
expect(sniffer({}, {}).hashchange).toBe(false);
expect(sniffer({document: {}}).hashchange).toBe(false);
});
it('should be false if documentMode is 7 (IE8 comp mode)', function() {
expect(sniffer({onhashchange: true}, {documentMode: 7}).hashchange).toBe(false);
expect(sniffer({onhashchange: true, document: {documentMode: 7}}).hashchange).toBe(false);
});
});
@@ -43,7 +42,7 @@ describe('$sniffer', function() {
if (elm === 'div') return mockDivElement;
});
$sniffer = sniffer({}, mockDocument);
$sniffer = sniffer({document: mockDocument});
});
@@ -79,21 +78,4 @@ describe('$sniffer', function() {
expect($sniffer.hasEvent('input')).toBe((msie == 9) ? false : true);
});
});
describe('csp', function() {
it('should be false if document.securityPolicy.isActive not available', function() {
expect(sniffer({}, {}).csp).toBe(false);
});
it('should use document.securityPolicy.isActive if available', function() {
var createDocumentWithCSP = function(csp) {
return {securityPolicy: {isActive: csp}};
};
expect(sniffer({}, createDocumentWithCSP(false)).csp).toBe(false);
expect(sniffer({}, createDocumentWithCSP(true)).csp).toBe(true);
});
});
});
-16
View File
@@ -327,22 +327,6 @@ describe('ngMock', function() {
$timeout.flush();
expect(logger).toEqual(['t1', 't3', 't2']);
}));
it('should throw an exception when not flushed', inject(function($timeout){
$timeout(noop);
var expectedError = 'Deferred tasks to flush (1): {id: 0, time: 0}';
expect(function() {$timeout.verifyNoPendingTasks();}).toThrow(expectedError);
}));
it('should do nothing when all tasks have been flushed', inject(function($timeout) {
$timeout(noop);
$timeout.flush();
expect(function() {$timeout.verifyNoPendingTasks();}).not.toThrow();
}));
});
-67
View File
@@ -14,14 +14,7 @@ describe("resource", function() {
},
patch: {
method: 'PATCH'
},
conditionalPut: {
method: 'PUT',
headers: {
'If-None-Match': '*'
}
}
});
callback = jasmine.createSpy();
}));
@@ -220,15 +213,6 @@ describe("resource", function() {
});
it('should send correct headers', function() {
$httpBackend.expectPUT('/CreditCard/123', undefined, function(headers) {
return headers['If-None-Match'] == "*";
}).respond({id:123});
CreditCard.conditionalPut({id: {key:123}});
});
it("should read partial resource", function() {
$httpBackend.expect('GET', '/CreditCard').respond([{id:{key:123}}]);
var ccs = CreditCard.query();
@@ -381,35 +365,6 @@ describe("resource", function() {
});
it('should support dynamic default parameters (global)', function() {
var currentGroup = 'students',
Person = $resource('/Person/:group/:id', { group: function() { return currentGroup; }});
$httpBackend.expect('GET', '/Person/students/fedor').respond({id: 'fedor', email: 'f@f.com'});
var fedor = Person.get({id: 'fedor'});
$httpBackend.flush();
expect(fedor).toEqualData({id: 'fedor', email: 'f@f.com'});
});
it('should support dynamic default parameters (action specific)', function() {
var currentGroup = 'students',
Person = $resource('/Person/:group/:id', {}, {
fetch: {method: 'GET', params: {group: function() { return currentGroup; }}}
});
$httpBackend.expect('GET', '/Person/students/fedor').respond({id: 'fedor', email: 'f@f.com'});
var fedor = Person.fetch({id: 'fedor'});
$httpBackend.flush();
expect(fedor).toEqualData({id: 'fedor', email: 'f@f.com'});
});
it('should exercise full stack', function() {
var Person = $resource('/Person/:id');
@@ -452,26 +407,4 @@ describe("resource", function() {
expect(callback).not.toHaveBeenCalled();
});
});
it('should transform request/response', function() {
var Person = $resource('/Person/:id', {}, {
save: {
method: 'POST',
params: {id: '@id'},
transformRequest: function(data) {
return angular.toJson({ __id: data.id });
},
transformResponse: function(data) {
return { id: data.__id };
}
}
});
$httpBackend.expect('POST', '/Person/123', { __id: 123 }).respond({ __id: 456 });
var person = new Person({id:123});
person.$save();
$httpBackend.flush();
expect(person.id).toEqual(456);
});
});
-7
View File
@@ -24,11 +24,4 @@ describe('linky', function() {
expect(linky("send email to me@example.com, but")).
toEqual('send email to <a href="mailto:me@example.com">me@example.com</a>, but');
});
it('should handle target:', function() {
expect(linky("http://example.com", "_blank")).
toEqual('<a target="_blank" href="http://example.com">http://example.com</a>')
expect(linky("http://example.com", "someNamedIFrame")).
toEqual('<a target="someNamedIFrame" href="http://example.com">http://example.com</a>')
});
});
+2 -3
View File
@@ -188,7 +188,7 @@ describe('HTML', function() {
expect(html).toEqual('<div>');
});
describe('explicitly disallow', function() {
describe('explicitly dissallow', function() {
it('should not allow attributes', function() {
writer.start('div', {id:'a', name:'a', style:'a'});
expect(html).toEqual('<div>');
@@ -230,11 +230,10 @@ describe('HTML', function() {
expect(isUri('https://abc')).toBeTruthy();
expect(isUri('ftp://abc')).toBeTruthy();
expect(isUri('mailto:me@example.com')).toBeTruthy();
expect(isUri('tel:123-123-1234')).toBeTruthy();
expect(isUri('#anchor')).toBeTruthy();
});
it('should not be URI', function() {
it('should not be UIR', function() {
expect(isUri('')).toBeFalsy();
expect(isUri('javascript:alert')).toBeFalsy();
});
-62
View File
@@ -270,16 +270,6 @@ describe("angular.scenario.dsl", function() {
expect($root.futureError).toMatch(/did not match/);
});
it('should fail to select an option that does not exist', function(){
doc.append(
'<select ng-model="test">' +
' <option value=A>one</option>' +
' <option value=B selected>two</option>' +
'</select>'
);
$root.dsl.select('test').option('three');
expect($root.futureError).toMatch(/not found/);
});
});
describe('Element', function() {
@@ -315,58 +305,6 @@ describe("angular.scenario.dsl", function() {
dealoc(elm);
});
it('should execute dblclick', function() {
var clicked;
// Hash is important, otherwise we actually
// go to a different page and break the runner
doc.append('<a href="#"></a>');
doc.find('a').dblclick(function() {
clicked = true;
});
$root.dsl.element('a').dblclick();
});
it('should navigate page if dblclick on anchor', function() {
expect($window.location).not.toEqual('#foo');
doc.append('<a href="#foo"></a>');
$root.dsl.element('a').dblclick();
expect($window.location).toMatch(/#foo$/);
});
it('should not navigate if dblclick event was cancelled', function() {
var initLocation = $window.location,
elm = jqLite('<a href="#foo"></a>');
doc.append(elm);
elm.bind('dblclick', function(event) {
event.preventDefault();
});
$root.dsl.element('a').dblclick();
expect($window.location).toBe(initLocation);
dealoc(elm);
});
it('should execute mouseover', function() {
var mousedOver;
doc.append('<div></div>');
doc.find('div').mouseover(function() {
mousedOver = true;
});
$root.dsl.element('div').mouseover();
expect(mousedOver).toBe(true);
});
it('should bubble up the mouseover event', function() {
var mousedOver;
doc.append('<div id="outer"><div id="inner"></div></div>');
doc.find('#outer').mouseover(function() {
mousedOver = true;
});
$root.dsl.element('#inner').mouseover();
expect(mousedOver).toBe(true);
});
it('should count matching elements', function() {
doc.append('<span></span><span></span>');
$root.dsl.element('span').count();
+2 -2
View File
@@ -13,7 +13,7 @@ var util = require('util');
var MAX_LENGTH = 70;
var PATTERN = /^(?:fixup!\s*)?(\w*)(\(([\w\$\.\-\*/]*)\))?\: (.*)$/;
var PATTERN = /^(\w*)(\(([\w\$\.\-\*/]*)\))?\: (.*)$/;
var IGNORED = /^WIP\:/;
var TYPES = {
feat: true,
@@ -51,7 +51,7 @@ var validateMessage = function(message) {
var match = PATTERN.exec(message);
if (!match) {
error('does not match "<type>(<scope>): <subject>" ! was: ' + message);
error('does not match "<type>(<scope>): <subject>" !');
return false;
}
+1 -2
View File
@@ -22,7 +22,6 @@ describe('validate-commit-msg.js', function() {
describe('validateMessage', function() {
it('should be valid', function() {
expect(m.validateMessage('fixup! fix($compile): something')).toBe(VALID);
expect(m.validateMessage('fix($compile): something')).toBe(VALID);
expect(m.validateMessage('feat($location): something')).toBe(VALID);
expect(m.validateMessage('docs($filter): something')).toBe(VALID);
@@ -51,7 +50,7 @@ describe('validate-commit-msg.js', function() {
var msg = 'not correct format';
expect(m.validateMessage(msg)).toBe(INVALID);
expect(errors).toEqual(['INVALID COMMIT MSG: does not match "<type>(<scope>): <subject>" ! was: not correct format']);
expect(errors).toEqual(['INVALID COMMIT MSG: does not match "<type>(<scope>): <subject>" !']);
});
+2 -2
View File
@@ -1,5 +1,5 @@
# AngularJS build config file
---
version: 1.1.2
codename: tofu-animation
version: 1.0.4
codename: bewildering-hair
stable: 1.0.3