You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by om...@apache.org on 2016/05/12 19:48:45 UTC

[1/6] cordova-cli git commit: Telemetry: 'cordova telemetry on' && 'cordova telemetry off'

Repository: cordova-cli
Updated Branches:
  refs/heads/master f0bb91849 -> 94190b841


Telemetry: 'cordova telemetry on' && 'cordova telemetry off'


Project: http://git-wip-us.apache.org/repos/asf/cordova-cli/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-cli/commit/330dea1a
Tree: http://git-wip-us.apache.org/repos/asf/cordova-cli/tree/330dea1a
Diff: http://git-wip-us.apache.org/repos/asf/cordova-cli/diff/330dea1a

Branch: refs/heads/master
Commit: 330dea1a17bc9c04562dd58e65da64975abc560d
Parents: eafb8b9
Author: Omar Mefire <om...@gmail.com>
Authored: Wed May 4 01:43:23 2016 -0700
Committer: Omar Mefire <om...@gmail.com>
Committed: Thu May 12 11:13:57 2016 -0700

----------------------------------------------------------------------
 src/cli.js       | 62 +++++++++++++++++++++++++++++++++++++++------------
 src/telemetry.js | 36 +++++++++++++++++++++++++-----
 2 files changed, 79 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/330dea1a/src/cli.js
----------------------------------------------------------------------
diff --git a/src/cli.js b/src/cli.js
index ac12f67..890f54a 100644
--- a/src/cli.js
+++ b/src/cli.js
@@ -30,7 +30,8 @@ var path = require('path'),
     _,
     updateNotifier,
     pkg = require('../package.json'),
-    telemetry = require('./telemetry');
+    telemetry = require('./telemetry'),
+    Q = require('q');
 
 var cordova_lib = require('cordova-lib'),
     CordovaError = cordova_lib.CordovaError,
@@ -81,14 +82,31 @@ function checkForUpdates() {
 }
 
 module.exports = function(inputArgs) {
-    // Telemetry Prompt: only shows up on first run
-    // If the user has not made any decision about telemetry yet,
-    // ... a timed prompt is shown(30 seconds), asking him whether or not he wants to opt-in.
-    // ... If the timeout expires without him having made any decisions, he is considered to have opted out.
     
-    // Note: The timed prompt can be prevented from being shown by setting an environment variable: CORDOVA_TELEMETRY_OPT_OUT
-    // ... This is useful in CI environments.
-    return telemetry.setup().then(function(isUserOptedIntoTelemetry) {
+    init();
+    
+    // If no inputArgs given, use process.argv.
+    inputArgs = inputArgs || process.argv;
+        
+    return Q().then(function() {
+        // Skip telemetry prompt when user runs: `cordova telemetry on | off`, `cordova telemetry ...`
+        var isTelemetryCmd = (function() {
+            return inputArgs[2] === 'telemetry';
+        })(inputArgs);
+        
+        if (isTelemetryCmd) {
+            return Q(telemetry.isOptedIn);
+        }
+
+        // Telemetry Prompt: only shows up on first run
+        // If the user has not made any decision about telemetry yet,
+        // ... a timed prompt is shown(30 seconds), asking him whether or not he wants to opt-in.
+        // ... If the timeout expires without him having made any decisions, he is considered to have opted out.
+
+        // Note: The timed prompt can be prevented from being shown by setting an environment variable: CORDOVA_TELEMETRY_OPT_OUT
+        // ... This is useful in CI environments.
+        return telemetry.setup();
+    }).then(function(isUserOptedIntoTelemetry) {
         return cli(inputArgs, isUserOptedIntoTelemetry);
     });
 };
@@ -134,11 +152,6 @@ function cli(inputArgs, isUserOptedIntoTelemetry) {
         , 't' : '--template'
         };
 
-    // If no inputArgs given, use process.argv.
-    inputArgs = inputArgs || process.argv;
-
-    init();
-
     checkForUpdates();
 
     var args = nopt(knownOpts, shortHands, inputArgs);
@@ -163,7 +176,7 @@ function cli(inputArgs, isUserOptedIntoTelemetry) {
     // are in a verbose mode.
     process.on('uncaughtException', function(err) {
         logger.error(err);
-        // Test this
+        // Test this: err could cause issues
         telemetry.track('uncaughtException', err);
         process.exit(1);
     });
@@ -211,6 +224,26 @@ function cli(inputArgs, isUserOptedIntoTelemetry) {
         }
         return help(remain);
     }
+    
+    // ToDO: Test this
+    // ToDO: Write console help
+    // ToDO: when running `cordova telemetry on|off`, don't show telemetry prompt
+    if (cmd === 'telemetry') {
+        if (undashed[1] === 'on') {
+            telemetry.turnOn();
+            if (isUserOptedIntoTelemetry) {
+                telemetry.track(cmd, 'on');
+            }
+        } else if (undashed[1] === 'off') {
+            telemetry.turnOff();
+            // Always track telemetry opt-outs whether user opted out or not!
+            telemetry.track('telemetry-opt-out', 'via-telemetry-cmd'); 
+        } else {
+            return help('telemetry'); // test this.
+        }
+
+        return Q();
+    }
 
     if ( !cordova.hasOwnProperty(cmd) ) {
         msg =
@@ -229,6 +262,7 @@ function cli(inputArgs, isUserOptedIntoTelemetry) {
         nohooks: args.nohooks || [],
         searchpath : args.searchpath
     };
+    
 
     if (cmd == 'emulate' || cmd == 'build' || cmd == 'prepare' || cmd == 'compile' || cmd == 'run' || cmd === 'clean') {
         // All options without dashes are assumed to be platform names

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/330dea1a/src/telemetry.js
----------------------------------------------------------------------
diff --git a/src/telemetry.js b/src/telemetry.js
index d05b696..0c40c71 100644
--- a/src/telemetry.js
+++ b/src/telemetry.js
@@ -34,7 +34,8 @@ var insight = new Insight({
     pkg: pkg
 });
 
-/**  Telemetry Prompt:
+/**
+ * Telemetry Prompt:
  * If the user has not made any decision about telemetry yet,
  * ... a timed prompt is shown, asking him whether or not he wants to opt-in.
  * ... If the timeout expires without him having made any decisions, he is considered to have opted out.
@@ -44,9 +45,10 @@ var insight = new Insight({
 
 @returns {Boolean} It returns true if the user has agreed to opt-in to telemetry, false otherwise
 */
-exports.setup = function setup() {
+function setup() {
     var deferred = Q.defer();
     
+    // ToDO: should we just rely on 'CI' env variable? (what are others doing?)
     var isInteractive = !process.env.CORDOVA_TELEMETRY_OPT_OUT && !process.env.CI;
     if(!isInteractive) {
         // Update user's config file to make sure telemetry doesn't get collected
@@ -67,7 +69,10 @@ exports.setup = function setup() {
         var msg = 'Privacy statement: http://docs.cordova.io/privacy-statement.html' + require('os').EOL +
                     'May cordova anonymously report usage statitics to improve the tool over time ?';
         insight.askPermission(msg, function(unused, optIn) {
-            track('telemetry-opt-out');
+            if(!optIn) {
+                // Always track telemetry opt-outs!
+                track('telemetry-opt-out', 'via-cli-prompt-choice');
+            }
             deferred.resolve(optIn /* same as !insight.optOut */);
         }, {
             optInByDefault: false // If prompt timeout expires, opt the user out of telemetry
@@ -79,11 +84,11 @@ exports.setup = function setup() {
     return deferred.promise;
 }
 
-exports.track = function track() {
+function track() {
     insight.track.apply(insight, arguments);
 }
 
-exports.trackEvent = function trackEvent(category, action, label, value) {
+function trackEvent(category, action, label, value) {
     insight.trackEvent({
         category: category,
         action: action,
@@ -91,3 +96,24 @@ exports.trackEvent = function trackEvent(category, action, label, value) {
         value: value
     });
 }
+
+function turnOn() {
+    insight.optOut = false;
+}
+
+function turnOff() {
+    insight.optOut = true;
+}
+
+function isOptedIn() {
+    return !insight.optOut;
+}
+
+module.exports = {
+    setup: setup,
+    track: track,
+    trackEvent: trackEvent,
+    turnOn: turnOn,
+    turnOff: turnOff,
+    isOptedIn: isOptedIn
+};
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


[2/6] cordova-cli git commit: Telemetry: The Foundational work

Posted by om...@apache.org.
Telemetry: The Foundational work


Project: http://git-wip-us.apache.org/repos/asf/cordova-cli/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-cli/commit/eafb8b9a
Tree: http://git-wip-us.apache.org/repos/asf/cordova-cli/tree/eafb8b9a
Diff: http://git-wip-us.apache.org/repos/asf/cordova-cli/diff/eafb8b9a

Branch: refs/heads/master
Commit: eafb8b9af1579b1f31a46bcb4c4e6a0aec8356d9
Parents: f0bb918
Author: Omar Mefire <om...@gmail.com>
Authored: Fri Apr 29 12:05:40 2016 -0700
Committer: Omar Mefire <om...@gmail.com>
Committed: Thu May 12 11:13:57 2016 -0700

----------------------------------------------------------------------
 package.json     |   3 +-
 src/cli.js       | 133 ++++++++++++++++++++++++++++++++++++--------------
 src/telemetry.js |  93 +++++++++++++++++++++++++++++++++++
 3 files changed, 191 insertions(+), 38 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/eafb8b9a/package.json
----------------------------------------------------------------------
diff --git a/package.json b/package.json
index 028fcd8..8a42b53 100644
--- a/package.json
+++ b/package.json
@@ -34,7 +34,8 @@
         "q": "1.0.1",
         "nopt": "3.0.1",
         "underscore": "1.7.0",
-        "update-notifier": "^0.5.0"
+        "update-notifier": "^0.5.0",
+        "insight": "~0.8.1"
     },
     "devDependencies": {
         "istanbul": "^0.3.4",

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/eafb8b9a/src/cli.js
----------------------------------------------------------------------
diff --git a/src/cli.js b/src/cli.js
index 301e913..ac12f67 100644
--- a/src/cli.js
+++ b/src/cli.js
@@ -29,7 +29,8 @@ var path = require('path'),
     nopt,
     _,
     updateNotifier,
-    pkg = require('../package.json');
+    pkg = require('../package.json'),
+    telemetry = require('./telemetry');
 
 var cordova_lib = require('cordova-lib'),
     CordovaError = cordova_lib.CordovaError,
@@ -79,8 +80,20 @@ function checkForUpdates() {
     }
 }
 
-module.exports = cli;
-function cli(inputArgs) {
+module.exports = function(inputArgs) {
+    // Telemetry Prompt: only shows up on first run
+    // If the user has not made any decision about telemetry yet,
+    // ... a timed prompt is shown(30 seconds), asking him whether or not he wants to opt-in.
+    // ... If the timeout expires without him having made any decisions, he is considered to have opted out.
+    
+    // Note: The timed prompt can be prevented from being shown by setting an environment variable: CORDOVA_TELEMETRY_OPT_OUT
+    // ... This is useful in CI environments.
+    return telemetry.setup().then(function(isUserOptedIntoTelemetry) {
+        return cli(inputArgs, isUserOptedIntoTelemetry);
+    });
+};
+
+function cli(inputArgs, isUserOptedIntoTelemetry) {
     // When changing command line arguments, update doc/help.txt accordingly.
     var knownOpts =
         { 'verbose' : Boolean
@@ -138,6 +151,10 @@ function cli(inputArgs) {
             toPrint += ' (cordova-lib@' + libVersion + ')';
         }
         console.log(toPrint);
+        if(isUserOptedIntoTelemetry) {
+            var cmd = 'version';
+            telemetry.track(cmd, args.version);
+        }
         return;
     }
 
@@ -146,6 +163,8 @@ function cli(inputArgs) {
     // are in a verbose mode.
     process.on('uncaughtException', function(err) {
         logger.error(err);
+        // Test this
+        telemetry.track('uncaughtException', err);
         process.exit(1);
     });
 
@@ -186,6 +205,10 @@ function cli(inputArgs) {
         if (!args.help && remain[0] == 'help') {
             remain.shift();
         }
+        if(isUserOptedIntoTelemetry) {
+            telemetry.track(cmd); 
+            telemetry.trackEvent('category', cmd);
+        }
         return help(remain);
     }
 
@@ -220,12 +243,25 @@ function cli(inputArgs) {
         opts.options = args;
         opts.options.argv = unparsedArgs;
 
-        if (cmd == 'run' && args.list && cordova.raw.targets) {
-            cordova.raw.targets.call(null, opts).done();
-            return;
+        if (cmd === 'run' && args.list && cordova.raw.targets) {
+            var result = cordova.raw.targets.call(null, opts);
+            return result.finally(function() {
+                if (isUserOptedIntoTelemetry) {
+                    telemetry.track(cmd, result.isFulfilled() ? 'successful' : 'unsuccessful');
+                    telemetry.trackEvent('category', cmd);
+                }
+                return result;
+            });
         }
 
-        cordova.raw[cmd].call(null, opts).done();
+        var result = cordova.raw[cmd].call(null, opts);
+        return result.finally(function() {
+            if (isUserOptedIntoTelemetry) {
+                telemetry.track(cmd, result.isFulfilled() ? 'successful' : 'unsuccessful');
+                telemetry.trackEvent('category', cmd);
+            }
+            return result;
+        });
     } else if (cmd === 'requirements') {
         // All options without dashes are assumed to be platform names
         opts.platforms = undashed.slice(1);
@@ -235,41 +271,58 @@ function cli(inputArgs) {
             throw new CordovaError(msg);
         }
 
-        cordova.raw[cmd].call(null, opts.platforms)
-        .then(function (platformChecks) {
-
-            var someChecksFailed = Object.keys(platformChecks).map(function (platformName) {
-                events.emit('log', '\nRequirements check results for ' + platformName + ':');
-                var platformCheck = platformChecks[platformName];
-                if (platformCheck instanceof CordovaError) {
-                    events.emit('warn', 'Check failed for ' + platformName + ' due to ' + platformCheck);
-                    return true;
-                }
+        var result = cordova.raw[cmd].call(null, opts.platforms)
+            .then(function(platformChecks) {
 
-                var someChecksFailed = false;
-                platformCheck.forEach(function (checkItem) {
-                    var checkSummary = checkItem.name + ': ' +
-                                    (checkItem.installed ? 'installed ' : 'not installed ') +
-                                    (checkItem.metadata.version || '');
-                    events.emit('log', checkSummary);
-                    if (!checkItem.installed) {
-                        someChecksFailed = true;
-                        events.emit('warn', checkItem.metadata.reason);
+                var someChecksFailed = Object.keys(platformChecks).map(function(platformName) {
+                    events.emit('log', '\nRequirements check results for ' + platformName + ':');
+                    var platformCheck = platformChecks[platformName];
+                    if (platformCheck instanceof CordovaError) {
+                        events.emit('warn', 'Check failed for ' + platformName + ' due to ' + platformCheck);
+                        return true;
                     }
+
+                    var someChecksFailed = false;
+                    platformCheck.forEach(function(checkItem) {
+                        var checkSummary = checkItem.name + ': ' +
+                            (checkItem.installed ? 'installed ' : 'not installed ') +
+                            (checkItem.metadata.version || '');
+                        events.emit('log', checkSummary);
+                        if (!checkItem.installed) {
+                            someChecksFailed = true;
+                            events.emit('warn', checkItem.metadata.reason);
+                        }
+                    });
+
+                    return someChecksFailed;
+                }).some(function(isCheckFailedForPlatform) {
+                    return isCheckFailedForPlatform;
                 });
 
-                return someChecksFailed;
-            }).some(function (isCheckFailedForPlatform) {
-                return isCheckFailedForPlatform;
+                if (someChecksFailed) throw new CordovaError('Some of requirements check failed');
             });
-
-            if (someChecksFailed) throw new CordovaError('Some of requirements check failed');
-        }).done();
+        return result.finally(function() {
+            if (isUserOptedIntoTelemetry) {
+                telemetry.track(cmd, result.isFulfilled() ? 'successful' : 'unsuccessful');
+            }
+            return result;
+        });   
     } else if (cmd == 'serve') {
         var port = undashed[1];
-        cordova.raw.serve(port).done();
+        var result = cordova.raw.serve(port);
+        return result.finally(function() {
+            if(isUserOptedIntoTelemetry) {
+                telemetry.track(cmd, result.isFulfilled() ? 'successful' : 'unsuccessful');
+            }
+        });
     } else if (cmd == 'create') {
-        create();
+        var result = create();
+        return result.finally(function() {
+            if (isUserOptedIntoTelemetry) {
+                telemetry.track(cmd, result.isFulfilled() ? 'successful' : 'unsuccessful');
+            }
+            return result;
+        });
     } else {
         // platform/plugins add/rm [target(s)]
         subcommand = undashed[1]; // sub-command like "add", "ls", "rm" etc.
@@ -297,7 +350,13 @@ function cli(inputArgs) {
                             , shrinkwrap: args.shrinkwrap || false
                             , force: args.force || false
                             };
-        cordova.raw[cmd](subcommand, targets, download_opts).done();
+        var result = cordova.raw[cmd](subcommand, targets, download_opts);
+        return result.finally(function() {
+            if (isUserOptedIntoTelemetry) {
+                telemetry.track(cmd, result.isFulfilled() ? 'successful' : 'unsuccessful');
+            }
+            return result;
+        });
     }
 
     function create() {
@@ -339,10 +398,10 @@ function cli(inputArgs) {
         }
 
         // create(dir, id, name, cfg)
-        cordova.raw.create( undashed[1]  // dir to create the project in
+        return cordova.raw.create( undashed[1]  // dir to create the project in
             , undashed[2]  // App id
             , undashed[3]  // App name
             , cfg
-        ).done();
+        );
     }
 }

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/eafb8b9a/src/telemetry.js
----------------------------------------------------------------------
diff --git a/src/telemetry.js b/src/telemetry.js
new file mode 100644
index 0000000..d05b696
--- /dev/null
+++ b/src/telemetry.js
@@ -0,0 +1,93 @@
+/**
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+*/
+
+/* jshint node:true, bitwise:true, undef:true, trailing:true, quotmark:true,
+          indent:4, unused:vars, latedef:nofunc,
+          laxcomma:true
+*/
+
+var path = require('path');
+var Q = require('q');
+
+var GOOGLE_ANALYTICS_TRACKING_ID = 'UA-64283057-7'; 
+
+var pkg = require('../package.json');
+var Insight = require('insight');
+var insight = new Insight({
+    trackingCode: GOOGLE_ANALYTICS_TRACKING_ID,
+    pkg: pkg
+});
+
+/**  Telemetry Prompt:
+ * If the user has not made any decision about telemetry yet,
+ * ... a timed prompt is shown, asking him whether or not he wants to opt-in.
+ * ... If the timeout expires without him having made any decisions, he is considered to have opted out.
+
+ * Note: The timed prompt can be prevented from being shown by setting an environment variable: CORDOVA_TELEMETRY_OPT_OUT
+ * ... This is useful in CI environments.
+
+@returns {Boolean} It returns true if the user has agreed to opt-in to telemetry, false otherwise
+*/
+exports.setup = function setup() {
+    var deferred = Q.defer();
+    
+    var isInteractive = !process.env.CORDOVA_TELEMETRY_OPT_OUT && !process.env.CI;
+    if(!isInteractive) {
+        // Update user's config file to make sure telemetry doesn't get collected
+        // This handles the case where user had previously opted-in, then 
+        // ... sets up environment variable to signify they want out
+        insight.optOut = true; 
+    }
+    
+    if (isInteractive && insight.optOut === undefined) {
+
+        // Note: insight.askPermission() won't display the permissions prompt if one of these is true:
+        //     - the process is not a TTY
+        //     - the process was started with --no-insight flag
+        //     - the CI environment variable is set 
+        // For further infos, see: https://github.com/yeoman/insight/blob/3a6ac613b7312272f9f10e1188310b199afa4e1d/lib/index.js#L133
+        
+        // ToDO: Fix link to privacy-statement
+        var msg = 'Privacy statement: http://docs.cordova.io/privacy-statement.html' + require('os').EOL +
+                    'May cordova anonymously report usage statitics to improve the tool over time ?';
+        insight.askPermission(msg, function(unused, optIn) {
+            track('telemetry-opt-out');
+            deferred.resolve(optIn /* same as !insight.optOut */);
+        }, {
+            optInByDefault: false // If prompt timeout expires, opt the user out of telemetry
+        });
+    } else {
+        deferred.resolve(!insight.optOut);
+    }
+    
+    return deferred.promise;
+}
+
+exports.track = function track() {
+    insight.track.apply(insight, arguments);
+}
+
+exports.trackEvent = function trackEvent(category, action, label, value) {
+    insight.trackEvent({
+        category: category,
+        action: action,
+        label: label,
+        value: value
+    });
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


[3/6] cordova-cli git commit: Telemetry: CLI Documentation

Posted by om...@apache.org.
Telemetry: CLI Documentation


Project: http://git-wip-us.apache.org/repos/asf/cordova-cli/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-cli/commit/50016c9c
Tree: http://git-wip-us.apache.org/repos/asf/cordova-cli/tree/50016c9c
Diff: http://git-wip-us.apache.org/repos/asf/cordova-cli/diff/50016c9c

Branch: refs/heads/master
Commit: 50016c9c8ebbbfea04066fb2ad219b2a4cae8240
Parents: 55df898
Author: Omar Mefire <om...@gmail.com>
Authored: Sun May 8 15:11:18 2016 -0700
Committer: Omar Mefire <om...@gmail.com>
Committed: Thu May 12 11:14:55 2016 -0700

----------------------------------------------------------------------
 doc/cordova.txt   | 11 ++++++++++-
 doc/telemetry.txt | 24 ++++++++++++++++++++++++
 src/cli.js        |  4 +++-
 src/telemetry.js  | 16 +++++++++++-----
 4 files changed, 48 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/50016c9c/doc/cordova.txt
----------------------------------------------------------------------
diff --git a/doc/cordova.txt b/doc/cordova.txt
index 164e81d..459fd65 100644
--- a/doc/cordova.txt
+++ b/doc/cordova.txt
@@ -23,6 +23,12 @@ Project Commands
     serve .............................. Run project with a local webserver
                                             (including prepare)
 
+Telemetry Commands
+    telemetry on ....................... Turn telemetry collection on
+    telemetry off ...................... Turn telemetry collection off 
+    <cordova-cmd> --no-telemetry ............... Turn telemetry collection off only for the command being run
+    For details, see our privacy notice: https://cordova.apache.org/privacy-notice.html                                           
+
 Learn more about command options using 'cordova-cli help <command>'
 
 Aliases
@@ -43,4 +49,7 @@ Examples
     cordova-cli requirements android    
     cordova-cli build android --verbose
     cordova-cli run android
-    cordova-cli build android --release -- --keystore="..\android.keystore" --storePassword=android --alias=mykey
\ No newline at end of file
+    cordova-cli build android --release -- --keystore="..\android.keystore" --storePassword=android --alias=mykey
+    cordova-cli telemetry on
+    cordova-cli telemetry off
+    cordova-cli build --no-telemetry
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/50016c9c/doc/telemetry.txt
----------------------------------------------------------------------
diff --git a/doc/telemetry.txt b/doc/telemetry.txt
new file mode 100644
index 0000000..2672ed5
--- /dev/null
+++ b/doc/telemetry.txt
@@ -0,0 +1,24 @@
+Synopsis
+
+    cordova-cli telemetry [STATE]
+    
+      STATE: on|off
+    
+Turns telemetry collection on or off
+    
+    on ....................... Turns telemetry collection on
+    off ...................... Turns telemetry collection off  
+
+Details
+    A timed prompt asking the user to opt-in or out is displayed the first time cordova is run.
+    It lasts for 30 seconds, after which the user is automatically opted-out if he doesn't provide any answer.
+    In CI environments, the `CI` environment variable can be set, which will prevent the prompt from showing up.
+    Telemetry collection can also be turned off on a single command by using the `--no-telemetry-flag`.
+
+Examples
+    cordova-cli telemetry on
+    cordova-cli telemetry off
+    cordova-cli build --no-telemetry
+
+For details, see our privacy notice: https://cordova.apache.org/privacy-notice.html 
+and the proposal: https://github.com/cordova/cordova-discuss/pull/43
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/50016c9c/src/cli.js
----------------------------------------------------------------------
diff --git a/src/cli.js b/src/cli.js
index 23d4ecf..9ed849f 100644
--- a/src/cli.js
+++ b/src/cli.js
@@ -246,12 +246,14 @@ function cli(inputArgs, shouldCollectTelemetry) {
             if (shouldCollectTelemetry) {
                 telemetry.track(cmd, 'on');
             }
+            console.log("Thanks for opting into telemetry to help us better cordova");
         } else if (undashed[1] === 'off') {
             telemetry.turnOff();
             // Always track telemetry opt-outs (whether user opted out or not!)
             telemetry.track('telemetry-opt-out', 'via-cordova-telemetry-off'); 
+            console.log("You have been opted out of telemetry. To change this, run: cordova telemetry on");
         } else {
-            return help('telemetry'); // test this.
+            return help(['telemetry']); 
         }
 
         return Q();

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/50016c9c/src/telemetry.js
----------------------------------------------------------------------
diff --git a/src/telemetry.js b/src/telemetry.js
index 77243c6..4505163 100644
--- a/src/telemetry.js
+++ b/src/telemetry.js
@@ -34,18 +34,24 @@ var insight = new Insight({
     pkg: pkg
 });
 
-
+/**
+ * Returns true if the user opted in, and false otherwise
+ */
 function showPrompt() {
-    
+
     var deferred = Q.defer();
     
     var msg = 'Do you want to prevent cordova from anonymously collecting usage statitics to improve the tool over time ?';
-    insight.askPermission(msg, function (unused, optIn) {
-        if (!optIn) {
+    insight.askPermission(msg, function (unused, optOut) {
+        if (optOut) {
+            console.log("You have been opted out of telemetry. To change this, run: cordova telemetry on");
             // Always track telemetry opt-outs! (whether opted-in or opted-out)
             track('telemetry-opt-out', 'via-cli-prompt-choice');
+        } else {
+            console.log("Thanks for opting into telemetry to help us better cordova");
         }
-        deferred.resolve(optIn /* same as !insight.optOut */);
+
+        deferred.resolve(!optOut); 
     });
     
     return deferred.promise;


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


[6/6] cordova-cli git commit: Telemetry: Update README.md documentation

Posted by om...@apache.org.
Telemetry: Update README.md documentation

 This closes #247


Project: http://git-wip-us.apache.org/repos/asf/cordova-cli/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-cli/commit/94190b84
Tree: http://git-wip-us.apache.org/repos/asf/cordova-cli/tree/94190b84
Diff: http://git-wip-us.apache.org/repos/asf/cordova-cli/diff/94190b84

Branch: refs/heads/master
Commit: 94190b8417e863a0d7a1aaf9a95a726f786229de
Parents: 39e5f17
Author: Omar Mefire <om...@gmail.com>
Authored: Thu May 12 12:41:47 2016 -0700
Committer: Omar Mefire <om...@gmail.com>
Committed: Thu May 12 12:47:32 2016 -0700

----------------------------------------------------------------------
 doc/readme.md | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/94190b84/doc/readme.md
----------------------------------------------------------------------
diff --git a/doc/readme.md b/doc/readme.md
index 4383359..7149873 100644
--- a/doc/readme.md
+++ b/doc/readme.md
@@ -629,6 +629,21 @@ cordova telemetry [STATE]
 | on          | Turn telemetry collection on.
 | off         | Turn telemetry collection off.
 
+### Details
+ A timed prompt asking the user to opt-in or out is displayed the first time cordova is run.
+ It lasts for 30 seconds, after which the user is automatically opted-out if he doesn't provide any answer.
+ In CI environments, the `CI` environment variable can be set, which will prevent the prompt from showing up.
+ Telemetry collection can also be turned off on a single command by using the `--no-telemetry` flag.
+
+### Examples
+```
+cordova telemetry on
+cordova telemetry off
+cordova build --no-telemetry
+```
+
+For details, see our privacy notice: https://cordova.apache.org/privacy
+
 ## cordova help command
 
 ### Synopsis


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


[5/6] cordova-cli git commit: Telemetry: Refactor telemetry calls into a single spot, Change prompt, More documentation, etc...

Posted by om...@apache.org.
Telemetry: Refactor telemetry calls into a single spot, Change prompt, More documentation, etc...


Project: http://git-wip-us.apache.org/repos/asf/cordova-cli/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-cli/commit/39e5f17c
Tree: http://git-wip-us.apache.org/repos/asf/cordova-cli/tree/39e5f17c
Diff: http://git-wip-us.apache.org/repos/asf/cordova-cli/diff/39e5f17c

Branch: refs/heads/master
Commit: 39e5f17cd91c4990a98deec02743de4e3371874b
Parents: 50016c9
Author: Omar Mefire <om...@gmail.com>
Authored: Mon May 9 19:41:02 2016 -0700
Committer: Omar Mefire <om...@gmail.com>
Committed: Thu May 12 11:14:55 2016 -0700

----------------------------------------------------------------------
 doc/cordova.txt   |  12 +---
 doc/readme.md     |  18 ++++++
 doc/telemetry.txt |   5 +-
 package.json      |   2 +-
 spec/cli.spec.js  | 156 +++++++++++++---------------------------------
 src/cli.js        | 165 +++++++++++++++++++++++++------------------------
 src/telemetry.js  |  35 +++++------
 7 files changed, 166 insertions(+), 227 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/39e5f17c/doc/cordova.txt
----------------------------------------------------------------------
diff --git a/doc/cordova.txt b/doc/cordova.txt
index 459fd65..630d5d4 100644
--- a/doc/cordova.txt
+++ b/doc/cordova.txt
@@ -5,6 +5,7 @@ Synopsis
 Global Commands
     create ............................. Create a project
     help ............................... Get help for a command
+    telemetry .......................... Turn telemetry collection on or off
 
 Project Commands
     info ............................... Generate project information
@@ -23,12 +24,6 @@ Project Commands
     serve .............................. Run project with a local webserver
                                             (including prepare)
 
-Telemetry Commands
-    telemetry on ....................... Turn telemetry collection on
-    telemetry off ...................... Turn telemetry collection off 
-    <cordova-cmd> --no-telemetry ............... Turn telemetry collection off only for the command being run
-    For details, see our privacy notice: https://cordova.apache.org/privacy-notice.html                                           
-
 Learn more about command options using 'cordova-cli help <command>'
 
 Aliases
@@ -49,7 +44,4 @@ Examples
     cordova-cli requirements android    
     cordova-cli build android --verbose
     cordova-cli run android
-    cordova-cli build android --release -- --keystore="..\android.keystore" --storePassword=android --alias=mykey
-    cordova-cli telemetry on
-    cordova-cli telemetry off
-    cordova-cli build --no-telemetry
\ No newline at end of file
+    cordova-cli build android --release -- --keystore="..\android.keystore" --storePassword=android --alias=mykey
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/39e5f17c/doc/readme.md
----------------------------------------------------------------------
diff --git a/doc/readme.md b/doc/readme.md
index 1321dc2..4383359 100644
--- a/doc/readme.md
+++ b/doc/readme.md
@@ -40,6 +40,7 @@ These commands are available at all times.
 |----------|--------------
 | create | Create a project
 | help <command> | Get help for a command
+| telemetry | Turn telemetry collection on or off
 
 ## Project Command List
 
@@ -611,6 +612,23 @@ Run a local web server for www/ assets using specified `port` or default of 8000
 cordova serve [port]
 ```
 
+## cordova telemetry command
+
+### Synopsis
+
+Turns telemetry collection on or off.
+
+### Syntax
+
+```
+cordova telemetry [STATE]
+```
+
+| Option      | Description
+|-------------|------------------
+| on          | Turn telemetry collection on.
+| off         | Turn telemetry collection off.
+
 ## cordova help command
 
 ### Synopsis

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/39e5f17c/doc/telemetry.txt
----------------------------------------------------------------------
diff --git a/doc/telemetry.txt b/doc/telemetry.txt
index 2672ed5..40ac9a4 100644
--- a/doc/telemetry.txt
+++ b/doc/telemetry.txt
@@ -13,12 +13,11 @@ Details
     A timed prompt asking the user to opt-in or out is displayed the first time cordova is run.
     It lasts for 30 seconds, after which the user is automatically opted-out if he doesn't provide any answer.
     In CI environments, the `CI` environment variable can be set, which will prevent the prompt from showing up.
-    Telemetry collection can also be turned off on a single command by using the `--no-telemetry-flag`.
+    Telemetry collection can also be turned off on a single command by using the `--no-telemetry` flag.
 
 Examples
     cordova-cli telemetry on
     cordova-cli telemetry off
     cordova-cli build --no-telemetry
 
-For details, see our privacy notice: https://cordova.apache.org/privacy-notice.html 
-and the proposal: https://github.com/cordova/cordova-discuss/pull/43
\ No newline at end of file
+For details, see our privacy notice: https://cordova.apache.org/privacy
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/39e5f17c/package.json
----------------------------------------------------------------------
diff --git a/package.json b/package.json
index 8a42b53..a5c788a 100644
--- a/package.json
+++ b/package.json
@@ -35,7 +35,7 @@
         "nopt": "3.0.1",
         "underscore": "1.7.0",
         "update-notifier": "^0.5.0",
-        "insight": "~0.8.1"
+        "insight": "~0.8.2"
     },
     "devDependencies": {
         "istanbul": "^0.3.4",

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/39e5f17c/spec/cli.spec.js
----------------------------------------------------------------------
diff --git a/spec/cli.spec.js b/spec/cli.spec.js
index c8b1e9a..011734d 100644
--- a/spec/cli.spec.js
+++ b/spec/cli.spec.js
@@ -57,32 +57,23 @@ describe("cordova cli", function () {
             });
             
             it("will spit out the version with -v", function (done) {
-                cli(["node", "cordova", "-v"]).then(function() {
+                cli(["node", "cordova", "-v"], function() {
                     expect(console.log.mostRecentCall.args[0]).toMatch(version);
                     done();
-                }).fail(function() {
-                    expect(true).toBe(false);
-                    done();
                 });
             });
 
             it("will spit out the version with --version", function (done) {
-                cli(["node", "cordova", "--version"]).then(function() {
+                cli(["node", "cordova", "--version"], function () {
                     expect(console.log.mostRecentCall.args[0]).toMatch(version);
-                    done();
-                }).fail(function() {
-                    assert(true).toBe(false);
-                    done();
+                    done()
                 });
             });
 
             it("will spit out the version with -v anywhere", function (done) {
-                cli(["node", "cordova", "one", "-v", "three"]).then(function() {
+                cli(["node", "cordova", "one", "-v", "three"], function () {
                     expect(console.log.mostRecentCall.args[0]).toMatch(version);
                     done();
-                }).fail(function() {
-                    expect(true).toBe(false);
-                    done();
                 });
             });
         });
@@ -94,61 +85,43 @@ describe("cordova cli", function () {
         });
 
         it("will call command with all arguments passed through", function (done) {
-            cli(["node", "cordova", "build", "blackberry10", "--", "-k", "abcd1234"]).then(function () {
-                expect(cordova.raw.build).toHaveBeenCalledWith({ platforms: ['blackberry10'], options: { argv: ['-k', 'abcd1234'] }, verbose: false, silent: false, browserify: false, nohooks: [], searchpath: undefined });
-                done();
-            }).fail(function () {
-                expect(true).toBe(false);
+            cli(["node", "cordova", "build", "blackberry10", "--", "-k", "abcd1234"], function () {
+                expect(cordova.raw.build).toHaveBeenCalledWith({ platforms: ['blackberry10'], options: { argv: ['-k', 'abcd1234'] }, verbose: false, silent: false, browserify: false, nohooks: [], searchpath: undefined, fetch: false });
                 done();
             });
         });
 
         it("will consume the first instance of -d", function (done) {
-            cli(["node", "cordova", "-d", "build", "blackberry10", "--", "-k", "abcd1234", "-d"]).then(function () {
-                expect(cordova.raw.build).toHaveBeenCalledWith({ platforms: ['blackberry10'], options: { verbose: true, argv: ['-k', 'abcd1234', '-d'] }, verbose: true, silent: false, browserify: false, nohooks: [], searchpath: undefined });
-                done();
-            }).fail(function () {
-                expect(true).toBe(false);
+            cli(["node", "cordova", "-d", "build", "blackberry10", "--", "-k", "abcd1234", "-d"], function () {
+                expect(cordova.raw.build).toHaveBeenCalledWith({ platforms: ['blackberry10'], options: { verbose: true, argv: ['-k', 'abcd1234', '-d'] }, verbose: true, silent: false, browserify: false, nohooks: [], searchpath: undefined, fetch: false });
                 done();
             });
         });
 
         it("will consume the first instance of --verbose", function (done) {
-            cli(["node", "cordova", "--verbose", "build", "blackberry10", "--", "-k", "abcd1234", "--verbose"]).then(function () {
-                expect(cordova.raw.build).toHaveBeenCalledWith({ platforms: ['blackberry10'], options: { verbose: true, argv: ['-k', 'abcd1234', '--verbose'] }, verbose: true, silent: false, browserify: false, nohooks: [], searchpath: undefined });
-                done();
-            }).fail(function () {
-                expect(true).toBe(false);
+            cli(["node", "cordova", "--verbose", "build", "blackberry10", "--", "-k", "abcd1234", "--verbose"], function () {
+                expect(cordova.raw.build).toHaveBeenCalledWith({ platforms: ['blackberry10'], options: { verbose: true, argv: ['-k', 'abcd1234', '--verbose'] }, verbose: true, silent: false, browserify: false, nohooks: [], searchpath: undefined, fetch: false });
                 done();
             });
         });
 
         it("will consume the first instance of either --verbose or -d", function (done) {
-            cli(["node", "cordova", "--verbose", "build", "blackberry10", "--", "-k", "abcd1234", "-d"]).then(function () {
-                expect(cordova.raw.build).toHaveBeenCalledWith({ platforms: ['blackberry10'], options: { verbose: true, argv: ['-k', 'abcd1234', '-d'] }, verbose: true, silent: false, browserify: false, nohooks: [], searchpath: undefined });
-                done();
-            }).fail(function () {
-                expect(true).toBe(false);
+            cli(["node", "cordova", "--verbose", "build", "blackberry10", "--", "-k", "abcd1234", "-d"], function () {
+                expect(cordova.raw.build).toHaveBeenCalledWith({ platforms: ['blackberry10'], options: { verbose: true, argv: ['-k', 'abcd1234', '-d'] }, verbose: true, silent: false, browserify: false, nohooks: [], searchpath: undefined, fetch: false });
                 done();
             });
         });
 
         it("will consume the first instance of either --verbose or -d", function (done) {
-            cli(["node", "cordova", "-d", "build", "blackberry10", "--", "-k", "abcd1234", "--verbose"]).then(function () {
-                expect(cordova.raw.build).toHaveBeenCalledWith({ platforms: ['blackberry10'], options: { verbose: true, argv: ['-k', 'abcd1234', '--verbose'] }, verbose: true, silent: false, browserify: false, nohooks: [], searchpath: undefined });
-                done();
-            }).fail(function () {
-                expect(true).toBe(false);
+            cli(["node", "cordova", "-d", "build", "blackberry10", "--", "-k", "abcd1234", "--verbose"], function () {
+                expect(cordova.raw.build).toHaveBeenCalledWith({ platforms: ['blackberry10'], options: { verbose: true, argv: ['-k', 'abcd1234', '--verbose'] }, verbose: true, silent: false, browserify: false, nohooks: [], searchpath: undefined, fetch: false });
                 done();
             });
         });
 
         it("will consume the first instance of --silent", function (done) {
-            cli(["node", "cordova", "--silent", "build", "blackberry10", "--", "-k", "abcd1234", "--silent"]).then(function () {
-                expect(cordova.raw.build).toHaveBeenCalledWith({ platforms: ['blackberry10'], options: { silent: true, argv: ['-k', 'abcd1234', '--silent'] }, verbose: false, silent: true, browserify: false, nohooks: [], searchpath: undefined });
-                done();
-            }).fail(function () {
-                expect(true).toBe(false);
+            cli(["node", "cordova", "--silent", "build", "blackberry10", "--", "-k", "abcd1234", "--silent"], function () {
+                expect(cordova.raw.build).toHaveBeenCalledWith({ platforms: ['blackberry10'], options: { silent: true, argv: ['-k', 'abcd1234', '--silent'] }, verbose: false, silent: true, browserify: false, nohooks: [], searchpath: undefined, fetch: false });
                 done();
             });
         });
@@ -161,12 +134,9 @@ describe("cordova cli", function () {
         });
 
         it("calls cordova raw create", function (done) {
-            cli(["node", "cordova", "create", "a", "b", "c", "--link-to", "c:\\personalWWW"]).then(function () {
+            cli(["node", "cordova", "create", "a", "b", "c", "--link-to", "c:\\personalWWW"], function () {
                 expect(cordova.raw.create).toHaveBeenCalledWith("a", "b", "c", jasmine.any(Object));
                 done();
-            }).fail(function () {
-                expect(true).toBe(false);
-                done();
             });
         });
     });
@@ -177,7 +147,7 @@ describe("cordova cli", function () {
         });
 
         it("will pass variables", function (done) {
-            cli(["node", "cordova", "plugin", "add", "facebook", "--variable", "FOO=foo"]).then(function () {
+            cli(["node", "cordova", "plugin", "add", "facebook", "--variable", "FOO=foo"], function () {
                 expect(cordova.raw.plugin).toHaveBeenCalledWith(
                     "add",
                     ["facebook"],
@@ -186,15 +156,11 @@ describe("cordova cli", function () {
                 var opts = cordova.raw.plugin.calls[0].args[2];
                 expect(opts.cli_variables.FOO).toBe('foo');
                 done();
-            }).fail(function() {
-                expect(true).toBe(false);
-                done();
             });
-
         });
 
         it("will  support variables with =", function (done) {
-            cli(["node", "cordova", "plugin", "add", "facebook", "--variable", "MOTO=DELTA=WAS=HERE"]).then(function () {
+            cli(["node", "cordova", "plugin", "add", "facebook", "--variable", "MOTO=DELTA=WAS=HERE"], function () {
                 expect(cordova.raw.plugin).toHaveBeenCalledWith(
                     "add",
                     ["facebook"],
@@ -203,14 +169,11 @@ describe("cordova cli", function () {
                 var opts = cordova.raw.plugin.calls[0].args[2];
                 expect(opts.cli_variables.MOTO).toBe('DELTA=WAS=HERE');
                 done();
-            }).fail(function () {
-                expect(true).toBe(false);
-                done();
             });
         });
 
         it("will pass hook patterns to suppress", function (done) {
-            cli(["node", "cordova", "plugin", "add", "facebook", "--nohooks", "before_plugin_add"]).then(function () {
+            cli(["node", "cordova", "plugin", "add", "facebook", "--nohooks", "before_plugin_add"], function () {
                 expect(cordova.raw.plugin).toHaveBeenCalledWith(
                     "add",
                     ["facebook"],
@@ -219,10 +182,7 @@ describe("cordova cli", function () {
                 var opts = cordova.raw.plugin.calls[0].args[2];
                 expect(opts.nohooks[0]).toBe("before_plugin_add");
                 done();
-            }).fail(function () {
-                expect(true).toBe(false);
-                done();
-            });  
+            });
         });
 
     });
@@ -234,15 +194,12 @@ describe("cordova cli", function () {
                wasPromptShown = true;
            });
 
-           cli(["node", "cordova", "telemetry", "on"]).then(function (done) {
-               return cli(["node", "cordova", "telemetry", "off"])
-           }).then(function () {
-               expect(wasPromptShown).toBeFalsy();
-               done();
-           }).fail(function () {
-               expect(true).toBe(false);
-               done();
-           });           
+           cli(["node", "cordova", "telemetry", "on"], function () {
+               cli(["node", "cordova", "telemetry", "off"], function () {
+                   expect(wasPromptShown).toBeFalsy();
+                   done();
+               });
+           });         
        });
        
        it("is NOT collected when user runs 'cordova telemetry on' while NOT opted-in", function(done) {
@@ -251,13 +208,10 @@ describe("cordova cli", function () {
            
            spyOn(telemetry, "track");
            
-           cli(["node", "cordova", "telemetry", "on"]).then(function () {
+           cli(["node", "cordova", "telemetry", "on"], function () {
                expect(telemetry.track).not.toHaveBeenCalled();
                done();
-           }).fail(function () {
-               expect(true).toBe(false);
-               done();
-           });  
+           });
        });
        
        it("is collected when user runs 'cordova telemetry off' while opted-in", function(done) {
@@ -266,13 +220,10 @@ describe("cordova cli", function () {
            
            spyOn(telemetry, "track");
            
-           cli(["node", "cordova", "telemetry", "off"]).then(function () {
-               expect(telemetry.track).toHaveBeenCalledWith("telemetry-opt-out", "via-cordova-telemetry-off");
+           cli(["node", "cordova", "telemetry", "off"], function () {
+               expect(telemetry.track).toHaveBeenCalledWith("telemetry", "off", "via-cordova-telemetry-cmd", "successful");
                done();
-           }).fail(function () {
-               expect(true).toBe(false);
-               done();
-           });  
+           });
        });
        
        it("shows prompt if user neither opted in or out yet", function(done) {
@@ -283,12 +234,9 @@ describe("cordova cli", function () {
            spyOn(telemetry, "isNoTelemetryFlag").andReturn(false);
            spyOn(telemetry, "showPrompt").andReturn(Q(false));
            
-           return cli(["node", "cordova", "prepare"]).then(function() {
+           cli(["node", "cordova", "prepare"], function () {
                expect(telemetry.showPrompt).toHaveBeenCalled();
                done();
-           }).fail(function() {
-               expect(true).toBe(false);
-               done();
            });
        });
 
@@ -302,12 +250,9 @@ describe("cordova cli", function () {
            spyOn(telemetry, "isCI").andReturn(false);
            spyOn(telemetry, "track");
            
-           cli(["node", "cordova", "--version"]).then(function() {
+           cli(["node", "cordova", "--version"], function () {
                expect(telemetry.isOptedIn()).toBeFalsy();
-               expect(telemetry.track).toHaveBeenCalledWith('telemetry-opt-out', 'via-cli-prompt-choice');
-               done();
-           }).fail(function() {
-               expect(true).toBe(false);
+               expect(telemetry.track).toHaveBeenCalledWith("telemetry", "off", "via-cli-prompt-choice", "successful");
                done();
            });
        }/*, 45000*/);
@@ -320,13 +265,10 @@ describe("cordova cli", function () {
            spyOn(telemetry, "showPrompt");
            spyOn(telemetry, "track");
            
-           cli(["node", "cordova", "--version"]).then(function() {
+           cli(["node", "cordova", "--version"], function () {
                expect(telemetry.showPrompt).not.toHaveBeenCalled();
                expect(telemetry.track).not.toHaveBeenCalled();
                done();
-           }).fail(function() {
-               expect(true).toBe(false);
-               done();
            });
        });
        
@@ -338,13 +280,10 @@ describe("cordova cli", function () {
            spyOn(telemetry, "showPrompt");
            spyOn(telemetry, "track");
            
-           cli(["node", "cordova", "--version", "--no-telemetry"]).then(function() {
+           cli(["node", "cordova", "--version", "--no-telemetry"], function () {
                expect(telemetry.showPrompt).not.toHaveBeenCalled();
                expect(telemetry.track).not.toHaveBeenCalled();
                done();
-           }).fail(function() {
-               expect(true).toBe(false);
-               done();
            });
        });
        
@@ -356,13 +295,10 @@ describe("cordova cli", function () {
            spyOn(telemetry, "showPrompt");
            spyOn(telemetry, "track");
            
-           cli(["node", "cordova", "--version"]).then(function() {
+           cli(["node", "cordova", "--version"], function () {
                expect(telemetry.showPrompt).not.toHaveBeenCalled();
                expect(telemetry.track).not.toHaveBeenCalled();
                done();
-           }).fail(function() {
-               expect(true).toBe(false);
-               done();
            });
        });
        
@@ -374,13 +310,10 @@ describe("cordova cli", function () {
            spyOn(telemetry, "showPrompt");
            spyOn(telemetry, "track");
            
-           cli(["node", "cordova", "--version"]).then(function() {
+           cli(["node", "cordova", "--version"], function () {
                expect(telemetry.showPrompt).not.toHaveBeenCalled();
                expect(telemetry.track).toHaveBeenCalled();
                done();
-           }).fail(function() {
-               expect(true).toBe(false);
-               done();
            });
        });
        
@@ -391,15 +324,12 @@ describe("cordova cli", function () {
            spyOn(telemetry, "track");
 
            expect(telemetry.isOptedIn()).toBeFalsy();
-           
-           cli(["node", "cordova", "telemetry", "off"]).then(function() {
+
+           cli(["node", "cordova", "telemetry", "off"], function () {
                expect(telemetry.isOptedIn()).toBeFalsy();
-               expect(telemetry.track).toHaveBeenCalledWith("telemetry-opt-out", "via-cordova-telemetry-off");
+               expect(telemetry.track).toHaveBeenCalledWith("telemetry", "off", "via-cordova-telemetry-cmd", "successful");
                done();
-           }).fail(function() {
-               expect(true).toBe(false);
-               done();
-           });;
+           });
        });
     });
 });

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/39e5f17c/src/cli.js
----------------------------------------------------------------------
diff --git a/src/cli.js b/src/cli.js
index 9ed849f..91b918f 100644
--- a/src/cli.js
+++ b/src/cli.js
@@ -81,17 +81,32 @@ function checkForUpdates() {
     }
 }
 
-module.exports = function(inputArgs) {
+var shouldCollectTelemetry = false;
+module.exports = function (inputArgs, cb) {
+    
+    /**
+     * mainly used for testing.
+     */
+    cb = cb || function(){};
     
     init();
     
     // If no inputArgs given, use process.argv.
     inputArgs = inputArgs || process.argv;
-        
-    return Q().then(function() {
+    var cmd = inputArgs[2]; // e.g: inputArgs= 'node cordova run ios'
+    var isTelemetryCmd = (cmd === 'telemetry');
+
+    // ToDO: Move nopt-based parsing of args up here
+    if(cmd === '--version' || cmd === '-v') {
+        cmd = 'version';
+    } else if(!cmd || cmd === '--help' || cmd === 'h') {
+        cmd = 'help';
+    }
+            
+    Q().then(function() {
         
         /**
-         * 1- Skip telemetry prompt if:
+         * Skip telemetry prompt if:
          * - CI environment variable is present
          * - Command is run with `--no-telemetry` flag
          * - Command ran is: `cordova telemetry on | off | ...`
@@ -102,30 +117,79 @@ module.exports = function(inputArgs) {
         }
         
         /**
-         * 2- We shouldn't prompt for telemetry if user issues a command of the form: `cordova telemetry on | off | ...x`
+         * We shouldn't prompt for telemetry if user issues a command of the form: `cordova telemetry on | off | ...x`
+         * Also, if the user has already been prompted and made a decision, use his saved answer
          */
-        var isTelemetryCmd = inputArgs[2] === 'telemetry';
         if(isTelemetryCmd) {
-            return Q(telemetry.isOptedIn());
+            var subcommand = inputArgs[3];
+            var isOptedIn = telemetry.isOptedIn();
+            return handleTelemetryCmd(subcommand, isOptedIn);
         }
         
-        // 3- If user has already been prompted and made a decision, use his saved answer
         if(telemetry.hasUserOptedInOrOut()) {
             return Q(telemetry.isOptedIn());
         }
         
         /**
-         * 4- Otherwise, prompt user to opt-in or out
+         * Otherwise, prompt user to opt-in or out
          * Note: the prompt is shown for 30 seconds. If no choice is made by that time, User is considered to have opted out.
          */
         return telemetry.showPrompt();
-        
-    }).then(function(shouldCollectTelemetry) { 
-        cli(inputArgs, shouldCollectTelemetry);
-    });
+    }).then(function (collectTelemetry) {
+        shouldCollectTelemetry = collectTelemetry;
+        if(isTelemetryCmd) {
+            return Q();
+        }
+        return cli(inputArgs);
+    }).then(function () {
+        if (shouldCollectTelemetry && !isTelemetryCmd) {
+            telemetry.track(cmd, 'successful');
+        }
+        // call cb with error as arg if something failed
+        cb(null);
+    }).fail(function (err) {
+        if (shouldCollectTelemetry && !isTelemetryCmd) {
+            telemetry.track(cmd, 'unsuccessful');
+        }
+        // call cb with error as arg if something failed
+        cb(err);
+        throw err;
+    }).done();
 };
 
-function cli(inputArgs, shouldCollectTelemetry) {
+function handleTelemetryCmd(subcommand, isOptedIn) {
+    var turnOn = subcommand === 'on' ? true : false;
+    var cmdSuccess = true;
+
+    // turn telemetry on or off
+    try {
+        if (turnOn) {
+            telemetry.turnOn();
+            console.log("Thanks for opting into telemetry to help us improve cordova.");
+        } else {
+            telemetry.turnOff();
+            console.log("You have been opted out of telemetry. To change this, run: cordova telemetry on.");
+        }
+    } catch (ex) {
+        cmdSuccess = false;
+    }
+
+    // track or not track ?, that is the question
+
+    if (!turnOn) {
+        // Always track telemetry opt-outs (whether user opted out or not!)
+        telemetry.track('telemetry', 'off', 'via-cordova-telemetry-cmd', cmdSuccess ? 'successful': 'unsuccessful');
+        return Q();
+    }
+    
+    if(isOptedIn) {
+        telemetry.track('telemetry', 'on', 'via-cordova-telemetry-cmd', cmdSuccess ? 'successful' : 'unsuccessful');
+    }
+    
+    return Q();
+}
+
+function cli(inputArgs) {
     // When changing command line arguments, update doc/help.txt accordingly.
     var knownOpts =
         { 'verbose' : Boolean
@@ -178,10 +242,6 @@ function cli(inputArgs, shouldCollectTelemetry) {
             toPrint += ' (cordova-lib@' + libVersion + ')';
         }
         console.log(toPrint);
-        if(shouldCollectTelemetry) {
-            var cmd = 'version';
-            telemetry.track(cmd, args.version);
-        }
         return Q();
     }
 
@@ -234,30 +294,8 @@ function cli(inputArgs, shouldCollectTelemetry) {
         if (!args.help && remain[0] == 'help') {
             remain.shift();
         }
-        if(shouldCollectTelemetry) {
-            telemetry.track(cmd); 
-        }
         return help(remain);
     }
-    
-    if (cmd === 'telemetry') {
-        if (undashed[1] === 'on') {
-            telemetry.turnOn();
-            if (shouldCollectTelemetry) {
-                telemetry.track(cmd, 'on');
-            }
-            console.log("Thanks for opting into telemetry to help us better cordova");
-        } else if (undashed[1] === 'off') {
-            telemetry.turnOff();
-            // Always track telemetry opt-outs (whether user opted out or not!)
-            telemetry.track('telemetry-opt-out', 'via-cordova-telemetry-off'); 
-            console.log("You have been opted out of telemetry. To change this, run: cordova telemetry on");
-        } else {
-            return help(['telemetry']); 
-        }
-
-        return Q();
-    }
 
     if ( !cordova.hasOwnProperty(cmd) ) {
         msg =
@@ -292,22 +330,10 @@ function cli(inputArgs, shouldCollectTelemetry) {
         opts.options.argv = unparsedArgs;
 
         if (cmd === 'run' && args.list && cordova.raw.targets) {
-            var result = cordova.raw.targets.call(null, opts);
-            return result.finally(function() {
-                if (shouldCollectTelemetry) {
-                    telemetry.track(cmd, result.isFulfilled() ? 'successful' : 'unsuccessful');
-                }
-                return result;
-            });
+            return cordova.raw.targets.call(null, opts);
         }
 
-        var result = cordova.raw[cmd].call(null, opts);
-        return result.finally(function() {
-            if (shouldCollectTelemetry) {
-                telemetry.track(cmd, result.isFulfilled() ? 'successful' : 'unsuccessful');
-            }
-            return result;
-        });
+        return cordova.raw[cmd].call(null, opts);
     } else if (cmd === 'requirements') {
         // All options without dashes are assumed to be platform names
         opts.platforms = undashed.slice(1);
@@ -317,7 +343,7 @@ function cli(inputArgs, shouldCollectTelemetry) {
             throw new CordovaError(msg);
         }
 
-        var result = cordova.raw[cmd].call(null, opts.platforms)
+        return cordova.raw[cmd].call(null, opts.platforms)
             .then(function(platformChecks) {
 
                 var someChecksFailed = Object.keys(platformChecks).map(function(platformName) {
@@ -347,28 +373,11 @@ function cli(inputArgs, shouldCollectTelemetry) {
 
                 if (someChecksFailed) throw new CordovaError('Some of requirements check failed');
             });
-        return result.finally(function() {
-            if (shouldCollectTelemetry) {
-                telemetry.track(cmd, result.isFulfilled() ? 'successful' : 'unsuccessful');
-            }
-            return result;
-        });   
     } else if (cmd == 'serve') {
         var port = undashed[1];
-        var result = cordova.raw.serve(port);
-        return result.finally(function() {
-            if(shouldCollectTelemetry) {
-                telemetry.track(cmd, result.isFulfilled() ? 'successful' : 'unsuccessful');
-            }
-        });
+        return cordova.raw.serve(port);
     } else if (cmd == 'create') {
-        var result = create();
-        return result.finally(function() {
-            if (shouldCollectTelemetry) {
-                telemetry.track(cmd, result.isFulfilled() ? 'successful' : 'unsuccessful');
-            }
-            return result;
-        });
+        return create();
     } else {
         // platform/plugins add/rm [target(s)]
         subcommand = undashed[1]; // sub-command like "add", "ls", "rm" etc.
@@ -396,13 +405,7 @@ function cli(inputArgs, shouldCollectTelemetry) {
                             , shrinkwrap: args.shrinkwrap || false
                             , force: args.force || false
                             };
-        var result = cordova.raw[cmd](subcommand, targets, download_opts);
-        return result.finally(function() {
-            if (shouldCollectTelemetry) {
-                telemetry.track(cmd, result.isFulfilled() ? 'successful' : 'unsuccessful');
-            }
-            return result;
-        });
+        return cordova.raw[cmd](subcommand, targets, download_opts);
     }
 
     function create() {

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/39e5f17c/src/telemetry.js
----------------------------------------------------------------------
diff --git a/src/telemetry.js b/src/telemetry.js
index 4505163..f80e2d4 100644
--- a/src/telemetry.js
+++ b/src/telemetry.js
@@ -22,6 +22,11 @@
           laxcomma:true
 */
 
+
+
+// For further details on telemetry, see:
+// https://github.com/cordova/cordova-discuss/pull/43
+
 var Q = require('q');
 
 // Google Analytics tracking code
@@ -41,17 +46,19 @@ function showPrompt() {
 
     var deferred = Q.defer();
     
-    var msg = 'Do you want to prevent cordova from anonymously collecting usage statitics to improve the tool over time ?';
-    insight.askPermission(msg, function (unused, optOut) {
-        if (optOut) {
-            console.log("You have been opted out of telemetry. To change this, run: cordova telemetry on");
-            // Always track telemetry opt-outs! (whether opted-in or opted-out)
-            track('telemetry-opt-out', 'via-cli-prompt-choice');
+    var msg = "May Cordova anonymously report usage statistics to improve the tool over time?";
+    insight.askPermission(msg, function (unused, optIn) {
+        var EOL = require('os').EOL;
+        if (optIn) {
+            console.log(EOL + "Thanks for opting into telemetry to help us improve cordova.");
+            track('telemetry', 'on', 'via-cli-prompt-choice', 'successful');
         } else {
-            console.log("Thanks for opting into telemetry to help us better cordova");
+            console.log(EOL + "You have been opted out of telemetry. To change this, run: cordova telemetry on.");
+            // Always track telemetry opt-outs! (whether opted-in or opted-out)
+            track('telemetry', 'off', 'via-cli-prompt-choice', 'successful');
         }
-
-        deferred.resolve(!optOut); 
+        
+        deferred.resolve(optIn); 
     });
     
     return deferred.promise;
@@ -61,15 +68,6 @@ function track() {
     insight.track.apply(insight, arguments);
 }
 
-function trackEvent(category, action, label, value) {
-    insight.trackEvent({
-        category: category,
-        action: action,
-        label: label,
-        value: value
-    });
-}
-
 function turnOn() {
     insight.optOut = false;
 }
@@ -114,7 +112,6 @@ function isNoTelemetryFlag(args) {
 
 module.exports = {
     track: track,
-    trackEvent: trackEvent,
     turnOn: turnOn,
     turnOff: turnOff,
     clear: clear,


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


[4/6] cordova-cli git commit: Telemetry: Adding Unit Tests

Posted by om...@apache.org.
Telemetry: Adding Unit Tests


Project: http://git-wip-us.apache.org/repos/asf/cordova-cli/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-cli/commit/55df8989
Tree: http://git-wip-us.apache.org/repos/asf/cordova-cli/tree/55df8989
Diff: http://git-wip-us.apache.org/repos/asf/cordova-cli/diff/55df8989

Branch: refs/heads/master
Commit: 55df89894e15cec9393460f0cb0a78dd2f55d818
Parents: 330dea1
Author: Omar Mefire <om...@gmail.com>
Authored: Fri May 6 12:44:43 2016 -0700
Committer: Omar Mefire <om...@gmail.com>
Committed: Thu May 12 11:14:55 2016 -0700

----------------------------------------------------------------------
 spec/cli.spec.js | 422 ++++++++++++++++++++++++++++++++++++--------------
 src/cli.js       |  88 ++++++-----
 src/telemetry.js |  97 ++++++------
 3 files changed, 406 insertions(+), 201 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/55df8989/spec/cli.spec.js
----------------------------------------------------------------------
diff --git a/spec/cli.spec.js b/spec/cli.spec.js
index b6064e9..c8b1e9a 100644
--- a/spec/cli.spec.js
+++ b/spec/cli.spec.js
@@ -21,8 +21,9 @@ var cli = require("../src/cli"),
     Q = require('q'),
     cordova_lib = require('cordova-lib'),
     events = cordova_lib.events,
-    cordova = cordova_lib.cordova;
-
+    cordova = cordova_lib.cordova,
+    telemetry = require('../src/telemetry');
+    
     //avoid node complaining of too many event listener added
     process.setMaxListeners(0);
 
@@ -41,6 +42,11 @@ describe("cordova cli", function () {
 
         spyOn(events, "on").andReturn(new FakeEvents());
         spyOn(console, 'log');
+        
+        // Prevent accidentally turning telemetry on/off during testing
+        telemetry.turnOn = function() {};
+        telemetry.turnOff = function() {};
+        telemetry.track = function() {};
     });
 
     describe("options", function () {
@@ -49,20 +55,35 @@ describe("cordova cli", function () {
 
             beforeEach(function () {
             });
-
-            it("will spit out the version with -v", function () {
-                cli(["node", "cordova", "-v"]);
-                expect(console.log.mostRecentCall.args[0]).toContain(version);
+            
+            it("will spit out the version with -v", function (done) {
+                cli(["node", "cordova", "-v"]).then(function() {
+                    expect(console.log.mostRecentCall.args[0]).toMatch(version);
+                    done();
+                }).fail(function() {
+                    expect(true).toBe(false);
+                    done();
+                });
             });
 
-            it("will spit out the version with --version", function () {
-                cli(["node", "cordova", "--version"]);
-                expect(console.log.mostRecentCall.args[0]).toContain(version);
+            it("will spit out the version with --version", function (done) {
+                cli(["node", "cordova", "--version"]).then(function() {
+                    expect(console.log.mostRecentCall.args[0]).toMatch(version);
+                    done();
+                }).fail(function() {
+                    assert(true).toBe(false);
+                    done();
+                });
             });
 
-            it("will spit out the version with -v anywhere", function () {
-                cli(["node", "cordova", "one", "-v", "three"]);
-                expect(console.log.mostRecentCall.args[0]).toContain(version);
+            it("will spit out the version with -v anywhere", function (done) {
+                cli(["node", "cordova", "one", "-v", "three"]).then(function() {
+                    expect(console.log.mostRecentCall.args[0]).toMatch(version);
+                    done();
+                }).fail(function() {
+                    expect(true).toBe(false);
+                    done();
+                });
             });
         });
     });
@@ -72,88 +93,64 @@ describe("cordova cli", function () {
             spyOn(cordova.raw, "build").andReturn(Q());
         });
 
-        it("will call command with all arguments passed through", function () {
-            cli(["node", "cordova", "build", "blackberry10", "--", "-k", "abcd1234"]);
-            expect(cordova.raw.build).toHaveBeenCalledWith(jasmine.objectContaining({
-                platforms : [ 'blackberry10' ],
-                options : { argv : [ '-k', 'abcd1234' ] },
-                verbose : false,
-                silent : false,
-                fetch: false,
-                browserify : false,
-                nohooks:[],
-                searchpath : undefined
-            }));
+        it("will call command with all arguments passed through", function (done) {
+            cli(["node", "cordova", "build", "blackberry10", "--", "-k", "abcd1234"]).then(function () {
+                expect(cordova.raw.build).toHaveBeenCalledWith({ platforms: ['blackberry10'], options: { argv: ['-k', 'abcd1234'] }, verbose: false, silent: false, browserify: false, nohooks: [], searchpath: undefined });
+                done();
+            }).fail(function () {
+                expect(true).toBe(false);
+                done();
+            });
         });
 
-        it("will consume the first instance of -d", function () {
-            cli(["node", "cordova", "-d", "build", "blackberry10", "--", "-k", "abcd1234", "-d"]);
-            expect(cordova.raw.build).toHaveBeenCalledWith(jasmine.objectContaining({
-                platforms : [ 'blackberry10' ],
-                options : { verbose : true, argv : [ '-k', 'abcd1234', '-d' ] },
-                verbose : true,
-                silent : false,
-                fetch: false,
-                browserify : false,
-                nohooks:[],
-                searchpath : undefined
-            }));
+        it("will consume the first instance of -d", function (done) {
+            cli(["node", "cordova", "-d", "build", "blackberry10", "--", "-k", "abcd1234", "-d"]).then(function () {
+                expect(cordova.raw.build).toHaveBeenCalledWith({ platforms: ['blackberry10'], options: { verbose: true, argv: ['-k', 'abcd1234', '-d'] }, verbose: true, silent: false, browserify: false, nohooks: [], searchpath: undefined });
+                done();
+            }).fail(function () {
+                expect(true).toBe(false);
+                done();
+            });
         });
 
-        it("will consume the first instance of --verbose", function () {
-            cli(["node", "cordova", "--verbose", "build", "blackberry10", "--", "-k", "abcd1234", "--verbose"]);
-            expect(cordova.raw.build).toHaveBeenCalledWith(jasmine.objectContaining({
-                platforms : [ 'blackberry10' ],
-                options : { verbose : true, argv : [ '-k', 'abcd1234', '--verbose' ] },
-                verbose : true,
-                silent : false,
-                fetch: false,
-                browserify : false,
-                nohooks:[],
-                searchpath : undefined
-            }));
+        it("will consume the first instance of --verbose", function (done) {
+            cli(["node", "cordova", "--verbose", "build", "blackberry10", "--", "-k", "abcd1234", "--verbose"]).then(function () {
+                expect(cordova.raw.build).toHaveBeenCalledWith({ platforms: ['blackberry10'], options: { verbose: true, argv: ['-k', 'abcd1234', '--verbose'] }, verbose: true, silent: false, browserify: false, nohooks: [], searchpath: undefined });
+                done();
+            }).fail(function () {
+                expect(true).toBe(false);
+                done();
+            });
         });
 
-        it("will consume the first instance of either --verbose of -d", function () {
-            cli(["node", "cordova", "--verbose", "build", "blackberry10", "--", "-k", "abcd1234", "-d"]);
-            expect(cordova.raw.build).toHaveBeenCalledWith(jasmine.objectContaining({
-                platforms : [ 'blackberry10' ],
-                options : { verbose : true, argv : [ '-k', 'abcd1234', '-d' ] },
-                verbose : true,
-                silent : false,
-                fetch: false,
-                browserify : false,
-                nohooks:[],
-                searchpath : undefined
-            }));
+        it("will consume the first instance of either --verbose or -d", function (done) {
+            cli(["node", "cordova", "--verbose", "build", "blackberry10", "--", "-k", "abcd1234", "-d"]).then(function () {
+                expect(cordova.raw.build).toHaveBeenCalledWith({ platforms: ['blackberry10'], options: { verbose: true, argv: ['-k', 'abcd1234', '-d'] }, verbose: true, silent: false, browserify: false, nohooks: [], searchpath: undefined });
+                done();
+            }).fail(function () {
+                expect(true).toBe(false);
+                done();
+            });
         });
 
-        it("will consume the first instance of either --verbose of -d", function () {
-            cli(["node", "cordova", "-d", "build", "blackberry10", "--", "-k", "abcd1234", "--verbose"]);
-            expect(cordova.raw.build).toHaveBeenCalledWith(jasmine.objectContaining({
-                platforms : [ 'blackberry10' ],
-                options : { verbose : true, argv : [ '-k', 'abcd1234', '--verbose' ] },
-                verbose : true,
-                silent : false,
-                fetch: false,
-                browserify : false,
-                nohooks:[],
-                searchpath : undefined
-            }));
+        it("will consume the first instance of either --verbose or -d", function (done) {
+            cli(["node", "cordova", "-d", "build", "blackberry10", "--", "-k", "abcd1234", "--verbose"]).then(function () {
+                expect(cordova.raw.build).toHaveBeenCalledWith({ platforms: ['blackberry10'], options: { verbose: true, argv: ['-k', 'abcd1234', '--verbose'] }, verbose: true, silent: false, browserify: false, nohooks: [], searchpath: undefined });
+                done();
+            }).fail(function () {
+                expect(true).toBe(false);
+                done();
+            });
         });
 
-        it("will consume the first instance of --silent", function () {
-            cli(["node", "cordova", "--silent", "build", "blackberry10", "--",  "-k", "abcd1234", "--silent"]);
-            expect(cordova.raw.build).toHaveBeenCalledWith(jasmine.objectContaining({
-                platforms : [ 'blackberry10' ],
-                options : { silent : true, argv : [ '-k', 'abcd1234', '--silent' ] },
-                verbose : false,
-                silent : true,
-                fetch: false,
-                browserify : false,
-                nohooks:[],
-                searchpath : undefined
-            }));
+        it("will consume the first instance of --silent", function (done) {
+            cli(["node", "cordova", "--silent", "build", "blackberry10", "--", "-k", "abcd1234", "--silent"]).then(function () {
+                expect(cordova.raw.build).toHaveBeenCalledWith({ platforms: ['blackberry10'], options: { silent: true, argv: ['-k', 'abcd1234', '--silent'] }, verbose: false, silent: true, browserify: false, nohooks: [], searchpath: undefined });
+                done();
+            }).fail(function () {
+                expect(true).toBe(false);
+                done();
+            });
         });
     });
 
@@ -163,9 +160,14 @@ describe("cordova cli", function () {
             spyOn(cordova_lib, "CordovaError");
         });
 
-        it("calls cordova raw create", function () {
-            cli(["node", "cordova", "create", "a", "b" , "c", "--link-to", "c:\\personalWWW"]);
-            expect(cordova.raw.create).toHaveBeenCalledWith("a","b","c", jasmine.any(Object));
+        it("calls cordova raw create", function (done) {
+            cli(["node", "cordova", "create", "a", "b", "c", "--link-to", "c:\\personalWWW"]).then(function () {
+                expect(cordova.raw.create).toHaveBeenCalledWith("a", "b", "c", jasmine.any(Object));
+                done();
+            }).fail(function () {
+                expect(true).toBe(false);
+                done();
+            });
         });
     });
 
@@ -174,38 +176,230 @@ describe("cordova cli", function () {
             spyOn(cordova.raw, "plugin").andReturn(Q());
         });
 
-        it("will pass variables", function () {
-            cli(["node", "cordova", "plugin", "add", "facebook", "--variable", "FOO=foo"]);
-            expect(cordova.raw.plugin).toHaveBeenCalledWith(
-                "add",
-                ["facebook"],
-                jasmine.any(Object)
-            );
-            var opts = cordova.raw.plugin.calls[0].args[2];
-            expect(opts.cli_variables.FOO).toBe('foo');
+        it("will pass variables", function (done) {
+            cli(["node", "cordova", "plugin", "add", "facebook", "--variable", "FOO=foo"]).then(function () {
+                expect(cordova.raw.plugin).toHaveBeenCalledWith(
+                    "add",
+                    ["facebook"],
+                    jasmine.any(Object)
+                );
+                var opts = cordova.raw.plugin.calls[0].args[2];
+                expect(opts.cli_variables.FOO).toBe('foo');
+                done();
+            }).fail(function() {
+                expect(true).toBe(false);
+                done();
+            });
+
         });
 
-          it("will  support variables with =", function () {
-            cli(["node", "cordova", "plugin", "add", "facebook", "--variable", "MOTO=DELTA=WAS=HERE"]);
-            expect(cordova.raw.plugin).toHaveBeenCalledWith(
-                "add",
-                ["facebook"],
-                jasmine.any(Object)
-            );
-            var opts = cordova.raw.plugin.calls[0].args[2];
-            expect(opts.cli_variables.MOTO).toBe('DELTA=WAS=HERE');
+        it("will  support variables with =", function (done) {
+            cli(["node", "cordova", "plugin", "add", "facebook", "--variable", "MOTO=DELTA=WAS=HERE"]).then(function () {
+                expect(cordova.raw.plugin).toHaveBeenCalledWith(
+                    "add",
+                    ["facebook"],
+                    jasmine.any(Object)
+                );
+                var opts = cordova.raw.plugin.calls[0].args[2];
+                expect(opts.cli_variables.MOTO).toBe('DELTA=WAS=HERE');
+                done();
+            }).fail(function () {
+                expect(true).toBe(false);
+                done();
+            });
         });
 
-        it("will pass hook patterns to suppress", function () {
-            cli(["node", "cordova", "plugin", "add", "facebook", "--nohooks", "before_plugin_add"]);
-            expect(cordova.raw.plugin).toHaveBeenCalledWith(
-                "add",
-                ["facebook"],
-                jasmine.any(Object)
-            );
-            var opts = cordova.raw.plugin.calls[0].args[2];
-            expect(opts.nohooks[0]).toBe("before_plugin_add");
+        it("will pass hook patterns to suppress", function (done) {
+            cli(["node", "cordova", "plugin", "add", "facebook", "--nohooks", "before_plugin_add"]).then(function () {
+                expect(cordova.raw.plugin).toHaveBeenCalledWith(
+                    "add",
+                    ["facebook"],
+                    jasmine.any(Object)
+                );
+                var opts = cordova.raw.plugin.calls[0].args[2];
+                expect(opts.nohooks[0]).toBe("before_plugin_add");
+                done();
+            }).fail(function () {
+                expect(true).toBe(false);
+                done();
+            });  
         });
 
     });
+    
+    describe("telemetry", function() {
+       it("skips prompt when user runs 'cordova telemetry X'", function(done) {
+           var wasPromptShown = false;
+           spyOn(telemetry, "showPrompt").andCallFake(function () {
+               wasPromptShown = true;
+           });
+
+           cli(["node", "cordova", "telemetry", "on"]).then(function (done) {
+               return cli(["node", "cordova", "telemetry", "off"])
+           }).then(function () {
+               expect(wasPromptShown).toBeFalsy();
+               done();
+           }).fail(function () {
+               expect(true).toBe(false);
+               done();
+           });           
+       });
+       
+       it("is NOT collected when user runs 'cordova telemetry on' while NOT opted-in", function(done) {
+           spyOn(telemetry, "isOptedIn").andReturn(false);
+           spyOn(telemetry, "isCI").andReturn(false);
+           
+           spyOn(telemetry, "track");
+           
+           cli(["node", "cordova", "telemetry", "on"]).then(function () {
+               expect(telemetry.track).not.toHaveBeenCalled();
+               done();
+           }).fail(function () {
+               expect(true).toBe(false);
+               done();
+           });  
+       });
+       
+       it("is collected when user runs 'cordova telemetry off' while opted-in", function(done) {
+           spyOn(telemetry, "isOptedIn").andReturn(true);
+           spyOn(telemetry, "isCI").andReturn(false);
+           
+           spyOn(telemetry, "track");
+           
+           cli(["node", "cordova", "telemetry", "off"]).then(function () {
+               expect(telemetry.track).toHaveBeenCalledWith("telemetry-opt-out", "via-cordova-telemetry-off");
+               done();
+           }).fail(function () {
+               expect(true).toBe(false);
+               done();
+           });  
+       });
+       
+       it("shows prompt if user neither opted in or out yet", function(done) {
+           spyOn(cordova.raw, "prepare").andReturn(Q());
+           spyOn(telemetry, "hasUserOptedInOrOut").andReturn(false);
+           
+           spyOn(telemetry, "isCI").andReturn(false);
+           spyOn(telemetry, "isNoTelemetryFlag").andReturn(false);
+           spyOn(telemetry, "showPrompt").andReturn(Q(false));
+           
+           return cli(["node", "cordova", "prepare"]).then(function() {
+               expect(telemetry.showPrompt).toHaveBeenCalled();
+               done();
+           }).fail(function() {
+               expect(true).toBe(false);
+               done();
+           });
+       });
+
+       // ToDO: Figure out a way to modify default timeout
+       // ... Timeout overriding isn't working anymore due to a bug with jasmine-node
+       xit("opts-out if prompt times out AND it tracks opt-out", function(done) {
+           // Remove any optOut settings that might have been saved
+           // ... and force prompt to be shown
+           telemetry.clear();
+           spyOn(telemetry, "hasUserOptedInOrOut").andReturn(false);
+           spyOn(telemetry, "isCI").andReturn(false);
+           spyOn(telemetry, "track");
+           
+           cli(["node", "cordova", "--version"]).then(function() {
+               expect(telemetry.isOptedIn()).toBeFalsy();
+               expect(telemetry.track).toHaveBeenCalledWith('telemetry-opt-out', 'via-cli-prompt-choice');
+               done();
+           }).fail(function() {
+               expect(true).toBe(false);
+               done();
+           });
+       }/*, 45000*/);
+       
+       it("is NOT collected in CI environments and doesn't prompt", function(done) {
+           spyOn(telemetry, "hasUserOptedInOrOut").andReturn(true);
+           spyOn(telemetry, "isOptedIn").andReturn(true);
+           spyOn(telemetry, "isCI").andReturn(true);
+           
+           spyOn(telemetry, "showPrompt");
+           spyOn(telemetry, "track");
+           
+           cli(["node", "cordova", "--version"]).then(function() {
+               expect(telemetry.showPrompt).not.toHaveBeenCalled();
+               expect(telemetry.track).not.toHaveBeenCalled();
+               done();
+           }).fail(function() {
+               expect(true).toBe(false);
+               done();
+           });
+       });
+       
+       it("is NOT collected when --no-telemetry flag found and doesn't prompt", function(done) {
+           spyOn(telemetry, "hasUserOptedInOrOut").andReturn(false);
+           spyOn(telemetry, "isOptedIn").andReturn(true);
+           spyOn(telemetry, "isCI").andReturn(false);
+           
+           spyOn(telemetry, "showPrompt");
+           spyOn(telemetry, "track");
+           
+           cli(["node", "cordova", "--version", "--no-telemetry"]).then(function() {
+               expect(telemetry.showPrompt).not.toHaveBeenCalled();
+               expect(telemetry.track).not.toHaveBeenCalled();
+               done();
+           }).fail(function() {
+               expect(true).toBe(false);
+               done();
+           });
+       });
+       
+       it("is NOT collected if user opted out", function(done) {
+           spyOn(telemetry, "hasUserOptedInOrOut").andReturn(true);
+           spyOn(telemetry, "isOptedIn").andReturn(false);
+           spyOn(telemetry, "isCI").andReturn(false);
+           
+           spyOn(telemetry, "showPrompt");
+           spyOn(telemetry, "track");
+           
+           cli(["node", "cordova", "--version"]).then(function() {
+               expect(telemetry.showPrompt).not.toHaveBeenCalled();
+               expect(telemetry.track).not.toHaveBeenCalled();
+               done();
+           }).fail(function() {
+               expect(true).toBe(false);
+               done();
+           });
+       });
+       
+       it("is collected if user opted in", function(done) {
+           spyOn(telemetry, "hasUserOptedInOrOut").andReturn(true);
+           spyOn(telemetry, "isOptedIn").andReturn(true);
+           spyOn(telemetry, "isCI").andReturn(false);
+           
+           spyOn(telemetry, "showPrompt");
+           spyOn(telemetry, "track");
+           
+           cli(["node", "cordova", "--version"]).then(function() {
+               expect(telemetry.showPrompt).not.toHaveBeenCalled();
+               expect(telemetry.track).toHaveBeenCalled();
+               done();
+           }).fail(function() {
+               expect(true).toBe(false);
+               done();
+           });
+       });
+       
+       it("track opt-out that happened via 'cordova telemetry off' even if user is NOT opted-in ", function(done) {
+           spyOn(telemetry, "isCI").andReturn(false);
+           spyOn(telemetry, "isOptedIn").andReturn(false); // same as calling `telemetry.turnOff();`
+           spyOn(telemetry, "hasUserOptedInOrOut").andReturn(true);
+           spyOn(telemetry, "track");
+
+           expect(telemetry.isOptedIn()).toBeFalsy();
+           
+           cli(["node", "cordova", "telemetry", "off"]).then(function() {
+               expect(telemetry.isOptedIn()).toBeFalsy();
+               expect(telemetry.track).toHaveBeenCalledWith("telemetry-opt-out", "via-cordova-telemetry-off");
+               done();
+           }).fail(function() {
+               expect(true).toBe(false);
+               done();
+           });;
+       });
+    });
 });

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/55df8989/src/cli.js
----------------------------------------------------------------------
diff --git a/src/cli.js b/src/cli.js
index 890f54a..23d4ecf 100644
--- a/src/cli.js
+++ b/src/cli.js
@@ -89,29 +89,43 @@ module.exports = function(inputArgs) {
     inputArgs = inputArgs || process.argv;
         
     return Q().then(function() {
-        // Skip telemetry prompt when user runs: `cordova telemetry on | off`, `cordova telemetry ...`
-        var isTelemetryCmd = (function() {
-            return inputArgs[2] === 'telemetry';
-        })(inputArgs);
         
-        if (isTelemetryCmd) {
-            return Q(telemetry.isOptedIn);
+        /**
+         * 1- Skip telemetry prompt if:
+         * - CI environment variable is present
+         * - Command is run with `--no-telemetry` flag
+         * - Command ran is: `cordova telemetry on | off | ...`
+         */
+        
+        if(telemetry.isCI(process.env) || telemetry.isNoTelemetryFlag(inputArgs)) {
+            return Q(false);
         }
-
-        // Telemetry Prompt: only shows up on first run
-        // If the user has not made any decision about telemetry yet,
-        // ... a timed prompt is shown(30 seconds), asking him whether or not he wants to opt-in.
-        // ... If the timeout expires without him having made any decisions, he is considered to have opted out.
-
-        // Note: The timed prompt can be prevented from being shown by setting an environment variable: CORDOVA_TELEMETRY_OPT_OUT
-        // ... This is useful in CI environments.
-        return telemetry.setup();
-    }).then(function(isUserOptedIntoTelemetry) {
-        return cli(inputArgs, isUserOptedIntoTelemetry);
+        
+        /**
+         * 2- We shouldn't prompt for telemetry if user issues a command of the form: `cordova telemetry on | off | ...x`
+         */
+        var isTelemetryCmd = inputArgs[2] === 'telemetry';
+        if(isTelemetryCmd) {
+            return Q(telemetry.isOptedIn());
+        }
+        
+        // 3- If user has already been prompted and made a decision, use his saved answer
+        if(telemetry.hasUserOptedInOrOut()) {
+            return Q(telemetry.isOptedIn());
+        }
+        
+        /**
+         * 4- Otherwise, prompt user to opt-in or out
+         * Note: the prompt is shown for 30 seconds. If no choice is made by that time, User is considered to have opted out.
+         */
+        return telemetry.showPrompt();
+        
+    }).then(function(shouldCollectTelemetry) { 
+        cli(inputArgs, shouldCollectTelemetry);
     });
 };
 
-function cli(inputArgs, isUserOptedIntoTelemetry) {
+function cli(inputArgs, shouldCollectTelemetry) {
     // When changing command line arguments, update doc/help.txt accordingly.
     var knownOpts =
         { 'verbose' : Boolean
@@ -164,11 +178,11 @@ function cli(inputArgs, isUserOptedIntoTelemetry) {
             toPrint += ' (cordova-lib@' + libVersion + ')';
         }
         console.log(toPrint);
-        if(isUserOptedIntoTelemetry) {
+        if(shouldCollectTelemetry) {
             var cmd = 'version';
             telemetry.track(cmd, args.version);
         }
-        return;
+        return Q();
     }
 
 
@@ -176,11 +190,13 @@ function cli(inputArgs, isUserOptedIntoTelemetry) {
     // are in a verbose mode.
     process.on('uncaughtException', function(err) {
         logger.error(err);
-        // Test this: err could cause issues
-        telemetry.track('uncaughtException', err);
+        // Don't send exception details, just send that it happened
+        if(shouldCollectTelemetry) {
+            telemetry.track('uncaughtException');
+        }
         process.exit(1);
     });
-
+    
     logger.subscribe(events);
 
     if (args.silent) {
@@ -218,26 +234,22 @@ function cli(inputArgs, isUserOptedIntoTelemetry) {
         if (!args.help && remain[0] == 'help') {
             remain.shift();
         }
-        if(isUserOptedIntoTelemetry) {
+        if(shouldCollectTelemetry) {
             telemetry.track(cmd); 
-            telemetry.trackEvent('category', cmd);
         }
         return help(remain);
     }
     
-    // ToDO: Test this
-    // ToDO: Write console help
-    // ToDO: when running `cordova telemetry on|off`, don't show telemetry prompt
     if (cmd === 'telemetry') {
         if (undashed[1] === 'on') {
             telemetry.turnOn();
-            if (isUserOptedIntoTelemetry) {
+            if (shouldCollectTelemetry) {
                 telemetry.track(cmd, 'on');
             }
         } else if (undashed[1] === 'off') {
             telemetry.turnOff();
-            // Always track telemetry opt-outs whether user opted out or not!
-            telemetry.track('telemetry-opt-out', 'via-telemetry-cmd'); 
+            // Always track telemetry opt-outs (whether user opted out or not!)
+            telemetry.track('telemetry-opt-out', 'via-cordova-telemetry-off'); 
         } else {
             return help('telemetry'); // test this.
         }
@@ -280,9 +292,8 @@ function cli(inputArgs, isUserOptedIntoTelemetry) {
         if (cmd === 'run' && args.list && cordova.raw.targets) {
             var result = cordova.raw.targets.call(null, opts);
             return result.finally(function() {
-                if (isUserOptedIntoTelemetry) {
+                if (shouldCollectTelemetry) {
                     telemetry.track(cmd, result.isFulfilled() ? 'successful' : 'unsuccessful');
-                    telemetry.trackEvent('category', cmd);
                 }
                 return result;
             });
@@ -290,9 +301,8 @@ function cli(inputArgs, isUserOptedIntoTelemetry) {
 
         var result = cordova.raw[cmd].call(null, opts);
         return result.finally(function() {
-            if (isUserOptedIntoTelemetry) {
+            if (shouldCollectTelemetry) {
                 telemetry.track(cmd, result.isFulfilled() ? 'successful' : 'unsuccessful');
-                telemetry.trackEvent('category', cmd);
             }
             return result;
         });
@@ -336,7 +346,7 @@ function cli(inputArgs, isUserOptedIntoTelemetry) {
                 if (someChecksFailed) throw new CordovaError('Some of requirements check failed');
             });
         return result.finally(function() {
-            if (isUserOptedIntoTelemetry) {
+            if (shouldCollectTelemetry) {
                 telemetry.track(cmd, result.isFulfilled() ? 'successful' : 'unsuccessful');
             }
             return result;
@@ -345,14 +355,14 @@ function cli(inputArgs, isUserOptedIntoTelemetry) {
         var port = undashed[1];
         var result = cordova.raw.serve(port);
         return result.finally(function() {
-            if(isUserOptedIntoTelemetry) {
+            if(shouldCollectTelemetry) {
                 telemetry.track(cmd, result.isFulfilled() ? 'successful' : 'unsuccessful');
             }
         });
     } else if (cmd == 'create') {
         var result = create();
         return result.finally(function() {
-            if (isUserOptedIntoTelemetry) {
+            if (shouldCollectTelemetry) {
                 telemetry.track(cmd, result.isFulfilled() ? 'successful' : 'unsuccessful');
             }
             return result;
@@ -386,7 +396,7 @@ function cli(inputArgs, isUserOptedIntoTelemetry) {
                             };
         var result = cordova.raw[cmd](subcommand, targets, download_opts);
         return result.finally(function() {
-            if (isUserOptedIntoTelemetry) {
+            if (shouldCollectTelemetry) {
                 telemetry.track(cmd, result.isFulfilled() ? 'successful' : 'unsuccessful');
             }
             return result;

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/55df8989/src/telemetry.js
----------------------------------------------------------------------
diff --git a/src/telemetry.js b/src/telemetry.js
index 0c40c71..77243c6 100644
--- a/src/telemetry.js
+++ b/src/telemetry.js
@@ -22,64 +22,31 @@
           laxcomma:true
 */
 
-var path = require('path');
 var Q = require('q');
 
-var GOOGLE_ANALYTICS_TRACKING_ID = 'UA-64283057-7'; 
+// Google Analytics tracking code
+var GA_TRACKING_CODE = 'UA-64283057-7';
 
 var pkg = require('../package.json');
 var Insight = require('insight');
 var insight = new Insight({
-    trackingCode: GOOGLE_ANALYTICS_TRACKING_ID,
+    trackingCode: GA_TRACKING_CODE,
     pkg: pkg
 });
 
-/**
- * Telemetry Prompt:
- * If the user has not made any decision about telemetry yet,
- * ... a timed prompt is shown, asking him whether or not he wants to opt-in.
- * ... If the timeout expires without him having made any decisions, he is considered to have opted out.
-
- * Note: The timed prompt can be prevented from being shown by setting an environment variable: CORDOVA_TELEMETRY_OPT_OUT
- * ... This is useful in CI environments.
 
-@returns {Boolean} It returns true if the user has agreed to opt-in to telemetry, false otherwise
-*/
-function setup() {
-    var deferred = Q.defer();
+function showPrompt() {
     
-    // ToDO: should we just rely on 'CI' env variable? (what are others doing?)
-    var isInteractive = !process.env.CORDOVA_TELEMETRY_OPT_OUT && !process.env.CI;
-    if(!isInteractive) {
-        // Update user's config file to make sure telemetry doesn't get collected
-        // This handles the case where user had previously opted-in, then 
-        // ... sets up environment variable to signify they want out
-        insight.optOut = true; 
-    }
+    var deferred = Q.defer();
     
-    if (isInteractive && insight.optOut === undefined) {
-
-        // Note: insight.askPermission() won't display the permissions prompt if one of these is true:
-        //     - the process is not a TTY
-        //     - the process was started with --no-insight flag
-        //     - the CI environment variable is set 
-        // For further infos, see: https://github.com/yeoman/insight/blob/3a6ac613b7312272f9f10e1188310b199afa4e1d/lib/index.js#L133
-        
-        // ToDO: Fix link to privacy-statement
-        var msg = 'Privacy statement: http://docs.cordova.io/privacy-statement.html' + require('os').EOL +
-                    'May cordova anonymously report usage statitics to improve the tool over time ?';
-        insight.askPermission(msg, function(unused, optIn) {
-            if(!optIn) {
-                // Always track telemetry opt-outs!
-                track('telemetry-opt-out', 'via-cli-prompt-choice');
-            }
-            deferred.resolve(optIn /* same as !insight.optOut */);
-        }, {
-            optInByDefault: false // If prompt timeout expires, opt the user out of telemetry
-        });
-    } else {
-        deferred.resolve(!insight.optOut);
-    }
+    var msg = 'Do you want to prevent cordova from anonymously collecting usage statitics to improve the tool over time ?';
+    insight.askPermission(msg, function (unused, optIn) {
+        if (!optIn) {
+            // Always track telemetry opt-outs! (whether opted-in or opted-out)
+            track('telemetry-opt-out', 'via-cli-prompt-choice');
+        }
+        deferred.resolve(optIn /* same as !insight.optOut */);
+    });
     
     return deferred.promise;
 }
@@ -105,15 +72,49 @@ function turnOff() {
     insight.optOut = true;
 }
 
+/**
+ * Clears telemetry setting
+ * Has the same effect as if user never answered the telemetry prompt
+ * Useful for testing purposes
+ */
+function clear() {
+    insight.optOut = undefined;
+}
+
 function isOptedIn() {
     return !insight.optOut;
 }
 
+/**
+ * Has the user already answered the telemetry prompt? (thereby opting in or out?)
+ */
+function hasUserOptedInOrOut() {
+    return !(insight.optOut === undefined);
+}
+
+/**
+ * Is the environment variable 'CI' specified ?
+ */
+function isCI(env) {
+    return !!env.CI;
+}
+
+/**
+ * Has the user ran a command of the form: `cordova run --no-telemetry` ?
+ */
+function isNoTelemetryFlag(args) {
+    return args.indexOf('--no-telemetry') > -1;
+}
+
 module.exports = {
-    setup: setup,
     track: track,
     trackEvent: trackEvent,
     turnOn: turnOn,
     turnOff: turnOff,
-    isOptedIn: isOptedIn
+    clear: clear,
+    isOptedIn: isOptedIn,
+    hasUserOptedInOrOut: hasUserOptedInOrOut,
+    isCI: isCI,
+    showPrompt: showPrompt,
+    isNoTelemetryFlag: isNoTelemetryFlag
 };
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org