diff --git a/docs/app/e2e/app.scenario.js b/docs/app/e2e/app.scenario.js
index 829323bb6115..4bacb00de97a 100644
--- a/docs/app/e2e/app.scenario.js
+++ b/docs/app/e2e/app.scenario.js
@@ -1,6 +1,6 @@
'use strict';
-var webdriver = require('protractor/node_modules/selenium-webdriver');
+var webdriver = require('selenium-webdriver');
describe('docs.angularjs.org', function() {
diff --git a/docs/content/error/$compile/badrestrict.ngdoc b/docs/content/error/$compile/badrestrict.ngdoc
new file mode 100644
index 000000000000..7c4eb41a1984
--- /dev/null
+++ b/docs/content/error/$compile/badrestrict.ngdoc
@@ -0,0 +1,18 @@
+@ngdoc error
+@name $compile:badrestrict
+@fullName Invalid Directive Restrict
+@description
+
+This error occurs when the restrict property of a directive is not valid.
+
+The directive restrict property must be a string including one of more of the following characters:
+* E (element)
+* A (attribute)
+* C (class)
+* M (comment)
+
+For example:
+```javascript
+restrict: 'E'
+restrict: 'EAC'
+```
\ No newline at end of file
diff --git a/docs/content/error/$compile/multilink.ngdoc b/docs/content/error/$compile/multilink.ngdoc
new file mode 100644
index 000000000000..6404ec04f69a
--- /dev/null
+++ b/docs/content/error/$compile/multilink.ngdoc
@@ -0,0 +1,27 @@
+@ngdoc error
+@name $compile:multilink
+@fullName Linking Element Multiple Times
+@description
+
+This error occurs when a single element is linked more then once.
+
+For example, if an element is compiled and linked twice without cloning:
+```
+ var linker = $compile(template);
+ linker($scope); //=> ok
+ linker($scope); //=> multilink error
+```
+
+Linking an element as a clone multiple times is ok:
+```
+ var linker = $compile(template);
+ linker($scope, function() { ... }); //=> ok
+ linker($scope, function() { ... }); //=> ok
+```
+
+However once an element has been linked it can not be re-linked as a clone:
+```
+ var linker = $compile(template);
+ linker($scope); //=> ok
+ linker($scope, function() { ... }); //=> multilink error
+```
\ No newline at end of file
diff --git a/docs/content/error/$compile/noident.ngdoc b/docs/content/error/$compile/noident.ngdoc
index 428629b5d7be..9770a94585e1 100644
--- a/docs/content/error/$compile/noident.ngdoc
+++ b/docs/content/error/$compile/noident.ngdoc
@@ -16,7 +16,7 @@ For example, the following directives are valid:
directive("okay", function() {
return {
bindToController: true,
- controller: "myCtrl as $ctrl"
+ controller: "myCtrl as $ctrl",
scope: {
text: "@text"
}
diff --git a/docs/content/guide/external-resources.ngdoc b/docs/content/guide/external-resources.ngdoc
index 1191a09da3f2..3113dcd76623 100644
--- a/docs/content/guide/external-resources.ngdoc
+++ b/docs/content/guide/external-resources.ngdoc
@@ -140,7 +140,7 @@ You can find a larger list of Angular external libraries at [ngmodules.org](http
[Pluralsite (3 courses)](http://www.pluralsight.com/training/Courses/Find?highlight=true&searchTerm=angularjs),
[Tuts+](https://tutsplus.com/course/easier-js-apps-with-angular/),
[lynda.com](http://www.lynda.com/AngularJS-tutorials/Up-Running-AngularJS/133318-2.html),
- [WintellectNOW (4 lessons)](http://www.wintellectnow.com/Course/Detail/mastering-angularjs)
+ [WintellectNOW (4 lessons)](http://www.wintellectnow.com/Course/Detail/mastering-angularjs),
+ [Packt](https://www.packtpub.com/web-development/angularjs-maintaining-web-applications)
* **Paid onsite:**
[angularbootcamp.com](http://angularbootcamp.com/)
-
diff --git a/karma-shared.conf.js b/karma-shared.conf.js
index ee4c78d00d7b..44acad709f48 100644
--- a/karma-shared.conf.js
+++ b/karma-shared.conf.js
@@ -170,8 +170,8 @@ module.exports = function(config, specificOptions) {
'/someSanitizedUrl',
'/{{testUrl}}'
];
- var log4js = require('./node_modules/karma/node_modules/log4js');
- var layouts = require('./node_modules/karma/node_modules/log4js/lib/layouts');
+ var log4js = require('log4js');
+ var layouts = require('log4js/lib/layouts');
var originalConfigure = log4js.configure;
log4js.configure = function(log4jsConfig) {
var consoleAppender = log4jsConfig.appenders.shift();
diff --git a/lib/grunt/plugins.js b/lib/grunt/plugins.js
index 6a436505a727..14cdecd300ce 100644
--- a/lib/grunt/plugins.js
+++ b/lib/grunt/plugins.js
@@ -39,7 +39,7 @@ module.exports = function(grunt) {
grunt.registerTask('docs', 'create angular docs', function() {
- var gruntProc = shelljs.exec('"node_modules/.bin/gulp" --gulpfile docs/gulpfile.js');
+ var gruntProc = shelljs.exec('npm run gulp -- --gulpfile docs/gulpfile.js');
if (gruntProc.code !== 0) {
throw new Error('doc generation failed');
}
diff --git a/lib/grunt/utils.js b/lib/grunt/utils.js
index 9837478b7c55..187bb8383b53 100644
--- a/lib/grunt/utils.js
+++ b/lib/grunt/utils.js
@@ -3,7 +3,7 @@
var fs = require('fs');
var shell = require('shelljs');
var grunt = require('grunt');
-var spawn = require('child_process').spawn;
+var spawn = require('cross-spawn');
var CSP_CSS_HEADER = '/* Include this file in your html if you are using the CSP mode. */\n\n';
@@ -15,7 +15,7 @@ module.exports = {
var reporters = grunt.option('reporters');
var noColor = grunt.option('no-colors');
var port = grunt.option('port');
- var p = spawn('node', ['node_modules/karma/bin/karma', 'start', config,
+ var p = spawn('./node_modules/.bin/karma', ['start', config,
singleRun ? '--single-run=true' : '',
reporters ? '--reporters=' + reporters : '',
browsers ? '--browsers=' + browsers : '',
@@ -38,7 +38,7 @@ module.exports = {
done();
return;
}
- var p = spawn('node', ['node_modules/protractor/bin/webdriver-manager', 'update']);
+ var p = spawn('./node_modules/.bin/webdriver-manager', ['update']);
p.stdout.pipe(process.stdout);
p.stderr.pipe(process.stderr);
p.on('exit', function(code) {
@@ -54,7 +54,7 @@ module.exports = {
var sauceBuild = grunt.option('capabilities.build');
var browser = grunt.option('browser');
var specs = grunt.option('specs');
- var args = ['node_modules/protractor/bin/protractor', config];
+ var args = [config];
if (sauceUser) args.push('--sauceUser=' + sauceUser);
if (sauceKey) args.push('--sauceKey=' + sauceKey);
if (tunnelIdentifier) args.push('--capabilities.tunnel-identifier=' + tunnelIdentifier);
@@ -65,7 +65,7 @@ module.exports = {
}
- var p = spawn('node', args);
+ var p = spawn('./node_modules/.bin/protractor', args);
p.stdout.pipe(process.stdout);
p.stderr.pipe(process.stderr);
p.on('exit', function(code) {
diff --git a/npm-shrinkwrap.clean.json b/npm-shrinkwrap.clean.json
index 53c84d8a7264..16f7fc7818c4 100644
--- a/npm-shrinkwrap.clean.json
+++ b/npm-shrinkwrap.clean.json
@@ -2630,6 +2630,30 @@
}
}
},
+ "cross-spawn": {
+ "version": "4.0.0",
+ "dependencies": {
+ "lru-cache": {
+ "version": "4.0.1",
+ "dependencies": {
+ "pseudomap": {
+ "version": "1.0.2"
+ },
+ "yallist": {
+ "version": "2.0.0"
+ }
+ }
+ },
+ "which": {
+ "version": "1.2.10",
+ "dependencies": {
+ "isexe": {
+ "version": "1.1.2"
+ }
+ }
+ }
+ }
+ },
"cz-conventional-changelog": {
"version": "1.1.4",
"dependencies": {
@@ -2933,14 +2957,6 @@
},
"async-each": {
"version": "0.1.6"
- },
- "fsevents": {
- "version": "0.3.8",
- "dependencies": {
- "nan": {
- "version": "2.4.0"
- }
- }
}
}
}
@@ -6966,378 +6982,6 @@
"version": "1.0.1"
}
}
- },
- "fsevents": {
- "version": "1.0.14",
- "dependencies": {
- "nan": {
- "version": "2.4.0"
- },
- "node-pre-gyp": {
- "version": "0.6.29"
- },
- "abbrev": {
- "version": "1.0.9"
- },
- "ansi-regex": {
- "version": "2.0.0"
- },
- "ansi-styles": {
- "version": "2.2.1"
- },
- "aproba": {
- "version": "1.0.4"
- },
- "are-we-there-yet": {
- "version": "1.1.2"
- },
- "asn1": {
- "version": "0.2.3"
- },
- "assert-plus": {
- "version": "0.2.0"
- },
- "async": {
- "version": "1.5.2"
- },
- "aws-sign2": {
- "version": "0.6.0"
- },
- "aws4": {
- "version": "1.4.1"
- },
- "balanced-match": {
- "version": "0.4.2"
- },
- "block-stream": {
- "version": "0.0.9"
- },
- "boom": {
- "version": "2.10.1"
- },
- "brace-expansion": {
- "version": "1.1.5"
- },
- "buffer-shims": {
- "version": "1.0.0"
- },
- "caseless": {
- "version": "0.11.0"
- },
- "chalk": {
- "version": "1.1.3"
- },
- "code-point-at": {
- "version": "1.0.0"
- },
- "combined-stream": {
- "version": "1.0.5"
- },
- "commander": {
- "version": "2.9.0"
- },
- "concat-map": {
- "version": "0.0.1"
- },
- "console-control-strings": {
- "version": "1.1.0"
- },
- "core-util-is": {
- "version": "1.0.2"
- },
- "cryptiles": {
- "version": "2.0.5"
- },
- "debug": {
- "version": "2.2.0"
- },
- "deep-extend": {
- "version": "0.4.1"
- },
- "delayed-stream": {
- "version": "1.0.0"
- },
- "delegates": {
- "version": "1.0.0"
- },
- "ecc-jsbn": {
- "version": "0.1.1"
- },
- "escape-string-regexp": {
- "version": "1.0.5"
- },
- "extend": {
- "version": "3.0.0"
- },
- "extsprintf": {
- "version": "1.0.2"
- },
- "forever-agent": {
- "version": "0.6.1"
- },
- "form-data": {
- "version": "1.0.0-rc4"
- },
- "fs.realpath": {
- "version": "1.0.0"
- },
- "fstream": {
- "version": "1.0.10"
- },
- "fstream-ignore": {
- "version": "1.0.5"
- },
- "gauge": {
- "version": "2.6.0"
- },
- "generate-function": {
- "version": "2.0.0"
- },
- "generate-object-property": {
- "version": "1.2.0"
- },
- "glob": {
- "version": "7.0.5"
- },
- "graceful-fs": {
- "version": "4.1.4"
- },
- "graceful-readlink": {
- "version": "1.0.1"
- },
- "har-validator": {
- "version": "2.0.6"
- },
- "has-ansi": {
- "version": "2.0.0"
- },
- "has-color": {
- "version": "0.1.7"
- },
- "has-unicode": {
- "version": "2.0.1"
- },
- "hawk": {
- "version": "3.1.3"
- },
- "hoek": {
- "version": "2.16.3"
- },
- "http-signature": {
- "version": "1.1.1"
- },
- "inflight": {
- "version": "1.0.5"
- },
- "inherits": {
- "version": "2.0.1"
- },
- "ini": {
- "version": "1.3.4"
- },
- "is-fullwidth-code-point": {
- "version": "1.0.0"
- },
- "is-my-json-valid": {
- "version": "2.13.1"
- },
- "is-property": {
- "version": "1.0.2"
- },
- "is-typedarray": {
- "version": "1.0.0"
- },
- "isarray": {
- "version": "1.0.0"
- },
- "isstream": {
- "version": "0.1.2"
- },
- "jodid25519": {
- "version": "1.0.2"
- },
- "jsbn": {
- "version": "0.1.0"
- },
- "json-schema": {
- "version": "0.2.2"
- },
- "json-stringify-safe": {
- "version": "5.0.1"
- },
- "jsonpointer": {
- "version": "2.0.0"
- },
- "jsprim": {
- "version": "1.3.0"
- },
- "mime-db": {
- "version": "1.23.0"
- },
- "mime-types": {
- "version": "2.1.11"
- },
- "minimatch": {
- "version": "3.0.2"
- },
- "minimist": {
- "version": "0.0.8"
- },
- "mkdirp": {
- "version": "0.5.1"
- },
- "ms": {
- "version": "0.7.1"
- },
- "node-uuid": {
- "version": "1.4.7"
- },
- "nopt": {
- "version": "3.0.6"
- },
- "npmlog": {
- "version": "3.1.2"
- },
- "number-is-nan": {
- "version": "1.0.0"
- },
- "oauth-sign": {
- "version": "0.8.2"
- },
- "object-assign": {
- "version": "4.1.0"
- },
- "once": {
- "version": "1.3.3"
- },
- "path-is-absolute": {
- "version": "1.0.0"
- },
- "pinkie": {
- "version": "2.0.4"
- },
- "pinkie-promise": {
- "version": "2.0.1"
- },
- "process-nextick-args": {
- "version": "1.0.7"
- },
- "qs": {
- "version": "6.2.0"
- },
- "readable-stream": {
- "version": "2.1.4"
- },
- "request": {
- "version": "2.73.0"
- },
- "rimraf": {
- "version": "2.5.3"
- },
- "semver": {
- "version": "5.2.0"
- },
- "set-blocking": {
- "version": "2.0.0"
- },
- "signal-exit": {
- "version": "3.0.0"
- },
- "sntp": {
- "version": "1.0.9"
- },
- "string-width": {
- "version": "1.0.1"
- },
- "string_decoder": {
- "version": "0.10.31"
- },
- "stringstream": {
- "version": "0.0.5"
- },
- "strip-ansi": {
- "version": "3.0.1"
- },
- "strip-json-comments": {
- "version": "1.0.4"
- },
- "supports-color": {
- "version": "2.0.0"
- },
- "tar": {
- "version": "2.2.1"
- },
- "tar-pack": {
- "version": "3.1.4"
- },
- "tough-cookie": {
- "version": "2.2.2"
- },
- "tunnel-agent": {
- "version": "0.4.3"
- },
- "tweetnacl": {
- "version": "0.13.3"
- },
- "uid-number": {
- "version": "0.0.6"
- },
- "util-deprecate": {
- "version": "1.0.2"
- },
- "verror": {
- "version": "1.3.6"
- },
- "wide-align": {
- "version": "1.1.0"
- },
- "wrappy": {
- "version": "1.0.2"
- },
- "xtend": {
- "version": "4.0.1"
- },
- "bl": {
- "version": "1.1.2",
- "dependencies": {
- "readable-stream": {
- "version": "2.0.6"
- }
- }
- },
- "dashdash": {
- "version": "1.14.0",
- "dependencies": {
- "assert-plus": {
- "version": "1.0.0"
- }
- }
- },
- "getpass": {
- "version": "0.1.6",
- "dependencies": {
- "assert-plus": {
- "version": "1.0.0"
- }
- }
- },
- "rc": {
- "version": "1.1.6",
- "dependencies": {
- "minimist": {
- "version": "1.2.0"
- }
- }
- },
- "sshpk": {
- "version": "1.8.3",
- "dependencies": {
- "assert-plus": {
- "version": "1.0.0"
- }
- }
- }
- }
}
}
},
@@ -7490,31 +7134,6 @@
"lodash": {
"version": "3.10.1"
},
- "log4js": {
- "version": "0.6.38",
- "dependencies": {
- "readable-stream": {
- "version": "1.0.34",
- "dependencies": {
- "core-util-is": {
- "version": "1.0.2"
- },
- "isarray": {
- "version": "0.0.1"
- },
- "string_decoder": {
- "version": "0.10.31"
- },
- "inherits": {
- "version": "2.0.1"
- }
- }
- },
- "semver": {
- "version": "4.3.6"
- }
- }
- },
"mime": {
"version": "1.3.4"
},
@@ -8379,6 +7998,31 @@
"lodash": {
"version": "2.4.2"
},
+ "log4js": {
+ "version": "0.6.38",
+ "dependencies": {
+ "readable-stream": {
+ "version": "1.0.34",
+ "dependencies": {
+ "core-util-is": {
+ "version": "1.0.2"
+ },
+ "isarray": {
+ "version": "0.0.1"
+ },
+ "string_decoder": {
+ "version": "0.10.31"
+ },
+ "inherits": {
+ "version": "2.0.1"
+ }
+ }
+ },
+ "semver": {
+ "version": "4.3.6"
+ }
+ }
+ },
"marked": {
"version": "0.3.5"
},
@@ -8636,42 +8280,6 @@
}
}
},
- "selenium-webdriver": {
- "version": "2.53.3",
- "dependencies": {
- "adm-zip": {
- "version": "0.4.4"
- },
- "rimraf": {
- "version": "2.5.4"
- },
- "tmp": {
- "version": "0.0.24"
- },
- "ws": {
- "version": "1.1.1",
- "dependencies": {
- "options": {
- "version": "0.0.6"
- },
- "ultron": {
- "version": "1.0.2"
- }
- }
- },
- "xml2js": {
- "version": "0.4.4",
- "dependencies": {
- "sax": {
- "version": "0.6.1"
- },
- "xmlbuilder": {
- "version": "8.2.2"
- }
- }
- }
- }
- },
"source-map-support": {
"version": "0.4.2",
"dependencies": {
@@ -9004,6 +8612,90 @@
"sax": {
"version": "1.2.1"
},
+ "selenium-webdriver": {
+ "version": "2.53.3",
+ "dependencies": {
+ "adm-zip": {
+ "version": "0.4.4"
+ },
+ "rimraf": {
+ "version": "2.5.4",
+ "dependencies": {
+ "glob": {
+ "version": "7.0.6",
+ "dependencies": {
+ "fs.realpath": {
+ "version": "1.0.0"
+ },
+ "inflight": {
+ "version": "1.0.5",
+ "dependencies": {
+ "wrappy": {
+ "version": "1.0.2"
+ }
+ }
+ },
+ "inherits": {
+ "version": "2.0.1"
+ },
+ "minimatch": {
+ "version": "3.0.3",
+ "dependencies": {
+ "brace-expansion": {
+ "version": "1.1.6",
+ "dependencies": {
+ "balanced-match": {
+ "version": "0.4.2"
+ },
+ "concat-map": {
+ "version": "0.0.1"
+ }
+ }
+ }
+ }
+ },
+ "once": {
+ "version": "1.3.3",
+ "dependencies": {
+ "wrappy": {
+ "version": "1.0.2"
+ }
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.0"
+ }
+ }
+ }
+ }
+ },
+ "tmp": {
+ "version": "0.0.24"
+ },
+ "ws": {
+ "version": "1.1.1",
+ "dependencies": {
+ "options": {
+ "version": "0.0.6"
+ },
+ "ultron": {
+ "version": "1.0.2"
+ }
+ }
+ },
+ "xml2js": {
+ "version": "0.4.4",
+ "dependencies": {
+ "sax": {
+ "version": "0.6.1"
+ },
+ "xmlbuilder": {
+ "version": "8.2.2"
+ }
+ }
+ }
+ }
+ },
"semver": {
"version": "4.0.3"
},
diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json
index c176d82cb3ec..4023e8f04610 100644
--- a/npm-shrinkwrap.json
+++ b/npm-shrinkwrap.json
@@ -3506,90 +3506,90 @@
},
"commitizen": {
"version": "2.8.4",
- "from": "commitizen@>=2.3.0 <3.0.0",
+ "from": "https://registry.npmjs.org/commitizen/-/commitizen-2.8.4.tgz",
"resolved": "https://registry.npmjs.org/commitizen/-/commitizen-2.8.4.tgz",
"dependencies": {
"chalk": {
"version": "1.1.3",
- "from": "chalk@1.1.3",
+ "from": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"dependencies": {
"ansi-styles": {
"version": "2.2.1",
- "from": "ansi-styles@>=2.2.1 <3.0.0",
+ "from": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz"
},
"escape-string-regexp": {
"version": "1.0.5",
- "from": "escape-string-regexp@>=1.0.2 <2.0.0",
+ "from": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
},
"has-ansi": {
"version": "2.0.0",
- "from": "has-ansi@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
"dependencies": {
"ansi-regex": {
"version": "2.0.0",
- "from": "ansi-regex@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz"
}
}
},
"strip-ansi": {
"version": "3.0.1",
- "from": "strip-ansi@>=3.0.0 <4.0.0",
+ "from": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"dependencies": {
"ansi-regex": {
"version": "2.0.0",
- "from": "ansi-regex@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz"
}
}
},
"supports-color": {
"version": "2.0.0",
- "from": "supports-color@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz"
}
}
},
"cz-conventional-changelog": {
"version": "1.1.6",
- "from": "cz-conventional-changelog@1.1.6",
+ "from": "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-1.1.6.tgz",
"resolved": "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-1.1.6.tgz",
"dependencies": {
"word-wrap": {
"version": "1.1.0",
- "from": "word-wrap@>=1.0.3 <2.0.0",
+ "from": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.1.0.tgz",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.1.0.tgz"
}
}
},
"dedent": {
"version": "0.6.0",
- "from": "dedent@0.6.0",
+ "from": "https://registry.npmjs.org/dedent/-/dedent-0.6.0.tgz",
"resolved": "https://registry.npmjs.org/dedent/-/dedent-0.6.0.tgz"
},
"detect-indent": {
"version": "4.0.0",
- "from": "detect-indent@4.0.0",
+ "from": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
"dependencies": {
"repeating": {
"version": "2.0.1",
- "from": "repeating@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
"dependencies": {
"is-finite": {
"version": "1.0.1",
- "from": "is-finite@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.1.tgz",
"dependencies": {
"number-is-nan": {
"version": "1.0.0",
- "from": "number-is-nan@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz"
}
}
@@ -3600,54 +3600,54 @@
},
"find-node-modules": {
"version": "1.0.3",
- "from": "find-node-modules@1.0.3",
+ "from": "https://registry.npmjs.org/find-node-modules/-/find-node-modules-1.0.3.tgz",
"resolved": "https://registry.npmjs.org/find-node-modules/-/find-node-modules-1.0.3.tgz",
"dependencies": {
"findup-sync": {
"version": "0.2.1",
- "from": "findup-sync@>=0.2.1 <0.3.0",
+ "from": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.2.1.tgz",
"resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.2.1.tgz",
"dependencies": {
"glob": {
"version": "4.3.5",
- "from": "glob@>=4.3.0 <4.4.0",
+ "from": "https://registry.npmjs.org/glob/-/glob-4.3.5.tgz",
"resolved": "https://registry.npmjs.org/glob/-/glob-4.3.5.tgz",
"dependencies": {
"inflight": {
"version": "1.0.5",
- "from": "inflight@>=1.0.4 <2.0.0",
+ "from": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz",
"dependencies": {
"wrappy": {
"version": "1.0.2",
- "from": "wrappy@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
}
}
},
"inherits": {
"version": "2.0.1",
- "from": "inherits@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
},
"minimatch": {
"version": "2.0.10",
- "from": "minimatch@>=2.0.1 <3.0.0",
+ "from": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz",
"dependencies": {
"brace-expansion": {
"version": "1.1.6",
- "from": "brace-expansion@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz",
"dependencies": {
"balanced-match": {
"version": "0.4.2",
- "from": "balanced-match@>=0.4.1 <0.5.0",
+ "from": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz"
},
"concat-map": {
"version": "0.0.1",
- "from": "concat-map@0.0.1",
+ "from": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
}
}
@@ -3656,12 +3656,12 @@
},
"once": {
"version": "1.3.3",
- "from": "once@>=1.3.0 <2.0.0",
+ "from": "https://registry.npmjs.org/once/-/once-1.3.3.tgz",
"resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz",
"dependencies": {
"wrappy": {
"version": "1.0.2",
- "from": "wrappy@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
}
}
@@ -3672,61 +3672,61 @@
},
"merge": {
"version": "1.2.0",
- "from": "merge@>=1.2.0 <2.0.0",
+ "from": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz",
"resolved": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz"
}
}
},
"find-root": {
"version": "1.0.0",
- "from": "find-root@1.0.0",
+ "from": "https://registry.npmjs.org/find-root/-/find-root-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/find-root/-/find-root-1.0.0.tgz"
},
"glob": {
"version": "7.0.5",
- "from": "glob@7.0.5",
+ "from": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz",
"dependencies": {
"fs.realpath": {
"version": "1.0.0",
- "from": "fs.realpath@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
},
"inflight": {
"version": "1.0.5",
- "from": "inflight@>=1.0.4 <2.0.0",
+ "from": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz",
"dependencies": {
"wrappy": {
"version": "1.0.2",
- "from": "wrappy@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
}
}
},
"inherits": {
"version": "2.0.1",
- "from": "inherits@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
},
"minimatch": {
"version": "3.0.2",
- "from": "minimatch@>=3.0.2 <4.0.0",
+ "from": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz",
"dependencies": {
"brace-expansion": {
"version": "1.1.6",
- "from": "brace-expansion@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz",
"dependencies": {
"balanced-match": {
"version": "0.4.2",
- "from": "balanced-match@>=0.4.1 <0.5.0",
+ "from": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz"
},
"concat-map": {
"version": "0.0.1",
- "from": "concat-map@0.0.1",
+ "from": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
}
}
@@ -3735,68 +3735,68 @@
},
"once": {
"version": "1.3.3",
- "from": "once@>=1.3.0 <2.0.0",
+ "from": "https://registry.npmjs.org/once/-/once-1.3.3.tgz",
"resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz",
"dependencies": {
"wrappy": {
"version": "1.0.2",
- "from": "wrappy@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
}
}
},
"path-is-absolute": {
"version": "1.0.0",
- "from": "path-is-absolute@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz"
}
}
},
"home-or-tmp": {
"version": "2.0.0",
- "from": "home-or-tmp@2.0.0",
+ "from": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz",
"dependencies": {
"os-homedir": {
"version": "1.0.1",
- "from": "os-homedir@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.1.tgz"
},
"os-tmpdir": {
"version": "1.0.1",
- "from": "os-tmpdir@>=1.0.1 <2.0.0",
+ "from": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.1.tgz"
}
}
},
"inquirer": {
"version": "1.1.2",
- "from": "inquirer@1.1.2",
+ "from": "https://registry.npmjs.org/inquirer/-/inquirer-1.1.2.tgz",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-1.1.2.tgz",
"dependencies": {
"ansi-escapes": {
"version": "1.4.0",
- "from": "ansi-escapes@>=1.1.0 <2.0.0",
+ "from": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz"
},
"cli-cursor": {
"version": "1.0.2",
- "from": "cli-cursor@>=1.0.1 <2.0.0",
+ "from": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
"dependencies": {
"restore-cursor": {
"version": "1.0.1",
- "from": "restore-cursor@>=1.0.1 <2.0.0",
+ "from": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
"dependencies": {
"exit-hook": {
"version": "1.1.1",
- "from": "exit-hook@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz",
"resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz"
},
"onetime": {
"version": "1.1.0",
- "from": "onetime@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz"
}
}
@@ -3805,67 +3805,67 @@
},
"cli-width": {
"version": "2.1.0",
- "from": "cli-width@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz",
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz"
},
"external-editor": {
"version": "1.0.3",
- "from": "external-editor@>=1.0.1 <2.0.0",
+ "from": "https://registry.npmjs.org/external-editor/-/external-editor-1.0.3.tgz",
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-1.0.3.tgz",
"dependencies": {
"extend": {
"version": "3.0.0",
- "from": "extend@>=3.0.0 <4.0.0",
+ "from": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz"
},
"spawn-sync": {
"version": "1.0.15",
- "from": "spawn-sync@>=1.0.15 <2.0.0",
+ "from": "https://registry.npmjs.org/spawn-sync/-/spawn-sync-1.0.15.tgz",
"resolved": "https://registry.npmjs.org/spawn-sync/-/spawn-sync-1.0.15.tgz",
"dependencies": {
"concat-stream": {
"version": "1.5.1",
- "from": "concat-stream@>=1.4.7 <2.0.0",
+ "from": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.1.tgz",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.1.tgz",
"dependencies": {
"inherits": {
"version": "2.0.1",
- "from": "inherits@>=2.0.1 <2.1.0",
+ "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
},
"typedarray": {
"version": "0.0.6",
- "from": "typedarray@>=0.0.5 <0.1.0",
+ "from": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz"
},
"readable-stream": {
"version": "2.0.6",
- "from": "readable-stream@>=2.0.0 <2.1.0",
+ "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
"dependencies": {
"core-util-is": {
"version": "1.0.2",
- "from": "core-util-is@>=1.0.0 <1.1.0",
+ "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz"
},
"isarray": {
"version": "1.0.0",
- "from": "isarray@>=1.0.0 <1.1.0",
+ "from": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz"
},
"process-nextick-args": {
"version": "1.0.7",
- "from": "process-nextick-args@>=1.0.6 <1.1.0",
+ "from": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz"
},
"string_decoder": {
"version": "0.10.31",
- "from": "string_decoder@>=0.10.0 <0.11.0",
+ "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz"
},
"util-deprecate": {
"version": "1.0.2",
- "from": "util-deprecate@>=1.0.1 <1.1.0",
+ "from": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
}
}
@@ -3874,24 +3874,24 @@
},
"os-shim": {
"version": "0.1.3",
- "from": "os-shim@>=0.1.2 <0.2.0",
+ "from": "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz",
"resolved": "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz"
}
}
},
"temp": {
"version": "0.8.3",
- "from": "temp@>=0.8.3 <0.9.0",
+ "from": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz",
"resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz",
"dependencies": {
"os-tmpdir": {
"version": "1.0.1",
- "from": "os-tmpdir@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.1.tgz"
},
"rimraf": {
"version": "2.2.8",
- "from": "rimraf@>=2.2.6 <2.3.0",
+ "from": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz"
}
}
@@ -3900,80 +3900,80 @@
},
"figures": {
"version": "1.7.0",
- "from": "figures@>=1.3.5 <2.0.0",
+ "from": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
"resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
"dependencies": {
"escape-string-regexp": {
"version": "1.0.5",
- "from": "escape-string-regexp@>=1.0.5 <2.0.0",
+ "from": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
},
"object-assign": {
"version": "4.1.0",
- "from": "object-assign@>=4.1.0 <5.0.0",
+ "from": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz"
}
}
},
"mute-stream": {
"version": "0.0.6",
- "from": "mute-stream@0.0.6",
+ "from": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.6.tgz",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.6.tgz"
},
"pinkie-promise": {
"version": "2.0.1",
- "from": "pinkie-promise@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
"dependencies": {
"pinkie": {
"version": "2.0.4",
- "from": "pinkie@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
"resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz"
}
}
},
"run-async": {
"version": "2.2.0",
- "from": "run-async@>=2.2.0 <3.0.0",
+ "from": "https://registry.npmjs.org/run-async/-/run-async-2.2.0.tgz",
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.2.0.tgz",
"dependencies": {
"is-promise": {
"version": "2.1.0",
- "from": "is-promise@>=2.1.0 <3.0.0",
+ "from": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz"
}
}
},
"rx": {
"version": "4.1.0",
- "from": "rx@>=4.1.0 <5.0.0",
+ "from": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz",
"resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz"
},
"string-width": {
"version": "1.0.1",
- "from": "string-width@>=1.0.1 <2.0.0",
+ "from": "https://registry.npmjs.org/string-width/-/string-width-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.1.tgz",
"dependencies": {
"code-point-at": {
"version": "1.0.0",
- "from": "code-point-at@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz",
"dependencies": {
"number-is-nan": {
"version": "1.0.0",
- "from": "number-is-nan@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz"
}
}
},
"is-fullwidth-code-point": {
"version": "1.0.0",
- "from": "is-fullwidth-code-point@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"dependencies": {
"number-is-nan": {
"version": "1.0.0",
- "from": "number-is-nan@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz"
}
}
@@ -3982,46 +3982,46 @@
},
"strip-ansi": {
"version": "3.0.1",
- "from": "strip-ansi@>=3.0.0 <4.0.0",
+ "from": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"dependencies": {
"ansi-regex": {
"version": "2.0.0",
- "from": "ansi-regex@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz"
}
}
},
"through": {
"version": "2.3.8",
- "from": "through@>=2.3.6 <3.0.0",
+ "from": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz"
}
}
},
"lodash": {
"version": "4.14.1",
- "from": "lodash@4.14.1",
+ "from": "https://registry.npmjs.org/lodash/-/lodash-4.14.1.tgz",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.14.1.tgz"
},
"minimist": {
"version": "1.2.0",
- "from": "minimist@1.2.0",
+ "from": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz"
},
"path-exists": {
"version": "2.1.0",
- "from": "path-exists@2.1.0",
+ "from": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
"dependencies": {
"pinkie-promise": {
"version": "2.0.1",
- "from": "pinkie-promise@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
"dependencies": {
"pinkie": {
"version": "2.0.4",
- "from": "pinkie@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
"resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz"
}
}
@@ -4030,16 +4030,52 @@
},
"shelljs": {
"version": "0.5.3",
- "from": "shelljs@0.5.3",
+ "from": "https://registry.npmjs.org/shelljs/-/shelljs-0.5.3.tgz",
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.5.3.tgz"
},
"strip-json-comments": {
"version": "2.0.1",
- "from": "strip-json-comments@2.0.1",
+ "from": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz"
}
}
},
+ "cross-spawn": {
+ "version": "4.0.0",
+ "from": "cross-spawn@latest",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.0.tgz",
+ "dependencies": {
+ "lru-cache": {
+ "version": "4.0.1",
+ "from": "lru-cache@>=4.0.1 <5.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.1.tgz",
+ "dependencies": {
+ "pseudomap": {
+ "version": "1.0.2",
+ "from": "pseudomap@>=1.0.1 <2.0.0",
+ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz"
+ },
+ "yallist": {
+ "version": "2.0.0",
+ "from": "yallist@>=2.0.0 <3.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.0.0.tgz"
+ }
+ }
+ },
+ "which": {
+ "version": "1.2.10",
+ "from": "which@>=1.2.9 <2.0.0",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.2.10.tgz",
+ "dependencies": {
+ "isexe": {
+ "version": "1.1.2",
+ "from": "isexe@>=1.1.1 <2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-1.1.2.tgz"
+ }
+ }
+ }
+ }
+ },
"cz-conventional-changelog": {
"version": "1.1.4",
"from": "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-1.1.4.tgz",
@@ -4145,22 +4181,22 @@
},
"dgeni-packages": {
"version": "0.14.0",
- "from": "dgeni-packages@>=0.14.0 <0.15.0",
+ "from": "https://registry.npmjs.org/dgeni-packages/-/dgeni-packages-0.14.0.tgz",
"resolved": "https://registry.npmjs.org/dgeni-packages/-/dgeni-packages-0.14.0.tgz",
"dependencies": {
"catharsis": {
"version": "0.8.8",
- "from": "catharsis@>=0.8.1 <0.9.0",
+ "from": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.8.tgz",
"resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.8.tgz",
"dependencies": {
"underscore-contrib": {
"version": "0.3.0",
- "from": "underscore-contrib@>=0.3.0 <0.4.0",
+ "from": "https://registry.npmjs.org/underscore-contrib/-/underscore-contrib-0.3.0.tgz",
"resolved": "https://registry.npmjs.org/underscore-contrib/-/underscore-contrib-0.3.0.tgz",
"dependencies": {
"underscore": {
"version": "1.6.0",
- "from": "underscore@1.6.0",
+ "from": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz"
}
}
@@ -4169,185 +4205,185 @@
},
"change-case": {
"version": "3.0.0",
- "from": "change-case@3.0.0",
+ "from": "https://registry.npmjs.org/change-case/-/change-case-3.0.0.tgz",
"resolved": "https://registry.npmjs.org/change-case/-/change-case-3.0.0.tgz",
"dependencies": {
"camel-case": {
"version": "3.0.0",
- "from": "camel-case@>=3.0.0 <4.0.0",
+ "from": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz",
"resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz"
},
"constant-case": {
"version": "2.0.0",
- "from": "constant-case@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/constant-case/-/constant-case-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/constant-case/-/constant-case-2.0.0.tgz"
},
"dot-case": {
"version": "2.1.0",
- "from": "dot-case@>=2.1.0 <3.0.0",
+ "from": "https://registry.npmjs.org/dot-case/-/dot-case-2.1.0.tgz",
"resolved": "https://registry.npmjs.org/dot-case/-/dot-case-2.1.0.tgz"
},
"header-case": {
"version": "1.0.0",
- "from": "header-case@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/header-case/-/header-case-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/header-case/-/header-case-1.0.0.tgz"
},
"is-lower-case": {
"version": "1.1.3",
- "from": "is-lower-case@>=1.1.0 <2.0.0",
+ "from": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-1.1.3.tgz",
"resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-1.1.3.tgz"
},
"is-upper-case": {
"version": "1.1.2",
- "from": "is-upper-case@>=1.1.0 <2.0.0",
+ "from": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-1.1.2.tgz",
"resolved": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-1.1.2.tgz"
},
"lower-case": {
"version": "1.1.3",
- "from": "lower-case@>=1.1.1 <2.0.0",
+ "from": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.3.tgz",
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.3.tgz"
},
"lower-case-first": {
"version": "1.0.2",
- "from": "lower-case-first@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/lower-case-first/-/lower-case-first-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/lower-case-first/-/lower-case-first-1.0.2.tgz"
},
"no-case": {
"version": "2.3.0",
- "from": "no-case@>=2.2.0 <3.0.0",
+ "from": "https://registry.npmjs.org/no-case/-/no-case-2.3.0.tgz",
"resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.0.tgz"
},
"param-case": {
"version": "2.1.0",
- "from": "param-case@>=2.1.0 <3.0.0",
+ "from": "https://registry.npmjs.org/param-case/-/param-case-2.1.0.tgz",
"resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.0.tgz"
},
"pascal-case": {
"version": "2.0.0",
- "from": "pascal-case@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/pascal-case/-/pascal-case-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-2.0.0.tgz"
},
"path-case": {
"version": "2.1.0",
- "from": "path-case@>=2.1.0 <3.0.0",
+ "from": "https://registry.npmjs.org/path-case/-/path-case-2.1.0.tgz",
"resolved": "https://registry.npmjs.org/path-case/-/path-case-2.1.0.tgz"
},
"sentence-case": {
"version": "2.1.0",
- "from": "sentence-case@>=2.1.0 <3.0.0",
+ "from": "https://registry.npmjs.org/sentence-case/-/sentence-case-2.1.0.tgz",
"resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-2.1.0.tgz"
},
"snake-case": {
"version": "2.1.0",
- "from": "snake-case@>=2.1.0 <3.0.0",
+ "from": "https://registry.npmjs.org/snake-case/-/snake-case-2.1.0.tgz",
"resolved": "https://registry.npmjs.org/snake-case/-/snake-case-2.1.0.tgz"
},
"swap-case": {
"version": "1.1.2",
- "from": "swap-case@>=1.1.0 <2.0.0",
+ "from": "https://registry.npmjs.org/swap-case/-/swap-case-1.1.2.tgz",
"resolved": "https://registry.npmjs.org/swap-case/-/swap-case-1.1.2.tgz"
},
"title-case": {
"version": "2.1.0",
- "from": "title-case@>=2.1.0 <3.0.0",
+ "from": "https://registry.npmjs.org/title-case/-/title-case-2.1.0.tgz",
"resolved": "https://registry.npmjs.org/title-case/-/title-case-2.1.0.tgz"
},
"upper-case": {
"version": "1.1.3",
- "from": "upper-case@>=1.1.1 <2.0.0",
+ "from": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
"resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz"
},
"upper-case-first": {
"version": "1.1.2",
- "from": "upper-case-first@>=1.1.0 <2.0.0",
+ "from": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-1.1.2.tgz",
"resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-1.1.2.tgz"
}
}
},
"espree": {
"version": "2.2.5",
- "from": "espree@>=2.2.3 <3.0.0",
+ "from": "https://registry.npmjs.org/espree/-/espree-2.2.5.tgz",
"resolved": "https://registry.npmjs.org/espree/-/espree-2.2.5.tgz"
},
"estraverse": {
"version": "4.2.0",
- "from": "estraverse@>=4.1.0 <5.0.0",
+ "from": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz"
},
"glob": {
"version": "7.0.5",
- "from": "glob@>=7.0.5 <8.0.0",
+ "from": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz",
"dependencies": {
"fs.realpath": {
"version": "1.0.0",
- "from": "fs.realpath@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
},
"inflight": {
"version": "1.0.5",
- "from": "inflight@>=1.0.4 <2.0.0",
+ "from": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz",
"dependencies": {
"wrappy": {
"version": "1.0.2",
- "from": "wrappy@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
}
}
},
"inherits": {
"version": "2.0.1",
- "from": "inherits@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
},
"once": {
"version": "1.3.3",
- "from": "once@>=1.3.0 <2.0.0",
+ "from": "https://registry.npmjs.org/once/-/once-1.3.3.tgz",
"resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz",
"dependencies": {
"wrappy": {
"version": "1.0.2",
- "from": "wrappy@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
}
}
},
"path-is-absolute": {
"version": "1.0.0",
- "from": "path-is-absolute@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz"
}
}
},
"htmlparser2": {
"version": "3.9.1",
- "from": "htmlparser2@>=3.7.3 <4.0.0",
+ "from": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.1.tgz",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.1.tgz",
"dependencies": {
"domelementtype": {
"version": "1.3.0",
- "from": "domelementtype@>=1.3.0 <2.0.0",
+ "from": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz"
},
"domhandler": {
"version": "2.3.0",
- "from": "domhandler@>=2.3.0 <3.0.0",
+ "from": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz"
},
"domutils": {
"version": "1.5.1",
- "from": "domutils@>=1.5.1 <2.0.0",
+ "from": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
"dependencies": {
"dom-serializer": {
"version": "0.1.0",
- "from": "dom-serializer@>=0.0.0 <1.0.0",
+ "from": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
"dependencies": {
"domelementtype": {
"version": "1.1.3",
- "from": "domelementtype@>=1.1.1 <1.2.0",
+ "from": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz"
}
}
@@ -4356,47 +4392,47 @@
},
"entities": {
"version": "1.1.1",
- "from": "entities@>=1.1.1 <2.0.0",
+ "from": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz",
"resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz"
},
"inherits": {
"version": "2.0.1",
- "from": "inherits@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
},
"readable-stream": {
"version": "2.1.4",
- "from": "readable-stream@>=2.0.2 <3.0.0",
+ "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.4.tgz",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.4.tgz",
"dependencies": {
"buffer-shims": {
"version": "1.0.0",
- "from": "buffer-shims@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz"
},
"core-util-is": {
"version": "1.0.2",
- "from": "core-util-is@>=1.0.0 <1.1.0",
+ "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz"
},
"isarray": {
"version": "1.0.0",
- "from": "isarray@>=1.0.0 <1.1.0",
+ "from": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz"
},
"process-nextick-args": {
"version": "1.0.7",
- "from": "process-nextick-args@>=1.0.6 <1.1.0",
+ "from": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz"
},
"string_decoder": {
"version": "0.10.31",
- "from": "string_decoder@>=0.10.0 <0.11.0",
+ "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz"
},
"util-deprecate": {
"version": "1.0.2",
- "from": "util-deprecate@>=1.0.1 <1.1.0",
+ "from": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
}
}
@@ -4405,27 +4441,27 @@
},
"lodash": {
"version": "4.14.1",
- "from": "lodash@>=4.13.1 <5.0.0",
+ "from": "https://registry.npmjs.org/lodash/-/lodash-4.14.1.tgz",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.14.1.tgz"
},
"minimatch": {
"version": "3.0.2",
- "from": "minimatch@>=3.0.2 <4.0.0",
+ "from": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz",
"dependencies": {
"brace-expansion": {
"version": "1.1.6",
- "from": "brace-expansion@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz",
"dependencies": {
"balanced-match": {
"version": "0.4.2",
- "from": "balanced-match@>=0.4.1 <0.5.0",
+ "from": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz"
},
"concat-map": {
"version": "0.0.1",
- "from": "concat-map@0.0.1",
+ "from": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
}
}
@@ -4434,81 +4470,81 @@
},
"nunjucks": {
"version": "1.3.4",
- "from": "nunjucks@>=1.2.0 <2.0.0",
+ "from": "https://registry.npmjs.org/nunjucks/-/nunjucks-1.3.4.tgz",
"resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-1.3.4.tgz",
"dependencies": {
"optimist": {
"version": "0.6.1",
- "from": "optimist@*",
+ "from": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
"resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
"dependencies": {
"wordwrap": {
"version": "0.0.3",
- "from": "wordwrap@>=0.0.2 <0.1.0",
+ "from": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz"
},
"minimist": {
"version": "0.0.10",
- "from": "minimist@>=0.0.1 <0.1.0",
+ "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz"
}
}
},
"chokidar": {
"version": "0.12.6",
- "from": "chokidar@>=0.12.5 <0.13.0",
+ "from": "https://registry.npmjs.org/chokidar/-/chokidar-0.12.6.tgz",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-0.12.6.tgz",
"dependencies": {
"readdirp": {
"version": "1.3.0",
- "from": "readdirp@>=1.3.0 <1.4.0",
+ "from": "https://registry.npmjs.org/readdirp/-/readdirp-1.3.0.tgz",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-1.3.0.tgz",
"dependencies": {
"graceful-fs": {
"version": "2.0.3",
- "from": "graceful-fs@>=2.0.0 <2.1.0",
+ "from": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz"
},
"minimatch": {
"version": "0.2.14",
- "from": "minimatch@>=0.2.12 <0.3.0",
+ "from": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz",
"dependencies": {
"lru-cache": {
"version": "2.7.3",
- "from": "lru-cache@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz"
},
"sigmund": {
"version": "1.0.1",
- "from": "sigmund@>=1.0.0 <1.1.0",
+ "from": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz"
}
}
},
"readable-stream": {
"version": "1.0.34",
- "from": "readable-stream@>=1.0.26-2 <1.1.0",
+ "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
"dependencies": {
"core-util-is": {
"version": "1.0.2",
- "from": "core-util-is@>=1.0.0 <1.1.0",
+ "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz"
},
"isarray": {
"version": "0.0.1",
- "from": "isarray@0.0.1",
+ "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz"
},
"string_decoder": {
"version": "0.10.31",
- "from": "string_decoder@>=0.10.0 <0.11.0",
+ "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz"
},
"inherits": {
"version": "2.0.1",
- "from": "inherits@>=2.0.1 <2.1.0",
+ "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
}
}
@@ -4517,20 +4553,8 @@
},
"async-each": {
"version": "0.1.6",
- "from": "async-each@>=0.1.5 <0.2.0",
+ "from": "https://registry.npmjs.org/async-each/-/async-each-0.1.6.tgz",
"resolved": "https://registry.npmjs.org/async-each/-/async-each-0.1.6.tgz"
- },
- "fsevents": {
- "version": "0.3.8",
- "from": "fsevents@>=0.3.1 <0.4.0",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-0.3.8.tgz",
- "dependencies": {
- "nan": {
- "version": "2.4.0",
- "from": "nan@>=2.0.2 <3.0.0",
- "resolved": "https://registry.npmjs.org/nan/-/nan-2.4.0.tgz"
- }
- }
}
}
}
@@ -4538,32 +4562,32 @@
},
"q": {
"version": "1.4.1",
- "from": "q@>=1.4.1 <1.5.0",
+ "from": "https://registry.npmjs.org/q/-/q-1.4.1.tgz",
"resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz"
},
"semver": {
"version": "5.3.0",
- "from": "semver@>=5.2.0 <6.0.0",
+ "from": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz"
},
"shelljs": {
"version": "0.7.3",
- "from": "shelljs@>=0.7.0 <0.8.0",
+ "from": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.3.tgz",
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.3.tgz",
"dependencies": {
"interpret": {
"version": "1.0.1",
- "from": "interpret@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/interpret/-/interpret-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.1.tgz"
},
"rechoir": {
"version": "0.6.2",
- "from": "rechoir@>=0.6.2 <0.7.0",
+ "from": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
"dependencies": {
"resolve": {
"version": "1.1.7",
- "from": "resolve@>=1.1.6 <2.0.0",
+ "from": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz"
}
}
@@ -4572,12 +4596,12 @@
},
"spdx-license-list": {
"version": "2.1.0",
- "from": "spdx-license-list@>=2.1.0 <3.0.0",
+ "from": "https://registry.npmjs.org/spdx-license-list/-/spdx-license-list-2.1.0.tgz",
"resolved": "https://registry.npmjs.org/spdx-license-list/-/spdx-license-list-2.1.0.tgz"
},
"typescript": {
"version": "1.8.10",
- "from": "typescript@>=1.7.5 <2.0.0",
+ "from": "https://registry.npmjs.org/typescript/-/typescript-1.8.10.tgz",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-1.8.10.tgz"
}
}
@@ -6080,103 +6104,103 @@
},
"grunt-eslint": {
"version": "19.0.0",
- "from": "grunt-eslint@latest",
+ "from": "https://registry.npmjs.org/grunt-eslint/-/grunt-eslint-19.0.0.tgz",
"resolved": "https://registry.npmjs.org/grunt-eslint/-/grunt-eslint-19.0.0.tgz",
"dependencies": {
"chalk": {
"version": "1.1.3",
- "from": "chalk@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"dependencies": {
"ansi-styles": {
"version": "2.2.1",
- "from": "ansi-styles@>=2.2.1 <3.0.0",
+ "from": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz"
},
"escape-string-regexp": {
"version": "1.0.5",
- "from": "escape-string-regexp@>=1.0.2 <2.0.0",
+ "from": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
},
"has-ansi": {
"version": "2.0.0",
- "from": "has-ansi@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
"dependencies": {
"ansi-regex": {
"version": "2.0.0",
- "from": "ansi-regex@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz"
}
}
},
"strip-ansi": {
"version": "3.0.1",
- "from": "strip-ansi@>=3.0.0 <4.0.0",
+ "from": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"dependencies": {
"ansi-regex": {
"version": "2.0.0",
- "from": "ansi-regex@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz"
}
}
},
"supports-color": {
"version": "2.0.0",
- "from": "supports-color@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz"
}
}
},
"eslint": {
"version": "3.2.2",
- "from": "eslint@>=3.0.0 <4.0.0",
+ "from": "https://registry.npmjs.org/eslint/-/eslint-3.2.2.tgz",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-3.2.2.tgz",
"dependencies": {
"concat-stream": {
"version": "1.5.1",
- "from": "concat-stream@>=1.4.6 <2.0.0",
+ "from": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.1.tgz",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.1.tgz",
"dependencies": {
"inherits": {
"version": "2.0.1",
- "from": "inherits@>=2.0.1 <2.1.0",
+ "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
},
"typedarray": {
"version": "0.0.6",
- "from": "typedarray@>=0.0.5 <0.1.0",
+ "from": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz"
},
"readable-stream": {
"version": "2.0.6",
- "from": "readable-stream@>=2.0.0 <2.1.0",
+ "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
"dependencies": {
"core-util-is": {
"version": "1.0.2",
- "from": "core-util-is@>=1.0.0 <1.1.0",
+ "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz"
},
"isarray": {
"version": "1.0.0",
- "from": "isarray@>=1.0.0 <1.1.0",
+ "from": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz"
},
"process-nextick-args": {
"version": "1.0.7",
- "from": "process-nextick-args@>=1.0.6 <1.1.0",
+ "from": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz"
},
"string_decoder": {
"version": "0.10.31",
- "from": "string_decoder@>=0.10.0 <0.11.0",
+ "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz"
},
"util-deprecate": {
"version": "1.0.2",
- "from": "util-deprecate@>=1.0.1 <1.1.0",
+ "from": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
}
}
@@ -6185,115 +6209,115 @@
},
"debug": {
"version": "2.2.0",
- "from": "debug@>=2.1.1 <3.0.0",
+ "from": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
"dependencies": {
"ms": {
"version": "0.7.1",
- "from": "ms@0.7.1",
+ "from": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
"resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz"
}
}
},
"doctrine": {
"version": "1.2.2",
- "from": "doctrine@>=1.2.2 <2.0.0",
+ "from": "https://registry.npmjs.org/doctrine/-/doctrine-1.2.2.tgz",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.2.2.tgz",
"dependencies": {
"esutils": {
"version": "1.1.6",
- "from": "esutils@>=1.1.6 <2.0.0",
+ "from": "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz"
},
"isarray": {
"version": "1.0.0",
- "from": "isarray@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz"
}
}
},
"escope": {
"version": "3.6.0",
- "from": "escope@>=3.6.0 <4.0.0",
+ "from": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz",
"resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz",
"dependencies": {
"es6-map": {
"version": "0.1.4",
- "from": "es6-map@>=0.1.3 <0.2.0",
+ "from": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.4.tgz",
"resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.4.tgz",
"dependencies": {
"d": {
"version": "0.1.1",
- "from": "d@>=0.1.1 <0.2.0",
+ "from": "https://registry.npmjs.org/d/-/d-0.1.1.tgz",
"resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz"
},
"es5-ext": {
"version": "0.10.12",
- "from": "es5-ext@>=0.10.8 <0.11.0",
+ "from": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.12.tgz",
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.12.tgz"
},
"es6-iterator": {
"version": "2.0.0",
- "from": "es6-iterator@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.0.tgz"
},
"es6-set": {
"version": "0.1.4",
- "from": "es6-set@>=0.1.3 <0.2.0",
+ "from": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.4.tgz",
"resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.4.tgz"
},
"es6-symbol": {
"version": "3.1.0",
- "from": "es6-symbol@>=3.1.0 <3.2.0",
+ "from": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.0.tgz",
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.0.tgz"
},
"event-emitter": {
"version": "0.3.4",
- "from": "event-emitter@>=0.3.4 <0.4.0",
+ "from": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.4.tgz",
"resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.4.tgz"
}
}
},
"es6-weak-map": {
"version": "2.0.1",
- "from": "es6-weak-map@>=2.0.1 <3.0.0",
+ "from": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.1.tgz",
"dependencies": {
"d": {
"version": "0.1.1",
- "from": "d@>=0.1.1 <0.2.0",
+ "from": "https://registry.npmjs.org/d/-/d-0.1.1.tgz",
"resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz"
},
"es5-ext": {
"version": "0.10.12",
- "from": "es5-ext@>=0.10.8 <0.11.0",
+ "from": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.12.tgz",
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.12.tgz"
},
"es6-iterator": {
"version": "2.0.0",
- "from": "es6-iterator@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.0.tgz"
},
"es6-symbol": {
"version": "3.1.0",
- "from": "es6-symbol@>=3.1.0 <3.2.0",
+ "from": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.0.tgz",
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.0.tgz"
}
}
},
"esrecurse": {
"version": "4.1.0",
- "from": "esrecurse@>=4.1.0 <5.0.0",
+ "from": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.1.0.tgz",
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.1.0.tgz",
"dependencies": {
"estraverse": {
"version": "4.1.1",
- "from": "estraverse@>=4.1.0 <4.2.0",
+ "from": "https://registry.npmjs.org/estraverse/-/estraverse-4.1.1.tgz",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.1.1.tgz"
},
"object-assign": {
"version": "4.1.0",
- "from": "object-assign@>=4.0.1 <5.0.0",
+ "from": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz"
}
}
@@ -6302,180 +6326,180 @@
},
"espree": {
"version": "3.1.7",
- "from": "espree@>=3.1.6 <4.0.0",
+ "from": "https://registry.npmjs.org/espree/-/espree-3.1.7.tgz",
"resolved": "https://registry.npmjs.org/espree/-/espree-3.1.7.tgz",
"dependencies": {
"acorn": {
"version": "3.3.0",
- "from": "acorn@>=3.3.0 <4.0.0",
+ "from": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz"
},
"acorn-jsx": {
"version": "3.0.1",
- "from": "acorn-jsx@>=3.0.0 <4.0.0",
+ "from": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz"
}
}
},
"estraverse": {
"version": "4.2.0",
- "from": "estraverse@>=4.2.0 <5.0.0",
+ "from": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz"
},
"esutils": {
"version": "2.0.2",
- "from": "esutils@>=2.0.2 <3.0.0",
+ "from": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz"
},
"file-entry-cache": {
"version": "1.3.1",
- "from": "file-entry-cache@>=1.3.1 <2.0.0",
+ "from": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-1.3.1.tgz",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-1.3.1.tgz",
"dependencies": {
"flat-cache": {
"version": "1.2.1",
- "from": "flat-cache@>=1.2.1 <2.0.0",
+ "from": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.1.tgz",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.1.tgz",
"dependencies": {
"circular-json": {
"version": "0.3.1",
- "from": "circular-json@>=0.3.0 <0.4.0",
+ "from": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.1.tgz",
"resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.1.tgz"
},
"del": {
"version": "2.2.1",
- "from": "del@>=2.0.2 <3.0.0",
+ "from": "https://registry.npmjs.org/del/-/del-2.2.1.tgz",
"resolved": "https://registry.npmjs.org/del/-/del-2.2.1.tgz",
"dependencies": {
"globby": {
"version": "5.0.0",
- "from": "globby@>=5.0.0 <6.0.0",
+ "from": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
"resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
"dependencies": {
"array-union": {
"version": "1.0.2",
- "from": "array-union@>=1.0.1 <2.0.0",
+ "from": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
"dependencies": {
"array-uniq": {
"version": "1.0.3",
- "from": "array-uniq@>=1.0.1 <2.0.0",
+ "from": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
"resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz"
}
}
},
"arrify": {
"version": "1.0.1",
- "from": "arrify@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz"
}
}
},
"is-path-cwd": {
"version": "1.0.0",
- "from": "is-path-cwd@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz"
},
"is-path-in-cwd": {
"version": "1.0.0",
- "from": "is-path-in-cwd@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz",
"dependencies": {
"is-path-inside": {
"version": "1.0.0",
- "from": "is-path-inside@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz"
}
}
},
"pify": {
"version": "2.3.0",
- "from": "pify@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz"
},
"pinkie-promise": {
"version": "2.0.1",
- "from": "pinkie-promise@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
"dependencies": {
"pinkie": {
"version": "2.0.4",
- "from": "pinkie@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
"resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz"
}
}
},
"rimraf": {
"version": "2.5.4",
- "from": "rimraf@>=2.2.8 <3.0.0",
+ "from": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz"
}
}
},
"graceful-fs": {
"version": "4.1.5",
- "from": "graceful-fs@>=4.1.2 <5.0.0",
+ "from": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.5.tgz",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.5.tgz"
},
"write": {
"version": "0.2.1",
- "from": "write@>=0.2.1 <0.3.0",
+ "from": "https://registry.npmjs.org/write/-/write-0.2.1.tgz",
"resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz"
}
}
},
"object-assign": {
"version": "4.1.0",
- "from": "object-assign@>=4.0.1 <5.0.0",
+ "from": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz"
}
}
},
"glob": {
"version": "7.0.5",
- "from": "glob@>=7.0.3 <8.0.0",
+ "from": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz",
"dependencies": {
"fs.realpath": {
"version": "1.0.0",
- "from": "fs.realpath@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
},
"inflight": {
"version": "1.0.5",
- "from": "inflight@>=1.0.4 <2.0.0",
+ "from": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz",
"dependencies": {
"wrappy": {
"version": "1.0.2",
- "from": "wrappy@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
}
}
},
"inherits": {
"version": "2.0.1",
- "from": "inherits@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
},
"minimatch": {
"version": "3.0.2",
- "from": "minimatch@>=3.0.2 <4.0.0",
+ "from": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz",
"dependencies": {
"brace-expansion": {
"version": "1.1.6",
- "from": "brace-expansion@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz",
"dependencies": {
"balanced-match": {
"version": "0.4.2",
- "from": "balanced-match@>=0.4.1 <0.5.0",
+ "from": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz"
},
"concat-map": {
"version": "0.0.1",
- "from": "concat-map@0.0.1",
+ "from": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
}
}
@@ -6484,71 +6508,71 @@
},
"once": {
"version": "1.3.3",
- "from": "once@>=1.3.0 <2.0.0",
+ "from": "https://registry.npmjs.org/once/-/once-1.3.3.tgz",
"resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz",
"dependencies": {
"wrappy": {
"version": "1.0.2",
- "from": "wrappy@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
}
}
},
"path-is-absolute": {
"version": "1.0.0",
- "from": "path-is-absolute@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz"
}
}
},
"globals": {
"version": "9.9.0",
- "from": "globals@>=9.2.0 <10.0.0",
+ "from": "https://registry.npmjs.org/globals/-/globals-9.9.0.tgz",
"resolved": "https://registry.npmjs.org/globals/-/globals-9.9.0.tgz"
},
"ignore": {
"version": "3.1.3",
- "from": "ignore@>=3.1.2 <4.0.0",
+ "from": "https://registry.npmjs.org/ignore/-/ignore-3.1.3.tgz",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-3.1.3.tgz"
},
"imurmurhash": {
"version": "0.1.4",
- "from": "imurmurhash@>=0.1.4 <0.2.0",
+ "from": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz"
},
"inquirer": {
"version": "0.12.0",
- "from": "inquirer@>=0.12.0 <0.13.0",
+ "from": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz",
"dependencies": {
"ansi-escapes": {
"version": "1.4.0",
- "from": "ansi-escapes@>=1.1.0 <2.0.0",
+ "from": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz"
},
"ansi-regex": {
"version": "2.0.0",
- "from": "ansi-regex@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz"
},
"cli-cursor": {
"version": "1.0.2",
- "from": "cli-cursor@>=1.0.1 <2.0.0",
+ "from": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
"dependencies": {
"restore-cursor": {
"version": "1.0.1",
- "from": "restore-cursor@>=1.0.1 <2.0.0",
+ "from": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
"dependencies": {
"exit-hook": {
"version": "1.1.1",
- "from": "exit-hook@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz",
"resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz"
},
"onetime": {
"version": "1.1.0",
- "from": "onetime@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz"
}
}
@@ -6557,75 +6581,75 @@
},
"cli-width": {
"version": "2.1.0",
- "from": "cli-width@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz",
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz"
},
"figures": {
"version": "1.7.0",
- "from": "figures@>=1.3.5 <2.0.0",
+ "from": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
"resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
"dependencies": {
"escape-string-regexp": {
"version": "1.0.5",
- "from": "escape-string-regexp@>=1.0.5 <2.0.0",
+ "from": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
},
"object-assign": {
"version": "4.1.0",
- "from": "object-assign@>=4.1.0 <5.0.0",
+ "from": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz"
}
}
},
"readline2": {
"version": "1.0.1",
- "from": "readline2@>=1.0.1 <2.0.0",
+ "from": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz",
"dependencies": {
"code-point-at": {
"version": "1.0.0",
- "from": "code-point-at@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz",
"dependencies": {
"number-is-nan": {
"version": "1.0.0",
- "from": "number-is-nan@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz"
}
}
},
"is-fullwidth-code-point": {
"version": "1.0.0",
- "from": "is-fullwidth-code-point@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"dependencies": {
"number-is-nan": {
"version": "1.0.0",
- "from": "number-is-nan@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz"
}
}
},
"mute-stream": {
"version": "0.0.5",
- "from": "mute-stream@0.0.5",
+ "from": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz"
}
}
},
"run-async": {
"version": "0.1.0",
- "from": "run-async@>=0.1.0 <0.2.0",
+ "from": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz",
"resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz",
"dependencies": {
"once": {
"version": "1.3.3",
- "from": "once@>=1.3.0 <2.0.0",
+ "from": "https://registry.npmjs.org/once/-/once-1.3.3.tgz",
"resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz",
"dependencies": {
"wrappy": {
"version": "1.0.2",
- "from": "wrappy@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
}
}
@@ -6634,34 +6658,34 @@
},
"rx-lite": {
"version": "3.1.2",
- "from": "rx-lite@>=3.1.2 <4.0.0",
+ "from": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz",
"resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz"
},
"string-width": {
"version": "1.0.1",
- "from": "string-width@>=1.0.1 <2.0.0",
+ "from": "https://registry.npmjs.org/string-width/-/string-width-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.1.tgz",
"dependencies": {
"code-point-at": {
"version": "1.0.0",
- "from": "code-point-at@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz",
"dependencies": {
"number-is-nan": {
"version": "1.0.0",
- "from": "number-is-nan@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz"
}
}
},
"is-fullwidth-code-point": {
"version": "1.0.0",
- "from": "is-fullwidth-code-point@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"dependencies": {
"number-is-nan": {
"version": "1.0.0",
- "from": "number-is-nan@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz"
}
}
@@ -6670,258 +6694,258 @@
},
"strip-ansi": {
"version": "3.0.1",
- "from": "strip-ansi@>=3.0.0 <4.0.0",
+ "from": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz"
},
"through": {
"version": "2.3.8",
- "from": "through@>=2.3.6 <3.0.0",
+ "from": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz"
}
}
},
"is-my-json-valid": {
"version": "2.13.1",
- "from": "is-my-json-valid@>=2.10.0 <3.0.0",
+ "from": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.13.1.tgz",
"resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.13.1.tgz",
"dependencies": {
"generate-function": {
"version": "2.0.0",
- "from": "generate-function@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz"
},
"generate-object-property": {
"version": "1.2.0",
- "from": "generate-object-property@>=1.1.0 <2.0.0",
+ "from": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz",
"resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz",
"dependencies": {
"is-property": {
"version": "1.0.2",
- "from": "is-property@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz"
}
}
},
"jsonpointer": {
"version": "2.0.0",
- "from": "jsonpointer@2.0.0",
+ "from": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-2.0.0.tgz"
},
"xtend": {
"version": "4.0.1",
- "from": "xtend@>=4.0.0 <5.0.0",
+ "from": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz"
}
}
},
"is-resolvable": {
"version": "1.0.0",
- "from": "is-resolvable@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz",
"dependencies": {
"tryit": {
"version": "1.0.2",
- "from": "tryit@>=1.0.1 <2.0.0",
+ "from": "https://registry.npmjs.org/tryit/-/tryit-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.2.tgz"
}
}
},
"js-yaml": {
"version": "3.6.1",
- "from": "js-yaml@>=3.5.1 <4.0.0",
+ "from": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz",
"dependencies": {
"argparse": {
"version": "1.0.7",
- "from": "argparse@>=1.0.7 <2.0.0",
+ "from": "https://registry.npmjs.org/argparse/-/argparse-1.0.7.tgz",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.7.tgz",
"dependencies": {
"sprintf-js": {
"version": "1.0.3",
- "from": "sprintf-js@>=1.0.2 <1.1.0",
+ "from": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz"
}
}
},
"esprima": {
"version": "2.7.2",
- "from": "esprima@>=2.6.0 <3.0.0",
+ "from": "https://registry.npmjs.org/esprima/-/esprima-2.7.2.tgz",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.2.tgz"
}
}
},
"json-stable-stringify": {
"version": "1.0.1",
- "from": "json-stable-stringify@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
"dependencies": {
"jsonify": {
"version": "0.0.0",
- "from": "jsonify@>=0.0.0 <0.1.0",
+ "from": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz"
}
}
},
"levn": {
"version": "0.3.0",
- "from": "levn@>=0.3.0 <0.4.0",
+ "from": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
"dependencies": {
"prelude-ls": {
"version": "1.1.2",
- "from": "prelude-ls@>=1.1.2 <1.2.0",
+ "from": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz"
},
"type-check": {
"version": "0.3.2",
- "from": "type-check@>=0.3.2 <0.4.0",
+ "from": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz"
}
}
},
"lodash": {
"version": "4.14.1",
- "from": "lodash@>=4.0.0 <5.0.0",
+ "from": "https://registry.npmjs.org/lodash/-/lodash-4.14.1.tgz",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.14.1.tgz"
},
"mkdirp": {
"version": "0.5.1",
- "from": "mkdirp@>=0.5.0 <0.6.0",
+ "from": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"dependencies": {
"minimist": {
"version": "0.0.8",
- "from": "minimist@0.0.8",
+ "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz"
}
}
},
"optionator": {
"version": "0.8.1",
- "from": "optionator@>=0.8.1 <0.9.0",
+ "from": "https://registry.npmjs.org/optionator/-/optionator-0.8.1.tgz",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.1.tgz",
"dependencies": {
"prelude-ls": {
"version": "1.1.2",
- "from": "prelude-ls@>=1.1.2 <1.2.0",
+ "from": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz"
},
"deep-is": {
"version": "0.1.3",
- "from": "deep-is@>=0.1.3 <0.2.0",
+ "from": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz"
},
"wordwrap": {
"version": "1.0.0",
- "from": "wordwrap@>=1.0.0 <1.1.0",
+ "from": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz"
},
"type-check": {
"version": "0.3.2",
- "from": "type-check@>=0.3.2 <0.4.0",
+ "from": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz"
},
"fast-levenshtein": {
"version": "1.1.4",
- "from": "fast-levenshtein@>=1.1.0 <2.0.0",
+ "from": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz",
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz"
}
}
},
"path-is-inside": {
"version": "1.0.1",
- "from": "path-is-inside@>=1.0.1 <2.0.0",
+ "from": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.1.tgz"
},
"pluralize": {
"version": "1.2.1",
- "from": "pluralize@>=1.2.1 <2.0.0",
+ "from": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz",
"resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz"
},
"progress": {
"version": "1.1.8",
- "from": "progress@>=1.1.8 <2.0.0",
+ "from": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz",
"resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz"
},
"require-uncached": {
"version": "1.0.2",
- "from": "require-uncached@>=1.0.2 <2.0.0",
+ "from": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.2.tgz",
"dependencies": {
"caller-path": {
"version": "0.1.0",
- "from": "caller-path@>=0.1.0 <0.2.0",
+ "from": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
"resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
"dependencies": {
"callsites": {
"version": "0.2.0",
- "from": "callsites@>=0.2.0 <0.3.0",
+ "from": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz"
}
}
},
"resolve-from": {
"version": "1.0.1",
- "from": "resolve-from@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz"
}
}
},
"shelljs": {
"version": "0.6.0",
- "from": "shelljs@>=0.6.0 <0.7.0",
+ "from": "https://registry.npmjs.org/shelljs/-/shelljs-0.6.0.tgz",
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.6.0.tgz"
},
"strip-bom": {
"version": "3.0.0",
- "from": "strip-bom@>=3.0.0 <4.0.0",
+ "from": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz"
},
"strip-json-comments": {
"version": "1.0.4",
- "from": "strip-json-comments@>=1.0.1 <1.1.0",
+ "from": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz"
},
"table": {
"version": "3.7.8",
- "from": "table@>=3.7.8 <4.0.0",
+ "from": "https://registry.npmjs.org/table/-/table-3.7.8.tgz",
"resolved": "https://registry.npmjs.org/table/-/table-3.7.8.tgz",
"dependencies": {
"bluebird": {
"version": "3.4.1",
- "from": "bluebird@>=3.1.1 <4.0.0",
+ "from": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.1.tgz",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.1.tgz"
},
"slice-ansi": {
"version": "0.0.4",
- "from": "slice-ansi@0.0.4",
+ "from": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz",
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz"
},
"string-width": {
"version": "1.0.1",
- "from": "string-width@>=1.0.1 <2.0.0",
+ "from": "https://registry.npmjs.org/string-width/-/string-width-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.1.tgz",
"dependencies": {
"code-point-at": {
"version": "1.0.0",
- "from": "code-point-at@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz",
"dependencies": {
"number-is-nan": {
"version": "1.0.0",
- "from": "number-is-nan@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz"
}
}
},
"is-fullwidth-code-point": {
"version": "1.0.0",
- "from": "is-fullwidth-code-point@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"dependencies": {
"number-is-nan": {
"version": "1.0.0",
- "from": "number-is-nan@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz"
}
}
@@ -6930,41 +6954,41 @@
},
"strip-ansi": {
"version": "3.0.1",
- "from": "strip-ansi@>=3.0.0 <4.0.0",
+ "from": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"dependencies": {
"ansi-regex": {
"version": "2.0.0",
- "from": "ansi-regex@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz"
}
}
},
"tv4": {
"version": "1.2.7",
- "from": "tv4@>=1.2.7 <2.0.0",
+ "from": "https://registry.npmjs.org/tv4/-/tv4-1.2.7.tgz",
"resolved": "https://registry.npmjs.org/tv4/-/tv4-1.2.7.tgz"
},
"xregexp": {
"version": "3.1.1",
- "from": "xregexp@>=3.0.0 <4.0.0",
+ "from": "https://registry.npmjs.org/xregexp/-/xregexp-3.1.1.tgz",
"resolved": "https://registry.npmjs.org/xregexp/-/xregexp-3.1.1.tgz"
}
}
},
"text-table": {
"version": "0.2.0",
- "from": "text-table@>=0.2.0 <0.3.0",
+ "from": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz"
},
"user-home": {
"version": "2.0.0",
- "from": "user-home@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz",
"dependencies": {
"os-homedir": {
"version": "1.0.1",
- "from": "os-homedir@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.1.tgz"
}
}
@@ -7608,52 +7632,52 @@
},
"gulp-eslint": {
"version": "3.0.1",
- "from": "gulp-eslint@latest",
+ "from": "https://registry.npmjs.org/gulp-eslint/-/gulp-eslint-3.0.1.tgz",
"resolved": "https://registry.npmjs.org/gulp-eslint/-/gulp-eslint-3.0.1.tgz",
"dependencies": {
"bufferstreams": {
"version": "1.1.1",
- "from": "bufferstreams@>=1.1.1 <2.0.0",
+ "from": "https://registry.npmjs.org/bufferstreams/-/bufferstreams-1.1.1.tgz",
"resolved": "https://registry.npmjs.org/bufferstreams/-/bufferstreams-1.1.1.tgz",
"dependencies": {
"readable-stream": {
"version": "2.1.4",
- "from": "readable-stream@>=2.0.2 <3.0.0",
+ "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.4.tgz",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.4.tgz",
"dependencies": {
"buffer-shims": {
"version": "1.0.0",
- "from": "buffer-shims@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz"
},
"core-util-is": {
"version": "1.0.2",
- "from": "core-util-is@>=1.0.0 <1.1.0",
+ "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz"
},
"inherits": {
"version": "2.0.1",
- "from": "inherits@>=2.0.1 <2.1.0",
+ "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
},
"isarray": {
"version": "1.0.0",
- "from": "isarray@>=1.0.0 <1.1.0",
+ "from": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz"
},
"process-nextick-args": {
"version": "1.0.7",
- "from": "process-nextick-args@>=1.0.6 <1.1.0",
+ "from": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz"
},
"string_decoder": {
"version": "0.10.31",
- "from": "string_decoder@>=0.10.0 <0.11.0",
+ "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz"
},
"util-deprecate": {
"version": "1.0.2",
- "from": "util-deprecate@>=1.0.1 <1.1.0",
+ "from": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
}
}
@@ -7662,98 +7686,98 @@
},
"eslint": {
"version": "3.2.2",
- "from": "eslint@>=3.0.0 <4.0.0",
+ "from": "https://registry.npmjs.org/eslint/-/eslint-3.2.2.tgz",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-3.2.2.tgz",
"dependencies": {
"chalk": {
"version": "1.1.3",
- "from": "chalk@>=1.1.3 <2.0.0",
+ "from": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"dependencies": {
"ansi-styles": {
"version": "2.2.1",
- "from": "ansi-styles@>=2.2.1 <3.0.0",
+ "from": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz"
},
"escape-string-regexp": {
"version": "1.0.5",
- "from": "escape-string-regexp@>=1.0.2 <2.0.0",
+ "from": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
},
"has-ansi": {
"version": "2.0.0",
- "from": "has-ansi@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
"dependencies": {
"ansi-regex": {
"version": "2.0.0",
- "from": "ansi-regex@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz"
}
}
},
"strip-ansi": {
"version": "3.0.1",
- "from": "strip-ansi@>=3.0.0 <4.0.0",
+ "from": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"dependencies": {
"ansi-regex": {
"version": "2.0.0",
- "from": "ansi-regex@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz"
}
}
},
"supports-color": {
"version": "2.0.0",
- "from": "supports-color@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz"
}
}
},
"concat-stream": {
"version": "1.5.1",
- "from": "concat-stream@>=1.4.6 <2.0.0",
+ "from": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.1.tgz",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.1.tgz",
"dependencies": {
"inherits": {
"version": "2.0.1",
- "from": "inherits@>=2.0.1 <2.1.0",
+ "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
},
"typedarray": {
"version": "0.0.6",
- "from": "typedarray@>=0.0.5 <0.1.0",
+ "from": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz"
},
"readable-stream": {
"version": "2.0.6",
- "from": "readable-stream@>=2.0.0 <2.1.0",
+ "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
"dependencies": {
"core-util-is": {
"version": "1.0.2",
- "from": "core-util-is@>=1.0.0 <1.1.0",
+ "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz"
},
"isarray": {
"version": "1.0.0",
- "from": "isarray@>=1.0.0 <1.1.0",
+ "from": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz"
},
"process-nextick-args": {
"version": "1.0.7",
- "from": "process-nextick-args@>=1.0.6 <1.1.0",
+ "from": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz"
},
"string_decoder": {
"version": "0.10.31",
- "from": "string_decoder@>=0.10.0 <0.11.0",
+ "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz"
},
"util-deprecate": {
"version": "1.0.2",
- "from": "util-deprecate@>=1.0.1 <1.1.0",
+ "from": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
}
}
@@ -7762,115 +7786,115 @@
},
"debug": {
"version": "2.2.0",
- "from": "debug@>=2.1.1 <3.0.0",
+ "from": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
"dependencies": {
"ms": {
"version": "0.7.1",
- "from": "ms@0.7.1",
+ "from": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
"resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz"
}
}
},
"doctrine": {
"version": "1.2.2",
- "from": "doctrine@>=1.2.2 <2.0.0",
+ "from": "https://registry.npmjs.org/doctrine/-/doctrine-1.2.2.tgz",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.2.2.tgz",
"dependencies": {
"esutils": {
"version": "1.1.6",
- "from": "esutils@>=1.1.6 <2.0.0",
+ "from": "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz"
},
"isarray": {
"version": "1.0.0",
- "from": "isarray@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz"
}
}
},
"escope": {
"version": "3.6.0",
- "from": "escope@>=3.6.0 <4.0.0",
+ "from": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz",
"resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz",
"dependencies": {
"es6-map": {
"version": "0.1.4",
- "from": "es6-map@>=0.1.3 <0.2.0",
+ "from": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.4.tgz",
"resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.4.tgz",
"dependencies": {
"d": {
"version": "0.1.1",
- "from": "d@>=0.1.1 <0.2.0",
+ "from": "https://registry.npmjs.org/d/-/d-0.1.1.tgz",
"resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz"
},
"es5-ext": {
"version": "0.10.12",
- "from": "es5-ext@>=0.10.8 <0.11.0",
+ "from": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.12.tgz",
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.12.tgz"
},
"es6-iterator": {
"version": "2.0.0",
- "from": "es6-iterator@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.0.tgz"
},
"es6-set": {
"version": "0.1.4",
- "from": "es6-set@>=0.1.3 <0.2.0",
+ "from": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.4.tgz",
"resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.4.tgz"
},
"es6-symbol": {
"version": "3.1.0",
- "from": "es6-symbol@>=3.1.0 <3.2.0",
+ "from": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.0.tgz",
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.0.tgz"
},
"event-emitter": {
"version": "0.3.4",
- "from": "event-emitter@>=0.3.4 <0.4.0",
+ "from": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.4.tgz",
"resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.4.tgz"
}
}
},
"es6-weak-map": {
"version": "2.0.1",
- "from": "es6-weak-map@>=2.0.1 <3.0.0",
+ "from": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.1.tgz",
"dependencies": {
"d": {
"version": "0.1.1",
- "from": "d@>=0.1.1 <0.2.0",
+ "from": "https://registry.npmjs.org/d/-/d-0.1.1.tgz",
"resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz"
},
"es5-ext": {
"version": "0.10.12",
- "from": "es5-ext@>=0.10.8 <0.11.0",
+ "from": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.12.tgz",
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.12.tgz"
},
"es6-iterator": {
"version": "2.0.0",
- "from": "es6-iterator@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.0.tgz"
},
"es6-symbol": {
"version": "3.1.0",
- "from": "es6-symbol@>=3.1.0 <3.2.0",
+ "from": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.0.tgz",
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.0.tgz"
}
}
},
"esrecurse": {
"version": "4.1.0",
- "from": "esrecurse@>=4.1.0 <5.0.0",
+ "from": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.1.0.tgz",
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.1.0.tgz",
"dependencies": {
"estraverse": {
"version": "4.1.1",
- "from": "estraverse@>=4.1.0 <4.2.0",
+ "from": "https://registry.npmjs.org/estraverse/-/estraverse-4.1.1.tgz",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.1.1.tgz"
},
"object-assign": {
"version": "4.1.0",
- "from": "object-assign@>=4.0.1 <5.0.0",
+ "from": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz"
}
}
@@ -7879,180 +7903,180 @@
},
"espree": {
"version": "3.1.7",
- "from": "espree@>=3.1.6 <4.0.0",
+ "from": "https://registry.npmjs.org/espree/-/espree-3.1.7.tgz",
"resolved": "https://registry.npmjs.org/espree/-/espree-3.1.7.tgz",
"dependencies": {
"acorn": {
"version": "3.3.0",
- "from": "acorn@>=3.3.0 <4.0.0",
+ "from": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz"
},
"acorn-jsx": {
"version": "3.0.1",
- "from": "acorn-jsx@>=3.0.0 <4.0.0",
+ "from": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz"
}
}
},
"estraverse": {
"version": "4.2.0",
- "from": "estraverse@>=4.2.0 <5.0.0",
+ "from": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz"
},
"esutils": {
"version": "2.0.2",
- "from": "esutils@>=2.0.2 <3.0.0",
+ "from": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz"
},
"file-entry-cache": {
"version": "1.3.1",
- "from": "file-entry-cache@>=1.3.1 <2.0.0",
+ "from": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-1.3.1.tgz",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-1.3.1.tgz",
"dependencies": {
"flat-cache": {
"version": "1.2.1",
- "from": "flat-cache@>=1.2.1 <2.0.0",
+ "from": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.1.tgz",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.1.tgz",
"dependencies": {
"circular-json": {
"version": "0.3.1",
- "from": "circular-json@>=0.3.0 <0.4.0",
+ "from": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.1.tgz",
"resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.1.tgz"
},
"del": {
"version": "2.2.1",
- "from": "del@>=2.0.2 <3.0.0",
+ "from": "https://registry.npmjs.org/del/-/del-2.2.1.tgz",
"resolved": "https://registry.npmjs.org/del/-/del-2.2.1.tgz",
"dependencies": {
"globby": {
"version": "5.0.0",
- "from": "globby@>=5.0.0 <6.0.0",
+ "from": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
"resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
"dependencies": {
"array-union": {
"version": "1.0.2",
- "from": "array-union@>=1.0.1 <2.0.0",
+ "from": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
"dependencies": {
"array-uniq": {
"version": "1.0.3",
- "from": "array-uniq@>=1.0.1 <2.0.0",
+ "from": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
"resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz"
}
}
},
"arrify": {
"version": "1.0.1",
- "from": "arrify@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz"
}
}
},
"is-path-cwd": {
"version": "1.0.0",
- "from": "is-path-cwd@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz"
},
"is-path-in-cwd": {
"version": "1.0.0",
- "from": "is-path-in-cwd@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz",
"dependencies": {
"is-path-inside": {
"version": "1.0.0",
- "from": "is-path-inside@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz"
}
}
},
"pify": {
"version": "2.3.0",
- "from": "pify@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz"
},
"pinkie-promise": {
"version": "2.0.1",
- "from": "pinkie-promise@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
"dependencies": {
"pinkie": {
"version": "2.0.4",
- "from": "pinkie@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
"resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz"
}
}
},
"rimraf": {
"version": "2.5.4",
- "from": "rimraf@>=2.2.8 <3.0.0",
+ "from": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz"
}
}
},
"graceful-fs": {
"version": "4.1.5",
- "from": "graceful-fs@>=4.1.2 <5.0.0",
+ "from": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.5.tgz",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.5.tgz"
},
"write": {
"version": "0.2.1",
- "from": "write@>=0.2.1 <0.3.0",
+ "from": "https://registry.npmjs.org/write/-/write-0.2.1.tgz",
"resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz"
}
}
},
"object-assign": {
"version": "4.1.0",
- "from": "object-assign@>=4.0.1 <5.0.0",
+ "from": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz"
}
}
},
"glob": {
"version": "7.0.5",
- "from": "glob@>=7.0.3 <8.0.0",
+ "from": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz",
"dependencies": {
"fs.realpath": {
"version": "1.0.0",
- "from": "fs.realpath@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
},
"inflight": {
"version": "1.0.5",
- "from": "inflight@>=1.0.4 <2.0.0",
+ "from": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz",
"dependencies": {
"wrappy": {
"version": "1.0.2",
- "from": "wrappy@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
}
}
},
"inherits": {
"version": "2.0.1",
- "from": "inherits@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
},
"minimatch": {
"version": "3.0.2",
- "from": "minimatch@>=3.0.2 <4.0.0",
+ "from": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz",
"dependencies": {
"brace-expansion": {
"version": "1.1.6",
- "from": "brace-expansion@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz",
"dependencies": {
"balanced-match": {
"version": "0.4.2",
- "from": "balanced-match@>=0.4.1 <0.5.0",
+ "from": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz"
},
"concat-map": {
"version": "0.0.1",
- "from": "concat-map@0.0.1",
+ "from": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
}
}
@@ -8061,71 +8085,71 @@
},
"once": {
"version": "1.3.3",
- "from": "once@>=1.3.0 <2.0.0",
+ "from": "https://registry.npmjs.org/once/-/once-1.3.3.tgz",
"resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz",
"dependencies": {
"wrappy": {
"version": "1.0.2",
- "from": "wrappy@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
}
}
},
"path-is-absolute": {
"version": "1.0.0",
- "from": "path-is-absolute@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz"
}
}
},
"globals": {
"version": "9.9.0",
- "from": "globals@>=9.2.0 <10.0.0",
+ "from": "https://registry.npmjs.org/globals/-/globals-9.9.0.tgz",
"resolved": "https://registry.npmjs.org/globals/-/globals-9.9.0.tgz"
},
"ignore": {
"version": "3.1.3",
- "from": "ignore@>=3.1.2 <4.0.0",
+ "from": "https://registry.npmjs.org/ignore/-/ignore-3.1.3.tgz",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-3.1.3.tgz"
},
"imurmurhash": {
"version": "0.1.4",
- "from": "imurmurhash@>=0.1.4 <0.2.0",
+ "from": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz"
},
"inquirer": {
"version": "0.12.0",
- "from": "inquirer@>=0.12.0 <0.13.0",
+ "from": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz",
"dependencies": {
"ansi-escapes": {
"version": "1.4.0",
- "from": "ansi-escapes@>=1.1.0 <2.0.0",
+ "from": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz"
},
"ansi-regex": {
"version": "2.0.0",
- "from": "ansi-regex@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz"
},
"cli-cursor": {
"version": "1.0.2",
- "from": "cli-cursor@>=1.0.1 <2.0.0",
+ "from": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
"dependencies": {
"restore-cursor": {
"version": "1.0.1",
- "from": "restore-cursor@>=1.0.1 <2.0.0",
+ "from": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
"dependencies": {
"exit-hook": {
"version": "1.1.1",
- "from": "exit-hook@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz",
"resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz"
},
"onetime": {
"version": "1.1.0",
- "from": "onetime@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz"
}
}
@@ -8134,75 +8158,75 @@
},
"cli-width": {
"version": "2.1.0",
- "from": "cli-width@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz",
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz"
},
"figures": {
"version": "1.7.0",
- "from": "figures@>=1.3.5 <2.0.0",
+ "from": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
"resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
"dependencies": {
"escape-string-regexp": {
"version": "1.0.5",
- "from": "escape-string-regexp@>=1.0.5 <2.0.0",
+ "from": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
},
"object-assign": {
"version": "4.1.0",
- "from": "object-assign@>=4.1.0 <5.0.0",
+ "from": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz"
}
}
},
"readline2": {
"version": "1.0.1",
- "from": "readline2@>=1.0.1 <2.0.0",
+ "from": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz",
"dependencies": {
"code-point-at": {
"version": "1.0.0",
- "from": "code-point-at@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz",
"dependencies": {
"number-is-nan": {
"version": "1.0.0",
- "from": "number-is-nan@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz"
}
}
},
"is-fullwidth-code-point": {
"version": "1.0.0",
- "from": "is-fullwidth-code-point@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"dependencies": {
"number-is-nan": {
"version": "1.0.0",
- "from": "number-is-nan@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz"
}
}
},
"mute-stream": {
"version": "0.0.5",
- "from": "mute-stream@0.0.5",
+ "from": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz"
}
}
},
"run-async": {
"version": "0.1.0",
- "from": "run-async@>=0.1.0 <0.2.0",
+ "from": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz",
"resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz",
"dependencies": {
"once": {
"version": "1.3.3",
- "from": "once@>=1.3.0 <2.0.0",
+ "from": "https://registry.npmjs.org/once/-/once-1.3.3.tgz",
"resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz",
"dependencies": {
"wrappy": {
"version": "1.0.2",
- "from": "wrappy@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
}
}
@@ -8211,34 +8235,34 @@
},
"rx-lite": {
"version": "3.1.2",
- "from": "rx-lite@>=3.1.2 <4.0.0",
+ "from": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz",
"resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz"
},
"string-width": {
"version": "1.0.1",
- "from": "string-width@>=1.0.1 <2.0.0",
+ "from": "https://registry.npmjs.org/string-width/-/string-width-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.1.tgz",
"dependencies": {
"code-point-at": {
"version": "1.0.0",
- "from": "code-point-at@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz",
"dependencies": {
"number-is-nan": {
"version": "1.0.0",
- "from": "number-is-nan@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz"
}
}
},
"is-fullwidth-code-point": {
"version": "1.0.0",
- "from": "is-fullwidth-code-point@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"dependencies": {
"number-is-nan": {
"version": "1.0.0",
- "from": "number-is-nan@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz"
}
}
@@ -8247,258 +8271,258 @@
},
"strip-ansi": {
"version": "3.0.1",
- "from": "strip-ansi@>=3.0.0 <4.0.0",
+ "from": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz"
},
"through": {
"version": "2.3.8",
- "from": "through@>=2.3.6 <3.0.0",
+ "from": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz"
}
}
},
"is-my-json-valid": {
"version": "2.13.1",
- "from": "is-my-json-valid@>=2.10.0 <3.0.0",
+ "from": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.13.1.tgz",
"resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.13.1.tgz",
"dependencies": {
"generate-function": {
"version": "2.0.0",
- "from": "generate-function@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz"
},
"generate-object-property": {
"version": "1.2.0",
- "from": "generate-object-property@>=1.1.0 <2.0.0",
+ "from": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz",
"resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz",
"dependencies": {
"is-property": {
"version": "1.0.2",
- "from": "is-property@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz"
}
}
},
"jsonpointer": {
"version": "2.0.0",
- "from": "jsonpointer@2.0.0",
+ "from": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-2.0.0.tgz"
},
"xtend": {
"version": "4.0.1",
- "from": "xtend@>=4.0.0 <5.0.0",
+ "from": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz"
}
}
},
"is-resolvable": {
"version": "1.0.0",
- "from": "is-resolvable@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz",
"dependencies": {
"tryit": {
"version": "1.0.2",
- "from": "tryit@>=1.0.1 <2.0.0",
+ "from": "https://registry.npmjs.org/tryit/-/tryit-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.2.tgz"
}
}
},
"js-yaml": {
"version": "3.6.1",
- "from": "js-yaml@>=3.5.1 <4.0.0",
+ "from": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz",
"dependencies": {
"argparse": {
"version": "1.0.7",
- "from": "argparse@>=1.0.7 <2.0.0",
+ "from": "https://registry.npmjs.org/argparse/-/argparse-1.0.7.tgz",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.7.tgz",
"dependencies": {
"sprintf-js": {
"version": "1.0.3",
- "from": "sprintf-js@>=1.0.2 <1.1.0",
+ "from": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz"
}
}
},
"esprima": {
"version": "2.7.2",
- "from": "esprima@>=2.6.0 <3.0.0",
+ "from": "https://registry.npmjs.org/esprima/-/esprima-2.7.2.tgz",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.2.tgz"
}
}
},
"json-stable-stringify": {
"version": "1.0.1",
- "from": "json-stable-stringify@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
"dependencies": {
"jsonify": {
"version": "0.0.0",
- "from": "jsonify@>=0.0.0 <0.1.0",
+ "from": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz"
}
}
},
"levn": {
"version": "0.3.0",
- "from": "levn@>=0.3.0 <0.4.0",
+ "from": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
"dependencies": {
"prelude-ls": {
"version": "1.1.2",
- "from": "prelude-ls@>=1.1.2 <1.2.0",
+ "from": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz"
},
"type-check": {
"version": "0.3.2",
- "from": "type-check@>=0.3.2 <0.4.0",
+ "from": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz"
}
}
},
"lodash": {
"version": "4.14.1",
- "from": "lodash@>=4.0.0 <5.0.0",
+ "from": "https://registry.npmjs.org/lodash/-/lodash-4.14.1.tgz",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.14.1.tgz"
},
"mkdirp": {
"version": "0.5.1",
- "from": "mkdirp@>=0.5.0 <0.6.0",
+ "from": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"dependencies": {
"minimist": {
"version": "0.0.8",
- "from": "minimist@0.0.8",
+ "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz"
}
}
},
"optionator": {
"version": "0.8.1",
- "from": "optionator@>=0.8.1 <0.9.0",
+ "from": "https://registry.npmjs.org/optionator/-/optionator-0.8.1.tgz",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.1.tgz",
"dependencies": {
"prelude-ls": {
"version": "1.1.2",
- "from": "prelude-ls@>=1.1.2 <1.2.0",
+ "from": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz"
},
"deep-is": {
"version": "0.1.3",
- "from": "deep-is@>=0.1.3 <0.2.0",
+ "from": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz"
},
"wordwrap": {
"version": "1.0.0",
- "from": "wordwrap@>=1.0.0 <1.1.0",
+ "from": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz"
},
"type-check": {
"version": "0.3.2",
- "from": "type-check@>=0.3.2 <0.4.0",
+ "from": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz"
},
"fast-levenshtein": {
"version": "1.1.4",
- "from": "fast-levenshtein@>=1.1.0 <2.0.0",
+ "from": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz",
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz"
}
}
},
"path-is-inside": {
"version": "1.0.1",
- "from": "path-is-inside@>=1.0.1 <2.0.0",
+ "from": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.1.tgz"
},
"pluralize": {
"version": "1.2.1",
- "from": "pluralize@>=1.2.1 <2.0.0",
+ "from": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz",
"resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz"
},
"progress": {
"version": "1.1.8",
- "from": "progress@>=1.1.8 <2.0.0",
+ "from": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz",
"resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz"
},
"require-uncached": {
"version": "1.0.2",
- "from": "require-uncached@>=1.0.2 <2.0.0",
+ "from": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.2.tgz",
"resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.2.tgz",
"dependencies": {
"caller-path": {
"version": "0.1.0",
- "from": "caller-path@>=0.1.0 <0.2.0",
+ "from": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
"resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
"dependencies": {
"callsites": {
"version": "0.2.0",
- "from": "callsites@>=0.2.0 <0.3.0",
+ "from": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz"
}
}
},
"resolve-from": {
"version": "1.0.1",
- "from": "resolve-from@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz"
}
}
},
"shelljs": {
"version": "0.6.0",
- "from": "shelljs@>=0.6.0 <0.7.0",
+ "from": "https://registry.npmjs.org/shelljs/-/shelljs-0.6.0.tgz",
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.6.0.tgz"
},
"strip-bom": {
"version": "3.0.0",
- "from": "strip-bom@>=3.0.0 <4.0.0",
+ "from": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz"
},
"strip-json-comments": {
"version": "1.0.4",
- "from": "strip-json-comments@>=1.0.1 <1.1.0",
+ "from": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz"
},
"table": {
"version": "3.7.8",
- "from": "table@>=3.7.8 <4.0.0",
+ "from": "https://registry.npmjs.org/table/-/table-3.7.8.tgz",
"resolved": "https://registry.npmjs.org/table/-/table-3.7.8.tgz",
"dependencies": {
"bluebird": {
"version": "3.4.1",
- "from": "bluebird@>=3.1.1 <4.0.0",
+ "from": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.1.tgz",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.1.tgz"
},
"slice-ansi": {
"version": "0.0.4",
- "from": "slice-ansi@0.0.4",
+ "from": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz",
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz"
},
"string-width": {
"version": "1.0.1",
- "from": "string-width@>=1.0.1 <2.0.0",
+ "from": "https://registry.npmjs.org/string-width/-/string-width-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.1.tgz",
"dependencies": {
"code-point-at": {
"version": "1.0.0",
- "from": "code-point-at@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz",
"dependencies": {
"number-is-nan": {
"version": "1.0.0",
- "from": "number-is-nan@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz"
}
}
},
"is-fullwidth-code-point": {
"version": "1.0.0",
- "from": "is-fullwidth-code-point@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"dependencies": {
"number-is-nan": {
"version": "1.0.0",
- "from": "number-is-nan@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz"
}
}
@@ -8507,41 +8531,41 @@
},
"strip-ansi": {
"version": "3.0.1",
- "from": "strip-ansi@>=3.0.0 <4.0.0",
+ "from": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"dependencies": {
"ansi-regex": {
"version": "2.0.0",
- "from": "ansi-regex@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz"
}
}
},
"tv4": {
"version": "1.2.7",
- "from": "tv4@>=1.2.7 <2.0.0",
+ "from": "https://registry.npmjs.org/tv4/-/tv4-1.2.7.tgz",
"resolved": "https://registry.npmjs.org/tv4/-/tv4-1.2.7.tgz"
},
"xregexp": {
"version": "3.1.1",
- "from": "xregexp@>=3.0.0 <4.0.0",
+ "from": "https://registry.npmjs.org/xregexp/-/xregexp-3.1.1.tgz",
"resolved": "https://registry.npmjs.org/xregexp/-/xregexp-3.1.1.tgz"
}
}
},
"text-table": {
"version": "0.2.0",
- "from": "text-table@>=0.2.0 <0.3.0",
+ "from": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz"
},
"user-home": {
"version": "2.0.0",
- "from": "user-home@>=2.0.0 <3.0.0",
+ "from": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz",
"dependencies": {
"os-homedir": {
"version": "1.0.1",
- "from": "os-homedir@>=1.0.0 <2.0.0",
+ "from": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.1.tgz"
}
}
@@ -10698,618 +10722,6 @@
"resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz"
}
}
- },
- "fsevents": {
- "version": "1.0.14",
- "from": "https://registry.npmjs.org/fsevents/-/fsevents-1.0.14.tgz",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.0.14.tgz",
- "dependencies": {
- "nan": {
- "version": "2.4.0",
- "from": "https://registry.npmjs.org/nan/-/nan-2.4.0.tgz",
- "resolved": "https://registry.npmjs.org/nan/-/nan-2.4.0.tgz"
- },
- "node-pre-gyp": {
- "version": "0.6.29",
- "from": "node-pre-gyp@>=0.6.29 <0.7.0",
- "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.29.tgz"
- },
- "abbrev": {
- "version": "1.0.9",
- "from": "abbrev@>=1.0.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz"
- },
- "ansi-regex": {
- "version": "2.0.0",
- "from": "ansi-regex@>=2.0.0 <3.0.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz"
- },
- "ansi-styles": {
- "version": "2.2.1",
- "from": "ansi-styles@>=2.2.1 <3.0.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz"
- },
- "aproba": {
- "version": "1.0.4",
- "from": "aproba@>=1.0.3 <2.0.0",
- "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.0.4.tgz"
- },
- "are-we-there-yet": {
- "version": "1.1.2",
- "from": "are-we-there-yet@>=1.1.2 <1.2.0",
- "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.2.tgz"
- },
- "asn1": {
- "version": "0.2.3",
- "from": "asn1@>=0.2.3 <0.3.0",
- "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz"
- },
- "assert-plus": {
- "version": "0.2.0",
- "from": "assert-plus@>=0.2.0 <0.3.0",
- "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz"
- },
- "async": {
- "version": "1.5.2",
- "from": "async@>=1.5.2 <2.0.0",
- "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz"
- },
- "aws-sign2": {
- "version": "0.6.0",
- "from": "aws-sign2@>=0.6.0 <0.7.0",
- "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz"
- },
- "aws4": {
- "version": "1.4.1",
- "from": "aws4@>=1.2.1 <2.0.0",
- "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.4.1.tgz"
- },
- "balanced-match": {
- "version": "0.4.2",
- "from": "balanced-match@>=0.4.1 <0.5.0",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz"
- },
- "block-stream": {
- "version": "0.0.9",
- "from": "block-stream@*",
- "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz"
- },
- "boom": {
- "version": "2.10.1",
- "from": "boom@>=2.0.0 <3.0.0",
- "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz"
- },
- "brace-expansion": {
- "version": "1.1.5",
- "from": "brace-expansion@>=1.0.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.5.tgz"
- },
- "buffer-shims": {
- "version": "1.0.0",
- "from": "buffer-shims@>=1.0.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz"
- },
- "caseless": {
- "version": "0.11.0",
- "from": "caseless@>=0.11.0 <0.12.0",
- "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz"
- },
- "chalk": {
- "version": "1.1.3",
- "from": "chalk@>=1.1.1 <2.0.0",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz"
- },
- "code-point-at": {
- "version": "1.0.0",
- "from": "code-point-at@>=1.0.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz"
- },
- "combined-stream": {
- "version": "1.0.5",
- "from": "combined-stream@>=1.0.5 <1.1.0",
- "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz"
- },
- "commander": {
- "version": "2.9.0",
- "from": "commander@>=2.9.0 <3.0.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz"
- },
- "concat-map": {
- "version": "0.0.1",
- "from": "concat-map@0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
- },
- "console-control-strings": {
- "version": "1.1.0",
- "from": "console-control-strings@>=1.1.0 <1.2.0",
- "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz"
- },
- "core-util-is": {
- "version": "1.0.2",
- "from": "core-util-is@>=1.0.0 <1.1.0",
- "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz"
- },
- "cryptiles": {
- "version": "2.0.5",
- "from": "cryptiles@>=2.0.0 <3.0.0",
- "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz"
- },
- "debug": {
- "version": "2.2.0",
- "from": "debug@>=2.2.0 <2.3.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz"
- },
- "deep-extend": {
- "version": "0.4.1",
- "from": "deep-extend@>=0.4.0 <0.5.0",
- "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.1.tgz"
- },
- "delayed-stream": {
- "version": "1.0.0",
- "from": "delayed-stream@>=1.0.0 <1.1.0",
- "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz"
- },
- "delegates": {
- "version": "1.0.0",
- "from": "delegates@>=1.0.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz"
- },
- "ecc-jsbn": {
- "version": "0.1.1",
- "from": "ecc-jsbn@>=0.1.1 <0.2.0",
- "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz"
- },
- "escape-string-regexp": {
- "version": "1.0.5",
- "from": "escape-string-regexp@>=1.0.2 <2.0.0",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
- },
- "extend": {
- "version": "3.0.0",
- "from": "extend@>=3.0.0 <3.1.0",
- "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz"
- },
- "extsprintf": {
- "version": "1.0.2",
- "from": "extsprintf@1.0.2",
- "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz"
- },
- "forever-agent": {
- "version": "0.6.1",
- "from": "forever-agent@>=0.6.1 <0.7.0",
- "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz"
- },
- "form-data": {
- "version": "1.0.0-rc4",
- "from": "form-data@>=1.0.0-rc4 <1.1.0",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc4.tgz"
- },
- "fs.realpath": {
- "version": "1.0.0",
- "from": "fs.realpath@>=1.0.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
- },
- "fstream": {
- "version": "1.0.10",
- "from": "fstream@>=1.0.2 <2.0.0",
- "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.10.tgz"
- },
- "fstream-ignore": {
- "version": "1.0.5",
- "from": "fstream-ignore@>=1.0.5 <1.1.0",
- "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz"
- },
- "gauge": {
- "version": "2.6.0",
- "from": "gauge@>=2.6.0 <2.7.0",
- "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.6.0.tgz"
- },
- "generate-function": {
- "version": "2.0.0",
- "from": "generate-function@>=2.0.0 <3.0.0",
- "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz"
- },
- "generate-object-property": {
- "version": "1.2.0",
- "from": "generate-object-property@>=1.1.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz"
- },
- "glob": {
- "version": "7.0.5",
- "from": "glob@>=7.0.5 <8.0.0",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz"
- },
- "graceful-fs": {
- "version": "4.1.4",
- "from": "graceful-fs@>=4.1.2 <5.0.0",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.4.tgz"
- },
- "graceful-readlink": {
- "version": "1.0.1",
- "from": "graceful-readlink@>=1.0.0",
- "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz"
- },
- "har-validator": {
- "version": "2.0.6",
- "from": "har-validator@>=2.0.6 <2.1.0",
- "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz"
- },
- "has-ansi": {
- "version": "2.0.0",
- "from": "has-ansi@>=2.0.0 <3.0.0",
- "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz"
- },
- "has-color": {
- "version": "0.1.7",
- "from": "has-color@>=0.1.7 <0.2.0",
- "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz"
- },
- "has-unicode": {
- "version": "2.0.1",
- "from": "has-unicode@>=2.0.0 <3.0.0",
- "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz"
- },
- "hawk": {
- "version": "3.1.3",
- "from": "hawk@>=3.1.3 <3.2.0",
- "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz"
- },
- "hoek": {
- "version": "2.16.3",
- "from": "hoek@>=2.0.0 <3.0.0",
- "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz"
- },
- "http-signature": {
- "version": "1.1.1",
- "from": "http-signature@>=1.1.0 <1.2.0",
- "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz"
- },
- "inflight": {
- "version": "1.0.5",
- "from": "inflight@>=1.0.4 <2.0.0",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz"
- },
- "inherits": {
- "version": "2.0.1",
- "from": "inherits@>=2.0.1 <2.1.0",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
- },
- "ini": {
- "version": "1.3.4",
- "from": "ini@>=1.3.0 <1.4.0",
- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz"
- },
- "is-fullwidth-code-point": {
- "version": "1.0.0",
- "from": "is-fullwidth-code-point@>=1.0.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz"
- },
- "is-my-json-valid": {
- "version": "2.13.1",
- "from": "is-my-json-valid@>=2.12.4 <3.0.0",
- "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.13.1.tgz"
- },
- "is-property": {
- "version": "1.0.2",
- "from": "is-property@>=1.0.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz"
- },
- "is-typedarray": {
- "version": "1.0.0",
- "from": "is-typedarray@>=1.0.0 <1.1.0",
- "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz"
- },
- "isarray": {
- "version": "1.0.0",
- "from": "isarray@>=1.0.0 <1.1.0",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz"
- },
- "isstream": {
- "version": "0.1.2",
- "from": "isstream@>=0.1.2 <0.2.0",
- "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz"
- },
- "jodid25519": {
- "version": "1.0.2",
- "from": "jodid25519@>=1.0.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz"
- },
- "jsbn": {
- "version": "0.1.0",
- "from": "jsbn@>=0.1.0 <0.2.0",
- "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz"
- },
- "json-schema": {
- "version": "0.2.2",
- "from": "json-schema@0.2.2",
- "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.2.tgz"
- },
- "json-stringify-safe": {
- "version": "5.0.1",
- "from": "json-stringify-safe@>=5.0.1 <5.1.0",
- "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz"
- },
- "jsonpointer": {
- "version": "2.0.0",
- "from": "jsonpointer@2.0.0",
- "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-2.0.0.tgz"
- },
- "jsprim": {
- "version": "1.3.0",
- "from": "jsprim@>=1.2.2 <2.0.0",
- "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.3.0.tgz"
- },
- "mime-db": {
- "version": "1.23.0",
- "from": "mime-db@>=1.23.0 <1.24.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.23.0.tgz"
- },
- "mime-types": {
- "version": "2.1.11",
- "from": "mime-types@>=2.1.7 <2.2.0",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz"
- },
- "minimatch": {
- "version": "3.0.2",
- "from": "minimatch@>=3.0.2 <4.0.0",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz"
- },
- "minimist": {
- "version": "0.0.8",
- "from": "minimist@0.0.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz"
- },
- "mkdirp": {
- "version": "0.5.1",
- "from": "mkdirp@>=0.5.0 <0.6.0",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz"
- },
- "ms": {
- "version": "0.7.1",
- "from": "ms@0.7.1",
- "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz"
- },
- "node-uuid": {
- "version": "1.4.7",
- "from": "node-uuid@>=1.4.7 <1.5.0",
- "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz"
- },
- "nopt": {
- "version": "3.0.6",
- "from": "nopt@>=3.0.1 <3.1.0",
- "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz"
- },
- "npmlog": {
- "version": "3.1.2",
- "from": "npmlog@>=3.1.2 <3.2.0",
- "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-3.1.2.tgz"
- },
- "number-is-nan": {
- "version": "1.0.0",
- "from": "number-is-nan@>=1.0.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz"
- },
- "oauth-sign": {
- "version": "0.8.2",
- "from": "oauth-sign@>=0.8.1 <0.9.0",
- "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz"
- },
- "object-assign": {
- "version": "4.1.0",
- "from": "object-assign@>=4.1.0 <5.0.0",
- "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz"
- },
- "once": {
- "version": "1.3.3",
- "from": "once@>=1.3.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz"
- },
- "path-is-absolute": {
- "version": "1.0.0",
- "from": "path-is-absolute@>=1.0.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz"
- },
- "pinkie": {
- "version": "2.0.4",
- "from": "pinkie@>=2.0.0 <3.0.0",
- "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz"
- },
- "pinkie-promise": {
- "version": "2.0.1",
- "from": "pinkie-promise@>=2.0.0 <3.0.0",
- "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz"
- },
- "process-nextick-args": {
- "version": "1.0.7",
- "from": "process-nextick-args@>=1.0.6 <1.1.0",
- "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz"
- },
- "qs": {
- "version": "6.2.0",
- "from": "qs@>=6.2.0 <6.3.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.0.tgz"
- },
- "readable-stream": {
- "version": "2.1.4",
- "from": "readable-stream@>=2.0.0 <3.0.0||>=1.1.13 <2.0.0",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.4.tgz"
- },
- "request": {
- "version": "2.73.0",
- "from": "request@>=2.0.0 <3.0.0",
- "resolved": "https://registry.npmjs.org/request/-/request-2.73.0.tgz"
- },
- "rimraf": {
- "version": "2.5.3",
- "from": "rimraf@>=2.5.0 <2.6.0",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.3.tgz"
- },
- "semver": {
- "version": "5.2.0",
- "from": "semver@>=5.2.0 <5.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.2.0.tgz"
- },
- "set-blocking": {
- "version": "2.0.0",
- "from": "set-blocking@>=2.0.0 <2.1.0",
- "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz"
- },
- "signal-exit": {
- "version": "3.0.0",
- "from": "signal-exit@>=3.0.0 <4.0.0",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.0.tgz"
- },
- "sntp": {
- "version": "1.0.9",
- "from": "sntp@>=1.0.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz"
- },
- "string-width": {
- "version": "1.0.1",
- "from": "string-width@>=1.0.1 <2.0.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.1.tgz"
- },
- "string_decoder": {
- "version": "0.10.31",
- "from": "string_decoder@>=0.10.0 <0.11.0",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz"
- },
- "stringstream": {
- "version": "0.0.5",
- "from": "stringstream@>=0.0.4 <0.1.0",
- "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz"
- },
- "strip-ansi": {
- "version": "3.0.1",
- "from": "strip-ansi@>=3.0.1 <4.0.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz"
- },
- "strip-json-comments": {
- "version": "1.0.4",
- "from": "strip-json-comments@>=1.0.4 <1.1.0",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz"
- },
- "supports-color": {
- "version": "2.0.0",
- "from": "supports-color@>=2.0.0 <3.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz"
- },
- "tar": {
- "version": "2.2.1",
- "from": "tar@>=2.2.0 <2.3.0",
- "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz"
- },
- "tar-pack": {
- "version": "3.1.4",
- "from": "tar-pack@>=3.1.0 <3.2.0",
- "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.1.4.tgz"
- },
- "tough-cookie": {
- "version": "2.2.2",
- "from": "tough-cookie@>=2.2.0 <2.3.0",
- "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.2.2.tgz"
- },
- "tunnel-agent": {
- "version": "0.4.3",
- "from": "tunnel-agent@>=0.4.1 <0.5.0",
- "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz"
- },
- "tweetnacl": {
- "version": "0.13.3",
- "from": "tweetnacl@>=0.13.0 <0.14.0",
- "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.13.3.tgz"
- },
- "uid-number": {
- "version": "0.0.6",
- "from": "uid-number@>=0.0.6 <0.1.0",
- "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz"
- },
- "util-deprecate": {
- "version": "1.0.2",
- "from": "util-deprecate@>=1.0.1 <1.1.0",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
- },
- "verror": {
- "version": "1.3.6",
- "from": "verror@1.3.6",
- "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz"
- },
- "wide-align": {
- "version": "1.1.0",
- "from": "wide-align@>=1.1.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.0.tgz"
- },
- "wrappy": {
- "version": "1.0.2",
- "from": "wrappy@>=1.0.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
- },
- "xtend": {
- "version": "4.0.1",
- "from": "xtend@>=4.0.0 <5.0.0",
- "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz"
- },
- "bl": {
- "version": "1.1.2",
- "from": "bl@>=1.1.2 <1.2.0",
- "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz",
- "dependencies": {
- "readable-stream": {
- "version": "2.0.6",
- "from": "readable-stream@>=2.0.5 <2.1.0",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz"
- }
- }
- },
- "dashdash": {
- "version": "1.14.0",
- "from": "dashdash@>=1.12.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.0.tgz",
- "dependencies": {
- "assert-plus": {
- "version": "1.0.0",
- "from": "assert-plus@>=1.0.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz"
- }
- }
- },
- "getpass": {
- "version": "0.1.6",
- "from": "getpass@>=0.1.1 <0.2.0",
- "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz",
- "dependencies": {
- "assert-plus": {
- "version": "1.0.0",
- "from": "assert-plus@>=1.0.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz"
- }
- }
- },
- "rc": {
- "version": "1.1.6",
- "from": "rc@>=1.1.0 <1.2.0",
- "resolved": "https://registry.npmjs.org/rc/-/rc-1.1.6.tgz",
- "dependencies": {
- "minimist": {
- "version": "1.2.0",
- "from": "minimist@>=1.2.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz"
- }
- }
- },
- "sshpk": {
- "version": "1.8.3",
- "from": "sshpk@>=1.7.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.8.3.tgz",
- "dependencies": {
- "assert-plus": {
- "version": "1.0.0",
- "from": "assert-plus@>=1.0.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz"
- }
- }
- }
- }
}
}
},
@@ -11544,45 +10956,6 @@
"from": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz"
},
- "log4js": {
- "version": "0.6.38",
- "from": "https://registry.npmjs.com/log4js/-/log4js-0.6.38.tgz",
- "resolved": "https://registry.npmjs.com/log4js/-/log4js-0.6.38.tgz",
- "dependencies": {
- "readable-stream": {
- "version": "1.0.34",
- "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
- "dependencies": {
- "core-util-is": {
- "version": "1.0.2",
- "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
- "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz"
- },
- "isarray": {
- "version": "0.0.1",
- "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz"
- },
- "string_decoder": {
- "version": "0.10.31",
- "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz"
- },
- "inherits": {
- "version": "2.0.1",
- "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
- }
- }
- },
- "semver": {
- "version": "4.3.6",
- "from": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz",
- "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz"
- }
- }
- },
"mime": {
"version": "1.3.4",
"from": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz",
@@ -12907,6 +12280,45 @@
"from": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz"
},
+ "log4js": {
+ "version": "0.6.38",
+ "from": "log4js@>=0.6.27 <0.7.0",
+ "resolved": "https://registry.npmjs.com/log4js/-/log4js-0.6.38.tgz",
+ "dependencies": {
+ "readable-stream": {
+ "version": "1.0.34",
+ "from": "readable-stream@>=1.0.2 <1.1.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
+ "dependencies": {
+ "core-util-is": {
+ "version": "1.0.2",
+ "from": "core-util-is@>=1.0.0 <1.1.0",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz"
+ },
+ "isarray": {
+ "version": "0.0.1",
+ "from": "isarray@0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz"
+ },
+ "string_decoder": {
+ "version": "0.10.31",
+ "from": "string_decoder@>=0.10.0 <0.11.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz"
+ },
+ "inherits": {
+ "version": "2.0.1",
+ "from": "inherits@>=2.0.1 <2.1.0",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
+ }
+ }
+ },
+ "semver": {
+ "version": "4.3.6",
+ "from": "semver@>=4.3.3 <4.4.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz"
+ }
+ }
+ },
"marked": {
"version": "0.3.5",
"from": "https://registry.npmjs.org/marked/-/marked-0.3.5.tgz",
@@ -13302,62 +12714,6 @@
}
}
},
- "selenium-webdriver": {
- "version": "2.53.3",
- "from": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-2.53.3.tgz",
- "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-2.53.3.tgz",
- "dependencies": {
- "adm-zip": {
- "version": "0.4.4",
- "from": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.4.tgz",
- "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.4.tgz"
- },
- "rimraf": {
- "version": "2.5.4",
- "from": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz"
- },
- "tmp": {
- "version": "0.0.24",
- "from": "https://registry.npmjs.org/tmp/-/tmp-0.0.24.tgz",
- "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.24.tgz"
- },
- "ws": {
- "version": "1.1.1",
- "from": "https://registry.npmjs.org/ws/-/ws-1.1.1.tgz",
- "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.1.tgz",
- "dependencies": {
- "options": {
- "version": "0.0.6",
- "from": "https://registry.npmjs.org/options/-/options-0.0.6.tgz",
- "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz"
- },
- "ultron": {
- "version": "1.0.2",
- "from": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz",
- "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz"
- }
- }
- },
- "xml2js": {
- "version": "0.4.4",
- "from": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.4.tgz",
- "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.4.tgz",
- "dependencies": {
- "sax": {
- "version": "0.6.1",
- "from": "https://registry.npmjs.org/sax/-/sax-0.6.1.tgz",
- "resolved": "https://registry.npmjs.org/sax/-/sax-0.6.1.tgz"
- },
- "xmlbuilder": {
- "version": "8.2.2",
- "from": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz",
- "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz"
- }
- }
- }
- }
- },
"source-map-support": {
"version": "0.4.2",
"from": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.2.tgz",
@@ -13874,6 +13230,134 @@
"from": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz"
},
+ "selenium-webdriver": {
+ "version": "2.53.3",
+ "from": "selenium-webdriver@>=2.53.1 <3.0.0",
+ "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-2.53.3.tgz",
+ "dependencies": {
+ "adm-zip": {
+ "version": "0.4.4",
+ "from": "adm-zip@0.4.4",
+ "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.4.tgz"
+ },
+ "rimraf": {
+ "version": "2.5.4",
+ "from": "rimraf@>=2.2.8 <3.0.0",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz",
+ "dependencies": {
+ "glob": {
+ "version": "7.0.6",
+ "from": "glob@>=7.0.5 <8.0.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz",
+ "dependencies": {
+ "fs.realpath": {
+ "version": "1.0.0",
+ "from": "fs.realpath@>=1.0.0 <2.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
+ },
+ "inflight": {
+ "version": "1.0.5",
+ "from": "inflight@>=1.0.4 <2.0.0",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz",
+ "dependencies": {
+ "wrappy": {
+ "version": "1.0.2",
+ "from": "wrappy@>=1.0.0 <2.0.0",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
+ }
+ }
+ },
+ "inherits": {
+ "version": "2.0.1",
+ "from": "inherits@>=2.0.0 <3.0.0",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
+ },
+ "minimatch": {
+ "version": "3.0.3",
+ "from": "minimatch@>=3.0.2 <4.0.0",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz",
+ "dependencies": {
+ "brace-expansion": {
+ "version": "1.1.6",
+ "from": "brace-expansion@>=1.0.0 <2.0.0",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz",
+ "dependencies": {
+ "balanced-match": {
+ "version": "0.4.2",
+ "from": "balanced-match@>=0.4.1 <0.5.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz"
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "from": "concat-map@0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
+ }
+ }
+ }
+ }
+ },
+ "once": {
+ "version": "1.3.3",
+ "from": "once@>=1.3.0 <2.0.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz",
+ "dependencies": {
+ "wrappy": {
+ "version": "1.0.2",
+ "from": "wrappy@>=1.0.0 <2.0.0",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
+ }
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.0",
+ "from": "path-is-absolute@>=1.0.0 <2.0.0",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz"
+ }
+ }
+ }
+ }
+ },
+ "tmp": {
+ "version": "0.0.24",
+ "from": "tmp@0.0.24",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.24.tgz"
+ },
+ "ws": {
+ "version": "1.1.1",
+ "from": "ws@>=1.0.1 <2.0.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.1.tgz",
+ "dependencies": {
+ "options": {
+ "version": "0.0.6",
+ "from": "options@>=0.0.5",
+ "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz"
+ },
+ "ultron": {
+ "version": "1.0.2",
+ "from": "ultron@>=1.0.0 <1.1.0",
+ "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz"
+ }
+ }
+ },
+ "xml2js": {
+ "version": "0.4.4",
+ "from": "xml2js@0.4.4",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.4.tgz",
+ "dependencies": {
+ "sax": {
+ "version": "0.6.1",
+ "from": "sax@>=0.6.0 <0.7.0",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-0.6.1.tgz"
+ },
+ "xmlbuilder": {
+ "version": "8.2.2",
+ "from": "xmlbuilder@>=1.0.0",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz"
+ }
+ }
+ }
+ }
+ },
"semver": {
"version": "4.0.3",
"from": "https://registry.npmjs.org/semver/-/semver-4.0.3.tgz",
@@ -14091,7 +13575,7 @@
},
"shelljs": {
"version": "0.3.0",
- "from": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz",
+ "from": "shelljs@0.3.0",
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz"
},
"sorted-object": {
diff --git a/package.json b/package.json
index 9889ac229eb1..84c2718dca5e 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,8 @@
"postinstall": "node scripts/npm/copy-npm-shrinkwrap.js",
"commit": "git-cz",
"test-i18n": "jasmine-node i18n/spec",
- "test-i18n-ucd": "jasmine-node i18n/ucd/spec"
+ "test-i18n-ucd": "jasmine-node i18n/ucd/spec",
+ "gulp": "gulp"
},
"devDependencies": {
"angular-benchpress": "0.x.x",
@@ -27,6 +28,7 @@
"canonical-path": "0.0.2",
"cheerio": "^0.17.0",
"commitizen": "^2.3.0",
+ "cross-spawn": "^4.0.0",
"cz-conventional-changelog": "1.1.4",
"dgeni": "^0.4.0",
"dgeni-packages": "^0.14.0",
@@ -65,6 +67,7 @@
"karma-script-launcher": "^1.0.0",
"load-grunt-tasks": "^3.5.0",
"lodash": "~2.4.1",
+ "log4js": "^0.6.27",
"marked": "~0.3.0",
"node-html-encoder": "0.0.2",
"promises-aplus-tests": "~2.1.0",
@@ -74,6 +77,7 @@
"qq": "^0.3.5",
"rewire": "~2.1.0",
"sax": "^1.1.1",
+ "selenium-webdriver": "^2.53.1",
"semver": "~4.0.3",
"serve-favicon": "^2.3.0",
"serve-index": "^1.8.0",
diff --git a/src/.eslintrc.json b/src/.eslintrc.json
index caa332ff8bf7..a5d959535803 100644
--- a/src/.eslintrc.json
+++ b/src/.eslintrc.json
@@ -45,6 +45,7 @@
"isObject": false,
"isString": false,
"isNumber": false,
+ "isNumberNaN": false,
"isDate": false,
"isArray": false,
"isFunction": false,
diff --git a/src/Angular.js b/src/Angular.js
index 60463f1e1eb3..ad68d3e128d5 100644
--- a/src/Angular.js
+++ b/src/Angular.js
@@ -40,6 +40,7 @@
isBlankObject,
isString,
isNumber,
+ isNumberNaN,
isDate,
isArray,
isFunction,
@@ -412,6 +413,11 @@ function toInt(str) {
return parseInt(str, 10);
}
+var isNumberNaN = Number.isNaN || function isNumberNaN(num) {
+ // eslint-disable-next-line no-self-compare
+ return num !== num;
+};
+
function inherit(parent, extra) {
return extend(Object.create(parent), extra);
@@ -1276,7 +1282,7 @@ function timezoneToOffset(timezone, fallback) {
// IE/Edge do not "understand" colon (`:`) in timezone
timezone = timezone.replace(ALL_COLONS, '');
var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;
- return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;
+ return isNumberNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;
}
diff --git a/src/AngularPublic.js b/src/AngularPublic.js
index b1b5f332ce8a..3edd34e3abe9 100644
--- a/src/AngularPublic.js
+++ b/src/AngularPublic.js
@@ -79,6 +79,7 @@
$jsonpCallbacksProvider,
$LocationProvider,
$LogProvider,
+ $ModelOptionsProvider,
$ParseProvider,
$RootScopeProvider,
$QProvider,
@@ -246,6 +247,7 @@ function publishExternalAPI(angular) {
$jsonpCallbacks: $jsonpCallbacksProvider,
$location: $LocationProvider,
$log: $LogProvider,
+ $modelOptions: $ModelOptionsProvider,
$parse: $ParseProvider,
$rootScope: $RootScopeProvider,
$q: $QProvider,
diff --git a/src/ng/compile.js b/src/ng/compile.js
index 47fc44c2e053..02cd0bdbaa94 100644
--- a/src/ng/compile.js
+++ b/src/ng/compile.js
@@ -697,7 +697,7 @@
*
* When you call a transclusion function you can pass in a **clone attach function**. This function accepts
* two parameters, `function(clone, scope) { ... }`, where the `clone` is a fresh compiled copy of your transcluded
- * content and the `scope` is the newly created transclusion scope, to which the clone is bound.
+ * content and the `scope` is the newly created transclusion scope, which the clone will be linked to.
*
*
* **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a transclude function
@@ -1071,6 +1071,17 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
return require;
}
+ function getDirectiveRestrict(restrict, name) {
+ if (restrict && !(isString(restrict) && /[EACM]/.test(restrict))) {
+ throw $compileMinErr('badrestrict',
+ 'Restrict property \'{0}\' of directive \'{1}\' is invalid',
+ restrict,
+ name);
+ }
+
+ return restrict || 'EA';
+ }
+
/**
* @ngdoc method
* @name $compileProvider#directive
@@ -1109,7 +1120,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
directive.index = index;
directive.name = directive.name || name;
directive.require = getDirectiveRequire(directive);
- directive.restrict = directive.restrict || 'EA';
+ directive.restrict = getDirectiveRestrict(directive.restrict, name);
directive.$$moduleName = directiveFactory.$$moduleName;
directives.push(directive);
} catch (e) {
@@ -1358,6 +1369,35 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
return debugInfoEnabled;
};
+ /**
+ * @ngdoc method
+ * @name $compileProvider#preAssignBindingsEnabled
+ *
+ * @param {boolean=} enabled update the preAssignBindingsEnabled state if provided, otherwise just return the
+ * current preAssignBindingsEnabled state
+ * @returns {*} current value if used as getter or itself (chaining) if used as setter
+ *
+ * @kind function
+ *
+ * @description
+ * Call this method to enable/disable whether directive controllers are assigned bindings before
+ * calling the controller's constructor.
+ * If enabled (true), the compiler assigns the value of each of the bindings to the
+ * properties of the controller object before the constructor of this object is called.
+ *
+ * If disabled (false), the compiler calls the constructor first before assigning bindings.
+ *
+ * The default value is true in Angular 1.5.x but will switch to false in Angular 1.6.x.
+ */
+ var preAssignBindingsEnabled = true;
+ this.preAssignBindingsEnabled = function(enabled) {
+ if (isDefined(enabled)) {
+ preAssignBindingsEnabled = enabled;
+ return this;
+ }
+ return preAssignBindingsEnabled;
+ };
+
var TTL = 10;
/**
@@ -1817,6 +1857,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
compile.$$addScopeClass($compileNodes);
var namespace = null;
return function publicLinkFn(scope, cloneConnectFn, options) {
+ if (!$compileNodes) {
+ throw $compileMinErr('multilink', 'This element has already been linked.');
+ }
assertArg(scope, 'scope');
if (previousCompileContext && previousCompileContext.needsNewScope) {
@@ -1871,6 +1914,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
if (cloneConnectFn) cloneConnectFn($linkNode, scope);
if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn);
+
+ if (!cloneConnectFn) {
+ $compileNodes = compositeLinkFn = null;
+ }
return $linkNode;
};
}
@@ -2661,22 +2708,29 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
var controller = elementControllers[name];
var bindings = controllerDirective.$$bindings.bindToController;
- if (controller.identifier && bindings) {
- controller.bindingInfo =
- initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);
- } else {
- controller.bindingInfo = {};
- }
+ if (preAssignBindingsEnabled) {
+ if (controller.identifier && bindings) {
+ controller.bindingInfo =
+ initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);
+ } else {
+ controller.bindingInfo = {};
+ }
- var controllerResult = controller();
- if (controllerResult !== controller.instance) {
- // If the controller constructor has a return value, overwrite the instance
- // from setupControllers
- controller.instance = controllerResult;
- $element.data('$' + controllerDirective.name + 'Controller', controllerResult);
- if (controller.bindingInfo.removeWatches) {
- controller.bindingInfo.removeWatches();
+ var controllerResult = controller();
+ if (controllerResult !== controller.instance) {
+ // If the controller constructor has a return value, overwrite the instance
+ // from setupControllers
+ controller.instance = controllerResult;
+ $element.data('$' + controllerDirective.name + 'Controller', controllerResult);
+ if (controller.bindingInfo.removeWatches) {
+ controller.bindingInfo.removeWatches();
+ }
+ controller.bindingInfo =
+ initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);
}
+ } else {
+ controller.instance = controller();
+ $element.data('$' + controllerDirective.name + 'Controller', controller.instance);
controller.bindingInfo =
initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);
}
@@ -2905,24 +2959,22 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
if (hasDirectives.hasOwnProperty(name)) {
for (var directive, directives = $injector.get(name + Suffix),
i = 0, ii = directives.length; i < ii; i++) {
- try {
- directive = directives[i];
- if ((isUndefined(maxPriority) || maxPriority > directive.priority) &&
- directive.restrict.indexOf(location) !== -1) {
- if (startAttrName) {
- directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});
- }
- if (!directive.$$bindings) {
- var bindings = directive.$$bindings =
- parseDirectiveBindings(directive, directive.name);
- if (isObject(bindings.isolateScope)) {
- directive.$$isolateBindings = bindings.isolateScope;
- }
+ directive = directives[i];
+ if ((isUndefined(maxPriority) || maxPriority > directive.priority) &&
+ directive.restrict.indexOf(location) !== -1) {
+ if (startAttrName) {
+ directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});
+ }
+ if (!directive.$$bindings) {
+ var bindings = directive.$$bindings =
+ parseDirectiveBindings(directive, directive.name);
+ if (isObject(bindings.isolateScope)) {
+ directive.$$isolateBindings = bindings.isolateScope;
}
- tDirectives.push(directive);
- match = directive;
}
- } catch (e) { $exceptionHandler(e); }
+ tDirectives.push(directive);
+ match = directive;
+ }
}
}
return match;
@@ -3484,7 +3536,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
});
function recordChanges(key, currentValue, previousValue) {
- if (isFunction(destination.$onChanges) && currentValue !== previousValue) {
+ if (isFunction(destination.$onChanges) && currentValue !== previousValue &&
+ // eslint-disable-next-line no-self-compare
+ (currentValue === currentValue || previousValue === previousValue)) {
// If we have not already scheduled the top level onChangesQueue handler then do so now
if (!onChangesQueue) {
scope.$$postDigest(flushOnChangesQueue);
diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js
index 13990b4c0b68..9b109793b90c 100644
--- a/src/ng/directive/input.js
+++ b/src/ng/directive/input.js
@@ -1424,7 +1424,7 @@ function createDateInputType(type, regexp, parseDate, format) {
return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter) {
badInputChecker(scope, element, attr, ctrl);
baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
- var timezone = ctrl && ctrl.$options && ctrl.$options.timezone;
+ var timezone = ctrl && ctrl.$options.getOption('timezone');
var previousDate;
ctrl.$$parserName = type;
@@ -1526,7 +1526,7 @@ function parseNumberAttrVal(val) {
if (isDefined(val) && !isNumber(val)) {
val = parseFloat(val);
}
- return isNumber(val) && !isNaN(val) ? val : undefined;
+ return !isNumberNaN(val) ? val : undefined;
}
function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
@@ -1650,7 +1650,7 @@ function rangeInputType(scope, element, attr, ctrl, $sniffer, $browser) {
function minChange(val) {
minVal = parseNumberAttrVal(val);
// ignore changes before model is initialized
- if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
+ if (isNumberNaN(ctrl.$modelValue)) {
return;
}
@@ -1671,7 +1671,7 @@ function rangeInputType(scope, element, attr, ctrl, $sniffer, $browser) {
function maxChange(val) {
maxVal = parseNumberAttrVal(val);
// ignore changes before model is initialized
- if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
+ if (isNumberNaN(ctrl.$modelValue)) {
return;
}
@@ -1693,7 +1693,7 @@ function rangeInputType(scope, element, attr, ctrl, $sniffer, $browser) {
function stepChange(val) {
stepVal = parseNumberAttrVal(val);
// ignore changes before model is initialized
- if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
+ if (isNumberNaN(ctrl.$modelValue)) {
return;
}
diff --git a/src/ng/directive/ngCsp.js b/src/ng/directive/ngCsp.js
index a2866dc1ea59..f0303ef8a844 100644
--- a/src/ng/directive/ngCsp.js
+++ b/src/ng/directive/ngCsp.js
@@ -161,7 +161,7 @@
beforeEach(function() {
util = require('util');
- webdriver = require('protractor/node_modules/selenium-webdriver');
+ webdriver = require('selenium-webdriver');
});
// For now, we only test on Chrome,
diff --git a/src/ng/directive/ngModel.js b/src/ng/directive/ngModel.js
index 6ef8ba408187..fd0ef15ce5ae 100644
--- a/src/ng/directive/ngModel.js
+++ b/src/ng/directive/ngModel.js
@@ -5,7 +5,8 @@
PRISTINE_CLASS: true,
DIRTY_CLASS: true,
UNTOUCHED_CLASS: true,
- TOUCHED_CLASS: true
+ TOUCHED_CLASS: true,
+ $ModelOptionsProvider: true
*/
var VALID_CLASS = 'ng-valid',
@@ -220,8 +221,8 @@ is set to `true`. The parse error is stored in `ngModel.$error.parse`.
*
*
*/
-var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate', '$timeout', '$rootScope', '$q', '$interpolate',
- /** @this */ function($scope, $exceptionHandler, $attr, $element, $parse, $animate, $timeout, $rootScope, $q, $interpolate) {
+var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate', '$timeout', '$rootScope', '$q', '$interpolate', '$modelOptions',
+ /** @this */ function($scope, $exceptionHandler, $attr, $element, $parse, $animate, $timeout, $rootScope, $q, $interpolate, $modelOptions) {
this.$viewValue = Number.NaN;
this.$modelValue = Number.NaN;
this.$$rawModelValue = undefined; // stores the parsed modelValue / model set from scope regardless of validity.
@@ -241,6 +242,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
this.$pending = undefined; // keep pending keys here
this.$name = $interpolate($attr.name || '', false)($scope);
this.$$parentForm = nullFormCtrl;
+ this.$options = $modelOptions;
var parsedNgModel = $parse($attr.ngModel),
parsedNgModelAssign = parsedNgModel.assign,
@@ -250,9 +252,10 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
parserValid,
ctrl = this;
- this.$$setOptions = function(options) {
- ctrl.$options = options;
- if (options && options.getterSetter) {
+
+ this.$$initGetterSetters = function() {
+
+ if (ctrl.$options.getOption('getterSetter')) {
var invokeModelGetter = $parse($attr.ngModel + '()'),
invokeModelSetter = $parse($attr.ngModel + '($$$p)');
@@ -276,6 +279,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
}
};
+
/**
* @ngdoc method
* @name ngModel.NgModelController#$render
@@ -548,7 +552,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
*/
this.$validate = function() {
// ignore $validate before model is initialized
- if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
+ if (isNumberNaN(ctrl.$modelValue)) {
return;
}
@@ -562,7 +566,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
var prevValid = ctrl.$valid;
var prevModelValue = ctrl.$modelValue;
- var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;
+ var allowInvalid = ctrl.$options.getOption('allowInvalid');
ctrl.$$runValidators(modelValue, viewValue, function(allValid) {
// If there was no change in validity, don't update the model
@@ -719,12 +723,12 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
}
}
}
- if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
+ if (isNumberNaN(ctrl.$modelValue)) {
// ctrl.$modelValue has not been touched yet...
ctrl.$modelValue = ngModelGet($scope);
}
var prevModelValue = ctrl.$modelValue;
- var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;
+ var allowInvalid = ctrl.$options.getOption('allowInvalid');
ctrl.$$rawModelValue = modelValue;
if (allowInvalid) {
@@ -815,25 +819,19 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
*/
this.$setViewValue = function(value, trigger) {
ctrl.$viewValue = value;
- if (!ctrl.$options || ctrl.$options.updateOnDefault) {
+ if (ctrl.$options.getOption('updateOnDefault')) {
ctrl.$$debounceViewValueCommit(trigger);
}
};
this.$$debounceViewValueCommit = function(trigger) {
- var debounceDelay = 0,
- options = ctrl.$options,
- debounce;
-
- if (options && isDefined(options.debounce)) {
- debounce = options.debounce;
- if (isNumber(debounce)) {
- debounceDelay = debounce;
- } else if (isNumber(debounce[trigger])) {
- debounceDelay = debounce[trigger];
- } else if (isNumber(debounce['default'])) {
- debounceDelay = debounce['default'];
- }
+ var options = ctrl.$options,
+ debounceDelay = options.getOption('debounce');
+
+ if (isNumber(debounceDelay[trigger])) {
+ debounceDelay = debounceDelay[trigger];
+ } else if (isNumber(debounceDelay['default'])) {
+ debounceDelay = debounceDelay['default'];
}
$timeout.cancel(pendingDebounce);
@@ -1096,9 +1094,14 @@ var ngModelDirective = ['$rootScope', function($rootScope) {
return {
pre: function ngModelPreLink(scope, element, attr, ctrls) {
var modelCtrl = ctrls[0],
- formCtrl = ctrls[1] || modelCtrl.$$parentForm;
+ formCtrl = ctrls[1] || modelCtrl.$$parentForm,
+ optionsCtrl = ctrls[2];
+
+ if (optionsCtrl) {
+ modelCtrl.$options = optionsCtrl.$options;
+ }
- modelCtrl.$$setOptions(ctrls[2] && ctrls[2].$options);
+ modelCtrl.$$initGetterSetters();
// notify others, especially parent forms
formCtrl.$addControl(modelCtrl);
@@ -1115,8 +1118,8 @@ var ngModelDirective = ['$rootScope', function($rootScope) {
},
post: function ngModelPostLink(scope, element, attr, ctrls) {
var modelCtrl = ctrls[0];
- if (modelCtrl.$options && modelCtrl.$options.updateOn) {
- element.on(modelCtrl.$options.updateOn, function(ev) {
+ if (modelCtrl.$options.getOption('updateOn')) {
+ element.on(modelCtrl.$options.getOption('updateOn'), function(ev) {
modelCtrl.$$debounceViewValueCommit(ev && ev.type);
});
}
@@ -1137,17 +1140,47 @@ var ngModelDirective = ['$rootScope', function($rootScope) {
}];
-
-var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
-
/**
* @ngdoc directive
* @name ngModelOptions
*
* @description
- * Allows tuning how model updates are done. Using `ngModelOptions` you can specify a custom list of
- * events that will trigger a model update and/or a debouncing delay so that the actual update only
- * takes place when a timer expires; this timer will be reset after another change takes place.
+ * This directive allows you to modify the behaviour of ngModel and input directives within your
+ * application. You can specify an ngModelOptions directive on any element and the settings affect
+ * the ngModel and input directives on all descendent elements.
+ *
+ * The ngModelOptions settings are found by evaluating the value of the ngModelOptions attribute as
+ * an Angular expression. This expression should evaluate to an object, whose properties contain
+ * the settings.
+ *
+ * If a setting is not specified as a property on the object for a particular ngModelOptions directive
+ * then it will inherit that setting from the first ngModelOptions directive found by traversing up the
+ * DOM tree. If there is no ancestor element containing an ngModelOptions directive then the settings in
+ * {@link $modelOptions} will be used.
+ *
+ * For example given the following fragment of HTML
+ *
+ *
+ * ```html
+ *
+ *
+ *
+ * ```
+ *
+ * the `input` element will have the following settings
+ *
+ * ```js
+ * { allowInvalid: true, updateOn: 'default' }
+ * ```
+ *
+ *
+ * ## Triggering and debouncing model updates
+ *
+ * The `updateOn` and `debounce` properties allow you to specify a custom list of events that will
+ * trigger a model update and/or a debouncing delay so that the actual update only takes place when
+ * a timer expires; this timer will be reset after another change takes place.
*
* Given the nature of `ngModelOptions`, the value displayed inside input fields in the view might
* be different from the value in the actual model. This means that if you update the model you
@@ -1163,7 +1196,130 @@ var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
* `submit` event. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`
* to have access to the updated model.
*
- * `ngModelOptions` has an effect on the element it's declared on and its descendants.
+ * The following example shows how to override immediate updates. Changes on the inputs within the
+ * form will update the model only when the control loses focus (blur event). If `escape` key is
+ * pressed while the input field is focused, the value is reset to the value in the current model.
+ *
+ *
+ *
+ *
+ *
+ *
+ * angular.module('optionsExample', [])
+ * .controller('ExampleController', ['$scope', function($scope) {
+ * $scope.user = { name: 'say', data: '' };
+ *
+ * $scope.cancel = function(e) {
+ * if (e.keyCode === 27) {
+ * $scope.userForm.userName.$rollbackViewValue();
+ * }
+ * };
+ * }]);
+ *
+ *
+ * var model = element(by.binding('user.name'));
+ * var input = element(by.model('user.name'));
+ * var other = element(by.model('user.data'));
+ *
+ * it('should allow custom events', function() {
+ * input.sendKeys(' hello');
+ * input.click();
+ * expect(model.getText()).toEqual('say');
+ * other.click();
+ * expect(model.getText()).toEqual('say hello');
+ * });
+ *
+ * it('should $rollbackViewValue when model changes', function() {
+ * input.sendKeys(' hello');
+ * expect(input.getAttribute('value')).toEqual('say hello');
+ * input.sendKeys(protractor.Key.ESCAPE);
+ * expect(input.getAttribute('value')).toEqual('say');
+ * other.click();
+ * expect(model.getText()).toEqual('say');
+ * });
+ *
+ *
+ *
+ * The next example shows how to debounce model changes. Model will be updated only 1 sec after last change.
+ * If the `Clear` button is pressed, any debounced action is canceled and the value becomes empty.
+ *
+ *
+ *
+ *
+ *
+ *
+ * angular.module('optionsExample', [])
+ * .controller('ExampleController', ['$scope', function($scope) {
+ * $scope.user = { name: 'say' };
+ * }]);
+ *
+ *
+ *
+ * ## Model updates and validation
+ *
+ * The default behaviour in `ngModel` is that the model value is set to `null` when the validation
+ * determines that the value is invalid. By setting the `allowInvalid` property to true, the model
+ * will still be updated even if the value is invalid.
+ *
+ *
+ * ## Connecting to the scope
+ *
+ * By setting the `getterSetter` property to true you are telling ngModel that the `ngModel` expression
+ * on the scope refers to a "getter/setter" function rather than the value itself.
+ *
+ * The following example shows how to bind to getter/setters:
+ *
+ *
+ *
+ *
+ *
+ *
+ * angular.module('getterSetterExample', [])
+ * .controller('ExampleController', ['$scope', function($scope) {
+ * var _name = 'Brian';
+ * $scope.user = {
+ * name: function(newName) {
+ * return angular.isDefined(newName) ? (_name = newName) : _name;
+ * }
+ * };
+ * }]);
+ *
+ *
+ *
+ *
+ * ## Specifying timezones
+ *
+ * You can specify the timezone that date/time input directives expect by providing its name in the
+ * `timezone` property.
*
* @param {Object} ngModelOptions options to apply to the current model. Valid keys are:
* - `updateOn`: string specifying which event should the input be bound to. You can set several
@@ -1176,153 +1332,134 @@ var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
* - `allowInvalid`: boolean value which indicates that the model can be set with values that did
* not validate correctly instead of the default behavior of setting the model to undefined.
* - `getterSetter`: boolean value which determines whether or not to treat functions bound to
- `ngModel` as getters/setters.
+ * `ngModel` as getters/setters.
* - `timezone`: Defines the timezone to be used to read/write the `Date` instance in the model for
* `
`, `
`, ... . It understands UTC/GMT and the
* continental US time zone abbreviations, but for general use, use a time zone offset, for
* example, `'+0430'` (4 hours, 30 minutes east of the Greenwich meridian)
* If not specified, the timezone of the browser will be used.
*
- * @example
-
- The following example shows how to override immediate updates. Changes on the inputs within the
- form will update the model only when the control loses focus (blur event). If `escape` key is
- pressed while the input field is focused, the value is reset to the value in the current model.
-
-
-
-
-
-
user.name =
-
user.data =
-
-
-
- angular.module('optionsExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.user = { name: 'John', data: '' };
-
- $scope.cancel = function(e) {
- if (e.keyCode === 27) {
- $scope.userForm.userName.$rollbackViewValue();
- }
- };
- }]);
-
-
- var model = element(by.binding('user.name'));
- var input = element(by.model('user.name'));
- var other = element(by.model('user.data'));
-
- it('should allow custom events', function() {
- input.sendKeys(' Doe');
- input.click();
- expect(model.getText()).toEqual('John');
- other.click();
- expect(model.getText()).toEqual('John Doe');
- });
+ */
+var ngModelOptionsDirective = ['$modelOptions', function($modelOptions) {
+ return {
+ restrict: 'A',
+ // ngModelOptions needs to run before ngModel and input directives
+ priority: 10,
+ require: ['ngModelOptions', '?^^ngModelOptions'],
+ controller: function NgModelOptionsController() {},
+ link: {
+ pre: function ngModelOptionsPreLinkFn(scope, element, attrs, ctrls) {
+ var optionsCtrl = ctrls[0];
+ var parentOptions = ctrls[1] ? ctrls[1].$options : $modelOptions;
+ optionsCtrl.$options = parentOptions.createChild(scope.$eval(attrs.ngModelOptions));
+ }
+ }
+ };
+}];
- it('should $rollbackViewValue when model changes', function() {
- input.sendKeys(' Doe');
- expect(input.getAttribute('value')).toEqual('John Doe');
- input.sendKeys(protractor.Key.ESCAPE);
- expect(input.getAttribute('value')).toEqual('John');
- other.click();
- expect(model.getText()).toEqual('John');
- });
-
-
- This one shows how to debounce model changes. Model will be updated only 1 sec after last change.
- If the `Clear` button is pressed, any debounced action is canceled and the value becomes empty.
+/**
+ * @ngdoc provider
+ * @name $modelOptionsProvider
+ * @description
+ *
+ * Here, you can change the default settings from which {@link ngModelOptions}
+ * directives inherit.
+ *
+ * See the {@link ngModelOptions} directive for a list of the available options.
+ */
+function $ModelOptionsProvider() {
+ return {
+ /**
+ * @ngdoc property
+ * @name $modelOptionsProvider#defaultOptions
+ * @type {Object}
+ * @description
+ * The default options to fall back on when there are no more ngModelOption
+ * directives as ancestors.
+ * Use this property to specify the defaultOptions for the application as a whole.
+ *
+ * The initial default options are:
+ *
+ * * `updateOn`: `default`
+ * * `debounce`: `0`
+ * * `allowInvalid`: `undefined`
+ * * `getterSetter`: `undefined`
+ * * `timezone`: 'undefined'
+ */
+ defaultOptions: {
+ updateOn: 'default',
+ debounce: 0
+ },
-
-
-
-
-
- angular.module('optionsExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- $scope.user = { name: 'Igor' };
- }]);
-
-
+ /**
+ * @ngdoc service
+ * @name $modelOptions
+ * @type ModelOptions
+ * @description
+ *
+ * This service provides the application wide default {@link ModelOptions} options that
+ * will be used by {@link ngModel} directives if no {@link ngModelOptions} directive is
+ * specified.
+ */
+ $get: function() {
+ return new ModelOptions(this.defaultOptions);
+ }
+ };
+}
- This one shows how to bind to getter/setters:
-
-
-
-
-
- angular.module('getterSetterExample', [])
- .controller('ExampleController', ['$scope', function($scope) {
- var _name = 'Brian';
- $scope.user = {
- name: function(newName) {
- // Note that newName can be undefined for two reasons:
- // 1. Because it is called as a getter and thus called with no arguments
- // 2. Because the property should actually be set to undefined. This happens e.g. if the
- // input is invalid
- return arguments.length ? (_name = newName) : _name;
- }
- };
- }]);
-
-
+/**
+ * @ngdoc type
+ * @name ModelOptions
+ * @description
+ * A container for the options set by the {@link ngModelOptions} directive
+ * and the {@link $modelOptions} service.
*/
-var ngModelOptionsDirective = function() {
- return {
- restrict: 'A',
- controller: ['$scope', '$attrs', function NgModelOptionsController($scope, $attrs) {
- var that = this;
- this.$options = copy($scope.$eval($attrs.ngModelOptions));
- // Allow adding/overriding bound events
- if (isDefined(this.$options.updateOn)) {
- this.$options.updateOnDefault = false;
- // extract "default" pseudo-event from list of events that can trigger a model update
- this.$options.updateOn = trim(this.$options.updateOn.replace(DEFAULT_REGEXP, function() {
- that.$options.updateOnDefault = true;
- return ' ';
- }));
- } else {
- this.$options.updateOnDefault = true;
- }
- }]
- };
-};
+var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
+function ModelOptions(options, parentOptions) {
+
+ // Extend the parent's options with these new ones
+ var _options = extend({}, parentOptions, options);
+
+ // do extra processing on the options
+
+ // updateOn and updateOnDefault
+ if (isDefined(_options.updateOn) && _options.updateOn.trim()) {
+ _options.updateOnDefault = false;
+ // extract "default" pseudo-event from list of events that can trigger a model update
+ _options.updateOn = trim(_options.updateOn.replace(DEFAULT_REGEXP, function() {
+ _options.updateOnDefault = true;
+ return ' ';
+ }));
+ } else if (parentOptions) {
+ _options.updateOn = parentOptions.updateOn;
+ _options.updateOnDefault = parentOptions.updateOnDefault;
+ } else {
+ _options.updateOnDefault = true;
+ }
+ /**
+ * @ngdoc method
+ * @name ModelOptions#getOption
+ * @param {string} name the name of the option to retrieve
+ * @returns {*} the value of the option
+ * @description
+ * Returns the value of the given option
+ */
+ this.getOption = function(name) { return _options[name]; };
+
+ /**
+ * @ngdoc method
+ * @name ModelOptions#createChild
+ * @param {Object} options a hash of options for the new child that will override the parent's options
+ * @return {ModelOptions} a new `ModelOptions` object initialized with the given options.
+ */
+ this.createChild = function(options) {
+ return new ModelOptions(options, _options);
+ };
+}
// helper methods
function addSetValidityMethod(context) {
diff --git a/src/ng/directive/ngPluralize.js b/src/ng/directive/ngPluralize.js
index 8d3a8a8cc48d..f0b7a67500ec 100644
--- a/src/ng/directive/ngPluralize.js
+++ b/src/ng/directive/ngPluralize.js
@@ -206,7 +206,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
scope.$watch(numberExp, function ngPluralizeWatchAction(newVal) {
var count = parseFloat(newVal);
- var countIsNaN = isNaN(count);
+ var countIsNaN = isNumberNaN(count);
if (!countIsNaN && !(count in whens)) {
// If an explicit number rule such as 1, 2, 3... is defined, just use it.
@@ -216,7 +216,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
// If both `count` and `lastCount` are NaN, we don't need to re-register a watch.
// In JS `NaN !== NaN`, so we have to explicitly check.
- if ((count !== lastCount) && !(countIsNaN && isNumber(lastCount) && isNaN(lastCount))) {
+ if ((count !== lastCount) && !(countIsNaN && isNumberNaN(lastCount))) {
watchRemover();
var whenExpFn = whensExpFns[count];
if (isUndefined(whenExpFn)) {
diff --git a/src/ng/directive/validators.js b/src/ng/directive/validators.js
index 052228299faf..36201f9f287f 100644
--- a/src/ng/directive/validators.js
+++ b/src/ng/directive/validators.js
@@ -259,7 +259,7 @@ var maxlengthDirective = function() {
var maxlength = -1;
attr.$observe('maxlength', function(value) {
var intVal = toInt(value);
- maxlength = isNaN(intVal) ? -1 : intVal;
+ maxlength = isNumberNaN(intVal) ? -1 : intVal;
ctrl.$validate();
});
ctrl.$validators.maxlength = function(modelValue, viewValue) {
diff --git a/src/ng/filter/filters.js b/src/ng/filter/filters.js
index 8d8f221a56cb..f0ef2f29d3aa 100644
--- a/src/ng/filter/filters.js
+++ b/src/ng/filter/filters.js
@@ -31,7 +31,7 @@ var ZERO_CHAR = '0';
default currency symbol ($): {{amount | currency}}
- custom currency identifier (USD$): {{amount | currency:"USD$"}}
+ custom currency identifier (USD$): {{amount | currency:"USD$"}}
no fractions (0): {{amount | currency:"USD$":0}}
diff --git a/src/ng/filter/limitTo.js b/src/ng/filter/limitTo.js
index 7c87a594345d..3a7998b73957 100644
--- a/src/ng/filter/limitTo.js
+++ b/src/ng/filter/limitTo.js
@@ -106,7 +106,7 @@ function limitToFilter() {
} else {
limit = toInt(limit);
}
- if (isNaN(limit)) return input;
+ if (isNumberNaN(limit)) return input;
if (isNumber(input)) input = input.toString();
if (!isArrayLike(input)) return input;
diff --git a/src/ng/rootScope.js b/src/ng/rootScope.js
index afefa45e8058..7731c646dfee 100644
--- a/src/ng/rootScope.js
+++ b/src/ng/rootScope.js
@@ -806,8 +806,7 @@ function $RootScopeProvider() {
if ((value = get(current)) !== (last = watch.last) &&
!(watch.eq
? equals(value, last)
- : (typeof value === 'number' && typeof last === 'number'
- && isNaN(value) && isNaN(last)))) {
+ : (isNumberNaN(value) && isNumberNaN(last)))) {
dirty = true;
lastDirtyWatch = watch;
watch.last = watch.eq ? copy(value, null) : value;
diff --git a/src/ngSanitize/sanitize.js b/src/ngSanitize/sanitize.js
index a816069bcf48..f5f7490c2f67 100644
--- a/src/ngSanitize/sanitize.js
+++ b/src/ngSanitize/sanitize.js
@@ -499,27 +499,26 @@ function $SanitizeProvider() {
* @param node Root element to process
*/
function stripCustomNsAttrs(node) {
- if (node.nodeType === window.Node.ELEMENT_NODE) {
- var attrs = node.attributes;
- for (var i = 0, l = attrs.length; i < l; i++) {
- var attrNode = attrs[i];
- var attrName = attrNode.name.toLowerCase();
- if (attrName === 'xmlns:ns1' || attrName.lastIndexOf('ns1:', 0) === 0) {
- node.removeAttributeNode(attrNode);
- i--;
- l--;
+ while (node) {
+ if (node.nodeType === window.Node.ELEMENT_NODE) {
+ var attrs = node.attributes;
+ for (var i = 0, l = attrs.length; i < l; i++) {
+ var attrNode = attrs[i];
+ var attrName = attrNode.name.toLowerCase();
+ if (attrName === 'xmlns:ns1' || attrName.lastIndexOf('ns1:', 0) === 0) {
+ node.removeAttributeNode(attrNode);
+ i--;
+ l--;
+ }
}
}
- }
- var nextNode = node.firstChild;
- if (nextNode) {
- stripCustomNsAttrs(nextNode);
- }
+ var nextNode = node.firstChild;
+ if (nextNode) {
+ stripCustomNsAttrs(nextNode);
+ }
- nextNode = node.nextSibling;
- if (nextNode) {
- stripCustomNsAttrs(nextNode);
+ node = node.nextSibling;
}
}
}
diff --git a/test/.eslintrc.json b/test/.eslintrc.json
index 2bf89b2bb07e..ca882335b492 100644
--- a/test/.eslintrc.json
+++ b/test/.eslintrc.json
@@ -59,6 +59,7 @@
"isObject": false,
"isString": false,
"isNumber": false,
+ "isNumberNaN": false,
"isDate": false,
"isArray": false,
"isFunction": false,
diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js
index 4c57925ec5a1..e4a8ddf4e960 100755
--- a/test/ng/compileSpec.js
+++ b/test/ng/compileSpec.js
@@ -151,6 +151,60 @@ describe('$compile', function() {
describe('configuration', function() {
+ it('should allow aHrefSanitizationWhitelist to be configured', function() {
+ module(function($compileProvider) {
+ expect($compileProvider.aHrefSanitizationWhitelist()).toEqual(/^\s*(https?|ftp|mailto|tel|file):/); // the default
+ $compileProvider.aHrefSanitizationWhitelist(/other/);
+ expect($compileProvider.aHrefSanitizationWhitelist()).toEqual(/other/);
+ });
+ inject();
+ });
+
+ it('should allow debugInfoEnabled to be configured', function() {
+ module(function($compileProvider) {
+ expect($compileProvider.debugInfoEnabled()).toBe(true); // the default
+ $compileProvider.debugInfoEnabled(false);
+ expect($compileProvider.debugInfoEnabled()).toBe(false);
+ });
+ inject();
+ });
+
+ it('should allow preAssignBindingsEnabled to be configured', function() {
+ module(function($compileProvider) {
+ expect($compileProvider.preAssignBindingsEnabled()).toBe(true); // the default
+ $compileProvider.preAssignBindingsEnabled(false);
+ expect($compileProvider.preAssignBindingsEnabled()).toBe(false);
+ });
+ inject();
+ });
+
+ it('should allow onChangesTtl to be configured', function() {
+ module(function($compileProvider) {
+ expect($compileProvider.onChangesTtl()).toBe(10); // the default
+ $compileProvider.onChangesTtl(2);
+ expect($compileProvider.onChangesTtl()).toBe(2);
+ });
+ inject();
+ });
+
+ it('should allow commentDirectivesEnabled to be configured', function() {
+ module(function($compileProvider) {
+ expect($compileProvider.commentDirectivesEnabled()).toBe(true); // the default
+ $compileProvider.commentDirectivesEnabled(false);
+ expect($compileProvider.commentDirectivesEnabled()).toBe(false);
+ });
+ inject();
+ });
+
+ it('should allow cssClassDirectivesEnabled to be configured', function() {
+ module(function($compileProvider) {
+ expect($compileProvider.cssClassDirectivesEnabled()).toBe(true); // the default
+ $compileProvider.cssClassDirectivesEnabled(false);
+ expect($compileProvider.cssClassDirectivesEnabled()).toBe(false);
+ });
+ inject();
+ });
+
it('should register a directive', function() {
module(function() {
directive('div', function(log) {
@@ -3631,6 +3685,14 @@ describe('$compile', function() {
expect(element.text()).toBe('3');
});
});
+
+ it('should throw multilink error when linking the same element more then once', function() {
+ var linker = $compile('
');
+ linker($rootScope).remove();
+ expect(function() {
+ linker($rootScope);
+ }).toThrowMinErr('$compile', 'multilink', 'This element has already been linked.');
+ });
});
@@ -3837,6002 +3899,6285 @@ describe('$compile', function() {
});
});
- describe('controller lifecycle hooks', function() {
-
- describe('$onInit', function() {
+ forEach([true, false], function(preAssignBindingsEnabled) {
+ describe((preAssignBindingsEnabled ? 'with' : 'without') + ' pre-assigned bindings', function() {
+ beforeEach(module(function($compileProvider) {
+ $compileProvider.preAssignBindingsEnabled(preAssignBindingsEnabled);
+ }));
- it('should call `$onInit`, if provided, after all the controllers on the element have been initialized', function() {
+ describe('controller lifecycle hooks', function() {
- function check() {
- expect(this.element.controller('d1').id).toEqual(1);
- expect(this.element.controller('d2').id).toEqual(2);
- }
+ describe('$onInit', function() {
- function Controller1($element) { this.id = 1; this.element = $element; }
- Controller1.prototype.$onInit = jasmine.createSpy('$onInit').and.callFake(check);
+ it('should call `$onInit`, if provided, after all the controllers on the element have been initialized', function() {
- function Controller2($element) { this.id = 2; this.element = $element; }
- Controller2.prototype.$onInit = jasmine.createSpy('$onInit').and.callFake(check);
+ function check() {
+ expect(this.element.controller('d1').id).toEqual(1);
+ expect(this.element.controller('d2').id).toEqual(2);
+ }
- angular.module('my', [])
- .directive('d1', valueFn({ controller: Controller1 }))
- .directive('d2', valueFn({ controller: Controller2 }));
+ function Controller1($element) { this.id = 1; this.element = $element; }
+ Controller1.prototype.$onInit = jasmine.createSpy('$onInit').and.callFake(check);
- module('my');
- inject(function($compile, $rootScope) {
- element = $compile('
')($rootScope);
- expect(Controller1.prototype.$onInit).toHaveBeenCalledOnce();
- expect(Controller2.prototype.$onInit).toHaveBeenCalledOnce();
- });
- });
+ function Controller2($element) { this.id = 2; this.element = $element; }
+ Controller2.prototype.$onInit = jasmine.createSpy('$onInit').and.callFake(check);
- it('should continue to trigger other `$onInit` hooks if one throws an error', function() {
- function ThrowingController() {
- this.$onInit = function() {
- throw new Error('bad hook');
- };
- }
- function LoggingController($log) {
- this.$onInit = function() {
- $log.info('onInit');
- };
- }
+ angular.module('my', [])
+ .directive('d1', valueFn({ controller: Controller1 }))
+ .directive('d2', valueFn({ controller: Controller2 }));
- angular.module('my', [])
- .component('c1', {
- controller: ThrowingController,
- bindings: {'prop': '<'}
- })
- .component('c2', {
- controller: LoggingController,
- bindings: {'prop': '<'}
- })
- .config(function($exceptionHandlerProvider) {
- // We need to test with the exceptionHandler not rethrowing...
- $exceptionHandlerProvider.mode('log');
+ module('my');
+ inject(function($compile, $rootScope) {
+ element = $compile('
')($rootScope);
+ expect(Controller1.prototype.$onInit).toHaveBeenCalledOnce();
+ expect(Controller2.prototype.$onInit).toHaveBeenCalledOnce();
+ });
});
- module('my');
- inject(function($compile, $rootScope, $exceptionHandler, $log) {
-
- // Setup the directive with bindings that will keep updating the bound value forever
- element = $compile('
')($rootScope);
+ it('should continue to trigger other `$onInit` hooks if one throws an error', function() {
+ function ThrowingController() {
+ this.$onInit = function() {
+ throw new Error('bad hook');
+ };
+ }
+ function LoggingController($log) {
+ this.$onInit = function() {
+ $log.info('onInit');
+ };
+ }
- // The first component's error should be logged
- expect($exceptionHandler.errors.pop()).toEqual(new Error('bad hook'));
+ angular.module('my', [])
+ .component('c1', {
+ controller: ThrowingController,
+ bindings: {'prop': '<'}
+ })
+ .component('c2', {
+ controller: LoggingController,
+ bindings: {'prop': '<'}
+ })
+ .config(function($exceptionHandlerProvider) {
+ // We need to test with the exceptionHandler not rethrowing...
+ $exceptionHandlerProvider.mode('log');
+ });
- // The second component's hook should still be called
- expect($log.info.logs.pop()).toEqual(['onInit']);
- });
- });
- });
+ module('my');
+ inject(function($compile, $rootScope, $exceptionHandler, $log) {
+ // Setup the directive with bindings that will keep updating the bound value forever
+ element = $compile('
')($rootScope);
- describe('$onDestroy', function() {
+ // The first component's error should be logged
+ expect($exceptionHandler.errors.pop()).toEqual(new Error('bad hook'));
- it('should call `$onDestroy`, if provided, on the controller when its scope is destroyed', function() {
+ // The second component's hook should still be called
+ expect($log.info.logs.pop()).toEqual(['onInit']);
+ });
+ });
+ });
- function TestController() { this.count = 0; }
- TestController.prototype.$onDestroy = function() { this.count++; };
- angular.module('my', [])
- .directive('d1', valueFn({ scope: true, controller: TestController }))
- .directive('d2', valueFn({ scope: {}, controller: TestController }))
- .directive('d3', valueFn({ controller: TestController }));
+ describe('$onDestroy', function() {
- module('my');
- inject(function($compile, $rootScope) {
+ it('should call `$onDestroy`, if provided, on the controller when its scope is destroyed', function() {
- element = $compile('
')($rootScope);
+ function TestController() { this.count = 0; }
+ TestController.prototype.$onDestroy = function() { this.count++; };
- $rootScope.$apply('show = [true, true, true]');
- var d1Controller = element.find('d1').controller('d1');
- var d2Controller = element.find('d2').controller('d2');
- var d3Controller = element.find('d3').controller('d3');
+ angular.module('my', [])
+ .directive('d1', valueFn({ scope: true, controller: TestController }))
+ .directive('d2', valueFn({ scope: {}, controller: TestController }))
+ .directive('d3', valueFn({ controller: TestController }));
- expect([d1Controller.count, d2Controller.count, d3Controller.count]).toEqual([0,0,0]);
- $rootScope.$apply('show = [false, true, true]');
- expect([d1Controller.count, d2Controller.count, d3Controller.count]).toEqual([1,0,0]);
- $rootScope.$apply('show = [false, false, true]');
- expect([d1Controller.count, d2Controller.count, d3Controller.count]).toEqual([1,1,0]);
- $rootScope.$apply('show = [false, false, false]');
- expect([d1Controller.count, d2Controller.count, d3Controller.count]).toEqual([1,1,1]);
- });
- });
+ module('my');
+ inject(function($compile, $rootScope) {
+ element = $compile('
')($rootScope);
- it('should call `$onDestroy` top-down (the same as `scope.$broadcast`)', function() {
- var log = [];
- function ParentController() { log.push('parent created'); }
- ParentController.prototype.$onDestroy = function() { log.push('parent destroyed'); };
- function ChildController() { log.push('child created'); }
- ChildController.prototype.$onDestroy = function() { log.push('child destroyed'); };
- function GrandChildController() { log.push('grand child created'); }
- GrandChildController.prototype.$onDestroy = function() { log.push('grand child destroyed'); };
+ $rootScope.$apply('show = [true, true, true]');
+ var d1Controller = element.find('d1').controller('d1');
+ var d2Controller = element.find('d2').controller('d2');
+ var d3Controller = element.find('d3').controller('d3');
- angular.module('my', [])
- .directive('parent', valueFn({ scope: true, controller: ParentController }))
- .directive('child', valueFn({ scope: true, controller: ChildController }))
- .directive('grandChild', valueFn({ scope: true, controller: GrandChildController }));
+ expect([d1Controller.count, d2Controller.count, d3Controller.count]).toEqual([0,0,0]);
+ $rootScope.$apply('show = [false, true, true]');
+ expect([d1Controller.count, d2Controller.count, d3Controller.count]).toEqual([1,0,0]);
+ $rootScope.$apply('show = [false, false, true]');
+ expect([d1Controller.count, d2Controller.count, d3Controller.count]).toEqual([1,1,0]);
+ $rootScope.$apply('show = [false, false, false]');
+ expect([d1Controller.count, d2Controller.count, d3Controller.count]).toEqual([1,1,1]);
+ });
+ });
- module('my');
- inject(function($compile, $rootScope) {
- element = $compile('
')($rootScope);
- $rootScope.$apply('show = true');
- expect(log).toEqual(['parent created', 'child created', 'grand child created']);
- log = [];
- $rootScope.$apply('show = false');
- expect(log).toEqual(['parent destroyed', 'child destroyed', 'grand child destroyed']);
- });
- });
- });
+ it('should call `$onDestroy` top-down (the same as `scope.$broadcast`)', function() {
+ var log = [];
+ function ParentController() { log.push('parent created'); }
+ ParentController.prototype.$onDestroy = function() { log.push('parent destroyed'); };
+ function ChildController() { log.push('child created'); }
+ ChildController.prototype.$onDestroy = function() { log.push('child destroyed'); };
+ function GrandChildController() { log.push('grand child created'); }
+ GrandChildController.prototype.$onDestroy = function() { log.push('grand child destroyed'); };
+ angular.module('my', [])
+ .directive('parent', valueFn({ scope: true, controller: ParentController }))
+ .directive('child', valueFn({ scope: true, controller: ChildController }))
+ .directive('grandChild', valueFn({ scope: true, controller: GrandChildController }));
- describe('$postLink', function() {
+ module('my');
+ inject(function($compile, $rootScope) {
- it('should call `$postLink`, if provided, after the element has completed linking (i.e. post-link)', function() {
+ element = $compile('
')($rootScope);
+ $rootScope.$apply('show = true');
+ expect(log).toEqual(['parent created', 'child created', 'grand child created']);
+ log = [];
+ $rootScope.$apply('show = false');
+ expect(log).toEqual(['parent destroyed', 'child destroyed', 'grand child destroyed']);
+ });
+ });
+ });
- var log = [];
- function Controller1() { }
- Controller1.prototype.$postLink = function() { log.push('d1 view init'); };
+ describe('$postLink', function() {
- function Controller2() { }
- Controller2.prototype.$postLink = function() { log.push('d2 view init'); };
+ it('should call `$postLink`, if provided, after the element has completed linking (i.e. post-link)', function() {
- angular.module('my', [])
- .directive('d1', valueFn({
- controller: Controller1,
- link: { pre: function(s, e) { log.push('d1 pre: ' + e.text()); }, post: function(s, e) { log.push('d1 post: ' + e.text()); } },
- template: '
'
- }))
- .directive('d2', valueFn({
- controller: Controller2,
- link: { pre: function(s, e) { log.push('d2 pre: ' + e.text()); }, post: function(s, e) { log.push('d2 post: ' + e.text()); } },
- template: 'loaded'
- }));
+ var log = [];
- module('my');
- inject(function($compile, $rootScope) {
- element = $compile('
')($rootScope);
- expect(log).toEqual([
- 'd1 pre: loaded',
- 'd2 pre: loaded',
- 'd2 post: loaded',
- 'd2 view init',
- 'd1 post: loaded',
- 'd1 view init'
- ]);
- });
- });
- });
+ function Controller1() { }
+ Controller1.prototype.$postLink = function() { log.push('d1 view init'); };
- describe('$doCheck', function() {
- it('should call `$doCheck`, if provided, for each digest cycle, after $onChanges and $onInit', function() {
- var log = [];
+ function Controller2() { }
+ Controller2.prototype.$postLink = function() { log.push('d2 view init'); };
- function TestController() { }
- TestController.prototype.$doCheck = function() { log.push('$doCheck'); };
- TestController.prototype.$onChanges = function() { log.push('$onChanges'); };
- TestController.prototype.$onInit = function() { log.push('$onInit'); };
+ angular.module('my', [])
+ .directive('d1', valueFn({
+ controller: Controller1,
+ link: { pre: function(s, e) { log.push('d1 pre: ' + e.text()); }, post: function(s, e) { log.push('d1 post: ' + e.text()); } },
+ template: '
'
+ }))
+ .directive('d2', valueFn({
+ controller: Controller2,
+ link: { pre: function(s, e) { log.push('d2 pre: ' + e.text()); }, post: function(s, e) { log.push('d2 post: ' + e.text()); } },
+ template: 'loaded'
+ }));
- angular.module('my', [])
- .component('dcc', {
- controller: TestController,
- bindings: { 'prop1': '<' }
+ module('my');
+ inject(function($compile, $rootScope) {
+ element = $compile('
')($rootScope);
+ expect(log).toEqual([
+ 'd1 pre: loaded',
+ 'd2 pre: loaded',
+ 'd2 post: loaded',
+ 'd2 view init',
+ 'd1 post: loaded',
+ 'd1 view init'
+ ]);
+ });
});
+ });
- module('my');
- inject(function($compile, $rootScope) {
- element = $compile('
')($rootScope);
- expect(log).toEqual([
- '$onChanges',
- '$onInit',
- '$doCheck'
- ]);
+ describe('$doCheck', function() {
+ it('should call `$doCheck`, if provided, for each digest cycle, after $onChanges and $onInit', function() {
+ var log = [];
- // Clear log
- log = [];
+ function TestController() { }
+ TestController.prototype.$doCheck = function() { log.push('$doCheck'); };
+ TestController.prototype.$onChanges = function() { log.push('$onChanges'); };
+ TestController.prototype.$onInit = function() { log.push('$onInit'); };
- $rootScope.$apply();
- expect(log).toEqual([
- '$doCheck',
- '$doCheck'
- ]);
+ angular.module('my', [])
+ .component('dcc', {
+ controller: TestController,
+ bindings: { 'prop1': '<' }
+ });
- // Clear log
- log = [];
+ module('my');
+ inject(function($compile, $rootScope) {
+ element = $compile('
')($rootScope);
+ expect(log).toEqual([
+ '$onChanges',
+ '$onInit',
+ '$doCheck'
+ ]);
+
+ // Clear log
+ log = [];
+
+ $rootScope.$apply();
+ expect(log).toEqual([
+ '$doCheck',
+ '$doCheck'
+ ]);
+
+ // Clear log
+ log = [];
+
+ $rootScope.$apply('val = 2');
+ expect(log).toEqual([
+ '$doCheck',
+ '$onChanges',
+ '$doCheck'
+ ]);
+ });
+ });
- $rootScope.$apply('val = 2');
- expect(log).toEqual([
- '$doCheck',
- '$onChanges',
- '$doCheck'
- ]);
- });
- });
+ it('should work if $doCheck is provided in the constructor', function() {
+ var log = [];
- it('should work if $doCheck is provided in the constructor', function() {
- var log = [];
+ function TestController() {
+ this.$doCheck = function() { log.push('$doCheck'); };
+ this.$onChanges = function() { log.push('$onChanges'); };
+ this.$onInit = function() { log.push('$onInit'); };
+ }
- function TestController() {
- this.$doCheck = function() { log.push('$doCheck'); };
- this.$onChanges = function() { log.push('$onChanges'); };
- this.$onInit = function() { log.push('$onInit'); };
- }
+ angular.module('my', [])
+ .component('dcc', {
+ controller: TestController,
+ bindings: { 'prop1': '<' }
+ });
- angular.module('my', [])
- .component('dcc', {
- controller: TestController,
- bindings: { 'prop1': '<' }
+ module('my');
+ inject(function($compile, $rootScope) {
+ element = $compile('
')($rootScope);
+ expect(log).toEqual([
+ '$onChanges',
+ '$onInit',
+ '$doCheck'
+ ]);
+
+ // Clear log
+ log = [];
+
+ $rootScope.$apply();
+ expect(log).toEqual([
+ '$doCheck',
+ '$doCheck'
+ ]);
+
+ // Clear log
+ log = [];
+
+ $rootScope.$apply('val = 2');
+ expect(log).toEqual([
+ '$doCheck',
+ '$onChanges',
+ '$doCheck'
+ ]);
+ });
});
+ });
- module('my');
- inject(function($compile, $rootScope) {
- element = $compile('
')($rootScope);
- expect(log).toEqual([
- '$onChanges',
- '$onInit',
- '$doCheck'
- ]);
-
- // Clear log
- log = [];
+ describe('$onChanges', function() {
- $rootScope.$apply();
- expect(log).toEqual([
- '$doCheck',
- '$doCheck'
- ]);
+ it('should call `$onChanges`, if provided, when a one-way (`<`) or interpolation (`@`) bindings are updated', function() {
+ var log = [];
+ function TestController() { }
+ TestController.prototype.$onChanges = function(change) { log.push(change); };
- // Clear log
- log = [];
+ angular.module('my', [])
+ .component('c1', {
+ controller: TestController,
+ bindings: { 'prop1': '<', 'prop2': '<', 'other': '=', 'attr': '@' }
+ });
- $rootScope.$apply('val = 2');
- expect(log).toEqual([
- '$doCheck',
- '$onChanges',
- '$doCheck'
- ]);
- });
- });
- });
+ module('my');
+ inject(function($compile, $rootScope) {
+ // Setup a watch to indicate some complicated updated logic
+ $rootScope.$watch('val', function(val, oldVal) { $rootScope.val2 = val * 2; });
+ // Setup the directive with two bindings
+ element = $compile('
')($rootScope);
+
+ expect(log).toEqual([
+ {
+ prop1: jasmine.objectContaining({currentValue: undefined}),
+ prop2: jasmine.objectContaining({currentValue: undefined}),
+ attr: jasmine.objectContaining({currentValue: ''})
+ }
+ ]);
- describe('$onChanges', function() {
+ // Clear the initial changes from the log
+ log = [];
- it('should call `$onChanges`, if provided, when a one-way (`<`) or interpolation (`@`) bindings are updated', function() {
- var log = [];
- function TestController() { }
- TestController.prototype.$onChanges = function(change) { log.push(change); };
+ // Update val to trigger the onChanges
+ $rootScope.$apply('val = 42');
- angular.module('my', [])
- .component('c1', {
- controller: TestController,
- bindings: { 'prop1': '<', 'prop2': '<', 'other': '=', 'attr': '@' }
+ // Now we should have a single changes entry in the log
+ expect(log).toEqual([
+ {
+ prop1: jasmine.objectContaining({currentValue: 42}),
+ prop2: jasmine.objectContaining({currentValue: 84})
+ }
+ ]);
+
+ // Clear the log
+ log = [];
+
+ // Update val to trigger the onChanges
+ $rootScope.$apply('val = 17');
+ // Now we should have a single changes entry in the log
+ expect(log).toEqual([
+ {
+ prop1: jasmine.objectContaining({previousValue: 42, currentValue: 17}),
+ prop2: jasmine.objectContaining({previousValue: 84, currentValue: 34})
+ }
+ ]);
+
+ // Clear the log
+ log = [];
+
+ // Update val3 to trigger the "other" two-way binding
+ $rootScope.$apply('val3 = 63');
+ // onChanges should not have been called
+ expect(log).toEqual([]);
+
+ // Update val4 to trigger the "attr" interpolation binding
+ $rootScope.$apply('val4 = 22');
+ // onChanges should not have been called
+ expect(log).toEqual([
+ {
+ attr: jasmine.objectContaining({previousValue: '', currentValue: '22'})
+ }
+ ]);
+ });
});
- module('my');
- inject(function($compile, $rootScope) {
- // Setup a watch to indicate some complicated updated logic
- $rootScope.$watch('val', function(val, oldVal) { $rootScope.val2 = val * 2; });
- // Setup the directive with two bindings
- element = $compile('
')($rootScope);
-
- expect(log).toEqual([
- {
- prop1: jasmine.objectContaining({currentValue: undefined}),
- prop2: jasmine.objectContaining({currentValue: undefined}),
- attr: jasmine.objectContaining({currentValue: ''})
- }
- ]);
-
- // Clear the initial changes from the log
- log = [];
- // Update val to trigger the onChanges
- $rootScope.$apply('val = 42');
+ it('should trigger `$onChanges` even if the inner value already equals the new outer value', function() {
+ var log = [];
+ function TestController() { }
+ TestController.prototype.$onChanges = function(change) { log.push(change); };
- // Now we should have a single changes entry in the log
- expect(log).toEqual([
- {
- prop1: jasmine.objectContaining({currentValue: 42}),
- prop2: jasmine.objectContaining({currentValue: 84})
- }
- ]);
-
- // Clear the log
- log = [];
-
- // Update val to trigger the onChanges
- $rootScope.$apply('val = 17');
- // Now we should have a single changes entry in the log
- expect(log).toEqual([
- {
- prop1: jasmine.objectContaining({previousValue: 42, currentValue: 17}),
- prop2: jasmine.objectContaining({previousValue: 84, currentValue: 34})
- }
- ]);
-
- // Clear the log
- log = [];
-
- // Update val3 to trigger the "other" two-way binding
- $rootScope.$apply('val3 = 63');
- // onChanges should not have been called
- expect(log).toEqual([]);
-
- // Update val4 to trigger the "attr" interpolation binding
- $rootScope.$apply('val4 = 22');
- // onChanges should not have been called
- expect(log).toEqual([
- {
- attr: jasmine.objectContaining({previousValue: '', currentValue: '22'})
- }
- ]);
- });
- });
+ angular.module('my', [])
+ .component('c1', {
+ controller: TestController,
+ bindings: { 'prop1': '<' }
+ });
+ module('my');
+ inject(function($compile, $rootScope) {
+ element = $compile('
')($rootScope);
- it('should trigger `$onChanges` even if the inner value already equals the new outer value', function() {
- var log = [];
- function TestController() { }
- TestController.prototype.$onChanges = function(change) { log.push(change); };
+ $rootScope.$apply('val = 1');
+ expect(log.pop()).toEqual({prop1: jasmine.objectContaining({previousValue: undefined, currentValue: 1})});
- angular.module('my', [])
- .component('c1', {
- controller: TestController,
- bindings: { 'prop1': '<' }
+ element.isolateScope().$ctrl.prop1 = 2;
+ $rootScope.$apply('val = 2');
+ expect(log.pop()).toEqual({prop1: jasmine.objectContaining({previousValue: 1, currentValue: 2})});
+ });
});
- module('my');
- inject(function($compile, $rootScope) {
- element = $compile('
')($rootScope);
- $rootScope.$apply('val = 1');
- expect(log.pop()).toEqual({prop1: jasmine.objectContaining({previousValue: undefined, currentValue: 1})});
+ it('should pass the original value as `previousValue` even if there were multiple changes in a single digest', function() {
+ var log = [];
+ function TestController() { }
+ TestController.prototype.$onChanges = function(change) { log.push(change); };
- element.isolateScope().$ctrl.prop1 = 2;
- $rootScope.$apply('val = 2');
- expect(log.pop()).toEqual({prop1: jasmine.objectContaining({previousValue: 1, currentValue: 2})});
- });
- });
+ angular.module('my', [])
+ .component('c1', {
+ controller: TestController,
+ bindings: { 'prop': '<' }
+ });
+ module('my');
+ inject(function($compile, $rootScope) {
+ element = $compile('
')($rootScope);
- it('should pass the original value as `previousValue` even if there were multiple changes in a single digest', function() {
- var log = [];
- function TestController() { }
- TestController.prototype.$onChanges = function(change) { log.push(change); };
+ // We add this watch after the compilation to ensure that it will run after the binding watchers
+ // therefore triggering the thing that this test is hoping to enfore
+ $rootScope.$watch('a', function(val) { $rootScope.b = val * 2; });
- angular.module('my', [])
- .component('c1', {
- controller: TestController,
- bindings: { 'prop': '<' }
- });
+ expect(log).toEqual([{prop: jasmine.objectContaining({currentValue: undefined})}]);
- module('my');
- inject(function($compile, $rootScope) {
- element = $compile('
')($rootScope);
+ // Clear the initial values from the log
+ log = [];
- // We add this watch after the compilation to ensure that it will run after the binding watchers
- // therefore triggering the thing that this test is hoping to enfore
- $rootScope.$watch('a', function(val) { $rootScope.b = val * 2; });
+ // Update val to trigger the onChanges
+ $rootScope.$apply('a = 42');
+ // Now the change should have the real previous value (undefined), not the intermediate one (42)
+ expect(log).toEqual([{prop: jasmine.objectContaining({currentValue: 126})}]);
- expect(log).toEqual([{prop: jasmine.objectContaining({currentValue: undefined})}]);
+ // Clear the log
+ log = [];
- // Clear the initial values from the log
- log = [];
+ // Update val to trigger the onChanges
+ $rootScope.$apply('a = 7');
+ // Now the change should have the real previous value (126), not the intermediate one, (91)
+ expect(log).toEqual([{prop: jasmine.objectContaining({previousValue: 126, currentValue: 21})}]);
+ });
+ });
- // Update val to trigger the onChanges
- $rootScope.$apply('a = 42');
- // Now the change should have the real previous value (undefined), not the intermediate one (42)
- expect(log).toEqual([{prop: jasmine.objectContaining({currentValue: 126})}]);
- // Clear the log
- log = [];
+ it('should trigger an initial onChanges call for each binding with the `isFirstChange()` returning true', function() {
+ var log = [];
+ function TestController() { }
+ TestController.prototype.$onChanges = function(change) { log.push(change); };
- // Update val to trigger the onChanges
- $rootScope.$apply('a = 7');
- // Now the change should have the real previous value (126), not the intermediate one, (91)
- expect(log).toEqual([{prop: jasmine.objectContaining({previousValue: 126, currentValue: 21})}]);
- });
- });
+ angular.module('my', [])
+ .component('c1', {
+ controller: TestController,
+ bindings: { 'prop': '<', attr: '@' }
+ });
+ module('my');
+ inject(function($compile, $rootScope) {
- it('should trigger an initial onChanges call for each binding with the `isFirstChange()` returning true', function() {
- var log = [];
- function TestController() { }
- TestController.prototype.$onChanges = function(change) { log.push(change); };
+ $rootScope.$apply('a = 7');
+ element = $compile('
')($rootScope);
- angular.module('my', [])
- .component('c1', {
- controller: TestController,
- bindings: { 'prop': '<', attr: '@' }
+ expect(log).toEqual([
+ {
+ prop: jasmine.objectContaining({currentValue: 7}),
+ attr: jasmine.objectContaining({currentValue: '7'})
+ }
+ ]);
+ expect(log[0].prop.isFirstChange()).toEqual(true);
+ expect(log[0].attr.isFirstChange()).toEqual(true);
+
+ log = [];
+ $rootScope.$apply('a = 9');
+ expect(log).toEqual([
+ {
+ prop: jasmine.objectContaining({previousValue: 7, currentValue: 9}),
+ attr: jasmine.objectContaining({previousValue: '7', currentValue: '9'})
+ }
+ ]);
+ expect(log[0].prop.isFirstChange()).toEqual(false);
+ expect(log[0].attr.isFirstChange()).toEqual(false);
+ });
});
- module('my');
- inject(function($compile, $rootScope) {
-
- $rootScope.$apply('a = 7');
- element = $compile('
')($rootScope);
- expect(log).toEqual([
- {
- prop: jasmine.objectContaining({currentValue: 7}),
- attr: jasmine.objectContaining({currentValue: '7'})
+ it('should trigger an initial onChanges call for each binding even if the hook is defined in the constructor', function() {
+ var log = [];
+ function TestController() {
+ this.$onChanges = function(change) { log.push(change); };
}
- ]);
- expect(log[0].prop.isFirstChange()).toEqual(true);
- expect(log[0].attr.isFirstChange()).toEqual(true);
-
- log = [];
- $rootScope.$apply('a = 9');
- expect(log).toEqual([
- {
- prop: jasmine.objectContaining({previousValue: 7, currentValue: 9}),
- attr: jasmine.objectContaining({previousValue: '7', currentValue: '9'})
- }
- ]);
- expect(log[0].prop.isFirstChange()).toEqual(false);
- expect(log[0].attr.isFirstChange()).toEqual(false);
- });
- });
+ angular.module('my', [])
+ .component('c1', {
+ controller: TestController,
+ bindings: { 'prop': '<', attr: '@' }
+ });
- it('should trigger an initial onChanges call for each binding even if the hook is defined in the constructor', function() {
- var log = [];
- function TestController() {
- this.$onChanges = function(change) { log.push(change); };
- }
+ module('my');
+ inject(function($compile, $rootScope) {
+ $rootScope.$apply('a = 7');
+ element = $compile('
')($rootScope);
- angular.module('my', [])
- .component('c1', {
- controller: TestController,
- bindings: { 'prop': '<', attr: '@' }
+ expect(log).toEqual([
+ {
+ prop: jasmine.objectContaining({currentValue: 7}),
+ attr: jasmine.objectContaining({currentValue: '7'})
+ }
+ ]);
+ expect(log[0].prop.isFirstChange()).toEqual(true);
+ expect(log[0].attr.isFirstChange()).toEqual(true);
+
+ log = [];
+ $rootScope.$apply('a = 10');
+ expect(log).toEqual([
+ {
+ prop: jasmine.objectContaining({previousValue: 7, currentValue: 10}),
+ attr: jasmine.objectContaining({previousValue: '7', currentValue: '10'})
+ }
+ ]);
+ expect(log[0].prop.isFirstChange()).toEqual(false);
+ expect(log[0].attr.isFirstChange()).toEqual(false);
+ });
});
- module('my');
- inject(function($compile, $rootScope) {
- $rootScope.$apply('a = 7');
- element = $compile('
')($rootScope);
- expect(log).toEqual([
- {
- prop: jasmine.objectContaining({currentValue: 7}),
- attr: jasmine.objectContaining({currentValue: '7'})
- }
- ]);
- expect(log[0].prop.isFirstChange()).toEqual(true);
- expect(log[0].attr.isFirstChange()).toEqual(true);
-
- log = [];
- $rootScope.$apply('a = 10');
- expect(log).toEqual([
- {
- prop: jasmine.objectContaining({previousValue: 7, currentValue: 10}),
- attr: jasmine.objectContaining({previousValue: '7', currentValue: '10'})
- }
- ]);
- expect(log[0].prop.isFirstChange()).toEqual(false);
- expect(log[0].attr.isFirstChange()).toEqual(false);
- });
- });
+ it('should not call `$onChanges` twice even when the initial value is `NaN`', function() {
+ var onChangesSpy = jasmine.createSpy('$onChanges');
+ module(function($compileProvider) {
+ $compileProvider.component('test', {
+ bindings: {prop: '<', attr: '@'},
+ controller: function TestController() {
+ this.$onChanges = onChangesSpy;
+ }
+ });
+ });
- it('should only trigger one extra digest however many controllers have changes', function() {
- var log = [];
- function TestController1() { }
- TestController1.prototype.$onChanges = function(change) { log.push(['TestController1', change]); };
- function TestController2() { }
- TestController2.prototype.$onChanges = function(change) { log.push(['TestController2', change]); };
+ inject(function($compile, $rootScope) {
+ var template = '
' +
+ '
';
+ $rootScope.a = 'foo';
+ $rootScope.b = NaN;
- angular.module('my', [])
- .component('c1', {
- controller: TestController1,
- bindings: {'prop': '<'}
- })
- .component('c2', {
- controller: TestController2,
- bindings: {'prop': '<'}
- });
+ element = $compile(template)($rootScope);
+ $rootScope.$digest();
- module('my');
- inject(function($compile, $rootScope) {
+ expect(onChangesSpy).toHaveBeenCalledTimes(2);
+ expect(onChangesSpy.calls.argsFor(0)[0]).toEqual({
+ prop: jasmine.objectContaining({currentValue: 'foo'}),
+ attr: jasmine.objectContaining({currentValue: 'foo'})
+ });
+ expect(onChangesSpy.calls.argsFor(1)[0]).toEqual({
+ prop: jasmine.objectContaining({currentValue: NaN}),
+ attr: jasmine.objectContaining({currentValue: 'NaN'})
+ });
- // Create a watcher to count the number of digest cycles
- var watchCount = 0;
- $rootScope.$watch(function() { watchCount++; });
+ onChangesSpy.calls.reset();
+ $rootScope.$apply('a = "bar"; b = 42');
- // Setup two sibling components with bindings that will change
- element = $compile('
')($rootScope);
+ expect(onChangesSpy).toHaveBeenCalledTimes(2);
+ expect(onChangesSpy.calls.argsFor(0)[0]).toEqual({
+ prop: jasmine.objectContaining({previousValue: 'foo', currentValue: 'bar'}),
+ attr: jasmine.objectContaining({previousValue: 'foo', currentValue: 'bar'})
+ });
+ expect(onChangesSpy.calls.argsFor(1)[0]).toEqual({
+ prop: jasmine.objectContaining({previousValue: NaN, currentValue: 42}),
+ attr: jasmine.objectContaining({previousValue: 'NaN', currentValue: '42'})
+ });
+ });
+ });
- // Clear out initial changes
- log = [];
- // Update val to trigger the onChanges
- $rootScope.$apply('val1 = 42; val2 = 17');
+ it('should only trigger one extra digest however many controllers have changes', function() {
+ var log = [];
+ function TestController1() { }
+ TestController1.prototype.$onChanges = function(change) { log.push(['TestController1', change]); };
+ function TestController2() { }
+ TestController2.prototype.$onChanges = function(change) { log.push(['TestController2', change]); };
- expect(log).toEqual([
- ['TestController1', {prop: jasmine.objectContaining({currentValue: 42})}],
- ['TestController2', {prop: jasmine.objectContaining({currentValue: 17})}]
- ]);
- // A single apply should only trigger three turns of the digest loop
- expect(watchCount).toEqual(3);
- });
- });
+ angular.module('my', [])
+ .component('c1', {
+ controller: TestController1,
+ bindings: {'prop': '<'}
+ })
+ .component('c2', {
+ controller: TestController2,
+ bindings: {'prop': '<'}
+ });
+ module('my');
+ inject(function($compile, $rootScope) {
- it('should cope with changes occuring inside `$onChanges()` hooks', function() {
- var log = [];
- function OuterController() {
- this.prop1 = 0;
- }
- OuterController.prototype.$onChanges = function(change) {
- log.push(['OuterController', change]);
- // Make a change to the inner component
- this.b = this.prop1 * 2;
- };
+ // Create a watcher to count the number of digest cycles
+ var watchCount = 0;
+ $rootScope.$watch(function() { watchCount++; });
- function InnerController() { }
- InnerController.prototype.$onChanges = function(change) { log.push(['InnerController', change]); };
+ // Setup two sibling components with bindings that will change
+ element = $compile('
')($rootScope);
- angular.module('my', [])
- .component('outer', {
- controller: OuterController,
- bindings: {'prop1': '<'},
- template: '
'
- })
- .component('inner', {
- controller: InnerController,
- bindings: {'prop2': '<'}
+ // Clear out initial changes
+ log = [];
+
+ // Update val to trigger the onChanges
+ $rootScope.$apply('val1 = 42; val2 = 17');
+
+ expect(log).toEqual([
+ ['TestController1', {prop: jasmine.objectContaining({currentValue: 42})}],
+ ['TestController2', {prop: jasmine.objectContaining({currentValue: 17})}]
+ ]);
+ // A single apply should only trigger three turns of the digest loop
+ expect(watchCount).toEqual(3);
+ });
});
- module('my');
- inject(function($compile, $rootScope) {
- // Setup the directive with two bindings
- element = $compile('
')($rootScope);
+ it('should cope with changes occuring inside `$onChanges()` hooks', function() {
+ var log = [];
+ function OuterController() {}
+ OuterController.prototype.$onChanges = function(change) {
+ log.push(['OuterController', change]);
+ // Make a change to the inner component
+ this.b = this.prop1 * 2;
+ };
- // Clear out initial changes
- log = [];
+ function InnerController() { }
+ InnerController.prototype.$onChanges = function(change) { log.push(['InnerController', change]); };
- // Update val to trigger the onChanges
- $rootScope.$apply('a = 42');
+ angular.module('my', [])
+ .component('outer', {
+ controller: OuterController,
+ bindings: {'prop1': '<'},
+ template: '
'
+ })
+ .component('inner', {
+ controller: InnerController,
+ bindings: {'prop2': '<'}
+ });
- expect(log).toEqual([
- ['OuterController', {prop1: jasmine.objectContaining({currentValue: 42})}],
- ['InnerController', {prop2: jasmine.objectContaining({currentValue: 84})}]
- ]);
- });
- });
+ module('my');
+ inject(function($compile, $rootScope) {
+ // Setup the directive with two bindings
+ element = $compile('
')($rootScope);
- it('should throw an error if `$onChanges()` hooks are not stable', function() {
- function TestController() {}
- TestController.prototype.$onChanges = function(change) {
- this.onChange();
- };
+ // Clear out initial changes
+ log = [];
+
+ // Update val to trigger the onChanges
+ $rootScope.$apply('a = 42');
- angular.module('my', [])
- .component('c1', {
- controller: TestController,
- bindings: {'prop': '<', onChange: '&'}
+ expect(log).toEqual([
+ ['OuterController', {prop1: jasmine.objectContaining({previousValue: undefined, currentValue: 42})}],
+ ['InnerController', {prop2: jasmine.objectContaining({previousValue: NaN, currentValue: 84})}]
+ ]);
+ });
});
- module('my');
- inject(function($compile, $rootScope) {
- // Setup the directive with bindings that will keep updating the bound value forever
- element = $compile('
')($rootScope);
+ it('should throw an error if `$onChanges()` hooks are not stable', function() {
+ function TestController() {}
+ TestController.prototype.$onChanges = function(change) {
+ this.onChange();
+ };
- // Update val to trigger the unstable onChanges, which will result in an error
- expect(function() {
- $rootScope.$apply('a = 42');
- }).toThrowMinErr('$compile', 'infchng');
+ angular.module('my', [])
+ .component('c1', {
+ controller: TestController,
+ bindings: {'prop': '<', onChange: '&'}
+ });
- dealoc(element);
- element = $compile('
')($rootScope);
- $rootScope.$apply('b = 24');
- $rootScope.$apply('b = 48');
- });
- });
+ module('my');
+ inject(function($compile, $rootScope) {
+ // Setup the directive with bindings that will keep updating the bound value forever
+ element = $compile('
')($rootScope);
- it('should log an error if `$onChanges()` hooks are not stable', function() {
- function TestController() {}
- TestController.prototype.$onChanges = function(change) {
- this.onChange();
- };
+ // Update val to trigger the unstable onChanges, which will result in an error
+ expect(function() {
+ $rootScope.$apply('a = 42');
+ }).toThrowMinErr('$compile', 'infchng');
- angular.module('my', [])
- .component('c1', {
- controller: TestController,
- bindings: {'prop': '<', onChange: '&'}
- })
- .config(function($exceptionHandlerProvider) {
- // We need to test with the exceptionHandler not rethrowing...
- $exceptionHandlerProvider.mode('log');
+ dealoc(element);
+ element = $compile('
')($rootScope);
+ $rootScope.$apply('b = 24');
+ $rootScope.$apply('b = 48');
+ });
});
- module('my');
- inject(function($compile, $rootScope, $exceptionHandler) {
- // Setup the directive with bindings that will keep updating the bound value forever
- element = $compile('
')($rootScope);
+ it('should log an error if `$onChanges()` hooks are not stable', function() {
+ function TestController() {}
+ TestController.prototype.$onChanges = function(change) {
+ this.onChange();
+ };
- // Update val to trigger the unstable onChanges, which will result in an error
- $rootScope.$apply('a = 42');
- expect($exceptionHandler.errors.length).toEqual(1);
- expect($exceptionHandler.errors[0].toString()).toContain('[$compile:infchng] 10 $onChanges() iterations reached.');
- });
- });
+ angular.module('my', [])
+ .component('c1', {
+ controller: TestController,
+ bindings: {'prop': '<', onChange: '&'}
+ })
+ .config(function($exceptionHandlerProvider) {
+ // We need to test with the exceptionHandler not rethrowing...
+ $exceptionHandlerProvider.mode('log');
+ });
+ module('my');
+ inject(function($compile, $rootScope, $exceptionHandler) {
- it('should continue to trigger other `$onChanges` hooks if one throws an error', function() {
- function ThrowingController() {
- this.$onChanges = function(change) {
- throw new Error('bad hook');
- };
- }
- function LoggingController($log) {
- this.$onChanges = function(change) {
- $log.info('onChange');
- };
- }
+ // Setup the directive with bindings that will keep updating the bound value forever
+ element = $compile('
')($rootScope);
- angular.module('my', [])
- .component('c1', {
- controller: ThrowingController,
- bindings: {'prop': '<'}
- })
- .component('c2', {
- controller: LoggingController,
- bindings: {'prop': '<'}
- })
- .config(function($exceptionHandlerProvider) {
- // We need to test with the exceptionHandler not rethrowing...
- $exceptionHandlerProvider.mode('log');
+ // Update val to trigger the unstable onChanges, which will result in an error
+ $rootScope.$apply('a = 42');
+ expect($exceptionHandler.errors.length).toEqual(1);
+ expect($exceptionHandler.errors[0].toString()).toContain('[$compile:infchng] 10 $onChanges() iterations reached.');
+ });
});
- module('my');
- inject(function($compile, $rootScope, $exceptionHandler, $log) {
- // Setup the directive with bindings that will keep updating the bound value forever
- element = $compile('
')($rootScope);
+ it('should continue to trigger other `$onChanges` hooks if one throws an error', function() {
+ function ThrowingController() {
+ this.$onChanges = function(change) {
+ throw new Error('bad hook');
+ };
+ }
+ function LoggingController($log) {
+ this.$onChanges = function(change) {
+ $log.info('onChange');
+ };
+ }
- // The first component's error should be logged
- expect($exceptionHandler.errors.pop()).toEqual(new Error('bad hook'));
+ angular.module('my', [])
+ .component('c1', {
+ controller: ThrowingController,
+ bindings: {'prop': '<'}
+ })
+ .component('c2', {
+ controller: LoggingController,
+ bindings: {'prop': '<'}
+ })
+ .config(function($exceptionHandlerProvider) {
+ // We need to test with the exceptionHandler not rethrowing...
+ $exceptionHandlerProvider.mode('log');
+ });
- // The second component's changes should still be called
- expect($log.info.logs.pop()).toEqual(['onChange']);
+ module('my');
+ inject(function($compile, $rootScope, $exceptionHandler, $log) {
- $rootScope.$apply('a = 42');
+ // Setup the directive with bindings that will keep updating the bound value forever
+ element = $compile('
')($rootScope);
- // The first component's error should be logged
- var errors = $exceptionHandler.errors.pop();
- expect(errors[0]).toEqual(new Error('bad hook'));
+ // The first component's error should be logged
+ expect($exceptionHandler.errors.pop()).toEqual(new Error('bad hook'));
- // The second component's changes should still be called
- expect($log.info.logs.pop()).toEqual(['onChange']);
- });
- });
+ // The second component's changes should still be called
+ expect($log.info.logs.pop()).toEqual(['onChange']);
+ $rootScope.$apply('a = 42');
- it('should collect up all `$onChanges` errors into one throw', function() {
- function ThrowingController() {
- this.$onChanges = function(change) {
- throw new Error('bad hook: ' + this.prop);
- };
- }
+ // The first component's error should be logged
+ var errors = $exceptionHandler.errors.pop();
+ expect(errors[0]).toEqual(new Error('bad hook'));
- angular.module('my', [])
- .component('c1', {
- controller: ThrowingController,
- bindings: {'prop': '<'}
- })
- .config(function($exceptionHandlerProvider) {
- // We need to test with the exceptionHandler not rethrowing...
- $exceptionHandlerProvider.mode('log');
+ // The second component's changes should still be called
+ expect($log.info.logs.pop()).toEqual(['onChange']);
+ });
});
- module('my');
- inject(function($compile, $rootScope, $exceptionHandler, $log) {
- // Setup the directive with bindings that will keep updating the bound value forever
- element = $compile('
')($rootScope);
+ it('should collect up all `$onChanges` errors into one throw', function() {
+ function ThrowingController() {
+ this.$onChanges = function(change) {
+ throw new Error('bad hook: ' + this.prop);
+ };
+ }
- // Both component's errors should be logged
- expect($exceptionHandler.errors.pop()).toEqual(new Error('bad hook: NaN'));
- expect($exceptionHandler.errors.pop()).toEqual(new Error('bad hook: undefined'));
+ angular.module('my', [])
+ .component('c1', {
+ controller: ThrowingController,
+ bindings: {'prop': '<'}
+ })
+ .config(function($exceptionHandlerProvider) {
+ // We need to test with the exceptionHandler not rethrowing...
+ $exceptionHandlerProvider.mode('log');
+ });
- $rootScope.$apply('a = 42');
+ module('my');
+ inject(function($compile, $rootScope, $exceptionHandler, $log) {
- // Both component's error should be logged
- var errors = $exceptionHandler.errors.pop();
- expect(errors.pop()).toEqual(new Error('bad hook: 84'));
- expect(errors.pop()).toEqual(new Error('bad hook: 42'));
- });
- });
- });
- });
+ // Setup the directive with bindings that will keep updating the bound value forever
+ element = $compile('
')($rootScope);
+ // Both component's errors should be logged
+ expect($exceptionHandler.errors.pop()).toEqual(new Error('bad hook: NaN'));
+ expect($exceptionHandler.errors.pop()).toEqual(new Error('bad hook: undefined'));
- describe('isolated locals', function() {
- var componentScope, regularScope;
+ $rootScope.$apply('a = 42');
- beforeEach(module(function() {
- directive('myComponent', function() {
- return {
- scope: {
- attr: '@',
- attrAlias: '@attr',
- ref: '=',
- refAlias: '= ref',
- reference: '=',
- optref: '=?',
- optrefAlias: '=? optref',
- optreference: '=?',
- colref: '=*',
- colrefAlias: '=* colref',
- owRef: '<',
- owRefAlias: '< owRef',
- owOptref: '',
- owOptrefAlias: ' owOptref',
- expr: '&',
- optExpr: '&?',
- exprAlias: '&expr',
- constructor: '&?'
- },
- link: function(scope) {
- componentScope = scope;
- }
- };
- });
- directive('badDeclaration', function() {
- return {
- scope: { attr: 'xxx' }
- };
- });
- directive('storeScope', function() {
- return {
- link: function(scope) {
- regularScope = scope;
- }
- };
+ // Both component's error should be logged
+ var errors = $exceptionHandler.errors.pop();
+ expect(errors.pop()).toEqual(new Error('bad hook: 84'));
+ expect(errors.pop()).toEqual(new Error('bad hook: 42'));
+ });
+ });
+ });
});
- }));
- it('should give other directives the parent scope', inject(function($rootScope) {
- compile('
');
- $rootScope.$apply(function() {
- $rootScope.value = 'from-parent';
- });
- expect(element.find('input').val()).toBe('from-parent');
- expect(componentScope).not.toBe(regularScope);
- expect(componentScope.$parent).toBe(regularScope);
- }));
+ describe('isolated locals', function() {
+ var componentScope, regularScope;
+ beforeEach(module(function() {
+ directive('myComponent', function() {
+ return {
+ scope: {
+ attr: '@',
+ attrAlias: '@attr',
+ ref: '=',
+ refAlias: '= ref',
+ reference: '=',
+ optref: '=?',
+ optrefAlias: '=? optref',
+ optreference: '=?',
+ colref: '=*',
+ colrefAlias: '=* colref',
+ owRef: '<',
+ owRefAlias: '< owRef',
+ owOptref: '',
+ owOptrefAlias: ' owOptref',
+ expr: '&',
+ optExpr: '&?',
+ exprAlias: '&expr',
+ constructor: '&?'
+ },
+ link: function(scope) {
+ componentScope = scope;
+ }
+ };
+ });
+ directive('badDeclaration', function() {
+ return {
+ scope: { attr: 'xxx' }
+ };
+ });
+ directive('storeScope', function() {
+ return {
+ link: function(scope) {
+ regularScope = scope;
+ }
+ };
+ });
+ }));
- it('should not give the isolate scope to other directive template', function() {
- module(function() {
- directive('otherTplDir', function() {
- return {
- template: 'value: {{value}}'
- };
- });
- });
-
- inject(function($rootScope) {
- compile('
');
- $rootScope.$apply(function() {
- $rootScope.value = 'from-parent';
- });
+ it('should give other directives the parent scope', inject(function($rootScope) {
+ compile('
');
+ $rootScope.$apply(function() {
+ $rootScope.value = 'from-parent';
+ });
+ expect(element.find('input').val()).toBe('from-parent');
+ expect(componentScope).not.toBe(regularScope);
+ expect(componentScope.$parent).toBe(regularScope);
+ }));
- expect(element.html()).toBe('value: from-parent');
- });
- });
+ it('should not give the isolate scope to other directive template', function() {
+ module(function() {
+ directive('otherTplDir', function() {
+ return {
+ template: 'value: {{value}}'
+ };
+ });
+ });
- it('should not give the isolate scope to other directive template (with templateUrl)', function() {
- module(function() {
- directive('otherTplDir', function() {
- return {
- templateUrl: 'other.html'
- };
- });
- });
+ inject(function($rootScope) {
+ compile('
');
- inject(function($rootScope, $templateCache) {
- $templateCache.put('other.html', 'value: {{value}}');
- compile('
');
+ $rootScope.$apply(function() {
+ $rootScope.value = 'from-parent';
+ });
- $rootScope.$apply(function() {
- $rootScope.value = 'from-parent';
+ expect(element.html()).toBe('value: from-parent');
+ });
});
- expect(element.html()).toBe('value: from-parent');
- });
- });
+ it('should not give the isolate scope to other directive template (with templateUrl)', function() {
+ module(function() {
+ directive('otherTplDir', function() {
+ return {
+ templateUrl: 'other.html'
+ };
+ });
+ });
- it('should not give the isolate scope to regular child elements', function() {
- inject(function($rootScope) {
- compile('
value: {{value}}
');
+ inject(function($rootScope, $templateCache) {
+ $templateCache.put('other.html', 'value: {{value}}');
+ compile('
');
- $rootScope.$apply(function() {
- $rootScope.value = 'from-parent';
+ $rootScope.$apply(function() {
+ $rootScope.value = 'from-parent';
+ });
+
+ expect(element.html()).toBe('value: from-parent');
+ });
});
- expect(element.html()).toBe('value: from-parent');
- });
- });
+ it('should not give the isolate scope to regular child elements', function() {
+ inject(function($rootScope) {
+ compile('
value: {{value}}
');
- it('should update parent scope when "="-bound NaN changes', inject(function($compile, $rootScope) {
- $rootScope.num = NaN;
- compile('
');
- var isolateScope = element.isolateScope();
- expect(isolateScope.reference).toBeNaN();
+ $rootScope.$apply(function() {
+ $rootScope.value = 'from-parent';
+ });
- isolateScope.$apply(function(scope) { scope.reference = 64; });
- expect($rootScope.num).toBe(64);
- }));
+ expect(element.html()).toBe('value: from-parent');
+ });
+ });
- it('should update isolate scope when "="-bound NaN changes', inject(function($compile, $rootScope) {
- $rootScope.num = NaN;
- compile('
');
- var isolateScope = element.isolateScope();
- expect(isolateScope.reference).toBeNaN();
+ it('should update parent scope when "="-bound NaN changes', inject(function($compile, $rootScope) {
+ $rootScope.num = NaN;
+ compile('
');
+ var isolateScope = element.isolateScope();
+ expect(isolateScope.reference).toBeNaN();
- $rootScope.$apply(function(scope) { scope.num = 64; });
- expect(isolateScope.reference).toBe(64);
- }));
+ isolateScope.$apply(function(scope) { scope.reference = 64; });
+ expect($rootScope.num).toBe(64);
+ }));
- it('should be able to bind attribute names which are present in Object.prototype', function() {
- module(function() {
- directive('inProtoAttr', valueFn({
- scope: {
- 'constructor': '@',
- 'toString': '&',
+ it('should update isolate scope when "="-bound NaN changes', inject(function($compile, $rootScope) {
+ $rootScope.num = NaN;
+ compile('
');
+ var isolateScope = element.isolateScope();
+ expect(isolateScope.reference).toBeNaN();
- // Spidermonkey extension, may be obsolete in the future
- 'watch': '='
- }
+ $rootScope.$apply(function(scope) { scope.num = 64; });
+ expect(isolateScope.reference).toBe(64);
}));
- });
- inject(function($rootScope) {
- expect(function() {
- compile('
');
- }).not.toThrow();
- var isolateScope = element.isolateScope();
-
- expect(typeof isolateScope.constructor).toBe('string');
- expect(isArray(isolateScope.watch)).toBe(true);
- expect(typeof isolateScope.toString).toBe('function');
- expect($rootScope.value).toBeUndefined();
- isolateScope.toString();
- expect($rootScope.value).toBe(true);
- });
- });
- it('should be able to interpolate attribute names which are present in Object.prototype', function() {
- var attrs;
- module(function() {
- directive('attrExposer', valueFn({
- link: function($scope, $element, $attrs) {
- attrs = $attrs;
- }
- }));
- });
- inject(function($compile, $rootScope) {
- $compile('
')($rootScope);
- $rootScope.$apply();
- expect(attrs.toString).toBe('2');
- });
- });
+ it('should be able to bind attribute names which are present in Object.prototype', function() {
+ module(function() {
+ directive('inProtoAttr', valueFn({
+ scope: {
+ 'constructor': '@',
+ 'toString': '&',
- it('should not initialize scope value if optional expression binding is not passed', inject(function($compile) {
- compile('
');
- var isolateScope = element.isolateScope();
- expect(isolateScope.optExpr).toBeUndefined();
- }));
+ // Spidermonkey extension, may be obsolete in the future
+ 'watch': '='
+ }
+ }));
+ });
+ inject(function($rootScope) {
+ expect(function() {
+ compile('
');
+ }).not.toThrow();
+ var isolateScope = element.isolateScope();
+ expect(typeof isolateScope.constructor).toBe('string');
+ expect(isArray(isolateScope.watch)).toBe(true);
+ expect(typeof isolateScope.toString).toBe('function');
+ expect($rootScope.value).toBeUndefined();
+ isolateScope.toString();
+ expect($rootScope.value).toBe(true);
+ });
+ });
- it('should not initialize scope value if optional expression binding with Object.prototype name is not passed', inject(function($compile) {
- compile('
');
- var isolateScope = element.isolateScope();
- expect(isolateScope.constructor).toBe($rootScope.constructor);
- }));
+ it('should be able to interpolate attribute names which are present in Object.prototype', function() {
+ var attrs;
+ module(function() {
+ directive('attrExposer', valueFn({
+ link: function($scope, $element, $attrs) {
+ attrs = $attrs;
+ }
+ }));
+ });
+ inject(function($compile, $rootScope) {
+ $compile('
')($rootScope);
+ $rootScope.$apply();
+ expect(attrs.toString).toBe('2');
+ });
+ });
- it('should initialize scope value if optional expression binding is passed', inject(function($compile) {
- compile('
');
- var isolateScope = element.isolateScope();
- expect(typeof isolateScope.optExpr).toBe('function');
- expect(isolateScope.optExpr()).toBe('did!');
- expect($rootScope.value).toBe('did!');
- }));
+ it('should not initialize scope value if optional expression binding is not passed', inject(function($compile) {
+ compile('
');
+ var isolateScope = element.isolateScope();
+ expect(isolateScope.optExpr).toBeUndefined();
+ }));
- it('should initialize scope value if optional expression binding with Object.prototype name is passed', inject(function($compile) {
- compile('
');
- var isolateScope = element.isolateScope();
- expect(typeof isolateScope.constructor).toBe('function');
- expect(isolateScope.constructor()).toBe('did!');
- expect($rootScope.value).toBe('did!');
- }));
+ it('should not initialize scope value if optional expression binding with Object.prototype name is not passed', inject(function($compile) {
+ compile('
');
+ var isolateScope = element.isolateScope();
+ expect(isolateScope.constructor).toBe($rootScope.constructor);
+ }));
- it('should not overwrite @-bound property each digest when not present', function() {
- module(function($compileProvider) {
- $compileProvider.directive('testDir', valueFn({
- scope: {prop: '@'},
- controller: function($scope) {
- $scope.prop = $scope.prop || 'default';
- this.getProp = function() {
- return $scope.prop;
- };
- },
- controllerAs: 'ctrl',
- template: '
'
+ it('should initialize scope value if optional expression binding is passed', inject(function($compile) {
+ compile('
');
+ var isolateScope = element.isolateScope();
+ expect(typeof isolateScope.optExpr).toBe('function');
+ expect(isolateScope.optExpr()).toBe('did!');
+ expect($rootScope.value).toBe('did!');
}));
- });
- inject(function($compile, $rootScope) {
- element = $compile('
')($rootScope);
- var scope = element.isolateScope();
- expect(scope.ctrl.getProp()).toBe('default');
-
- $rootScope.$digest();
- expect(scope.ctrl.getProp()).toBe('default');
- });
- });
- it('should ignore optional "="-bound property if value is the emptry string', function() {
- module(function($compileProvider) {
- $compileProvider.directive('testDir', valueFn({
- scope: {prop: '=?'},
- controller: function($scope) {
- $scope.prop = $scope.prop || 'default';
- this.getProp = function() {
- return $scope.prop;
- };
- },
- controllerAs: 'ctrl',
- template: '
'
+ it('should initialize scope value if optional expression binding with Object.prototype name is passed', inject(function($compile) {
+ compile('
');
+ var isolateScope = element.isolateScope();
+ expect(typeof isolateScope.constructor).toBe('function');
+ expect(isolateScope.constructor()).toBe('did!');
+ expect($rootScope.value).toBe('did!');
}));
- });
- inject(function($compile, $rootScope) {
- element = $compile('
')($rootScope);
- var scope = element.isolateScope();
- expect(scope.ctrl.getProp()).toBe('default');
- $rootScope.$digest();
- expect(scope.ctrl.getProp()).toBe('default');
- scope.prop = 'foop';
- $rootScope.$digest();
- expect(scope.ctrl.getProp()).toBe('foop');
- });
- });
- describe('bind-once', function() {
-
- function countWatches(scope) {
- var result = 0;
- while (scope !== null) {
- result += (scope.$$watchers && scope.$$watchers.length) || 0;
- result += countWatches(scope.$$childHead);
- scope = scope.$$nextSibling;
- }
- return result;
- }
+ it('should not overwrite @-bound property each digest when not present', function() {
+ module(function($compileProvider) {
+ $compileProvider.directive('testDir', valueFn({
+ scope: {prop: '@'},
+ controller: function($scope) {
+ $scope.prop = $scope.prop || 'default';
+ this.getProp = function() {
+ return $scope.prop;
+ };
+ },
+ controllerAs: 'ctrl',
+ template: '
'
+ }));
+ });
+ inject(function($compile, $rootScope) {
+ element = $compile('
')($rootScope);
+ var scope = element.isolateScope();
+ expect(scope.ctrl.getProp()).toBe('default');
- it('should be possible to one-time bind a parameter on a component with a template', function() {
- module(function() {
- directive('otherTplDir', function() {
- return {
- scope: {param1: '=', param2: '='},
- template: '1:{{param1}};2:{{param2}};3:{{::param1}};4:{{::param2}}'
- };
+ $rootScope.$digest();
+ expect(scope.ctrl.getProp()).toBe('default');
});
});
- inject(function($rootScope) {
- compile('
');
- expect(countWatches($rootScope)).toEqual(6); // 4 -> template watch group, 2 -> '='
- $rootScope.$digest();
- expect(element.html()).toBe('1:;2:;3:;4:');
- expect(countWatches($rootScope)).toEqual(6);
- $rootScope.foo = 'foo';
- $rootScope.$digest();
- expect(element.html()).toBe('1:foo;2:;3:foo;4:');
- expect(countWatches($rootScope)).toEqual(4);
+ it('should ignore optional "="-bound property if value is the emptry string', function() {
+ module(function($compileProvider) {
+ $compileProvider.directive('testDir', valueFn({
+ scope: {prop: '=?'},
+ controller: function($scope) {
+ $scope.prop = $scope.prop || 'default';
+ this.getProp = function() {
+ return $scope.prop;
+ };
+ },
+ controllerAs: 'ctrl',
+ template: '
'
+ }));
+ });
+ inject(function($compile, $rootScope) {
+ element = $compile('
')($rootScope);
+ var scope = element.isolateScope();
+ expect(scope.ctrl.getProp()).toBe('default');
+ $rootScope.$digest();
+ expect(scope.ctrl.getProp()).toBe('default');
+ scope.prop = 'foop';
+ $rootScope.$digest();
+ expect(scope.ctrl.getProp()).toBe('foop');
+ });
+ });
- $rootScope.foo = 'baz';
- $rootScope.bar = 'bar';
- $rootScope.$digest();
- expect(element.html()).toBe('1:foo;2:bar;3:foo;4:bar');
- expect(countWatches($rootScope)).toEqual(3);
- $rootScope.bar = 'baz';
- $rootScope.$digest();
- expect(element.html()).toBe('1:foo;2:baz;3:foo;4:bar');
- });
- });
+ describe('bind-once', function() {
- it('should be possible to one-time bind a parameter on a component with a template', function() {
- module(function() {
- directive('otherTplDir', function() {
- return {
- scope: {param1: '@', param2: '@'},
- template: '1:{{param1}};2:{{param2}};3:{{::param1}};4:{{::param2}}'
- };
- });
- });
+ function countWatches(scope) {
+ var result = 0;
+ while (scope !== null) {
+ result += (scope.$$watchers && scope.$$watchers.length) || 0;
+ result += countWatches(scope.$$childHead);
+ scope = scope.$$nextSibling;
+ }
+ return result;
+ }
- inject(function($rootScope) {
- compile('
');
- expect(countWatches($rootScope)).toEqual(6); // 4 -> template watch group, 2 -> {{ }}
- $rootScope.$digest();
- expect(element.html()).toBe('1:;2:;3:;4:');
- expect(countWatches($rootScope)).toEqual(4); // (- 2) -> bind-once in template
+ it('should be possible to one-time bind a parameter on a component with a template', function() {
+ module(function() {
+ directive('otherTplDir', function() {
+ return {
+ scope: {param1: '=', param2: '='},
+ template: '1:{{param1}};2:{{param2}};3:{{::param1}};4:{{::param2}}'
+ };
+ });
+ });
- $rootScope.foo = 'foo';
- $rootScope.$digest();
- expect(element.html()).toBe('1:foo;2:;3:;4:');
- expect(countWatches($rootScope)).toEqual(3);
+ inject(function($rootScope) {
+ compile('
');
+ expect(countWatches($rootScope)).toEqual(6); // 4 -> template watch group, 2 -> '='
+ $rootScope.$digest();
+ expect(element.html()).toBe('1:;2:;3:;4:');
+ expect(countWatches($rootScope)).toEqual(6);
- $rootScope.foo = 'baz';
- $rootScope.bar = 'bar';
- $rootScope.$digest();
- expect(element.html()).toBe('1:foo;2:bar;3:;4:');
- expect(countWatches($rootScope)).toEqual(3);
+ $rootScope.foo = 'foo';
+ $rootScope.$digest();
+ expect(element.html()).toBe('1:foo;2:;3:foo;4:');
+ expect(countWatches($rootScope)).toEqual(4);
- $rootScope.bar = 'baz';
- $rootScope.$digest();
- expect(element.html()).toBe('1:foo;2:baz;3:;4:');
- });
- });
+ $rootScope.foo = 'baz';
+ $rootScope.bar = 'bar';
+ $rootScope.$digest();
+ expect(element.html()).toBe('1:foo;2:bar;3:foo;4:bar');
+ expect(countWatches($rootScope)).toEqual(3);
- it('should be possible to one-time bind a parameter on a component with a template', function() {
- module(function() {
- directive('otherTplDir', function() {
- return {
- scope: {param1: '=', param2: '='},
- templateUrl: 'other.html'
- };
+ $rootScope.bar = 'baz';
+ $rootScope.$digest();
+ expect(element.html()).toBe('1:foo;2:baz;3:foo;4:bar');
+ });
});
- });
- inject(function($rootScope, $templateCache) {
- $templateCache.put('other.html', '1:{{param1}};2:{{param2}};3:{{::param1}};4:{{::param2}}');
- compile('
');
- $rootScope.$digest();
- expect(element.html()).toBe('1:;2:;3:;4:');
- expect(countWatches($rootScope)).toEqual(6); // 4 -> template watch group, 2 -> '='
+ it('should be possible to one-time bind a parameter on a component with a template', function() {
+ module(function() {
+ directive('otherTplDir', function() {
+ return {
+ scope: {param1: '@', param2: '@'},
+ template: '1:{{param1}};2:{{param2}};3:{{::param1}};4:{{::param2}}'
+ };
+ });
+ });
- $rootScope.foo = 'foo';
- $rootScope.$digest();
- expect(element.html()).toBe('1:foo;2:;3:foo;4:');
- expect(countWatches($rootScope)).toEqual(4);
+ inject(function($rootScope) {
+ compile('
');
+ expect(countWatches($rootScope)).toEqual(6); // 4 -> template watch group, 2 -> {{ }}
+ $rootScope.$digest();
+ expect(element.html()).toBe('1:;2:;3:;4:');
+ expect(countWatches($rootScope)).toEqual(4); // (- 2) -> bind-once in template
- $rootScope.foo = 'baz';
- $rootScope.bar = 'bar';
- $rootScope.$digest();
- expect(element.html()).toBe('1:foo;2:bar;3:foo;4:bar');
- expect(countWatches($rootScope)).toEqual(3);
+ $rootScope.foo = 'foo';
+ $rootScope.$digest();
+ expect(element.html()).toBe('1:foo;2:;3:;4:');
+ expect(countWatches($rootScope)).toEqual(3);
- $rootScope.bar = 'baz';
- $rootScope.$digest();
- expect(element.html()).toBe('1:foo;2:baz;3:foo;4:bar');
- });
- });
+ $rootScope.foo = 'baz';
+ $rootScope.bar = 'bar';
+ $rootScope.$digest();
+ expect(element.html()).toBe('1:foo;2:bar;3:;4:');
+ expect(countWatches($rootScope)).toEqual(3);
- it('should be possible to one-time bind a parameter on a component with a template', function() {
- module(function() {
- directive('otherTplDir', function() {
- return {
- scope: {param1: '@', param2: '@'},
- templateUrl: 'other.html'
- };
+ $rootScope.bar = 'baz';
+ $rootScope.$digest();
+ expect(element.html()).toBe('1:foo;2:baz;3:;4:');
+ });
});
- });
- inject(function($rootScope, $templateCache) {
- $templateCache.put('other.html', '1:{{param1}};2:{{param2}};3:{{::param1}};4:{{::param2}}');
- compile('
');
- $rootScope.$digest();
- expect(element.html()).toBe('1:;2:;3:;4:');
- expect(countWatches($rootScope)).toEqual(4); // (4 - 2) -> template watch group, 2 -> {{ }}
+ it('should be possible to one-time bind a parameter on a component with a template', function() {
+ module(function() {
+ directive('otherTplDir', function() {
+ return {
+ scope: {param1: '=', param2: '='},
+ templateUrl: 'other.html'
+ };
+ });
+ });
- $rootScope.foo = 'foo';
- $rootScope.$digest();
- expect(element.html()).toBe('1:foo;2:;3:;4:');
- expect(countWatches($rootScope)).toEqual(3);
+ inject(function($rootScope, $templateCache) {
+ $templateCache.put('other.html', '1:{{param1}};2:{{param2}};3:{{::param1}};4:{{::param2}}');
+ compile('
');
+ $rootScope.$digest();
+ expect(element.html()).toBe('1:;2:;3:;4:');
+ expect(countWatches($rootScope)).toEqual(6); // 4 -> template watch group, 2 -> '='
- $rootScope.foo = 'baz';
- $rootScope.bar = 'bar';
- $rootScope.$digest();
- expect(element.html()).toBe('1:foo;2:bar;3:;4:');
- expect(countWatches($rootScope)).toEqual(3);
+ $rootScope.foo = 'foo';
+ $rootScope.$digest();
+ expect(element.html()).toBe('1:foo;2:;3:foo;4:');
+ expect(countWatches($rootScope)).toEqual(4);
- $rootScope.bar = 'baz';
- $rootScope.$digest();
- expect(element.html()).toBe('1:foo;2:baz;3:;4:');
- });
- });
+ $rootScope.foo = 'baz';
+ $rootScope.bar = 'bar';
+ $rootScope.$digest();
+ expect(element.html()).toBe('1:foo;2:bar;3:foo;4:bar');
+ expect(countWatches($rootScope)).toEqual(3);
- it('should continue with a digets cycle when there is a two-way binding from the child to the parent', function() {
- module(function() {
- directive('hello', function() {
- return {
- restrict: 'E',
- scope: { greeting: '=' },
- template: '
Say hi! ',
- link: function(scope) {
- scope.setGreeting = function() { scope.greeting = 'Hello!'; };
- }
- };
+ $rootScope.bar = 'baz';
+ $rootScope.$digest();
+ expect(element.html()).toBe('1:foo;2:baz;3:foo;4:bar');
+ });
});
- });
- inject(function($rootScope) {
- compile('
' +
- '
{{greeting}}
' +
- '
' +
- '
');
- $rootScope.$digest();
- browserTrigger(element.find('button'), 'click');
- expect(element.find('p').text()).toBe('Hello!');
- });
- });
+ it('should be possible to one-time bind a parameter on a component with a template', function() {
+ module(function() {
+ directive('otherTplDir', function() {
+ return {
+ scope: {param1: '@', param2: '@'},
+ templateUrl: 'other.html'
+ };
+ });
+ });
- });
+ inject(function($rootScope, $templateCache) {
+ $templateCache.put('other.html', '1:{{param1}};2:{{param2}};3:{{::param1}};4:{{::param2}}');
+ compile('
');
+ $rootScope.$digest();
+ expect(element.html()).toBe('1:;2:;3:;4:');
+ expect(countWatches($rootScope)).toEqual(4); // (4 - 2) -> template watch group, 2 -> {{ }}
+ $rootScope.foo = 'foo';
+ $rootScope.$digest();
+ expect(element.html()).toBe('1:foo;2:;3:;4:');
+ expect(countWatches($rootScope)).toEqual(3);
- describe('attribute', function() {
- it('should copy simple attribute', inject(function() {
- compile('
');
+ $rootScope.foo = 'baz';
+ $rootScope.bar = 'bar';
+ $rootScope.$digest();
+ expect(element.html()).toBe('1:foo;2:bar;3:;4:');
+ expect(countWatches($rootScope)).toEqual(3);
- expect(componentScope.attr).toEqual('some text');
- expect(componentScope.attrAlias).toEqual('some text');
- expect(componentScope.attrAlias).toEqual(componentScope.attr);
- }));
+ $rootScope.bar = 'baz';
+ $rootScope.$digest();
+ expect(element.html()).toBe('1:foo;2:baz;3:;4:');
+ });
+ });
- it('should copy an attribute with spaces', inject(function() {
- compile('');
+ it('should continue with a digets cycle when there is a two-way binding from the child to the parent', function() {
+ module(function() {
+ directive('hello', function() {
+ return {
+ restrict: 'E',
+ scope: { greeting: '=' },
+ template: 'Say hi! ',
+ link: function(scope) {
+ scope.setGreeting = function() { scope.greeting = 'Hello!'; };
+ }
+ };
+ });
+ });
- expect(componentScope.attr).toEqual(' some text ');
- expect(componentScope.attrAlias).toEqual(' some text ');
- expect(componentScope.attrAlias).toEqual(componentScope.attr);
- }));
+ inject(function($rootScope) {
+ compile('' +
+ '
{{greeting}}
' +
+ '
' +
+ '
');
+ $rootScope.$digest();
+ browserTrigger(element.find('button'), 'click');
+ expect(element.find('p').text()).toBe('Hello!');
+ });
+ });
- it('should set up the interpolation before it reaches the link function', inject(function() {
- $rootScope.name = 'misko';
- compile('');
- expect(componentScope.attr).toEqual('hello misko');
- expect(componentScope.attrAlias).toEqual('hello misko');
- }));
+ });
- it('should update when interpolated attribute updates', inject(function() {
- compile('');
- $rootScope.name = 'igor';
- $rootScope.$apply();
+ describe('attribute', function() {
+ it('should copy simple attribute', inject(function() {
+ compile('');
- expect(componentScope.attr).toEqual('hello igor');
- expect(componentScope.attrAlias).toEqual('hello igor');
- }));
- });
+ expect(componentScope.attr).toEqual('some text');
+ expect(componentScope.attrAlias).toEqual('some text');
+ expect(componentScope.attrAlias).toEqual(componentScope.attr);
+ }));
+ it('should copy an attribute with spaces', inject(function() {
+ compile('');
- describe('object reference', function() {
- it('should update local when origin changes', inject(function() {
- compile('');
- expect(componentScope.ref).toBeUndefined();
- expect(componentScope.refAlias).toBe(componentScope.ref);
-
- $rootScope.name = 'misko';
- $rootScope.$apply();
-
- expect($rootScope.name).toBe('misko');
- expect(componentScope.ref).toBe('misko');
- expect(componentScope.refAlias).toBe('misko');
+ expect(componentScope.attr).toEqual(' some text ');
+ expect(componentScope.attrAlias).toEqual(' some text ');
+ expect(componentScope.attrAlias).toEqual(componentScope.attr);
+ }));
- $rootScope.name = {};
- $rootScope.$apply();
- expect(componentScope.ref).toBe($rootScope.name);
- expect(componentScope.refAlias).toBe($rootScope.name);
- }));
+ it('should set up the interpolation before it reaches the link function', inject(function() {
+ $rootScope.name = 'misko';
+ compile('');
+ expect(componentScope.attr).toEqual('hello misko');
+ expect(componentScope.attrAlias).toEqual('hello misko');
+ }));
+ it('should update when interpolated attribute updates', inject(function() {
+ compile('');
- it('should update local when both change', inject(function() {
- compile('');
- $rootScope.name = {mark:123};
- componentScope.ref = 'misko';
+ $rootScope.name = 'igor';
+ $rootScope.$apply();
- $rootScope.$apply();
- expect($rootScope.name).toEqual({mark:123});
- expect(componentScope.ref).toBe($rootScope.name);
- expect(componentScope.refAlias).toBe($rootScope.name);
+ expect(componentScope.attr).toEqual('hello igor');
+ expect(componentScope.attrAlias).toEqual('hello igor');
+ }));
+ });
- $rootScope.name = 'igor';
- componentScope.ref = {};
- $rootScope.$apply();
- expect($rootScope.name).toEqual('igor');
- expect(componentScope.ref).toBe($rootScope.name);
- expect(componentScope.refAlias).toBe($rootScope.name);
- }));
- it('should not break if local and origin both change to the same value', inject(function() {
- $rootScope.name = 'aaa';
+ describe('object reference', function() {
+ it('should update local when origin changes', inject(function() {
+ compile('');
+ expect(componentScope.ref).toBeUndefined();
+ expect(componentScope.refAlias).toBe(componentScope.ref);
- compile('');
+ $rootScope.name = 'misko';
+ $rootScope.$apply();
- //change both sides to the same item within the same digest cycle
- componentScope.ref = 'same';
- $rootScope.name = 'same';
- $rootScope.$apply();
+ expect($rootScope.name).toBe('misko');
+ expect(componentScope.ref).toBe('misko');
+ expect(componentScope.refAlias).toBe('misko');
- //change origin back to its previous value
- $rootScope.name = 'aaa';
- $rootScope.$apply();
+ $rootScope.name = {};
+ $rootScope.$apply();
+ expect(componentScope.ref).toBe($rootScope.name);
+ expect(componentScope.refAlias).toBe($rootScope.name);
+ }));
- expect($rootScope.name).toBe('aaa');
- expect(componentScope.ref).toBe('aaa');
- }));
- it('should complain on non assignable changes', inject(function() {
- compile('');
- $rootScope.name = 'world';
- $rootScope.$apply();
- expect(componentScope.ref).toBe('hello world');
+ it('should update local when both change', inject(function() {
+ compile('');
+ $rootScope.name = {mark:123};
+ componentScope.ref = 'misko';
- componentScope.ref = 'ignore me';
- expect(function() { $rootScope.$apply(); }).
- toThrowMinErr('$compile', 'nonassign', 'Expression \'\'hello \' + name\' in attribute \'ref\' used with directive \'myComponent\' is non-assignable!');
- expect(componentScope.ref).toBe('hello world');
- // reset since the exception was rethrown which prevented phase clearing
- $rootScope.$$phase = null;
+ $rootScope.$apply();
+ expect($rootScope.name).toEqual({mark:123});
+ expect(componentScope.ref).toBe($rootScope.name);
+ expect(componentScope.refAlias).toBe($rootScope.name);
- $rootScope.name = 'misko';
- $rootScope.$apply();
- expect(componentScope.ref).toBe('hello misko');
- }));
+ $rootScope.name = 'igor';
+ componentScope.ref = {};
+ $rootScope.$apply();
+ expect($rootScope.name).toEqual('igor');
+ expect(componentScope.ref).toBe($rootScope.name);
+ expect(componentScope.refAlias).toBe($rootScope.name);
+ }));
- it('should complain if assigning to undefined', inject(function() {
- compile('');
- $rootScope.$apply();
- expect(componentScope.ref).toBeUndefined();
+ it('should not break if local and origin both change to the same value', inject(function() {
+ $rootScope.name = 'aaa';
- componentScope.ref = 'ignore me';
- expect(function() { $rootScope.$apply(); }).
- toThrowMinErr('$compile', 'nonassign', 'Expression \'undefined\' in attribute \'ref\' used with directive \'myComponent\' is non-assignable!');
- expect(componentScope.ref).toBeUndefined();
+ compile('');
- $rootScope.$$phase = null; // reset since the exception was rethrown which prevented phase clearing
- $rootScope.$apply();
- expect(componentScope.ref).toBeUndefined();
- }));
+ //change both sides to the same item within the same digest cycle
+ componentScope.ref = 'same';
+ $rootScope.name = 'same';
+ $rootScope.$apply();
- // regression
- it('should stabilize model', inject(function() {
- compile('');
+ //change origin back to its previous value
+ $rootScope.name = 'aaa';
+ $rootScope.$apply();
- var lastRefValueInParent;
- $rootScope.$watch('name', function(ref) {
- lastRefValueInParent = ref;
- });
+ expect($rootScope.name).toBe('aaa');
+ expect(componentScope.ref).toBe('aaa');
+ }));
- $rootScope.name = 'aaa';
- $rootScope.$apply();
+ it('should complain on non assignable changes', inject(function() {
+ compile('');
+ $rootScope.name = 'world';
+ $rootScope.$apply();
+ expect(componentScope.ref).toBe('hello world');
- componentScope.reference = 'new';
- $rootScope.$apply();
+ componentScope.ref = 'ignore me';
+ expect(function() { $rootScope.$apply(); }).
+ toThrowMinErr('$compile', 'nonassign', 'Expression \'\'hello \' + name\' in attribute \'ref\' used with directive \'myComponent\' is non-assignable!');
+ expect(componentScope.ref).toBe('hello world');
+ // reset since the exception was rethrown which prevented phase clearing
+ $rootScope.$$phase = null;
- expect(lastRefValueInParent).toBe('new');
- }));
+ $rootScope.name = 'misko';
+ $rootScope.$apply();
+ expect(componentScope.ref).toBe('hello misko');
+ }));
- describe('literal objects', function() {
- it('should copy parent changes', inject(function() {
- compile('');
+ it('should complain if assigning to undefined', inject(function() {
+ compile('');
+ $rootScope.$apply();
+ expect(componentScope.ref).toBeUndefined();
- $rootScope.name = 'a';
- $rootScope.$apply();
- expect(componentScope.reference).toEqual({name: 'a'});
+ componentScope.ref = 'ignore me';
+ expect(function() { $rootScope.$apply(); }).
+ toThrowMinErr('$compile', 'nonassign', 'Expression \'undefined\' in attribute \'ref\' used with directive \'myComponent\' is non-assignable!');
+ expect(componentScope.ref).toBeUndefined();
- $rootScope.name = 'b';
- $rootScope.$apply();
- expect(componentScope.reference).toEqual({name: 'b'});
- }));
+ $rootScope.$$phase = null; // reset since the exception was rethrown which prevented phase clearing
+ $rootScope.$apply();
+ expect(componentScope.ref).toBeUndefined();
+ }));
- it('should not change the component when parent does not change', inject(function() {
- compile('');
+ // regression
+ it('should stabilize model', inject(function() {
+ compile('');
- $rootScope.name = 'a';
- $rootScope.$apply();
- var lastComponentValue = componentScope.reference;
- $rootScope.$apply();
- expect(componentScope.reference).toBe(lastComponentValue);
- }));
+ var lastRefValueInParent;
+ $rootScope.$watch('name', function(ref) {
+ lastRefValueInParent = ref;
+ });
- it('should complain when the component changes', inject(function() {
- compile('');
+ $rootScope.name = 'aaa';
+ $rootScope.$apply();
- $rootScope.name = 'a';
- $rootScope.$apply();
- componentScope.reference = {name: 'b'};
- expect(function() {
+ componentScope.reference = 'new';
$rootScope.$apply();
- }).toThrowMinErr('$compile', 'nonassign', 'Expression \'{name: name}\' in attribute \'reference\' used with directive \'myComponent\' is non-assignable!');
- }));
+ expect(lastRefValueInParent).toBe('new');
+ }));
- it('should work for primitive literals', inject(function() {
- test('1', 1);
- test('null', null);
- test('undefined', undefined);
- test('\'someString\'', 'someString');
- test('true', true);
+ describe('literal objects', function() {
+ it('should copy parent changes', inject(function() {
+ compile('');
- function test(literalString, literalValue) {
- compile('');
+ $rootScope.name = 'a';
+ $rootScope.$apply();
+ expect(componentScope.reference).toEqual({name: 'a'});
- $rootScope.$apply();
- expect(componentScope.reference).toBe(literalValue);
- dealoc(element);
- }
- }));
+ $rootScope.name = 'b';
+ $rootScope.$apply();
+ expect(componentScope.reference).toEqual({name: 'b'});
+ }));
- });
+ it('should not change the component when parent does not change', inject(function() {
+ compile('');
- });
+ $rootScope.name = 'a';
+ $rootScope.$apply();
+ var lastComponentValue = componentScope.reference;
+ $rootScope.$apply();
+ expect(componentScope.reference).toBe(lastComponentValue);
+ }));
+ it('should complain when the component changes', inject(function() {
+ compile('');
- describe('optional object reference', function() {
- it('should update local when origin changes', inject(function() {
- compile('');
- expect(componentScope.optRef).toBeUndefined();
- expect(componentScope.optRefAlias).toBe(componentScope.optRef);
+ $rootScope.name = 'a';
+ $rootScope.$apply();
+ componentScope.reference = {name: 'b'};
+ expect(function() {
+ $rootScope.$apply();
+ }).toThrowMinErr('$compile', 'nonassign', 'Expression \'{name: name}\' in attribute \'reference\' used with directive \'myComponent\' is non-assignable!');
- $rootScope.name = 'misko';
- $rootScope.$apply();
- expect(componentScope.optref).toBe($rootScope.name);
- expect(componentScope.optrefAlias).toBe($rootScope.name);
+ }));
- $rootScope.name = {};
- $rootScope.$apply();
- expect(componentScope.optref).toBe($rootScope.name);
- expect(componentScope.optrefAlias).toBe($rootScope.name);
- }));
+ it('should work for primitive literals', inject(function() {
+ test('1', 1);
+ test('null', null);
+ test('undefined', undefined);
+ test('\'someString\'', 'someString');
+ test('true', true);
- it('should not throw exception when reference does not exist', inject(function() {
- compile('');
+ function test(literalString, literalValue) {
+ compile('');
- expect(componentScope.optref).toBeUndefined();
- expect(componentScope.optrefAlias).toBeUndefined();
- expect(componentScope.optreference).toBeUndefined();
- }));
- });
+ $rootScope.$apply();
+ expect(componentScope.reference).toBe(literalValue);
+ dealoc(element);
+ }
+ }));
+ });
- describe('collection object reference', function() {
- it('should update isolate scope when origin scope changes', inject(function() {
- $rootScope.collection = [{
- name: 'Gabriel',
- value: 18
- }, {
- name: 'Tony',
- value: 91
- }];
- $rootScope.query = '';
- $rootScope.$apply();
+ });
- compile('');
- expect(componentScope.colref).toEqual($rootScope.collection);
- expect(componentScope.colrefAlias).toEqual(componentScope.colref);
+ describe('optional object reference', function() {
+ it('should update local when origin changes', inject(function() {
+ compile('');
+ expect(componentScope.optRef).toBeUndefined();
+ expect(componentScope.optRefAlias).toBe(componentScope.optRef);
- $rootScope.query = 'Gab';
- $rootScope.$apply();
+ $rootScope.name = 'misko';
+ $rootScope.$apply();
+ expect(componentScope.optref).toBe($rootScope.name);
+ expect(componentScope.optrefAlias).toBe($rootScope.name);
- expect(componentScope.colref).toEqual([$rootScope.collection[0]]);
- expect(componentScope.colrefAlias).toEqual([$rootScope.collection[0]]);
- }));
+ $rootScope.name = {};
+ $rootScope.$apply();
+ expect(componentScope.optref).toBe($rootScope.name);
+ expect(componentScope.optrefAlias).toBe($rootScope.name);
+ }));
- it('should update origin scope when isolate scope changes', inject(function() {
- $rootScope.collection = [{
- name: 'Gabriel',
- value: 18
- }, {
- name: 'Tony',
- value: 91
- }];
+ it('should not throw exception when reference does not exist', inject(function() {
+ compile('');
- compile('');
+ expect(componentScope.optref).toBeUndefined();
+ expect(componentScope.optrefAlias).toBeUndefined();
+ expect(componentScope.optreference).toBeUndefined();
+ }));
+ });
- var newItem = {
- name: 'Pablo',
- value: 10
- };
- componentScope.colref.push(newItem);
- componentScope.$apply();
- expect($rootScope.collection[2]).toEqual(newItem);
- }));
- });
+ describe('collection object reference', function() {
+ it('should update isolate scope when origin scope changes', inject(function() {
+ $rootScope.collection = [{
+ name: 'Gabriel',
+ value: 18
+ }, {
+ name: 'Tony',
+ value: 91
+ }];
+ $rootScope.query = '';
+ $rootScope.$apply();
+ compile('');
- describe('one-way binding', function() {
- it('should update isolate when the identity of origin changes', inject(function() {
- compile('');
+ expect(componentScope.colref).toEqual($rootScope.collection);
+ expect(componentScope.colrefAlias).toEqual(componentScope.colref);
- expect(componentScope.owRef).toBeUndefined();
- expect(componentScope.owRefAlias).toBe(componentScope.owRef);
+ $rootScope.query = 'Gab';
+ $rootScope.$apply();
- $rootScope.obj = {value: 'initial'};
- $rootScope.$apply();
+ expect(componentScope.colref).toEqual([$rootScope.collection[0]]);
+ expect(componentScope.colrefAlias).toEqual([$rootScope.collection[0]]);
+ }));
- expect($rootScope.obj).toEqual({value: 'initial'});
- expect(componentScope.owRef).toEqual({value: 'initial'});
- expect(componentScope.owRefAlias).toBe(componentScope.owRef);
+ it('should update origin scope when isolate scope changes', inject(function() {
+ $rootScope.collection = [{
+ name: 'Gabriel',
+ value: 18
+ }, {
+ name: 'Tony',
+ value: 91
+ }];
- // This changes in both scopes because of reference
- $rootScope.obj.value = 'origin1';
- $rootScope.$apply();
- expect(componentScope.owRef.value).toBe('origin1');
- expect(componentScope.owRefAlias.value).toBe('origin1');
+ compile('');
- componentScope.owRef = {value: 'isolate1'};
- componentScope.$apply();
- expect($rootScope.obj.value).toBe('origin1');
+ var newItem = {
+ name: 'Pablo',
+ value: 10
+ };
+ componentScope.colref.push(newItem);
+ componentScope.$apply();
- // Change does not propagate because object identity hasn't changed
- $rootScope.obj.value = 'origin2';
- $rootScope.$apply();
- expect(componentScope.owRef.value).toBe('isolate1');
- expect(componentScope.owRefAlias.value).toBe('origin2');
+ expect($rootScope.collection[2]).toEqual(newItem);
+ }));
+ });
- // Change does propagate because object identity changes
- $rootScope.obj = {value: 'origin3'};
- $rootScope.$apply();
- expect(componentScope.owRef.value).toBe('origin3');
- expect(componentScope.owRef).toBe($rootScope.obj);
- expect(componentScope.owRefAlias).toBe($rootScope.obj);
- }));
- it('should update isolate when both change', inject(function() {
- compile('');
+ describe('one-way binding', function() {
+ it('should update isolate when the identity of origin changes', inject(function() {
+ compile('');
- $rootScope.name = {mark:123};
- componentScope.owRef = 'misko';
+ expect(componentScope.owRef).toBeUndefined();
+ expect(componentScope.owRefAlias).toBe(componentScope.owRef);
- $rootScope.$apply();
- expect($rootScope.name).toEqual({mark:123});
- expect(componentScope.owRef).toBe($rootScope.name);
- expect(componentScope.owRefAlias).toBe($rootScope.name);
+ $rootScope.obj = {value: 'initial'};
+ $rootScope.$apply();
- $rootScope.name = 'igor';
- componentScope.owRef = {};
- $rootScope.$apply();
- expect($rootScope.name).toEqual('igor');
- expect(componentScope.owRef).toBe($rootScope.name);
- expect(componentScope.owRefAlias).toBe($rootScope.name);
- }));
+ expect($rootScope.obj).toEqual({value: 'initial'});
+ expect(componentScope.owRef).toEqual({value: 'initial'});
+ expect(componentScope.owRefAlias).toBe(componentScope.owRef);
- describe('initialization', function() {
- var component, log;
+ // This changes in both scopes because of reference
+ $rootScope.obj.value = 'origin1';
+ $rootScope.$apply();
+ expect(componentScope.owRef.value).toBe('origin1');
+ expect(componentScope.owRefAlias.value).toBe('origin1');
- beforeEach(function() {
- log = [];
- angular.module('owComponentTest', [])
- .component('owComponent', {
- bindings: { input: '<' },
- controller: function() {
- component = this;
- this.input = 'constructor';
- log.push('constructor');
+ componentScope.owRef = {value: 'isolate1'};
+ componentScope.$apply();
+ expect($rootScope.obj.value).toBe('origin1');
- this.$onInit = function() {
- this.input = '$onInit';
- log.push('$onInit');
- };
+ // Change does not propagate because object identity hasn't changed
+ $rootScope.obj.value = 'origin2';
+ $rootScope.$apply();
+ expect(componentScope.owRef.value).toBe('isolate1');
+ expect(componentScope.owRefAlias.value).toBe('origin2');
- this.$onChanges = function(changes) {
- if (changes.input) {
- log.push(['$onChanges', changes.input]);
- }
- };
- }
- });
- });
+ // Change does propagate because object identity changes
+ $rootScope.obj = {value: 'origin3'};
+ $rootScope.$apply();
+ expect(componentScope.owRef.value).toBe('origin3');
+ expect(componentScope.owRef).toBe($rootScope.obj);
+ expect(componentScope.owRefAlias).toBe($rootScope.obj);
+ }));
- it('should not update isolate again after $onInit if outer has not changed', function() {
- module('owComponentTest');
- inject(function() {
- $rootScope.name = 'outer';
- compile(' ');
+ it('should update isolate when both change', inject(function() {
+ compile('');
- expect($rootScope.name).toEqual('outer');
- expect(component.input).toEqual('$onInit');
+ $rootScope.name = {mark:123};
+ componentScope.owRef = 'misko';
+
+ $rootScope.$apply();
+ expect($rootScope.name).toEqual({mark:123});
+ expect(componentScope.owRef).toBe($rootScope.name);
+ expect(componentScope.owRefAlias).toBe($rootScope.name);
+ $rootScope.name = 'igor';
+ componentScope.owRef = {};
$rootScope.$apply();
+ expect($rootScope.name).toEqual('igor');
+ expect(componentScope.owRef).toBe($rootScope.name);
+ expect(componentScope.owRefAlias).toBe($rootScope.name);
+ }));
- expect($rootScope.name).toEqual('outer');
- expect(component.input).toEqual('$onInit');
+ describe('initialization', function() {
+ var component, log;
+
+ beforeEach(function() {
+ log = [];
+ angular.module('owComponentTest', [])
+ .component('owComponent', {
+ bindings: { input: '<' },
+ controller: function() {
+ component = this;
+ this.input = 'constructor';
+ log.push('constructor');
+
+ this.$onInit = function() {
+ this.input = '$onInit';
+ log.push('$onInit');
+ };
- expect(log).toEqual([
- 'constructor',
- ['$onChanges', jasmine.objectContaining({ currentValue: 'outer' })],
- '$onInit'
- ]);
- });
- });
+ this.$onChanges = function(changes) {
+ if (changes.input) {
+ log.push(['$onChanges', changes.input]);
+ }
+ };
+ }
+ });
+ });
- it('should update isolate again after $onInit if outer has changed (before initial watchAction call)', function() {
- module('owComponentTest');
- inject(function() {
- $rootScope.name = 'outer1';
- compile(' ');
+ it('should not update isolate again after $onInit if outer has not changed', function() {
+ module('owComponentTest');
+ inject(function() {
+ $rootScope.name = 'outer';
+ compile(' ');
- expect(component.input).toEqual('$onInit');
- $rootScope.$apply('name = "outer2"');
+ expect($rootScope.name).toEqual('outer');
+ expect(component.input).toEqual('$onInit');
- expect($rootScope.name).toEqual('outer2');
- expect(component.input).toEqual('outer2');
- expect(log).toEqual([
- 'constructor',
- ['$onChanges', jasmine.objectContaining({ currentValue: 'outer1' })],
- '$onInit',
- ['$onChanges', jasmine.objectContaining({ currentValue: 'outer2', previousValue: 'outer1' })]
- ]);
- });
- });
+ $rootScope.$apply();
- it('should update isolate again after $onInit if outer has changed (before initial watchAction call)', function() {
- angular.module('owComponentTest')
- .directive('changeInput', function() {
- return function(scope, elem, attrs) {
- scope.name = 'outer2';
- };
+ expect($rootScope.name).toEqual('outer');
+ expect(component.input).toEqual('$onInit');
+
+ expect(log).toEqual([
+ 'constructor',
+ ['$onChanges', jasmine.objectContaining({ currentValue: 'outer' })],
+ '$onInit'
+ ]);
+ });
});
- module('owComponentTest');
- inject(function() {
- $rootScope.name = 'outer1';
- compile(' ');
- expect(component.input).toEqual('$onInit');
- $rootScope.$digest();
+ it('should update isolate again after $onInit if outer has changed (before initial watchAction call)', function() {
+ module('owComponentTest');
+ inject(function() {
+ $rootScope.name = 'outer1';
+ compile(' ');
+
+ expect(component.input).toEqual('$onInit');
+ $rootScope.$apply('name = "outer2"');
+
+ expect($rootScope.name).toEqual('outer2');
+ expect(component.input).toEqual('outer2');
+ expect(log).toEqual([
+ 'constructor',
+ ['$onChanges', jasmine.objectContaining({ currentValue: 'outer1' })],
+ '$onInit',
+ ['$onChanges', jasmine.objectContaining({ currentValue: 'outer2', previousValue: 'outer1' })]
+ ]);
+ });
+ });
- expect($rootScope.name).toEqual('outer2');
- expect(component.input).toEqual('outer2');
- expect(log).toEqual([
- 'constructor',
- ['$onChanges', jasmine.objectContaining({ currentValue: 'outer1' })],
- '$onInit',
- ['$onChanges', jasmine.objectContaining({ currentValue: 'outer2', previousValue: 'outer1' })]
- ]);
+ it('should update isolate again after $onInit if outer has changed (before initial watchAction call)', function() {
+ angular.module('owComponentTest')
+ .directive('changeInput', function() {
+ return function(scope, elem, attrs) {
+ scope.name = 'outer2';
+ };
+ });
+ module('owComponentTest');
+ inject(function() {
+ $rootScope.name = 'outer1';
+ compile(' ');
+
+ expect(component.input).toEqual('$onInit');
+ $rootScope.$digest();
+
+ expect($rootScope.name).toEqual('outer2');
+ expect(component.input).toEqual('outer2');
+ expect(log).toEqual([
+ 'constructor',
+ ['$onChanges', jasmine.objectContaining({ currentValue: 'outer1' })],
+ '$onInit',
+ ['$onChanges', jasmine.objectContaining({ currentValue: 'outer2', previousValue: 'outer1' })]
+ ]);
+ });
+ });
});
- });
- });
- it('should not break when isolate and origin both change to the same value', inject(function() {
- $rootScope.name = 'aaa';
- compile('');
+ it('should not break when isolate and origin both change to the same value', inject(function() {
+ $rootScope.name = 'aaa';
+ compile('');
- //change both sides to the same item within the same digest cycle
- componentScope.owRef = 'same';
- $rootScope.name = 'same';
- $rootScope.$apply();
+ //change both sides to the same item within the same digest cycle
+ componentScope.owRef = 'same';
+ $rootScope.name = 'same';
+ $rootScope.$apply();
- //change origin back to its previous value
- $rootScope.name = 'aaa';
- $rootScope.$apply();
+ //change origin back to its previous value
+ $rootScope.name = 'aaa';
+ $rootScope.$apply();
- expect($rootScope.name).toBe('aaa');
- expect(componentScope.owRef).toBe('aaa');
- }));
+ expect($rootScope.name).toBe('aaa');
+ expect(componentScope.owRef).toBe('aaa');
+ }));
- it('should not update origin when identity of isolate changes', inject(function() {
- $rootScope.name = {mark:123};
- compile('');
+ it('should not update origin when identity of isolate changes', inject(function() {
+ $rootScope.name = {mark:123};
+ compile('');
- expect($rootScope.name).toEqual({mark:123});
- expect(componentScope.owRef).toBe($rootScope.name);
- expect(componentScope.owRefAlias).toBe($rootScope.name);
+ expect($rootScope.name).toEqual({mark:123});
+ expect(componentScope.owRef).toBe($rootScope.name);
+ expect(componentScope.owRefAlias).toBe($rootScope.name);
- componentScope.owRef = 'martin';
- $rootScope.$apply();
- expect($rootScope.name).toEqual({mark: 123});
- expect(componentScope.owRef).toBe('martin');
- expect(componentScope.owRefAlias).toEqual({mark: 123});
- }));
+ componentScope.owRef = 'martin';
+ $rootScope.$apply();
+ expect($rootScope.name).toEqual({mark: 123});
+ expect(componentScope.owRef).toBe('martin');
+ expect(componentScope.owRefAlias).toEqual({mark: 123});
+ }));
- it('should update origin when property of isolate object reference changes', inject(function() {
- $rootScope.obj = {mark:123};
- compile('');
+ it('should update origin when property of isolate object reference changes', inject(function() {
+ $rootScope.obj = {mark:123};
+ compile('');
- expect($rootScope.obj).toEqual({mark:123});
- expect(componentScope.owRef).toBe($rootScope.obj);
+ expect($rootScope.obj).toEqual({mark:123});
+ expect(componentScope.owRef).toBe($rootScope.obj);
- componentScope.owRef.mark = 789;
- $rootScope.$apply();
- expect($rootScope.obj).toEqual({mark: 789});
- expect(componentScope.owRef).toBe($rootScope.obj);
- }));
+ componentScope.owRef.mark = 789;
+ $rootScope.$apply();
+ expect($rootScope.obj).toEqual({mark: 789});
+ expect(componentScope.owRef).toBe($rootScope.obj);
+ }));
- it('should not throw on non assignable expressions in the parent', inject(function() {
- compile('');
+ it('should not throw on non assignable expressions in the parent', inject(function() {
+ compile('');
- $rootScope.name = 'world';
- $rootScope.$apply();
- expect(componentScope.owRef).toBe('hello world');
+ $rootScope.name = 'world';
+ $rootScope.$apply();
+ expect(componentScope.owRef).toBe('hello world');
- componentScope.owRef = 'ignore me';
- expect(componentScope.owRef).toBe('ignore me');
- expect($rootScope.name).toBe('world');
+ componentScope.owRef = 'ignore me';
+ expect(componentScope.owRef).toBe('ignore me');
+ expect($rootScope.name).toBe('world');
- $rootScope.name = 'misko';
- $rootScope.$apply();
- expect(componentScope.owRef).toBe('hello misko');
- }));
+ $rootScope.name = 'misko';
+ $rootScope.$apply();
+ expect(componentScope.owRef).toBe('hello misko');
+ }));
- it('should not throw when assigning to undefined', inject(function() {
- compile('');
+ it('should not throw when assigning to undefined', inject(function() {
+ compile('');
- expect(componentScope.owRef).toBeUndefined();
+ expect(componentScope.owRef).toBeUndefined();
- componentScope.owRef = 'ignore me';
- expect(componentScope.owRef).toBe('ignore me');
+ componentScope.owRef = 'ignore me';
+ expect(componentScope.owRef).toBe('ignore me');
- $rootScope.$apply();
- expect(componentScope.owRef).toBe('ignore me');
- }));
+ $rootScope.$apply();
+ expect(componentScope.owRef).toBe('ignore me');
+ }));
- it('should update isolate scope when "<"-bound NaN changes', inject(function() {
- $rootScope.num = NaN;
- compile('
');
+ it('should update isolate scope when "<"-bound NaN changes', inject(function() {
+ $rootScope.num = NaN;
+ compile('
');
- var isolateScope = element.isolateScope();
- expect(isolateScope.owRef).toBeNaN();
+ var isolateScope = element.isolateScope();
+ expect(isolateScope.owRef).toBeNaN();
- $rootScope.num = 64;
- $rootScope.$apply();
- expect(isolateScope.owRef).toBe(64);
- }));
+ $rootScope.num = 64;
+ $rootScope.$apply();
+ expect(isolateScope.owRef).toBe(64);
+ }));
- describe('literal objects', function() {
- it('should copy parent changes', inject(function() {
- compile('');
+ describe('literal objects', function() {
+ it('should copy parent changes', inject(function() {
+ compile('');
- $rootScope.name = 'a';
- $rootScope.$apply();
- expect(componentScope.owRef).toEqual({name: 'a'});
+ $rootScope.name = 'a';
+ $rootScope.$apply();
+ expect(componentScope.owRef).toEqual({name: 'a'});
- $rootScope.name = 'b';
- $rootScope.$apply();
- expect(componentScope.owRef).toEqual({name: 'b'});
- }));
+ $rootScope.name = 'b';
+ $rootScope.$apply();
+ expect(componentScope.owRef).toEqual({name: 'b'});
+ }));
- it('should not change the isolated scope when origin does not change', inject(function() {
- compile('');
+ it('should not change the isolated scope when origin does not change', inject(function() {
+ compile('');
- $rootScope.name = 'a';
- $rootScope.$apply();
- var lastComponentValue = componentScope.owRef;
- $rootScope.$apply();
- expect(componentScope.owRef).toBe(lastComponentValue);
- }));
+ $rootScope.name = 'a';
+ $rootScope.$apply();
+ var lastComponentValue = componentScope.owRef;
+ $rootScope.$apply();
+ expect(componentScope.owRef).toBe(lastComponentValue);
+ }));
- it('should deep-watch array literals', inject(function() {
- $rootScope.name = 'georgios';
- $rootScope.obj = {name: 'pete'};
- compile('');
+ it('should deep-watch array literals', inject(function() {
+ $rootScope.name = 'georgios';
+ $rootScope.obj = {name: 'pete'};
+ compile('');
- expect(componentScope.owRef).toEqual([{name: 'georgios'}, {name: 'pete'}]);
+ expect(componentScope.owRef).toEqual([{name: 'georgios'}, {name: 'pete'}]);
- $rootScope.name = 'lucas';
- $rootScope.obj = {name: 'martin'};
- $rootScope.$apply();
- expect(componentScope.owRef).toEqual([{name: 'lucas'}, {name: 'martin'}]);
- }));
+ $rootScope.name = 'lucas';
+ $rootScope.obj = {name: 'martin'};
+ $rootScope.$apply();
+ expect(componentScope.owRef).toEqual([{name: 'lucas'}, {name: 'martin'}]);
+ }));
- it('should deep-watch object literals', inject(function() {
- $rootScope.name = 'georgios';
- $rootScope.obj = {name: 'pete'};
- compile('');
+ it('should deep-watch object literals', inject(function() {
+ $rootScope.name = 'georgios';
+ $rootScope.obj = {name: 'pete'};
+ compile('');
- expect(componentScope.owRef).toEqual({name: 'georgios', item: {name: 'pete'}});
+ expect(componentScope.owRef).toEqual({name: 'georgios', item: {name: 'pete'}});
- $rootScope.name = 'lucas';
- $rootScope.obj = {name: 'martin'};
- $rootScope.$apply();
- expect(componentScope.owRef).toEqual({name: 'lucas', item: {name: 'martin'}});
- }));
+ $rootScope.name = 'lucas';
+ $rootScope.obj = {name: 'martin'};
+ $rootScope.$apply();
+ expect(componentScope.owRef).toEqual({name: 'lucas', item: {name: 'martin'}});
+ }));
- it('should not complain when the isolated scope changes', inject(function() {
- compile('');
+ it('should not complain when the isolated scope changes', inject(function() {
+ compile('');
- $rootScope.name = 'a';
- $rootScope.$apply();
- componentScope.owRef = {name: 'b'};
- componentScope.$apply();
+ $rootScope.name = 'a';
+ $rootScope.$apply();
+ componentScope.owRef = {name: 'b'};
+ componentScope.$apply();
- expect(componentScope.owRef).toEqual({name: 'b'});
- expect($rootScope.name).toBe('a');
+ expect(componentScope.owRef).toEqual({name: 'b'});
+ expect($rootScope.name).toBe('a');
- $rootScope.name = 'c';
- $rootScope.$apply();
- expect(componentScope.owRef).toEqual({name: 'c'});
- }));
+ $rootScope.name = 'c';
+ $rootScope.$apply();
+ expect(componentScope.owRef).toEqual({name: 'c'});
+ }));
- it('should work for primitive literals', inject(function() {
- test('1', 1);
- test('null', null);
- test('undefined', undefined);
- test('\'someString\'', 'someString');
- test('true', true);
+ it('should work for primitive literals', inject(function() {
+ test('1', 1);
+ test('null', null);
+ test('undefined', undefined);
+ test('\'someString\'', 'someString');
+ test('true', true);
- function test(literalString, literalValue) {
- compile('');
+ function test(literalString, literalValue) {
+ compile('');
- expect(componentScope.owRef).toBe(literalValue);
- dealoc(element);
- }
- }));
+ expect(componentScope.owRef).toBe(literalValue);
+ dealoc(element);
+ }
+ }));
- describe('optional one-way binding', function() {
- it('should update local when origin changes', inject(function() {
- compile('');
+ describe('optional one-way binding', function() {
+ it('should update local when origin changes', inject(function() {
+ compile('');
- expect(componentScope.owOptref).toBeUndefined();
- expect(componentScope.owOptrefAlias).toBe(componentScope.owOptref);
+ expect(componentScope.owOptref).toBeUndefined();
+ expect(componentScope.owOptrefAlias).toBe(componentScope.owOptref);
- $rootScope.name = 'misko';
- $rootScope.$apply();
- expect(componentScope.owOptref).toBe($rootScope.name);
- expect(componentScope.owOptrefAlias).toBe($rootScope.name);
+ $rootScope.name = 'misko';
+ $rootScope.$apply();
+ expect(componentScope.owOptref).toBe($rootScope.name);
+ expect(componentScope.owOptrefAlias).toBe($rootScope.name);
- $rootScope.name = {};
- $rootScope.$apply();
- expect(componentScope.owOptref).toBe($rootScope.name);
- expect(componentScope.owOptrefAlias).toBe($rootScope.name);
- }));
+ $rootScope.name = {};
+ $rootScope.$apply();
+ expect(componentScope.owOptref).toBe($rootScope.name);
+ expect(componentScope.owOptrefAlias).toBe($rootScope.name);
+ }));
- it('should not throw exception when reference does not exist', inject(function() {
- compile('');
+ it('should not throw exception when reference does not exist', inject(function() {
+ compile('');
- expect(componentScope.owOptref).toBeUndefined();
- expect(componentScope.owOptrefAlias).toBeUndefined();
- }));
+ expect(componentScope.owOptref).toBeUndefined();
+ expect(componentScope.owOptrefAlias).toBeUndefined();
+ }));
+ });
+ });
});
- });
- });
- describe('executable expression', function() {
- it('should allow expression execution with locals', inject(function() {
- compile('');
- $rootScope.count = 2;
+ describe('executable expression', function() {
+ it('should allow expression execution with locals', inject(function() {
+ compile('');
+ $rootScope.count = 2;
- expect(typeof componentScope.expr).toBe('function');
- expect(typeof componentScope.exprAlias).toBe('function');
+ expect(typeof componentScope.expr).toBe('function');
+ expect(typeof componentScope.exprAlias).toBe('function');
- expect(componentScope.expr({offset: 1})).toEqual(3);
- expect($rootScope.count).toEqual(3);
-
- expect(componentScope.exprAlias({offset: 10})).toEqual(13);
- expect($rootScope.count).toEqual(13);
- }));
- });
-
- it('should throw on unknown definition', inject(function() {
- expect(function() {
- compile('');
- }).toThrowMinErr('$compile', 'iscp', 'Invalid isolate scope definition for directive \'badDeclaration\'. Definition: {... attr: \'xxx\' ...}');
- }));
-
- it('should expose a $$isolateBindings property onto the scope', inject(function() {
- compile('');
-
- expect(typeof componentScope.$$isolateBindings).toBe('object');
-
- expect(componentScope.$$isolateBindings.attr.mode).toBe('@');
- expect(componentScope.$$isolateBindings.attr.attrName).toBe('attr');
- expect(componentScope.$$isolateBindings.attrAlias.attrName).toBe('attr');
- expect(componentScope.$$isolateBindings.ref.mode).toBe('=');
- expect(componentScope.$$isolateBindings.ref.attrName).toBe('ref');
- expect(componentScope.$$isolateBindings.refAlias.attrName).toBe('ref');
- expect(componentScope.$$isolateBindings.reference.mode).toBe('=');
- expect(componentScope.$$isolateBindings.reference.attrName).toBe('reference');
- expect(componentScope.$$isolateBindings.owRef.mode).toBe('<');
- expect(componentScope.$$isolateBindings.owRef.attrName).toBe('owRef');
- expect(componentScope.$$isolateBindings.owRefAlias.attrName).toBe('owRef');
- expect(componentScope.$$isolateBindings.expr.mode).toBe('&');
- expect(componentScope.$$isolateBindings.expr.attrName).toBe('expr');
- expect(componentScope.$$isolateBindings.exprAlias.attrName).toBe('expr');
-
- var firstComponentScope = componentScope,
- first$$isolateBindings = componentScope.$$isolateBindings;
-
- dealoc(element);
- compile('');
- expect(componentScope).not.toBe(firstComponentScope);
- expect(componentScope.$$isolateBindings).toBe(first$$isolateBindings);
- }));
+ expect(componentScope.expr({offset: 1})).toEqual(3);
+ expect($rootScope.count).toEqual(3);
+ expect(componentScope.exprAlias({offset: 10})).toEqual(13);
+ expect($rootScope.count).toEqual(13);
+ }));
+ });
- it('should expose isolate scope variables on controller with controllerAs when bindToController is true (template)', function() {
- var controllerCalled = false;
- module(function($compileProvider) {
- $compileProvider.directive('fooDir', valueFn({
- template: 'isolate
',
- scope: {
- 'data': '=dirData',
- 'oneway': '');
+ }).toThrowMinErr('$compile', 'iscp', 'Invalid isolate scope definition for directive \'badDeclaration\'. Definition: {... attr: \'xxx\' ...}');
}));
- });
- inject(function($compile, $rootScope) {
- $rootScope.fn = valueFn('called!');
- $rootScope.whom = 'world';
- $rootScope.remoteData = {
- 'foo': 'bar',
- 'baz': 'biz'
- };
- element = $compile('
')($rootScope);
- expect(controllerCalled).toBe(true);
- });
- });
-
- it('should eventually expose isolate scope variables on ES6 class controller with controllerAs when bindToController is true', function() {
- if (!/chrome/i.test(window.navigator.userAgent)) return;
- var controllerCalled = false;
- // eslint-disable-next-line no-eval
- var Controller = eval(
- 'class Foo {\n' +
- ' constructor($scope) {}\n' +
- ' $onInit() { this.check(); }\n' +
- ' check() {\n' +
- ' expect(this.data).toEqualData({\n' +
- ' \'foo\': \'bar\',\n' +
- ' \'baz\': \'biz\'\n' +
- ' });\n' +
- ' expect(this.oneway).toEqualData({\n' +
- ' \'foo\': \'bar\',\n' +
- ' \'baz\': \'biz\'\n' +
- ' });\n' +
- ' expect(this.str).toBe(\'Hello, world!\');\n' +
- ' expect(this.fn()).toBe(\'called!\');\n' +
- ' controllerCalled = true;\n' +
- ' }\n' +
- '}');
- spyOn(Controller.prototype, '$onInit').and.callThrough();
+ it('should expose a $$isolateBindings property onto the scope', inject(function() {
+ compile('');
+
+ expect(typeof componentScope.$$isolateBindings).toBe('object');
+
+ expect(componentScope.$$isolateBindings.attr.mode).toBe('@');
+ expect(componentScope.$$isolateBindings.attr.attrName).toBe('attr');
+ expect(componentScope.$$isolateBindings.attrAlias.attrName).toBe('attr');
+ expect(componentScope.$$isolateBindings.ref.mode).toBe('=');
+ expect(componentScope.$$isolateBindings.ref.attrName).toBe('ref');
+ expect(componentScope.$$isolateBindings.refAlias.attrName).toBe('ref');
+ expect(componentScope.$$isolateBindings.reference.mode).toBe('=');
+ expect(componentScope.$$isolateBindings.reference.attrName).toBe('reference');
+ expect(componentScope.$$isolateBindings.owRef.mode).toBe('<');
+ expect(componentScope.$$isolateBindings.owRef.attrName).toBe('owRef');
+ expect(componentScope.$$isolateBindings.owRefAlias.attrName).toBe('owRef');
+ expect(componentScope.$$isolateBindings.expr.mode).toBe('&');
+ expect(componentScope.$$isolateBindings.expr.attrName).toBe('expr');
+ expect(componentScope.$$isolateBindings.exprAlias.attrName).toBe('expr');
+
+ var firstComponentScope = componentScope,
+ first$$isolateBindings = componentScope.$$isolateBindings;
- module(function($compileProvider) {
- $compileProvider.directive('fooDir', valueFn({
- template: 'isolate
',
- scope: {
- 'data': '=dirData',
- 'oneway': '');
+ expect(componentScope).not.toBe(firstComponentScope);
+ expect(componentScope.$$isolateBindings).toBe(first$$isolateBindings);
}));
- });
- inject(function($compile, $rootScope) {
- $rootScope.fn = valueFn('called!');
- $rootScope.whom = 'world';
- $rootScope.remoteData = {
- 'foo': 'bar',
- 'baz': 'biz'
- };
- element = $compile('
')($rootScope);
- expect(Controller.prototype.$onInit).toHaveBeenCalled();
- expect(controllerCalled).toBe(true);
- });
- });
-
- it('should update @-bindings on controller when bindToController and attribute change observed', function() {
- module(function($compileProvider) {
- $compileProvider.directive('atBinding', valueFn({
- template: '{{At.text}}
',
- scope: {
- text: '@atBinding'
- },
- controller: function($scope) {},
- bindToController: true,
- controllerAs: 'At'
- }));
- });
- inject(function($compile, $rootScope) {
- element = $compile('
')($rootScope);
- var p = element.find('p');
- $rootScope.$digest();
- expect(p.text()).toBe('Test: ');
-
- $rootScope.text = 'Kittens';
- $rootScope.$digest();
- expect(p.text()).toBe('Test: Kittens');
- });
- });
-
-
- it('should expose isolate scope variables on controller with controllerAs when bindToController is true (templateUrl)', function() {
- var controllerCalled = false;
- module(function($compileProvider) {
- $compileProvider.directive('fooDir', valueFn({
- templateUrl: 'test.html',
- scope: {
- 'data': '=dirData',
- 'oneway': 'isolate',
+ scope: {
+ 'data': '=dirData',
+ 'oneway': 'isolate');
- $rootScope.fn = valueFn('called!');
- $rootScope.whom = 'world';
- $rootScope.remoteData = {
- 'foo': 'bar',
- 'baz': 'biz'
- };
- element = $compile('
')($rootScope);
- $rootScope.$digest();
- expect(controllerCalled).toBe(true);
- });
- });
-
-
- it('should throw noctrl when missing controller', function() {
- module(function($compileProvider) {
- $compileProvider.directive('noCtrl', valueFn({
- templateUrl: 'test.html',
- scope: {
- 'data': '=dirData',
- 'oneway': '')($rootScope);
- }).toThrowMinErr('$compile', 'noctrl',
- 'Cannot bind to controller without directive \'noCtrl\'s controller.');
- });
- });
-
-
- it('should throw noident when missing controllerAs directive property', function() {
- module(function($compileProvider) {
- $compileProvider.directive('noIdent', valueFn({
- templateUrl: 'test.html',
- scope: {
- 'data': '=dirData',
- 'oneway': '')($rootScope);
- }).toThrowMinErr('$compile', 'noident',
- 'Cannot bind to controller without identifier for directive \'noIdent\'.');
- });
- });
-
-
- it('should throw noident when missing controller identifier', function() {
- module(function($compileProvider, $controllerProvider) {
- $controllerProvider.register('myCtrl', function() {});
- $compileProvider.directive('noIdent', valueFn({
- templateUrl: 'test.html',
- scope: {
- 'data': '=dirData',
- 'oneway': '')($rootScope);
- }).toThrowMinErr('$compile', 'noident',
- 'Cannot bind to controller without identifier for directive \'noIdent\'.');
- });
- });
-
-
- it('should bind to controller via object notation (isolate scope)', function() {
- var controllerCalled = false;
- module(function($compileProvider, $controllerProvider) {
- $controllerProvider.register('myCtrl', function() {
- expect(this.data).toEqualData({
- 'foo': 'bar',
- 'baz': 'biz'
- });
- expect(this.oneway).toEqualData({
- 'foo': 'bar',
- 'baz': 'biz'
- });
- expect(this.str).toBe('Hello, world!');
- expect(this.fn()).toBe('called!');
- controllerCalled = true;
- });
- $compileProvider.directive('fooDir', valueFn({
- templateUrl: 'test.html',
- bindToController: {
- 'data': '=dirData',
- 'oneway': 'isolate');
- $rootScope.fn = valueFn('called!');
- $rootScope.whom = 'world';
- $rootScope.remoteData = {
- 'foo': 'bar',
- 'baz': 'biz'
- };
- element = $compile('
')($rootScope);
- $rootScope.$digest();
- expect(controllerCalled).toBe(true);
- });
- });
-
-
- it('should bind to controller via object notation (new scope)', function() {
- var controllerCalled = false;
- module(function($compileProvider, $controllerProvider) {
- $controllerProvider.register('myCtrl', function() {
- expect(this.data).toEqualData({
- 'foo': 'bar',
- 'baz': 'biz'
- });
- expect(this.data).toEqualData({
- 'foo': 'bar',
- 'baz': 'biz'
- });
- expect(this.str).toBe('Hello, world!');
- expect(this.fn()).toBe('called!');
- controllerCalled = true;
- });
- $compileProvider.directive('fooDir', valueFn({
- templateUrl: 'test.html',
- bindToController: {
- 'data': '=dirData',
- 'oneway': 'isolate');
- $rootScope.fn = valueFn('called!');
- $rootScope.whom = 'world';
- $rootScope.remoteData = {
- 'foo': 'bar',
- 'baz': 'biz'
- };
- element = $compile('
')($rootScope);
- $rootScope.$digest();
- expect(controllerCalled).toBe(true);
- });
- });
-
-
- it('should bind to multiple directives controllers via object notation (no scope)', function() {
- var controller1Called = false;
- var controller2Called = false;
- module(function($compileProvider, $controllerProvider) {
- $compileProvider.directive('foo', valueFn({
- bindToController: {
- 'data': '=fooData',
- 'oneway': ' ' +
- ' ')($rootScope);
- $rootScope.$digest();
- expect(controller1Called).toBe(true);
- expect(controller2Called).toBe(true);
- });
- });
-
-
- it('should bind to multiple directives controllers via object notation (new iso scope)', function() {
- var controller1Called = false;
- var controller2Called = false;
- module(function($compileProvider, $controllerProvider) {
- $compileProvider.directive('foo', valueFn({
- bindToController: {
- 'data': '=fooData',
- 'oneway': ' ' +
- ' ')($rootScope);
- $rootScope.$digest();
- expect(controller1Called).toBe(true);
- expect(controller2Called).toBe(true);
- });
- });
-
-
- it('should bind to multiple directives controllers via object notation (new scope)', function() {
- var controller1Called = false;
- var controller2Called = false;
- module(function($compileProvider, $controllerProvider) {
- $compileProvider.directive('foo', valueFn({
- bindToController: {
- 'data': '=fooData',
- 'oneway': ' ' +
- ' ')($rootScope);
- $rootScope.$digest();
- expect(controller1Called).toBe(true);
- expect(controller2Called).toBe(true);
- });
- });
-
-
- it('should evaluate against the correct scope, when using `bindToController` (new scope)',
- function() {
- module(function($compileProvider, $controllerProvider) {
- $controllerProvider.register({
- 'ParentCtrl': function() {
- this.value1 = 'parent1';
- this.value2 = 'parent2';
- this.value3 = function() { return 'parent3'; };
- this.value4 = 'parent4';
- },
- 'ChildCtrl': function() {
- this.value1 = 'child1';
- this.value2 = 'child2';
- this.value3 = function() { return 'child3'; };
- this.value4 = 'child4';
- }
+ };
+ element = $compile('
')($rootScope);
+ expect(controllerCalled).toBe(true);
});
-
- $compileProvider.directive('child', valueFn({
- scope: true,
- controller: 'ChildCtrl as ctrl',
- bindToController: {
- fromParent1: '@',
- fromParent2: '=',
- fromParent3: '&',
- fromParent4: '<'
- },
- template: ''
- }));
});
- inject(function($compile, $rootScope) {
- element = $compile(
- '' +
- '' +
- ' ' +
- '
')($rootScope);
- $rootScope.$digest();
- var parentCtrl = element.controller('ngController');
- var childCtrl = element.find('child').controller('child');
-
- expect(childCtrl.fromParent1).toBe(parentCtrl.value1);
- expect(childCtrl.fromParent1).not.toBe(childCtrl.value1);
- expect(childCtrl.fromParent2).toBe(parentCtrl.value2);
- expect(childCtrl.fromParent2).not.toBe(childCtrl.value2);
- expect(childCtrl.fromParent3()()).toBe(parentCtrl.value3());
- expect(childCtrl.fromParent3()()).not.toBe(childCtrl.value3());
- expect(childCtrl.fromParent4).toBe(parentCtrl.value4);
- expect(childCtrl.fromParent4).not.toBe(childCtrl.value4);
-
- childCtrl.fromParent2 = 'modified';
- $rootScope.$digest();
-
- expect(parentCtrl.value2).toBe('modified');
- expect(childCtrl.value2).toBe('child2');
- });
- }
- );
-
-
- it('should evaluate against the correct scope, when using `bindToController` (new iso scope)',
- function() {
- module(function($compileProvider, $controllerProvider) {
- $controllerProvider.register({
- 'ParentCtrl': function() {
- this.value1 = 'parent1';
- this.value2 = 'parent2';
- this.value3 = function() { return 'parent3'; };
- this.value4 = 'parent4';
- },
- 'ChildCtrl': function() {
- this.value1 = 'child1';
- this.value2 = 'child2';
- this.value3 = function() { return 'child3'; };
- this.value4 = 'child4';
- }
+ it('should not pre-assign bound properties to the controller if `preAssignBindingsEnabled` is disabled', function() {
+ var controllerCalled = false, onInitCalled = false;
+ module(function($compileProvider) {
+ $compileProvider.preAssignBindingsEnabled(false);
+ $compileProvider.directive('fooDir', valueFn({
+ template: 'isolate
',
+ scope: {
+ 'data': '=dirData',
+ 'oneway': ' ')($rootScope);
+ expect(controllerCalled).toBe(true);
+ expect(onInitCalled).toBe(true);
});
-
- $compileProvider.directive('child', valueFn({
- scope: {},
- controller: 'ChildCtrl as ctrl',
- bindToController: {
- fromParent1: '@',
- fromParent2: '=',
- fromParent3: '&',
- fromParent4: '<'
- },
- template: ''
- }));
- });
-
- inject(function($compile, $rootScope) {
- element = $compile(
- '' +
- '' +
- ' ' +
- '
')($rootScope);
- $rootScope.$digest();
-
- var parentCtrl = element.controller('ngController');
- var childCtrl = element.find('child').controller('child');
-
- expect(childCtrl.fromParent1).toBe(parentCtrl.value1);
- expect(childCtrl.fromParent1).not.toBe(childCtrl.value1);
- expect(childCtrl.fromParent2).toBe(parentCtrl.value2);
- expect(childCtrl.fromParent2).not.toBe(childCtrl.value2);
- expect(childCtrl.fromParent3()()).toBe(parentCtrl.value3());
- expect(childCtrl.fromParent3()()).not.toBe(childCtrl.value3());
- expect(childCtrl.fromParent4).toBe(parentCtrl.value4);
- expect(childCtrl.fromParent4).not.toBe(childCtrl.value4);
-
- childCtrl.fromParent2 = 'modified';
- $rootScope.$digest();
-
- expect(parentCtrl.value2).toBe('modified');
- expect(childCtrl.value2).toBe('child2');
- });
- }
- );
-
-
- it('should put controller in scope when controller identifier present but not using controllerAs', function() {
- var controllerCalled = false;
- var myCtrl;
- module(function($compileProvider, $controllerProvider) {
- $controllerProvider.register('myCtrl', function() {
- controllerCalled = true;
- myCtrl = this;
});
- $compileProvider.directive('fooDir', valueFn({
- templateUrl: 'test.html',
- bindToController: {},
- scope: true,
- controller: 'myCtrl as theCtrl'
- }));
- });
- inject(function($compile, $rootScope, $templateCache) {
- $templateCache.put('test.html', 'isolate
');
- element = $compile('')($rootScope);
- $rootScope.$digest();
- expect(controllerCalled).toBe(true);
- var childScope = element.children().scope();
- expect(childScope).not.toBe($rootScope);
- expect(childScope.theCtrl).toBe(myCtrl);
- });
- });
+ it('should pre-assign bound properties to the controller if `preAssignBindingsEnabled` is enabled', function() {
+ var controllerCalled = false, onInitCalled = false;
+ module(function($compileProvider) {
+ $compileProvider.preAssignBindingsEnabled(true);
+ $compileProvider.directive('fooDir', valueFn({
+ template: '
isolate
',
+ scope: {
+ 'data': '=dirData',
+ 'oneway': '
')($rootScope);
+ expect(controllerCalled).toBe(true);
+ expect(onInitCalled).toBe(true);
+ });
+ });
+
+ it('should eventually expose isolate scope variables on ES6 class controller with controllerAs when bindToController is true', function() {
+ if (!/chrome/i.test(window.navigator.userAgent)) return;
+ var controllerCalled = false;
+ // eslint-disable-next-line no-eval
+ var Controller = eval(
+ 'class Foo {\n' +
+ ' constructor($scope) {}\n' +
+ ' $onInit() { this.check(); }\n' +
+ ' check() {\n' +
+ ' expect(this.data).toEqualData({\n' +
+ ' \'foo\': \'bar\',\n' +
+ ' \'baz\': \'biz\'\n' +
+ ' });\n' +
+ ' expect(this.oneway).toEqualData({\n' +
+ ' \'foo\': \'bar\',\n' +
+ ' \'baz\': \'biz\'\n' +
+ ' });\n' +
+ ' expect(this.str).toBe(\'Hello, world!\');\n' +
+ ' expect(this.fn()).toBe(\'called!\');\n' +
+ ' controllerCalled = true;\n' +
+ ' }\n' +
+ '}');
+ spyOn(Controller.prototype, '$onInit').and.callThrough();
- it('should re-install controllerAs and bindings for returned value from controller (new scope)', function() {
- var controllerCalled = false;
- var myCtrl;
-
- function MyCtrl() {
- }
- MyCtrl.prototype.test = function() {
- expect(this.data).toEqualData({
- 'foo': 'bar',
- 'baz': 'biz'
- });
- expect(this.oneway).toEqualData({
- 'foo': 'bar',
- 'baz': 'biz'
+ module(function($compileProvider) {
+ $compileProvider.directive('fooDir', valueFn({
+ template: 'isolate
',
+ scope: {
+ 'data': '=dirData',
+ 'oneway': ' ')($rootScope);
+ expect(Controller.prototype.$onInit).toHaveBeenCalled();
+ expect(controllerCalled).toBe(true);
+ });
});
- expect(this.str).toBe('Hello, world!');
- expect(this.fn()).toBe('called!');
- };
- module(function($compileProvider, $controllerProvider) {
- $controllerProvider.register('myCtrl', function() {
- controllerCalled = true;
- myCtrl = this;
- return new MyCtrl();
- });
- $compileProvider.directive('fooDir', valueFn({
- templateUrl: 'test.html',
- bindToController: {
- 'data': '=dirData',
- 'oneway': 'isolate');
- $rootScope.fn = valueFn('called!');
- $rootScope.whom = 'world';
- $rootScope.remoteData = {
- 'foo': 'bar',
- 'baz': 'biz'
- };
- element = $compile('
')($rootScope);
- $rootScope.$digest();
- expect(controllerCalled).toBe(true);
- var childScope = element.children().scope();
- expect(childScope).not.toBe($rootScope);
- expect(childScope.theCtrl).not.toBe(myCtrl);
- expect(childScope.theCtrl.constructor).toBe(MyCtrl);
- childScope.theCtrl.test();
- });
- });
+ it('should update @-bindings on controller when bindToController and attribute change observed', function() {
+ module(function($compileProvider) {
+ $compileProvider.directive('atBinding', valueFn({
+ template: '{{At.text}}
',
+ scope: {
+ text: '@atBinding'
+ },
+ controller: function($scope) {},
+ bindToController: true,
+ controllerAs: 'At'
+ }));
+ });
- it('should re-install controllerAs and bindings for returned value from controller (isolate scope)', function() {
- var controllerCalled = false;
- var myCtrl;
+ inject(function($compile, $rootScope) {
+ element = $compile('
')($rootScope);
+ var p = element.find('p');
+ $rootScope.$digest();
+ expect(p.text()).toBe('Test: ');
- function MyCtrl() {
- }
- MyCtrl.prototype.test = function() {
- expect(this.data).toEqualData({
- 'foo': 'bar',
- 'baz': 'biz'
- });
- expect(this.oneway).toEqualData({
- 'foo': 'bar',
- 'baz': 'biz'
+ $rootScope.text = 'Kittens';
+ $rootScope.$digest();
+ expect(p.text()).toBe('Test: Kittens');
+ });
});
- expect(this.str).toBe('Hello, world!');
- expect(this.fn()).toBe('called!');
- };
- module(function($compileProvider, $controllerProvider) {
- $controllerProvider.register('myCtrl', function() {
- controllerCalled = true;
- myCtrl = this;
- return new MyCtrl();
- });
- $compileProvider.directive('fooDir', valueFn({
- templateUrl: 'test.html',
- bindToController: true,
- scope: {
- 'data': '=dirData',
- 'oneway': 'isolate');
- $rootScope.fn = valueFn('called!');
- $rootScope.whom = 'world';
- $rootScope.remoteData = {
- 'foo': 'bar',
- 'baz': 'biz'
- };
- element = $compile('
')($rootScope);
- $rootScope.$digest();
- expect(controllerCalled).toBe(true);
- var childScope = element.children().scope();
- expect(childScope).not.toBe($rootScope);
- expect(childScope.theCtrl).not.toBe(myCtrl);
- expect(childScope.theCtrl.constructor).toBe(MyCtrl);
- childScope.theCtrl.test();
- });
- });
-
- describe('should not overwrite @-bound property each digest when not present', function() {
- it('when creating new scope', function() {
- module(function($compileProvider) {
- $compileProvider.directive('testDir', valueFn({
- scope: true,
- bindToController: {
- prop: '@'
- },
- controller: function() {
- var self = this;
- this.prop = this.prop || 'default';
- this.getProp = function() {
- return self.prop;
- };
- },
- controllerAs: 'ctrl',
- template: '
'
- }));
- });
- inject(function($compile, $rootScope) {
- element = $compile('
')($rootScope);
- var scope = element.scope();
- expect(scope.ctrl.getProp()).toBe('default');
- $rootScope.$digest();
- expect(scope.ctrl.getProp()).toBe('default');
+ it('should expose isolate scope variables on controller with controllerAs when bindToController is true (templateUrl)', function() {
+ var controllerCalled = false;
+ module(function($compileProvider) {
+ $compileProvider.directive('fooDir', valueFn({
+ templateUrl: 'test.html',
+ scope: {
+ 'data': '=dirData',
+ 'oneway': 'isolate');
+ $rootScope.fn = valueFn('called!');
+ $rootScope.whom = 'world';
+ $rootScope.remoteData = {
+ 'foo': 'bar',
+ 'baz': 'biz'
+ };
+ element = $compile('
')($rootScope);
+ $rootScope.$digest();
+ expect(controllerCalled).toBe(true);
+ });
});
- });
- it('when creating isolate scope', function() {
- module(function($compileProvider) {
- $compileProvider.directive('testDir', valueFn({
- scope: {},
- bindToController: {
- prop: '@'
- },
- controller: function() {
- var self = this;
- this.prop = this.prop || 'default';
- this.getProp = function() {
- return self.prop;
- };
- },
- controllerAs: 'ctrl',
- template: '
'
- }));
- });
- inject(function($compile, $rootScope) {
- element = $compile('
')($rootScope);
- var scope = element.isolateScope();
- expect(scope.ctrl.getProp()).toBe('default');
- $rootScope.$digest();
- expect(scope.ctrl.getProp()).toBe('default');
+ it('should throw noctrl when missing controller', function() {
+ module(function($compileProvider) {
+ $compileProvider.directive('noCtrl', valueFn({
+ templateUrl: 'test.html',
+ scope: {
+ 'data': '=dirData',
+ 'oneway': '')($rootScope);
+ }).toThrowMinErr('$compile', 'noctrl',
+ 'Cannot bind to controller without directive \'noCtrl\'s controller.');
+ });
});
- });
- });
- });
-
-
- describe('controller', function() {
- it('should get required controller', function() {
- module(function() {
- directive('main', function(log) {
- return {
- priority: 2,
- controller: function() {
- this.name = 'main';
- },
- link: function(scope, element, attrs, controller) {
- log(controller.name);
- }
- };
- });
- directive('dep', function(log) {
- return {
- priority: 1,
- require: 'main',
- link: function(scope, element, attrs, controller) {
- log('dep:' + controller.name);
- }
- };
- });
- directive('other', function(log) {
- return {
- link: function(scope, element, attrs, controller) {
- log(!!controller); // should be false
- }
- };
- });
- });
- inject(function(log, $compile, $rootScope) {
- element = $compile('
')($rootScope);
- expect(log).toEqual('false; dep:main; main');
- });
- });
+ it('should throw badrestrict on first compilation when restrict is invalid', function() {
+ module(function($compileProvider, $exceptionHandlerProvider) {
+ $compileProvider.directive('invalidRestrictBadString', valueFn({restrict: '"'}));
+ $compileProvider.directive('invalidRestrictTrue', valueFn({restrict: true}));
+ $compileProvider.directive('invalidRestrictObject', valueFn({restrict: {}}));
+ $compileProvider.directive('invalidRestrictNumber', valueFn({restrict: 42}));
- it('should respect explicit return value from controller', function() {
- var expectedController;
- module(function() {
- directive('logControllerProp', function(log) {
- return {
- controller: function($scope) {
- this.foo = 'baz'; // value should not be used.
- expectedController = {foo: 'bar'};
- return expectedController;
- },
- link: function(scope, element, attrs, controller) {
- expect(expectedController).toBeDefined();
- expect(controller).toBe(expectedController);
- expect(controller.foo).toBe('bar');
- log('done');
- }
- };
- });
- });
- inject(function(log, $compile, $rootScope) {
- element = $compile(' ')($rootScope);
- expect(log).toEqual('done');
- expect(element.data('$logControllerPropController')).toBe(expectedController);
- });
- });
+ // We need to test with the exceptionHandler not rethrowing...
+ $exceptionHandlerProvider.mode('log');
+ });
+ inject(function($exceptionHandler, $compile, $rootScope) {
+ $compile('')($rootScope);
+ expect($exceptionHandler.errors.length).toBe(1);
+ expect($exceptionHandler.errors[0]).toMatch(/\$compile.*badrestrict.*'true'/);
- it('should get explicit return value of required parent controller', function() {
- var expectedController;
- module(function() {
- directive('nested', function(log) {
- return {
- require: '^^?nested',
- controller: function() {
- if (!expectedController) expectedController = {foo: 'bar'};
- return expectedController;
- },
- link: function(scope, element, attrs, controller) {
- if (element.parent().length) {
- expect(expectedController).toBeDefined();
- expect(controller).toBe(expectedController);
- expect(controller.foo).toBe('bar');
- log('done');
- }
- }
- };
- });
- });
- inject(function(log, $compile, $rootScope) {
- element = $compile('
')($rootScope);
- expect(log).toEqual('done');
- expect(element.data('$nestedController')).toBe(expectedController);
- });
- });
+ $compile('
')($rootScope);
+ $compile('
')($rootScope);
+ expect($exceptionHandler.errors.length).toBe(2);
+ expect($exceptionHandler.errors[1]).toMatch(/\$compile.*badrestrict.*'"'/);
+ $compile('
')($rootScope);
+ expect($exceptionHandler.errors.length).toBe(3);
+ expect($exceptionHandler.errors[2]).toMatch(/\$compile.*badrestrict.*'{}'/);
- it('should respect explicit controller return value when using controllerAs', function() {
- module(function() {
- directive('main', function() {
- return {
- templateUrl: 'main.html',
- scope: {},
- controller: function() {
- this.name = 'lucas';
- return {name: 'george'};
- },
- controllerAs: 'mainCtrl'
- };
+ $compile('
')($rootScope);
+ expect($exceptionHandler.errors.length).toBe(4);
+ expect($exceptionHandler.errors[3]).toMatch(/\$compile.*badrestrict.*'42'/);
+ });
});
- });
- inject(function($templateCache, $compile, $rootScope) {
- $templateCache.put('main.html', '
template:{{mainCtrl.name}} ');
- element = $compile('
')($rootScope);
- $rootScope.$apply();
- expect(element.text()).toBe('template:george');
- });
- });
- it('transcluded children should receive explicit return value of parent controller', function() {
- var expectedController;
- module(function() {
- directive('nester', valueFn({
- transclude: true,
- controller: function($transclude) {
- this.foo = 'baz';
- expectedController = {transclude:$transclude, foo: 'bar'};
- return expectedController;
- },
- link: function(scope, el, attr, ctrl) {
- ctrl.transclude(cloneAttach);
- function cloneAttach(clone) {
- el.append(clone);
- }
- }
- }));
- directive('nested', function(log) {
- return {
- require: '^^nester',
- link: function(scope, element, attrs, controller) {
- expect(controller).toBeDefined();
- expect(controller).toBe(expectedController);
- log('done');
- }
- };
+ it('should throw noident when missing controllerAs directive property', function() {
+ module(function($compileProvider) {
+ $compileProvider.directive('noIdent', valueFn({
+ templateUrl: 'test.html',
+ scope: {
+ 'data': '=dirData',
+ 'oneway': '
')($rootScope);
+ }).toThrowMinErr('$compile', 'noident',
+ 'Cannot bind to controller without identifier for directive \'noIdent\'.');
+ });
});
- });
- inject(function(log, $compile) {
- element = $compile('')($rootScope);
- $rootScope.$apply();
- expect(log.toString()).toBe('done');
- expect(element.data('$nesterController')).toBe(expectedController);
- });
- });
- it('explicit controller return values are ignored if they are primitives', function() {
- module(function() {
- directive('logControllerProp', function(log) {
- return {
- controller: function($scope) {
- this.foo = 'baz'; // value *will* be used.
- return 'bar';
- },
- link: function(scope, element, attrs, controller) {
- log(controller.foo);
- }
- };
+ it('should throw noident when missing controller identifier', function() {
+ module(function($compileProvider, $controllerProvider) {
+ $controllerProvider.register('myCtrl', function() {});
+ $compileProvider.directive('noIdent', valueFn({
+ templateUrl: 'test.html',
+ scope: {
+ 'data': '=dirData',
+ 'oneway': '')($rootScope);
+ }).toThrowMinErr('$compile', 'noident',
+ 'Cannot bind to controller without identifier for directive \'noIdent\'.');
+ });
});
- });
- inject(function(log, $compile, $rootScope) {
- element = $compile(' ')($rootScope);
- expect(log).toEqual('baz');
- expect(element.data('$logControllerPropController').foo).toEqual('baz');
- });
- });
-
- it('should correctly assign controller return values for multiple directives', function() {
- var directiveController, otherDirectiveController;
- module(function() {
- directive('myDirective', function(log) {
- return {
- scope: true,
- controller: function($scope) {
- directiveController = {
- foo: 'bar'
+ it('should bind to controller via object notation (isolate scope)', function() {
+ var controllerCalled = false;
+ module(function($compileProvider, $controllerProvider) {
+ $controllerProvider.register('myCtrl', function() {
+ this.check = function() {
+ expect(this.data).toEqualData({
+ 'foo': 'bar',
+ 'baz': 'biz'
+ });
+ expect(this.oneway).toEqualData({
+ 'foo': 'bar',
+ 'baz': 'biz'
+ });
+ expect(this.str).toBe('Hello, world!');
+ expect(this.fn()).toBe('called!');
};
- return directiveController;
- }
- };
+ controllerCalled = true;
+ if (preAssignBindingsEnabled) {
+ this.check();
+ } else {
+ this.$onInit = this.check;
+ }
+ });
+ $compileProvider.directive('fooDir', valueFn({
+ templateUrl: 'test.html',
+ bindToController: {
+ 'data': '=dirData',
+ 'oneway': 'isolate');
+ $rootScope.fn = valueFn('called!');
+ $rootScope.whom = 'world';
+ $rootScope.remoteData = {
+ 'foo': 'bar',
+ 'baz': 'biz'
+ };
+ element = $compile('
')($rootScope);
+ $rootScope.$digest();
+ expect(controllerCalled).toBe(true);
+ });
});
- directive('myOtherDirective', function(log) {
- return {
- controller: function($scope) {
- otherDirectiveController = {
- baz: 'luh'
+
+ it('should bind to controller via object notation (new scope)', function() {
+ var controllerCalled = false;
+ module(function($compileProvider, $controllerProvider) {
+ $controllerProvider.register('myCtrl', function() {
+ this.check = function() {
+ expect(this.data).toEqualData({
+ 'foo': 'bar',
+ 'baz': 'biz'
+ });
+ expect(this.data).toEqualData({
+ 'foo': 'bar',
+ 'baz': 'biz'
+ });
+ expect(this.str).toBe('Hello, world!');
+ expect(this.fn()).toBe('called!');
};
- return otherDirectiveController;
- }
- };
+ controllerCalled = true;
+ if (preAssignBindingsEnabled) {
+ this.check();
+ } else {
+ this.$onInit = this.check;
+ }
+ });
+ $compileProvider.directive('fooDir', valueFn({
+ templateUrl: 'test.html',
+ bindToController: {
+ 'data': '=dirData',
+ 'oneway': 'isolate');
+ $rootScope.fn = valueFn('called!');
+ $rootScope.whom = 'world';
+ $rootScope.remoteData = {
+ 'foo': 'bar',
+ 'baz': 'biz'
+ };
+ element = $compile('
')($rootScope);
+ $rootScope.$digest();
+ expect(controllerCalled).toBe(true);
+ });
});
- });
-
- inject(function(log, $compile, $rootScope) {
- element = $compile(' ')($rootScope);
- expect(element.data('$myDirectiveController')).toBe(directiveController);
- expect(element.data('$myOtherDirectiveController')).toBe(otherDirectiveController);
- });
- });
-
- it('should get required parent controller', function() {
- module(function() {
- directive('nested', function(log) {
- return {
- require: '^^?nested',
- controller: function($scope) {},
- link: function(scope, element, attrs, controller) {
- log(!!controller);
- }
- };
+ it('should bind to multiple directives controllers via object notation (no scope)', function() {
+ var controller1Called = false;
+ var controller2Called = false;
+ module(function($compileProvider, $controllerProvider) {
+ $compileProvider.directive('foo', valueFn({
+ bindToController: {
+ 'data': '=fooData',
+ 'oneway': ' ' +
+ ' ')($rootScope);
+ $rootScope.$digest();
+ expect(controller1Called).toBe(true);
+ expect(controller2Called).toBe(true);
+ });
});
- });
- inject(function(log, $compile, $rootScope) {
- element = $compile('
')($rootScope);
- expect(log).toEqual('true; false');
- });
- });
- it('should get required parent controller when the question mark precedes the ^^', function() {
- module(function() {
- directive('nested', function(log) {
- return {
- require: '?^^nested',
- controller: function($scope) {},
- link: function(scope, element, attrs, controller) {
- log(!!controller);
- }
- };
+ it('should bind to multiple directives controllers via object notation (new iso scope)', function() {
+ var controller1Called = false;
+ var controller2Called = false;
+ module(function($compileProvider, $controllerProvider) {
+ $compileProvider.directive('foo', valueFn({
+ bindToController: {
+ 'data': '=fooData',
+ 'oneway': '
' +
+ ' ')($rootScope);
+ $rootScope.$digest();
+ expect(controller1Called).toBe(true);
+ expect(controller2Called).toBe(true);
+ });
});
- });
- inject(function(log, $compile, $rootScope) {
- element = $compile('
')($rootScope);
- expect(log).toEqual('true; false');
- });
- });
- it('should throw if required parent is not found', function() {
- module(function() {
- directive('nested', function() {
- return {
- require: '^^nested',
- controller: function($scope) {},
- link: function(scope, element, attrs, controller) {}
- };
+ it('should bind to multiple directives controllers via object notation (new scope)', function() {
+ var controller1Called = false;
+ var controller2Called = false;
+ module(function($compileProvider, $controllerProvider) {
+ $compileProvider.directive('foo', valueFn({
+ bindToController: {
+ 'data': '=fooData',
+ 'oneway': '
' +
+ ' ')($rootScope);
+ $rootScope.$digest();
+ expect(controller1Called).toBe(true);
+ expect(controller2Called).toBe(true);
+ });
});
- });
- inject(function($compile, $rootScope) {
- expect(function() {
- element = $compile('
')($rootScope);
- }).toThrowMinErr('$compile', 'ctreq', 'Controller \'nested\', required by directive \'nested\', can\'t be found!');
- });
- });
-
- it('should get required controller via linkingFn (template)', function() {
- module(function() {
- directive('dirA', function() {
- return {
- controller: function() {
- this.name = 'dirA';
- }
- };
- });
- directive('dirB', function(log) {
- return {
- require: 'dirA',
- template: '
dirB
',
- link: function(scope, element, attrs, dirAController) {
- log('dirAController.name: ' + dirAController.name);
- }
- };
- });
- });
- inject(function(log, $compile, $rootScope) {
- element = $compile('
')($rootScope);
- expect(log).toEqual('dirAController.name: dirA');
- });
- });
+ it('should evaluate against the correct scope, when using `bindToController` (new scope)',
+ function() {
+ module(function($compileProvider, $controllerProvider) {
+ $controllerProvider.register({
+ 'ParentCtrl': function() {
+ this.value1 = 'parent1';
+ this.value2 = 'parent2';
+ this.value3 = function() { return 'parent3'; };
+ this.value4 = 'parent4';
+ },
+ 'ChildCtrl': function() {
+ this.value1 = 'child1';
+ this.value2 = 'child2';
+ this.value3 = function() { return 'child3'; };
+ this.value4 = 'child4';
+ }
+ });
- it('should get required controller via linkingFn (templateUrl)', function() {
- module(function() {
- directive('dirA', function() {
- return {
- controller: function() {
- this.name = 'dirA';
- }
- };
- });
- directive('dirB', function(log) {
- return {
- require: 'dirA',
- templateUrl: 'dirB.html',
- link: function(scope, element, attrs, dirAController) {
- log('dirAController.name: ' + dirAController.name);
- }
- };
- });
- });
- inject(function(log, $compile, $rootScope, $templateCache) {
- $templateCache.put('dirB.html', '
dirB
');
- element = $compile('
')($rootScope);
- $rootScope.$digest();
- expect(log).toEqual('dirAController.name: dirA');
- });
- });
+ $compileProvider.directive('child', valueFn({
+ scope: true,
+ controller: 'ChildCtrl as ctrl',
+ bindToController: {
+ fromParent1: '@',
+ fromParent2: '=',
+ fromParent3: '&',
+ fromParent4: '<'
+ },
+ template: ''
+ }));
+ });
- it('should bind the required controllers to the directive controller, if provided as an object and bindToController is truthy', function() {
- var parentController, siblingController;
+ inject(function($compile, $rootScope) {
+ element = $compile(
+ '
' +
+ '' +
+ ' ' +
+ '
')($rootScope);
+ $rootScope.$digest();
- function ParentController() { this.name = 'Parent'; }
- function SiblingController() { this.name = 'Sibling'; }
- function MeController() { this.name = 'Me'; }
- MeController.prototype.$onInit = function() {
- parentController = this.container;
- siblingController = this.friend;
- };
- spyOn(MeController.prototype, '$onInit').and.callThrough();
+ var parentCtrl = element.controller('ngController');
+ var childCtrl = element.find('child').controller('child');
- angular.module('my', [])
- .directive('me', function() {
- return {
- restrict: 'E',
- scope: {},
- require: { container: '^parent', friend: 'sibling' },
- bindToController: true,
- controller: MeController,
- controllerAs: '$ctrl'
- };
- })
- .directive('parent', function() {
- return {
- restrict: 'E',
- scope: {},
- controller: ParentController
- };
- })
- .directive('sibling', function() {
- return {
- controller: SiblingController
- };
- });
+ expect(childCtrl.fromParent1).toBe(parentCtrl.value1);
+ expect(childCtrl.fromParent1).not.toBe(childCtrl.value1);
+ expect(childCtrl.fromParent2).toBe(parentCtrl.value2);
+ expect(childCtrl.fromParent2).not.toBe(childCtrl.value2);
+ expect(childCtrl.fromParent3()()).toBe(parentCtrl.value3());
+ expect(childCtrl.fromParent3()()).not.toBe(childCtrl.value3());
+ expect(childCtrl.fromParent4).toBe(parentCtrl.value4);
+ expect(childCtrl.fromParent4).not.toBe(childCtrl.value4);
- module('my');
- inject(function($compile, $rootScope, meDirective) {
- element = $compile('
')($rootScope);
- expect(MeController.prototype.$onInit).toHaveBeenCalled();
- expect(parentController).toEqual(jasmine.any(ParentController));
- expect(siblingController).toEqual(jasmine.any(SiblingController));
- });
- });
+ childCtrl.fromParent2 = 'modified';
+ $rootScope.$digest();
- it('should use the key if the name of a required controller is omitted', function() {
- function ParentController() { this.name = 'Parent'; }
- function ParentOptController() { this.name = 'ParentOpt'; }
- function ParentOrSiblingController() { this.name = 'ParentOrSibling'; }
- function ParentOrSiblingOptController() { this.name = 'ParentOrSiblingOpt'; }
- function SiblingController() { this.name = 'Sibling'; }
- function SiblingOptController() { this.name = 'SiblingOpt'; }
-
- angular.module('my', [])
- .component('me', {
- require: {
- parent: '^^',
- parentOpt: '?^^',
- parentOrSibling1: '^',
- parentOrSiblingOpt1: '?^',
- parentOrSibling2: '^',
- parentOrSiblingOpt2: '?^',
- sibling: '',
- siblingOpt: '?'
+ expect(parentCtrl.value2).toBe('modified');
+ expect(childCtrl.value2).toBe('child2');
+ });
}
- })
- .directive('parent', function() {
- return {controller: ParentController};
- })
- .directive('parentOpt', function() {
- return {controller: ParentOptController};
- })
- .directive('parentOrSibling1', function() {
- return {controller: ParentOrSiblingController};
- })
- .directive('parentOrSiblingOpt1', function() {
- return {controller: ParentOrSiblingOptController};
- })
- .directive('parentOrSibling2', function() {
- return {controller: ParentOrSiblingController};
- })
- .directive('parentOrSiblingOpt2', function() {
- return {controller: ParentOrSiblingOptController};
- })
- .directive('sibling', function() {
- return {controller: SiblingController};
- })
- .directive('siblingOpt', function() {
- return {controller: SiblingOptController};
- });
+ );
- module('my');
- inject(function($compile, $rootScope) {
- var template =
- '
' +
- // With optional
- '
' +
- ' ' +
- ' ' +
- // Without optional
- '
' +
- ' ' +
- ' ' +
- '
';
- element = $compile(template)($rootScope);
-
- var ctrl1 = element.find('me').eq(0).controller('me');
- expect(ctrl1.parent).toEqual(jasmine.any(ParentController));
- expect(ctrl1.parentOpt).toEqual(jasmine.any(ParentOptController));
- expect(ctrl1.parentOrSibling1).toEqual(jasmine.any(ParentOrSiblingController));
- expect(ctrl1.parentOrSiblingOpt1).toEqual(jasmine.any(ParentOrSiblingOptController));
- expect(ctrl1.parentOrSibling2).toEqual(jasmine.any(ParentOrSiblingController));
- expect(ctrl1.parentOrSiblingOpt2).toEqual(jasmine.any(ParentOrSiblingOptController));
- expect(ctrl1.sibling).toEqual(jasmine.any(SiblingController));
- expect(ctrl1.siblingOpt).toEqual(jasmine.any(SiblingOptController));
-
- var ctrl2 = element.find('me').eq(1).controller('me');
- expect(ctrl2.parent).toEqual(jasmine.any(ParentController));
- expect(ctrl2.parentOpt).toBe(null);
- expect(ctrl2.parentOrSibling1).toEqual(jasmine.any(ParentOrSiblingController));
- expect(ctrl2.parentOrSiblingOpt1).toBe(null);
- expect(ctrl2.parentOrSibling2).toEqual(jasmine.any(ParentOrSiblingController));
- expect(ctrl2.parentOrSiblingOpt2).toBe(null);
- expect(ctrl2.sibling).toEqual(jasmine.any(SiblingController));
- expect(ctrl2.siblingOpt).toBe(null);
- });
- });
+ it('should evaluate against the correct scope, when using `bindToController` (new iso scope)',
+ function() {
+ module(function($compileProvider, $controllerProvider) {
+ $controllerProvider.register({
+ 'ParentCtrl': function() {
+ this.value1 = 'parent1';
+ this.value2 = 'parent2';
+ this.value3 = function() { return 'parent3'; };
+ this.value4 = 'parent4';
+ },
+ 'ChildCtrl': function() {
+ this.value1 = 'child1';
+ this.value2 = 'child2';
+ this.value3 = function() { return 'child3'; };
+ this.value4 = 'child4';
+ }
+ });
- it('should not bind required controllers if bindToController is falsy', function() {
- var parentController, siblingController;
+ $compileProvider.directive('child', valueFn({
+ scope: {},
+ controller: 'ChildCtrl as ctrl',
+ bindToController: {
+ fromParent1: '@',
+ fromParent2: '=',
+ fromParent3: '&',
+ fromParent4: '<'
+ },
+ template: ''
+ }));
+ });
- function ParentController() { this.name = 'Parent'; }
- function SiblingController() { this.name = 'Sibling'; }
- function MeController() { this.name = 'Me'; }
- MeController.prototype.$onInit = function() {
- parentController = this.container;
- siblingController = this.friend;
- };
- spyOn(MeController.prototype, '$onInit').and.callThrough();
+ inject(function($compile, $rootScope) {
+ element = $compile(
+ '
' +
+ '' +
+ ' ' +
+ '
')($rootScope);
+ $rootScope.$digest();
- angular.module('my', [])
- .directive('me', function() {
- return {
- restrict: 'E',
- scope: {},
- require: { container: '^parent', friend: 'sibling' },
- controller: MeController
- };
- })
- .directive('parent', function() {
- return {
- restrict: 'E',
- scope: {},
- controller: ParentController
- };
- })
- .directive('sibling', function() {
- return {
- controller: SiblingController
- };
- });
+ var parentCtrl = element.controller('ngController');
+ var childCtrl = element.find('child').controller('child');
- module('my');
- inject(function($compile, $rootScope, meDirective) {
- element = $compile('
')($rootScope);
- expect(MeController.prototype.$onInit).toHaveBeenCalled();
- expect(parentController).toBeUndefined();
- expect(siblingController).toBeUndefined();
- });
- });
+ expect(childCtrl.fromParent1).toBe(parentCtrl.value1);
+ expect(childCtrl.fromParent1).not.toBe(childCtrl.value1);
+ expect(childCtrl.fromParent2).toBe(parentCtrl.value2);
+ expect(childCtrl.fromParent2).not.toBe(childCtrl.value2);
+ expect(childCtrl.fromParent3()()).toBe(parentCtrl.value3());
+ expect(childCtrl.fromParent3()()).not.toBe(childCtrl.value3());
+ expect(childCtrl.fromParent4).toBe(parentCtrl.value4);
+ expect(childCtrl.fromParent4).not.toBe(childCtrl.value4);
- it('should bind required controllers to controller that has an explicit constructor return value', function() {
- var parentController, siblingController, meController;
+ childCtrl.fromParent2 = 'modified';
+ $rootScope.$digest();
- function ParentController() { this.name = 'Parent'; }
- function SiblingController() { this.name = 'Sibling'; }
- function MeController() {
- meController = {
- name: 'Me',
- $onInit: function() {
- parentController = this.container;
- siblingController = this.friend;
+ expect(parentCtrl.value2).toBe('modified');
+ expect(childCtrl.value2).toBe('child2');
+ });
}
- };
- spyOn(meController, '$onInit').and.callThrough();
- return meController;
- }
-
- angular.module('my', [])
- .directive('me', function() {
- return {
- restrict: 'E',
- scope: {},
- require: { container: '^parent', friend: 'sibling' },
- bindToController: true,
- controller: MeController,
- controllerAs: '$ctrl'
- };
- })
- .directive('parent', function() {
- return {
- restrict: 'E',
- scope: {},
- controller: ParentController
- };
- })
- .directive('sibling', function() {
- return {
- controller: SiblingController
- };
- });
+ );
- module('my');
- inject(function($compile, $rootScope, meDirective) {
- element = $compile('
')($rootScope);
- expect(meController.$onInit).toHaveBeenCalled();
- expect(parentController).toEqual(jasmine.any(ParentController));
- expect(siblingController).toEqual(jasmine.any(SiblingController));
- });
- });
+ it('should put controller in scope when controller identifier present but not using controllerAs', function() {
+ var controllerCalled = false;
+ var myCtrl;
+ module(function($compileProvider, $controllerProvider) {
+ $controllerProvider.register('myCtrl', function() {
+ controllerCalled = true;
+ myCtrl = this;
+ });
+ $compileProvider.directive('fooDir', valueFn({
+ templateUrl: 'test.html',
+ bindToController: {},
+ scope: true,
+ controller: 'myCtrl as theCtrl'
+ }));
+ });
+ inject(function($compile, $rootScope, $templateCache) {
+ $templateCache.put('test.html', '
isolate
');
+ element = $compile('
')($rootScope);
+ $rootScope.$digest();
+ expect(controllerCalled).toBe(true);
+ var childScope = element.children().scope();
+ expect(childScope).not.toBe($rootScope);
+ expect(childScope.theCtrl).toBe(myCtrl);
+ });
+ });
- it('should bind required controllers to controllers that return an explicit constructor return value', function() {
- var parentController, containerController, siblingController, friendController, meController;
- function MeController() {
- this.name = 'Me';
- this.$onInit = function() {
- containerController = this.container;
- friendController = this.friend;
- };
- }
- function ParentController() {
- parentController = { name: 'Parent' };
- return parentController;
- }
- function SiblingController() {
- siblingController = { name: 'Sibling' };
- return siblingController;
- }
+ it('should re-install controllerAs and bindings for returned value from controller (new scope)', function() {
+ var controllerCalled = false;
+ var myCtrl;
- angular.module('my', [])
- .directive('me', function() {
- return {
- priority: 1, // make sure it is run before sibling to test this case correctly
- restrict: 'E',
- scope: {},
- require: { container: '^parent', friend: 'sibling' },
- bindToController: true,
- controller: MeController,
- controllerAs: '$ctrl'
- };
- })
- .directive('parent', function() {
- return {
- restrict: 'E',
- scope: {},
- controller: ParentController
- };
- })
- .directive('sibling', function() {
- return {
- controller: SiblingController
+ function MyCtrl() {
+ }
+ MyCtrl.prototype.test = function() {
+ expect(this.data).toEqualData({
+ 'foo': 'bar',
+ 'baz': 'biz'
+ });
+ expect(this.oneway).toEqualData({
+ 'foo': 'bar',
+ 'baz': 'biz'
+ });
+ expect(this.str).toBe('Hello, world!');
+ expect(this.fn()).toBe('called!');
};
+
+ module(function($compileProvider, $controllerProvider) {
+ $controllerProvider.register('myCtrl', function() {
+ controllerCalled = true;
+ myCtrl = this;
+ return new MyCtrl();
+ });
+ $compileProvider.directive('fooDir', valueFn({
+ templateUrl: 'test.html',
+ bindToController: {
+ 'data': '=dirData',
+ 'oneway': '
isolate');
+ $rootScope.fn = valueFn('called!');
+ $rootScope.whom = 'world';
+ $rootScope.remoteData = {
+ 'foo': 'bar',
+ 'baz': 'biz'
+ };
+ element = $compile('
')($rootScope);
+ $rootScope.$digest();
+ expect(controllerCalled).toBe(true);
+ var childScope = element.children().scope();
+ expect(childScope).not.toBe($rootScope);
+ expect(childScope.theCtrl).not.toBe(myCtrl);
+ expect(childScope.theCtrl.constructor).toBe(MyCtrl);
+ childScope.theCtrl.test();
+ });
});
- module('my');
- inject(function($compile, $rootScope, meDirective) {
- element = $compile(' ')($rootScope);
- expect(containerController).toEqual(parentController);
- expect(friendController).toEqual(siblingController);
- });
- });
- it('should require controller of an isolate directive from a non-isolate directive on the ' +
- 'same element', function() {
- var IsolateController = function() {};
- var isolateDirControllerInNonIsolateDirective;
+ it('should re-install controllerAs and bindings for returned value from controller (isolate scope)', function() {
+ var controllerCalled = false;
+ var myCtrl;
- module(function() {
- directive('isolate', function() {
- return {
- scope: {},
- controller: IsolateController
- };
- });
- directive('nonIsolate', function() {
- return {
- require: 'isolate',
- link: function(_, __, ___, isolateDirController) {
- isolateDirControllerInNonIsolateDirective = isolateDirController;
- }
+ function MyCtrl() {
+ }
+ MyCtrl.prototype.test = function() {
+ expect(this.data).toEqualData({
+ 'foo': 'bar',
+ 'baz': 'biz'
+ });
+ expect(this.oneway).toEqualData({
+ 'foo': 'bar',
+ 'baz': 'biz'
+ });
+ expect(this.str).toBe('Hello, world!');
+ expect(this.fn()).toBe('called!');
};
+
+ module(function($compileProvider, $controllerProvider) {
+ $controllerProvider.register('myCtrl', function() {
+ controllerCalled = true;
+ myCtrl = this;
+ return new MyCtrl();
+ });
+ $compileProvider.directive('fooDir', valueFn({
+ templateUrl: 'test.html',
+ bindToController: true,
+ scope: {
+ 'data': '=dirData',
+ 'oneway': 'isolate');
+ $rootScope.fn = valueFn('called!');
+ $rootScope.whom = 'world';
+ $rootScope.remoteData = {
+ 'foo': 'bar',
+ 'baz': 'biz'
+ };
+ element = $compile('
')($rootScope);
+ $rootScope.$digest();
+ expect(controllerCalled).toBe(true);
+ var childScope = element.children().scope();
+ expect(childScope).not.toBe($rootScope);
+ expect(childScope.theCtrl).not.toBe(myCtrl);
+ expect(childScope.theCtrl.constructor).toBe(MyCtrl);
+ childScope.theCtrl.test();
+ });
});
- });
- inject(function($compile, $rootScope) {
- element = $compile('
')($rootScope);
+ describe('should not overwrite @-bound property each digest when not present', function() {
+ it('when creating new scope', function() {
+ module(function($compileProvider) {
+ $compileProvider.directive('testDir', valueFn({
+ scope: true,
+ bindToController: {
+ prop: '@'
+ },
+ controller: function() {
+ var self = this;
+ this.initProp = function() {
+ this.prop = this.prop || 'default';
+ };
+ if (preAssignBindingsEnabled) {
+ this.initProp();
+ } else {
+ this.$onInit = this.initProp;
+ }
+ this.getProp = function() {
+ return self.prop;
+ };
+ },
+ controllerAs: 'ctrl',
+ template: '
'
+ }));
+ });
+ inject(function($compile, $rootScope) {
+ element = $compile('
')($rootScope);
+ var scope = element.scope();
+ expect(scope.ctrl.getProp()).toBe('default');
- expect(isolateDirControllerInNonIsolateDirective).toBeDefined();
- expect(isolateDirControllerInNonIsolateDirective instanceof IsolateController).toBe(true);
- });
- });
+ $rootScope.$digest();
+ expect(scope.ctrl.getProp()).toBe('default');
+ });
+ });
+ it('when creating isolate scope', function() {
+ module(function($compileProvider) {
+ $compileProvider.directive('testDir', valueFn({
+ scope: {},
+ bindToController: {
+ prop: '@'
+ },
+ controller: function() {
+ var self = this;
+ this.initProp = function() {
+ this.prop = this.prop || 'default';
+ };
+ this.getProp = function() {
+ return self.prop;
+ };
+ if (preAssignBindingsEnabled) {
+ this.initProp();
+ } else {
+ this.$onInit = this.initProp;
+ }
+ },
+ controllerAs: 'ctrl',
+ template: '
'
+ }));
+ });
+ inject(function($compile, $rootScope) {
+ element = $compile('
')($rootScope);
+ var scope = element.isolateScope();
+ expect(scope.ctrl.getProp()).toBe('default');
- it('should give the isolate scope to the controller of another replaced directives in the template', function() {
- module(function() {
- directive('testDirective', function() {
- return {
- replace: true,
- restrict: 'E',
- scope: {},
- template: ' '
- };
+ $rootScope.$digest();
+ expect(scope.ctrl.getProp()).toBe('default');
+ });
+ });
});
- });
-
- inject(function($rootScope) {
- compile('
');
- element = element.children().eq(0);
- expect(element[0].checked).toBe(false);
- element.isolateScope().model = true;
- $rootScope.$digest();
- expect(element[0].checked).toBe(true);
});
- });
+ describe('require', function() {
- it('should share isolate scope with replaced directives (template)', function() {
- var normalScope;
- var isolateScope;
-
- module(function() {
- directive('isolate', function() {
- return {
- replace: true,
- scope: {},
- template: '{{name}} ',
- link: function(s) {
- isolateScope = s;
- }
- };
- });
- directive('nonIsolate', function() {
- return {
- link: function(s) {
- normalScope = s;
- }
- };
+ it('should get required controller', function() {
+ module(function() {
+ directive('main', function(log) {
+ return {
+ priority: 2,
+ controller: function() {
+ this.name = 'main';
+ },
+ link: function(scope, element, attrs, controller) {
+ log(controller.name);
+ }
+ };
+ });
+ directive('dep', function(log) {
+ return {
+ priority: 1,
+ require: 'main',
+ link: function(scope, element, attrs, controller) {
+ log('dep:' + controller.name);
+ }
+ };
+ });
+ directive('other', function(log) {
+ return {
+ link: function(scope, element, attrs, controller) {
+ log(!!controller); // should be false
+ }
+ };
+ });
+ });
+ inject(function(log, $compile, $rootScope) {
+ element = $compile('
')($rootScope);
+ expect(log).toEqual('false; dep:main; main');
+ });
});
- });
-
- inject(function($compile, $rootScope) {
- element = $compile('
')($rootScope);
- expect(normalScope).toBe($rootScope);
- expect(normalScope.name).toEqual(undefined);
- expect(isolateScope.name).toEqual('WORKS');
- $rootScope.$digest();
- expect(element.text()).toEqual('WORKS');
- });
- });
+ it('should respect explicit return value from controller', function() {
+ var expectedController;
+ module(function() {
+ directive('logControllerProp', function(log) {
+ return {
+ controller: function($scope) {
+ this.foo = 'baz'; // value should not be used.
+ expectedController = {foo: 'bar'};
+ return expectedController;
+ },
+ link: function(scope, element, attrs, controller) {
+ expect(expectedController).toBeDefined();
+ expect(controller).toBe(expectedController);
+ expect(controller.foo).toBe('bar');
+ log('done');
+ }
+ };
+ });
+ });
+ inject(function(log, $compile, $rootScope) {
+ element = $compile(' ')($rootScope);
+ expect(log).toEqual('done');
+ expect(element.data('$logControllerPropController')).toBe(expectedController);
+ });
+ });
- it('should share isolate scope with replaced directives (templateUrl)', function() {
- var normalScope;
- var isolateScope;
- module(function() {
- directive('isolate', function() {
- return {
- replace: true,
- scope: {},
- templateUrl: 'main.html',
- link: function(s) {
- isolateScope = s;
- }
- };
- });
- directive('nonIsolate', function() {
- return {
- link: function(s) {
- normalScope = s;
- }
- };
+ it('should get explicit return value of required parent controller', function() {
+ var expectedController;
+ module(function() {
+ directive('nested', function(log) {
+ return {
+ require: '^^?nested',
+ controller: function() {
+ if (!expectedController) expectedController = {foo: 'bar'};
+ return expectedController;
+ },
+ link: function(scope, element, attrs, controller) {
+ if (element.parent().length) {
+ expect(expectedController).toBeDefined();
+ expect(controller).toBe(expectedController);
+ expect(controller.foo).toBe('bar');
+ log('done');
+ }
+ }
+ };
+ });
+ });
+ inject(function(log, $compile, $rootScope) {
+ element = $compile('')($rootScope);
+ expect(log).toEqual('done');
+ expect(element.data('$nestedController')).toBe(expectedController);
+ });
});
- });
- inject(function($compile, $rootScope, $templateCache) {
- $templateCache.put('main.html', '{{name}} ');
- element = $compile('
')($rootScope);
- $rootScope.$apply();
-
- expect(normalScope).toBe($rootScope);
- expect(normalScope.name).toEqual(undefined);
- expect(isolateScope.name).toEqual('WORKS');
- expect(element.text()).toEqual('WORKS');
- });
- });
+ it('should respect explicit controller return value when using controllerAs', function() {
+ module(function() {
+ directive('main', function() {
+ return {
+ templateUrl: 'main.html',
+ scope: {},
+ controller: function() {
+ this.name = 'lucas';
+ return {name: 'george'};
+ },
+ controllerAs: 'mainCtrl'
+ };
+ });
+ });
+ inject(function($templateCache, $compile, $rootScope) {
+ $templateCache.put('main.html', 'template:{{mainCtrl.name}} ');
+ element = $compile(' ')($rootScope);
+ $rootScope.$apply();
+ expect(element.text()).toBe('template:george');
+ });
+ });
- it('should not get confused about where to use isolate scope when a replaced directive is used multiple times',
- function() {
- module(function() {
- directive('isolate', function() {
- return {
- replace: true,
- scope: {},
- template: ' '
- };
- });
- directive('scopeTester', function(log) {
- return {
- link: function($scope, $element) {
- log($element.attr('scope-tester') + '=' + ($scope.$root === $scope ? 'non-isolate' : 'isolate'));
- }
- };
+ it('transcluded children should receive explicit return value of parent controller', function() {
+ var expectedController;
+ module(function() {
+ directive('nester', valueFn({
+ transclude: true,
+ controller: function($transclude) {
+ this.foo = 'baz';
+ expectedController = {transclude:$transclude, foo: 'bar'};
+ return expectedController;
+ },
+ link: function(scope, el, attr, ctrl) {
+ ctrl.transclude(cloneAttach);
+ function cloneAttach(clone) {
+ el.append(clone);
+ }
+ }
+ }));
+ directive('nested', function(log) {
+ return {
+ require: '^^nester',
+ link: function(scope, element, attrs, controller) {
+ expect(controller).toBeDefined();
+ expect(controller).toBe(expectedController);
+ log('done');
+ }
+ };
+ });
+ });
+ inject(function(log, $compile) {
+ element = $compile('')($rootScope);
+ $rootScope.$apply();
+ expect(log.toString()).toBe('done');
+ expect(element.data('$nesterController')).toBe(expectedController);
+ });
});
- });
-
- inject(function($compile, $rootScope, log) {
- element = $compile('')($rootScope);
- $rootScope.$digest();
- expect(log).toEqual('inside=isolate; ' +
- 'outside replaced=non-isolate; ' + // outside
- 'outside replaced=isolate; ' + // replaced
- 'sibling=non-isolate');
- });
- });
+ it('explicit controller return values are ignored if they are primitives', function() {
+ module(function() {
+ directive('logControllerProp', function(log) {
+ return {
+ controller: function($scope) {
+ this.foo = 'baz'; // value *will* be used.
+ return 'bar';
+ },
+ link: function(scope, element, attrs, controller) {
+ log(controller.foo);
+ }
+ };
+ });
+ });
+ inject(function(log, $compile, $rootScope) {
+ element = $compile(' ')($rootScope);
+ expect(log).toEqual('baz');
+ expect(element.data('$logControllerPropController').foo).toEqual('baz');
+ });
+ });
- it('should require controller of a non-isolate directive from an isolate directive on the ' +
- 'same element', function() {
- var NonIsolateController = function() {};
- var nonIsolateDirControllerInIsolateDirective;
- module(function() {
- directive('isolate', function() {
- return {
- scope: {},
- require: 'nonIsolate',
- link: function(_, __, ___, nonIsolateDirController) {
- nonIsolateDirControllerInIsolateDirective = nonIsolateDirController;
- }
- };
- });
- directive('nonIsolate', function() {
- return {
- controller: NonIsolateController
- };
- });
- });
+ it('should correctly assign controller return values for multiple directives', function() {
+ var directiveController, otherDirectiveController;
+ module(function() {
- inject(function($compile, $rootScope) {
- element = $compile('
')($rootScope);
+ directive('myDirective', function(log) {
+ return {
+ scope: true,
+ controller: function($scope) {
+ directiveController = {
+ foo: 'bar'
+ };
+ return directiveController;
+ }
+ };
+ });
- expect(nonIsolateDirControllerInIsolateDirective).toBeDefined();
- expect(nonIsolateDirControllerInIsolateDirective instanceof NonIsolateController).toBe(true);
- });
- });
+ directive('myOtherDirective', function(log) {
+ return {
+ controller: function($scope) {
+ otherDirectiveController = {
+ baz: 'luh'
+ };
+ return otherDirectiveController;
+ }
+ };
+ });
+ });
- it('should support controllerAs', function() {
- module(function() {
- directive('main', function() {
- return {
- templateUrl: 'main.html',
- transclude: true,
- scope: {},
- controller: function() {
- this.name = 'lucas';
- },
- controllerAs: 'mainCtrl'
- };
+ inject(function(log, $compile, $rootScope) {
+ element = $compile(' ')($rootScope);
+ expect(element.data('$myDirectiveController')).toBe(directiveController);
+ expect(element.data('$myOtherDirectiveController')).toBe(otherDirectiveController);
+ });
});
- });
- inject(function($templateCache, $compile, $rootScope) {
- $templateCache.put('main.html', 'template:{{mainCtrl.name}}
');
- element = $compile('transclude:{{mainCtrl.name}}
')($rootScope);
- $rootScope.$apply();
- expect(element.text()).toBe('template:lucas transclude:');
- });
- });
- it('should support controller alias', function() {
- module(function($controllerProvider) {
- $controllerProvider.register('MainCtrl', function() {
- this.name = 'lucas';
- });
- directive('main', function() {
- return {
- templateUrl: 'main.html',
- scope: {},
- controller: 'MainCtrl as mainCtrl'
- };
+ it('should get required parent controller', function() {
+ module(function() {
+ directive('nested', function(log) {
+ return {
+ require: '^^?nested',
+ controller: function($scope) {},
+ link: function(scope, element, attrs, controller) {
+ log(!!controller);
+ }
+ };
+ });
+ });
+ inject(function(log, $compile, $rootScope) {
+ element = $compile('')($rootScope);
+ expect(log).toEqual('true; false');
+ });
});
- });
- inject(function($templateCache, $compile, $rootScope) {
- $templateCache.put('main.html', '{{mainCtrl.name}} ');
- element = $compile('
')($rootScope);
- $rootScope.$apply();
- expect(element.text()).toBe('lucas');
- });
- });
-
- it('should require controller on parent element',function() {
- module(function() {
- directive('main', function(log) {
- return {
- controller: function() {
- this.name = 'main';
- }
- };
- });
- directive('dep', function(log) {
- return {
- require: '^main',
- link: function(scope, element, attrs, controller) {
- log('dep:' + controller.name);
- }
- };
+ it('should get required parent controller when the question mark precedes the ^^', function() {
+ module(function() {
+ directive('nested', function(log) {
+ return {
+ require: '?^^nested',
+ controller: function($scope) {},
+ link: function(scope, element, attrs, controller) {
+ log(!!controller);
+ }
+ };
+ });
+ });
+ inject(function(log, $compile, $rootScope) {
+ element = $compile('')($rootScope);
+ expect(log).toEqual('true; false');
+ });
});
- });
- inject(function(log, $compile, $rootScope) {
- element = $compile('')($rootScope);
- expect(log).toEqual('dep:main');
- });
- });
- it('should throw an error if required controller can\'t be found',function() {
- module(function() {
- directive('dep', function(log) {
- return {
- require: '^main',
- link: function(scope, element, attrs, controller) {
- log('dep:' + controller.name);
- }
- };
+ it('should throw if required parent is not found', function() {
+ module(function() {
+ directive('nested', function() {
+ return {
+ require: '^^nested',
+ controller: function($scope) {},
+ link: function(scope, element, attrs, controller) {}
+ };
+ });
+ });
+ inject(function($compile, $rootScope) {
+ expect(function() {
+ element = $compile('
')($rootScope);
+ }).toThrowMinErr('$compile', 'ctreq', 'Controller \'nested\', required by directive \'nested\', can\'t be found!');
+ });
});
- });
- inject(function(log, $compile, $rootScope) {
- expect(function() {
- $compile('')($rootScope);
- }).toThrowMinErr('$compile', 'ctreq', 'Controller \'main\', required by directive \'dep\', can\'t be found!');
- });
- });
- it('should pass null if required controller can\'t be found and is optional',function() {
- module(function() {
- directive('dep', function(log) {
- return {
- require: '?^main',
- link: function(scope, element, attrs, controller) {
- log('dep:' + controller);
- }
- };
+ it('should get required controller via linkingFn (template)', function() {
+ module(function() {
+ directive('dirA', function() {
+ return {
+ controller: function() {
+ this.name = 'dirA';
+ }
+ };
+ });
+ directive('dirB', function(log) {
+ return {
+ require: 'dirA',
+ template: 'dirB
',
+ link: function(scope, element, attrs, dirAController) {
+ log('dirAController.name: ' + dirAController.name);
+ }
+ };
+ });
+ });
+ inject(function(log, $compile, $rootScope) {
+ element = $compile('
')($rootScope);
+ expect(log).toEqual('dirAController.name: dirA');
+ });
});
- });
- inject(function(log, $compile, $rootScope) {
- $compile('')($rootScope);
- expect(log).toEqual('dep:null');
- });
- });
- it('should pass null if required controller can\'t be found and is optional with the question mark on the right',function() {
- module(function() {
- directive('dep', function(log) {
- return {
- require: '^?main',
- link: function(scope, element, attrs, controller) {
- log('dep:' + controller);
- }
- };
+ it('should get required controller via linkingFn (templateUrl)', function() {
+ module(function() {
+ directive('dirA', function() {
+ return {
+ controller: function() {
+ this.name = 'dirA';
+ }
+ };
+ });
+ directive('dirB', function(log) {
+ return {
+ require: 'dirA',
+ templateUrl: 'dirB.html',
+ link: function(scope, element, attrs, dirAController) {
+ log('dirAController.name: ' + dirAController.name);
+ }
+ };
+ });
+ });
+ inject(function(log, $compile, $rootScope, $templateCache) {
+ $templateCache.put('dirB.html', 'dirB
');
+ element = $compile('
')($rootScope);
+ $rootScope.$digest();
+ expect(log).toEqual('dirAController.name: dirA');
+ });
});
- });
- inject(function(log, $compile, $rootScope) {
- $compile('')($rootScope);
- expect(log).toEqual('dep:null');
- });
- });
+ it('should bind the required controllers to the directive controller, if provided as an object and bindToController is truthy', function() {
+ var parentController, siblingController;
- it('should have optional controller on current element', function() {
- module(function() {
- directive('dep', function(log) {
- return {
- require: '?main',
- link: function(scope, element, attrs, controller) {
- log('dep:' + !!controller);
- }
+ function ParentController() { this.name = 'Parent'; }
+ function SiblingController() { this.name = 'Sibling'; }
+ function MeController() { this.name = 'Me'; }
+ MeController.prototype.$onInit = function() {
+ parentController = this.container;
+ siblingController = this.friend;
};
- });
- });
- inject(function(log, $compile, $rootScope) {
- element = $compile('')($rootScope);
- expect(log).toEqual('dep:false');
- });
- });
+ spyOn(MeController.prototype, '$onInit').and.callThrough();
+
+ angular.module('my', [])
+ .directive('me', function() {
+ return {
+ restrict: 'E',
+ scope: {},
+ require: { container: '^parent', friend: 'sibling' },
+ bindToController: true,
+ controller: MeController,
+ controllerAs: '$ctrl'
+ };
+ })
+ .directive('parent', function() {
+ return {
+ restrict: 'E',
+ scope: {},
+ controller: ParentController
+ };
+ })
+ .directive('sibling', function() {
+ return {
+ controller: SiblingController
+ };
+ });
+ module('my');
+ inject(function($compile, $rootScope, meDirective) {
+ element = $compile(' ')($rootScope);
+ expect(MeController.prototype.$onInit).toHaveBeenCalled();
+ expect(parentController).toEqual(jasmine.any(ParentController));
+ expect(siblingController).toEqual(jasmine.any(SiblingController));
+ });
+ });
+
+ it('should use the key if the name of a required controller is omitted', function() {
+ function ParentController() { this.name = 'Parent'; }
+ function ParentOptController() { this.name = 'ParentOpt'; }
+ function ParentOrSiblingController() { this.name = 'ParentOrSibling'; }
+ function ParentOrSiblingOptController() { this.name = 'ParentOrSiblingOpt'; }
+ function SiblingController() { this.name = 'Sibling'; }
+ function SiblingOptController() { this.name = 'SiblingOpt'; }
+
+ angular.module('my', [])
+ .component('me', {
+ require: {
+ parent: '^^',
+ parentOpt: '?^^',
+ parentOrSibling1: '^',
+ parentOrSiblingOpt1: '?^',
+ parentOrSibling2: '^',
+ parentOrSiblingOpt2: '?^',
+ sibling: '',
+ siblingOpt: '?'
+ }
+ })
+ .directive('parent', function() {
+ return {controller: ParentController};
+ })
+ .directive('parentOpt', function() {
+ return {controller: ParentOptController};
+ })
+ .directive('parentOrSibling1', function() {
+ return {controller: ParentOrSiblingController};
+ })
+ .directive('parentOrSiblingOpt1', function() {
+ return {controller: ParentOrSiblingOptController};
+ })
+ .directive('parentOrSibling2', function() {
+ return {controller: ParentOrSiblingController};
+ })
+ .directive('parentOrSiblingOpt2', function() {
+ return {controller: ParentOrSiblingOptController};
+ })
+ .directive('sibling', function() {
+ return {controller: SiblingController};
+ })
+ .directive('siblingOpt', function() {
+ return {controller: SiblingOptController};
+ });
- it('should support multiple controllers', function() {
- module(function() {
- directive('c1', valueFn({
- controller: function() { this.name = 'c1'; }
- }));
- directive('c2', valueFn({
- controller: function() { this.name = 'c2'; }
- }));
- directive('dep', function(log) {
- return {
- require: ['^c1', '^c2'],
- link: function(scope, element, attrs, controller) {
- log('dep:' + controller[0].name + '-' + controller[1].name);
- }
+ module('my');
+ inject(function($compile, $rootScope) {
+ var template =
+ '' +
+ // With optional
+ '
' +
+ ' ' +
+ ' ' +
+ // Without optional
+ '
' +
+ ' ' +
+ ' ' +
+ '
';
+ element = $compile(template)($rootScope);
+
+ var ctrl1 = element.find('me').eq(0).controller('me');
+ expect(ctrl1.parent).toEqual(jasmine.any(ParentController));
+ expect(ctrl1.parentOpt).toEqual(jasmine.any(ParentOptController));
+ expect(ctrl1.parentOrSibling1).toEqual(jasmine.any(ParentOrSiblingController));
+ expect(ctrl1.parentOrSiblingOpt1).toEqual(jasmine.any(ParentOrSiblingOptController));
+ expect(ctrl1.parentOrSibling2).toEqual(jasmine.any(ParentOrSiblingController));
+ expect(ctrl1.parentOrSiblingOpt2).toEqual(jasmine.any(ParentOrSiblingOptController));
+ expect(ctrl1.sibling).toEqual(jasmine.any(SiblingController));
+ expect(ctrl1.siblingOpt).toEqual(jasmine.any(SiblingOptController));
+
+ var ctrl2 = element.find('me').eq(1).controller('me');
+ expect(ctrl2.parent).toEqual(jasmine.any(ParentController));
+ expect(ctrl2.parentOpt).toBe(null);
+ expect(ctrl2.parentOrSibling1).toEqual(jasmine.any(ParentOrSiblingController));
+ expect(ctrl2.parentOrSiblingOpt1).toBe(null);
+ expect(ctrl2.parentOrSibling2).toEqual(jasmine.any(ParentOrSiblingController));
+ expect(ctrl2.parentOrSiblingOpt2).toBe(null);
+ expect(ctrl2.sibling).toEqual(jasmine.any(SiblingController));
+ expect(ctrl2.siblingOpt).toBe(null);
+ });
+ });
+
+
+ it('should not bind required controllers if bindToController is falsy', function() {
+ var parentController, siblingController;
+
+ function ParentController() { this.name = 'Parent'; }
+ function SiblingController() { this.name = 'Sibling'; }
+ function MeController() { this.name = 'Me'; }
+ MeController.prototype.$onInit = function() {
+ parentController = this.container;
+ siblingController = this.friend;
};
- });
- });
- inject(function(log, $compile, $rootScope) {
- element = $compile('')($rootScope);
- expect(log).toEqual('dep:c1-c2');
- });
- });
+ spyOn(MeController.prototype, '$onInit').and.callThrough();
- it('should support multiple controllers as an object hash', function() {
- module(function() {
- directive('c1', valueFn({
- controller: function() { this.name = 'c1'; }
- }));
- directive('c2', valueFn({
- controller: function() { this.name = 'c2'; }
- }));
- directive('dep', function(log) {
- return {
- require: { myC1: '^c1', myC2: '^c2' },
- link: function(scope, element, attrs, controllers) {
- log('dep:' + controllers.myC1.name + '-' + controllers.myC2.name);
- }
- };
+ angular.module('my', [])
+ .directive('me', function() {
+ return {
+ restrict: 'E',
+ scope: {},
+ require: { container: '^parent', friend: 'sibling' },
+ controller: MeController
+ };
+ })
+ .directive('parent', function() {
+ return {
+ restrict: 'E',
+ scope: {},
+ controller: ParentController
+ };
+ })
+ .directive('sibling', function() {
+ return {
+ controller: SiblingController
+ };
+ });
+
+ module('my');
+ inject(function($compile, $rootScope, meDirective) {
+ element = $compile(' ')($rootScope);
+ expect(MeController.prototype.$onInit).toHaveBeenCalled();
+ expect(parentController).toBeUndefined();
+ expect(siblingController).toBeUndefined();
+ });
});
- });
- inject(function(log, $compile, $rootScope) {
- element = $compile('')($rootScope);
- expect(log).toEqual('dep:c1-c2');
- });
- });
- it('should support omitting the name of the required controller if it is the same as the key',
- function() {
- module(function() {
- directive('myC1', valueFn({
- controller: function() { this.name = 'c1'; }
- }));
- directive('myC2', valueFn({
- controller: function() { this.name = 'c2'; }
- }));
- directive('dep', function(log) {
- return {
- require: { myC1: '^', myC2: '^' },
- link: function(scope, element, attrs, controllers) {
- log('dep:' + controllers.myC1.name + '-' + controllers.myC2.name);
+ it('should bind required controllers to controller that has an explicit constructor return value', function() {
+ var parentController, siblingController, meController;
+
+ function ParentController() { this.name = 'Parent'; }
+ function SiblingController() { this.name = 'Sibling'; }
+ function MeController() {
+ meController = {
+ name: 'Me',
+ $onInit: function() {
+ parentController = this.container;
+ siblingController = this.friend;
}
};
+ spyOn(meController, '$onInit').and.callThrough();
+ return meController;
+ }
+
+ angular.module('my', [])
+ .directive('me', function() {
+ return {
+ restrict: 'E',
+ scope: {},
+ require: { container: '^parent', friend: 'sibling' },
+ bindToController: true,
+ controller: MeController,
+ controllerAs: '$ctrl'
+ };
+ })
+ .directive('parent', function() {
+ return {
+ restrict: 'E',
+ scope: {},
+ controller: ParentController
+ };
+ })
+ .directive('sibling', function() {
+ return {
+ controller: SiblingController
+ };
+ });
+
+ module('my');
+ inject(function($compile, $rootScope, meDirective) {
+ element = $compile(' ')($rootScope);
+ expect(meController.$onInit).toHaveBeenCalled();
+ expect(parentController).toEqual(jasmine.any(ParentController));
+ expect(siblingController).toEqual(jasmine.any(SiblingController));
});
});
- inject(function(log, $compile, $rootScope) {
- element = $compile('')($rootScope);
- expect(log).toEqual('dep:c1-c2');
- });
- }
- );
- it('should instantiate the controller just once when template/templateUrl', function() {
- var syncCtrlSpy = jasmine.createSpy('sync controller'),
- asyncCtrlSpy = jasmine.createSpy('async controller');
- module(function() {
- directive('myDirectiveSync', valueFn({
- template: 'Hello!
',
- controller: syncCtrlSpy
- }));
- directive('myDirectiveAsync', valueFn({
- templateUrl: 'myDirectiveAsync.html',
- controller: asyncCtrlSpy,
- compile: function() {
- return function() {
+ it('should bind required controllers to controllers that return an explicit constructor return value', function() {
+ var parentController, containerController, siblingController, friendController, meController;
+
+ function MeController() {
+ this.name = 'Me';
+ this.$onInit = function() {
+ containerController = this.container;
+ friendController = this.friend;
};
}
- }));
- });
+ function ParentController() {
+ parentController = { name: 'Parent' };
+ return parentController;
+ }
+ function SiblingController() {
+ siblingController = { name: 'Sibling' };
+ return siblingController;
+ }
- inject(function($templateCache, $compile, $rootScope) {
- expect(syncCtrlSpy).not.toHaveBeenCalled();
- expect(asyncCtrlSpy).not.toHaveBeenCalled();
+ angular.module('my', [])
+ .directive('me', function() {
+ return {
+ priority: 1, // make sure it is run before sibling to test this case correctly
+ restrict: 'E',
+ scope: {},
+ require: { container: '^parent', friend: 'sibling' },
+ bindToController: true,
+ controller: MeController,
+ controllerAs: '$ctrl'
+ };
+ })
+ .directive('parent', function() {
+ return {
+ restrict: 'E',
+ scope: {},
+ controller: ParentController
+ };
+ })
+ .directive('sibling', function() {
+ return {
+ controller: SiblingController
+ };
+ });
- $templateCache.put('myDirectiveAsync.html', 'Hello!
');
- element = $compile('' +
- ' ' +
- ' ' +
- '
')($rootScope);
- expect(syncCtrlSpy).not.toHaveBeenCalled();
- expect(asyncCtrlSpy).not.toHaveBeenCalled();
+ module('my');
+ inject(function($compile, $rootScope, meDirective) {
+ element = $compile(' ')($rootScope);
+ expect(containerController).toEqual(parentController);
+ expect(friendController).toEqual(siblingController);
+ });
+ });
- $rootScope.$apply();
+ it('should require controller of an isolate directive from a non-isolate directive on the ' +
+ 'same element', function() {
+ var IsolateController = function() {};
+ var isolateDirControllerInNonIsolateDirective;
- //expect(syncCtrlSpy).toHaveBeenCalledOnce();
- expect(asyncCtrlSpy).toHaveBeenCalledOnce();
- });
- });
+ module(function() {
+ directive('isolate', function() {
+ return {
+ scope: {},
+ controller: IsolateController
+ };
+ });
+ directive('nonIsolate', function() {
+ return {
+ require: 'isolate',
+ link: function(_, __, ___, isolateDirController) {
+ isolateDirControllerInNonIsolateDirective = isolateDirController;
+ }
+ };
+ });
+ });
+ inject(function($compile, $rootScope) {
+ element = $compile('
')($rootScope);
+ expect(isolateDirControllerInNonIsolateDirective).toBeDefined();
+ expect(isolateDirControllerInNonIsolateDirective instanceof IsolateController).toBe(true);
+ });
+ });
- it('should instantiate controllers in the parent->child order when transluction, templateUrl and replacement ' +
- 'are in the mix', function() {
- // When a child controller is in the transclusion that replaces the parent element that has a directive with
- // a controller, we should ensure that we first instantiate the parent and only then stuff that comes from the
- // transclusion.
- //
- // The transclusion moves the child controller onto the same element as parent controller so both controllers are
- // on the same level.
- module(function() {
- directive('parentDirective', function() {
- return {
- transclude: true,
- replace: true,
- templateUrl: 'parentDirective.html',
- controller: function(log) { log('parentController'); }
- };
+ it('should give the isolate scope to the controller of another replaced directives in the template', function() {
+ module(function() {
+ directive('testDirective', function() {
+ return {
+ replace: true,
+ restrict: 'E',
+ scope: {},
+ template: ' '
+ };
+ });
+ });
+
+ inject(function($rootScope) {
+ compile('
');
+
+ element = element.children().eq(0);
+ expect(element[0].checked).toBe(false);
+ element.isolateScope().model = true;
+ $rootScope.$digest();
+ expect(element[0].checked).toBe(true);
+ });
});
- directive('childDirective', function() {
- return {
- require: '^parentDirective',
- templateUrl: 'childDirective.html',
- controller: function(log) { log('childController'); }
- };
+
+
+ it('should share isolate scope with replaced directives (template)', function() {
+ var normalScope;
+ var isolateScope;
+
+ module(function() {
+ directive('isolate', function() {
+ return {
+ replace: true,
+ scope: {},
+ template: '{{name}} ',
+ link: function(s) {
+ isolateScope = s;
+ }
+ };
+ });
+ directive('nonIsolate', function() {
+ return {
+ link: function(s) {
+ normalScope = s;
+ }
+ };
+ });
+ });
+
+ inject(function($compile, $rootScope) {
+ element = $compile('
')($rootScope);
+
+ expect(normalScope).toBe($rootScope);
+ expect(normalScope.name).toEqual(undefined);
+ expect(isolateScope.name).toEqual('WORKS');
+ $rootScope.$digest();
+ expect(element.text()).toEqual('WORKS');
+ });
});
- });
- inject(function($templateCache, log, $compile, $rootScope) {
- $templateCache.put('parentDirective.html', 'parentTemplateText;
');
- $templateCache.put('childDirective.html', 'childTemplateText; ');
- element = $compile('')($rootScope);
- $rootScope.$apply();
- expect(log).toEqual('parentController; childController');
- expect(element.text()).toBe('childTemplateText;childContentText;');
- });
- });
+ it('should share isolate scope with replaced directives (templateUrl)', function() {
+ var normalScope;
+ var isolateScope;
+ module(function() {
+ directive('isolate', function() {
+ return {
+ replace: true,
+ scope: {},
+ templateUrl: 'main.html',
+ link: function(s) {
+ isolateScope = s;
+ }
+ };
+ });
+ directive('nonIsolate', function() {
+ return {
+ link: function(s) {
+ normalScope = s;
+ }
+ };
+ });
+ });
- it('should instantiate the controller after the isolate scope bindings are initialized (with template)', function() {
- module(function() {
- var Ctrl = function($scope, log) {
- log('myFoo=' + $scope.myFoo);
- };
+ inject(function($compile, $rootScope, $templateCache) {
+ $templateCache.put('main.html', '{{name}} ');
+ element = $compile('
')($rootScope);
+ $rootScope.$apply();
- directive('myDirective', function() {
- return {
- scope: {
- myFoo: '='
- },
- template: 'Hello
',
- controller: Ctrl
- };
+ expect(normalScope).toBe($rootScope);
+ expect(normalScope.name).toEqual(undefined);
+ expect(isolateScope.name).toEqual('WORKS');
+ expect(element.text()).toEqual('WORKS');
+ });
});
- });
- inject(function($templateCache, $compile, $rootScope, log) {
- $rootScope.foo = 'bar';
- element = $compile('
')($rootScope);
- $rootScope.$apply();
- expect(log).toEqual('myFoo=bar');
- });
- });
+ it('should not get confused about where to use isolate scope when a replaced directive is used multiple times',
+ function() {
+ module(function() {
+ directive('isolate', function() {
+ return {
+ replace: true,
+ scope: {},
+ template: ' '
+ };
+ });
+ directive('scopeTester', function(log) {
+ return {
+ link: function($scope, $element) {
+ log($element.attr('scope-tester') + '=' + ($scope.$root === $scope ? 'non-isolate' : 'isolate'));
+ }
+ };
+ });
+ });
- it('should instantiate the controller after the isolate scope bindings are initialized (with templateUrl)', function() {
- module(function() {
- var Ctrl = function($scope, log) {
- log('myFoo=' + $scope.myFoo);
- };
+ inject(function($compile, $rootScope, log) {
+ element = $compile('')($rootScope);
- directive('myDirective', function() {
- return {
- scope: {
- myFoo: '='
- },
- templateUrl: 'hello.html',
- controller: Ctrl
- };
+ $rootScope.$digest();
+ expect(log).toEqual('inside=isolate; ' +
+ 'outside replaced=non-isolate; ' + // outside
+ 'outside replaced=isolate; ' + // replaced
+ 'sibling=non-isolate');
+ });
});
- });
- inject(function($templateCache, $compile, $rootScope, log) {
- $templateCache.put('hello.html', 'Hello
');
- $rootScope.foo = 'bar';
- element = $compile('
')($rootScope);
- $rootScope.$apply();
- expect(log).toEqual('myFoo=bar');
- });
- });
+ it('should require controller of a non-isolate directive from an isolate directive on the ' +
+ 'same element', function() {
+ var NonIsolateController = function() {};
+ var nonIsolateDirControllerInIsolateDirective;
+ module(function() {
+ directive('isolate', function() {
+ return {
+ scope: {},
+ require: 'nonIsolate',
+ link: function(_, __, ___, nonIsolateDirController) {
+ nonIsolateDirControllerInIsolateDirective = nonIsolateDirController;
+ }
+ };
+ });
+ directive('nonIsolate', function() {
+ return {
+ controller: NonIsolateController
+ };
+ });
+ });
- it('should instantiate controllers in the parent->child->baby order when nested transluction, templateUrl and ' +
- 'replacement are in the mix', function() {
- // similar to the test above, except that we have one more layer of nesting and nested transclusion
+ inject(function($compile, $rootScope) {
+ element = $compile('
')($rootScope);
- module(function() {
- directive('parentDirective', function() {
- return {
- transclude: true,
- replace: true,
- templateUrl: 'parentDirective.html',
- controller: function(log) { log('parentController'); }
- };
- });
- directive('childDirective', function() {
- return {
- require: '^parentDirective',
- transclude: true,
- replace: true,
- templateUrl: 'childDirective.html',
- controller: function(log) { log('childController'); }
- };
+ expect(nonIsolateDirControllerInIsolateDirective).toBeDefined();
+ expect(nonIsolateDirControllerInIsolateDirective instanceof NonIsolateController).toBe(true);
+ });
});
- directive('babyDirective', function() {
- return {
- require: '^childDirective',
- templateUrl: 'babyDirective.html',
- controller: function(log) { log('babyController'); }
- };
+
+
+ it('should support controllerAs', function() {
+ module(function() {
+ directive('main', function() {
+ return {
+ templateUrl: 'main.html',
+ transclude: true,
+ scope: {},
+ controller: function() {
+ this.name = 'lucas';
+ },
+ controllerAs: 'mainCtrl'
+ };
+ });
+ });
+ inject(function($templateCache, $compile, $rootScope) {
+ $templateCache.put('main.html', 'template:{{mainCtrl.name}}
');
+ element = $compile('transclude:{{mainCtrl.name}}
')($rootScope);
+ $rootScope.$apply();
+ expect(element.text()).toBe('template:lucas transclude:');
+ });
});
- });
- inject(function($templateCache, log, $compile, $rootScope) {
- $templateCache.put('parentDirective.html', 'parentTemplateText;
');
- $templateCache.put('childDirective.html', 'childTemplateText; ');
- $templateCache.put('babyDirective.html', 'babyTemplateText; ');
- element = $compile('' +
- '
' +
- 'childContentText;' +
- '
babyContent;
' +
- '
' +
- '
')($rootScope);
- $rootScope.$apply();
- expect(log).toEqual('parentController; childController; babyController');
- expect(element.text()).toBe('childContentText;babyTemplateText;');
- });
- });
+ it('should support controller alias', function() {
+ module(function($controllerProvider) {
+ $controllerProvider.register('MainCtrl', function() {
+ this.name = 'lucas';
+ });
+ directive('main', function() {
+ return {
+ templateUrl: 'main.html',
+ scope: {},
+ controller: 'MainCtrl as mainCtrl'
+ };
+ });
+ });
+ inject(function($templateCache, $compile, $rootScope) {
+ $templateCache.put('main.html', '{{mainCtrl.name}} ');
+ element = $compile('
')($rootScope);
+ $rootScope.$apply();
+ expect(element.text()).toBe('lucas');
+ });
+ });
- it('should allow controller usage in pre-link directive functions with templateUrl', function() {
- module(function() {
- var Ctrl = function(log) {
- log('instance');
- };
- directive('myDirective', function() {
- return {
- scope: true,
- templateUrl: 'hello.html',
- controller: Ctrl,
- compile: function() {
+ it('should require controller on parent element',function() {
+ module(function() {
+ directive('main', function(log) {
return {
- pre: function(scope, template, attr, ctrl) {},
- post: function() {}
+ controller: function() {
+ this.name = 'main';
+ }
};
- }
- };
+ });
+ directive('dep', function(log) {
+ return {
+ require: '^main',
+ link: function(scope, element, attrs, controller) {
+ log('dep:' + controller.name);
+ }
+ };
+ });
+ });
+ inject(function(log, $compile, $rootScope) {
+ element = $compile('')($rootScope);
+ expect(log).toEqual('dep:main');
+ });
});
- });
- inject(function($templateCache, $compile, $rootScope, log) {
- $templateCache.put('hello.html', 'Hello
');
- element = $compile('
')($rootScope);
- $rootScope.$apply();
+ it('should throw an error if required controller can\'t be found',function() {
+ module(function() {
+ directive('dep', function(log) {
+ return {
+ require: '^main',
+ link: function(scope, element, attrs, controller) {
+ log('dep:' + controller.name);
+ }
+ };
+ });
+ });
+ inject(function(log, $compile, $rootScope) {
+ expect(function() {
+ $compile('')($rootScope);
+ }).toThrowMinErr('$compile', 'ctreq', 'Controller \'main\', required by directive \'dep\', can\'t be found!');
+ });
+ });
- expect(log).toEqual('instance');
- expect(element.text()).toBe('Hello');
- });
- });
+ it('should pass null if required controller can\'t be found and is optional',function() {
+ module(function() {
+ directive('dep', function(log) {
+ return {
+ require: '?^main',
+ link: function(scope, element, attrs, controller) {
+ log('dep:' + controller);
+ }
+ };
+ });
+ });
+ inject(function(log, $compile, $rootScope) {
+ $compile('')($rootScope);
+ expect(log).toEqual('dep:null');
+ });
+ });
- it('should allow controller usage in pre-link directive functions with a template', function() {
- module(function() {
- var Ctrl = function(log) {
- log('instance');
- };
- directive('myDirective', function() {
- return {
- scope: true,
- template: 'Hello
',
- controller: Ctrl,
- compile: function() {
+ it('should pass null if required controller can\'t be found and is optional with the question mark on the right',function() {
+ module(function() {
+ directive('dep', function(log) {
return {
- pre: function(scope, template, attr, ctrl) {},
- post: function() {}
+ require: '^?main',
+ link: function(scope, element, attrs, controller) {
+ log('dep:' + controller);
+ }
};
- }
- };
+ });
+ });
+ inject(function(log, $compile, $rootScope) {
+ $compile('')($rootScope);
+ expect(log).toEqual('dep:null');
+ });
});
- });
- inject(function($templateCache, $compile, $rootScope, log) {
- element = $compile('
')($rootScope);
- $rootScope.$apply();
- expect(log).toEqual('instance');
- expect(element.text()).toBe('Hello');
- });
- });
+ it('should have optional controller on current element', function() {
+ module(function() {
+ directive('dep', function(log) {
+ return {
+ require: '?main',
+ link: function(scope, element, attrs, controller) {
+ log('dep:' + !!controller);
+ }
+ };
+ });
+ });
+ inject(function(log, $compile, $rootScope) {
+ element = $compile('')($rootScope);
+ expect(log).toEqual('dep:false');
+ });
+ });
- it('should throw ctreq with correct directive name, regardless of order', function() {
- module(function($compileProvider) {
- $compileProvider.directive('aDir', valueFn({
- restrict: 'E',
- require: 'ngModel',
- link: noop
- }));
- });
- inject(function($compile, $rootScope) {
- expect(function() {
- // a-dir will cause a ctreq error to be thrown. Previously, the error would reference
- // the last directive in the chain (which in this case would be ngClick), based on
- // priority and alphabetical ordering. This test verifies that the ordering does not
- // affect which directive is referenced in the minErr message.
- element = $compile(' ')($rootScope);
- }).toThrowMinErr('$compile', 'ctreq',
- 'Controller \'ngModel\', required by directive \'aDir\', can\'t be found!');
- });
- });
- });
+ it('should support multiple controllers', function() {
+ module(function() {
+ directive('c1', valueFn({
+ controller: function() { this.name = 'c1'; }
+ }));
+ directive('c2', valueFn({
+ controller: function() { this.name = 'c2'; }
+ }));
+ directive('dep', function(log) {
+ return {
+ require: ['^c1', '^c2'],
+ link: function(scope, element, attrs, controller) {
+ log('dep:' + controller[0].name + '-' + controller[1].name);
+ }
+ };
+ });
+ });
+ inject(function(log, $compile, $rootScope) {
+ element = $compile('')($rootScope);
+ expect(log).toEqual('dep:c1-c2');
+ });
+ });
+ it('should support multiple controllers as an object hash', function() {
+ module(function() {
+ directive('c1', valueFn({
+ controller: function() { this.name = 'c1'; }
+ }));
+ directive('c2', valueFn({
+ controller: function() { this.name = 'c2'; }
+ }));
+ directive('dep', function(log) {
+ return {
+ require: { myC1: '^c1', myC2: '^c2' },
+ link: function(scope, element, attrs, controllers) {
+ log('dep:' + controllers.myC1.name + '-' + controllers.myC2.name);
+ }
+ };
+ });
+ });
+ inject(function(log, $compile, $rootScope) {
+ element = $compile('')($rootScope);
+ expect(log).toEqual('dep:c1-c2');
+ });
+ });
- describe('transclude', function() {
+ it('should support omitting the name of the required controller if it is the same as the key',
+ function() {
+ module(function() {
+ directive('myC1', valueFn({
+ controller: function() { this.name = 'c1'; }
+ }));
+ directive('myC2', valueFn({
+ controller: function() { this.name = 'c2'; }
+ }));
+ directive('dep', function(log) {
+ return {
+ require: { myC1: '^', myC2: '^' },
+ link: function(scope, element, attrs, controllers) {
+ log('dep:' + controllers.myC1.name + '-' + controllers.myC2.name);
+ }
+ };
+ });
+ });
+ inject(function(log, $compile, $rootScope) {
+ element = $compile('')($rootScope);
+ expect(log).toEqual('dep:c1-c2');
+ });
+ }
+ );
- describe('content transclusion', function() {
+ it('should instantiate the controller just once when template/templateUrl', function() {
+ var syncCtrlSpy = jasmine.createSpy('sync controller'),
+ asyncCtrlSpy = jasmine.createSpy('async controller');
- it('should support transclude directive', function() {
- module(function() {
- directive('trans', function() {
- return {
- transclude: 'content',
- replace: true,
- scope: {},
- link: function(scope) {
- scope.x = 'iso';
- },
- template: 'W:{{x}}-{{$parent.$id}}-{{$id}}; '
- };
+ module(function() {
+ directive('myDirectiveSync', valueFn({
+ template: 'Hello!
',
+ controller: syncCtrlSpy
+ }));
+ directive('myDirectiveAsync', valueFn({
+ templateUrl: 'myDirectiveAsync.html',
+ controller: asyncCtrlSpy,
+ compile: function() {
+ return function() {
+ };
+ }
+ }));
});
- });
- inject(function(log, $rootScope, $compile) {
- element = $compile('T:{{x}}-{{$parent.$id}}-{{$id}};
')($rootScope);
- $rootScope.x = 'root';
- $rootScope.$apply();
- expect(element.text()).toEqual('W:iso-1-2;T:root-2-3;');
- expect(jqLite(jqLite(element.find('li')[1]).contents()[0]).text()).toEqual('T:root-2-3');
- expect(jqLite(element.find('span')[0]).text()).toEqual(';');
- });
- });
+ inject(function($templateCache, $compile, $rootScope) {
+ expect(syncCtrlSpy).not.toHaveBeenCalled();
+ expect(asyncCtrlSpy).not.toHaveBeenCalled();
- it('should transclude transcluded content', function() {
- module(function() {
- directive('book', valueFn({
- transclude: 'content',
- template: ''
- }));
- directive('chapter', valueFn({
- transclude: 'content',
- templateUrl: 'chapter.html'
- }));
- directive('section', valueFn({
- transclude: 'content',
- template: ' '
- }));
- return function($httpBackend) {
- $httpBackend.
- expect('GET', 'chapter.html').
- respond('
');
- };
- });
- inject(function(log, $rootScope, $compile, $httpBackend) {
- element = $compile('
')($rootScope);
- $rootScope.$apply();
+ $templateCache.put('myDirectiveAsync.html', '
Hello!
');
+ element = $compile('
' +
+ ' ' +
+ ' ' +
+ '
')($rootScope);
+ expect(syncCtrlSpy).not.toHaveBeenCalled();
+ expect(asyncCtrlSpy).not.toHaveBeenCalled();
- expect(element.text()).toEqual('book-');
+ $rootScope.$apply();
- $httpBackend.flush();
- $rootScope.$apply();
- expect(element.text()).toEqual('book-chapter-section-![(paragraph)]!');
+ //expect(syncCtrlSpy).toHaveBeenCalledOnce();
+ expect(asyncCtrlSpy).toHaveBeenCalledOnce();
+ });
});
- });
- it('should not merge text elements from transcluded content', function() {
- module(function() {
- directive('foo', valueFn({
- transclude: 'content',
- template: '
This is before {{before}}.
',
- link: function(scope, element, attr, ctrls, $transclude) {
- var futureParent = element.children().eq(0);
- $transclude(function(clone) {
- futureParent.append(clone);
- }, futureParent);
- },
- scope: true
- }));
- });
- inject(function($rootScope, $compile) {
- element = $compile('
')($rootScope);
- $rootScope.before = 'BEFORE';
- $rootScope.after = 'AFTER';
- $rootScope.$apply();
- expect(element.text()).toEqual('This is before BEFORE. This is after AFTER');
- $rootScope.before = 'Not-Before';
- $rootScope.after = 'AfTeR';
- $rootScope.$$childHead.before = 'BeFoRe';
- $rootScope.$$childHead.after = 'Not-After';
- $rootScope.$apply();
- expect(element.text()).toEqual('This is before BeFoRe. This is after AfTeR');
- });
- });
+ it('should instantiate controllers in the parent->child order when transluction, templateUrl and replacement ' +
+ 'are in the mix', function() {
+ // When a child controller is in the transclusion that replaces the parent element that has a directive with
+ // a controller, we should ensure that we first instantiate the parent and only then stuff that comes from the
+ // transclusion.
+ //
+ // The transclusion moves the child controller onto the same element as parent controller so both controllers are
+ // on the same level.
+
+ module(function() {
+ directive('parentDirective', function() {
+ return {
+ transclude: true,
+ replace: true,
+ templateUrl: 'parentDirective.html',
+ controller: function(log) { log('parentController'); }
+ };
+ });
+ directive('childDirective', function() {
+ return {
+ require: '^parentDirective',
+ templateUrl: 'childDirective.html',
+ controller: function(log) { log('childController'); }
+ };
+ });
+ });
+ inject(function($templateCache, log, $compile, $rootScope) {
+ $templateCache.put('parentDirective.html', '
parentTemplateText;
');
+ $templateCache.put('childDirective.html', '
childTemplateText; ');
- it('should only allow one content transclusion per element', function() {
- module(function() {
- directive('first', valueFn({
- transclude: true
- }));
- directive('second', valueFn({
- transclude: true
- }));
- });
- inject(function($compile) {
- expect(function() {
- $compile('
');
- }).toThrowMinErr('$compile', 'multidir', /Multiple directives \[first, second\] asking for transclusion on:
')($rootScope);
+ $rootScope.$apply();
+ expect(log).toEqual('parentController; childController');
+ expect(element.text()).toBe('childTemplateText;childContentText;');
+ });
});
- });
- //see issue https://github.com/angular/angular.js/issues/12936
- it('should use the proper scope when it is on the root element of a replaced directive template', function() {
- module(function() {
- directive('isolate', valueFn({
- scope: {},
- replace: true,
- template: '
{{x}}
',
- link: function(scope, element, attr, ctrl) {
- scope.x = 'iso';
- }
- }));
- directive('trans', valueFn({
- transclude: 'content',
- link: function(scope, element, attr, ctrl, $transclude) {
- $transclude(function(clone) {
- element.append(clone);
- });
- }
- }));
- });
- inject(function($rootScope, $compile) {
- element = $compile('
')($rootScope);
- $rootScope.x = 'root';
- $rootScope.$apply();
- expect(element.text()).toEqual('iso');
- });
- });
+ it('should instantiate the controller after the isolate scope bindings are initialized (with template)', function() {
+ module(function() {
+ var Ctrl = function($scope, log) {
+ log('myFoo=' + $scope.myFoo);
+ };
+
+ directive('myDirective', function() {
+ return {
+ scope: {
+ myFoo: '='
+ },
+ template: '
Hello
',
+ controller: Ctrl
+ };
+ });
+ });
- //see issue https://github.com/angular/angular.js/issues/12936
- it('should use the proper scope when it is on the root element of a replaced directive template with child scope', function() {
- module(function() {
- directive('child', valueFn({
- scope: true,
- replace: true,
- template: '
{{x}}
',
- link: function(scope, element, attr, ctrl) {
- scope.x = 'child';
- }
- }));
- directive('trans', valueFn({
- transclude: 'content',
- link: function(scope, element, attr, ctrl, $transclude) {
- $transclude(function(clone) {
- element.append(clone);
- });
- }
- }));
- });
- inject(function($rootScope, $compile) {
- element = $compile('
')($rootScope);
- $rootScope.x = 'root';
- $rootScope.$apply();
- expect(element.text()).toEqual('child');
+ inject(function($templateCache, $compile, $rootScope, log) {
+ $rootScope.foo = 'bar';
+
+ element = $compile('
')($rootScope);
+ $rootScope.$apply();
+ expect(log).toEqual('myFoo=bar');
+ });
});
- });
- it('should not leak if two "element" transclusions are on the same element (with debug info)', function() {
- if (jQuery) {
- // jQuery 2.x doesn't expose the cache storage.
- return;
- }
+ it('should instantiate the controller after the isolate scope bindings are initialized (with templateUrl)', function() {
+ module(function() {
+ var Ctrl = function($scope, log) {
+ log('myFoo=' + $scope.myFoo);
+ };
+ directive('myDirective', function() {
+ return {
+ scope: {
+ myFoo: '='
+ },
+ templateUrl: 'hello.html',
+ controller: Ctrl
+ };
+ });
+ });
- module(function($compileProvider) {
- $compileProvider.debugInfoEnabled(true);
- });
+ inject(function($templateCache, $compile, $rootScope, log) {
+ $templateCache.put('hello.html', '
Hello
');
+ $rootScope.foo = 'bar';
- inject(function($compile, $rootScope) {
- var cacheSize = jqLiteCacheSize();
+ element = $compile('
')($rootScope);
+ $rootScope.$apply();
+ expect(log).toEqual('myFoo=bar');
+ });
+ });
- element = $compile('
')($rootScope);
- expect(jqLiteCacheSize()).toEqual(cacheSize + 1);
- $rootScope.$apply('xs = [0,1]');
- expect(jqLiteCacheSize()).toEqual(cacheSize + 2);
+ it('should instantiate controllers in the parent->child->baby order when nested transluction, templateUrl and ' +
+ 'replacement are in the mix', function() {
+ // similar to the test above, except that we have one more layer of nesting and nested transclusion
- $rootScope.$apply('xs = [0]');
- expect(jqLiteCacheSize()).toEqual(cacheSize + 1);
+ module(function() {
+ directive('parentDirective', function() {
+ return {
+ transclude: true,
+ replace: true,
+ templateUrl: 'parentDirective.html',
+ controller: function(log) { log('parentController'); }
+ };
+ });
+ directive('childDirective', function() {
+ return {
+ require: '^parentDirective',
+ transclude: true,
+ replace: true,
+ templateUrl: 'childDirective.html',
+ controller: function(log) { log('childController'); }
+ };
+ });
+ directive('babyDirective', function() {
+ return {
+ require: '^childDirective',
+ templateUrl: 'babyDirective.html',
+ controller: function(log) { log('babyController'); }
+ };
+ });
+ });
- $rootScope.$apply('xs = []');
- expect(jqLiteCacheSize()).toEqual(cacheSize + 1);
+ inject(function($templateCache, log, $compile, $rootScope) {
+ $templateCache.put('parentDirective.html', '
parentTemplateText;
');
+ $templateCache.put('childDirective.html', '
childTemplateText; ');
+ $templateCache.put('babyDirective.html', '
babyTemplateText; ');
- element.remove();
- expect(jqLiteCacheSize()).toEqual(cacheSize + 0);
+ element = $compile('
' +
+ '
' +
+ 'childContentText;' +
+ '
babyContent;
' +
+ '
' +
+ '
')($rootScope);
+ $rootScope.$apply();
+ expect(log).toEqual('parentController; childController; babyController');
+ expect(element.text()).toBe('childContentText;babyTemplateText;');
+ });
});
- });
- it('should not leak if two "element" transclusions are on the same element (without debug info)', function() {
- if (jQuery) {
- // jQuery 2.x doesn't expose the cache storage.
- return;
- }
+ it('should allow controller usage in pre-link directive functions with templateUrl', function() {
+ module(function() {
+ var Ctrl = function(log) {
+ log('instance');
+ };
+
+ directive('myDirective', function() {
+ return {
+ scope: true,
+ templateUrl: 'hello.html',
+ controller: Ctrl,
+ compile: function() {
+ return {
+ pre: function(scope, template, attr, ctrl) {},
+ post: function() {}
+ };
+ }
+ };
+ });
+ });
+ inject(function($templateCache, $compile, $rootScope, log) {
+ $templateCache.put('hello.html', '
Hello
');
- module(function($compileProvider) {
- $compileProvider.debugInfoEnabled(false);
+ element = $compile('
')($rootScope);
+ $rootScope.$apply();
+
+ expect(log).toEqual('instance');
+ expect(element.text()).toBe('Hello');
+ });
});
- inject(function($compile, $rootScope) {
- var cacheSize = jqLiteCacheSize();
- element = $compile('
')($rootScope);
- expect(jqLiteCacheSize()).toEqual(cacheSize);
+ it('should allow controller usage in pre-link directive functions with a template', function() {
+ module(function() {
+ var Ctrl = function(log) {
+ log('instance');
+ };
+
+ directive('myDirective', function() {
+ return {
+ scope: true,
+ template: '
Hello
',
+ controller: Ctrl,
+ compile: function() {
+ return {
+ pre: function(scope, template, attr, ctrl) {},
+ post: function() {}
+ };
+ }
+ };
+ });
+ });
- $rootScope.$apply('xs = [0,1]');
- expect(jqLiteCacheSize()).toEqual(cacheSize);
+ inject(function($templateCache, $compile, $rootScope, log) {
+ element = $compile('
')($rootScope);
+ $rootScope.$apply();
- $rootScope.$apply('xs = [0]');
- expect(jqLiteCacheSize()).toEqual(cacheSize);
+ expect(log).toEqual('instance');
+ expect(element.text()).toBe('Hello');
+ });
+ });
- $rootScope.$apply('xs = []');
- expect(jqLiteCacheSize()).toEqual(cacheSize);
- element.remove();
- expect(jqLiteCacheSize()).toEqual(cacheSize);
+ it('should throw ctreq with correct directive name, regardless of order', function() {
+ module(function($compileProvider) {
+ $compileProvider.directive('aDir', valueFn({
+ restrict: 'E',
+ require: 'ngModel',
+ link: noop
+ }));
+ });
+ inject(function($compile, $rootScope) {
+ expect(function() {
+ // a-dir will cause a ctreq error to be thrown. Previously, the error would reference
+ // the last directive in the chain (which in this case would be ngClick), based on
+ // priority and alphabetical ordering. This test verifies that the ordering does not
+ // affect which directive is referenced in the minErr message.
+ element = $compile('
')($rootScope);
+ }).toThrowMinErr('$compile', 'ctreq',
+ 'Controller \'ngModel\', required by directive \'aDir\', can\'t be found!');
+ });
});
});
- it('should not leak if two "element" transclusions are on the same element (with debug info)', function() {
- if (jQuery) {
- // jQuery 2.x doesn't expose the cache storage.
- return;
- }
+ describe('transclude', function() {
- module(function($compileProvider) {
- $compileProvider.debugInfoEnabled(true);
- });
+ describe('content transclusion', function() {
- inject(function($compile, $rootScope) {
- var cacheSize = jqLiteCacheSize();
- element = $compile('
')($rootScope);
+ it('should support transclude directive', function() {
+ module(function() {
+ directive('trans', function() {
+ return {
+ transclude: 'content',
+ replace: true,
+ scope: {},
+ link: function(scope) {
+ scope.x = 'iso';
+ },
+ template: '
W:{{x}}-{{$parent.$id}}-{{$id}}; '
+ };
+ });
+ });
+ inject(function(log, $rootScope, $compile) {
+ element = $compile('
T:{{x}}-{{$parent.$id}}-{{$id}};
')($rootScope);
+ $rootScope.x = 'root';
+ $rootScope.$apply();
+ expect(element.text()).toEqual('W:iso-1-2;T:root-2-3;');
+ expect(jqLite(jqLite(element.find('li')[1]).contents()[0]).text()).toEqual('T:root-2-3');
+ expect(jqLite(element.find('span')[0]).text()).toEqual(';');
+ });
+ });
+
+
+ it('should transclude transcluded content', function() {
+ module(function() {
+ directive('book', valueFn({
+ transclude: 'content',
+ template: '
'
+ }));
+ directive('chapter', valueFn({
+ transclude: 'content',
+ templateUrl: 'chapter.html'
+ }));
+ directive('section', valueFn({
+ transclude: 'content',
+ template: '
'
+ }));
+ return function($httpBackend) {
+ $httpBackend.
+ expect('GET', 'chapter.html').
+ respond('
');
+ };
+ });
+ inject(function(log, $rootScope, $compile, $httpBackend) {
+ element = $compile('
')($rootScope);
+ $rootScope.$apply();
- $rootScope.$apply('xs = [0,1]');
- // At this point we have a bunch of comment placeholders but no real transcluded elements
- // So the cache only contains the root element's data
- expect(jqLiteCacheSize()).toEqual(cacheSize + 1);
+ expect(element.text()).toEqual('book-');
- $rootScope.$apply('val = true');
- // Now we have two concrete transcluded elements plus some comments so two more cache items
- expect(jqLiteCacheSize()).toEqual(cacheSize + 3);
+ $httpBackend.flush();
+ $rootScope.$apply();
+ expect(element.text()).toEqual('book-chapter-section-![(paragraph)]!');
+ });
+ });
- $rootScope.$apply('val = false');
- // Once again we only have comments so no transcluded elements and the cache is back to just
- // the root element
- expect(jqLiteCacheSize()).toEqual(cacheSize + 1);
- element.remove();
- // Now we've even removed the root element along with its cache
- expect(jqLiteCacheSize()).toEqual(cacheSize + 0);
- });
- });
+ it('should not merge text elements from transcluded content', function() {
+ module(function() {
+ directive('foo', valueFn({
+ transclude: 'content',
+ template: '
This is before {{before}}.
',
+ link: function(scope, element, attr, ctrls, $transclude) {
+ var futureParent = element.children().eq(0);
+ $transclude(function(clone) {
+ futureParent.append(clone);
+ }, futureParent);
+ },
+ scope: true
+ }));
+ });
+ inject(function($rootScope, $compile) {
+ element = $compile('
')($rootScope);
+ $rootScope.before = 'BEFORE';
+ $rootScope.after = 'AFTER';
+ $rootScope.$apply();
+ expect(element.text()).toEqual('This is before BEFORE. This is after AFTER');
+
+ $rootScope.before = 'Not-Before';
+ $rootScope.after = 'AfTeR';
+ $rootScope.$$childHead.before = 'BeFoRe';
+ $rootScope.$$childHead.after = 'Not-After';
+ $rootScope.$apply();
+ expect(element.text()).toEqual('This is before BeFoRe. This is after AfTeR');
+ });
+ });
- it('should not leak when continuing the compilation of elements on a scope that was destroyed', function() {
- if (jQuery) {
- // jQuery 2.x doesn't expose the cache storage.
- return;
- }
- var linkFn = jasmine.createSpy('linkFn');
+ it('should only allow one content transclusion per element', function() {
+ module(function() {
+ directive('first', valueFn({
+ transclude: true
+ }));
+ directive('second', valueFn({
+ transclude: true
+ }));
+ });
+ inject(function($compile) {
+ expect(function() {
+ $compile('
');
+ }).toThrowMinErr('$compile', 'multidir', /Multiple directives \[first, second\] asking for transclusion on:
{{x}}
',
+ link: function(scope, element, attr, ctrl) {
+ scope.x = 'iso';
+ }
+ }));
+ directive('trans', valueFn({
+ transclude: 'content',
+ link: function(scope, element, attr, ctrl, $transclude) {
+ $transclude(function(clone) {
+ element.append(clone);
+ });
+ }
+ }));
+ });
+ inject(function($rootScope, $compile) {
+ element = $compile('
')($rootScope);
+ $rootScope.x = 'root';
+ $rootScope.$apply();
+ expect(element.text()).toEqual('iso');
});
});
- $compileProvider.directive('isolateRed', function() {
- return {
- restrict: 'A',
- scope: {},
- template: '
'
- };
+
+
+ //see issue https://github.com/angular/angular.js/issues/12936
+ it('should use the proper scope when it is on the root element of a replaced directive template with child scope', function() {
+ module(function() {
+ directive('child', valueFn({
+ scope: true,
+ replace: true,
+ template: '
{{x}}
',
+ link: function(scope, element, attr, ctrl) {
+ scope.x = 'child';
+ }
+ }));
+ directive('trans', valueFn({
+ transclude: 'content',
+ link: function(scope, element, attr, ctrl, $transclude) {
+ $transclude(function(clone) {
+ element.append(clone);
+ });
+ }
+ }));
+ });
+ inject(function($rootScope, $compile) {
+ element = $compile('
')($rootScope);
+ $rootScope.x = 'root';
+ $rootScope.$apply();
+ expect(element.text()).toEqual('child');
+ });
});
- $compileProvider.directive('red', function() {
- return {
- restrict: 'A',
- templateUrl: 'red.html',
- scope: {},
- link: linkFn
- };
+
+ it('should throw if a transcluded node is transcluded again', function() {
+ module(function() {
+ directive('trans', valueFn({
+ transclude: true,
+ link: function(scope, element, attr, ctrl, $transclude) {
+ $transclude();
+ $transclude();
+ }
+ }));
+ });
+ inject(function($rootScope, $compile) {
+ expect(function() {
+ $compile('
')($rootScope);
+ }).toThrowMinErr('$compile', 'multilink', 'This element has already been linked.');
+ });
});
- });
- inject(function($compile, $rootScope, $httpBackend, $timeout, $templateCache) {
- var cacheSize = jqLiteCacheSize();
- $httpBackend.whenGET('red.html').respond('
red.html
');
- var template = $compile(
- '
');
- element = template($rootScope);
- $rootScope.$digest();
- $timeout.flush();
- $httpBackend.flush();
- expect(linkFn).not.toHaveBeenCalled();
- expect(jqLiteCacheSize()).toEqual(cacheSize + 2);
+ it('should not leak if two "element" transclusions are on the same element (with debug info)', function() {
+ if (jQuery) {
+ // jQuery 2.x doesn't expose the cache storage.
+ return;
+ }
- $templateCache.removeAll();
- var destroyedScope = $rootScope.$new();
- destroyedScope.$destroy();
- var clone = template(destroyedScope);
- $rootScope.$digest();
- $timeout.flush();
- expect(linkFn).not.toHaveBeenCalled();
- });
- });
- if (jQuery) {
- describe('cleaning up after a replaced element', function() {
- var $compile, xs;
- beforeEach(inject(function(_$compile_) {
- $compile = _$compile_;
- xs = [0, 1];
- }));
+ module(function($compileProvider) {
+ $compileProvider.debugInfoEnabled(true);
+ });
- function testCleanup() {
- var privateData, firstRepeatedElem;
+ inject(function($compile, $rootScope) {
+ var cacheSize = jqLiteCacheSize();
- element = $compile('
')($rootScope);
+ element = $compile('
')($rootScope);
+ expect(jqLiteCacheSize()).toEqual(cacheSize + 1);
- $rootScope.$apply('xs = [' + xs + ']');
- firstRepeatedElem = element.children('.ng-scope').eq(0);
+ $rootScope.$apply('xs = [0,1]');
+ expect(jqLiteCacheSize()).toEqual(cacheSize + 2);
- expect(firstRepeatedElem.data('$scope')).toBeDefined();
- privateData = jQuery._data(firstRepeatedElem[0]);
- expect(privateData.events).toBeDefined();
- expect(privateData.events.click).toBeDefined();
- expect(privateData.events.click[0]).toBeDefined();
+ $rootScope.$apply('xs = [0]');
+ expect(jqLiteCacheSize()).toEqual(cacheSize + 1);
- //Ensure the angular $destroy event is still sent
- var destroyCount = 0;
- element.find('div').on('$destroy', function() { destroyCount++; });
+ $rootScope.$apply('xs = []');
+ expect(jqLiteCacheSize()).toEqual(cacheSize + 1);
- $rootScope.$apply('xs = null');
+ element.remove();
+ expect(jqLiteCacheSize()).toEqual(cacheSize + 0);
+ });
+ });
- expect(destroyCount).toBe(2);
- expect(firstRepeatedElem.data('$scope')).not.toBeDefined();
- privateData = jQuery._data(firstRepeatedElem[0]);
- expect(privateData && privateData.events).not.toBeDefined();
- }
- it('should work without external libraries (except jQuery)', testCleanup);
-
- it('should work with another library patching jQuery.cleanData after Angular', function() {
- var cleanedCount = 0;
- var currentCleanData = jQuery.cleanData;
- jQuery.cleanData = function(elems) {
- cleanedCount += elems.length;
- // Don't return the output and explicitly pass only the first parameter
- // so that we're sure we're not relying on either of them. jQuery UI patch
- // behaves in this way.
- currentCleanData(elems);
- };
+ it('should not leak if two "element" transclusions are on the same element (without debug info)', function() {
+ if (jQuery) {
+ // jQuery 2.x doesn't expose the cache storage.
+ return;
+ }
- testCleanup();
- // The ng-repeat template is removed/cleaned (the +1)
- // and each clone of the ng-repeat template is also removed (xs.length)
- expect(cleanedCount).toBe(xs.length + 1);
+ module(function($compileProvider) {
+ $compileProvider.debugInfoEnabled(false);
+ });
- // Restore the previous jQuery.cleanData.
- jQuery.cleanData = currentCleanData;
- });
- });
- }
+ inject(function($compile, $rootScope) {
+ var cacheSize = jqLiteCacheSize();
+ element = $compile('
')($rootScope);
+ expect(jqLiteCacheSize()).toEqual(cacheSize);
- it('should add a $$transcluded property onto the transcluded scope', function() {
- module(function() {
- directive('trans', function() {
- return {
- transclude: true,
- replace: true,
- scope: true,
- template: '
I:{{$$transcluded}}
'
- };
- });
- });
- inject(function($rootScope, $compile) {
- element = $compile('
')($rootScope);
- $rootScope.$apply();
- expect(jqLite(element.find('span')[0]).text()).toEqual('I:');
- expect(jqLite(element.find('span')[1]).text()).toEqual('T:true');
- });
- });
+ $rootScope.$apply('xs = [0,1]');
+ expect(jqLiteCacheSize()).toEqual(cacheSize);
+ $rootScope.$apply('xs = [0]');
+ expect(jqLiteCacheSize()).toEqual(cacheSize);
- it('should clear contents of the ng-translude element before appending transcluded content' +
- ' if transcluded content exists', function() {
- module(function() {
- directive('trans', function() {
- return {
- transclude: true,
- template: '
old stuff!
'
- };
- });
- });
- inject(function($rootScope, $compile) {
- element = $compile('
unicorn!
')($rootScope);
- $rootScope.$apply();
- expect(sortedHtml(element.html())).toEqual('
unicorn!
');
- });
- });
+ $rootScope.$apply('xs = []');
+ expect(jqLiteCacheSize()).toEqual(cacheSize);
- it('should NOT clear contents of the ng-translude element before appending transcluded content' +
- ' if transcluded content does NOT exist', function() {
- module(function() {
- directive('trans', function() {
- return {
- transclude: true,
- template: '
old stuff!
'
- };
+ element.remove();
+ expect(jqLiteCacheSize()).toEqual(cacheSize);
+ });
});
- });
- inject(function(log, $rootScope, $compile) {
- element = $compile('
')($rootScope);
- $rootScope.$apply();
- expect(sortedHtml(element.html())).toEqual('
old stuff!
');
- });
- });
- it('should clear the fallback content from the element during compile and before linking', function() {
- module(function() {
- directive('trans', function() {
- return {
- transclude: true,
- template: '
fallback content
'
- };
- });
- });
- inject(function(log, $rootScope, $compile) {
- element = jqLite('
');
- var linkfn = $compile(element);
- expect(element.html()).toEqual('
');
- linkfn($rootScope);
- $rootScope.$apply();
- expect(sortedHtml(element.html())).toEqual('
fallback content
');
- });
- });
+ it('should not leak if two "element" transclusions are on the same element (with debug info)', function() {
+ if (jQuery) {
+ // jQuery 2.x doesn't expose the cache storage.
+ return;
+ }
+ module(function($compileProvider) {
+ $compileProvider.debugInfoEnabled(true);
+ });
- it('should allow cloning of the fallback via ngRepeat', function() {
- module(function() {
- directive('trans', function() {
- return {
- transclude: true,
- template: '
'
- };
+ inject(function($compile, $rootScope) {
+ var cacheSize = jqLiteCacheSize();
+ element = $compile('
')($rootScope);
+
+ $rootScope.$apply('xs = [0,1]');
+ // At this point we have a bunch of comment placeholders but no real transcluded elements
+ // So the cache only contains the root element's data
+ expect(jqLiteCacheSize()).toEqual(cacheSize + 1);
+
+ $rootScope.$apply('val = true');
+ // Now we have two concrete transcluded elements plus some comments so two more cache items
+ expect(jqLiteCacheSize()).toEqual(cacheSize + 3);
+
+ $rootScope.$apply('val = false');
+ // Once again we only have comments so no transcluded elements and the cache is back to just
+ // the root element
+ expect(jqLiteCacheSize()).toEqual(cacheSize + 1);
+
+ element.remove();
+ // Now we've even removed the root element along with its cache
+ expect(jqLiteCacheSize()).toEqual(cacheSize + 0);
+ });
});
- });
- inject(function(log, $rootScope, $compile) {
- element = $compile('
')($rootScope);
- $rootScope.$apply();
- expect(element.text()).toEqual('012');
- });
- });
+ it('should not leak when continuing the compilation of elements on a scope that was destroyed', function() {
+ if (jQuery) {
+ // jQuery 2.x doesn't expose the cache storage.
+ return;
+ }
+
+ var linkFn = jasmine.createSpy('linkFn');
+
+ module(function($controllerProvider, $compileProvider) {
+ $controllerProvider.register('Leak', function($scope, $timeout) {
+ $scope.code = 'red';
+ $timeout(function() {
+ $scope.code = 'blue';
+ });
+ });
+ $compileProvider.directive('isolateRed', function() {
+ return {
+ restrict: 'A',
+ scope: {},
+ template: '
'
+ };
+ });
+ $compileProvider.directive('red', function() {
+ return {
+ restrict: 'A',
+ templateUrl: 'red.html',
+ scope: {},
+ link: linkFn
+ };
+ });
+ });
- it('should not link the fallback content if transcluded content is provided', function() {
- var linkSpy = jasmine.createSpy('postlink');
+ inject(function($compile, $rootScope, $httpBackend, $timeout, $templateCache) {
+ var cacheSize = jqLiteCacheSize();
+ $httpBackend.whenGET('red.html').respond('
red.html
');
+ var template = $compile(
+ '
');
+ element = template($rootScope, noop);
+ $rootScope.$digest();
+ $timeout.flush();
+ $httpBackend.flush();
+ expect(linkFn).not.toHaveBeenCalled();
+ expect(jqLiteCacheSize()).toEqual(cacheSize + 2);
- module(function() {
- directive('inner', function() {
- return {
- restrict: 'E',
- template: 'old stuff! ',
- link: linkSpy
- };
+ $templateCache.removeAll();
+ var destroyedScope = $rootScope.$new();
+ destroyedScope.$destroy();
+ var clone = template(destroyedScope, noop);
+ $rootScope.$digest();
+ $timeout.flush();
+ expect(linkFn).not.toHaveBeenCalled();
+ clone.remove();
+ });
});
- directive('trans', function() {
- return {
- transclude: true,
- template: '
'
- };
- });
- });
- inject(function($rootScope, $compile) {
- element = $compile('
unicorn!
')($rootScope);
- $rootScope.$apply();
- expect(sortedHtml(element.html())).toEqual('
unicorn!
');
- expect(linkSpy).not.toHaveBeenCalled();
- });
- });
+ if (jQuery) {
+ describe('cleaning up after a replaced element', function() {
+ var $compile, xs;
+ beforeEach(inject(function(_$compile_) {
+ $compile = _$compile_;
+ xs = [0, 1];
+ }));
- it('should compile and link the fallback content if no transcluded content is provided', function() {
- var linkSpy = jasmine.createSpy('postlink');
+ function testCleanup() {
+ var privateData, firstRepeatedElem;
- module(function() {
- directive('inner', function() {
- return {
- restrict: 'E',
- template: 'old stuff! ',
- link: linkSpy
- };
- });
+ element = $compile('
')($rootScope);
- directive('trans', function() {
- return {
- transclude: true,
- template: '
'
- };
- });
- });
- inject(function(log, $rootScope, $compile) {
- element = $compile('
')($rootScope);
- $rootScope.$apply();
- expect(sortedHtml(element.html())).toEqual('
old stuff!
');
- expect(linkSpy).toHaveBeenCalled();
- });
- });
+ $rootScope.$apply('xs = [' + xs + ']');
+ firstRepeatedElem = element.children('.ng-scope').eq(0);
- it('should compile and link the fallback content if an optional transclusion slot is not provided', function() {
- var linkSpy = jasmine.createSpy('postlink');
+ expect(firstRepeatedElem.data('$scope')).toBeDefined();
+ privateData = jQuery._data(firstRepeatedElem[0]);
+ expect(privateData.events).toBeDefined();
+ expect(privateData.events.click).toBeDefined();
+ expect(privateData.events.click[0]).toBeDefined();
- module(function() {
- directive('inner', function() {
- return {
- restrict: 'E',
- template: 'old stuff! ',
- link: linkSpy
- };
- });
+ //Ensure the angular $destroy event is still sent
+ var destroyCount = 0;
+ element.find('div').on('$destroy', function() { destroyCount++; });
- directive('trans', function() {
- return {
- transclude: { optionalSlot: '?optional'},
- template: '
'
- };
- });
- });
- inject(function(log, $rootScope, $compile) {
- element = $compile('
')($rootScope);
- $rootScope.$apply();
- expect(sortedHtml(element.html())).toEqual('
old stuff!
');
- expect(linkSpy).toHaveBeenCalled();
- });
- });
+ $rootScope.$apply('xs = null');
- it('should cope if there is neither transcluded content nor fallback content', function() {
- module(function() {
- directive('trans', function() {
- return {
- transclude: true,
- template: '
'
- };
- });
- });
- inject(function($rootScope, $compile) {
- element = $compile('
')($rootScope);
- $rootScope.$apply();
- expect(sortedHtml(element.html())).toEqual('
');
- });
- });
+ expect(destroyCount).toBe(2);
+ expect(firstRepeatedElem.data('$scope')).not.toBeDefined();
+ privateData = jQuery._data(firstRepeatedElem[0]);
+ expect(privateData && privateData.events).not.toBeDefined();
+ }
- it('should throw on an ng-transclude element inside no transclusion directive', function() {
- inject(function($rootScope, $compile) {
- // we need to do this because different browsers print empty attributes differently
- try {
- $compile('
')($rootScope);
- } catch (e) {
- expect(e.message).toMatch(new RegExp(
- '^\\[ngTransclude:orphan\\] ' +
- 'Illegal use of ngTransclude directive in the template! ' +
- 'No parent directive that requires a transclusion found\\. ' +
- 'Element:
' +
- '
' +
- '
this one should get replaced with content
' +
- '
' +
- '
',
- transclude: true
- }));
+ it('should add a $$transcluded property onto the transcluded scope', function() {
+ module(function() {
+ directive('trans', function() {
+ return {
+ transclude: true,
+ replace: true,
+ scope: true,
+ template: '
I:{{$$transcluded}}
'
+ };
+ });
+ });
+ inject(function($rootScope, $compile) {
+ element = $compile('
')($rootScope);
+ $rootScope.$apply();
+ expect(jqLite(element.find('span')[0]).text()).toEqual('I:');
+ expect(jqLite(element.find('span')[1]).text()).toEqual('T:true');
+ });
+ });
- $compileProvider.directive('noTransBar', valueFn({
- template: '
' +
- // This ng-transclude is invalid. It should throw an error.
- '
' +
- '
',
- transclude: false
- }));
- });
+ it('should clear contents of the ng-translude element before appending transcluded content' +
+ ' if transcluded content exists', function() {
+ module(function() {
+ directive('trans', function() {
+ return {
+ transclude: true,
+ template: '
old stuff!
'
+ };
+ });
+ });
+ inject(function($rootScope, $compile) {
+ element = $compile('
unicorn!
')($rootScope);
+ $rootScope.$apply();
+ expect(sortedHtml(element.html())).toEqual('
unicorn!
');
+ });
+ });
- inject(function($compile, $rootScope) {
- expect(function() {
- $compile('
content
')($rootScope);
- }).toThrowMinErr('ngTransclude', 'orphan',
- 'Illegal use of ngTransclude directive in the template! No parent directive that requires a transclusion found. Element:
');
- });
- });
+ it('should NOT clear contents of the ng-translude element before appending transcluded content' +
+ ' if transcluded content does NOT exist', function() {
+ module(function() {
+ directive('trans', function() {
+ return {
+ transclude: true,
+ template: '
old stuff!
'
+ };
+ });
+ });
+ inject(function(log, $rootScope, $compile) {
+ element = $compile('
')($rootScope);
+ $rootScope.$apply();
+ expect(sortedHtml(element.html())).toEqual('
old stuff!
');
+ });
+ });
- it('should not pass transclusion into a templateUrl directive', function() {
+ it('should clear the fallback content from the element during compile and before linking', function() {
+ module(function() {
+ directive('trans', function() {
+ return {
+ transclude: true,
+ template: '
fallback content
'
+ };
+ });
+ });
+ inject(function(log, $rootScope, $compile) {
+ element = jqLite('
');
+ var linkfn = $compile(element);
+ expect(element.html()).toEqual('
');
+ linkfn($rootScope);
+ $rootScope.$apply();
+ expect(sortedHtml(element.html())).toEqual('
fallback content
');
+ });
+ });
- module(function($compileProvider) {
- $compileProvider.directive('transFoo', valueFn({
- template: '
' +
- '
' +
- '
this one should get replaced with content
' +
- '
' +
- '
',
- transclude: true
+ it('should allow cloning of the fallback via ngRepeat', function() {
+ module(function() {
+ directive('trans', function() {
+ return {
+ transclude: true,
+ template: '
'
+ };
+ });
+ });
+ inject(function(log, $rootScope, $compile) {
+ element = $compile('
')($rootScope);
+ $rootScope.$apply();
+ expect(element.text()).toEqual('012');
+ });
+ });
- }));
- $compileProvider.directive('noTransBar', valueFn({
- templateUrl: 'noTransBar.html',
- transclude: false
+ it('should not link the fallback content if transcluded content is provided', function() {
+ var linkSpy = jasmine.createSpy('postlink');
- }));
- });
+ module(function() {
+ directive('inner', function() {
+ return {
+ restrict: 'E',
+ template: 'old stuff! ',
+ link: linkSpy
+ };
+ });
- inject(function($compile, $rootScope, $templateCache) {
- $templateCache.put('noTransBar.html',
- '
' +
- // This ng-transclude is invalid. It should throw an error.
- '
' +
- '
');
+ directive('trans', function() {
+ return {
+ transclude: true,
+ template: '
'
+ };
+ });
+ });
+ inject(function($rootScope, $compile) {
+ element = $compile('
unicorn!
')($rootScope);
+ $rootScope.$apply();
+ expect(sortedHtml(element.html())).toEqual('
unicorn!
');
+ expect(linkSpy).not.toHaveBeenCalled();
+ });
+ });
- expect(function() {
- element = $compile('
content
')($rootScope);
- $rootScope.$apply();
- }).toThrowMinErr('ngTransclude', 'orphan',
- 'Illegal use of ngTransclude directive in the template! No parent directive that requires a transclusion found. Element:
');
- });
- });
+ it('should compile and link the fallback content if no transcluded content is provided', function() {
+ var linkSpy = jasmine.createSpy('postlink');
+ module(function() {
+ directive('inner', function() {
+ return {
+ restrict: 'E',
+ template: 'old stuff! ',
+ link: linkSpy
+ };
+ });
- it('should expose transcludeFn in compile fn even for templateUrl', function() {
- module(function() {
- directive('transInCompile', valueFn({
- transclude: true,
- // template: '
whatever
',
- templateUrl: 'foo.html',
- compile: function(_, __, transclude) {
- return function(scope, element) {
- transclude(scope, function(clone, scope) {
- element.html('');
- element.append(clone);
- });
- };
- }
- }));
- });
+ directive('trans', function() {
+ return {
+ transclude: true,
+ template: '
'
+ };
+ });
+ });
+ inject(function(log, $rootScope, $compile) {
+ element = $compile('
')($rootScope);
+ $rootScope.$apply();
+ expect(sortedHtml(element.html())).toEqual('
old stuff!
');
+ expect(linkSpy).toHaveBeenCalled();
+ });
+ });
- inject(function($compile, $rootScope, $templateCache) {
- $templateCache.put('foo.html', '
whatever
');
+ it('should compile and link the fallback content if an optional transclusion slot is not provided', function() {
+ var linkSpy = jasmine.createSpy('postlink');
- compile('
transcluded content
');
- $rootScope.$apply();
+ module(function() {
+ directive('inner', function() {
+ return {
+ restrict: 'E',
+ template: 'old stuff! ',
+ link: linkSpy
+ };
+ });
- expect(trim(element.text())).toBe('transcluded content');
- });
- });
+ directive('trans', function() {
+ return {
+ transclude: { optionalSlot: '?optional'},
+ template: '
'
+ };
+ });
+ });
+ inject(function(log, $rootScope, $compile) {
+ element = $compile('
')($rootScope);
+ $rootScope.$apply();
+ expect(sortedHtml(element.html())).toEqual('
old stuff!
');
+ expect(linkSpy).toHaveBeenCalled();
+ });
+ });
+ it('should cope if there is neither transcluded content nor fallback content', function() {
+ module(function() {
+ directive('trans', function() {
+ return {
+ transclude: true,
+ template: '
'
+ };
+ });
+ });
+ inject(function($rootScope, $compile) {
+ element = $compile('
')($rootScope);
+ $rootScope.$apply();
+ expect(sortedHtml(element.html())).toEqual('
');
+ });
+ });
- it('should make the result of a transclusion available to the parent directive in post-linking phase' +
- '(template)', function() {
- module(function() {
- directive('trans', function(log) {
- return {
- transclude: true,
- template: '
',
- link: {
- pre: function($scope, $element) {
- log('pre(' + $element.text() + ')');
- },
- post: function($scope, $element) {
- log('post(' + $element.text() + ')');
- }
+ it('should throw on an ng-transclude element inside no transclusion directive', function() {
+ inject(function($rootScope, $compile) {
+ // we need to do this because different browsers print empty attributes differently
+ try {
+ $compile('
')($rootScope);
+ } catch (e) {
+ expect(e.message).toMatch(new RegExp(
+ '^\\[ngTransclude:orphan\\] ' +
+ 'Illegal use of ngTransclude directive in the template! ' +
+ 'No parent directive that requires a transclusion found\\. ' +
+ 'Element:
unicorn!
')($rootScope);
- $rootScope.$apply();
- expect(log).toEqual('pre(); post(unicorn!)');
- });
- });
- it('should make the result of a transclusion available to the parent directive in post-linking phase' +
- '(templateUrl)', function() {
- // when compiling an async directive the transclusion is always processed before the directive
- // this is different compared to sync directive. delaying the transclusion makes little sense.
+ it('should not pass transclusion into a template directive when the directive didn\'t request transclusion', function() {
- module(function() {
- directive('trans', function(log) {
- return {
- transclude: true,
- templateUrl: 'trans.html',
- link: {
- pre: function($scope, $element) {
- log('pre(' + $element.text() + ')');
- },
- post: function($scope, $element) {
- log('post(' + $element.text() + ')');
- }
- }
- };
- });
- });
- inject(function(log, $rootScope, $compile, $templateCache) {
- $templateCache.put('trans.html', '
');
+ module(function($compileProvider) {
- element = $compile('
unicorn!
')($rootScope);
- $rootScope.$apply();
- expect(log).toEqual('pre(); post(unicorn!)');
- });
- });
+ $compileProvider.directive('transFoo', valueFn({
+ template: '
' +
+ '
' +
+ '
this one should get replaced with content
' +
+ '
' +
+ '
',
+ transclude: true
+ }));
- it('should make the result of a transclusion available to the parent *replace* directive in post-linking phase' +
- '(template)', function() {
- module(function() {
- directive('replacedTrans', function(log) {
- return {
- transclude: true,
- replace: true,
- template: '
',
- link: {
- pre: function($scope, $element) {
- log('pre(' + $element.text() + ')');
- },
- post: function($scope, $element) {
- log('post(' + $element.text() + ')');
- }
- }
- };
- });
- });
- inject(function(log, $rootScope, $compile) {
- element = $compile('
unicorn!
')($rootScope);
- $rootScope.$apply();
- expect(log).toEqual('pre(); post(unicorn!)');
- });
- });
+ $compileProvider.directive('noTransBar', valueFn({
+ template: '
' +
+ // This ng-transclude is invalid. It should throw an error.
+ '
' +
+ '
',
+ transclude: false
+ }));
+ });
- it('should make the result of a transclusion available to the parent *replace* directive in post-linking phase' +
- ' (templateUrl)', function() {
- module(function() {
- directive('replacedTrans', function(log) {
- return {
- transclude: true,
- replace: true,
- templateUrl: 'trans.html',
- link: {
- pre: function($scope, $element) {
- log('pre(' + $element.text() + ')');
- },
- post: function($scope, $element) {
- log('post(' + $element.text() + ')');
- }
- }
- };
+ inject(function($compile, $rootScope) {
+ expect(function() {
+ $compile('
content
')($rootScope);
+ }).toThrowMinErr('ngTransclude', 'orphan',
+ 'Illegal use of ngTransclude directive in the template! No parent directive that requires a transclusion found. Element:
');
+ });
});
- });
- inject(function(log, $rootScope, $compile, $templateCache) {
- $templateCache.put('trans.html', '
');
- element = $compile('
unicorn!
')($rootScope);
- $rootScope.$apply();
- expect(log).toEqual('pre(); post(unicorn!)');
- });
- });
- it('should copy the directive controller to all clones', function() {
- var transcludeCtrl, cloneCount = 2;
- module(function() {
- directive('transclude', valueFn({
- transclude: 'content',
- controller: function($transclude) {
- transcludeCtrl = this;
- },
- link: function(scope, el, attr, ctrl, $transclude) {
- var i;
- for (i = 0; i < cloneCount; i++) {
- $transclude(cloneAttach);
- }
+ it('should not pass transclusion into a templateUrl directive', function() {
- function cloneAttach(clone) {
- el.append(clone);
- }
- }
- }));
- });
- inject(function($compile) {
- element = $compile('
')($rootScope);
- var children = element.children(), i;
- expect(transcludeCtrl).toBeDefined();
+ module(function($compileProvider) {
- expect(element.data('$transcludeController')).toBe(transcludeCtrl);
- for (i = 0; i < cloneCount; i++) {
- expect(children.eq(i).data('$transcludeController')).toBeUndefined();
- }
- });
- });
+ $compileProvider.directive('transFoo', valueFn({
+ template: '
' +
+ '
' +
+ '
this one should get replaced with content
' +
+ '
' +
+ '
',
+ transclude: true
- it('should provide the $transclude controller local as 5th argument to the pre and post-link function', function() {
- var ctrlTransclude, preLinkTransclude, postLinkTransclude;
- module(function() {
- directive('transclude', valueFn({
- transclude: 'content',
- controller: function($transclude) {
- ctrlTransclude = $transclude;
- },
- compile: function() {
- return {
- pre: function(scope, el, attr, ctrl, $transclude) {
- preLinkTransclude = $transclude;
- },
- post: function(scope, el, attr, ctrl, $transclude) {
- postLinkTransclude = $transclude;
- }
- };
- }
- }));
- });
- inject(function($compile) {
- element = $compile('
')($rootScope);
- expect(ctrlTransclude).toBeDefined();
- expect(ctrlTransclude).toBe(preLinkTransclude);
- expect(ctrlTransclude).toBe(postLinkTransclude);
- });
- });
+ }));
+
+ $compileProvider.directive('noTransBar', valueFn({
+ templateUrl: 'noTransBar.html',
+ transclude: false
+
+ }));
+ });
+
+ inject(function($compile, $rootScope, $templateCache) {
+ $templateCache.put('noTransBar.html',
+ '
' +
+ // This ng-transclude is invalid. It should throw an error.
+ '
' +
+ '
');
+
+ expect(function() {
+ element = $compile('
content
')($rootScope);
+ $rootScope.$apply();
+ }).toThrowMinErr('ngTransclude', 'orphan',
+ 'Illegal use of ngTransclude directive in the template! No parent directive that requires a transclusion found. Element:
');
+ });
+ });
+
+
+ it('should expose transcludeFn in compile fn even for templateUrl', function() {
+ module(function() {
+ directive('transInCompile', valueFn({
+ transclude: true,
+ // template: '
whatever
',
+ templateUrl: 'foo.html',
+ compile: function(_, __, transclude) {
+ return function(scope, element) {
+ transclude(scope, function(clone, scope) {
+ element.html('');
+ element.append(clone);
+ });
+ };
+ }
+ }));
+ });
- it('should allow an optional scope argument in $transclude', function() {
- var capturedChildCtrl;
- module(function() {
- directive('transclude', valueFn({
- transclude: 'content',
- link: function(scope, element, attr, ctrl, $transclude) {
- $transclude(scope, function(clone) {
- element.append(clone);
+ inject(function($compile, $rootScope, $templateCache) {
+ $templateCache.put('foo.html', '
whatever
');
+
+ compile('
transcluded content
');
+ $rootScope.$apply();
+
+ expect(trim(element.text())).toBe('transcluded content');
+ });
+ });
+
+
+ it('should make the result of a transclusion available to the parent directive in post-linking phase' +
+ '(template)', function() {
+ module(function() {
+ directive('trans', function(log) {
+ return {
+ transclude: true,
+ template: '
',
+ link: {
+ pre: function($scope, $element) {
+ log('pre(' + $element.text() + ')');
+ },
+ post: function($scope, $element) {
+ log('post(' + $element.text() + ')');
+ }
+ }
+ };
});
- }
- }));
- });
- inject(function($compile) {
- element = $compile('
{{$id}}
')($rootScope);
- $rootScope.$apply();
- expect(element.text()).toBe('' + $rootScope.$id);
- });
+ });
+ inject(function(log, $rootScope, $compile) {
+ element = $compile('
unicorn!
')($rootScope);
+ $rootScope.$apply();
+ expect(log).toEqual('pre(); post(unicorn!)');
+ });
+ });
- });
- it('should expose the directive controller to transcluded children', function() {
- var capturedChildCtrl;
- module(function() {
- directive('transclude', valueFn({
- transclude: 'content',
- controller: function() {
- },
- link: function(scope, element, attr, ctrl, $transclude) {
- $transclude(function(clone) {
- element.append(clone);
+ it('should make the result of a transclusion available to the parent directive in post-linking phase' +
+ '(templateUrl)', function() {
+ // when compiling an async directive the transclusion is always processed before the directive
+ // this is different compared to sync directive. delaying the transclusion makes little sense.
+
+ module(function() {
+ directive('trans', function(log) {
+ return {
+ transclude: true,
+ templateUrl: 'trans.html',
+ link: {
+ pre: function($scope, $element) {
+ log('pre(' + $element.text() + ')');
+ },
+ post: function($scope, $element) {
+ log('post(' + $element.text() + ')');
+ }
+ }
+ };
});
- }
- }));
- directive('child', valueFn({
- require: '^transclude',
- link: function(scope, element, attr, ctrl) {
- capturedChildCtrl = ctrl;
- }
- }));
- });
- inject(function($compile) {
- element = $compile('
')($rootScope);
- expect(capturedChildCtrl).toBeTruthy();
- });
- });
+ });
+ inject(function(log, $rootScope, $compile, $templateCache) {
+ $templateCache.put('trans.html', '
');
+ element = $compile('
unicorn!
')($rootScope);
+ $rootScope.$apply();
+ expect(log).toEqual('pre(); post(unicorn!)');
+ });
+ });
- // See issue https://github.com/angular/angular.js/issues/14924
- it('should not process top-level transcluded text nodes merged into their sibling',
- function() {
- module(function() {
- directive('transclude', valueFn({
- template: '
',
- transclude: true,
- scope: {}
- }));
+
+ it('should make the result of a transclusion available to the parent *replace* directive in post-linking phase' +
+ '(template)', function() {
+ module(function() {
+ directive('replacedTrans', function(log) {
+ return {
+ transclude: true,
+ replace: true,
+ template: '
',
+ link: {
+ pre: function($scope, $element) {
+ log('pre(' + $element.text() + ')');
+ },
+ post: function($scope, $element) {
+ log('post(' + $element.text() + ')');
+ }
+ }
+ };
+ });
+ });
+ inject(function(log, $rootScope, $compile) {
+ element = $compile('
unicorn!
')($rootScope);
+ $rootScope.$apply();
+ expect(log).toEqual('pre(); post(unicorn!)');
+ });
});
- inject(function($compile) {
- element = jqLite('
');
- element[0].appendChild(document.createTextNode('1{{ value }}'));
- element[0].appendChild(document.createTextNode('2{{ value }}'));
- element[0].appendChild(document.createTextNode('3{{ value }}'));
- var initialWatcherCount = $rootScope.$countWatchers();
- $compile(element)($rootScope);
- $rootScope.$apply('value = 0');
- var newWatcherCount = $rootScope.$countWatchers() - initialWatcherCount;
+ it('should make the result of a transclusion available to the parent *replace* directive in post-linking phase' +
+ ' (templateUrl)', function() {
+ module(function() {
+ directive('replacedTrans', function(log) {
+ return {
+ transclude: true,
+ replace: true,
+ templateUrl: 'trans.html',
+ link: {
+ pre: function($scope, $element) {
+ log('pre(' + $element.text() + ')');
+ },
+ post: function($scope, $element) {
+ log('post(' + $element.text() + ')');
+ }
+ }
+ };
+ });
+ });
+ inject(function(log, $rootScope, $compile, $templateCache) {
+ $templateCache.put('trans.html', '
');
- expect(element.text()).toBe('102030');
- expect(newWatcherCount).toBe(3);
+ element = $compile('
unicorn!
')($rootScope);
+ $rootScope.$apply();
+ expect(log).toEqual('pre(); post(unicorn!)');
+ });
});
- }
- );
+ it('should copy the directive controller to all clones', function() {
+ var transcludeCtrl, cloneCount = 2;
+ module(function() {
+ directive('transclude', valueFn({
+ transclude: 'content',
+ controller: function($transclude) {
+ transcludeCtrl = this;
+ },
+ link: function(scope, el, attr, ctrl, $transclude) {
+ var i;
+ for (i = 0; i < cloneCount; i++) {
+ $transclude(cloneAttach);
+ }
- // see issue https://github.com/angular/angular.js/issues/9413
- describe('passing a parent bound transclude function to the link ' +
- 'function returned from `$compile`', function() {
+ function cloneAttach(clone) {
+ el.append(clone);
+ }
+ }
+ }));
+ });
+ inject(function($compile) {
+ element = $compile('
')($rootScope);
+ var children = element.children(), i;
+ expect(transcludeCtrl).toBeDefined();
- beforeEach(module(function() {
- directive('lazyCompile', function($compile) {
- return {
- compile: function(tElement, tAttrs) {
- var content = tElement.contents();
- tElement.empty();
- return function(scope, element, attrs, ctrls, transcludeFn) {
- element.append(content);
- $compile(content)(scope, undefined, {
- parentBoundTranscludeFn: transcludeFn
- });
- };
+ expect(element.data('$transcludeController')).toBe(transcludeCtrl);
+ for (i = 0; i < cloneCount; i++) {
+ expect(children.eq(i).data('$transcludeController')).toBeUndefined();
}
- };
+ });
});
- directive('toggle', valueFn({
- scope: {t: '=toggle'},
- transclude: true,
- template: '
'
- }));
- }));
- it('should preserve the bound scope', function() {
+ it('should provide the $transclude controller local as 5th argument to the pre and post-link function', function() {
+ var ctrlTransclude, preLinkTransclude, postLinkTransclude;
+ module(function() {
+ directive('transclude', valueFn({
+ transclude: 'content',
+ controller: function($transclude) {
+ ctrlTransclude = $transclude;
+ },
+ compile: function() {
+ return {
+ pre: function(scope, el, attr, ctrl, $transclude) {
+ preLinkTransclude = $transclude;
+ },
+ post: function(scope, el, attr, ctrl, $transclude) {
+ postLinkTransclude = $transclude;
+ }
+ };
+ }
+ }));
+ });
+ inject(function($compile) {
+ element = $compile('
')($rootScope);
+ expect(ctrlTransclude).toBeDefined();
+ expect(ctrlTransclude).toBe(preLinkTransclude);
+ expect(ctrlTransclude).toBe(postLinkTransclude);
+ });
+ });
- inject(function($compile, $rootScope) {
- element = $compile(
- '
' +
- '
' +
- '
' +
- 'Success Error ' +
- '
' +
- '
')($rootScope);
+ it('should allow an optional scope argument in $transclude', function() {
+ var capturedChildCtrl;
+ module(function() {
+ directive('transclude', valueFn({
+ transclude: 'content',
+ link: function(scope, element, attr, ctrl, $transclude) {
+ $transclude(scope, function(clone) {
+ element.append(clone);
+ });
+ }
+ }));
+ });
+ inject(function($compile) {
+ element = $compile('
{{$id}}
')($rootScope);
+ $rootScope.$apply();
+ expect(element.text()).toBe('' + $rootScope.$id);
+ });
- $rootScope.$apply('t = false');
- expect($rootScope.$countChildScopes()).toBe(1);
- expect(element.text()).toBe('');
+ });
- $rootScope.$apply('t = true');
- expect($rootScope.$countChildScopes()).toBe(4);
- expect(element.text()).toBe('Success');
+ it('should expose the directive controller to transcluded children', function() {
+ var capturedChildCtrl;
+ module(function() {
+ directive('transclude', valueFn({
+ transclude: 'content',
+ controller: function() {
+ },
+ link: function(scope, element, attr, ctrl, $transclude) {
+ $transclude(function(clone) {
+ element.append(clone);
+ });
+ }
+ }));
+ directive('child', valueFn({
+ require: '^transclude',
+ link: function(scope, element, attr, ctrl) {
+ capturedChildCtrl = ctrl;
+ }
+ }));
+ });
+ inject(function($compile) {
+ element = $compile('
')($rootScope);
+ expect(capturedChildCtrl).toBeTruthy();
+ });
+ });
- $rootScope.$apply('t = false');
- expect($rootScope.$countChildScopes()).toBe(1);
- expect(element.text()).toBe('');
- $rootScope.$apply('t = true');
- expect($rootScope.$countChildScopes()).toBe(4);
- expect(element.text()).toBe('Success');
- });
- });
+ // See issue https://github.com/angular/angular.js/issues/14924
+ it('should not process top-level transcluded text nodes merged into their sibling',
+ function() {
+ module(function() {
+ directive('transclude', valueFn({
+ template: '
',
+ transclude: true,
+ scope: {}
+ }));
+ });
+ inject(function($compile) {
+ element = jqLite('
');
+ element[0].appendChild(document.createTextNode('1{{ value }}'));
+ element[0].appendChild(document.createTextNode('2{{ value }}'));
+ element[0].appendChild(document.createTextNode('3{{ value }}'));
- it('should preserve the bound scope when using recursive transclusion', function() {
+ var initialWatcherCount = $rootScope.$countWatchers();
+ $compile(element)($rootScope);
+ $rootScope.$apply('value = 0');
+ var newWatcherCount = $rootScope.$countWatchers() - initialWatcherCount;
- directive('recursiveTransclude', valueFn({
- transclude: true,
- template: '
'
- }));
+ expect(element.text()).toBe('102030');
+ expect(newWatcherCount).toBe(3);
+ });
+ }
+ );
- inject(function($compile, $rootScope) {
- element = $compile(
- '
' +
- '
' +
- '
' +
- '
' +
- 'Success Error ' +
- '
' +
- '
' +
- '
')($rootScope);
- $rootScope.$apply('t = false');
- expect($rootScope.$countChildScopes()).toBe(1);
- expect(element.text()).toBe('');
+ // see issue https://github.com/angular/angular.js/issues/9413
+ describe('passing a parent bound transclude function to the link ' +
+ 'function returned from `$compile`', function() {
- $rootScope.$apply('t = true');
- expect($rootScope.$countChildScopes()).toBe(4);
- expect(element.text()).toBe('Success');
+ beforeEach(module(function() {
+ directive('lazyCompile', function($compile) {
+ return {
+ compile: function(tElement, tAttrs) {
+ var content = tElement.contents();
+ tElement.empty();
+ return function(scope, element, attrs, ctrls, transcludeFn) {
+ element.append(content);
+ $compile(content)(scope, undefined, {
+ parentBoundTranscludeFn: transcludeFn
+ });
+ };
+ }
+ };
+ });
+ directive('toggle', valueFn({
+ scope: {t: '=toggle'},
+ transclude: true,
+ template: '
'
+ }));
+ }));
- $rootScope.$apply('t = false');
- expect($rootScope.$countChildScopes()).toBe(1);
- expect(element.text()).toBe('');
+ it('should preserve the bound scope', function() {
- $rootScope.$apply('t = true');
- expect($rootScope.$countChildScopes()).toBe(4);
- expect(element.text()).toBe('Success');
- });
- });
- });
+ inject(function($compile, $rootScope) {
+ element = $compile(
+ '
' +
+ '
' +
+ '
' +
+ 'Success Error ' +
+ '
' +
+ '
')($rootScope);
+
+ $rootScope.$apply('t = false');
+ expect($rootScope.$countChildScopes()).toBe(1);
+ expect(element.text()).toBe('');
+
+ $rootScope.$apply('t = true');
+ expect($rootScope.$countChildScopes()).toBe(4);
+ expect(element.text()).toBe('Success');
+
+ $rootScope.$apply('t = false');
+ expect($rootScope.$countChildScopes()).toBe(1);
+ expect(element.text()).toBe('');
+
+ $rootScope.$apply('t = true');
+ expect($rootScope.$countChildScopes()).toBe(4);
+ expect(element.text()).toBe('Success');
+ });
+ });
- // see issue https://github.com/angular/angular.js/issues/9095
- describe('removing a transcluded element', function() {
+ it('should preserve the bound scope when using recursive transclusion', function() {
- beforeEach(module(function() {
- directive('toggle', function() {
- return {
- transclude: true,
- template: '
'
- };
+ directive('recursiveTransclude', valueFn({
+ transclude: true,
+ template: '
'
+ }));
+
+ inject(function($compile, $rootScope) {
+ element = $compile(
+ '
' +
+ '
' +
+ '
' +
+ '
' +
+ 'Success Error ' +
+ '
' +
+ '
' +
+ '
')($rootScope);
+
+ $rootScope.$apply('t = false');
+ expect($rootScope.$countChildScopes()).toBe(1);
+ expect(element.text()).toBe('');
+
+ $rootScope.$apply('t = true');
+ expect($rootScope.$countChildScopes()).toBe(4);
+ expect(element.text()).toBe('Success');
+
+ $rootScope.$apply('t = false');
+ expect($rootScope.$countChildScopes()).toBe(1);
+ expect(element.text()).toBe('');
+
+ $rootScope.$apply('t = true');
+ expect($rootScope.$countChildScopes()).toBe(4);
+ expect(element.text()).toBe('Success');
+ });
+ });
});
- }));
- it('should not leak the transclude scope when the transcluded content is an element transclusion directive',
- inject(function($compile, $rootScope) {
+ // see issue https://github.com/angular/angular.js/issues/9095
+ describe('removing a transcluded element', function() {
- element = $compile(
- '
'
- )($rootScope);
-
- $rootScope.$apply('t = true');
- expect(element.text()).toContain('msg-1');
- // Expected scopes: $rootScope, ngIf, transclusion, ngRepeat
- expect($rootScope.$countChildScopes()).toBe(3);
-
- $rootScope.$apply('t = false');
- expect(element.text()).not.toContain('msg-1');
- // Expected scopes: $rootScope
- expect($rootScope.$countChildScopes()).toBe(0);
-
- $rootScope.$apply('t = true');
- expect(element.text()).toContain('msg-1');
- // Expected scopes: $rootScope, ngIf, transclusion, ngRepeat
- expect($rootScope.$countChildScopes()).toBe(3);
-
- $rootScope.$apply('t = false');
- expect(element.text()).not.toContain('msg-1');
- // Expected scopes: $rootScope
- expect($rootScope.$countChildScopes()).toBe(0);
- }));
+ beforeEach(module(function() {
+ directive('toggle', function() {
+ return {
+ transclude: true,
+ template: '
'
+ };
+ });
+ }));
- it('should not leak the transclude scope when the transcluded content is an multi-element transclusion directive',
- inject(function($compile, $rootScope) {
+ it('should not leak the transclude scope when the transcluded content is an element transclusion directive',
+ inject(function($compile, $rootScope) {
- element = $compile(
- '
' +
- '
{{ msg }}
' +
- '
{{ msg }}
' +
- '
'
- )($rootScope);
-
- $rootScope.$apply('t = true');
- expect(element.text()).toContain('msg-1msg-1');
- // Expected scopes: $rootScope, ngIf, transclusion, ngRepeat
- expect($rootScope.$countChildScopes()).toBe(3);
-
- $rootScope.$apply('t = false');
- expect(element.text()).not.toContain('msg-1msg-1');
- // Expected scopes: $rootScope
- expect($rootScope.$countChildScopes()).toBe(0);
-
- $rootScope.$apply('t = true');
- expect(element.text()).toContain('msg-1msg-1');
- // Expected scopes: $rootScope, ngIf, transclusion, ngRepeat
- expect($rootScope.$countChildScopes()).toBe(3);
-
- $rootScope.$apply('t = false');
- expect(element.text()).not.toContain('msg-1msg-1');
- // Expected scopes: $rootScope
- expect($rootScope.$countChildScopes()).toBe(0);
- }));
+ element = $compile(
+ '
'
+ )($rootScope);
+ $rootScope.$apply('t = true');
+ expect(element.text()).toContain('msg-1');
+ // Expected scopes: $rootScope, ngIf, transclusion, ngRepeat
+ expect($rootScope.$countChildScopes()).toBe(3);
+
+ $rootScope.$apply('t = false');
+ expect(element.text()).not.toContain('msg-1');
+ // Expected scopes: $rootScope
+ expect($rootScope.$countChildScopes()).toBe(0);
+
+ $rootScope.$apply('t = true');
+ expect(element.text()).toContain('msg-1');
+ // Expected scopes: $rootScope, ngIf, transclusion, ngRepeat
+ expect($rootScope.$countChildScopes()).toBe(3);
+
+ $rootScope.$apply('t = false');
+ expect(element.text()).not.toContain('msg-1');
+ // Expected scopes: $rootScope
+ expect($rootScope.$countChildScopes()).toBe(0);
+ }));
- it('should not leak the transclude scope if the transcluded contains only comments',
- inject(function($compile, $rootScope) {
- element = $compile(
- '
' +
- '' +
- '
'
- )($rootScope);
-
- $rootScope.$apply('t = true');
- expect(element.html()).toContain('some comment');
- // Expected scopes: $rootScope, ngIf, transclusion
- expect($rootScope.$countChildScopes()).toBe(2);
-
- $rootScope.$apply('t = false');
- expect(element.html()).not.toContain('some comment');
- // Expected scopes: $rootScope
- expect($rootScope.$countChildScopes()).toBe(0);
-
- $rootScope.$apply('t = true');
- expect(element.html()).toContain('some comment');
- // Expected scopes: $rootScope, ngIf, transclusion
- expect($rootScope.$countChildScopes()).toBe(2);
-
- $rootScope.$apply('t = false');
- expect(element.html()).not.toContain('some comment');
- // Expected scopes: $rootScope
- expect($rootScope.$countChildScopes()).toBe(0);
- }));
+ it('should not leak the transclude scope when the transcluded content is an multi-element transclusion directive',
+ inject(function($compile, $rootScope) {
- it('should not leak the transclude scope if the transcluded contains only text nodes',
- inject(function($compile, $rootScope) {
+ element = $compile(
+ '
' +
+ '
{{ msg }}
' +
+ '
{{ msg }}
' +
+ '
'
+ )($rootScope);
- element = $compile(
- '
' +
- 'some text' +
- '
'
- )($rootScope);
-
- $rootScope.$apply('t = true');
- expect(element.html()).toContain('some text');
- // Expected scopes: $rootScope, ngIf, transclusion
- expect($rootScope.$countChildScopes()).toBe(2);
-
- $rootScope.$apply('t = false');
- expect(element.html()).not.toContain('some text');
- // Expected scopes: $rootScope
- expect($rootScope.$countChildScopes()).toBe(0);
-
- $rootScope.$apply('t = true');
- expect(element.html()).toContain('some text');
- // Expected scopes: $rootScope, ngIf, transclusion
- expect($rootScope.$countChildScopes()).toBe(2);
-
- $rootScope.$apply('t = false');
- expect(element.html()).not.toContain('some text');
- // Expected scopes: $rootScope
- expect($rootScope.$countChildScopes()).toBe(0);
- }));
+ $rootScope.$apply('t = true');
+ expect(element.text()).toContain('msg-1msg-1');
+ // Expected scopes: $rootScope, ngIf, transclusion, ngRepeat
+ expect($rootScope.$countChildScopes()).toBe(3);
+
+ $rootScope.$apply('t = false');
+ expect(element.text()).not.toContain('msg-1msg-1');
+ // Expected scopes: $rootScope
+ expect($rootScope.$countChildScopes()).toBe(0);
+
+ $rootScope.$apply('t = true');
+ expect(element.text()).toContain('msg-1msg-1');
+ // Expected scopes: $rootScope, ngIf, transclusion, ngRepeat
+ expect($rootScope.$countChildScopes()).toBe(3);
+
+ $rootScope.$apply('t = false');
+ expect(element.text()).not.toContain('msg-1msg-1');
+ // Expected scopes: $rootScope
+ expect($rootScope.$countChildScopes()).toBe(0);
+ }));
- it('should mark as destroyed all sub scopes of the scope being destroyed',
- inject(function($compile, $rootScope) {
- element = $compile(
- '
'
- )($rootScope);
+ it('should not leak the transclude scope if the transcluded contains only comments',
+ inject(function($compile, $rootScope) {
- $rootScope.$apply('t = true');
- var childScopes = getChildScopes($rootScope);
+ element = $compile(
+ '
' +
+ '' +
+ '
'
+ )($rootScope);
- $rootScope.$apply('t = false');
- for (var i = 0; i < childScopes.length; ++i) {
- expect(childScopes[i].$$destroyed).toBe(true);
- }
- }));
- });
+ $rootScope.$apply('t = true');
+ expect(element.html()).toContain('some comment');
+ // Expected scopes: $rootScope, ngIf, transclusion
+ expect($rootScope.$countChildScopes()).toBe(2);
+
+ $rootScope.$apply('t = false');
+ expect(element.html()).not.toContain('some comment');
+ // Expected scopes: $rootScope
+ expect($rootScope.$countChildScopes()).toBe(0);
+
+ $rootScope.$apply('t = true');
+ expect(element.html()).toContain('some comment');
+ // Expected scopes: $rootScope, ngIf, transclusion
+ expect($rootScope.$countChildScopes()).toBe(2);
+
+ $rootScope.$apply('t = false');
+ expect(element.html()).not.toContain('some comment');
+ // Expected scopes: $rootScope
+ expect($rootScope.$countChildScopes()).toBe(0);
+ }));
+ it('should not leak the transclude scope if the transcluded contains only text nodes',
+ inject(function($compile, $rootScope) {
- describe('nested transcludes', function() {
+ element = $compile(
+ '
' +
+ 'some text' +
+ '
'
+ )($rootScope);
- beforeEach(module(function($compileProvider) {
+ $rootScope.$apply('t = true');
+ expect(element.html()).toContain('some text');
+ // Expected scopes: $rootScope, ngIf, transclusion
+ expect($rootScope.$countChildScopes()).toBe(2);
+
+ $rootScope.$apply('t = false');
+ expect(element.html()).not.toContain('some text');
+ // Expected scopes: $rootScope
+ expect($rootScope.$countChildScopes()).toBe(0);
+
+ $rootScope.$apply('t = true');
+ expect(element.html()).toContain('some text');
+ // Expected scopes: $rootScope, ngIf, transclusion
+ expect($rootScope.$countChildScopes()).toBe(2);
+
+ $rootScope.$apply('t = false');
+ expect(element.html()).not.toContain('some text');
+ // Expected scopes: $rootScope
+ expect($rootScope.$countChildScopes()).toBe(0);
+ }));
- $compileProvider.directive('noop', valueFn({}));
+ it('should mark as destroyed all sub scopes of the scope being destroyed',
+ inject(function($compile, $rootScope) {
- $compileProvider.directive('sync', valueFn({
- template: '
',
- transclude: true
- }));
+ element = $compile(
+ '
'
+ )($rootScope);
- $compileProvider.directive('async', valueFn({
- templateUrl: 'async',
- transclude: true
- }));
+ $rootScope.$apply('t = true');
+ var childScopes = getChildScopes($rootScope);
- $compileProvider.directive('syncSync', valueFn({
- template: '
',
- transclude: true
- }));
+ $rootScope.$apply('t = false');
+ for (var i = 0; i < childScopes.length; ++i) {
+ expect(childScopes[i].$$destroyed).toBe(true);
+ }
+ }));
+ });
- $compileProvider.directive('syncAsync', valueFn({
- template: '
',
- transclude: true
- }));
- $compileProvider.directive('asyncSync', valueFn({
- templateUrl: 'asyncSync',
- transclude: true
- }));
+ describe('nested transcludes', function() {
- $compileProvider.directive('asyncAsync', valueFn({
- templateUrl: 'asyncAsync',
- transclude: true
- }));
+ beforeEach(module(function($compileProvider) {
- }));
+ $compileProvider.directive('noop', valueFn({}));
- beforeEach(inject(function($templateCache) {
- $templateCache.put('async', '
');
- $templateCache.put('asyncSync', '
');
- $templateCache.put('asyncAsync', '
');
- }));
+ $compileProvider.directive('sync', valueFn({
+ template: '
',
+ transclude: true
+ }));
+ $compileProvider.directive('async', valueFn({
+ templateUrl: 'async',
+ transclude: true
+ }));
- it('should allow nested transclude directives with sync template containing sync template', inject(function($compile, $rootScope) {
- element = $compile('
transcluded content
')($rootScope);
- $rootScope.$digest();
- expect(element.text()).toEqual('transcluded content');
- }));
+ $compileProvider.directive('syncSync', valueFn({
+ template: '
',
+ transclude: true
+ }));
- it('should allow nested transclude directives with sync template containing async template', inject(function($compile, $rootScope) {
- element = $compile('
transcluded content
')($rootScope);
- $rootScope.$digest();
- expect(element.text()).toEqual('transcluded content');
- }));
+ $compileProvider.directive('syncAsync', valueFn({
+ template: '
',
+ transclude: true
+ }));
- it('should allow nested transclude directives with async template containing sync template', inject(function($compile, $rootScope) {
- element = $compile('
transcluded content
')($rootScope);
- $rootScope.$digest();
- expect(element.text()).toEqual('transcluded content');
- }));
+ $compileProvider.directive('asyncSync', valueFn({
+ templateUrl: 'asyncSync',
+ transclude: true
+ }));
- it('should allow nested transclude directives with async template containing asynch template', inject(function($compile, $rootScope) {
- element = $compile('
transcluded content
')($rootScope);
- $rootScope.$digest();
- expect(element.text()).toEqual('transcluded content');
- }));
+ $compileProvider.directive('asyncAsync', valueFn({
+ templateUrl: 'asyncAsync',
+ transclude: true
+ }));
+ }));
- it('should not leak memory with nested transclusion', function() {
- inject(function($compile, $rootScope) {
- var size, initialSize = jqLiteCacheSize();
+ beforeEach(inject(function($templateCache) {
+ $templateCache.put('async', '
');
+ $templateCache.put('asyncSync', '
');
+ $templateCache.put('asyncAsync', '
');
+ }));
- element = jqLite('
');
- $compile(element)($rootScope.$new());
- $rootScope.nums = [0,1,2];
- $rootScope.$apply();
- size = jqLiteCacheSize();
+ it('should allow nested transclude directives with sync template containing sync template', inject(function($compile, $rootScope) {
+ element = $compile('
transcluded content
')($rootScope);
+ $rootScope.$digest();
+ expect(element.text()).toEqual('transcluded content');
+ }));
- $rootScope.nums = [3,4,5];
- $rootScope.$apply();
- expect(jqLiteCacheSize()).toEqual(size);
+ it('should allow nested transclude directives with sync template containing async template', inject(function($compile, $rootScope) {
+ element = $compile('
transcluded content
')($rootScope);
+ $rootScope.$digest();
+ expect(element.text()).toEqual('transcluded content');
+ }));
- element.remove();
- expect(jqLiteCacheSize()).toEqual(initialSize);
- });
- });
- });
+ it('should allow nested transclude directives with async template containing sync template', inject(function($compile, $rootScope) {
+ element = $compile('
transcluded content
')($rootScope);
+ $rootScope.$digest();
+ expect(element.text()).toEqual('transcluded content');
+ }));
+ it('should allow nested transclude directives with async template containing asynch template', inject(function($compile, $rootScope) {
+ element = $compile('
transcluded content
')($rootScope);
+ $rootScope.$digest();
+ expect(element.text()).toEqual('transcluded content');
+ }));
- describe('nested isolated scope transcludes', function() {
- beforeEach(module(function($compileProvider) {
- $compileProvider.directive('trans', valueFn({
- restrict: 'E',
- template: '
',
- transclude: true
- }));
+ it('should not leak memory with nested transclusion', function() {
+ inject(function($compile, $rootScope) {
+ var size, initialSize = jqLiteCacheSize();
- $compileProvider.directive('transAsync', valueFn({
- restrict: 'E',
- templateUrl: 'transAsync',
- transclude: true
- }));
+ element = jqLite('
');
+ $compile(element)($rootScope.$new());
- $compileProvider.directive('iso', valueFn({
- restrict: 'E',
- transclude: true,
- template: '
',
- scope: {}
- }));
- $compileProvider.directive('isoAsync1', valueFn({
- restrict: 'E',
- transclude: true,
- template: '
',
- scope: {}
- }));
- $compileProvider.directive('isoAsync2', valueFn({
- restrict: 'E',
- transclude: true,
- templateUrl: 'isoAsync',
- scope: {}
- }));
- }));
+ $rootScope.nums = [0,1,2];
+ $rootScope.$apply();
+ size = jqLiteCacheSize();
- beforeEach(inject(function($templateCache) {
- $templateCache.put('transAsync', '
');
- $templateCache.put('isoAsync', '
');
- }));
+ $rootScope.nums = [3,4,5];
+ $rootScope.$apply();
+ expect(jqLiteCacheSize()).toEqual(size);
+
+ element.remove();
+ expect(jqLiteCacheSize()).toEqual(initialSize);
+ });
+ });
+ });
- it('should pass the outer scope to the transclude on the isolated template sync-sync', inject(function($compile, $rootScope) {
+ describe('nested isolated scope transcludes', function() {
+ beforeEach(module(function($compileProvider) {
- $rootScope.val = 'transcluded content';
- element = $compile('
')($rootScope);
- $rootScope.$digest();
- expect(element.text()).toEqual('transcluded content');
- }));
+ $compileProvider.directive('trans', valueFn({
+ restrict: 'E',
+ template: '
',
+ transclude: true
+ }));
- it('should pass the outer scope to the transclude on the isolated template async-sync', inject(function($compile, $rootScope) {
+ $compileProvider.directive('transAsync', valueFn({
+ restrict: 'E',
+ templateUrl: 'transAsync',
+ transclude: true
+ }));
- $rootScope.val = 'transcluded content';
- element = $compile('
')($rootScope);
- $rootScope.$digest();
- expect(element.text()).toEqual('transcluded content');
- }));
+ $compileProvider.directive('iso', valueFn({
+ restrict: 'E',
+ transclude: true,
+ template: '
',
+ scope: {}
+ }));
+ $compileProvider.directive('isoAsync1', valueFn({
+ restrict: 'E',
+ transclude: true,
+ template: '
',
+ scope: {}
+ }));
+ $compileProvider.directive('isoAsync2', valueFn({
+ restrict: 'E',
+ transclude: true,
+ templateUrl: 'isoAsync',
+ scope: {}
+ }));
+ }));
- it('should pass the outer scope to the transclude on the isolated template async-async', inject(function($compile, $rootScope) {
+ beforeEach(inject(function($templateCache) {
+ $templateCache.put('transAsync', '
');
+ $templateCache.put('isoAsync', '
');
+ }));
- $rootScope.val = 'transcluded content';
- element = $compile('
')($rootScope);
- $rootScope.$digest();
- expect(element.text()).toEqual('transcluded content');
- }));
- });
+ it('should pass the outer scope to the transclude on the isolated template sync-sync', inject(function($compile, $rootScope) {
- describe('multiple siblings receiving transclusion', function() {
+ $rootScope.val = 'transcluded content';
+ element = $compile('
')($rootScope);
+ $rootScope.$digest();
+ expect(element.text()).toEqual('transcluded content');
+ }));
- it('should only receive transclude from parent', function() {
+ it('should pass the outer scope to the transclude on the isolated template async-sync', inject(function($compile, $rootScope) {
- module(function($compileProvider) {
+ $rootScope.val = 'transcluded content';
+ element = $compile('
')($rootScope);
+ $rootScope.$digest();
+ expect(element.text()).toEqual('transcluded content');
+ }));
- $compileProvider.directive('myExample', valueFn({
- scope: {},
- link: function link(scope, element, attrs) {
- var foo = element[0].querySelector('.foo');
- scope.children = angular.element(foo).children().length;
- },
- template: '
' +
- '
myExample {{children}}!
' +
- '
has children
' +
- '
' +
- '
',
- transclude: true
+ it('should pass the outer scope to the transclude on the isolated template async-async', inject(function($compile, $rootScope) {
+ $rootScope.val = 'transcluded content';
+ element = $compile('
')($rootScope);
+ $rootScope.$digest();
+ expect(element.text()).toEqual('transcluded content');
}));
});
- inject(function($compile, $rootScope) {
- var element = $compile('
')($rootScope);
- $rootScope.$digest();
- expect(element.text()).toEqual('myExample 0!');
- dealoc(element);
+ describe('multiple siblings receiving transclusion', function() {
- element = $compile('
')($rootScope);
- $rootScope.$digest();
- expect(element.text()).toEqual('myExample 1!has children');
- dealoc(element);
+ it('should only receive transclude from parent', function() {
+
+ module(function($compileProvider) {
+
+ $compileProvider.directive('myExample', valueFn({
+ scope: {},
+ link: function link(scope, element, attrs) {
+ var foo = element[0].querySelector('.foo');
+ scope.children = angular.element(foo).children().length;
+ },
+ template: '
' +
+ '
myExample {{children}}!
' +
+ '
has children
' +
+ '
' +
+ '
',
+ transclude: true
+
+ }));
+
+ });
+
+ inject(function($compile, $rootScope) {
+ var element = $compile('
')($rootScope);
+ $rootScope.$digest();
+ expect(element.text()).toEqual('myExample 0!');
+ dealoc(element);
+
+ element = $compile('
')($rootScope);
+ $rootScope.$digest();
+ expect(element.text()).toEqual('myExample 1!has children');
+ dealoc(element);
+ });
+ });
});
});
- });
- });
- describe('element transclusion', function() {
+ describe('element transclusion', function() {
- it('should support basic element transclusion', function() {
- module(function() {
- directive('trans', function(log) {
- return {
- transclude: 'element',
- priority: 2,
- controller: function($transclude) { this.$transclude = $transclude; },
- compile: function(element, attrs, template) {
- log('compile: ' + angular.mock.dump(element));
- return function(scope, element, attrs, ctrl) {
- log('link');
- var cursor = element;
- template(scope.$new(), function(clone) {cursor.after(cursor = clone);});
- ctrl.$transclude(function(clone) {cursor.after(clone);});
+ it('should support basic element transclusion', function() {
+ module(function() {
+ directive('trans', function(log) {
+ return {
+ transclude: 'element',
+ priority: 2,
+ controller: function($transclude) { this.$transclude = $transclude; },
+ compile: function(element, attrs, template) {
+ log('compile: ' + angular.mock.dump(element));
+ return function(scope, element, attrs, ctrl) {
+ log('link');
+ var cursor = element;
+ template(scope.$new(), function(clone) {cursor.after(cursor = clone);});
+ ctrl.$transclude(function(clone) {cursor.after(clone);});
+ };
+ }
};
- }
- };
+ });
+ });
+ inject(function(log, $rootScope, $compile) {
+ element = $compile('
')($rootScope);
+ $rootScope.$apply();
+ expect(log).toEqual('compile: ; link; LOG; LOG; HIGH');
+ expect(element.text()).toEqual('1-2;1-3;');
+ });
});
- });
- inject(function(log, $rootScope, $compile) {
- element = $compile('
')($rootScope);
- $rootScope.$apply();
- expect(log).toEqual('compile: ; link; LOG; LOG; HIGH');
- expect(element.text()).toEqual('1-2;1-3;');
- });
- });
- it('should only allow one element transclusion per element', function() {
- module(function() {
- directive('first', valueFn({
- transclude: 'element'
- }));
- directive('second', valueFn({
- transclude: 'element'
- }));
- });
- inject(function($compile) {
- expect(function() {
- $compile('
');
- }).toThrowMinErr('$compile', 'multidir', 'Multiple directives [first, second] asking for transclusion on: ' +
- '');
- });
- });
+ it('should only allow one element transclusion per element', function() {
+ module(function() {
+ directive('first', valueFn({
+ transclude: 'element'
+ }));
+ directive('second', valueFn({
+ transclude: 'element'
+ }));
+ });
+ inject(function($compile) {
+ expect(function() {
+ $compile('
');
+ }).toThrowMinErr('$compile', 'multidir', 'Multiple directives [first, second] asking for transclusion on: ' +
+ '');
+ });
+ });
- it('should only allow one element transclusion per element when directives have different priorities', function() {
- // we restart compilation in this case and we need to remember the duplicates during the second compile
- // regression #3893
- module(function() {
- directive('first', valueFn({
- transclude: 'element',
- priority: 100
- }));
- directive('second', valueFn({
- transclude: 'element'
- }));
- });
- inject(function($compile) {
- expect(function() {
- $compile('
');
- }).toThrowMinErr('$compile', 'multidir', /Multiple directives \[first, second\] asking for transclusion on:
');
+ }).toThrowMinErr('$compile', 'multidir', /Multiple directives \[first, second\] asking for transclusion on:
template.html');
- $compile('
');
- expect(function() {
- $httpBackend.flush();
- }).toThrowMinErr('$compile', 'multidir', /Multiple directives \[first, second\] asking for transclusion on:
template.html
');
+ $compile('
');
+ expect(function() {
+ $httpBackend.flush();
+ }).toThrowMinErr('$compile', 'multidir', /Multiple directives \[first, second\] asking for transclusion on:
',
- replace: true
- }));
- directive('first', valueFn({
- transclude: 'element',
- priority: 100
- }));
- directive('second', valueFn({
- transclude: 'element'
- }));
- });
- inject(function($compile) {
- expect(function() {
- $compile('
');
- }).toThrowMinErr('$compile', 'multidir', /Multiple directives \[first, second\] asking for transclusion on:
',
+ replace: true
+ }));
+ directive('first', valueFn({
+ transclude: 'element',
+ priority: 100
+ }));
+ directive('second', valueFn({
+ transclude: 'element'
+ }));
+ });
+ inject(function($compile) {
+ expect(function() {
+ $compile('
');
+ }).toThrowMinErr('$compile', 'multidir', /Multiple directives \[first, second\] asking for transclusion on:
before
after
').contents();
- expect(element.length).toEqual(3);
- expect(nodeName_(element[1])).toBe('div');
- $compile(element)($rootScope);
- expect(nodeName_(element[1])).toBe('#comment');
- expect(nodeName_(comment)).toBe('#comment');
- });
- });
+ it('should support transcluded element on root content', function() {
+ var comment;
+ module(function() {
+ directive('transclude', valueFn({
+ transclude: 'element',
+ compile: function(element, attr, linker) {
+ return function(scope, element, attr) {
+ comment = element;
+ };
+ }
+ }));
+ });
+ inject(function($compile, $rootScope) {
+ var element = jqLite('
').contents();
+ expect(element.length).toEqual(3);
+ expect(nodeName_(element[1])).toBe('div');
+ $compile(element)($rootScope);
+ expect(nodeName_(element[1])).toBe('#comment');
+ expect(nodeName_(comment)).toBe('#comment');
+ });
+ });
- it('should terminate compilation only for element trasclusion', function() {
- module(function() {
- directive('elementTrans', function(log) {
- return {
- transclude: 'element',
- priority: 50,
- compile: log.fn('compile:elementTrans')
- };
- });
- directive('regularTrans', function(log) {
- return {
- transclude: true,
- priority: 50,
- compile: log.fn('compile:regularTrans')
- };
+ it('should terminate compilation only for element trasclusion', function() {
+ module(function() {
+ directive('elementTrans', function(log) {
+ return {
+ transclude: 'element',
+ priority: 50,
+ compile: log.fn('compile:elementTrans')
+ };
+ });
+ directive('regularTrans', function(log) {
+ return {
+ transclude: true,
+ priority: 50,
+ compile: log.fn('compile:regularTrans')
+ };
+ });
+ });
+ inject(function(log, $compile, $rootScope) {
+ $compile('
')($rootScope);
+ expect(log).toEqual('compile:elementTrans; compile:regularTrans; regular');
+ });
});
- });
- inject(function(log, $compile, $rootScope) {
- $compile('
')($rootScope);
- expect(log).toEqual('compile:elementTrans; compile:regularTrans; regular');
- });
- });
- it('should instantiate high priority controllers only once, but low priority ones each time we transclude',
- function() {
- module(function() {
- directive('elementTrans', function(log) {
- return {
- transclude: 'element',
- priority: 50,
- controller: function($transclude, $element) {
- log('controller:elementTrans');
- $transclude(function(clone) {
- $element.after(clone);
- });
- $transclude(function(clone) {
- $element.after(clone);
- });
- $transclude(function(clone) {
- $element.after(clone);
- });
- }
- };
+ it('should instantiate high priority controllers only once, but low priority ones each time we transclude',
+ function() {
+ module(function() {
+ directive('elementTrans', function(log) {
+ return {
+ transclude: 'element',
+ priority: 50,
+ controller: function($transclude, $element) {
+ log('controller:elementTrans');
+ $transclude(function(clone) {
+ $element.after(clone);
+ });
+ $transclude(function(clone) {
+ $element.after(clone);
+ });
+ $transclude(function(clone) {
+ $element.after(clone);
+ });
+ }
+ };
+ });
+ directive('normalDir', function(log) {
+ return {
+ controller: function() {
+ log('controller:normalDir');
+ }
+ };
+ });
+ });
+ inject(function($compile, $rootScope, log) {
+ element = $compile('
')($rootScope);
+ expect(log).toEqual([
+ 'controller:elementTrans',
+ 'controller:normalDir',
+ 'controller:normalDir',
+ 'controller:normalDir'
+ ]);
+ });
});
- directive('normalDir', function(log) {
- return {
- controller: function() {
- log('controller:normalDir');
- }
- };
+
+ it('should allow to access $transclude in the same directive', function() {
+ var _$transclude;
+ module(function() {
+ directive('transclude', valueFn({
+ transclude: 'element',
+ controller: function($transclude) {
+ _$transclude = $transclude;
+ }
+ }));
+ });
+ inject(function($compile) {
+ element = $compile('
')($rootScope);
+ expect(_$transclude).toBeDefined();
+ });
});
- });
- inject(function($compile, $rootScope, log) {
- element = $compile('
')($rootScope);
- expect(log).toEqual([
- 'controller:elementTrans',
- 'controller:normalDir',
- 'controller:normalDir',
- 'controller:normalDir'
- ]);
- });
- });
- it('should allow to access $transclude in the same directive', function() {
- var _$transclude;
- module(function() {
- directive('transclude', valueFn({
- transclude: 'element',
- controller: function($transclude) {
- _$transclude = $transclude;
- }
- }));
- });
- inject(function($compile) {
- element = $compile('
')($rootScope);
- expect(_$transclude).toBeDefined();
- });
- });
+ it('should copy the directive controller to all clones', function() {
+ var transcludeCtrl, cloneCount = 2;
+ module(function() {
+ directive('transclude', valueFn({
+ transclude: 'element',
+ controller: function() {
+ transcludeCtrl = this;
+ },
+ link: function(scope, el, attr, ctrl, $transclude) {
+ var i;
+ for (i = 0; i < cloneCount; i++) {
+ $transclude(cloneAttach);
+ }
- it('should copy the directive controller to all clones', function() {
- var transcludeCtrl, cloneCount = 2;
- module(function() {
- directive('transclude', valueFn({
- transclude: 'element',
- controller: function() {
- transcludeCtrl = this;
- },
- link: function(scope, el, attr, ctrl, $transclude) {
- var i;
+ function cloneAttach(clone) {
+ el.after(clone);
+ }
+ }
+ }));
+ });
+ inject(function($compile) {
+ element = $compile('
')($rootScope);
+ var children = element.children(), i;
for (i = 0; i < cloneCount; i++) {
- $transclude(cloneAttach);
+ expect(children.eq(i).data('$transcludeController')).toBe(transcludeCtrl);
}
+ });
+ });
- function cloneAttach(clone) {
- el.after(clone);
- }
- }
- }));
- });
- inject(function($compile) {
- element = $compile('
')($rootScope);
- var children = element.children(), i;
- for (i = 0; i < cloneCount; i++) {
- expect(children.eq(i).data('$transcludeController')).toBe(transcludeCtrl);
- }
- });
- });
+ it('should expose the directive controller to transcluded children', function() {
+ var capturedTranscludeCtrl;
+ module(function() {
+ directive('transclude', valueFn({
+ transclude: 'element',
+ controller: function() {
+ },
+ link: function(scope, element, attr, ctrl, $transclude) {
+ $transclude(scope, function(clone) {
+ element.after(clone);
+ });
+ }
+ }));
+ directive('child', valueFn({
+ require: '^transclude',
+ link: function(scope, element, attr, ctrl) {
+ capturedTranscludeCtrl = ctrl;
+ }
+ }));
+ });
+ inject(function($compile) {
+ // We need to wrap the transclude directive's element in a parent element so that the
+ // cloned element gets deallocated/cleaned up correctly
+ element = $compile('
')($rootScope);
+ expect(capturedTranscludeCtrl).toBeTruthy();
+ });
+ });
- it('should expose the directive controller to transcluded children', function() {
- var capturedTranscludeCtrl;
- module(function() {
- directive('transclude', valueFn({
- transclude: 'element',
- controller: function() {
- },
- link: function(scope, element, attr, ctrl, $transclude) {
- $transclude(scope, function(clone) {
- element.after(clone);
+ it('should allow access to $transclude in a templateUrl directive', function() {
+ var transclude;
+ module(function() {
+ directive('template', valueFn({
+ templateUrl: 'template.html',
+ replace: true
+ }));
+ directive('transclude', valueFn({
+ transclude: 'content',
+ controller: function($transclude) {
+ transclude = $transclude;
+ }
+ }));
+ });
+ inject(function($compile, $httpBackend) {
+ $httpBackend.expectGET('template.html').respond('
');
+ element = $compile('
')($rootScope);
+ $httpBackend.flush();
+ expect(transclude).toBeDefined();
+ });
+ });
+
+ // issue #6006
+ it('should link directive with $element as a comment node', function() {
+ module(function($provide) {
+ directive('innerAgain', function(log) {
+ return {
+ transclude: 'element',
+ link: function(scope, element, attr, controllers, transclude) {
+ log('innerAgain:' + lowercase(nodeName_(element)) + ':' + trim(element[0].data));
+ transclude(scope, function(clone) {
+ element.parent().append(clone);
+ });
+ }
+ };
+ });
+ directive('inner', function(log) {
+ return {
+ replace: true,
+ templateUrl: 'inner.html',
+ link: function(scope, element) {
+ log('inner:' + lowercase(nodeName_(element)) + ':' + trim(element[0].data));
+ }
+ };
});
- }
- }));
- directive('child', valueFn({
- require: '^transclude',
- link: function(scope, element, attr, ctrl) {
- capturedTranscludeCtrl = ctrl;
- }
- }));
- });
- inject(function($compile) {
- // We need to wrap the transclude directive's element in a parent element so that the
- // cloned element gets deallocated/cleaned up correctly
- element = $compile('
')($rootScope);
- expect(capturedTranscludeCtrl).toBeTruthy();
+ directive('outer', function(log) {
+ return {
+ transclude: 'element',
+ link: function(scope, element, attrs, controllers, transclude) {
+ log('outer:' + lowercase(nodeName_(element)) + ':' + trim(element[0].data));
+ transclude(scope, function(clone) {
+ element.parent().append(clone);
+ });
+ }
+ };
+ });
+ });
+ inject(function(log, $compile, $rootScope, $templateCache) {
+ $templateCache.put('inner.html', '
');
+ element = $compile('
')($rootScope);
+ $rootScope.$digest();
+ var child = element.children();
+
+ expect(log.toArray()).toEqual([
+ 'outer:#comment:outer:',
+ 'innerAgain:#comment:innerAgain:',
+ 'inner:#comment:innerAgain:'
+ ]);
+ expect(child.length).toBe(1);
+ expect(child.contents().length).toBe(2);
+ expect(lowercase(nodeName_(child.contents().eq(0)))).toBe('#comment');
+ expect(lowercase(nodeName_(child.contents().eq(1)))).toBe('div');
+ });
+ });
});
- });
- it('should allow access to $transclude in a templateUrl directive', function() {
- var transclude;
- module(function() {
- directive('template', valueFn({
- templateUrl: 'template.html',
- replace: true
- }));
- directive('transclude', valueFn({
- transclude: 'content',
- controller: function($transclude) {
- transclude = $transclude;
- }
- }));
- });
- inject(function($compile, $httpBackend) {
- $httpBackend.expectGET('template.html').respond('
');
- element = $compile('
')($rootScope);
- $httpBackend.flush();
- expect(transclude).toBeDefined();
- });
- });
- // issue #6006
- it('should link directive with $element as a comment node', function() {
- module(function($provide) {
- directive('innerAgain', function(log) {
- return {
- transclude: 'element',
- link: function(scope, element, attr, controllers, transclude) {
- log('innerAgain:' + lowercase(nodeName_(element)) + ':' + trim(element[0].data));
- transclude(scope, function(clone) {
- element.parent().append(clone);
- });
- }
- };
- });
- directive('inner', function(log) {
- return {
- replace: true,
- templateUrl: 'inner.html',
- link: function(scope, element) {
- log('inner:' + lowercase(nodeName_(element)) + ':' + trim(element[0].data));
- }
- };
+ it('should be possible to change the scope of a directive using $provide', function() {
+ module(function($provide) {
+ directive('foo', function() {
+ return {
+ scope: {},
+ template: '
'
+ };
+ });
+ $provide.decorator('fooDirective', function($delegate) {
+ var directive = $delegate[0];
+ directive.scope.something = '=';
+ directive.template = '
{{something}} ';
+ return $delegate;
+ });
});
- directive('outer', function(log) {
- return {
- transclude: 'element',
- link: function(scope, element, attrs, controllers, transclude) {
- log('outer:' + lowercase(nodeName_(element)) + ':' + trim(element[0].data));
- transclude(scope, function(clone) {
- element.parent().append(clone);
- });
- }
- };
+ inject(function($compile, $rootScope) {
+ element = $compile('
')($rootScope);
+ $rootScope.bar = 'bar';
+ $rootScope.$digest();
+ expect(element.text()).toBe('bar');
});
});
- inject(function(log, $compile, $rootScope, $templateCache) {
- $templateCache.put('inner.html', '
');
- element = $compile('
')($rootScope);
- $rootScope.$digest();
- var child = element.children();
-
- expect(log.toArray()).toEqual([
- 'outer:#comment:outer:',
- 'innerAgain:#comment:innerAgain:',
- 'inner:#comment:innerAgain:'
- ]);
- expect(child.length).toBe(1);
- expect(child.contents().length).toBe(2);
- expect(lowercase(nodeName_(child.contents().eq(0)))).toBe('#comment');
- expect(lowercase(nodeName_(child.contents().eq(1)))).toBe('div');
- });
- });
- });
- it('should be possible to change the scope of a directive using $provide', function() {
- module(function($provide) {
- directive('foo', function() {
- return {
- scope: {},
- template: '
'
- };
- });
- $provide.decorator('fooDirective', function($delegate) {
- var directive = $delegate[0];
- directive.scope.something = '=';
- directive.template = '
{{something}} ';
- return $delegate;
+ it('should distinguish different bindings with the same binding name', function() {
+ module(function() {
+ directive('foo', function() {
+ return {
+ scope: {
+ foo: '=',
+ bar: '='
+ },
+ template: '
'
+ };
+ });
+ });
+ inject(function($compile, $rootScope) {
+ element = $compile('
')($rootScope);
+ $rootScope.$digest();
+ expect(element.text()).toBe('foobar');
+ });
});
- });
- inject(function($compile, $rootScope) {
- element = $compile('
')($rootScope);
- $rootScope.bar = 'bar';
- $rootScope.$digest();
- expect(element.text()).toBe('bar');
- });
- });
-
- it('should distinguish different bindings with the same binding name', function() {
- module(function() {
- directive('foo', function() {
- return {
- scope: {
- foo: '=',
- bar: '='
- },
- template: '
'
- };
- });
- });
- inject(function($compile, $rootScope) {
- element = $compile('
')($rootScope);
- $rootScope.$digest();
- expect(element.text()).toBe('foobar');
- });
- });
+ it('should safely create transclude comment node and not break with "-->"',
+ inject(function($rootScope) {
+ // see: https://github.com/angular/angular.js/issues/1740
+ element = $compile('
')($rootScope);
+ $rootScope.$digest();
- it('should safely create transclude comment node and not break with "-->"',
- inject(function($rootScope) {
- // see: https://github.com/angular/angular.js/issues/1740
- element = $compile('
')($rootScope);
- $rootScope.$digest();
+ expect(element.text()).toBe('-->|x|');
+ }));
- expect(element.text()).toBe('-->|x|');
- }));
+ describe('lazy compilation', function() {
+ // See https://github.com/angular/angular.js/issues/7183
+ it('should pass transclusion through to template of a \'replace\' directive', function() {
+ module(function() {
+ directive('transSync', function() {
+ return {
+ transclude: true,
+ link: function(scope, element, attr, ctrl, transclude) {
- describe('lazy compilation', function() {
- // See https://github.com/angular/angular.js/issues/7183
- it('should pass transclusion through to template of a \'replace\' directive', function() {
- module(function() {
- directive('transSync', function() {
- return {
- transclude: true,
- link: function(scope, element, attr, ctrl, transclude) {
+ expect(transclude).toEqual(jasmine.any(Function));
- expect(transclude).toEqual(jasmine.any(Function));
+ transclude(function(child) { element.append(child); });
+ }
+ };
+ });
- transclude(function(child) { element.append(child); });
- }
- };
- });
+ directive('trans', function($timeout) {
+ return {
+ transclude: true,
+ link: function(scope, element, attrs, ctrl, transclude) {
- directive('trans', function($timeout) {
- return {
- transclude: true,
- link: function(scope, element, attrs, ctrl, transclude) {
+ // We use timeout here to simulate how ng-if works
+ $timeout(function() {
+ transclude(function(child) { element.append(child); });
+ });
+ }
+ };
+ });
- // We use timeout here to simulate how ng-if works
- $timeout(function() {
- transclude(function(child) { element.append(child); });
- });
- }
- };
- });
+ directive('replaceWithTemplate', function() {
+ return {
+ templateUrl: 'template.html',
+ replace: true
+ };
+ });
+ });
- directive('replaceWithTemplate', function() {
- return {
- templateUrl: 'template.html',
- replace: true
- };
- });
- });
+ inject(function($compile, $rootScope, $templateCache, $timeout) {
- inject(function($compile, $rootScope, $templateCache, $timeout) {
+ $templateCache.put('template.html', '
Content To Be Transcluded
');
- $templateCache.put('template.html', '
Content To Be Transcluded
');
+ expect(function() {
+ element = $compile('
')($rootScope);
+ $timeout.flush();
+ }).not.toThrow();
- expect(function() {
- element = $compile('
')($rootScope);
- $timeout.flush();
- }).not.toThrow();
+ expect(element.text()).toEqual('Content To Be Transcluded');
+ });
- expect(element.text()).toEqual('Content To Be Transcluded');
- });
+ });
- });
+ it('should lazily compile the contents of directives that are transcluded', function() {
+ var innerCompilationCount = 0, transclude;
- it('should lazily compile the contents of directives that are transcluded', function() {
- var innerCompilationCount = 0, transclude;
+ module(function() {
+ directive('trans', valueFn({
+ transclude: true,
+ controller: function($transclude) {
+ transclude = $transclude;
+ }
+ }));
- module(function() {
- directive('trans', valueFn({
- transclude: true,
- controller: function($transclude) {
- transclude = $transclude;
- }
- }));
+ directive('inner', valueFn({
+ template: '
FooBar ',
+ compile: function() {
+ innerCompilationCount += 1;
+ }
+ }));
+ });
- directive('inner', valueFn({
- template: '
FooBar ',
- compile: function() {
- innerCompilationCount += 1;
- }
- }));
- });
+ inject(function($compile, $rootScope) {
+ element = $compile('
')($rootScope);
+ expect(innerCompilationCount).toBe(0);
+ transclude(function(child) { element.append(child); });
+ expect(innerCompilationCount).toBe(1);
+ expect(element.text()).toBe('FooBar');
+ });
+ });
- inject(function($compile, $rootScope) {
- element = $compile('
')($rootScope);
- expect(innerCompilationCount).toBe(0);
- transclude(function(child) { element.append(child); });
- expect(innerCompilationCount).toBe(1);
- expect(element.text()).toBe('FooBar');
- });
- });
+ it('should lazily compile the contents of directives that are transcluded with a template', function() {
+ var innerCompilationCount = 0, transclude;
- it('should lazily compile the contents of directives that are transcluded with a template', function() {
- var innerCompilationCount = 0, transclude;
+ module(function() {
+ directive('trans', valueFn({
+ transclude: true,
+ template: '
Baz
',
+ controller: function($transclude) {
+ transclude = $transclude;
+ }
+ }));
- module(function() {
- directive('trans', valueFn({
- transclude: true,
- template: '
Baz
',
- controller: function($transclude) {
- transclude = $transclude;
- }
- }));
+ directive('inner', valueFn({
+ template: '
FooBar ',
+ compile: function() {
+ innerCompilationCount += 1;
+ }
+ }));
+ });
- directive('inner', valueFn({
- template: '
FooBar ',
- compile: function() {
- innerCompilationCount += 1;
- }
- }));
- });
+ inject(function($compile, $rootScope) {
+ element = $compile('
')($rootScope);
+ expect(innerCompilationCount).toBe(0);
+ transclude(function(child) { element.append(child); });
+ expect(innerCompilationCount).toBe(1);
+ expect(element.text()).toBe('BazFooBar');
+ });
+ });
- inject(function($compile, $rootScope) {
- element = $compile('
')($rootScope);
- expect(innerCompilationCount).toBe(0);
- transclude(function(child) { element.append(child); });
- expect(innerCompilationCount).toBe(1);
- expect(element.text()).toBe('BazFooBar');
- });
- });
+ it('should lazily compile the contents of directives that are transcluded with a templateUrl', function() {
+ var innerCompilationCount = 0, transclude;
- it('should lazily compile the contents of directives that are transcluded with a templateUrl', function() {
- var innerCompilationCount = 0, transclude;
+ module(function() {
+ directive('trans', valueFn({
+ transclude: true,
+ templateUrl: 'baz.html',
+ controller: function($transclude) {
+ transclude = $transclude;
+ }
+ }));
- module(function() {
- directive('trans', valueFn({
- transclude: true,
- templateUrl: 'baz.html',
- controller: function($transclude) {
- transclude = $transclude;
- }
- }));
+ directive('inner', valueFn({
+ template: '
FooBar ',
+ compile: function() {
+ innerCompilationCount += 1;
+ }
+ }));
+ });
- directive('inner', valueFn({
- template: '
FooBar ',
- compile: function() {
- innerCompilationCount += 1;
- }
- }));
- });
+ inject(function($compile, $rootScope, $httpBackend) {
+ $httpBackend.expectGET('baz.html').respond('
Baz
');
+ element = $compile('
')($rootScope);
+ $httpBackend.flush();
- inject(function($compile, $rootScope, $httpBackend) {
- $httpBackend.expectGET('baz.html').respond('
Baz
');
- element = $compile('
')($rootScope);
- $httpBackend.flush();
+ expect(innerCompilationCount).toBe(0);
+ transclude(function(child) { element.append(child); });
+ expect(innerCompilationCount).toBe(1);
+ expect(element.text()).toBe('BazFooBar');
+ });
+ });
- expect(innerCompilationCount).toBe(0);
- transclude(function(child) { element.append(child); });
- expect(innerCompilationCount).toBe(1);
- expect(element.text()).toBe('BazFooBar');
- });
- });
+ it('should lazily compile the contents of directives that are transclude element', function() {
+ var innerCompilationCount = 0, transclude;
- it('should lazily compile the contents of directives that are transclude element', function() {
- var innerCompilationCount = 0, transclude;
+ module(function() {
+ directive('trans', valueFn({
+ transclude: 'element',
+ controller: function($transclude) {
+ transclude = $transclude;
+ }
+ }));
- module(function() {
- directive('trans', valueFn({
- transclude: 'element',
- controller: function($transclude) {
- transclude = $transclude;
- }
- }));
+ directive('inner', valueFn({
+ template: '
FooBar ',
+ compile: function() {
+ innerCompilationCount += 1;
+ }
+ }));
+ });
- directive('inner', valueFn({
- template: '
FooBar ',
- compile: function() {
- innerCompilationCount += 1;
- }
- }));
- });
+ inject(function($compile, $rootScope) {
+ element = $compile('
')($rootScope);
+ expect(innerCompilationCount).toBe(0);
+ transclude(function(child) { element.append(child); });
+ expect(innerCompilationCount).toBe(1);
+ expect(element.text()).toBe('FooBar');
+ });
+ });
- inject(function($compile, $rootScope) {
- element = $compile('
')($rootScope);
- expect(innerCompilationCount).toBe(0);
- transclude(function(child) { element.append(child); });
- expect(innerCompilationCount).toBe(1);
- expect(element.text()).toBe('FooBar');
- });
- });
+ it('should lazily compile transcluded directives with ngIf on them', function() {
+ var innerCompilationCount = 0, outerCompilationCount = 0, transclude;
- it('should lazily compile transcluded directives with ngIf on them', function() {
- var innerCompilationCount = 0, outerCompilationCount = 0, transclude;
+ module(function() {
+ directive('outer', valueFn({
+ transclude: true,
+ compile: function() {
+ outerCompilationCount += 1;
+ },
+ controller: function($transclude) {
+ transclude = $transclude;
+ }
+ }));
- module(function() {
- directive('outer', valueFn({
- transclude: true,
- compile: function() {
- outerCompilationCount += 1;
- },
- controller: function($transclude) {
- transclude = $transclude;
- }
- }));
+ directive('inner', valueFn({
+ template: '
FooBar ',
+ compile: function() {
+ innerCompilationCount += 1;
+ }
+ }));
+ });
- directive('inner', valueFn({
- template: '
FooBar ',
- compile: function() {
- innerCompilationCount += 1;
- }
- }));
- });
+ inject(function($compile, $rootScope) {
+ $rootScope.shouldCompile = false;
+
+ element = $compile('
')($rootScope);
+ expect(outerCompilationCount).toBe(0);
+ expect(innerCompilationCount).toBe(0);
+ expect(transclude).toBeUndefined();
+ $rootScope.$apply('shouldCompile=true');
+ expect(outerCompilationCount).toBe(1);
+ expect(innerCompilationCount).toBe(0);
+ expect(transclude).toBeDefined();
+ transclude(function(child) { element.append(child); });
+ expect(outerCompilationCount).toBe(1);
+ expect(innerCompilationCount).toBe(1);
+ expect(element.text()).toBe('FooBar');
+ });
+ });
- inject(function($compile, $rootScope) {
- $rootScope.shouldCompile = false;
+ it('should eagerly compile multiple directives with transclusion and templateUrl/replace', function() {
+ var innerCompilationCount = 0;
- element = $compile('
')($rootScope);
- expect(outerCompilationCount).toBe(0);
- expect(innerCompilationCount).toBe(0);
- expect(transclude).toBeUndefined();
- $rootScope.$apply('shouldCompile=true');
- expect(outerCompilationCount).toBe(1);
- expect(innerCompilationCount).toBe(0);
- expect(transclude).toBeDefined();
- transclude(function(child) { element.append(child); });
- expect(outerCompilationCount).toBe(1);
- expect(innerCompilationCount).toBe(1);
- expect(element.text()).toBe('FooBar');
- });
- });
+ module(function() {
+ directive('outer', valueFn({
+ transclude: true
+ }));
- it('should eagerly compile multiple directives with transclusion and templateUrl/replace', function() {
- var innerCompilationCount = 0;
+ directive('outer', valueFn({
+ templateUrl: 'inner.html',
+ replace: true
+ }));
- module(function() {
- directive('outer', valueFn({
- transclude: true
- }));
+ directive('inner', valueFn({
+ compile: function() {
+ innerCompilationCount += 1;
+ }
+ }));
+ });
- directive('outer', valueFn({
- templateUrl: 'inner.html',
- replace: true
- }));
+ inject(function($compile, $rootScope, $httpBackend) {
+ $httpBackend.expectGET('inner.html').respond('
');
+ element = $compile('
')($rootScope);
+ $httpBackend.flush();
- directive('inner', valueFn({
- compile: function() {
- innerCompilationCount += 1;
- }
- }));
+ expect(innerCompilationCount).toBe(1);
+ });
+ });
});
- inject(function($compile, $rootScope, $httpBackend) {
- $httpBackend.expectGET('inner.html').respond('
');
- element = $compile('
')($rootScope);
- $httpBackend.flush();
-
- expect(innerCompilationCount).toBe(1);
- });
});
});
-
});
-
describe('multi-slot transclude', function() {
it('should only include elements without a matching transclusion element in default transclusion slot', function() {
module(function() {
diff --git a/test/ng/directive/formSpec.js b/test/ng/directive/formSpec.js
index f878c4826070..e1d681956b23 100644
--- a/test/ng/directive/formSpec.js
+++ b/test/ng/directive/formSpec.js
@@ -290,7 +290,7 @@ describe('form', function() {
describe('triggering commit value on submit', function() {
it('should trigger update on form submit', function() {
var form = $compile(
- '
')(scope);
scope.$digest();
@@ -305,7 +305,7 @@ describe('form', function() {
it('should trigger update on form submit with nested forms', function() {
var form = $compile(
- '
')(scope);
scope.$digest();
@@ -342,7 +342,7 @@ describe('form', function() {
describe('rollback view value', function() {
it('should trigger rollback on form controls', function() {
var form = $compile(
- '
')(scope);
@@ -358,7 +358,7 @@ describe('form', function() {
it('should trigger rollback on form controls with nested forms', function() {
var form = $compile(
- '
' +
+ ' ' +
+ ' ')($rootScope);
+ var inputOptions = $rootScope.form.alias.$options;
+
+ expect(inputOptions.getOption('debounce')).toEqual($modelOptions.getOption('debounce'));
+ expect($modelOptions.getOption('updateOnDefault')).toBe(true);
+ expect(inputOptions.getOption('updateOnDefault')).toBe(false);
+ dealoc(form);
+ }));
+
+
it('should allow overriding the model update trigger event on text inputs', function() {
var inputElm = helper.compileInput(
'
b
c').toEqual('a
b
c');
});
+ it('should handle large datasets', function() {
+ // Large is non-trivial to quantify, but handling ~100,000 should be sufficient for most purposes.
+ var largeNumber = 17; // 2^17 = 131,072
+ var result = '
b
';
+ // Ideally we would use repeat, but that isn't supported in IE.
+ for (var i = 0; i < largeNumber; i++) {
+ result += result;
+ }
+ expectHTML('a' + result + 'c').toEqual('a' + result + 'c');
+ });
+
it('should remove style', function() {
expectHTML('ac.').toEqual('ac.');
});