Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b879223cf3 | |||
| bba6004147 | |||
| d386b7ae4b | |||
| ebc5a477db | |||
| 21c935a303 | |||
| 7e5ef766da | |||
| 1cb96303e9 | |||
| d2058d92bd | |||
| 053f4e26ae | |||
| 45ca45a29a | |||
| e2bf5726ab | |||
| bf706f2f52 | |||
| d2fe381ea8 | |||
| 63c83ffa43 | |||
| 7fa13c3da2 | |||
| 4b91042559 | |||
| a9ecde1e33 | |||
| ada25a9266 | |||
| 0f956b2893 | |||
| 17eb3d717f | |||
| c9ccc801b9 | |||
| 420490aa1b | |||
| 2a65c3deb7 | |||
| ef0c333776 | |||
| bce1d8ecad | |||
| 5a1bc6eb32 | |||
| 1f7a0b2b72 | |||
| a665550933 | |||
| d434f3db53 | |||
| 7e08975b67 | |||
| 82c481bb23 | |||
| b1f46bb1b2 | |||
| 3a6bf0d5bc | |||
| e201f9040f | |||
| 40e9bcd1b4 | |||
| f98e038418 | |||
| ec98c94ccb | |||
| f13055a0a5 | |||
| 623ce1ad2c | |||
| 34cf141838 | |||
| 274e93537e |
+17
-21
@@ -1,6 +1,7 @@
|
||||
language: node_js
|
||||
sudo: false
|
||||
node_js:
|
||||
- '0.10'
|
||||
- '4.2'
|
||||
|
||||
cache:
|
||||
directories:
|
||||
@@ -14,28 +15,26 @@ branches:
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- JOB=ci-checks
|
||||
- JOB=unit BROWSER_PROVIDER=saucelabs
|
||||
- JOB=docs-e2e BROWSER_PROVIDER=saucelabs
|
||||
- JOB=e2e TEST_TARGET=jqlite BROWSER_PROVIDER=saucelabs
|
||||
- JOB=e2e TEST_TARGET=jquery BROWSER_PROVIDER=saucelabs
|
||||
- JOB=unit BROWSER_PROVIDER=browserstack
|
||||
- JOB=docs-e2e BROWSER_PROVIDER=browserstack
|
||||
- JOB=e2e TEST_TARGET=jqlite BROWSER_PROVIDER=browserstack
|
||||
- JOB=e2e TEST_TARGET=jquery BROWSER_PROVIDER=browserstack
|
||||
global:
|
||||
- CXX=g++-4.8 # node 4 likes the G++ v4.8 compiler
|
||||
- SAUCE_USERNAME=angular-ci
|
||||
- SAUCE_ACCESS_KEY=9b988f434ff8-fbca-8aa4-4ae3-35442987
|
||||
- BROWSER_STACK_USERNAME=VojtaJina
|
||||
- BROWSER_STACK_ACCESS_KEY=QCQJ1ZpWXpBkSwEdD8ev
|
||||
- LOGS_DIR=/tmp/angular-build/logs
|
||||
- BROWSER_PROVIDER_READY_FILE=/tmp/browsersprovider-tunnel-ready
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- env: "JOB=unit BROWSER_PROVIDER=browserstack"
|
||||
- env: "JOB=docs-e2e BROWSER_PROVIDER=browserstack"
|
||||
- env: "JOB=e2e TEST_TARGET=jqlite BROWSER_PROVIDER=browserstack"
|
||||
- env: "JOB=e2e TEST_TARGET=jquery BROWSER_PROVIDER=browserstack"
|
||||
# node 4 likes the G++ v4.8 compiler
|
||||
# see https://docs.travis-ci.com/user/languages/javascript-with-nodejs#Node.js-v4-(or-io.js-v3)-compiler-requirements
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-4.8
|
||||
|
||||
install:
|
||||
# Check the size of caches
|
||||
@@ -45,21 +44,18 @@ install:
|
||||
- npm config set spin false
|
||||
# Log HTTP requests
|
||||
- npm config set loglevel http
|
||||
- npm install -g npm@2.5
|
||||
# Instal npm dependecies and ensure that npm cache is not stale
|
||||
- scripts/npm/install-dependencies.sh
|
||||
#- npm install -g npm@2.5
|
||||
# Install npm dependencies and ensure that npm cache is not stale
|
||||
- npm install
|
||||
|
||||
before_script:
|
||||
- mkdir -p $LOGS_DIR
|
||||
- ./scripts/travis/start_browser_provider.sh
|
||||
- npm install -g grunt-cli
|
||||
- grunt package
|
||||
- ./scripts/travis/wait_for_browser_provider.sh
|
||||
- ./scripts/travis/before_build.sh
|
||||
|
||||
script:
|
||||
- ./scripts/travis/build.sh
|
||||
|
||||
after_script:
|
||||
- ./scripts/travis/tear_down_browser_provider.sh
|
||||
- ./scripts/travis/print_logs.sh
|
||||
|
||||
notifications:
|
||||
|
||||
+116
@@ -1,3 +1,119 @@
|
||||
<a name="1.3.20"></a>
|
||||
# 1.3.20 shallow-translucence (2015-09-29)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$parse:** do not convert to string computed properties multiple times
|
||||
([d434f3db](https://github.com/angular/angular.js/commit/d434f3db53d6209eb140b904e83bbde401686c16))
|
||||
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
|
||||
<a name="1.3.19"></a>
|
||||
# 1.3.19 glutinous-shriek (2015-09-15)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$http:** propagate status -1 for timed out requests
|
||||
([f13055a0](https://github.com/angular/angular.js/commit/f13055a0a53a39b160448713a5617edee6042801),
|
||||
[#4491](https://github.com/angular/angular.js/issues/4491), [#8756](https://github.com/angular/angular.js/issues/8756))
|
||||
- **$location:** don't crash if navigating outside the app base
|
||||
([623ce1ad](https://github.com/angular/angular.js/commit/623ce1ad2cf68024719c5cae5d682d00195df30c),
|
||||
[#11667](https://github.com/angular/angular.js/issues/11667))
|
||||
- **$parse:** throw error when accessing a restricted property indirectly
|
||||
([ec98c94c](https://github.com/angular/angular.js/commit/ec98c94ccbfc97b655447956738d5f6ff98b2f33),
|
||||
[#12833](https://github.com/angular/angular.js/issues/12833))
|
||||
- **ngModel:** validate pattern against the viewValue
|
||||
([274e9353](https://github.com/angular/angular.js/commit/274e93537ed4e95aefeacea48909eb334894f0ac),
|
||||
[#12344](https://github.com/angular/angular.js/issues/12344))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **ngAnimate:** introduce `$animate.flush` for unit testing
|
||||
([f98e0384](https://github.com/angular/angular.js/commit/f98e038418f7367b2373adcf4887f64a8e8bdcb0))
|
||||
|
||||
|
||||
## Possible Breaking Changes
|
||||
|
||||
- **ngModel:** due to [274e9353](https://github.com/angular/angular.js/commit/274e93537ed4e95aefeacea48909eb334894f0ac),
|
||||
|
||||
|
||||
The `ngPattern` and `pattern` directives will validate the regex
|
||||
against the `viewValue` of `ngModel`, i.e. the value of the model
|
||||
before the $parsers are applied. Previously, the modelValue
|
||||
(the result of the $parsers) was validated.
|
||||
|
||||
This fixes issues where `input[date]` and `input[number]` cannot
|
||||
be validated because the viewValue string is parsed into
|
||||
`Date` and `Number` respectively (starting with Angular 1.3).
|
||||
It also brings the directives in line with HTML5 constraint
|
||||
validation, which validates against the input value.
|
||||
|
||||
This change is unlikely to cause applications to fail, because even
|
||||
in Angular 1.2, the value that was validated by pattern could have
|
||||
been manipulated by the $parsers, as all validation was done
|
||||
inside this pipeline.
|
||||
|
||||
If you rely on the pattern being validated against the modelValue,
|
||||
you must create your own validator directive that overwrites
|
||||
the built-in pattern validator:
|
||||
|
||||
```
|
||||
.directive('patternModelOverwrite', function patternModelOverwriteDirective() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
require: '?ngModel',
|
||||
priority: 1,
|
||||
compile: function() {
|
||||
var regexp, patternExp;
|
||||
|
||||
return {
|
||||
pre: function(scope, elm, attr, ctrl) {
|
||||
if (!ctrl) return;
|
||||
|
||||
attr.$observe('pattern', function(regex) {
|
||||
/**
|
||||
* The built-in directive will call our overwritten validator
|
||||
* (see below). We just need to update the regex.
|
||||
* The preLink fn guaranetees our observer is called first.
|
||||
*/
|
||||
if (isString(regex) && regex.length > 0) {
|
||||
regex = new RegExp('^' + regex + '$');
|
||||
}
|
||||
|
||||
if (regex && !regex.test) {
|
||||
//The built-in validator will throw at this point
|
||||
return;
|
||||
}
|
||||
|
||||
regexp = regex || undefined;
|
||||
});
|
||||
|
||||
},
|
||||
post: function(scope, elm, attr, ctrl) {
|
||||
if (!ctrl) return;
|
||||
|
||||
regexp, patternExp = attr.ngPattern || attr.pattern;
|
||||
|
||||
//The postLink fn guarantees we overwrite the built-in pattern validator
|
||||
ctrl.$validators.pattern = function(value) {
|
||||
return ctrl.$isEmpty(value) ||
|
||||
isUndefined(regexp) ||
|
||||
regexp.test(value);
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="1.3.18"></a>
|
||||
# 1.3.18 collective-penmanship (2015-08-18)
|
||||
|
||||
|
||||
+14
-12
@@ -155,7 +155,7 @@ module.exports = function(grunt) {
|
||||
jscs: {
|
||||
src: ['src/**/*.js', 'test/**/*.js'],
|
||||
options: {
|
||||
config: ".jscsrc"
|
||||
config: '.jscsrc'
|
||||
}
|
||||
},
|
||||
|
||||
@@ -220,9 +220,9 @@ module.exports = function(grunt) {
|
||||
dest: 'build/angular-aria.js',
|
||||
src: util.wrap(files['angularModules']['ngAria'], 'module')
|
||||
},
|
||||
"promises-aplus-adapter": {
|
||||
'promises-aplus-adapter': {
|
||||
dest:'tmp/promises-aplus-adapter++.js',
|
||||
src:['src/ng/q.js','lib/promises-aplus/promises-aplus-test-adapter.js']
|
||||
src:['src/ng/q.js', 'lib/promises-aplus/promises-aplus-test-adapter.js']
|
||||
}
|
||||
},
|
||||
|
||||
@@ -241,7 +241,7 @@ module.exports = function(grunt) {
|
||||
},
|
||||
|
||||
|
||||
"ddescribe-iit": {
|
||||
'ddescribe-iit': {
|
||||
files: [
|
||||
'src/**/*.js',
|
||||
'test/**/*.js',
|
||||
@@ -262,7 +262,7 @@ module.exports = function(grunt) {
|
||||
}
|
||||
},
|
||||
|
||||
"merge-conflict": {
|
||||
'merge-conflict': {
|
||||
files: [
|
||||
'src/**/*',
|
||||
'test/**/*',
|
||||
@@ -292,11 +292,11 @@ module.exports = function(grunt) {
|
||||
},
|
||||
|
||||
shell: {
|
||||
"npm-install": {
|
||||
command: path.normalize('scripts/npm/install-dependencies.sh')
|
||||
'npm-install': {
|
||||
command: 'node scripts/npm/check-node-modules.js'
|
||||
},
|
||||
|
||||
"promises-aplus-tests": {
|
||||
'promises-aplus-tests': {
|
||||
options: {
|
||||
stdout: false,
|
||||
stderr: true,
|
||||
@@ -327,8 +327,10 @@ module.exports = function(grunt) {
|
||||
grunt.task.run('shell:npm-install');
|
||||
}
|
||||
|
||||
|
||||
|
||||
//alias tasks
|
||||
grunt.registerTask('test', 'Run unit, docs and e2e tests with Karma', ['jshint', 'jscs', 'package','test:unit','test:promises-aplus', 'tests:docs', 'test:protractor']);
|
||||
grunt.registerTask('test', 'Run unit, docs and e2e tests with Karma', ['jshint', 'jscs', 'package', 'test:unit', 'test:promises-aplus', 'tests:docs', 'test:protractor']);
|
||||
grunt.registerTask('test:jqlite', 'Run the unit tests with Karma' , ['tests:jqlite']);
|
||||
grunt.registerTask('test:jquery', 'Run the jQuery unit tests with Karma', ['tests:jquery']);
|
||||
grunt.registerTask('test:modules', 'Run the Karma module tests with Karma', ['build', 'tests:modules']);
|
||||
@@ -338,11 +340,11 @@ module.exports = function(grunt) {
|
||||
grunt.registerTask('test:travis-protractor', 'Run the end to end tests with Protractor for Travis CI builds', ['connect:testserver', 'protractor:travis']);
|
||||
grunt.registerTask('test:ci-protractor', 'Run the end to end tests with Protractor for Jenkins CI builds', ['webdriver', 'connect:testserver', 'protractor:jenkins']);
|
||||
grunt.registerTask('test:e2e', 'Alias for test:protractor', ['test:protractor']);
|
||||
grunt.registerTask('test:promises-aplus',['build:promises-aplus-adapter','shell:promises-aplus-tests']);
|
||||
grunt.registerTask('test:promises-aplus',['build:promises-aplus-adapter', 'shell:promises-aplus-tests']);
|
||||
|
||||
grunt.registerTask('minify', ['bower','clean', 'build', 'minall']);
|
||||
grunt.registerTask('minify', ['bower', 'clean', 'build', 'minall']);
|
||||
grunt.registerTask('webserver', ['connect:devserver']);
|
||||
grunt.registerTask('package', ['bower','clean', 'buildall', 'minall', 'collect-errors', 'docs', 'copy', 'write', 'compress']);
|
||||
grunt.registerTask('package', ['bower', 'validate-angular-files', 'clean', 'buildall', 'minall', 'collect-errors', 'docs', 'copy', 'write', 'compress']);
|
||||
grunt.registerTask('ci-checks', ['ddescribe-iit', 'merge-conflict', 'jshint', 'jscs']);
|
||||
grunt.registerTask('default', ['package']);
|
||||
};
|
||||
|
||||
Vendored
+2
-1
@@ -32,6 +32,7 @@ var angularFiles = {
|
||||
'src/ng/q.js',
|
||||
'src/ng/raf.js',
|
||||
'src/ng/rootScope.js',
|
||||
'src/ng/rootElement.js',
|
||||
'src/ng/sanitizeUri.js',
|
||||
'src/ng/sce.js',
|
||||
'src/ng/sniffer.js',
|
||||
@@ -78,7 +79,7 @@ var angularFiles = {
|
||||
],
|
||||
|
||||
'angularLoader': [
|
||||
'stringify.js',
|
||||
'src/stringify.js',
|
||||
'src/minErr.js',
|
||||
'src/loader.js'
|
||||
],
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $compile:baddir
|
||||
@fullName Invalid Directive Name
|
||||
@description
|
||||
|
||||
This error occurs when the name of a directive is not valid.
|
||||
|
||||
Directives must start with a lowercase character.
|
||||
@@ -0,0 +1,7 @@
|
||||
@ngdoc error
|
||||
@name ng:cpta
|
||||
@fullName Copying TypedArray
|
||||
@description
|
||||
|
||||
Copying TypedArray's with a destination is not supported because TypedArray
|
||||
objects can not be mutated, they are fixed length.
|
||||
@@ -0,0 +1,28 @@
|
||||
@ngdoc error
|
||||
@name ngModel:nopromise
|
||||
@fullName No promise
|
||||
@description
|
||||
|
||||
The return value of an async validator, must always be a promise. If you want to return a
|
||||
non-promise value, you can convert it to a promise using {@link ng.$q#resolve `$q.resolve()`} or
|
||||
{@link ng.$q#reject `$q.reject()`}.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
.directive('asyncValidator', function($q) {
|
||||
return {
|
||||
require: 'ngModel',
|
||||
link: function(scope, elem, attrs, ngModel) {
|
||||
ngModel.$asyncValidators.myAsyncValidation = function(modelValue, viewValue) {
|
||||
if (/* I don't need to hit the backend API */) {
|
||||
return $q.resolve(); // to mark as valid or
|
||||
// return $q.reject(); // to mark as invalid
|
||||
} else {
|
||||
// ...send a request to the backend and return a promise
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
})
|
||||
```
|
||||
@@ -173,7 +173,7 @@ function request(method, url, options, response) {
|
||||
res.on('error', function (e) { console.log(e); });
|
||||
break;
|
||||
case 401:
|
||||
console.log('Eror: Login credentials expired! Please login.');
|
||||
console.log('Error: Login credentials expired! Please login.');
|
||||
break;
|
||||
default:
|
||||
data = [];
|
||||
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e -o pipefail
|
||||
|
||||
|
||||
echo "Shutting down Browserstack tunnel"
|
||||
echo "TODO: implement me"
|
||||
exit 1
|
||||
@@ -0,0 +1,58 @@
|
||||
'use strict';
|
||||
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var glob = require("glob");
|
||||
var _ = require('lodash');
|
||||
var files = require('../../angularFiles').files;
|
||||
|
||||
module.exports = function(grunt) {
|
||||
|
||||
grunt.registerTask('validate-angular-files', function() {
|
||||
var combinedFiles = _.clone(files.angularModules);
|
||||
combinedFiles.ng = files.angularSrc;
|
||||
combinedFiles.angularLoader = files.angularLoader;
|
||||
|
||||
var errorsDetected = false;
|
||||
var directories = [];
|
||||
var detectedFiles = {};
|
||||
|
||||
for (var section in combinedFiles) {
|
||||
var sectionFiles = combinedFiles[section];
|
||||
|
||||
if (section != 'angularLoader') {
|
||||
directories.push('src/' + section);
|
||||
}
|
||||
|
||||
grunt.log.debug('Validating ' + sectionFiles.length + ' files from the "' + section + '" module.');
|
||||
|
||||
sectionFiles.forEach(function(file) {
|
||||
detectedFiles[file] = true;
|
||||
|
||||
if (!fs.existsSync(file)) {
|
||||
grunt.log.error(file + ' does not exist in the local file structure.');
|
||||
errorsDetected = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
directories.forEach(function(directory) {
|
||||
glob.sync(directory + '/**/*').forEach(function(filePath) {
|
||||
if (!fs.lstatSync(filePath).isDirectory()) {
|
||||
var fileName = path.basename(filePath);
|
||||
var isHiddenFile = fileName[0] == '.';
|
||||
if (!isHiddenFile && !detectedFiles[filePath]) {
|
||||
grunt.log.error(filePath + ' exists in the local file structure but isn\'t used by any module.');
|
||||
errorsDetected = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (errorsDetected) {
|
||||
throw new Error('Not all files were properly detected in the local file structure.');
|
||||
} else {
|
||||
grunt.log.ok('All files were detected successfully!');
|
||||
}
|
||||
});
|
||||
};
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e -o pipefail
|
||||
|
||||
|
||||
echo "Shutting down Sauce Connect tunnel"
|
||||
|
||||
killall sc
|
||||
|
||||
while [[ -n `ps -ef | grep "sauce-connect-" | grep -v "grep"` ]]; do
|
||||
printf "."
|
||||
sleep .5
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Sauce Connect tunnel has been shut down"
|
||||
+240
-74
@@ -207,7 +207,7 @@
|
||||
"dependencies": {
|
||||
"traceur": {
|
||||
"version": "0.0.33",
|
||||
"resolved": "git+https://github.com/vojtajina/traceur-compiler#d90b1e34c799bf61cd1aafdc33db0a554fa9e617",
|
||||
"resolved": "git+https://github.com/vojtajina/traceur-compiler.git#d90b1e34c799bf61cd1aafdc33db0a554fa9e617",
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "2.7.1",
|
||||
@@ -2580,14 +2580,6 @@
|
||||
},
|
||||
"async-each": {
|
||||
"version": "0.1.6"
|
||||
},
|
||||
"fsevents": {
|
||||
"version": "0.3.6",
|
||||
"dependencies": {
|
||||
"nan": {
|
||||
"version": "1.8.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2740,6 +2732,49 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"glob": {
|
||||
"version": "6.0.1",
|
||||
"dependencies": {
|
||||
"inflight": {
|
||||
"version": "1.0.4",
|
||||
"dependencies": {
|
||||
"wrappy": {
|
||||
"version": "1.0.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.1"
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.0",
|
||||
"dependencies": {
|
||||
"brace-expansion": {
|
||||
"version": "1.1.2",
|
||||
"dependencies": {
|
||||
"balanced-match": {
|
||||
"version": "0.3.0"
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"once": {
|
||||
"version": "1.3.3",
|
||||
"dependencies": {
|
||||
"wrappy": {
|
||||
"version": "1.0.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"grunt": {
|
||||
"version": "0.4.5",
|
||||
"dependencies": {
|
||||
@@ -5470,14 +5505,6 @@
|
||||
},
|
||||
"async-each": {
|
||||
"version": "0.1.6"
|
||||
},
|
||||
"fsevents": {
|
||||
"version": "0.3.5",
|
||||
"dependencies": {
|
||||
"nan": {
|
||||
"version": "1.5.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -6505,37 +6532,45 @@
|
||||
}
|
||||
},
|
||||
"protractor": {
|
||||
"version": "2.0.0",
|
||||
"version": "2.5.1",
|
||||
"dependencies": {
|
||||
"request": {
|
||||
"version": "2.36.0",
|
||||
"version": "2.57.0",
|
||||
"dependencies": {
|
||||
"qs": {
|
||||
"version": "0.6.6"
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.0"
|
||||
},
|
||||
"mime": {
|
||||
"version": "1.2.11"
|
||||
},
|
||||
"forever-agent": {
|
||||
"version": "0.5.2"
|
||||
},
|
||||
"node-uuid": {
|
||||
"version": "1.4.3"
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "0.12.1",
|
||||
"bl": {
|
||||
"version": "0.9.4",
|
||||
"dependencies": {
|
||||
"punycode": {
|
||||
"version": "1.3.2"
|
||||
"readable-stream": {
|
||||
"version": "1.0.33",
|
||||
"dependencies": {
|
||||
"core-util-is": {
|
||||
"version": "1.0.2"
|
||||
},
|
||||
"isarray": {
|
||||
"version": "0.0.1"
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "0.10.31"
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"caseless": {
|
||||
"version": "0.10.0"
|
||||
},
|
||||
"forever-agent": {
|
||||
"version": "0.6.1"
|
||||
},
|
||||
"form-data": {
|
||||
"version": "0.1.4",
|
||||
"version": "0.2.0",
|
||||
"dependencies": {
|
||||
"async": {
|
||||
"version": "0.9.2"
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "0.0.7",
|
||||
"dependencies": {
|
||||
@@ -6543,17 +6578,34 @@
|
||||
"version": "0.0.5"
|
||||
}
|
||||
}
|
||||
},
|
||||
"async": {
|
||||
"version": "0.9.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.1"
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.0.14",
|
||||
"dependencies": {
|
||||
"mime-db": {
|
||||
"version": "1.12.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"node-uuid": {
|
||||
"version": "1.4.7"
|
||||
},
|
||||
"qs": {
|
||||
"version": "3.1.0"
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.4.0"
|
||||
"version": "0.4.2"
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.2.1"
|
||||
},
|
||||
"http-signature": {
|
||||
"version": "0.10.1",
|
||||
"version": "0.11.0",
|
||||
"dependencies": {
|
||||
"assert-plus": {
|
||||
"version": "0.1.5"
|
||||
@@ -6567,38 +6619,120 @@
|
||||
}
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.3.0"
|
||||
"version": "0.8.0"
|
||||
},
|
||||
"hawk": {
|
||||
"version": "1.0.0",
|
||||
"version": "2.3.1",
|
||||
"dependencies": {
|
||||
"hoek": {
|
||||
"version": "0.9.1"
|
||||
"version": "2.16.3"
|
||||
},
|
||||
"boom": {
|
||||
"version": "0.4.2"
|
||||
"version": "2.10.1"
|
||||
},
|
||||
"cryptiles": {
|
||||
"version": "0.2.2"
|
||||
"version": "2.0.5"
|
||||
},
|
||||
"sntp": {
|
||||
"version": "0.2.4"
|
||||
"version": "1.0.9"
|
||||
}
|
||||
}
|
||||
},
|
||||
"aws-sign2": {
|
||||
"version": "0.5.0"
|
||||
},
|
||||
"stringstream": {
|
||||
"version": "0.0.5"
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.5",
|
||||
"dependencies": {
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"isstream": {
|
||||
"version": "0.1.2"
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "1.8.0",
|
||||
"dependencies": {
|
||||
"bluebird": {
|
||||
"version": "2.10.2"
|
||||
},
|
||||
"chalk": {
|
||||
"version": "1.1.1",
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "2.1.0"
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.3"
|
||||
},
|
||||
"has-ansi": {
|
||||
"version": "2.0.0",
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "2.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.0",
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "2.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "2.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.9.0",
|
||||
"dependencies": {
|
||||
"graceful-readlink": {
|
||||
"version": "1.0.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"is-my-json-valid": {
|
||||
"version": "2.12.3",
|
||||
"dependencies": {
|
||||
"generate-function": {
|
||||
"version": "2.0.0"
|
||||
},
|
||||
"generate-object-property": {
|
||||
"version": "1.2.0",
|
||||
"dependencies": {
|
||||
"is-property": {
|
||||
"version": "1.0.2"
|
||||
}
|
||||
}
|
||||
},
|
||||
"jsonpointer": {
|
||||
"version": "2.0.0"
|
||||
},
|
||||
"xtend": {
|
||||
"version": "4.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"selenium-webdriver": {
|
||||
"version": "2.45.1",
|
||||
"version": "2.47.0",
|
||||
"dependencies": {
|
||||
"rimraf": {
|
||||
"version": "2.3.2",
|
||||
"version": "2.4.4",
|
||||
"dependencies": {
|
||||
"glob": {
|
||||
"version": "4.5.3",
|
||||
"version": "5.0.15",
|
||||
"dependencies": {
|
||||
"inflight": {
|
||||
"version": "1.0.4",
|
||||
@@ -6612,13 +6746,13 @@
|
||||
"version": "2.0.1"
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "2.0.4",
|
||||
"version": "3.0.0",
|
||||
"dependencies": {
|
||||
"brace-expansion": {
|
||||
"version": "1.1.0",
|
||||
"version": "1.1.2",
|
||||
"dependencies": {
|
||||
"balanced-match": {
|
||||
"version": "0.2.0"
|
||||
"version": "0.3.0"
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1"
|
||||
@@ -6628,12 +6762,15 @@
|
||||
}
|
||||
},
|
||||
"once": {
|
||||
"version": "1.3.1",
|
||||
"version": "1.3.3",
|
||||
"dependencies": {
|
||||
"wrappy": {
|
||||
"version": "1.0.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6643,33 +6780,33 @@
|
||||
"version": "0.0.24"
|
||||
},
|
||||
"ws": {
|
||||
"version": "0.7.1",
|
||||
"version": "0.8.1",
|
||||
"dependencies": {
|
||||
"options": {
|
||||
"version": "0.0.6"
|
||||
},
|
||||
"ultron": {
|
||||
"version": "1.0.1"
|
||||
"version": "1.0.2"
|
||||
},
|
||||
"bufferutil": {
|
||||
"version": "1.0.1",
|
||||
"version": "1.2.1",
|
||||
"dependencies": {
|
||||
"bindings": {
|
||||
"version": "1.2.1"
|
||||
},
|
||||
"nan": {
|
||||
"version": "1.6.2"
|
||||
"version": "2.1.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"version": "1.0.1",
|
||||
"version": "1.2.1",
|
||||
"dependencies": {
|
||||
"bindings": {
|
||||
"version": "1.2.1"
|
||||
},
|
||||
"nan": {
|
||||
"version": "1.6.2"
|
||||
"version": "2.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6682,10 +6819,10 @@
|
||||
"version": "0.6.1"
|
||||
},
|
||||
"xmlbuilder": {
|
||||
"version": "2.6.2",
|
||||
"version": "4.2.0",
|
||||
"dependencies": {
|
||||
"lodash": {
|
||||
"version": "3.5.0"
|
||||
"version": "3.10.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6700,18 +6837,47 @@
|
||||
"version": "1.1.0"
|
||||
},
|
||||
"jasminewd2": {
|
||||
"version": "0.0.3"
|
||||
"version": "0.0.6"
|
||||
},
|
||||
"jasmine": {
|
||||
"version": "2.1.1",
|
||||
"version": "2.3.2",
|
||||
"dependencies": {
|
||||
"exit": {
|
||||
"version": "0.1.2"
|
||||
},
|
||||
"jasmine-core": {
|
||||
"version": "2.1.3"
|
||||
"version": "2.3.4"
|
||||
}
|
||||
}
|
||||
},
|
||||
"saucelabs": {
|
||||
"version": "0.1.1"
|
||||
"version": "1.0.1",
|
||||
"dependencies": {
|
||||
"https-proxy-agent": {
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"agent-base": {
|
||||
"version": "2.0.1",
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "5.0.3"
|
||||
}
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.2.0",
|
||||
"dependencies": {
|
||||
"ms": {
|
||||
"version": "0.7.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"glob": {
|
||||
"version": "3.2.11",
|
||||
@@ -6723,10 +6889,10 @@
|
||||
"version": "0.3.0",
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "2.5.0"
|
||||
"version": "2.7.3"
|
||||
},
|
||||
"sigmund": {
|
||||
"version": "1.0.0"
|
||||
"version": "1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6739,7 +6905,7 @@
|
||||
"version": "0.6.1",
|
||||
"dependencies": {
|
||||
"wordwrap": {
|
||||
"version": "0.0.2"
|
||||
"version": "0.0.3"
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.10"
|
||||
@@ -6756,14 +6922,14 @@
|
||||
"version": "0.1.32",
|
||||
"dependencies": {
|
||||
"amdefine": {
|
||||
"version": "0.1.0"
|
||||
"version": "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"html-entities": {
|
||||
"version": "1.1.2"
|
||||
"version": "1.1.3"
|
||||
},
|
||||
"accessibility-developer-tools": {
|
||||
"version": "2.6.0"
|
||||
|
||||
Generated
+544
-290
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"name": "angularjs",
|
||||
"branchVersion": "1.3.*",
|
||||
"distTag": "previous_1_3",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/angular/angular.js.git"
|
||||
@@ -10,6 +11,10 @@
|
||||
"npm": "~2.5"
|
||||
},
|
||||
"engineStrict": true,
|
||||
"scripts": {
|
||||
"preinstall": "node scripts/npm/check-node-modules.js --purge",
|
||||
"postinstall": "node scripts/npm/copy-npm-shrinkwrap.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"angular-benchpress": "0.x.x",
|
||||
"benchmark": "1.x.x",
|
||||
@@ -20,6 +25,7 @@
|
||||
"dgeni": "^0.4.0",
|
||||
"dgeni-packages": "^0.10.0",
|
||||
"event-stream": "~3.1.0",
|
||||
"glob": "^6.0.1",
|
||||
"grunt": "~0.4.2",
|
||||
"grunt-bump": "~0.0.13",
|
||||
"grunt-contrib-clean": "~0.6.0",
|
||||
|
||||
@@ -29,6 +29,8 @@ function init {
|
||||
angular-touch
|
||||
angular-messages
|
||||
)
|
||||
# get the npm dist-tag from a custom property (distTag) in package.json
|
||||
DIST_TAG=$(readJsonProp "package.json" "distTag")
|
||||
}
|
||||
|
||||
|
||||
@@ -110,19 +112,8 @@ function publish {
|
||||
|
||||
# don't publish every build to npm
|
||||
if [ "${NEW_VERSION/+sha}" = "$NEW_VERSION" ] ; then
|
||||
if [ "${NEW_VERSION/-}" = "$NEW_VERSION" ] ; then
|
||||
if [[ $NEW_VERSION =~ ^1\.2\.[0-9]+$ ]] ; then
|
||||
# publish 1.2.x releases with the appropriate tag
|
||||
# this ensures that `npm install` by default will not grab `1.2.x` releases
|
||||
npm publish --tag=old
|
||||
else
|
||||
# publish releases as "latest"
|
||||
npm publish
|
||||
fi
|
||||
else
|
||||
# publish prerelease builds with the beta tag
|
||||
npm publish --tag=beta
|
||||
fi
|
||||
echo "-- Publishing to npm as $DIST_TAG"
|
||||
npm publish --tag=$DIST_TAG
|
||||
fi
|
||||
|
||||
cd $SCRIPT_DIR
|
||||
|
||||
@@ -7,6 +7,8 @@ echo "#################################"
|
||||
# Enable tracing and exit on first failure
|
||||
set -xe
|
||||
|
||||
scripts/jenkins/set-node-version.sh
|
||||
|
||||
# This is the default set of browsers to use on the CI server unless overridden via env variable
|
||||
if [[ -z "$BROWSERS" ]]
|
||||
then
|
||||
@@ -19,6 +21,7 @@ rm -f angular.js.size
|
||||
|
||||
|
||||
# BUILD #
|
||||
npm install -g grunt-cli
|
||||
npm install --color false
|
||||
grunt ci-checks package --no-color
|
||||
|
||||
@@ -4,9 +4,7 @@ echo "#################################"
|
||||
echo "#### Update master ##############"
|
||||
echo "#################################"
|
||||
|
||||
ARG_DEFS=(
|
||||
"[--no-test=(true|false)]"
|
||||
)
|
||||
ARG_DEFS=()
|
||||
|
||||
function init {
|
||||
if [[ ! $VERBOSE ]]; then
|
||||
@@ -17,14 +15,7 @@ function init {
|
||||
|
||||
function build {
|
||||
cd ../..
|
||||
|
||||
if [[ $NO_TEST == "true" ]]; then
|
||||
npm install --color false
|
||||
grunt ci-checks package --no-color
|
||||
else
|
||||
./jenkins_build.sh
|
||||
fi
|
||||
|
||||
scripts/jenkins/build.sh
|
||||
cd $SCRIPT_DIR
|
||||
}
|
||||
|
||||
|
||||
@@ -35,8 +35,10 @@ function init {
|
||||
}
|
||||
|
||||
function build {
|
||||
./set-node-version.sh
|
||||
cd ../..
|
||||
|
||||
npm install -g grunt-cli
|
||||
npm install --color false
|
||||
grunt ci-checks package --no-color
|
||||
|
||||
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Install nvm for this shell
|
||||
source ~/.nvm/nvm.sh
|
||||
|
||||
# Use node.js at 4.2.x
|
||||
nvm install 4.2
|
||||
@@ -0,0 +1,74 @@
|
||||
// Implementation based on:
|
||||
// https://github.com/angular/angular/blob/3b9c08676a4c921bbfa847802e08566fb601ba7a/tools/npm/check-node-modules.js
|
||||
'use strict';
|
||||
|
||||
// Imports
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
// Constants
|
||||
var PROJECT_ROOT = path.join(__dirname, '../../');
|
||||
var NODE_MODULES_DIR = 'node_modules';
|
||||
var NPM_SHRINKWRAP_FILE = 'npm-shrinkwrap.json';
|
||||
var NPM_SHRINKWRAP_CACHED_FILE = NODE_MODULES_DIR + '/npm-shrinkwrap.cached.json';
|
||||
|
||||
// Run
|
||||
_main();
|
||||
|
||||
// Functions - Definitions
|
||||
function _main() {
|
||||
var purgeIfStale = process.argv.indexOf('--purge') !== -1;
|
||||
|
||||
process.chdir(PROJECT_ROOT);
|
||||
checkNodeModules(purgeIfStale);
|
||||
}
|
||||
|
||||
function checkNodeModules(purgeIfStale) {
|
||||
var nodeModulesOk = compareMarkerFiles(NPM_SHRINKWRAP_FILE, NPM_SHRINKWRAP_CACHED_FILE);
|
||||
|
||||
if (nodeModulesOk) {
|
||||
console.log(':-) npm dependencies are looking good!');
|
||||
} else if (purgeIfStale) {
|
||||
console.log(':-( npm dependencies are stale or in an unknown state!');
|
||||
console.log(' Purging \'' + NODE_MODULES_DIR + '\'...');
|
||||
deleteDirSync(NODE_MODULES_DIR);
|
||||
} else {
|
||||
var separator = new Array(81).join('!');
|
||||
|
||||
console.warn(separator);
|
||||
console.warn(':-( npm dependencies are stale or in an unknown state!');
|
||||
console.warn('You can rebuild the dependencies by running `npm install`.');
|
||||
console.warn(separator);
|
||||
}
|
||||
|
||||
return nodeModulesOk;
|
||||
}
|
||||
|
||||
function compareMarkerFiles(markerFilePath, cachedMarkerFilePath) {
|
||||
if (!fs.existsSync(cachedMarkerFilePath)) return false;
|
||||
|
||||
var opts = {encoding: 'utf-8'};
|
||||
var markerContent = fs.readFileSync(markerFilePath, opts);
|
||||
var cachedMarkerContent = fs.readFileSync(cachedMarkerFilePath, opts);
|
||||
|
||||
return markerContent === cachedMarkerContent;
|
||||
}
|
||||
|
||||
// Custom implementation of `rm -rf` that works consistently across OSes
|
||||
function deleteDirSync(path) {
|
||||
if (fs.existsSync(path)) {
|
||||
fs.readdirSync(path).forEach(deleteDirOrFileSync);
|
||||
fs.rmdirSync(path);
|
||||
}
|
||||
|
||||
// Helpers
|
||||
function deleteDirOrFileSync(subpath) {
|
||||
var curPath = path + '/' + subpath;
|
||||
|
||||
if (fs.lstatSync(curPath).isDirectory()) {
|
||||
deleteDirSync(curPath);
|
||||
} else {
|
||||
fs.unlinkSync(curPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
'use strict';
|
||||
|
||||
// Imports
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
// Constants
|
||||
var PROJECT_ROOT = path.join(__dirname, '../../');
|
||||
var NODE_MODULES_DIR = 'node_modules';
|
||||
var NPM_SHRINKWRAP_FILE = 'npm-shrinkwrap.json';
|
||||
var NPM_SHRINKWRAP_CACHED_FILE = NODE_MODULES_DIR + '/npm-shrinkwrap.cached.json';
|
||||
|
||||
// Run
|
||||
_main();
|
||||
|
||||
// Functions - Definitions
|
||||
function _main() {
|
||||
process.chdir(PROJECT_ROOT);
|
||||
copyFile(NPM_SHRINKWRAP_FILE, NPM_SHRINKWRAP_CACHED_FILE, onCopied);
|
||||
}
|
||||
|
||||
// Implementation based on:
|
||||
// https://stackoverflow.com/questions/11293857/fastest-way-to-copy-file-in-node-js#answer-21995878
|
||||
function copyFile(srcPath, dstPath, callback) {
|
||||
var callbackCalled = false;
|
||||
|
||||
if (!fs.existsSync(srcPath)) {
|
||||
done(new Error('Missing source file: ' + srcPath));
|
||||
return;
|
||||
}
|
||||
|
||||
var rs = fs.createReadStream(srcPath);
|
||||
rs.on('error', done);
|
||||
|
||||
var ws = fs.createWriteStream(dstPath);
|
||||
ws.on('error', done);
|
||||
ws.on('finish', done);
|
||||
|
||||
rs.pipe(ws);
|
||||
|
||||
// Helpers
|
||||
function done(err) {
|
||||
if (callback && !callbackCalled) {
|
||||
callbackCalled = true;
|
||||
callback(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onCopied(err) {
|
||||
if (err) {
|
||||
var separator = new Array(81).join('!');
|
||||
|
||||
console.error(separator);
|
||||
console.error(
|
||||
'Failed to copy `' + NPM_SHRINKWRAP_FILE + '` to `' + NPM_SHRINKWRAP_CACHED_FILE + '`:');
|
||||
console.error(err);
|
||||
console.error(separator);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
SHRINKWRAP_FILE=npm-shrinkwrap.json
|
||||
SHRINKWRAP_CACHED_FILE=node_modules/npm-shrinkwrap.cached.json
|
||||
|
||||
if diff -q $SHRINKWRAP_FILE $SHRINKWRAP_CACHED_FILE; then
|
||||
echo 'No shrinkwrap changes detected. npm install will be skipped...';
|
||||
else
|
||||
echo 'Blowing away node_modules and reinstalling npm dependencies...'
|
||||
rm -rf node_modules
|
||||
npm install
|
||||
cp $SHRINKWRAP_FILE $SHRINKWRAP_CACHED_FILE
|
||||
echo 'npm install successful!'
|
||||
fi
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
mkdir -p $LOGS_DIR
|
||||
|
||||
if [ $JOB != "ci-checks" ]; then
|
||||
echo "start_browser_provider"
|
||||
./scripts/travis/start_browser_provider.sh
|
||||
fi
|
||||
|
||||
npm install -g grunt-cli
|
||||
|
||||
if [ $JOB != "ci-checks" ]; then
|
||||
grunt package
|
||||
echo "wait_for_browser_provider"
|
||||
./scripts/travis/wait_for_browser_provider.sh
|
||||
fi
|
||||
@@ -5,7 +5,9 @@ set -e
|
||||
export BROWSER_STACK_ACCESS_KEY=`echo $BROWSER_STACK_ACCESS_KEY | rev`
|
||||
export SAUCE_ACCESS_KEY=`echo $SAUCE_ACCESS_KEY | rev`
|
||||
|
||||
if [ $JOB = "unit" ]; then
|
||||
if [ $JOB = "ci-checks" ]; then
|
||||
grunt ci-checks
|
||||
elif [ $JOB = "unit" ]; then
|
||||
if [ "$BROWSER_PROVIDER" == "browserstack" ]; then
|
||||
BROWSERS="BS_Chrome,BS_Safari,BS_Firefox,BS_IE_9,BS_IE_10,BS_IE_11,BS_iOS"
|
||||
else
|
||||
@@ -14,7 +16,6 @@ if [ $JOB = "unit" ]; then
|
||||
|
||||
grunt test:promises-aplus
|
||||
grunt test:unit --browsers $BROWSERS --reporters dots
|
||||
grunt ci-checks
|
||||
grunt tests:docs --browsers $BROWSERS --reporters dots
|
||||
elif [ $JOB = "docs-e2e" ]; then
|
||||
grunt test:travis-protractor --specs "docs/app/e2e/**/*.scenario.js"
|
||||
@@ -31,5 +32,5 @@ elif [ $JOB = "e2e" ]; then
|
||||
export TARGET_SPECS="test/e2e/tests/**/*.js,$TARGET_SPECS"
|
||||
grunt test:travis-protractor --specs "$TARGET_SPECS"
|
||||
else
|
||||
echo "Unknown job type. Please set JOB=unit or JOB=e2e-*."
|
||||
echo "Unknown job type. Please set JOB=ci-checks, JOB=unit or JOB=e2e-*."
|
||||
fi
|
||||
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
# Has to be run from project root directory.
|
||||
|
||||
./lib/${BROWSER_PROVIDER}/teardown_tunnel.sh
|
||||
+111
-59
@@ -36,6 +36,7 @@
|
||||
isUndefined: true,
|
||||
isDefined: true,
|
||||
isObject: true,
|
||||
isBlankObject: true,
|
||||
isString: true,
|
||||
isNumber: true,
|
||||
isDate: true,
|
||||
@@ -172,6 +173,7 @@ var
|
||||
splice = [].splice,
|
||||
push = [].push,
|
||||
toString = Object.prototype.toString,
|
||||
getPrototypeOf = Object.getPrototypeOf,
|
||||
ngMinErr = minErr('ng'),
|
||||
|
||||
/** @name angular */
|
||||
@@ -461,6 +463,16 @@ function isObject(value) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if a value is an object with a null prototype
|
||||
*
|
||||
* @returns {boolean} True if `value` is an `Object` with a null prototype
|
||||
*/
|
||||
function isBlankObject(value) {
|
||||
return value !== null && typeof value === 'object' && !getPrototypeOf(value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name angular.isString
|
||||
@@ -597,6 +609,12 @@ function isPromiseLike(obj) {
|
||||
}
|
||||
|
||||
|
||||
var TYPED_ARRAY_REGEXP = /^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array\]$/;
|
||||
function isTypedArray(value) {
|
||||
return value && isNumber(value.length) && TYPED_ARRAY_REGEXP.test(toString.call(value));
|
||||
}
|
||||
|
||||
|
||||
var trim = function(value) {
|
||||
return isString(value) ? value.trim() : value;
|
||||
};
|
||||
@@ -713,77 +731,111 @@ function arrayRemove(array, value) {
|
||||
</file>
|
||||
</example>
|
||||
*/
|
||||
function copy(source, destination, stackSource, stackDest) {
|
||||
if (isWindow(source) || isScope(source)) {
|
||||
throw ngMinErr('cpws',
|
||||
"Can't copy! Making copies of Window or Scope instances is not supported.");
|
||||
function copy(source, destination) {
|
||||
var stackSource = [];
|
||||
var stackDest = [];
|
||||
|
||||
if (destination) {
|
||||
if (isTypedArray(destination)) {
|
||||
throw ngMinErr('cpta', "Can't copy! TypedArray destination cannot be mutated.");
|
||||
}
|
||||
if (source === destination) {
|
||||
throw ngMinErr('cpi', "Can't copy! Source and destination are identical.");
|
||||
}
|
||||
|
||||
// Empty the destination object
|
||||
if (isArray(destination)) {
|
||||
destination.length = 0;
|
||||
} else {
|
||||
forEach(destination, function(value, key) {
|
||||
if (key !== '$$hashKey') {
|
||||
delete destination[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
stackSource.push(source);
|
||||
stackDest.push(destination);
|
||||
return copyRecurse(source, destination);
|
||||
}
|
||||
|
||||
if (!destination) {
|
||||
destination = source;
|
||||
if (source) {
|
||||
if (isArray(source)) {
|
||||
destination = copy(source, [], stackSource, stackDest);
|
||||
} else if (isDate(source)) {
|
||||
destination = new Date(source.getTime());
|
||||
} else if (isRegExp(source)) {
|
||||
destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
|
||||
destination.lastIndex = source.lastIndex;
|
||||
} else if (isObject(source)) {
|
||||
var emptyObject = Object.create(Object.getPrototypeOf(source));
|
||||
destination = copy(source, emptyObject, stackSource, stackDest);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (source === destination) throw ngMinErr('cpi',
|
||||
"Can't copy! Source and destination are identical.");
|
||||
return copyElement(source);
|
||||
|
||||
stackSource = stackSource || [];
|
||||
stackDest = stackDest || [];
|
||||
|
||||
if (isObject(source)) {
|
||||
var index = stackSource.indexOf(source);
|
||||
if (index !== -1) return stackDest[index];
|
||||
|
||||
stackSource.push(source);
|
||||
stackDest.push(destination);
|
||||
}
|
||||
|
||||
var result;
|
||||
function copyRecurse(source, destination) {
|
||||
var h = destination.$$hashKey;
|
||||
var result, key;
|
||||
if (isArray(source)) {
|
||||
destination.length = 0;
|
||||
for (var i = 0; i < source.length; i++) {
|
||||
result = copy(source[i], null, stackSource, stackDest);
|
||||
if (isObject(source[i])) {
|
||||
stackSource.push(source[i]);
|
||||
stackDest.push(result);
|
||||
for (var i = 0, ii = source.length; i < ii; i++) {
|
||||
destination.push(copyElement(source[i]));
|
||||
}
|
||||
} else if (isBlankObject(source)) {
|
||||
// createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
|
||||
for (key in source) {
|
||||
destination[key] = copyElement(source[key]);
|
||||
}
|
||||
} else if (source && typeof source.hasOwnProperty === 'function') {
|
||||
// Slow path, which must rely on hasOwnProperty
|
||||
for (key in source) {
|
||||
if (source.hasOwnProperty(key)) {
|
||||
destination[key] = copyElement(source[key]);
|
||||
}
|
||||
destination.push(result);
|
||||
}
|
||||
} else {
|
||||
var h = destination.$$hashKey;
|
||||
if (isArray(destination)) {
|
||||
destination.length = 0;
|
||||
} else {
|
||||
forEach(destination, function(value, key) {
|
||||
delete destination[key];
|
||||
});
|
||||
}
|
||||
for (var key in source) {
|
||||
if (source.hasOwnProperty(key)) {
|
||||
result = copy(source[key], null, stackSource, stackDest);
|
||||
if (isObject(source[key])) {
|
||||
stackSource.push(source[key]);
|
||||
stackDest.push(result);
|
||||
}
|
||||
destination[key] = result;
|
||||
// Slowest path --- hasOwnProperty can't be called as a method
|
||||
for (key in source) {
|
||||
if (hasOwnProperty.call(source, key)) {
|
||||
destination[key] = copyElement(source[key]);
|
||||
}
|
||||
}
|
||||
setHashKey(destination,h);
|
||||
}
|
||||
setHashKey(destination, h);
|
||||
return destination;
|
||||
}
|
||||
|
||||
function copyElement(source) {
|
||||
// Simple values
|
||||
if (!isObject(source)) {
|
||||
return source;
|
||||
}
|
||||
|
||||
// Already copied values
|
||||
var index = stackSource.indexOf(source);
|
||||
if (index !== -1) {
|
||||
return stackDest[index];
|
||||
}
|
||||
|
||||
if (isWindow(source) || isScope(source)) {
|
||||
throw ngMinErr('cpws',
|
||||
"Can't copy! Making copies of Window or Scope instances is not supported.");
|
||||
}
|
||||
|
||||
var needsRecurse = false;
|
||||
var destination;
|
||||
|
||||
if (isArray(source)) {
|
||||
destination = [];
|
||||
needsRecurse = true;
|
||||
} else if (isTypedArray(source)) {
|
||||
destination = new source.constructor(source);
|
||||
} else if (isDate(source)) {
|
||||
destination = new Date(source.getTime());
|
||||
} else if (isRegExp(source)) {
|
||||
destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
|
||||
destination.lastIndex = source.lastIndex;
|
||||
} else if (isFunction(source.cloneNode)) {
|
||||
destination = source.cloneNode(true);
|
||||
} else {
|
||||
destination = Object.create(getPrototypeOf(source));
|
||||
needsRecurse = true;
|
||||
}
|
||||
|
||||
stackSource.push(source);
|
||||
stackDest.push(destination);
|
||||
|
||||
return needsRecurse
|
||||
? copyRecurse(source, destination)
|
||||
: destination;
|
||||
}
|
||||
return destination;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -757,14 +757,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
return bindings;
|
||||
}
|
||||
|
||||
function assertValidDirectiveName(name) {
|
||||
var letter = name.charAt(0);
|
||||
if (!letter || letter !== lowercase(letter)) {
|
||||
throw $compileMinErr('baddir', "Directive name '{0}' is invalid. The first character must be a lowercase letter", name);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $compileProvider#directive
|
||||
@@ -783,7 +775,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
this.directive = function registerDirective(name, directiveFactory) {
|
||||
assertNotHasOwnProperty(name, 'directive');
|
||||
if (isString(name)) {
|
||||
assertValidDirectiveName(name);
|
||||
assertArg(directiveFactory, 'directiveFactory');
|
||||
if (!hasDirectives.hasOwnProperty(name)) {
|
||||
hasDirectives[name] = [];
|
||||
|
||||
@@ -318,13 +318,9 @@ function FormController(element, attrs, $scope, $animate, $interpolate) {
|
||||
*
|
||||
* In Angular, forms can be nested. This means that the outer form is valid when all of the child
|
||||
* forms are valid as well. However, browsers do not allow nesting of `<form>` elements, so
|
||||
* Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to
|
||||
* `<form>` but can be nested. This allows you to have nested forms, which is very useful when
|
||||
* using Angular validation directives in forms that are dynamically generated using the
|
||||
* {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name`
|
||||
* attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an
|
||||
* `ngForm` directive and nest these in an outer `form` element.
|
||||
*
|
||||
* Angular provides the {@link ng.directive:ngForm `ngForm`} directive, which behaves identically to
|
||||
* `form` but can be nested. Nested forms can be useful, for example, if the validity of a sub-group
|
||||
* of controls needs to be determined.
|
||||
*
|
||||
* # CSS classes
|
||||
* - `ng-valid` is set if the form is valid.
|
||||
|
||||
@@ -1535,13 +1535,16 @@ var inputDirective = ['$browser', '$sniffer', '$filter', '$parse',
|
||||
return {
|
||||
restrict: 'E',
|
||||
require: ['?ngModel'],
|
||||
link: {
|
||||
pre: function(scope, element, attr, ctrls) {
|
||||
if (ctrls[0]) {
|
||||
(inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer,
|
||||
$browser, $filter, $parse);
|
||||
compile: function(tElement, tAttr) {
|
||||
if (lowercase(tAttr.type) === 'hidden') tAttr.$set('autocomplete', 'off');
|
||||
return {
|
||||
pre: function(scope, element, attr, ctrls) {
|
||||
if (ctrls[0]) {
|
||||
(inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer,
|
||||
$browser, $filter, $parse);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}];
|
||||
|
||||
@@ -596,7 +596,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
|
||||
forEach(ctrl.$asyncValidators, function(validator, name) {
|
||||
var promise = validator(modelValue, viewValue);
|
||||
if (!isPromiseLike(promise)) {
|
||||
throw ngModelMinErr("$asyncValidators",
|
||||
throw ngModelMinErr('nopromise',
|
||||
"Expected asynchronous validator to return a promise but got '{0}' instead.", promise);
|
||||
}
|
||||
setValidity(name, undefined);
|
||||
|
||||
@@ -43,8 +43,9 @@ var patternDirective = function() {
|
||||
ctrl.$validate();
|
||||
});
|
||||
|
||||
ctrl.$validators.pattern = function(value) {
|
||||
return ctrl.$isEmpty(value) || isUndefined(regexp) || regexp.test(value);
|
||||
ctrl.$validators.pattern = function(modelValue, viewValue) {
|
||||
// HTML5 pattern constraint validates the input value, so we validate the viewValue
|
||||
return ctrl.$isEmpty(viewValue) || isUndefined(regexp) || regexp.test(viewValue);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
+2
-2
@@ -1110,8 +1110,8 @@ function $HttpProvider() {
|
||||
* Resolves the raw $http promise.
|
||||
*/
|
||||
function resolvePromise(response, status, headers, statusText) {
|
||||
// normalize internal statuses to 0
|
||||
status = Math.max(status, 0);
|
||||
//status: HTTP response status code, 0, -1 (aborted by timeout / promise)
|
||||
status = status >= -1 ? status : 0;
|
||||
|
||||
(isSuccess(status) ? deferred.resolve : deferred.reject)({
|
||||
data: response,
|
||||
|
||||
+16
-8
@@ -89,12 +89,12 @@ function serverBase(url) {
|
||||
*
|
||||
* @constructor
|
||||
* @param {string} appBase application base URL
|
||||
* @param {string} appBaseNoFile application base URL stripped of any filename
|
||||
* @param {string} basePrefix url path prefix
|
||||
*/
|
||||
function LocationHtml5Url(appBase, basePrefix) {
|
||||
function LocationHtml5Url(appBase, appBaseNoFile, basePrefix) {
|
||||
this.$$html5 = true;
|
||||
basePrefix = basePrefix || '';
|
||||
var appBaseNoFile = stripFile(appBase);
|
||||
parseAbsoluteUrl(appBase, this);
|
||||
|
||||
|
||||
@@ -168,10 +168,10 @@ function LocationHtml5Url(appBase, basePrefix) {
|
||||
*
|
||||
* @constructor
|
||||
* @param {string} appBase application base URL
|
||||
* @param {string} appBaseNoFile application base URL stripped of any filename
|
||||
* @param {string} hashPrefix hashbang prefix
|
||||
*/
|
||||
function LocationHashbangUrl(appBase, hashPrefix) {
|
||||
var appBaseNoFile = stripFile(appBase);
|
||||
function LocationHashbangUrl(appBase, appBaseNoFile, hashPrefix) {
|
||||
|
||||
parseAbsoluteUrl(appBase, this);
|
||||
|
||||
@@ -280,14 +280,13 @@ function LocationHashbangUrl(appBase, hashPrefix) {
|
||||
*
|
||||
* @constructor
|
||||
* @param {string} appBase application base URL
|
||||
* @param {string} appBaseNoFile application base URL stripped of any filename
|
||||
* @param {string} hashPrefix hashbang prefix
|
||||
*/
|
||||
function LocationHashbangInHtml5Url(appBase, hashPrefix) {
|
||||
function LocationHashbangInHtml5Url(appBase, appBaseNoFile, hashPrefix) {
|
||||
this.$$html5 = true;
|
||||
LocationHashbangUrl.apply(this, arguments);
|
||||
|
||||
var appBaseNoFile = stripFile(appBase);
|
||||
|
||||
this.$$parseLinkUrl = function(url, relHref) {
|
||||
if (relHref && relHref[0] === '#') {
|
||||
// special case for links to hash fragments:
|
||||
@@ -823,7 +822,9 @@ function $LocationProvider() {
|
||||
appBase = stripHash(initialUrl);
|
||||
LocationMode = LocationHashbangUrl;
|
||||
}
|
||||
$location = new LocationMode(appBase, '#' + hashPrefix);
|
||||
var appBaseNoFile = stripFile(appBase);
|
||||
|
||||
$location = new LocationMode(appBase, appBaseNoFile, '#' + hashPrefix);
|
||||
$location.$$parseLinkUrl(initialUrl, initialUrl);
|
||||
|
||||
$location.$$state = $browser.state();
|
||||
@@ -903,6 +904,13 @@ function $LocationProvider() {
|
||||
|
||||
// update $location when $browser url changes
|
||||
$browser.onUrlChange(function(newUrl, newState) {
|
||||
|
||||
if (isUndefined(beginsWith(appBaseNoFile, newUrl))) {
|
||||
// If we are navigating outside of the app then force a reload
|
||||
$window.location.href = newUrl;
|
||||
return;
|
||||
}
|
||||
|
||||
$rootScope.$evalAsync(function() {
|
||||
var oldUrl = $location.absUrl();
|
||||
var oldState = $location.$$state;
|
||||
|
||||
+21
-2
@@ -48,6 +48,25 @@ function ensureSafeMemberName(name, fullExpression) {
|
||||
return name;
|
||||
}
|
||||
|
||||
function getStringValue(name, fullExpression) {
|
||||
// From the JavaScript docs:
|
||||
// Property names must be strings. This means that non-string objects cannot be used
|
||||
// as keys in an object. Any non-string object, including a number, is typecasted
|
||||
// into a string via the toString method.
|
||||
//
|
||||
// So, to ensure that we are checking the same `name` that JavaScript would use,
|
||||
// we cast it to a string, if possible.
|
||||
// Doing `name + ''` can cause a repl error if the result to `toString` is not a string,
|
||||
// this is, this will handle objects that misbehave.
|
||||
name = name + '';
|
||||
if (!isString(name)) {
|
||||
throw $parseMinErr('iseccst',
|
||||
'Cannot convert object to primitive value! '
|
||||
+ 'Expression: {0}', fullExpression);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
function ensureSafeObject(obj, fullExpression) {
|
||||
// nifty check if obj is Function that is fast and works across iframes and other contexts
|
||||
if (obj) {
|
||||
@@ -689,7 +708,7 @@ Parser.prototype = {
|
||||
|
||||
return extend(function $parseObjectIndex(self, locals) {
|
||||
var o = obj(self, locals),
|
||||
i = indexFn(self, locals),
|
||||
i = getStringValue(indexFn(self, locals), expression),
|
||||
v;
|
||||
|
||||
ensureSafeMemberName(i, expression);
|
||||
@@ -698,7 +717,7 @@ Parser.prototype = {
|
||||
return v;
|
||||
}, {
|
||||
assign: function(self, value, locals) {
|
||||
var key = ensureSafeMemberName(indexFn(self, locals), expression);
|
||||
var key = ensureSafeMemberName(getStringValue(indexFn(self, locals), expression), expression);
|
||||
// prevent overwriting of Function.constructor which would break ensureSafeObject check
|
||||
var o = ensureSafeObject(obj(self, locals), expression);
|
||||
if (!o) obj.assign(self, o = {}, locals);
|
||||
|
||||
@@ -1956,7 +1956,7 @@ angular.module('ngAnimate', ['ng'])
|
||||
function onAnimationProgress(event) {
|
||||
event.stopPropagation();
|
||||
var ev = event.originalEvent || event;
|
||||
var timeStamp = ev.$manualTimeStamp || ev.timeStamp || Date.now();
|
||||
var timeStamp = ev.$manualTimeStamp || Date.now();
|
||||
|
||||
/* Firefox (or possibly just Gecko) likes to not round values up
|
||||
* when a ms measurement is used for the animation */
|
||||
@@ -1964,7 +1964,7 @@ angular.module('ngAnimate', ['ng'])
|
||||
|
||||
/* $manualTimeStamp is a mocked timeStamp value which is set
|
||||
* within browserTrigger(). This is only here so that tests can
|
||||
* mock animations properly. Real events fallback to event.timeStamp,
|
||||
* mock animations properly. Real events fallback to Date.now(),
|
||||
* or, if they don't, then a timeStamp is automatically created for them.
|
||||
* We're checking to see if the timeStamp surpasses the expected delay,
|
||||
* but we're using elapsedTime instead of the timeStamp on the 2nd
|
||||
|
||||
Vendored
+48
-10
@@ -782,8 +782,8 @@ angular.mock.animate = angular.module('ngAnimateMock', ['ng'])
|
||||
};
|
||||
});
|
||||
|
||||
$provide.decorator('$animate', ['$delegate', '$$asyncCallback', '$timeout', '$browser',
|
||||
function($delegate, $$asyncCallback, $timeout, $browser) {
|
||||
$provide.decorator('$animate', ['$delegate', '$$asyncCallback', '$timeout', '$browser', '$rootScope', '$$rAF',
|
||||
function($delegate, $$asyncCallback, $timeout, $browser, $rootScope, $$rAF) {
|
||||
var animate = {
|
||||
queue: [],
|
||||
cancel: $delegate.cancel,
|
||||
@@ -803,6 +803,43 @@ angular.mock.animate = angular.module('ngAnimateMock', ['ng'])
|
||||
fn();
|
||||
});
|
||||
reflowQueue = [];
|
||||
},
|
||||
flush: function() {
|
||||
$rootScope.$digest();
|
||||
var doNextRun, somethingFlushed = false;
|
||||
do {
|
||||
doNextRun = false;
|
||||
if (reflowQueue.length) {
|
||||
doNextRun = somethingFlushed = true;
|
||||
this.triggerReflow();
|
||||
}
|
||||
if ($$rAF.queue.length) {
|
||||
doNextRun = somethingFlushed = true;
|
||||
$$rAF.flush();
|
||||
}
|
||||
if ($$asyncCallback.queue.length) {
|
||||
doNextRun = somethingFlushed = true;
|
||||
this.triggerCallbackEvents();
|
||||
}
|
||||
if (timeoutsRemaining()) {
|
||||
var oldValue = timeoutsRemaining();
|
||||
this.triggerCallbackPromise();
|
||||
var newValue = timeoutsRemaining();
|
||||
if (newValue < oldValue) {
|
||||
doNextRun = somethingFlushed = true;
|
||||
}
|
||||
}
|
||||
} while (doNextRun);
|
||||
|
||||
if (!somethingFlushed) {
|
||||
throw new Error('No pending animations ready to be closed or flushed');
|
||||
}
|
||||
|
||||
$rootScope.$digest();
|
||||
|
||||
function timeoutsRemaining() {
|
||||
return $browser.deferredFns.length;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1752,8 +1789,7 @@ angular.mock.$TimeoutDecorator = ['$delegate', '$browser', function($delegate, $
|
||||
}];
|
||||
|
||||
angular.mock.$RAFDecorator = ['$delegate', function($delegate) {
|
||||
var queue = [];
|
||||
var rafFn = function(fn) {
|
||||
var queue, rafFn = function(fn) {
|
||||
var index = queue.length;
|
||||
queue.push(fn);
|
||||
return function() {
|
||||
@@ -1761,6 +1797,8 @@ angular.mock.$RAFDecorator = ['$delegate', function($delegate) {
|
||||
};
|
||||
};
|
||||
|
||||
queue = rafFn.queue = [];
|
||||
|
||||
rafFn.supported = $delegate.supported;
|
||||
|
||||
rafFn.flush = function() {
|
||||
@@ -1773,22 +1811,22 @@ angular.mock.$RAFDecorator = ['$delegate', function($delegate) {
|
||||
queue[i]();
|
||||
}
|
||||
|
||||
queue = [];
|
||||
queue.length = 0;
|
||||
};
|
||||
|
||||
return rafFn;
|
||||
}];
|
||||
|
||||
angular.mock.$AsyncCallbackDecorator = ['$delegate', function($delegate) {
|
||||
var callbacks = [];
|
||||
var addFn = function(fn) {
|
||||
callbacks.push(fn);
|
||||
var queue, addFn = function(fn) {
|
||||
queue.push(fn);
|
||||
};
|
||||
queue = addFn.queue = [];
|
||||
addFn.flush = function() {
|
||||
angular.forEach(callbacks, function(fn) {
|
||||
angular.forEach(queue, function(fn) {
|
||||
fn();
|
||||
});
|
||||
callbacks = [];
|
||||
queue.length = 0;
|
||||
};
|
||||
return addFn;
|
||||
}];
|
||||
|
||||
+2
-1
@@ -165,6 +165,7 @@
|
||||
"spyOnlyCallsWithArgs": false,
|
||||
"createMockStyleSheet": false,
|
||||
"browserTrigger": false,
|
||||
"jqLiteCacheSize": false
|
||||
"jqLiteCacheSize": false,
|
||||
"browserSupportsCssAnimations": false
|
||||
}
|
||||
}
|
||||
|
||||
+283
-2
@@ -78,6 +78,186 @@ describe('angular', function() {
|
||||
expect(copy(objWithRegExp.re) === objWithRegExp.re).toBeFalsy();
|
||||
});
|
||||
|
||||
it("should copy a Uint8Array with no destination", function() {
|
||||
if (typeof Uint8Array !== 'undefined') {
|
||||
var src = new Uint8Array(2);
|
||||
src[1] = 1;
|
||||
var dst = copy(src);
|
||||
expect(copy(src) instanceof Uint8Array).toBeTruthy();
|
||||
expect(dst).toEqual(src);
|
||||
expect(dst).not.toBe(src);
|
||||
}
|
||||
});
|
||||
|
||||
it("should copy a Uint8ClampedArray with no destination", function() {
|
||||
if (typeof Uint8ClampedArray !== 'undefined') {
|
||||
var src = new Uint8ClampedArray(2);
|
||||
src[1] = 1;
|
||||
var dst = copy(src);
|
||||
expect(copy(src) instanceof Uint8ClampedArray).toBeTruthy();
|
||||
expect(dst).toEqual(src);
|
||||
expect(dst).not.toBe(src);
|
||||
}
|
||||
});
|
||||
|
||||
it("should copy a Uint16Array with no destination", function() {
|
||||
if (typeof Uint16Array !== 'undefined') {
|
||||
var src = new Uint16Array(2);
|
||||
src[1] = 1;
|
||||
var dst = copy(src);
|
||||
expect(copy(src) instanceof Uint16Array).toBeTruthy();
|
||||
expect(dst).toEqual(src);
|
||||
expect(dst).not.toBe(src);
|
||||
}
|
||||
});
|
||||
|
||||
it("should copy a Uint32Array with no destination", function() {
|
||||
if (typeof Uint32Array !== 'undefined') {
|
||||
var src = new Uint32Array(2);
|
||||
src[1] = 1;
|
||||
var dst = copy(src);
|
||||
expect(copy(src) instanceof Uint32Array).toBeTruthy();
|
||||
expect(dst).toEqual(src);
|
||||
expect(dst).not.toBe(src);
|
||||
}
|
||||
});
|
||||
|
||||
it("should copy a Int8Array with no destination", function() {
|
||||
if (typeof Int8Array !== 'undefined') {
|
||||
var src = new Int8Array(2);
|
||||
src[1] = 1;
|
||||
var dst = copy(src);
|
||||
expect(copy(src) instanceof Int8Array).toBeTruthy();
|
||||
expect(dst).toEqual(src);
|
||||
expect(dst).not.toBe(src);
|
||||
}
|
||||
});
|
||||
|
||||
it("should copy a Int16Array with no destination", function() {
|
||||
if (typeof Int16Array !== 'undefined') {
|
||||
var src = new Int16Array(2);
|
||||
src[1] = 1;
|
||||
var dst = copy(src);
|
||||
expect(copy(src) instanceof Int16Array).toBeTruthy();
|
||||
expect(dst).toEqual(src);
|
||||
expect(dst).not.toBe(src);
|
||||
}
|
||||
});
|
||||
|
||||
it("should copy a Int32Array with no destination", function() {
|
||||
if (typeof Int32Array !== 'undefined') {
|
||||
var src = new Int32Array(2);
|
||||
src[1] = 1;
|
||||
var dst = copy(src);
|
||||
expect(copy(src) instanceof Int32Array).toBeTruthy();
|
||||
expect(dst).toEqual(src);
|
||||
expect(dst).not.toBe(src);
|
||||
}
|
||||
});
|
||||
|
||||
it("should copy a Float32Array with no destination", function() {
|
||||
if (typeof Float32Array !== 'undefined') {
|
||||
var src = new Float32Array(2);
|
||||
src[1] = 1;
|
||||
var dst = copy(src);
|
||||
expect(copy(src) instanceof Float32Array).toBeTruthy();
|
||||
expect(dst).toEqual(src);
|
||||
expect(dst).not.toBe(src);
|
||||
}
|
||||
});
|
||||
|
||||
it("should copy a Float64Array with no destination", function() {
|
||||
if (typeof Float64Array !== 'undefined') {
|
||||
var src = new Float64Array(2);
|
||||
src[1] = 1;
|
||||
var dst = copy(src);
|
||||
expect(copy(src) instanceof Float64Array).toBeTruthy();
|
||||
expect(dst).toEqual(src);
|
||||
expect(dst).not.toBe(src);
|
||||
}
|
||||
});
|
||||
|
||||
it("should throw an exception if a Uint8Array is the destination", function() {
|
||||
if (typeof Uint8Array !== 'undefined') {
|
||||
var src = new Uint8Array();
|
||||
var dst = new Uint8Array(5);
|
||||
expect(function() { copy(src, dst); })
|
||||
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
|
||||
}
|
||||
});
|
||||
|
||||
it("should throw an exception if a Uint8ClampedArray is the destination", function() {
|
||||
if (typeof Uint8ClampedArray !== 'undefined') {
|
||||
var src = new Uint8ClampedArray();
|
||||
var dst = new Uint8ClampedArray(5);
|
||||
expect(function() { copy(src, dst); })
|
||||
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
|
||||
}
|
||||
});
|
||||
|
||||
it("should throw an exception if a Uint16Array is the destination", function() {
|
||||
if (typeof Uint16Array !== 'undefined') {
|
||||
var src = new Uint16Array();
|
||||
var dst = new Uint16Array(5);
|
||||
expect(function() { copy(src, dst); })
|
||||
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
|
||||
}
|
||||
});
|
||||
|
||||
it("should throw an exception if a Uint32Array is the destination", function() {
|
||||
if (typeof Uint32Array !== 'undefined') {
|
||||
var src = new Uint32Array();
|
||||
var dst = new Uint32Array(5);
|
||||
expect(function() { copy(src, dst); })
|
||||
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
|
||||
}
|
||||
});
|
||||
|
||||
it("should throw an exception if a Int8Array is the destination", function() {
|
||||
if (typeof Int8Array !== 'undefined') {
|
||||
var src = new Int8Array();
|
||||
var dst = new Int8Array(5);
|
||||
expect(function() { copy(src, dst); })
|
||||
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
|
||||
}
|
||||
});
|
||||
|
||||
it("should throw an exception if a Int16Array is the destination", function() {
|
||||
if (typeof Int16Array !== 'undefined') {
|
||||
var src = new Int16Array();
|
||||
var dst = new Int16Array(5);
|
||||
expect(function() { copy(src, dst); })
|
||||
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
|
||||
}
|
||||
});
|
||||
|
||||
it("should throw an exception if a Int32Array is the destination", function() {
|
||||
if (typeof Int32Array !== 'undefined') {
|
||||
var src = new Int32Array();
|
||||
var dst = new Int32Array(5);
|
||||
expect(function() { copy(src, dst); })
|
||||
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
|
||||
}
|
||||
});
|
||||
|
||||
it("should throw an exception if a Float32Array is the destination", function() {
|
||||
if (typeof Float32Array !== 'undefined') {
|
||||
var src = new Float32Array();
|
||||
var dst = new Float32Array(5);
|
||||
expect(function() { copy(src, dst); })
|
||||
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
|
||||
}
|
||||
});
|
||||
|
||||
it("should throw an exception if a Float64Array is the destination", function() {
|
||||
if (typeof Float64Array !== 'undefined') {
|
||||
var src = new Float64Array();
|
||||
var dst = new Float64Array(5);
|
||||
expect(function() { copy(src, dst); })
|
||||
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
|
||||
}
|
||||
});
|
||||
|
||||
it("should deeply copy an array into an existing array", function() {
|
||||
var src = [1, {name:"value"}];
|
||||
var dst = [{key:"v"}];
|
||||
@@ -133,11 +313,19 @@ describe('angular', function() {
|
||||
it('should throw an exception if a Scope is being copied', inject(function($rootScope) {
|
||||
expect(function() { copy($rootScope.$new()); }).
|
||||
toThrowMinErr("ng", "cpws", "Can't copy! Making copies of Window or Scope instances is not supported.");
|
||||
expect(function() { copy({child: $rootScope.$new()}, {}); }).
|
||||
toThrowMinErr("ng", "cpws", "Can't copy! Making copies of Window or Scope instances is not supported.");
|
||||
expect(function() { copy([$rootScope.$new()]); }).
|
||||
toThrowMinErr("ng", "cpws", "Can't copy! Making copies of Window or Scope instances is not supported.");
|
||||
}));
|
||||
|
||||
it('should throw an exception if a Window is being copied', function() {
|
||||
expect(function() { copy(window); }).
|
||||
toThrowMinErr("ng", "cpws", "Can't copy! Making copies of Window or Scope instances is not supported.");
|
||||
expect(function() { copy({child: window}); }).
|
||||
toThrowMinErr("ng", "cpws", "Can't copy! Making copies of Window or Scope instances is not supported.");
|
||||
expect(function() { copy([window], []); }).
|
||||
toThrowMinErr("ng", "cpws", "Can't copy! Making copies of Window or Scope instances is not supported.");
|
||||
});
|
||||
|
||||
it('should throw an exception when source and destination are equivalent', function() {
|
||||
@@ -154,9 +342,14 @@ describe('angular', function() {
|
||||
hashKey(src);
|
||||
dst = copy(src);
|
||||
expect(hashKey(dst)).not.toEqual(hashKey(src));
|
||||
|
||||
src = {foo: {}};
|
||||
hashKey(src.foo);
|
||||
dst = copy(src);
|
||||
expect(hashKey(src.foo)).not.toEqual(hashKey(dst.foo));
|
||||
});
|
||||
|
||||
it('should retain the previous $$hashKey', function() {
|
||||
it('should retain the previous $$hashKey when copying object with hashKey', function() {
|
||||
var src,dst,h;
|
||||
src = {};
|
||||
dst = {};
|
||||
@@ -171,7 +364,21 @@ describe('angular', function() {
|
||||
expect(hashKey(dst)).toEqual(h);
|
||||
});
|
||||
|
||||
it('should handle circular references when circularRefs is turned on', function() {
|
||||
it('should retain the previous $$hashKey when copying non-object', function() {
|
||||
var dst = {};
|
||||
var h = hashKey(dst);
|
||||
|
||||
copy(null, dst);
|
||||
expect(hashKey(dst)).toEqual(h);
|
||||
|
||||
copy(42, dst);
|
||||
expect(hashKey(dst)).toEqual(h);
|
||||
|
||||
copy(new Date(), dst);
|
||||
expect(hashKey(dst)).toEqual(h);
|
||||
});
|
||||
|
||||
it('should handle circular references', function() {
|
||||
var a = {b: {a: null}, self: null, selfs: [null, null, [null]]};
|
||||
a.b.a = a;
|
||||
a.self = a;
|
||||
@@ -182,13 +389,87 @@ describe('angular', function() {
|
||||
|
||||
expect(aCopy).not.toBe(a);
|
||||
expect(aCopy).toBe(aCopy.self);
|
||||
expect(aCopy).toBe(aCopy.selfs[2][0]);
|
||||
expect(aCopy.selfs[2]).not.toBe(a.selfs[2]);
|
||||
|
||||
var copyTo = [];
|
||||
aCopy = copy(a, copyTo);
|
||||
expect(aCopy).toBe(copyTo);
|
||||
expect(aCopy).not.toBe(a);
|
||||
expect(aCopy).toBe(aCopy.self);
|
||||
});
|
||||
|
||||
it('should deeply copy XML nodes', function() {
|
||||
var anElement = document.createElement('foo');
|
||||
anElement.appendChild(document.createElement('bar'));
|
||||
var theCopy = anElement.cloneNode(true);
|
||||
expect(copy(anElement).outerHTML).toEqual(theCopy.outerHTML);
|
||||
expect(copy(anElement)).not.toBe(anElement);
|
||||
});
|
||||
|
||||
it('should not try to call a non-function called `cloneNode`', function() {
|
||||
expect(copy.bind(null, { cloneNode: 100 })).not.toThrow();
|
||||
});
|
||||
|
||||
it('should handle objects with multiple references', function() {
|
||||
var b = {};
|
||||
var a = [b, -1, b];
|
||||
|
||||
var aCopy = copy(a);
|
||||
expect(aCopy[0]).not.toBe(a[0]);
|
||||
expect(aCopy[0]).toBe(aCopy[2]);
|
||||
|
||||
var copyTo = [];
|
||||
aCopy = copy(a, copyTo);
|
||||
expect(aCopy).toBe(copyTo);
|
||||
expect(aCopy[0]).not.toBe(a[0]);
|
||||
expect(aCopy[0]).toBe(aCopy[2]);
|
||||
});
|
||||
|
||||
it('should handle date/regex objects with multiple references', function() {
|
||||
var re = /foo/;
|
||||
var d = new Date();
|
||||
var o = {re: re, re2: re, d: d, d2: d};
|
||||
|
||||
var oCopy = copy(o);
|
||||
expect(oCopy.re).toBe(oCopy.re2);
|
||||
expect(oCopy.d).toBe(oCopy.d2);
|
||||
|
||||
oCopy = copy(o, {});
|
||||
expect(oCopy.re).toBe(oCopy.re2);
|
||||
expect(oCopy.d).toBe(oCopy.d2);
|
||||
});
|
||||
|
||||
it('should clear destination arrays correctly when source is non-array', function() {
|
||||
expect(copy(null, [1,2,3])).toEqual([]);
|
||||
expect(copy(undefined, [1,2,3])).toEqual([]);
|
||||
expect(copy({0: 1, 1: 2}, [1,2,3])).toEqual([1,2]);
|
||||
expect(copy(new Date(), [1,2,3])).toEqual([]);
|
||||
expect(copy(/a/, [1,2,3])).toEqual([]);
|
||||
expect(copy(true, [1,2,3])).toEqual([]);
|
||||
});
|
||||
|
||||
it('should clear destination objects correctly when source is non-array', function() {
|
||||
expect(copy(null, {0:1,1:2,2:3})).toEqual({});
|
||||
expect(copy(undefined, {0:1,1:2,2:3})).toEqual({});
|
||||
expect(copy(new Date(), {0:1,1:2,2:3})).toEqual({});
|
||||
expect(copy(/a/, {0:1,1:2,2:3})).toEqual({});
|
||||
expect(copy(true, {0:1,1:2,2:3})).toEqual({});
|
||||
});
|
||||
|
||||
it('should copy objects with no prototype parent', function() {
|
||||
var obj = extend(Object.create(null), {
|
||||
a: 1,
|
||||
b: 2,
|
||||
c: 3
|
||||
});
|
||||
var dest = copy(obj);
|
||||
|
||||
expect(Object.getPrototypeOf(dest)).toBe(null);
|
||||
expect(dest.a).toBe(1);
|
||||
expect(dest.b).toBe(2);
|
||||
expect(dest.c).toBe(3);
|
||||
expect(Object.keys(dest)).toEqual(['a', 'b', 'c']);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html ng-app>
|
||||
<body>
|
||||
<form>
|
||||
<input type="hidden" value="{{value}}" />
|
||||
<button ng-click="value = '{{ 7 * 6 }}'">Click me</button>
|
||||
</form>
|
||||
<script src="angular.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,15 @@
|
||||
describe('hidden thingy', function() {
|
||||
it('should pass', function() {
|
||||
|
||||
loadFixture('input-hidden');
|
||||
expect(element(by.css('input')).getAttribute('value')).toEqual('');
|
||||
|
||||
element(by.css('button')).click();
|
||||
expect(element(by.css('input')).getAttribute('value')).toEqual('{{ 7 * 6 }}');
|
||||
|
||||
loadFixture('sample');
|
||||
browser.driver.executeScript('history.back()');
|
||||
var expectedValue = browser.params.browser === 'safari' ? '{{ 7 * 6 }}' : '';
|
||||
expect(element(by.css('input')).getAttribute('value')).toEqual(expectedValue);
|
||||
});
|
||||
});
|
||||
@@ -56,3 +56,12 @@ function createMockStyleSheet(doc, wind) {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function browserSupportsCssAnimations() {
|
||||
var nav = window.navigator.appVersion;
|
||||
if (nav.indexOf('MSIE') >= 0) {
|
||||
var version = parseInt(navigator.appVersion.match(/MSIE ([\d.]+)/)[1]);
|
||||
return version >= 10; //only IE10+ support keyframes / transitions
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -147,7 +147,6 @@ describe('$compile', function() {
|
||||
|
||||
|
||||
describe('configuration', function() {
|
||||
|
||||
it('should register a directive', function() {
|
||||
module(function() {
|
||||
directive('div', function(log) {
|
||||
@@ -202,15 +201,6 @@ describe('$compile', function() {
|
||||
});
|
||||
inject(function($compile) {});
|
||||
});
|
||||
|
||||
it('should throw an exception if a directive name starts with a non-lowercase letter', function() {
|
||||
module(function() {
|
||||
expect(function() {
|
||||
directive('BadDirectiveName', function() { });
|
||||
}).toThrowMinErr('$compile','baddir', "Directive name 'BadDirectiveName' is invalid. The first character must be a lowercase letter");
|
||||
});
|
||||
inject(function($compile) {});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -472,7 +472,7 @@ describe('ngClass animations', function() {
|
||||
//is spaced-out then it is required so that the original digestion
|
||||
//is kicked into gear
|
||||
$rootScope.$digest();
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
expect(element.data('state')).toBe('crazy-enter');
|
||||
expect(enterComplete).toBe(true);
|
||||
|
||||
@@ -433,7 +433,7 @@ describe('ngInclude', function() {
|
||||
|
||||
expect(autoScrollSpy).not.toHaveBeenCalled();
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
expect(autoScrollSpy).toHaveBeenCalledOnce();
|
||||
}));
|
||||
@@ -450,7 +450,7 @@ describe('ngInclude', function() {
|
||||
});
|
||||
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
$rootScope.$apply(function() {
|
||||
$rootScope.tpl = 'another.html';
|
||||
@@ -459,7 +459,7 @@ describe('ngInclude', function() {
|
||||
|
||||
expect($animate.queue.shift().event).toBe('leave');
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
$rootScope.$apply(function() {
|
||||
$rootScope.tpl = 'template.html';
|
||||
@@ -468,7 +468,7 @@ describe('ngInclude', function() {
|
||||
|
||||
expect($animate.queue.shift().event).toBe('leave');
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
expect(autoScrollSpy).toHaveBeenCalled();
|
||||
expect(autoScrollSpy.callCount).toBe(3);
|
||||
@@ -484,7 +484,7 @@ describe('ngInclude', function() {
|
||||
});
|
||||
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
expect(autoScrollSpy).not.toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
@@ -500,7 +500,7 @@ describe('ngInclude', function() {
|
||||
});
|
||||
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
$rootScope.$apply(function() {
|
||||
$rootScope.tpl = 'template.html';
|
||||
@@ -522,7 +522,7 @@ describe('ngInclude', function() {
|
||||
|
||||
$rootScope.$apply("tpl = 'template.html'");
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
expect(autoScrollSpy).toHaveBeenCalledOnce();
|
||||
}
|
||||
|
||||
@@ -904,7 +904,7 @@ describe('ngModel', function() {
|
||||
|
||||
expect(function() {
|
||||
scope.$apply('value = "123"');
|
||||
}).toThrowMinErr("ngModel", "$asyncValidators",
|
||||
}).toThrowMinErr("ngModel", "nopromise",
|
||||
"Expected asynchronous validator to return a promise but got 'true' instead.");
|
||||
}));
|
||||
|
||||
|
||||
@@ -1486,7 +1486,7 @@ describe('ngRepeat animations', function() {
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(element.text()).toBe('123'); // the original order should be preserved
|
||||
$animate.triggerReflow();
|
||||
$animate.flush();
|
||||
$timeout.flush(1500); // 1s * 1.5 closing buffer
|
||||
expect(element.text()).toBe('13');
|
||||
|
||||
|
||||
@@ -204,6 +204,21 @@ describe('validators', function() {
|
||||
expect($rootScope.form.test.$error.pattern).toBe(true);
|
||||
expect(inputElm).not.toBeValid();
|
||||
});
|
||||
|
||||
|
||||
it('should validate the viewValue and not the modelValue', function() {
|
||||
var inputElm = helper.compileInput('<input type="text" name="test" ng-model="value" pattern="\\d{4}">');
|
||||
var ctrl = inputElm.controller('ngModel');
|
||||
|
||||
ctrl.$parsers.push(function(value) {
|
||||
return (value * 10) + '';
|
||||
});
|
||||
|
||||
helper.changeInputValueTo('1234');
|
||||
expect($rootScope.form.test.$error.pattern).not.toBe(true);
|
||||
expect($rootScope.form.test.$modelValue).toBe('12340');
|
||||
expect(inputElm).toBeValid();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -1657,7 +1657,7 @@ describe('$http', function() {
|
||||
$http({method: 'GET', url: '/some', timeout: canceler.promise}).error(
|
||||
function(data, status, headers, config) {
|
||||
expect(data).toBeUndefined();
|
||||
expect(status).toBe(0);
|
||||
expect(status).toBe(-1);
|
||||
expect(headers()).toEqual({});
|
||||
expect(config.url).toBe('/some');
|
||||
callback();
|
||||
|
||||
+49
-35
@@ -46,7 +46,7 @@ describe('$location', function() {
|
||||
|
||||
it('should not include the drive name in path() on WIN', function() {
|
||||
//See issue #4680 for details
|
||||
var locationUrl = new LocationHashbangUrl('file:///base', '#!');
|
||||
var locationUrl = new LocationHashbangUrl('file:///base', 'file:///', '#!');
|
||||
locationUrl.$$parse('file:///base#!/foo?a=b&c#hash');
|
||||
|
||||
expect(locationUrl.path()).toBe('/foo');
|
||||
@@ -54,7 +54,7 @@ describe('$location', function() {
|
||||
|
||||
|
||||
it('should include the drive name if it was provided in the input url', function() {
|
||||
var locationUrl = new LocationHashbangUrl('file:///base', '#!');
|
||||
var locationUrl = new LocationHashbangUrl('file:///base', 'file:///', '#!');
|
||||
locationUrl.$$parse('file:///base#!/C:/foo?a=b&c#hash');
|
||||
|
||||
expect(locationUrl.path()).toBe('/C:/foo');
|
||||
@@ -64,7 +64,7 @@ describe('$location', function() {
|
||||
|
||||
describe('NewUrl', function() {
|
||||
function createLocationHtml5Url() {
|
||||
var locationUrl = new LocationHtml5Url('http://www.domain.com:9877/');
|
||||
var locationUrl = new LocationHtml5Url('http://www.domain.com:9877/', 'http://www.domain.com:9877/');
|
||||
locationUrl.$$parse('http://www.domain.com:9877/path/b?search=a&b=c&d#hash');
|
||||
return locationUrl;
|
||||
}
|
||||
@@ -299,18 +299,18 @@ describe('$location', function() {
|
||||
|
||||
|
||||
it('should parse new url', function() {
|
||||
var locationUrl = new LocationHtml5Url('http://host.com/');
|
||||
var locationUrl = new LocationHtml5Url('http://host.com/', 'http://host.com/');
|
||||
locationUrl.$$parse('http://host.com/base');
|
||||
expect(locationUrl.path()).toBe('/base');
|
||||
|
||||
locationUrl = new LocationHtml5Url('http://host.com/');
|
||||
locationUrl = new LocationHtml5Url('http://host.com/', 'http://host.com/');
|
||||
locationUrl.$$parse('http://host.com/base#');
|
||||
expect(locationUrl.path()).toBe('/base');
|
||||
});
|
||||
|
||||
|
||||
it('should prefix path with forward-slash', function() {
|
||||
var locationUrl = new LocationHtml5Url('http://server/');
|
||||
var locationUrl = new LocationHtml5Url('http://server/', 'http://server/') ;
|
||||
locationUrl.path('b');
|
||||
|
||||
expect(locationUrl.path()).toBe('/b');
|
||||
@@ -319,7 +319,7 @@ describe('$location', function() {
|
||||
|
||||
|
||||
it('should set path to forward-slash when empty', function() {
|
||||
var locationUrl = new LocationHtml5Url('http://server/');
|
||||
var locationUrl = new LocationHtml5Url('http://server/', 'http://server/') ;
|
||||
locationUrl.$$parse('http://server/');
|
||||
expect(locationUrl.path()).toBe('/');
|
||||
expect(locationUrl.absUrl()).toBe('http://server/');
|
||||
@@ -356,7 +356,7 @@ describe('$location', function() {
|
||||
});
|
||||
|
||||
it('should prepend path with basePath', function() {
|
||||
var locationUrl = new LocationHtml5Url('http://server/base/');
|
||||
var locationUrl = new LocationHtml5Url('http://server/base/', 'http://server/base/') ;
|
||||
locationUrl.$$parse('http://server/base/abc?a');
|
||||
expect(locationUrl.path()).toBe('/abc');
|
||||
expect(locationUrl.search()).toEqual({a: true});
|
||||
@@ -367,7 +367,7 @@ describe('$location', function() {
|
||||
|
||||
|
||||
it('should throw error when invalid server url given', function() {
|
||||
var locationUrl = new LocationHtml5Url('http://server.org/base/abc', '/base');
|
||||
var locationUrl = new LocationHtml5Url('http://server.org/base/abc', 'http://server.org/base/', '/base');
|
||||
|
||||
expect(function() {
|
||||
locationUrl.$$parse('http://other.server.org/path#/path');
|
||||
@@ -376,7 +376,7 @@ describe('$location', function() {
|
||||
|
||||
|
||||
it('should throw error when invalid base url given', function() {
|
||||
var locationUrl = new LocationHtml5Url('http://server.org/base/abc', '/base');
|
||||
var locationUrl = new LocationHtml5Url('http://server.org/base/abc', 'http://server.org/base/', '/base');
|
||||
|
||||
expect(function() {
|
||||
locationUrl.$$parse('http://server.org/path#/path');
|
||||
@@ -444,7 +444,7 @@ describe('$location', function() {
|
||||
|
||||
|
||||
it('should decode special characters', function() {
|
||||
var locationUrl = new LocationHtml5Url('http://host.com/');
|
||||
var locationUrl = new LocationHtml5Url('http://host.com/', 'http://host.com/');
|
||||
locationUrl.$$parse('http://host.com/a%20%3C%3E%23?i%20j=%3C%3E%23#x%20%3C%3E%23');
|
||||
expect(locationUrl.path()).toBe('/a <>#');
|
||||
expect(locationUrl.search()).toEqual({'i j': '<>#'});
|
||||
@@ -452,7 +452,7 @@ describe('$location', function() {
|
||||
});
|
||||
|
||||
it('should decode pluses as spaces in urls', function() {
|
||||
var locationUrl = new LocationHtml5Url('http://host.com/');
|
||||
var locationUrl = new LocationHtml5Url('http://host.com/', 'http://host.com/');
|
||||
locationUrl.$$parse('http://host.com/?a+b=c+d');
|
||||
expect(locationUrl.search()).toEqual({'a b':'c d'});
|
||||
});
|
||||
@@ -470,7 +470,7 @@ describe('$location', function() {
|
||||
describe('HashbangUrl', function() {
|
||||
|
||||
function createHashbangUrl() {
|
||||
var locationUrl = new LocationHashbangUrl('http://www.server.org:1234/base', '#!');
|
||||
var locationUrl = new LocationHashbangUrl('http://www.server.org:1234/base', 'http://www.server.org:1234/', '#!');
|
||||
locationUrl.$$parse('http://www.server.org:1234/base#!/path?a=b&c#hash');
|
||||
return locationUrl;
|
||||
}
|
||||
@@ -499,7 +499,7 @@ describe('$location', function() {
|
||||
|
||||
|
||||
it('should preserve query params in base', function() {
|
||||
var locationUrl = new LocationHashbangUrl('http://www.server.org:1234/base?base=param', '#');
|
||||
var locationUrl = new LocationHashbangUrl('http://www.server.org:1234/base?base=param', 'http://www.server.org:1234/', '#');
|
||||
locationUrl.$$parse('http://www.server.org:1234/base?base=param#/path?a=b&c#hash');
|
||||
expect(locationUrl.absUrl()).toBe('http://www.server.org:1234/base?base=param#/path?a=b&c#hash');
|
||||
|
||||
@@ -511,7 +511,7 @@ describe('$location', function() {
|
||||
|
||||
|
||||
it('should prefix path with forward-slash', function() {
|
||||
var locationUrl = new LocationHashbangUrl('http://host.com/base', '#');
|
||||
var locationUrl = new LocationHashbangUrl('http://host.com/base', 'http://host.com/', '#');
|
||||
locationUrl.$$parse('http://host.com/base#path');
|
||||
expect(locationUrl.path()).toBe('/path');
|
||||
expect(locationUrl.absUrl()).toBe('http://host.com/base#/path');
|
||||
@@ -523,7 +523,7 @@ describe('$location', function() {
|
||||
|
||||
|
||||
it('should set path to forward-slash when empty', function() {
|
||||
var locationUrl = new LocationHashbangUrl('http://server/base', '#!');
|
||||
var locationUrl = new LocationHashbangUrl('http://server/base', 'http://server/', '#!');
|
||||
locationUrl.$$parse('http://server/base');
|
||||
locationUrl.path('aaa');
|
||||
|
||||
@@ -592,7 +592,7 @@ describe('$location', function() {
|
||||
|
||||
|
||||
it('should decode special characters', function() {
|
||||
var locationUrl = new LocationHashbangUrl('http://host.com/a', '#');
|
||||
var locationUrl = new LocationHashbangUrl('http://host.com/a', 'http://host.com/', '#');
|
||||
locationUrl.$$parse('http://host.com/a#/%20%3C%3E%23?i%20j=%3C%3E%23#x%20%3C%3E%23');
|
||||
expect(locationUrl.path()).toBe('/ <>#');
|
||||
expect(locationUrl.search()).toEqual({'i j': '<>#'});
|
||||
@@ -601,35 +601,35 @@ describe('$location', function() {
|
||||
|
||||
|
||||
it('should return decoded characters for search specified in URL', function() {
|
||||
var locationUrl = new LocationHtml5Url('http://host.com/');
|
||||
var locationUrl = new LocationHtml5Url('http://host.com/', 'http://host.com/');
|
||||
locationUrl.$$parse('http://host.com/?q=1%2F2%203');
|
||||
expect(locationUrl.search()).toEqual({'q': '1/2 3'});
|
||||
});
|
||||
|
||||
|
||||
it('should return decoded characters for search specified with setter', function() {
|
||||
var locationUrl = new LocationHtml5Url('http://host.com/');
|
||||
var locationUrl = new LocationHtml5Url('http://host.com/', 'http://host.com/');
|
||||
locationUrl.$$parse('http://host.com/');
|
||||
locationUrl.search('q', '1/2 3');
|
||||
expect(locationUrl.search()).toEqual({'q': '1/2 3'});
|
||||
});
|
||||
|
||||
it('should return an array for duplicate params', function() {
|
||||
var locationUrl = new LocationHtml5Url('http://host.com');
|
||||
var locationUrl = new LocationHtml5Url('http://host.com', 'http://host.com') ;
|
||||
locationUrl.$$parse('http://host.com');
|
||||
locationUrl.search('q', ['1/2 3','4/5 6']);
|
||||
expect(locationUrl.search()).toEqual({'q': ['1/2 3','4/5 6']});
|
||||
});
|
||||
|
||||
it('should encode an array correctly from search and add to url', function() {
|
||||
var locationUrl = new LocationHtml5Url('http://host.com');
|
||||
var locationUrl = new LocationHtml5Url('http://host.com', 'http://host.com') ;
|
||||
locationUrl.$$parse('http://host.com');
|
||||
locationUrl.search({'q': ['1/2 3','4/5 6']});
|
||||
expect(locationUrl.absUrl()).toEqual('http://host.com?q=1%2F2%203&q=4%2F5%206');
|
||||
});
|
||||
|
||||
it('should rewrite params when specifing a single param in search', function() {
|
||||
var locationUrl = new LocationHtml5Url('http://host.com');
|
||||
var locationUrl = new LocationHtml5Url('http://host.com', 'http://host.com') ;
|
||||
locationUrl.$$parse('http://host.com');
|
||||
locationUrl.search({'q': '1/2 3'});
|
||||
expect(locationUrl.absUrl()).toEqual('http://host.com?q=1%2F2%203');
|
||||
@@ -860,7 +860,6 @@ describe('$location', function() {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// location.href = '...' fires hashchange event synchronously, so it might happen inside $apply
|
||||
it('should not $apply when browser url changed inside $apply', function() {
|
||||
initService({html5Mode:false,hashPrefix: '!',supportHistory: true});
|
||||
@@ -1150,6 +1149,19 @@ describe('$location', function() {
|
||||
expect($browserUrl.mostRecentCall.args).toEqual(['http://new.com/a/b/bar', false, null]);
|
||||
});
|
||||
});
|
||||
|
||||
it('should force a page reload if navigating outside of the application base href', function() {
|
||||
initService({html5Mode:true, supportHistory: true});
|
||||
mockUpBrowser({initialUrl:'http://new.com/a/b/', baseHref:'/a/b/'});
|
||||
|
||||
inject(function($window, $browser, $location) {
|
||||
$window.location.href = 'http://new.com/a/outside.html';
|
||||
spyOn($window.location, '$$setHref');
|
||||
expect($window.location.$$setHref).not.toHaveBeenCalled();
|
||||
$browser.$$checkUrlChange();
|
||||
expect($window.location.$$setHref).toHaveBeenCalledWith('http://new.com/a/outside.html');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -2353,8 +2365,8 @@ describe('$location', function() {
|
||||
var locationUrl, locationIndexUrl;
|
||||
|
||||
beforeEach(function() {
|
||||
locationUrl = new LocationHtml5Url('http://server/pre/', 'http://server/pre/path');
|
||||
locationIndexUrl = new LocationHtml5Url('http://server/pre/index.html', 'http://server/pre/path');
|
||||
locationUrl = new LocationHtml5Url('http://server/pre/', 'http://server/pre/', 'http://server/pre/path');
|
||||
locationIndexUrl = new LocationHtml5Url('http://server/pre/index.html', 'http://server/pre/', 'http://server/pre/path');
|
||||
});
|
||||
|
||||
it('should rewrite URL', function() {
|
||||
@@ -2416,7 +2428,7 @@ describe('$location', function() {
|
||||
|
||||
it('should rewrite URL', function() {
|
||||
/* jshint scripturl: true */
|
||||
locationUrl = new LocationHashbangUrl('http://server/pre/', '#');
|
||||
locationUrl = new LocationHashbangUrl('http://server/pre/', 'http://server/pre/', '#');
|
||||
|
||||
expect(parseLinkAndReturn(locationUrl, 'http://other')).toEqual(undefined);
|
||||
expect(parseLinkAndReturn(locationUrl, 'http://server/pre/')).toEqual('http://server/pre/');
|
||||
@@ -2425,7 +2437,7 @@ describe('$location', function() {
|
||||
});
|
||||
|
||||
it("should not set hash if one was not originally specified", function() {
|
||||
locationUrl = new LocationHashbangUrl('http://server/pre/index.html', '#');
|
||||
locationUrl = new LocationHashbangUrl('http://server/pre/index.html', 'http://server/pre/', '#');
|
||||
|
||||
locationUrl.$$parse('http://server/pre/index.html');
|
||||
expect(locationUrl.url()).toBe('');
|
||||
@@ -2433,7 +2445,7 @@ describe('$location', function() {
|
||||
});
|
||||
|
||||
it("should parse hash if one was specified", function() {
|
||||
locationUrl = new LocationHashbangUrl('http://server/pre/index.html', '#');
|
||||
locationUrl = new LocationHashbangUrl('http://server/pre/index.html', 'http://server/pre/', '#');
|
||||
|
||||
locationUrl.$$parse('http://server/pre/index.html#/foo/bar');
|
||||
expect(locationUrl.url()).toBe('/foo/bar');
|
||||
@@ -2442,7 +2454,7 @@ describe('$location', function() {
|
||||
|
||||
|
||||
it("should prefix hash url with / if one was originally missing", function() {
|
||||
locationUrl = new LocationHashbangUrl('http://server/pre/index.html', '#');
|
||||
locationUrl = new LocationHashbangUrl('http://server/pre/index.html', 'http://server/pre/', '#');
|
||||
|
||||
locationUrl.$$parse('http://server/pre/index.html#not-starting-with-slash');
|
||||
expect(locationUrl.url()).toBe('/not-starting-with-slash');
|
||||
@@ -2452,7 +2464,7 @@ describe('$location', function() {
|
||||
|
||||
it('should not strip stuff from path just because it looks like Windows drive when it\'s not',
|
||||
function() {
|
||||
locationUrl = new LocationHashbangUrl('http://server/pre/index.html', '#');
|
||||
locationUrl = new LocationHashbangUrl('http://server/pre/index.html', 'http://server/pre/', '#');
|
||||
|
||||
locationUrl.$$parse('http://server/pre/index.html#http%3A%2F%2Fexample.com%2F');
|
||||
expect(locationUrl.url()).toBe('/http://example.com/');
|
||||
@@ -2464,7 +2476,7 @@ describe('$location', function() {
|
||||
});
|
||||
|
||||
it('should allow navigating outside the original base URL', function() {
|
||||
locationUrl = new LocationHashbangUrl('http://server/pre/index.html', '#');
|
||||
locationUrl = new LocationHashbangUrl('http://server/pre/index.html', 'http://server/pre/', '#');
|
||||
|
||||
locationUrl.$$parse('http://server/next/index.html');
|
||||
expect(locationUrl.url()).toBe('');
|
||||
@@ -2478,8 +2490,8 @@ describe('$location', function() {
|
||||
var locationUrl, locationIndexUrl;
|
||||
|
||||
beforeEach(function() {
|
||||
locationUrl = new LocationHashbangInHtml5Url('http://server/pre/', '#!');
|
||||
locationIndexUrl = new LocationHashbangInHtml5Url('http://server/pre/index.html', '#!');
|
||||
locationUrl = new LocationHashbangInHtml5Url('http://server/pre/', 'http://server/pre/', '#!');
|
||||
locationIndexUrl = new LocationHashbangInHtml5Url('http://server/pre/index.html', 'http://server/pre/', '#!');
|
||||
});
|
||||
|
||||
it('should rewrite URL', function() {
|
||||
@@ -2540,8 +2552,10 @@ describe('$location', function() {
|
||||
win.addEventListener = angular.noop;
|
||||
win.removeEventListener = angular.noop;
|
||||
win.location = {
|
||||
get href() { return parser.href; },
|
||||
set href(val) { parser.href = val; },
|
||||
get href() { return this.$$getHref(); },
|
||||
$$getHref: function() { return parser.href; },
|
||||
set href(val) { this.$$setHref(val); },
|
||||
$$setHref: function(val) { parser.href = val; },
|
||||
get hash() { return parser.hash; },
|
||||
// The parser correctly strips on a single preceding hash character if necessary
|
||||
// before joining the fragment onto the href by a new hash character
|
||||
|
||||
@@ -1190,6 +1190,20 @@ describe('parser', function() {
|
||||
scope.$eval('{}["__proto__"].foo = 1');
|
||||
}).toThrowMinErr('$parse', 'isecfld');
|
||||
|
||||
expect(function() {
|
||||
scope.$eval('{}[["__proto__"]]');
|
||||
}).toThrowMinErr('$parse', 'isecfld');
|
||||
expect(function() {
|
||||
scope.$eval('{}[["__proto__"]].foo = 1');
|
||||
}).toThrowMinErr('$parse', 'isecfld');
|
||||
|
||||
expect(function() {
|
||||
scope.$eval('0[["__proto__"]]');
|
||||
}).toThrowMinErr('$parse', 'isecfld');
|
||||
expect(function() {
|
||||
scope.$eval('0[["__proto__"]].foo = 1');
|
||||
}).toThrowMinErr('$parse', 'isecfld');
|
||||
|
||||
scope.a = "__pro";
|
||||
scope.b = "to__";
|
||||
expect(function() {
|
||||
@@ -1201,6 +1215,15 @@ describe('parser', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should prevent the exploit', function() {
|
||||
expect(function() {
|
||||
scope.$eval('(1)[{0: "__proto__", 1: "__proto__", 2: "__proto__", 3: "safe", length: 4, toString: [].pop}].foo = 1');
|
||||
});
|
||||
if (!msie || msie > 10) {
|
||||
expect((1)['__proto__'].foo).toBeUndefined();
|
||||
}
|
||||
});
|
||||
|
||||
it('should prevent the exploit', function() {
|
||||
expect(function() {
|
||||
scope.$eval('' +
|
||||
|
||||
+218
-261
File diff suppressed because it is too large
Load Diff
Vendored
+179
@@ -1828,6 +1828,185 @@ describe('ngMockE2E', function() {
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('ngAnimateMock', function() {
|
||||
|
||||
beforeEach(module('ngAnimate'));
|
||||
beforeEach(module('ngAnimateMock'));
|
||||
|
||||
var ss, element, trackedAnimations;
|
||||
|
||||
beforeEach(module(function($animateProvider) {
|
||||
trackedAnimations = [];
|
||||
$animateProvider.register('.animate', function($timeout) {
|
||||
return {
|
||||
leave: logFn('leave'),
|
||||
addClass: logFn('addClass')
|
||||
};
|
||||
|
||||
function logFn(method) {
|
||||
return function(element) {
|
||||
trackedAnimations.push(getDoneCallback(arguments));
|
||||
// this will never finish an animation so we'll issue a call
|
||||
// to timeout so that the mock driver won't throw an exception
|
||||
$timeout(angular.noop, 0, false);
|
||||
};
|
||||
}
|
||||
|
||||
function getDoneCallback(args) {
|
||||
for (var i = args.length; i > 0; i--) {
|
||||
if (angular.isFunction(args[i])) return args[i];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return function($animate, $rootElement, $document, $rootScope, $window) {
|
||||
if (ss) {
|
||||
ss.destroy();
|
||||
}
|
||||
ss = createMockStyleSheet($document, $window);
|
||||
|
||||
element = angular.element('<div class="animate"></div>');
|
||||
$rootElement.append(element);
|
||||
angular.element($document[0].body).append($rootElement);
|
||||
$animate.enabled(true);
|
||||
$rootScope.$digest();
|
||||
};
|
||||
}));
|
||||
|
||||
describe('$animate.queue', function() {
|
||||
it('should maintain a queue of the executed animations', inject(function($animate) {
|
||||
element.removeClass('animate'); // we don't care to test any actual animations
|
||||
var options = {};
|
||||
|
||||
$animate.addClass(element, 'on', options);
|
||||
var first = $animate.queue[0];
|
||||
expect(first.element).toBe(element);
|
||||
expect(first.event).toBe('addClass');
|
||||
expect(first.options).toBe(options);
|
||||
|
||||
$animate.removeClass(element, 'off', options);
|
||||
var second = $animate.queue[1];
|
||||
expect(second.element).toBe(element);
|
||||
expect(second.event).toBe('removeClass');
|
||||
expect(second.options).toBe(options);
|
||||
|
||||
$animate.leave(element, options);
|
||||
var third = $animate.queue[2];
|
||||
expect(third.element).toBe(element);
|
||||
expect(third.event).toBe('leave');
|
||||
expect(third.options).toBe(options);
|
||||
}));
|
||||
});
|
||||
|
||||
describe('$animate.flush()', function() {
|
||||
it('should throw an error if there is nothing to animate', inject(function($animate) {
|
||||
expect(function() {
|
||||
$animate.flush();
|
||||
}).toThrow('No pending animations ready to be closed or flushed');
|
||||
}));
|
||||
|
||||
it('should trigger the animation to start',
|
||||
inject(function($animate) {
|
||||
|
||||
expect(trackedAnimations.length).toBe(0);
|
||||
$animate.leave(element);
|
||||
$animate.flush();
|
||||
expect(trackedAnimations.length).toBe(1);
|
||||
}));
|
||||
|
||||
it('should trigger the animation to end once run and called',
|
||||
inject(function($animate) {
|
||||
|
||||
$animate.leave(element);
|
||||
$animate.flush();
|
||||
expect(element.parent().length).toBe(1);
|
||||
|
||||
trackedAnimations[0]();
|
||||
$animate.flush();
|
||||
expect(element.parent().length).toBe(0);
|
||||
}));
|
||||
|
||||
it('should trigger the animation promise callback to fire once run and closed',
|
||||
inject(function($animate) {
|
||||
|
||||
var doneSpy = jasmine.createSpy();
|
||||
$animate.leave(element).then(doneSpy);
|
||||
$animate.flush();
|
||||
|
||||
trackedAnimations[0]();
|
||||
expect(doneSpy).not.toHaveBeenCalled();
|
||||
$animate.flush();
|
||||
expect(doneSpy).toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
it('should trigger a series of CSS animations to trigger and start once run',
|
||||
inject(function($animate, $rootScope) {
|
||||
|
||||
if (!browserSupportsCssAnimations()) return;
|
||||
|
||||
ss.addRule('.leave-me.ng-leave', 'transition:1s linear all;');
|
||||
|
||||
var i, elm, elms = [];
|
||||
for (i = 0; i < 5; i++) {
|
||||
elm = angular.element('<div class="leave-me"></div>');
|
||||
element.append(elm);
|
||||
elms.push(elm);
|
||||
|
||||
$animate.leave(elm);
|
||||
}
|
||||
|
||||
$rootScope.$digest();
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
elm = elms[i];
|
||||
expect(elm.hasClass('ng-leave')).toBe(true);
|
||||
expect(elm.hasClass('ng-leave-active')).toBe(false);
|
||||
}
|
||||
|
||||
$animate.flush();
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
elm = elms[i];
|
||||
expect(elm.hasClass('ng-leave')).toBe(true);
|
||||
expect(elm.hasClass('ng-leave-active')).toBe(true);
|
||||
}
|
||||
}));
|
||||
|
||||
it('should trigger parent and child animations to run within the same flush',
|
||||
inject(function($animate, $rootScope) {
|
||||
|
||||
var child = angular.element('<div class="animate child"></div>');
|
||||
element.append(child);
|
||||
|
||||
expect(trackedAnimations.length).toBe(0);
|
||||
|
||||
$animate.addClass(element, 'go');
|
||||
$animate.addClass(child, 'start');
|
||||
$animate.flush();
|
||||
|
||||
expect(trackedAnimations.length).toBe(2);
|
||||
}));
|
||||
|
||||
it('should trigger animation callbacks when called',
|
||||
inject(function($animate, $rootScope) {
|
||||
|
||||
var spy = jasmine.createSpy();
|
||||
element.on('$animate:before', spy);
|
||||
element.on('$animate:close', spy);
|
||||
|
||||
$animate.addClass(element, 'on');
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
|
||||
$animate.flush();
|
||||
expect(spy.callCount).toBe(1);
|
||||
|
||||
trackedAnimations[0]();
|
||||
$animate.flush();
|
||||
expect(spy.callCount).toBe(2);
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('make sure that we can create an injector outside of tests', function() {
|
||||
|
||||
@@ -712,7 +712,7 @@ describe('ngView animations', function() {
|
||||
$location.path('/foo');
|
||||
$rootScope.$digest();
|
||||
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
$location.path('/');
|
||||
$rootScope.$digest();
|
||||
@@ -776,7 +776,7 @@ describe('ngView animations', function() {
|
||||
expect($animate.queue.shift().event).toBe('addClass');
|
||||
expect($animate.queue.shift().event).toBe('removeClass');
|
||||
|
||||
$animate.triggerReflow();
|
||||
$animate.flush();
|
||||
|
||||
expect(item.hasClass('classy')).toBe(false);
|
||||
expect(item.hasClass('boring')).toBe(true);
|
||||
@@ -914,7 +914,7 @@ describe('ngView animations', function() {
|
||||
$location.path('/foo');
|
||||
$rootScope.$digest();
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
expect(autoScrollSpy).toHaveBeenCalledOnce();
|
||||
}));
|
||||
@@ -928,7 +928,7 @@ describe('ngView animations', function() {
|
||||
$location.path('/foo');
|
||||
$rootScope.$digest();
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
expect(autoScrollSpy).toHaveBeenCalledOnce();
|
||||
}));
|
||||
@@ -941,7 +941,7 @@ describe('ngView animations', function() {
|
||||
$location.path('/foo');
|
||||
$rootScope.$digest();
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
expect(autoScrollSpy).not.toHaveBeenCalled();
|
||||
}));
|
||||
@@ -955,7 +955,7 @@ describe('ngView animations', function() {
|
||||
$location.path('/foo');
|
||||
$rootScope.$digest();
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
expect(autoScrollSpy).not.toHaveBeenCalled();
|
||||
}));
|
||||
@@ -972,7 +972,7 @@ describe('ngView animations', function() {
|
||||
expect(autoScrollSpy).not.toHaveBeenCalled();
|
||||
|
||||
expect($animate.queue.shift().event).toBe('enter');
|
||||
$animate.triggerCallbacks();
|
||||
$animate.flush();
|
||||
|
||||
expect($animate.enter).toHaveBeenCalledOnce();
|
||||
expect(autoScrollSpy).toHaveBeenCalledOnce();
|
||||
|
||||
Reference in New Issue
Block a user